Merging with most recent changes on the default branch. Including switch to org.netbeans.html namespace.
1.1 --- a/.hgtags Thu Dec 19 17:11:01 2013 +0100
1.2 +++ b/.hgtags Tue Jan 07 08:21:57 2014 +0100
1.3 @@ -6,3 +6,4 @@
1.4 24612fed24b589c313c416a4e86df9cc4a2ecde5 release-0.4
1.5 6656cca0a73a0f0c3d0a349f471a6c5bab6035a9 release-0.5
1.6 3e5e3c96f9f13bc1487c46e050a6d545c427d945 release-0.6
1.7 +53634fd10e30d0fcfd8d05a2bdf2df36c50ee237 netbeans_base
2.1 --- a/COPYING Thu Dec 19 17:11:01 2013 +0100
2.2 +++ b/COPYING Tue Jan 07 08:21:57 2014 +0100
2.3 @@ -1,18 +1,40 @@
2.4 -HTML via Java(tm) Language Bindings
2.5 -Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
2.6 +DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
2.7
2.8 -This program is free software: you can redistribute it and/or modify
2.9 -it under the terms of the GNU General Public License as published by
2.10 -the Free Software Foundation, version 2 of the License.
2.11 +Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
2.12
2.13 -This program is distributed in the hope that it will be useful,
2.14 -but WITHOUT ANY WARRANTY; without even the implied warranty of
2.15 -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2.16 -GNU General Public License for more details. apidesign.org
2.17 -designates this particular file as subject to the
2.18 -"Classpath" exception as provided by apidesign.org
2.19 -in the License file that accompanied this code.
2.20 +Oracle and Java are registered trademarks of Oracle and/or its affiliates.
2.21 +Other names may be trademarks of their respective owners.
2.22
2.23 -You should have received a copy of the GNU General Public License
2.24 -along with this program. Look for COPYING file in the top folder.
2.25 -If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
2.26 +The contents of this file are subject to the terms of either the GNU
2.27 +General Public License Version 2 only ("GPL") or the Common
2.28 +Development and Distribution License("CDDL") (collectively, the
2.29 +"License"). You may not use this file except in compliance with the
2.30 +License. You can obtain a copy of the License at
2.31 +http://www.netbeans.org/cddl-gplv2.html
2.32 +or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
2.33 +specific language governing permissions and limitations under the
2.34 +License. When distributing the software, include this License Header
2.35 +Notice in each file and include the License file at
2.36 +nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
2.37 +particular file as subject to the "Classpath" exception as provided
2.38 +by Oracle in the GPL Version 2 section of the License file that
2.39 +accompanied this code. If applicable, add the following below the
2.40 +License Header, with the fields enclosed by brackets [] replaced by
2.41 +your own identifying information:
2.42 +"Portions Copyrighted [year] [name of copyright owner]"
2.43 +
2.44 +Contributor(s):
2.45 +
2.46 +The Original Software is NetBeans. The Initial Developer of the Original
2.47 +Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
2.48 +
2.49 +If you wish your version of this file to be governed by only the CDDL
2.50 +or only the GPL Version 2, indicate your decision by adding
2.51 +"[Contributor] elects to include this software in this distribution
2.52 +under the [CDDL or GPL Version 2] license." If you do not indicate a
2.53 +single choice of license, a recipient has the option to distribute
2.54 +your version of this file under either the CDDL, the GPL Version 2 or
2.55 +to extend the choice of license to its licensees as provided above.
2.56 +However, if you add GPL Version 2 code and therefore, elected the GPL
2.57 +Version 2 license, then the option applies only if the new code is
2.58 +made subject to such option by the copyright holder.
3.1 --- a/boot-fx/pom.xml Thu Dec 19 17:11:01 2013 +0100
3.2 +++ b/boot-fx/pom.xml Tue Jan 07 08:21:57 2014 +0100
3.3 @@ -2,12 +2,12 @@
3.4 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
3.5 <modelVersion>4.0.0</modelVersion>
3.6 <parent>
3.7 - <groupId>org.apidesign</groupId>
3.8 - <artifactId>html</artifactId>
3.9 + <groupId>org.netbeans.html</groupId>
3.10 + <artifactId>pom</artifactId>
3.11 <version>0.7-SNAPSHOT</version>
3.12 </parent>
3.13 - <groupId>org.apidesign.html</groupId>
3.14 - <artifactId>boot-fx</artifactId>
3.15 + <groupId>org.netbeans.html</groupId>
3.16 + <artifactId>net.java.html.boot.fx</artifactId>
3.17 <version>0.7-SNAPSHOT</version>
3.18 <name>FX WebView Bootstrap</name>
3.19 <packaging>bundle</packaging>
3.20 @@ -54,7 +54,7 @@
3.21 <scope>provided</scope>
3.22 </dependency>
3.23 <dependency>
3.24 - <groupId>org.apidesign.html</groupId>
3.25 + <groupId>org.netbeans.html</groupId>
3.26 <artifactId>net.java.html.boot</artifactId>
3.27 <version>${project.version}</version>
3.28 <type>jar</type>
4.1 --- a/boot-fx/src/main/java/net/java/html/boot/fx/FXBrowsers.java Thu Dec 19 17:11:01 2013 +0100
4.2 +++ b/boot-fx/src/main/java/net/java/html/boot/fx/FXBrowsers.java Tue Jan 07 08:21:57 2014 +0100
4.3 @@ -1,22 +1,44 @@
4.4 /**
4.5 - * HTML via Java(tm) Language Bindings
4.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
4.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4.8 *
4.9 - * This program is free software: you can redistribute it and/or modify
4.10 - * it under the terms of the GNU General Public License as published by
4.11 - * the Free Software Foundation, version 2 of the License.
4.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
4.13 *
4.14 - * This program is distributed in the hope that it will be useful,
4.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
4.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4.17 - * GNU General Public License for more details. apidesign.org
4.18 - * designates this particular file as subject to the
4.19 - * "Classpath" exception as provided by apidesign.org
4.20 - * in the License file that accompanied this code.
4.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
4.22 + * Other names may be trademarks of their respective owners.
4.23 *
4.24 - * You should have received a copy of the GNU General Public License
4.25 - * along with this program. Look for COPYING file in the top folder.
4.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
4.27 + * The contents of this file are subject to the terms of either the GNU
4.28 + * General Public License Version 2 only ("GPL") or the Common
4.29 + * Development and Distribution License("CDDL") (collectively, the
4.30 + * "License"). You may not use this file except in compliance with the
4.31 + * License. You can obtain a copy of the License at
4.32 + * http://www.netbeans.org/cddl-gplv2.html
4.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
4.34 + * specific language governing permissions and limitations under the
4.35 + * License. When distributing the software, include this License Header
4.36 + * Notice in each file and include the License file at
4.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
4.38 + * particular file as subject to the "Classpath" exception as provided
4.39 + * by Oracle in the GPL Version 2 section of the License file that
4.40 + * accompanied this code. If applicable, add the following below the
4.41 + * License Header, with the fields enclosed by brackets [] replaced by
4.42 + * your own identifying information:
4.43 + * "Portions Copyrighted [year] [name of copyright owner]"
4.44 + *
4.45 + * Contributor(s):
4.46 + *
4.47 + * The Original Software is NetBeans. The Initial Developer of the Original
4.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
4.49 + *
4.50 + * If you wish your version of this file to be governed by only the CDDL
4.51 + * or only the GPL Version 2, indicate your decision by adding
4.52 + * "[Contributor] elects to include this software in this distribution
4.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
4.54 + * single choice of license, a recipient has the option to distribute
4.55 + * your version of this file under either the CDDL, the GPL Version 2 or
4.56 + * to extend the choice of license to its licensees as provided above.
4.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
4.58 + * Version 2 license, then the option applies only if the new code is
4.59 + * made subject to such option by the copyright holder.
4.60 */
4.61 package net.java.html.boot.fx;
4.62
4.63 @@ -27,7 +49,7 @@
4.64 import javafx.scene.web.WebView;
4.65 import net.java.html.boot.BrowserBuilder;
4.66 import net.java.html.js.JavaScriptBody;
4.67 -import org.apidesign.html.boot.fx.AbstractFXPresenter;
4.68 +import org.netbeans.html.boot.fx.AbstractFXPresenter;
4.69
4.70 /** Utility methods for working with <em>JavaFX</em> <code>WebView</code>s.
4.71 *
5.1 --- a/boot-fx/src/main/java/org/apidesign/html/boot/fx/AbstractFXPresenter.java Thu Dec 19 17:11:01 2013 +0100
5.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
5.3 @@ -1,168 +0,0 @@
5.4 -/**
5.5 - * HTML via Java(tm) Language Bindings
5.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
5.7 - *
5.8 - * This program is free software: you can redistribute it and/or modify
5.9 - * it under the terms of the GNU General Public License as published by
5.10 - * the Free Software Foundation, version 2 of the License.
5.11 - *
5.12 - * This program is distributed in the hope that it will be useful,
5.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
5.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5.15 - * GNU General Public License for more details. apidesign.org
5.16 - * designates this particular file as subject to the
5.17 - * "Classpath" exception as provided by apidesign.org
5.18 - * in the License file that accompanied this code.
5.19 - *
5.20 - * You should have received a copy of the GNU General Public License
5.21 - * along with this program. Look for COPYING file in the top folder.
5.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
5.23 - */
5.24 -package org.apidesign.html.boot.fx;
5.25 -
5.26 -import java.io.BufferedReader;
5.27 -import java.io.Reader;
5.28 -import java.net.URL;
5.29 -import java.util.ArrayList;
5.30 -import java.util.Arrays;
5.31 -import java.util.List;
5.32 -import java.util.logging.Level;
5.33 -import java.util.logging.Logger;
5.34 -import javafx.application.Platform;
5.35 -import javafx.scene.web.WebEngine;
5.36 -import javafx.scene.web.WebView;
5.37 -import netscape.javascript.JSObject;
5.38 -import org.apidesign.html.boot.spi.Fn;
5.39 -
5.40 -/**
5.41 - *
5.42 - * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
5.43 - */
5.44 -public abstract class AbstractFXPresenter implements Fn.Presenter {
5.45 - static final Logger LOG = Logger.getLogger(FXPresenter.class.getName());
5.46 - protected static int cnt;
5.47 - protected List<String> scripts;
5.48 - protected Runnable onLoad;
5.49 - protected WebEngine engine;
5.50 -
5.51 - @Override
5.52 - public Fn defineFn(String code, String... names) {
5.53 - StringBuilder sb = new StringBuilder();
5.54 - sb.append("(function() {");
5.55 - sb.append(" return function(");
5.56 - String sep = "";
5.57 - for (String n : names) {
5.58 - sb.append(sep).append(n);
5.59 - sep = ",";
5.60 - }
5.61 - sb.append(") {\n");
5.62 - sb.append(code);
5.63 - sb.append("};");
5.64 - sb.append("})()");
5.65 - if (LOG.isLoggable(Level.FINE)) {
5.66 - LOG.log(Level.FINE,
5.67 - "defining function #{0}:\n{1}\n",
5.68 - new Object[] { ++cnt, code }
5.69 - );
5.70 - }
5.71 - JSObject x = (JSObject) engine.executeScript(sb.toString());
5.72 - return new JSFn(this, x, cnt);
5.73 - }
5.74 -
5.75 - @Override
5.76 - public void loadScript(Reader code) throws Exception {
5.77 - BufferedReader r = new BufferedReader(code);
5.78 - StringBuilder sb = new StringBuilder();
5.79 - for (;;) {
5.80 - String l = r.readLine();
5.81 - if (l == null) {
5.82 - break;
5.83 - }
5.84 - sb.append(l).append('\n');
5.85 - }
5.86 - final String script = sb.toString();
5.87 - if (scripts != null) {
5.88 - scripts.add(script);
5.89 - }
5.90 - engine.executeScript(script);
5.91 - }
5.92 -
5.93 - protected final void onPageLoad() {
5.94 - if (scripts != null) {
5.95 - for (String s : scripts) {
5.96 - engine.executeScript(s);
5.97 - }
5.98 - }
5.99 - onLoad.run();
5.100 - }
5.101 -
5.102 - @Override
5.103 - public void displayPage(final URL resource, final Runnable onLoad) {
5.104 - this.onLoad = onLoad;
5.105 - final WebView view = findView(resource);
5.106 - this.engine = view.getEngine();
5.107 - try {
5.108 - if (FXInspect.initialize(engine)) {
5.109 - scripts = new ArrayList<String>();
5.110 - }
5.111 - } catch (Throwable ex) {
5.112 - ex.printStackTrace();
5.113 - }
5.114 -
5.115 - class Run implements Runnable {
5.116 -
5.117 - @Override
5.118 - public void run() {
5.119 - if (scripts != null) {
5.120 - view.setContextMenuEnabled(true);
5.121 - }
5.122 - engine.load(resource.toExternalForm());
5.123 - }
5.124 - }
5.125 - Run run = new Run();
5.126 - if (Platform.isFxApplicationThread()) {
5.127 - run.run();
5.128 - } else {
5.129 - Platform.runLater(run);
5.130 - }
5.131 - waitFinished();
5.132 - }
5.133 -
5.134 - protected abstract void waitFinished();
5.135 -
5.136 - protected abstract WebView findView(final URL resource);
5.137 -
5.138 - private static final class JSFn extends Fn {
5.139 -
5.140 - private final JSObject fn;
5.141 - private static int call;
5.142 - private final int id;
5.143 -
5.144 - public JSFn(AbstractFXPresenter p, JSObject fn, int id) {
5.145 - super(p);
5.146 - this.fn = fn;
5.147 - this.id = id;
5.148 - }
5.149 -
5.150 - @Override
5.151 - public Object invoke(Object thiz, Object... args) throws Exception {
5.152 - try {
5.153 - if (LOG.isLoggable(Level.FINE)) {
5.154 - LOG.log(Level.FINE, "calling {0} function #{1}", new Object[]{++call, id});
5.155 - }
5.156 - List<Object> all = new ArrayList<Object>(args.length + 1);
5.157 - all.add(thiz == null ? fn : thiz);
5.158 - all.addAll(Arrays.asList(args));
5.159 - Object ret = fn.call("call", all.toArray()); // NOI18N
5.160 - return ret == fn ? null : ret;
5.161 - } catch (Error t) {
5.162 - t.printStackTrace();
5.163 - throw t;
5.164 - } catch (Exception t) {
5.165 - t.printStackTrace();
5.166 - throw t;
5.167 - }
5.168 - }
5.169 - }
5.170 -
5.171 -}
6.1 --- a/boot-fx/src/main/java/org/apidesign/html/boot/fx/Dbgr.java Thu Dec 19 17:11:01 2013 +0100
6.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
6.3 @@ -1,66 +0,0 @@
6.4 -/**
6.5 - * HTML via Java(tm) Language Bindings
6.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
6.7 - *
6.8 - * This program is free software: you can redistribute it and/or modify
6.9 - * it under the terms of the GNU General Public License as published by
6.10 - * the Free Software Foundation, version 2 of the License.
6.11 - *
6.12 - * This program is distributed in the hope that it will be useful,
6.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
6.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6.15 - * GNU General Public License for more details. apidesign.org
6.16 - * designates this particular file as subject to the
6.17 - * "Classpath" exception as provided by apidesign.org
6.18 - * in the License file that accompanied this code.
6.19 - *
6.20 - * You should have received a copy of the GNU General Public License
6.21 - * along with this program. Look for COPYING file in the top folder.
6.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
6.23 - */
6.24 -
6.25 -package org.apidesign.html.boot.fx;
6.26 -
6.27 -import java.lang.reflect.Method;
6.28 -import java.util.logging.Level;
6.29 -import javafx.scene.web.WebEngine;
6.30 -import javafx.util.Callback;
6.31 -import static org.apidesign.html.boot.fx.AbstractFXPresenter.LOG;
6.32 -
6.33 -/** Debugger bridge to shield us from propriatory impl APIs.
6.34 - *
6.35 - * @author Jaroslav Tulach <jtulach@netbeans.org>
6.36 - */
6.37 -final class Dbgr {
6.38 - final Object dbg;
6.39 - final Method sendMsg;
6.40 -
6.41 - Dbgr(WebEngine eng, Callback<String,Void> callback) {
6.42 - Object d;
6.43 - Method m;
6.44 - try {
6.45 - d = eng.getClass().getMethod("impl_getDebugger").invoke(eng); // NOI18N
6.46 - Class<?> debugger = eng.getClass().getClassLoader().loadClass("com.sun.javafx.scene.web.Debugger"); // NOI18N
6.47 - debugger.getMethod("setEnabled", boolean.class).invoke(d, true); // NOI18N
6.48 - debugger.getMethod("setMessageCallback", Callback.class).invoke(d, callback); // NOI18N
6.49 - m = debugger.getMethod("sendMessage", String.class); // NOI18N
6.50 - } catch (Exception ex) {
6.51 - LOG.log(Level.INFO, null, ex);
6.52 - d = null;
6.53 - m = null;
6.54 - }
6.55 - dbg = d;
6.56 - sendMsg = m;
6.57 - }
6.58 -
6.59 - void sendMessage(String msg) {
6.60 - try {
6.61 - if (dbg != null) {
6.62 - sendMsg.invoke(dbg, msg);
6.63 - }
6.64 - } catch (Exception ex) {
6.65 - LOG.log(Level.INFO, null, ex);
6.66 - }
6.67 - }
6.68 -
6.69 -}
7.1 --- a/boot-fx/src/main/java/org/apidesign/html/boot/fx/FXBrwsr.java Thu Dec 19 17:11:01 2013 +0100
7.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
7.3 @@ -1,171 +0,0 @@
7.4 -/**
7.5 - * HTML via Java(tm) Language Bindings
7.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
7.7 - *
7.8 - * This program is free software: you can redistribute it and/or modify
7.9 - * it under the terms of the GNU General Public License as published by
7.10 - * the Free Software Foundation, version 2 of the License.
7.11 - *
7.12 - * This program is distributed in the hope that it will be useful,
7.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
7.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7.15 - * GNU General Public License for more details. apidesign.org
7.16 - * designates this particular file as subject to the
7.17 - * "Classpath" exception as provided by apidesign.org
7.18 - * in the License file that accompanied this code.
7.19 - *
7.20 - * You should have received a copy of the GNU General Public License
7.21 - * along with this program. Look for COPYING file in the top folder.
7.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
7.23 - */
7.24 -package org.apidesign.html.boot.fx;
7.25 -
7.26 -import java.net.URL;
7.27 -import java.util.concurrent.CountDownLatch;
7.28 -import java.util.concurrent.Executors;
7.29 -import java.util.logging.Level;
7.30 -import java.util.logging.Logger;
7.31 -import javafx.application.Application;
7.32 -import javafx.application.Platform;
7.33 -import javafx.beans.value.ChangeListener;
7.34 -import javafx.beans.value.ObservableValue;
7.35 -import javafx.concurrent.Worker;
7.36 -import javafx.event.ActionEvent;
7.37 -import javafx.event.EventHandler;
7.38 -import javafx.geometry.Insets;
7.39 -import javafx.geometry.Pos;
7.40 -import javafx.scene.Scene;
7.41 -import javafx.scene.control.Button;
7.42 -import javafx.scene.layout.BorderPane;
7.43 -import javafx.scene.layout.VBox;
7.44 -import javafx.scene.text.Text;
7.45 -import javafx.scene.web.WebEvent;
7.46 -import javafx.scene.web.WebView;
7.47 -import javafx.stage.Modality;
7.48 -import javafx.stage.Stage;
7.49 -
7.50 -/** This is an implementation class, use {@link BrowserBuilder} API. Just
7.51 - * include this JAR on classpath and the {@link BrowserBuilder} API will find
7.52 - * this implementation automatically.
7.53 - */
7.54 -public class FXBrwsr extends Application {
7.55 - private static final Logger LOG = Logger.getLogger(FXBrwsr.class.getName());
7.56 - private static FXBrwsr INSTANCE;
7.57 - private static final CountDownLatch FINISHED = new CountDownLatch(1);
7.58 - private BorderPane root;
7.59 -
7.60 - public static synchronized WebView findWebView(final URL url, final FXPresenter onLoad) {
7.61 - if (INSTANCE == null) {
7.62 - Executors.newFixedThreadPool(1).submit(new Runnable() {
7.63 - @Override
7.64 - public void run() {
7.65 - try {
7.66 - FXBrwsr.launch(FXBrwsr.class);
7.67 - } catch (Throwable ex) {
7.68 - ex.printStackTrace();
7.69 - } finally {
7.70 - FINISHED.countDown();
7.71 - }
7.72 - }
7.73 - });
7.74 - }
7.75 - while (INSTANCE == null) {
7.76 - try {
7.77 - FXBrwsr.class.wait();
7.78 - } catch (InterruptedException ex) {
7.79 - // wait more
7.80 - }
7.81 - }
7.82 - if (!Platform.isFxApplicationThread()) {
7.83 - final WebView[] arr = {null};
7.84 - final CountDownLatch waitForResult = new CountDownLatch(1);
7.85 - Platform.runLater(new Runnable() {
7.86 - @Override
7.87 - public void run() {
7.88 - arr[0] = INSTANCE.newView(url, onLoad);
7.89 - waitForResult.countDown();
7.90 - }
7.91 - });
7.92 - for (;;) {
7.93 - try {
7.94 - waitForResult.await();
7.95 - break;
7.96 - } catch (InterruptedException ex) {
7.97 - LOG.log(Level.INFO, null, ex);
7.98 - }
7.99 - }
7.100 - return arr[0];
7.101 - } else {
7.102 - return INSTANCE.newView(url, onLoad);
7.103 - }
7.104 - }
7.105 -
7.106 - @Override
7.107 - public void start(Stage primaryStage) throws Exception {
7.108 - synchronized (FXBrwsr.class) {
7.109 - INSTANCE = this;
7.110 - FXBrwsr.class.notifyAll();
7.111 - }
7.112 - BorderPane r = new BorderPane();
7.113 - Scene scene = new Scene(r, 800, 600);
7.114 - primaryStage.setScene(scene);
7.115 - primaryStage.show();
7.116 - this.root = r;
7.117 - }
7.118 -
7.119 - private WebView newView(final URL url, final FXPresenter onLoad) {
7.120 - final WebView view = new WebView();
7.121 - view.setContextMenuEnabled(false);
7.122 - view.getEngine().setOnAlert(new EventHandler<WebEvent<String>>() {
7.123 - @Override
7.124 - public void handle(WebEvent<String> t) {
7.125 - final Stage dialogStage = new Stage();
7.126 - dialogStage.initModality(Modality.WINDOW_MODAL);
7.127 - dialogStage.setTitle("Warning");
7.128 - final Button button = new Button("Close");
7.129 - final Text text = new Text(t.getData());
7.130 - VBox box = new VBox();
7.131 - box.setAlignment(Pos.CENTER);
7.132 - box.setSpacing(10);
7.133 - box.setPadding(new Insets(10));
7.134 - box.getChildren().addAll(text, button);
7.135 - dialogStage.setScene(new Scene(box));
7.136 - button.setCancelButton(true);
7.137 - button.setOnAction(new EventHandler<ActionEvent>() {
7.138 - @Override
7.139 - public void handle(ActionEvent t) {
7.140 - dialogStage.close();
7.141 - }
7.142 - });
7.143 - dialogStage.centerOnScreen();
7.144 - dialogStage.showAndWait();
7.145 - }
7.146 - });
7.147 - root.setCenter(view);
7.148 - final Worker<Void> w = view.getEngine().getLoadWorker();
7.149 - w.stateProperty().addListener(new ChangeListener<Worker.State>() {
7.150 - @Override
7.151 - public void changed(ObservableValue<? extends Worker.State> ov, Worker.State t, Worker.State newState) {
7.152 - if (newState.equals(Worker.State.SUCCEEDED)) {
7.153 - onLoad.onPageLoad();
7.154 - }
7.155 - if (newState.equals(Worker.State.FAILED)) {
7.156 - throw new IllegalStateException("Failed to load " + url);
7.157 - }
7.158 - }
7.159 - });
7.160 - return view;
7.161 - }
7.162 -
7.163 - static void waitFinished() {
7.164 - for (;;) {
7.165 - try {
7.166 - FINISHED.await();
7.167 - break;
7.168 - } catch (InterruptedException ex) {
7.169 - LOG.log(Level.INFO, null, ex);
7.170 - }
7.171 - }
7.172 - }
7.173 -
7.174 -}
8.1 --- a/boot-fx/src/main/java/org/apidesign/html/boot/fx/FXInspect.java Thu Dec 19 17:11:01 2013 +0100
8.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
8.3 @@ -1,112 +0,0 @@
8.4 -/**
8.5 - * HTML via Java(tm) Language Bindings
8.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
8.7 - *
8.8 - * This program is free software: you can redistribute it and/or modify
8.9 - * it under the terms of the GNU General Public License as published by
8.10 - * the Free Software Foundation, version 2 of the License.
8.11 - *
8.12 - * This program is distributed in the hope that it will be useful,
8.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
8.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8.15 - * GNU General Public License for more details. apidesign.org
8.16 - * designates this particular file as subject to the
8.17 - * "Classpath" exception as provided by apidesign.org
8.18 - * in the License file that accompanied this code.
8.19 - *
8.20 - * You should have received a copy of the GNU General Public License
8.21 - * along with this program. Look for COPYING file in the top folder.
8.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
8.23 - */
8.24 -package org.apidesign.html.boot.fx;
8.25 -
8.26 -import java.io.IOException;
8.27 -import java.io.ObjectInputStream;
8.28 -import java.io.ObjectOutputStream;
8.29 -import java.net.InetAddress;
8.30 -import java.net.Socket;
8.31 -import java.nio.charset.StandardCharsets;
8.32 -import java.util.logging.Level;
8.33 -import java.util.logging.Logger;
8.34 -import javafx.application.Platform;
8.35 -import javafx.scene.web.WebEngine;
8.36 -import javafx.util.Callback;
8.37 -
8.38 -/**
8.39 - *
8.40 - * @author Jaroslav Tulach <jtulach@netbeans.org>
8.41 - */
8.42 -final class FXInspect implements Runnable {
8.43 - private static final Logger LOG = Logger.getLogger(FXInspect.class.getName());
8.44 -
8.45 -
8.46 - private final WebEngine engine;
8.47 - private final ObjectInputStream input;
8.48 - private Dbgr dbg;
8.49 -
8.50 - private FXInspect(WebEngine engine, int port) throws IOException {
8.51 - this.engine = engine;
8.52 -
8.53 - Socket socket = new Socket(InetAddress.getByName(null), port);
8.54 - ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
8.55 - this.input = new ObjectInputStream(socket.getInputStream());
8.56 - initializeDebugger(output);
8.57 - }
8.58 -
8.59 - static boolean initialize(WebEngine engine) {
8.60 - final int inspectPort = Integer.getInteger("netbeans.inspect.port", -1); // NOI18N
8.61 - if (inspectPort != -1) {
8.62 - try {
8.63 - FXInspect inspector = new FXInspect(engine, inspectPort);
8.64 - Thread t = new Thread(inspector, "FX<->NetBeans Inspector");
8.65 - t.start();
8.66 - return true;
8.67 - } catch (IOException ex) {
8.68 - LOG.log(Level.INFO, "Cannot connect to NetBeans IDE to port " + inspectPort, ex); // NOI18N
8.69 - }
8.70 - }
8.71 - return false;
8.72 - }
8.73 -
8.74 - private void initializeDebugger(final ObjectOutputStream output) {
8.75 - Platform.runLater(new Runnable() {
8.76 - @Override
8.77 - public void run() {
8.78 - dbg = new Dbgr(engine, new Callback<String,Void>() {
8.79 - @Override
8.80 - public Void call(String message) {
8.81 - try {
8.82 - byte[] bytes = message.getBytes(StandardCharsets.UTF_8);
8.83 - output.writeInt(bytes.length);
8.84 - output.write(bytes);
8.85 - output.flush();
8.86 - } catch (IOException ioex) {
8.87 - ioex.printStackTrace();
8.88 - }
8.89 - return null;
8.90 - }
8.91 - });
8.92 - }
8.93 - });
8.94 - }
8.95 -
8.96 - @Override
8.97 - public void run() {
8.98 - try {
8.99 - while (true) {
8.100 - int length = input.readInt();
8.101 - byte[] bytes = new byte[length];
8.102 - input.readFully(bytes);
8.103 - final String message = new String(bytes, StandardCharsets.UTF_8);
8.104 - Platform.runLater(new Runnable() {
8.105 - @Override
8.106 - public void run() {
8.107 - dbg.sendMessage(message);
8.108 - }
8.109 - });
8.110 - }
8.111 - } catch (IOException ex) {
8.112 - LOG.log(Level.WARNING, null, ex);
8.113 - }
8.114 - }
8.115 -}
9.1 --- a/boot-fx/src/main/java/org/apidesign/html/boot/fx/FXPresenter.java Thu Dec 19 17:11:01 2013 +0100
9.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
9.3 @@ -1,76 +0,0 @@
9.4 -/**
9.5 - * HTML via Java(tm) Language Bindings
9.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
9.7 - *
9.8 - * This program is free software: you can redistribute it and/or modify
9.9 - * it under the terms of the GNU General Public License as published by
9.10 - * the Free Software Foundation, version 2 of the License.
9.11 - *
9.12 - * This program is distributed in the hope that it will be useful,
9.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
9.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9.15 - * GNU General Public License for more details. apidesign.org
9.16 - * designates this particular file as subject to the
9.17 - * "Classpath" exception as provided by apidesign.org
9.18 - * in the License file that accompanied this code.
9.19 - *
9.20 - * You should have received a copy of the GNU General Public License
9.21 - * along with this program. Look for COPYING file in the top folder.
9.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
9.23 - */
9.24 -package org.apidesign.html.boot.fx;
9.25 -
9.26 -import java.io.BufferedReader;
9.27 -import java.io.File;
9.28 -import java.io.Reader;
9.29 -import java.lang.reflect.Method;
9.30 -import java.net.URL;
9.31 -import java.net.URLClassLoader;
9.32 -import java.util.ArrayList;
9.33 -import java.util.Arrays;
9.34 -import java.util.List;
9.35 -import java.util.logging.Level;
9.36 -import java.util.logging.Logger;
9.37 -import javafx.application.Platform;
9.38 -import javafx.scene.web.WebEngine;
9.39 -import javafx.scene.web.WebView;
9.40 -import net.java.html.boot.BrowserBuilder;
9.41 -import netscape.javascript.JSObject;
9.42 -import org.apidesign.html.boot.spi.Fn;
9.43 -import org.openide.util.lookup.ServiceProvider;
9.44 -
9.45 -/** This is an implementation class, use {@link BrowserBuilder} API. Just
9.46 - * include this JAR on classpath and the {@link BrowserBuilder} API will find
9.47 - * this implementation automatically.
9.48 - *
9.49 - * @author Jaroslav Tulach <jtulach@netbeans.org>
9.50 - */
9.51 -@ServiceProvider(service = Fn.Presenter.class)
9.52 -public final class FXPresenter extends AbstractFXPresenter {
9.53 - static {
9.54 - try {
9.55 - try {
9.56 - Class<?> c = Class.forName("javafx.application.Platform");
9.57 - // OK, on classpath
9.58 - } catch (ClassNotFoundException classNotFoundException) {
9.59 - Method m = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
9.60 - m.setAccessible(true);
9.61 - File f = new File(System.getProperty("java.home"), "lib/jfxrt.jar");
9.62 - if (f.exists()) {
9.63 - URL l = f.toURI().toURL();
9.64 - m.invoke(ClassLoader.getSystemClassLoader(), l);
9.65 - }
9.66 - }
9.67 - } catch (Exception ex) {
9.68 - throw new LinkageError("Can't add jfxrt.jar on the classpath", ex);
9.69 - }
9.70 - }
9.71 -
9.72 - protected void waitFinished() {
9.73 - FXBrwsr.waitFinished();
9.74 - }
9.75 -
9.76 - protected WebView findView(final URL resource) {
9.77 - return FXBrwsr.findWebView(resource, this);
9.78 - }
9.79 -}
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
10.2 +++ b/boot-fx/src/main/java/org/netbeans/html/boot/fx/AbstractFXPresenter.java Tue Jan 07 08:21:57 2014 +0100
10.3 @@ -0,0 +1,190 @@
10.4 +/**
10.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
10.6 + *
10.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
10.8 + *
10.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
10.10 + * Other names may be trademarks of their respective owners.
10.11 + *
10.12 + * The contents of this file are subject to the terms of either the GNU
10.13 + * General Public License Version 2 only ("GPL") or the Common
10.14 + * Development and Distribution License("CDDL") (collectively, the
10.15 + * "License"). You may not use this file except in compliance with the
10.16 + * License. You can obtain a copy of the License at
10.17 + * http://www.netbeans.org/cddl-gplv2.html
10.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
10.19 + * specific language governing permissions and limitations under the
10.20 + * License. When distributing the software, include this License Header
10.21 + * Notice in each file and include the License file at
10.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
10.23 + * particular file as subject to the "Classpath" exception as provided
10.24 + * by Oracle in the GPL Version 2 section of the License file that
10.25 + * accompanied this code. If applicable, add the following below the
10.26 + * License Header, with the fields enclosed by brackets [] replaced by
10.27 + * your own identifying information:
10.28 + * "Portions Copyrighted [year] [name of copyright owner]"
10.29 + *
10.30 + * Contributor(s):
10.31 + *
10.32 + * The Original Software is NetBeans. The Initial Developer of the Original
10.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
10.34 + *
10.35 + * If you wish your version of this file to be governed by only the CDDL
10.36 + * or only the GPL Version 2, indicate your decision by adding
10.37 + * "[Contributor] elects to include this software in this distribution
10.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
10.39 + * single choice of license, a recipient has the option to distribute
10.40 + * your version of this file under either the CDDL, the GPL Version 2 or
10.41 + * to extend the choice of license to its licensees as provided above.
10.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
10.43 + * Version 2 license, then the option applies only if the new code is
10.44 + * made subject to such option by the copyright holder.
10.45 + */
10.46 +package org.netbeans.html.boot.fx;
10.47 +
10.48 +import java.io.BufferedReader;
10.49 +import java.io.Reader;
10.50 +import java.net.URL;
10.51 +import java.util.ArrayList;
10.52 +import java.util.Arrays;
10.53 +import java.util.List;
10.54 +import java.util.logging.Level;
10.55 +import java.util.logging.Logger;
10.56 +import javafx.application.Platform;
10.57 +import javafx.scene.web.WebEngine;
10.58 +import javafx.scene.web.WebView;
10.59 +import netscape.javascript.JSObject;
10.60 +import org.apidesign.html.boot.spi.Fn;
10.61 +
10.62 +/**
10.63 + *
10.64 + * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
10.65 + */
10.66 +public abstract class AbstractFXPresenter implements Fn.Presenter {
10.67 + static final Logger LOG = Logger.getLogger(FXPresenter.class.getName());
10.68 + protected static int cnt;
10.69 + protected List<String> scripts;
10.70 + protected Runnable onLoad;
10.71 + protected WebEngine engine;
10.72 +
10.73 + @Override
10.74 + public Fn defineFn(String code, String... names) {
10.75 + StringBuilder sb = new StringBuilder();
10.76 + sb.append("(function() {");
10.77 + sb.append(" return function(");
10.78 + String sep = "";
10.79 + for (String n : names) {
10.80 + sb.append(sep).append(n);
10.81 + sep = ",";
10.82 + }
10.83 + sb.append(") {\n");
10.84 + sb.append(code);
10.85 + sb.append("};");
10.86 + sb.append("})()");
10.87 + if (LOG.isLoggable(Level.FINE)) {
10.88 + LOG.log(Level.FINE,
10.89 + "defining function #{0}:\n{1}\n",
10.90 + new Object[] { ++cnt, code }
10.91 + );
10.92 + }
10.93 + JSObject x = (JSObject) engine.executeScript(sb.toString());
10.94 + return new JSFn(this, x, cnt);
10.95 + }
10.96 +
10.97 + @Override
10.98 + public void loadScript(Reader code) throws Exception {
10.99 + BufferedReader r = new BufferedReader(code);
10.100 + StringBuilder sb = new StringBuilder();
10.101 + for (;;) {
10.102 + String l = r.readLine();
10.103 + if (l == null) {
10.104 + break;
10.105 + }
10.106 + sb.append(l).append('\n');
10.107 + }
10.108 + final String script = sb.toString();
10.109 + if (scripts != null) {
10.110 + scripts.add(script);
10.111 + }
10.112 + engine.executeScript(script);
10.113 + }
10.114 +
10.115 + protected final void onPageLoad() {
10.116 + if (scripts != null) {
10.117 + for (String s : scripts) {
10.118 + engine.executeScript(s);
10.119 + }
10.120 + }
10.121 + onLoad.run();
10.122 + }
10.123 +
10.124 + @Override
10.125 + public void displayPage(final URL resource, final Runnable onLoad) {
10.126 + this.onLoad = onLoad;
10.127 + final WebView view = findView(resource);
10.128 + this.engine = view.getEngine();
10.129 + try {
10.130 + if (FXInspect.initialize(engine)) {
10.131 + scripts = new ArrayList<String>();
10.132 + }
10.133 + } catch (Throwable ex) {
10.134 + ex.printStackTrace();
10.135 + }
10.136 +
10.137 + class Run implements Runnable {
10.138 +
10.139 + @Override
10.140 + public void run() {
10.141 + if (scripts != null) {
10.142 + view.setContextMenuEnabled(true);
10.143 + }
10.144 + engine.load(resource.toExternalForm());
10.145 + }
10.146 + }
10.147 + Run run = new Run();
10.148 + if (Platform.isFxApplicationThread()) {
10.149 + run.run();
10.150 + } else {
10.151 + Platform.runLater(run);
10.152 + }
10.153 + waitFinished();
10.154 + }
10.155 +
10.156 + protected abstract void waitFinished();
10.157 +
10.158 + protected abstract WebView findView(final URL resource);
10.159 +
10.160 + private static final class JSFn extends Fn {
10.161 +
10.162 + private final JSObject fn;
10.163 + private static int call;
10.164 + private final int id;
10.165 +
10.166 + public JSFn(AbstractFXPresenter p, JSObject fn, int id) {
10.167 + super(p);
10.168 + this.fn = fn;
10.169 + this.id = id;
10.170 + }
10.171 +
10.172 + @Override
10.173 + public Object invoke(Object thiz, Object... args) throws Exception {
10.174 + try {
10.175 + if (LOG.isLoggable(Level.FINE)) {
10.176 + LOG.log(Level.FINE, "calling {0} function #{1}", new Object[]{++call, id});
10.177 + }
10.178 + List<Object> all = new ArrayList<Object>(args.length + 1);
10.179 + all.add(thiz == null ? fn : thiz);
10.180 + all.addAll(Arrays.asList(args));
10.181 + Object ret = fn.call("call", all.toArray()); // NOI18N
10.182 + return ret == fn ? null : ret;
10.183 + } catch (Error t) {
10.184 + t.printStackTrace();
10.185 + throw t;
10.186 + } catch (Exception t) {
10.187 + t.printStackTrace();
10.188 + throw t;
10.189 + }
10.190 + }
10.191 + }
10.192 +
10.193 +}
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
11.2 +++ b/boot-fx/src/main/java/org/netbeans/html/boot/fx/Dbgr.java Tue Jan 07 08:21:57 2014 +0100
11.3 @@ -0,0 +1,87 @@
11.4 +/**
11.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
11.6 + *
11.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
11.8 + *
11.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
11.10 + * Other names may be trademarks of their respective owners.
11.11 + *
11.12 + * The contents of this file are subject to the terms of either the GNU
11.13 + * General Public License Version 2 only ("GPL") or the Common
11.14 + * Development and Distribution License("CDDL") (collectively, the
11.15 + * "License"). You may not use this file except in compliance with the
11.16 + * License. You can obtain a copy of the License at
11.17 + * http://www.netbeans.org/cddl-gplv2.html
11.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
11.19 + * specific language governing permissions and limitations under the
11.20 + * License. When distributing the software, include this License Header
11.21 + * Notice in each file and include the License file at
11.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
11.23 + * particular file as subject to the "Classpath" exception as provided
11.24 + * by Oracle in the GPL Version 2 section of the License file that
11.25 + * accompanied this code. If applicable, add the following below the
11.26 + * License Header, with the fields enclosed by brackets [] replaced by
11.27 + * your own identifying information:
11.28 + * "Portions Copyrighted [year] [name of copyright owner]"
11.29 + *
11.30 + * Contributor(s):
11.31 + *
11.32 + * The Original Software is NetBeans. The Initial Developer of the Original
11.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
11.34 + *
11.35 + * If you wish your version of this file to be governed by only the CDDL
11.36 + * or only the GPL Version 2, indicate your decision by adding
11.37 + * "[Contributor] elects to include this software in this distribution
11.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
11.39 + * single choice of license, a recipient has the option to distribute
11.40 + * your version of this file under either the CDDL, the GPL Version 2 or
11.41 + * to extend the choice of license to its licensees as provided above.
11.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
11.43 + * Version 2 license, then the option applies only if the new code is
11.44 + * made subject to such option by the copyright holder.
11.45 + */
11.46 +package org.netbeans.html.boot.fx;
11.47 +
11.48 +import java.lang.reflect.Method;
11.49 +import java.util.logging.Level;
11.50 +import javafx.scene.web.WebEngine;
11.51 +import javafx.util.Callback;
11.52 +import static org.netbeans.html.boot.fx.AbstractFXPresenter.LOG;
11.53 +
11.54 +/** Debugger bridge to shield us from propriatory impl APIs.
11.55 + *
11.56 + * @author Jaroslav Tulach <jtulach@netbeans.org>
11.57 + */
11.58 +final class Dbgr {
11.59 + final Object dbg;
11.60 + final Method sendMsg;
11.61 +
11.62 + Dbgr(WebEngine eng, Callback<String,Void> callback) {
11.63 + Object d;
11.64 + Method m;
11.65 + try {
11.66 + d = eng.getClass().getMethod("impl_getDebugger").invoke(eng); // NOI18N
11.67 + Class<?> debugger = eng.getClass().getClassLoader().loadClass("com.sun.javafx.scene.web.Debugger"); // NOI18N
11.68 + debugger.getMethod("setEnabled", boolean.class).invoke(d, true); // NOI18N
11.69 + debugger.getMethod("setMessageCallback", Callback.class).invoke(d, callback); // NOI18N
11.70 + m = debugger.getMethod("sendMessage", String.class); // NOI18N
11.71 + } catch (Exception ex) {
11.72 + LOG.log(Level.INFO, null, ex);
11.73 + d = null;
11.74 + m = null;
11.75 + }
11.76 + dbg = d;
11.77 + sendMsg = m;
11.78 + }
11.79 +
11.80 + void sendMessage(String msg) {
11.81 + try {
11.82 + if (dbg != null) {
11.83 + sendMsg.invoke(dbg, msg);
11.84 + }
11.85 + } catch (Exception ex) {
11.86 + LOG.log(Level.INFO, null, ex);
11.87 + }
11.88 + }
11.89 +
11.90 +}
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
12.2 +++ b/boot-fx/src/main/java/org/netbeans/html/boot/fx/FXBrwsr.java Tue Jan 07 08:21:57 2014 +0100
12.3 @@ -0,0 +1,193 @@
12.4 +/**
12.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
12.6 + *
12.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
12.8 + *
12.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
12.10 + * Other names may be trademarks of their respective owners.
12.11 + *
12.12 + * The contents of this file are subject to the terms of either the GNU
12.13 + * General Public License Version 2 only ("GPL") or the Common
12.14 + * Development and Distribution License("CDDL") (collectively, the
12.15 + * "License"). You may not use this file except in compliance with the
12.16 + * License. You can obtain a copy of the License at
12.17 + * http://www.netbeans.org/cddl-gplv2.html
12.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
12.19 + * specific language governing permissions and limitations under the
12.20 + * License. When distributing the software, include this License Header
12.21 + * Notice in each file and include the License file at
12.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
12.23 + * particular file as subject to the "Classpath" exception as provided
12.24 + * by Oracle in the GPL Version 2 section of the License file that
12.25 + * accompanied this code. If applicable, add the following below the
12.26 + * License Header, with the fields enclosed by brackets [] replaced by
12.27 + * your own identifying information:
12.28 + * "Portions Copyrighted [year] [name of copyright owner]"
12.29 + *
12.30 + * Contributor(s):
12.31 + *
12.32 + * The Original Software is NetBeans. The Initial Developer of the Original
12.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
12.34 + *
12.35 + * If you wish your version of this file to be governed by only the CDDL
12.36 + * or only the GPL Version 2, indicate your decision by adding
12.37 + * "[Contributor] elects to include this software in this distribution
12.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
12.39 + * single choice of license, a recipient has the option to distribute
12.40 + * your version of this file under either the CDDL, the GPL Version 2 or
12.41 + * to extend the choice of license to its licensees as provided above.
12.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
12.43 + * Version 2 license, then the option applies only if the new code is
12.44 + * made subject to such option by the copyright holder.
12.45 + */
12.46 +package org.netbeans.html.boot.fx;
12.47 +
12.48 +import java.net.URL;
12.49 +import java.util.concurrent.CountDownLatch;
12.50 +import java.util.concurrent.Executors;
12.51 +import java.util.logging.Level;
12.52 +import java.util.logging.Logger;
12.53 +import javafx.application.Application;
12.54 +import javafx.application.Platform;
12.55 +import javafx.beans.value.ChangeListener;
12.56 +import javafx.beans.value.ObservableValue;
12.57 +import javafx.concurrent.Worker;
12.58 +import javafx.event.ActionEvent;
12.59 +import javafx.event.EventHandler;
12.60 +import javafx.geometry.Insets;
12.61 +import javafx.geometry.Pos;
12.62 +import javafx.scene.Scene;
12.63 +import javafx.scene.control.Button;
12.64 +import javafx.scene.layout.BorderPane;
12.65 +import javafx.scene.layout.VBox;
12.66 +import javafx.scene.text.Text;
12.67 +import javafx.scene.web.WebEvent;
12.68 +import javafx.scene.web.WebView;
12.69 +import javafx.stage.Modality;
12.70 +import javafx.stage.Stage;
12.71 +
12.72 +/** This is an implementation class, use {@link BrowserBuilder} API. Just
12.73 + * include this JAR on classpath and the {@link BrowserBuilder} API will find
12.74 + * this implementation automatically.
12.75 + */
12.76 +public class FXBrwsr extends Application {
12.77 + private static final Logger LOG = Logger.getLogger(FXBrwsr.class.getName());
12.78 + private static FXBrwsr INSTANCE;
12.79 + private static final CountDownLatch FINISHED = new CountDownLatch(1);
12.80 + private BorderPane root;
12.81 +
12.82 + public static synchronized WebView findWebView(final URL url, final FXPresenter onLoad) {
12.83 + if (INSTANCE == null) {
12.84 + Executors.newFixedThreadPool(1).submit(new Runnable() {
12.85 + @Override
12.86 + public void run() {
12.87 + try {
12.88 + FXBrwsr.launch(FXBrwsr.class);
12.89 + } catch (Throwable ex) {
12.90 + ex.printStackTrace();
12.91 + } finally {
12.92 + FINISHED.countDown();
12.93 + }
12.94 + }
12.95 + });
12.96 + }
12.97 + while (INSTANCE == null) {
12.98 + try {
12.99 + FXBrwsr.class.wait();
12.100 + } catch (InterruptedException ex) {
12.101 + // wait more
12.102 + }
12.103 + }
12.104 + if (!Platform.isFxApplicationThread()) {
12.105 + final WebView[] arr = {null};
12.106 + final CountDownLatch waitForResult = new CountDownLatch(1);
12.107 + Platform.runLater(new Runnable() {
12.108 + @Override
12.109 + public void run() {
12.110 + arr[0] = INSTANCE.newView(url, onLoad);
12.111 + waitForResult.countDown();
12.112 + }
12.113 + });
12.114 + for (;;) {
12.115 + try {
12.116 + waitForResult.await();
12.117 + break;
12.118 + } catch (InterruptedException ex) {
12.119 + LOG.log(Level.INFO, null, ex);
12.120 + }
12.121 + }
12.122 + return arr[0];
12.123 + } else {
12.124 + return INSTANCE.newView(url, onLoad);
12.125 + }
12.126 + }
12.127 +
12.128 + @Override
12.129 + public void start(Stage primaryStage) throws Exception {
12.130 + synchronized (FXBrwsr.class) {
12.131 + INSTANCE = this;
12.132 + FXBrwsr.class.notifyAll();
12.133 + }
12.134 + BorderPane r = new BorderPane();
12.135 + Scene scene = new Scene(r, 800, 600);
12.136 + primaryStage.setScene(scene);
12.137 + primaryStage.show();
12.138 + this.root = r;
12.139 + }
12.140 +
12.141 + private WebView newView(final URL url, final FXPresenter onLoad) {
12.142 + final WebView view = new WebView();
12.143 + view.setContextMenuEnabled(false);
12.144 + view.getEngine().setOnAlert(new EventHandler<WebEvent<String>>() {
12.145 + @Override
12.146 + public void handle(WebEvent<String> t) {
12.147 + final Stage dialogStage = new Stage();
12.148 + dialogStage.initModality(Modality.WINDOW_MODAL);
12.149 + dialogStage.setTitle("Warning");
12.150 + final Button button = new Button("Close");
12.151 + final Text text = new Text(t.getData());
12.152 + VBox box = new VBox();
12.153 + box.setAlignment(Pos.CENTER);
12.154 + box.setSpacing(10);
12.155 + box.setPadding(new Insets(10));
12.156 + box.getChildren().addAll(text, button);
12.157 + dialogStage.setScene(new Scene(box));
12.158 + button.setCancelButton(true);
12.159 + button.setOnAction(new EventHandler<ActionEvent>() {
12.160 + @Override
12.161 + public void handle(ActionEvent t) {
12.162 + dialogStage.close();
12.163 + }
12.164 + });
12.165 + dialogStage.centerOnScreen();
12.166 + dialogStage.showAndWait();
12.167 + }
12.168 + });
12.169 + root.setCenter(view);
12.170 + final Worker<Void> w = view.getEngine().getLoadWorker();
12.171 + w.stateProperty().addListener(new ChangeListener<Worker.State>() {
12.172 + @Override
12.173 + public void changed(ObservableValue<? extends Worker.State> ov, Worker.State t, Worker.State newState) {
12.174 + if (newState.equals(Worker.State.SUCCEEDED)) {
12.175 + onLoad.onPageLoad();
12.176 + }
12.177 + if (newState.equals(Worker.State.FAILED)) {
12.178 + throw new IllegalStateException("Failed to load " + url);
12.179 + }
12.180 + }
12.181 + });
12.182 + return view;
12.183 + }
12.184 +
12.185 + static void waitFinished() {
12.186 + for (;;) {
12.187 + try {
12.188 + FINISHED.await();
12.189 + break;
12.190 + } catch (InterruptedException ex) {
12.191 + LOG.log(Level.INFO, null, ex);
12.192 + }
12.193 + }
12.194 + }
12.195 +
12.196 +}
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
13.2 +++ b/boot-fx/src/main/java/org/netbeans/html/boot/fx/FXInspect.java Tue Jan 07 08:21:57 2014 +0100
13.3 @@ -0,0 +1,134 @@
13.4 +/**
13.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
13.6 + *
13.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
13.8 + *
13.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
13.10 + * Other names may be trademarks of their respective owners.
13.11 + *
13.12 + * The contents of this file are subject to the terms of either the GNU
13.13 + * General Public License Version 2 only ("GPL") or the Common
13.14 + * Development and Distribution License("CDDL") (collectively, the
13.15 + * "License"). You may not use this file except in compliance with the
13.16 + * License. You can obtain a copy of the License at
13.17 + * http://www.netbeans.org/cddl-gplv2.html
13.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13.19 + * specific language governing permissions and limitations under the
13.20 + * License. When distributing the software, include this License Header
13.21 + * Notice in each file and include the License file at
13.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
13.23 + * particular file as subject to the "Classpath" exception as provided
13.24 + * by Oracle in the GPL Version 2 section of the License file that
13.25 + * accompanied this code. If applicable, add the following below the
13.26 + * License Header, with the fields enclosed by brackets [] replaced by
13.27 + * your own identifying information:
13.28 + * "Portions Copyrighted [year] [name of copyright owner]"
13.29 + *
13.30 + * Contributor(s):
13.31 + *
13.32 + * The Original Software is NetBeans. The Initial Developer of the Original
13.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
13.34 + *
13.35 + * If you wish your version of this file to be governed by only the CDDL
13.36 + * or only the GPL Version 2, indicate your decision by adding
13.37 + * "[Contributor] elects to include this software in this distribution
13.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
13.39 + * single choice of license, a recipient has the option to distribute
13.40 + * your version of this file under either the CDDL, the GPL Version 2 or
13.41 + * to extend the choice of license to its licensees as provided above.
13.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
13.43 + * Version 2 license, then the option applies only if the new code is
13.44 + * made subject to such option by the copyright holder.
13.45 + */
13.46 +package org.netbeans.html.boot.fx;
13.47 +
13.48 +import java.io.IOException;
13.49 +import java.io.ObjectInputStream;
13.50 +import java.io.ObjectOutputStream;
13.51 +import java.net.InetAddress;
13.52 +import java.net.Socket;
13.53 +import java.nio.charset.StandardCharsets;
13.54 +import java.util.logging.Level;
13.55 +import java.util.logging.Logger;
13.56 +import javafx.application.Platform;
13.57 +import javafx.scene.web.WebEngine;
13.58 +import javafx.util.Callback;
13.59 +
13.60 +/**
13.61 + *
13.62 + * @author Jaroslav Tulach <jtulach@netbeans.org>
13.63 + */
13.64 +final class FXInspect implements Runnable {
13.65 + private static final Logger LOG = Logger.getLogger(FXInspect.class.getName());
13.66 +
13.67 +
13.68 + private final WebEngine engine;
13.69 + private final ObjectInputStream input;
13.70 + private Dbgr dbg;
13.71 +
13.72 + private FXInspect(WebEngine engine, int port) throws IOException {
13.73 + this.engine = engine;
13.74 +
13.75 + Socket socket = new Socket(InetAddress.getByName(null), port);
13.76 + ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
13.77 + this.input = new ObjectInputStream(socket.getInputStream());
13.78 + initializeDebugger(output);
13.79 + }
13.80 +
13.81 + static boolean initialize(WebEngine engine) {
13.82 + final int inspectPort = Integer.getInteger("netbeans.inspect.port", -1); // NOI18N
13.83 + if (inspectPort != -1) {
13.84 + try {
13.85 + FXInspect inspector = new FXInspect(engine, inspectPort);
13.86 + Thread t = new Thread(inspector, "FX<->NetBeans Inspector");
13.87 + t.start();
13.88 + return true;
13.89 + } catch (IOException ex) {
13.90 + LOG.log(Level.INFO, "Cannot connect to NetBeans IDE to port " + inspectPort, ex); // NOI18N
13.91 + }
13.92 + }
13.93 + return false;
13.94 + }
13.95 +
13.96 + private void initializeDebugger(final ObjectOutputStream output) {
13.97 + Platform.runLater(new Runnable() {
13.98 + @Override
13.99 + public void run() {
13.100 + dbg = new Dbgr(engine, new Callback<String,Void>() {
13.101 + @Override
13.102 + public Void call(String message) {
13.103 + try {
13.104 + byte[] bytes = message.getBytes(StandardCharsets.UTF_8);
13.105 + output.writeInt(bytes.length);
13.106 + output.write(bytes);
13.107 + output.flush();
13.108 + } catch (IOException ioex) {
13.109 + ioex.printStackTrace();
13.110 + }
13.111 + return null;
13.112 + }
13.113 + });
13.114 + }
13.115 + });
13.116 + }
13.117 +
13.118 + @Override
13.119 + public void run() {
13.120 + try {
13.121 + while (true) {
13.122 + int length = input.readInt();
13.123 + byte[] bytes = new byte[length];
13.124 + input.readFully(bytes);
13.125 + final String message = new String(bytes, StandardCharsets.UTF_8);
13.126 + Platform.runLater(new Runnable() {
13.127 + @Override
13.128 + public void run() {
13.129 + dbg.sendMessage(message);
13.130 + }
13.131 + });
13.132 + }
13.133 + } catch (IOException ex) {
13.134 + LOG.log(Level.WARNING, null, ex);
13.135 + }
13.136 + }
13.137 +}
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
14.2 +++ b/boot-fx/src/main/java/org/netbeans/html/boot/fx/FXPresenter.java Tue Jan 07 08:21:57 2014 +0100
14.3 @@ -0,0 +1,98 @@
14.4 +/**
14.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
14.6 + *
14.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
14.8 + *
14.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
14.10 + * Other names may be trademarks of their respective owners.
14.11 + *
14.12 + * The contents of this file are subject to the terms of either the GNU
14.13 + * General Public License Version 2 only ("GPL") or the Common
14.14 + * Development and Distribution License("CDDL") (collectively, the
14.15 + * "License"). You may not use this file except in compliance with the
14.16 + * License. You can obtain a copy of the License at
14.17 + * http://www.netbeans.org/cddl-gplv2.html
14.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
14.19 + * specific language governing permissions and limitations under the
14.20 + * License. When distributing the software, include this License Header
14.21 + * Notice in each file and include the License file at
14.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
14.23 + * particular file as subject to the "Classpath" exception as provided
14.24 + * by Oracle in the GPL Version 2 section of the License file that
14.25 + * accompanied this code. If applicable, add the following below the
14.26 + * License Header, with the fields enclosed by brackets [] replaced by
14.27 + * your own identifying information:
14.28 + * "Portions Copyrighted [year] [name of copyright owner]"
14.29 + *
14.30 + * Contributor(s):
14.31 + *
14.32 + * The Original Software is NetBeans. The Initial Developer of the Original
14.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
14.34 + *
14.35 + * If you wish your version of this file to be governed by only the CDDL
14.36 + * or only the GPL Version 2, indicate your decision by adding
14.37 + * "[Contributor] elects to include this software in this distribution
14.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
14.39 + * single choice of license, a recipient has the option to distribute
14.40 + * your version of this file under either the CDDL, the GPL Version 2 or
14.41 + * to extend the choice of license to its licensees as provided above.
14.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
14.43 + * Version 2 license, then the option applies only if the new code is
14.44 + * made subject to such option by the copyright holder.
14.45 + */
14.46 +package org.netbeans.html.boot.fx;
14.47 +
14.48 +import java.io.BufferedReader;
14.49 +import java.io.File;
14.50 +import java.io.Reader;
14.51 +import java.lang.reflect.Method;
14.52 +import java.net.URL;
14.53 +import java.net.URLClassLoader;
14.54 +import java.util.ArrayList;
14.55 +import java.util.Arrays;
14.56 +import java.util.List;
14.57 +import java.util.logging.Level;
14.58 +import java.util.logging.Logger;
14.59 +import javafx.application.Platform;
14.60 +import javafx.scene.web.WebEngine;
14.61 +import javafx.scene.web.WebView;
14.62 +import net.java.html.boot.BrowserBuilder;
14.63 +import netscape.javascript.JSObject;
14.64 +import org.apidesign.html.boot.spi.Fn;
14.65 +import org.openide.util.lookup.ServiceProvider;
14.66 +
14.67 +/** This is an implementation class, use {@link BrowserBuilder} API. Just
14.68 + * include this JAR on classpath and the {@link BrowserBuilder} API will find
14.69 + * this implementation automatically.
14.70 + *
14.71 + * @author Jaroslav Tulach <jtulach@netbeans.org>
14.72 + */
14.73 +@ServiceProvider(service = Fn.Presenter.class)
14.74 +public final class FXPresenter extends AbstractFXPresenter {
14.75 + static {
14.76 + try {
14.77 + try {
14.78 + Class<?> c = Class.forName("javafx.application.Platform");
14.79 + // OK, on classpath
14.80 + } catch (ClassNotFoundException classNotFoundException) {
14.81 + Method m = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
14.82 + m.setAccessible(true);
14.83 + File f = new File(System.getProperty("java.home"), "lib/jfxrt.jar");
14.84 + if (f.exists()) {
14.85 + URL l = f.toURI().toURL();
14.86 + m.invoke(ClassLoader.getSystemClassLoader(), l);
14.87 + }
14.88 + }
14.89 + } catch (Exception ex) {
14.90 + throw new LinkageError("Can't add jfxrt.jar on the classpath", ex);
14.91 + }
14.92 + }
14.93 +
14.94 + protected void waitFinished() {
14.95 + FXBrwsr.waitFinished();
14.96 + }
14.97 +
14.98 + protected WebView findView(final URL resource) {
14.99 + return FXBrwsr.findWebView(resource, this);
14.100 + }
14.101 +}
15.1 --- a/boot-fx/src/test/java/net/java/html/boot/fx/FXBrowsersOnResourceTest.java Thu Dec 19 17:11:01 2013 +0100
15.2 +++ b/boot-fx/src/test/java/net/java/html/boot/fx/FXBrowsersOnResourceTest.java Tue Jan 07 08:21:57 2014 +0100
15.3 @@ -1,22 +1,44 @@
15.4 /**
15.5 - * HTML via Java(tm) Language Bindings
15.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
15.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
15.8 *
15.9 - * This program is free software: you can redistribute it and/or modify
15.10 - * it under the terms of the GNU General Public License as published by
15.11 - * the Free Software Foundation, version 2 of the License.
15.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
15.13 *
15.14 - * This program is distributed in the hope that it will be useful,
15.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
15.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15.17 - * GNU General Public License for more details. apidesign.org
15.18 - * designates this particular file as subject to the
15.19 - * "Classpath" exception as provided by apidesign.org
15.20 - * in the License file that accompanied this code.
15.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
15.22 + * Other names may be trademarks of their respective owners.
15.23 *
15.24 - * You should have received a copy of the GNU General Public License
15.25 - * along with this program. Look for COPYING file in the top folder.
15.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
15.27 + * The contents of this file are subject to the terms of either the GNU
15.28 + * General Public License Version 2 only ("GPL") or the Common
15.29 + * Development and Distribution License("CDDL") (collectively, the
15.30 + * "License"). You may not use this file except in compliance with the
15.31 + * License. You can obtain a copy of the License at
15.32 + * http://www.netbeans.org/cddl-gplv2.html
15.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
15.34 + * specific language governing permissions and limitations under the
15.35 + * License. When distributing the software, include this License Header
15.36 + * Notice in each file and include the License file at
15.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
15.38 + * particular file as subject to the "Classpath" exception as provided
15.39 + * by Oracle in the GPL Version 2 section of the License file that
15.40 + * accompanied this code. If applicable, add the following below the
15.41 + * License Header, with the fields enclosed by brackets [] replaced by
15.42 + * your own identifying information:
15.43 + * "Portions Copyrighted [year] [name of copyright owner]"
15.44 + *
15.45 + * Contributor(s):
15.46 + *
15.47 + * The Original Software is NetBeans. The Initial Developer of the Original
15.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
15.49 + *
15.50 + * If you wish your version of this file to be governed by only the CDDL
15.51 + * or only the GPL Version 2, indicate your decision by adding
15.52 + * "[Contributor] elects to include this software in this distribution
15.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
15.54 + * single choice of license, a recipient has the option to distribute
15.55 + * your version of this file under either the CDDL, the GPL Version 2 or
15.56 + * to extend the choice of license to its licensees as provided above.
15.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
15.58 + * Version 2 license, then the option applies only if the new code is
15.59 + * made subject to such option by the copyright holder.
15.60 */
15.61 package net.java.html.boot.fx;
15.62
15.63 @@ -73,7 +95,7 @@
15.64 }
15.65
15.66 private void doTest() throws Throwable {
15.67 - URL u = FXBrowsersOnResourceTest.class.getResource("/org/apidesign/html/boot/fx/empty.html");
15.68 + URL u = FXBrowsersOnResourceTest.class.getResource("/org/netbeans/html/boot/fx/empty.html");
15.69 assertNotNull(u, "URL found");
15.70 FXBrowsers.load(App.getV1(), u, OnPages.class, "first");
15.71
15.72 @@ -109,7 +131,7 @@
15.73
15.74 assertEquals(increment(), 1, "Now it is one");
15.75
15.76 - URL u = FXBrowsersOnResourceTest.class.getResource("/org/apidesign/html/boot/fx/empty.html");
15.77 + URL u = FXBrowsersOnResourceTest.class.getResource("/org/netbeans/html/boot/fx/empty.html");
15.78 assertNotNull(u, "URL found");
15.79 FXBrowsers.load(App.getV2(), u, OnPages.class, "second", "Hello");
15.80
16.1 --- a/boot-fx/src/test/java/net/java/html/boot/fx/FXBrowsersTest.java Thu Dec 19 17:11:01 2013 +0100
16.2 +++ b/boot-fx/src/test/java/net/java/html/boot/fx/FXBrowsersTest.java Tue Jan 07 08:21:57 2014 +0100
16.3 @@ -1,22 +1,44 @@
16.4 /**
16.5 - * HTML via Java(tm) Language Bindings
16.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
16.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
16.8 *
16.9 - * This program is free software: you can redistribute it and/or modify
16.10 - * it under the terms of the GNU General Public License as published by
16.11 - * the Free Software Foundation, version 2 of the License.
16.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
16.13 *
16.14 - * This program is distributed in the hope that it will be useful,
16.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
16.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16.17 - * GNU General Public License for more details. apidesign.org
16.18 - * designates this particular file as subject to the
16.19 - * "Classpath" exception as provided by apidesign.org
16.20 - * in the License file that accompanied this code.
16.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
16.22 + * Other names may be trademarks of their respective owners.
16.23 *
16.24 - * You should have received a copy of the GNU General Public License
16.25 - * along with this program. Look for COPYING file in the top folder.
16.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
16.27 + * The contents of this file are subject to the terms of either the GNU
16.28 + * General Public License Version 2 only ("GPL") or the Common
16.29 + * Development and Distribution License("CDDL") (collectively, the
16.30 + * "License"). You may not use this file except in compliance with the
16.31 + * License. You can obtain a copy of the License at
16.32 + * http://www.netbeans.org/cddl-gplv2.html
16.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16.34 + * specific language governing permissions and limitations under the
16.35 + * License. When distributing the software, include this License Header
16.36 + * Notice in each file and include the License file at
16.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
16.38 + * particular file as subject to the "Classpath" exception as provided
16.39 + * by Oracle in the GPL Version 2 section of the License file that
16.40 + * accompanied this code. If applicable, add the following below the
16.41 + * License Header, with the fields enclosed by brackets [] replaced by
16.42 + * your own identifying information:
16.43 + * "Portions Copyrighted [year] [name of copyright owner]"
16.44 + *
16.45 + * Contributor(s):
16.46 + *
16.47 + * The Original Software is NetBeans. The Initial Developer of the Original
16.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
16.49 + *
16.50 + * If you wish your version of this file to be governed by only the CDDL
16.51 + * or only the GPL Version 2, indicate your decision by adding
16.52 + * "[Contributor] elects to include this software in this distribution
16.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
16.54 + * single choice of license, a recipient has the option to distribute
16.55 + * your version of this file under either the CDDL, the GPL Version 2 or
16.56 + * to extend the choice of license to its licensees as provided above.
16.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
16.58 + * Version 2 license, then the option applies only if the new code is
16.59 + * made subject to such option by the copyright holder.
16.60 */
16.61 package net.java.html.boot.fx;
16.62
16.63 @@ -73,7 +95,7 @@
16.64 }
16.65
16.66 private void doTest() throws Throwable {
16.67 - URL u = FXBrowsersTest.class.getResource("/org/apidesign/html/boot/fx/empty.html");
16.68 + URL u = FXBrowsersTest.class.getResource("/org/netbeans/html/boot/fx/empty.html");
16.69 assertNotNull(u, "URL found");
16.70 FXBrowsers.load(App.getV1(), u, OnPages.class, "first");
16.71
16.72 @@ -108,7 +130,7 @@
16.73
16.74 assertEquals(increment(), 1, "Now it is one");
16.75
16.76 - URL u = FXBrowsersTest.class.getResource("/org/apidesign/html/boot/fx/empty.html");
16.77 + URL u = FXBrowsersTest.class.getResource("/org/netbeans/html/boot/fx/empty.html");
16.78 assertNotNull(u, "URL found");
16.79 FXBrowsers.load(App.getV2(), u, OnPages.class, "second", "Hello");
16.80
17.1 --- a/boot-fx/src/test/java/org/apidesign/html/boot/fx/BootstrapTest.java Thu Dec 19 17:11:01 2013 +0100
17.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
17.3 @@ -1,93 +0,0 @@
17.4 -/**
17.5 - * HTML via Java(tm) Language Bindings
17.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
17.7 - *
17.8 - * This program is free software: you can redistribute it and/or modify
17.9 - * it under the terms of the GNU General Public License as published by
17.10 - * the Free Software Foundation, version 2 of the License.
17.11 - *
17.12 - * This program is distributed in the hope that it will be useful,
17.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
17.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17.15 - * GNU General Public License for more details. apidesign.org
17.16 - * designates this particular file as subject to the
17.17 - * "Classpath" exception as provided by apidesign.org
17.18 - * in the License file that accompanied this code.
17.19 - *
17.20 - * You should have received a copy of the GNU General Public License
17.21 - * along with this program. Look for COPYING file in the top folder.
17.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
17.23 - */
17.24 -package org.apidesign.html.boot.fx;
17.25 -
17.26 -import java.lang.annotation.Annotation;
17.27 -import java.lang.reflect.Method;
17.28 -import java.util.ArrayList;
17.29 -import java.util.List;
17.30 -import java.util.concurrent.Executors;
17.31 -import net.java.html.boot.BrowserBuilder;
17.32 -import org.apidesign.html.boot.impl.FnContext;
17.33 -import org.apidesign.html.boot.spi.Fn;
17.34 -import org.apidesign.html.json.tck.JavaScriptTCK;
17.35 -import org.apidesign.html.json.tck.KOTest;
17.36 -import org.testng.annotations.Factory;
17.37 -import org.testng.annotations.Test;
17.38 -
17.39 -/**
17.40 - *
17.41 - * @author Jaroslav Tulach <jtulach@netbeans.org>
17.42 - */
17.43 -public class BootstrapTest {
17.44 - private static Class<?> browserClass;
17.45 - private static Fn.Presenter browserPresenter;
17.46 -
17.47 - public BootstrapTest() {
17.48 - }
17.49 -
17.50 - @Factory public static Object[] compatibilityTests() throws Exception {
17.51 - final BrowserBuilder bb = BrowserBuilder.newBrowser().loadClass(BootstrapTest.class).
17.52 - loadPage("empty.html").
17.53 - invoke("initialized");
17.54 -
17.55 - Executors.newSingleThreadExecutor().submit(new Runnable() {
17.56 - @Override
17.57 - public void run() {
17.58 - bb.showAndWait();
17.59 - }
17.60 - });
17.61 -
17.62 - List<Object> res = new ArrayList<Object>();
17.63 - Class<? extends Annotation> test =
17.64 - loadClass().getClassLoader().loadClass(KOTest.class.getName()).
17.65 - asSubclass(Annotation.class);
17.66 -
17.67 - Class[] arr = (Class[]) loadClass().getDeclaredMethod("tests").invoke(null);
17.68 - for (Class c : arr) {
17.69 - for (Method m : c.getMethods()) {
17.70 - if (m.getAnnotation(test) != null) {
17.71 - res.add(new KOFx(browserPresenter, m));
17.72 - }
17.73 - }
17.74 - }
17.75 - return res.toArray();
17.76 - }
17.77 -
17.78 - static synchronized Class<?> loadClass() throws InterruptedException {
17.79 - while (browserClass == null) {
17.80 - BootstrapTest.class.wait();
17.81 - }
17.82 - return browserClass;
17.83 - }
17.84 -
17.85 - public static synchronized void ready(Class<?> browserCls) throws Exception {
17.86 - browserClass = browserCls;
17.87 - browserPresenter = Fn.activePresenter();
17.88 - BootstrapTest.class.notifyAll();
17.89 - }
17.90 -
17.91 - public static void initialized() throws Exception {
17.92 - Class<?> classpathClass = ClassLoader.getSystemClassLoader().loadClass(BootstrapTest.class.getName());
17.93 - Method m = classpathClass.getMethod("ready", Class.class);
17.94 - m.invoke(null, FxJavaScriptTst.class);
17.95 - }
17.96 -}
18.1 --- a/boot-fx/src/test/java/org/apidesign/html/boot/fx/FxJavaScriptTst.java Thu Dec 19 17:11:01 2013 +0100
18.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
18.3 @@ -1,33 +0,0 @@
18.4 -/**
18.5 - * HTML via Java(tm) Language Bindings
18.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
18.7 - *
18.8 - * This program is free software: you can redistribute it and/or modify
18.9 - * it under the terms of the GNU General Public License as published by
18.10 - * the Free Software Foundation, version 2 of the License.
18.11 - *
18.12 - * This program is distributed in the hope that it will be useful,
18.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
18.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18.15 - * GNU General Public License for more details. apidesign.org
18.16 - * designates this particular file as subject to the
18.17 - * "Classpath" exception as provided by apidesign.org
18.18 - * in the License file that accompanied this code.
18.19 - *
18.20 - * You should have received a copy of the GNU General Public License
18.21 - * along with this program. Look for COPYING file in the top folder.
18.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
18.23 - */
18.24 -package org.apidesign.html.boot.fx;
18.25 -
18.26 -import org.apidesign.html.json.tck.JavaScriptTCK;
18.27 -
18.28 -/**
18.29 - *
18.30 - * @author Jaroslav Tulach <jtulach@netbeans.org>
18.31 - */
18.32 -public final class FxJavaScriptTst extends JavaScriptTCK {
18.33 - public static Class[] tests() {
18.34 - return testClasses();
18.35 - }
18.36 -}
19.1 --- a/boot-fx/src/test/java/org/apidesign/html/boot/fx/KOFx.java Thu Dec 19 17:11:01 2013 +0100
19.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
19.3 @@ -1,103 +0,0 @@
19.4 -/**
19.5 - * HTML via Java(tm) Language Bindings
19.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
19.7 - *
19.8 - * This program is free software: you can redistribute it and/or modify
19.9 - * it under the terms of the GNU General Public License as published by
19.10 - * the Free Software Foundation, version 2 of the License.
19.11 - *
19.12 - * This program is distributed in the hope that it will be useful,
19.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
19.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19.15 - * GNU General Public License for more details. apidesign.org
19.16 - * designates this particular file as subject to the
19.17 - * "Classpath" exception as provided by apidesign.org
19.18 - * in the License file that accompanied this code.
19.19 - *
19.20 - * You should have received a copy of the GNU General Public License
19.21 - * along with this program. Look for COPYING file in the top folder.
19.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
19.23 - */
19.24 -package org.apidesign.html.boot.fx;
19.25 -
19.26 -import java.lang.reflect.InvocationTargetException;
19.27 -import java.lang.reflect.Method;
19.28 -import javafx.application.Platform;
19.29 -import org.apidesign.html.boot.impl.FnContext;
19.30 -import org.apidesign.html.boot.spi.Fn;
19.31 -import org.testng.IHookCallBack;
19.32 -import org.testng.IHookable;
19.33 -import org.testng.ITest;
19.34 -import org.testng.ITestResult;
19.35 -import org.testng.annotations.Test;
19.36 -
19.37 -/**
19.38 - *
19.39 - * @author Jaroslav Tulach <jtulach@netbeans.org>
19.40 - */
19.41 -public final class KOFx implements ITest, IHookable, Runnable {
19.42 - private final Fn.Presenter p;
19.43 - private final Method m;
19.44 - private Object result;
19.45 - private Object inst;
19.46 -
19.47 - KOFx(Fn.Presenter p, Method m) {
19.48 - this.p = p;
19.49 - this.m = m;
19.50 - }
19.51 -
19.52 - @Override
19.53 - public String getTestName() {
19.54 - return m.getName();
19.55 - }
19.56 -
19.57 - @Test
19.58 - public synchronized void executeTest() throws Exception {
19.59 - if (result == null) {
19.60 - Platform.runLater(this);
19.61 - wait();
19.62 - }
19.63 - if (result instanceof Exception) {
19.64 - throw (Exception)result;
19.65 - }
19.66 - if (result instanceof Error) {
19.67 - throw (Error)result;
19.68 - }
19.69 - }
19.70 -
19.71 - @Override
19.72 - public synchronized void run() {
19.73 - boolean notify = true;
19.74 - try {
19.75 - FnContext.currentPresenter(p);
19.76 - if (inst == null) {
19.77 - inst = m.getDeclaringClass().newInstance();
19.78 - }
19.79 - result = m.invoke(inst);
19.80 - if (result == null) {
19.81 - result = this;
19.82 - }
19.83 - } catch (InvocationTargetException ex) {
19.84 - Throwable r = ex.getTargetException();
19.85 - if (r instanceof InterruptedException) {
19.86 - notify = false;
19.87 - Platform.runLater(this);
19.88 - return;
19.89 - }
19.90 - result = r;
19.91 - } catch (Exception ex) {
19.92 - result = ex;
19.93 - } finally {
19.94 - if (notify) {
19.95 - notifyAll();
19.96 - }
19.97 - FnContext.currentPresenter(null);
19.98 - }
19.99 - }
19.100 -
19.101 - @Override
19.102 - public void run(IHookCallBack ihcb, ITestResult itr) {
19.103 - ihcb.runTestMethod(itr);
19.104 - }
19.105 -
19.106 -}
20.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
20.2 +++ b/boot-fx/src/test/java/org/netbeans/html/boot/fx/BootstrapTest.java Tue Jan 07 08:21:57 2014 +0100
20.3 @@ -0,0 +1,115 @@
20.4 +/**
20.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
20.6 + *
20.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
20.8 + *
20.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
20.10 + * Other names may be trademarks of their respective owners.
20.11 + *
20.12 + * The contents of this file are subject to the terms of either the GNU
20.13 + * General Public License Version 2 only ("GPL") or the Common
20.14 + * Development and Distribution License("CDDL") (collectively, the
20.15 + * "License"). You may not use this file except in compliance with the
20.16 + * License. You can obtain a copy of the License at
20.17 + * http://www.netbeans.org/cddl-gplv2.html
20.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
20.19 + * specific language governing permissions and limitations under the
20.20 + * License. When distributing the software, include this License Header
20.21 + * Notice in each file and include the License file at
20.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
20.23 + * particular file as subject to the "Classpath" exception as provided
20.24 + * by Oracle in the GPL Version 2 section of the License file that
20.25 + * accompanied this code. If applicable, add the following below the
20.26 + * License Header, with the fields enclosed by brackets [] replaced by
20.27 + * your own identifying information:
20.28 + * "Portions Copyrighted [year] [name of copyright owner]"
20.29 + *
20.30 + * Contributor(s):
20.31 + *
20.32 + * The Original Software is NetBeans. The Initial Developer of the Original
20.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
20.34 + *
20.35 + * If you wish your version of this file to be governed by only the CDDL
20.36 + * or only the GPL Version 2, indicate your decision by adding
20.37 + * "[Contributor] elects to include this software in this distribution
20.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
20.39 + * single choice of license, a recipient has the option to distribute
20.40 + * your version of this file under either the CDDL, the GPL Version 2 or
20.41 + * to extend the choice of license to its licensees as provided above.
20.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
20.43 + * Version 2 license, then the option applies only if the new code is
20.44 + * made subject to such option by the copyright holder.
20.45 + */
20.46 +package org.netbeans.html.boot.fx;
20.47 +
20.48 +import java.lang.annotation.Annotation;
20.49 +import java.lang.reflect.Method;
20.50 +import java.util.ArrayList;
20.51 +import java.util.List;
20.52 +import java.util.concurrent.Executors;
20.53 +import net.java.html.boot.BrowserBuilder;
20.54 +import org.netbeans.html.boot.impl.FnContext;
20.55 +import org.apidesign.html.boot.spi.Fn;
20.56 +import org.apidesign.html.json.tck.JavaScriptTCK;
20.57 +import org.apidesign.html.json.tck.KOTest;
20.58 +import org.testng.annotations.Factory;
20.59 +import org.testng.annotations.Test;
20.60 +
20.61 +/**
20.62 + *
20.63 + * @author Jaroslav Tulach <jtulach@netbeans.org>
20.64 + */
20.65 +public class BootstrapTest {
20.66 + private static Class<?> browserClass;
20.67 + private static Fn.Presenter browserPresenter;
20.68 +
20.69 + public BootstrapTest() {
20.70 + }
20.71 +
20.72 + @Factory public static Object[] compatibilityTests() throws Exception {
20.73 + final BrowserBuilder bb = BrowserBuilder.newBrowser().loadClass(BootstrapTest.class).
20.74 + loadPage("empty.html").
20.75 + invoke("initialized");
20.76 +
20.77 + Executors.newSingleThreadExecutor().submit(new Runnable() {
20.78 + @Override
20.79 + public void run() {
20.80 + bb.showAndWait();
20.81 + }
20.82 + });
20.83 +
20.84 + List<Object> res = new ArrayList<Object>();
20.85 + Class<? extends Annotation> test =
20.86 + loadClass().getClassLoader().loadClass(KOTest.class.getName()).
20.87 + asSubclass(Annotation.class);
20.88 +
20.89 + Class[] arr = (Class[]) loadClass().getDeclaredMethod("tests").invoke(null);
20.90 + for (Class c : arr) {
20.91 + for (Method m : c.getMethods()) {
20.92 + if (m.getAnnotation(test) != null) {
20.93 + res.add(new KOFx(browserPresenter, m));
20.94 + }
20.95 + }
20.96 + }
20.97 + return res.toArray();
20.98 + }
20.99 +
20.100 + static synchronized Class<?> loadClass() throws InterruptedException {
20.101 + while (browserClass == null) {
20.102 + BootstrapTest.class.wait();
20.103 + }
20.104 + return browserClass;
20.105 + }
20.106 +
20.107 + public static synchronized void ready(Class<?> browserCls) throws Exception {
20.108 + browserClass = browserCls;
20.109 + browserPresenter = Fn.activePresenter();
20.110 + BootstrapTest.class.notifyAll();
20.111 + }
20.112 +
20.113 + public static void initialized() throws Exception {
20.114 + Class<?> classpathClass = ClassLoader.getSystemClassLoader().loadClass(BootstrapTest.class.getName());
20.115 + Method m = classpathClass.getMethod("ready", Class.class);
20.116 + m.invoke(null, FxJavaScriptTst.class);
20.117 + }
20.118 +}
21.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
21.2 +++ b/boot-fx/src/test/java/org/netbeans/html/boot/fx/FXPresenterTst.java Tue Jan 07 08:21:57 2014 +0100
21.3 @@ -0,0 +1,71 @@
21.4 +/**
21.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
21.6 + *
21.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
21.8 + *
21.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
21.10 + * Other names may be trademarks of their respective owners.
21.11 + *
21.12 + * The contents of this file are subject to the terms of either the GNU
21.13 + * General Public License Version 2 only ("GPL") or the Common
21.14 + * Development and Distribution License("CDDL") (collectively, the
21.15 + * "License"). You may not use this file except in compliance with the
21.16 + * License. You can obtain a copy of the License at
21.17 + * http://www.netbeans.org/cddl-gplv2.html
21.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
21.19 + * specific language governing permissions and limitations under the
21.20 + * License. When distributing the software, include this License Header
21.21 + * Notice in each file and include the License file at
21.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
21.23 + * particular file as subject to the "Classpath" exception as provided
21.24 + * by Oracle in the GPL Version 2 section of the License file that
21.25 + * accompanied this code. If applicable, add the following below the
21.26 + * License Header, with the fields enclosed by brackets [] replaced by
21.27 + * your own identifying information:
21.28 + * "Portions Copyrighted [year] [name of copyright owner]"
21.29 + *
21.30 + * Contributor(s):
21.31 + *
21.32 + * The Original Software is NetBeans. The Initial Developer of the Original
21.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
21.34 + *
21.35 + * If you wish your version of this file to be governed by only the CDDL
21.36 + * or only the GPL Version 2, indicate your decision by adding
21.37 + * "[Contributor] elects to include this software in this distribution
21.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
21.39 + * single choice of license, a recipient has the option to distribute
21.40 + * your version of this file under either the CDDL, the GPL Version 2 or
21.41 + * to extend the choice of license to its licensees as provided above.
21.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
21.43 + * Version 2 license, then the option applies only if the new code is
21.44 + * made subject to such option by the copyright holder.
21.45 + */
21.46 +package org.netbeans.html.boot.fx;
21.47 +
21.48 +import net.java.html.js.JavaScriptBody;
21.49 +import static org.testng.Assert.*;
21.50 +import org.testng.annotations.Test;
21.51 +
21.52 +/**
21.53 + *
21.54 + * @author Jaroslav Tulach <jtulach@netbeans.org>
21.55 + */
21.56 +public class FXPresenterTst {
21.57 + @Test public void showClassLoader() {
21.58 + R run = new R();
21.59 + callback(run);
21.60 + assertEquals(run.cnt, 1, "Can call even private implementation classes");
21.61 + }
21.62 +
21.63 + @JavaScriptBody(args = { "r" }, javacall = true, body = "r.@java.lang.Runnable::run()();")
21.64 + private static native void callback(Runnable r);
21.65 +
21.66 + private static class R implements Runnable {
21.67 + int cnt;
21.68 +
21.69 + @Override
21.70 + public void run() {
21.71 + cnt++;
21.72 + }
21.73 + }
21.74 +}
22.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
22.2 +++ b/boot-fx/src/test/java/org/netbeans/html/boot/fx/FxJavaScriptTst.java Tue Jan 07 08:21:57 2014 +0100
22.3 @@ -0,0 +1,55 @@
22.4 +/**
22.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
22.6 + *
22.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
22.8 + *
22.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
22.10 + * Other names may be trademarks of their respective owners.
22.11 + *
22.12 + * The contents of this file are subject to the terms of either the GNU
22.13 + * General Public License Version 2 only ("GPL") or the Common
22.14 + * Development and Distribution License("CDDL") (collectively, the
22.15 + * "License"). You may not use this file except in compliance with the
22.16 + * License. You can obtain a copy of the License at
22.17 + * http://www.netbeans.org/cddl-gplv2.html
22.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
22.19 + * specific language governing permissions and limitations under the
22.20 + * License. When distributing the software, include this License Header
22.21 + * Notice in each file and include the License file at
22.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
22.23 + * particular file as subject to the "Classpath" exception as provided
22.24 + * by Oracle in the GPL Version 2 section of the License file that
22.25 + * accompanied this code. If applicable, add the following below the
22.26 + * License Header, with the fields enclosed by brackets [] replaced by
22.27 + * your own identifying information:
22.28 + * "Portions Copyrighted [year] [name of copyright owner]"
22.29 + *
22.30 + * Contributor(s):
22.31 + *
22.32 + * The Original Software is NetBeans. The Initial Developer of the Original
22.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
22.34 + *
22.35 + * If you wish your version of this file to be governed by only the CDDL
22.36 + * or only the GPL Version 2, indicate your decision by adding
22.37 + * "[Contributor] elects to include this software in this distribution
22.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
22.39 + * single choice of license, a recipient has the option to distribute
22.40 + * your version of this file under either the CDDL, the GPL Version 2 or
22.41 + * to extend the choice of license to its licensees as provided above.
22.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
22.43 + * Version 2 license, then the option applies only if the new code is
22.44 + * made subject to such option by the copyright holder.
22.45 + */
22.46 +package org.netbeans.html.boot.fx;
22.47 +
22.48 +import org.apidesign.html.json.tck.JavaScriptTCK;
22.49 +
22.50 +/**
22.51 + *
22.52 + * @author Jaroslav Tulach <jtulach@netbeans.org>
22.53 + */
22.54 +public final class FxJavaScriptTst extends JavaScriptTCK {
22.55 + public static Class[] tests() {
22.56 + return testClasses();
22.57 + }
22.58 +}
23.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
23.2 +++ b/boot-fx/src/test/java/org/netbeans/html/boot/fx/KOFx.java Tue Jan 07 08:21:57 2014 +0100
23.3 @@ -0,0 +1,125 @@
23.4 +/**
23.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
23.6 + *
23.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
23.8 + *
23.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
23.10 + * Other names may be trademarks of their respective owners.
23.11 + *
23.12 + * The contents of this file are subject to the terms of either the GNU
23.13 + * General Public License Version 2 only ("GPL") or the Common
23.14 + * Development and Distribution License("CDDL") (collectively, the
23.15 + * "License"). You may not use this file except in compliance with the
23.16 + * License. You can obtain a copy of the License at
23.17 + * http://www.netbeans.org/cddl-gplv2.html
23.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
23.19 + * specific language governing permissions and limitations under the
23.20 + * License. When distributing the software, include this License Header
23.21 + * Notice in each file and include the License file at
23.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
23.23 + * particular file as subject to the "Classpath" exception as provided
23.24 + * by Oracle in the GPL Version 2 section of the License file that
23.25 + * accompanied this code. If applicable, add the following below the
23.26 + * License Header, with the fields enclosed by brackets [] replaced by
23.27 + * your own identifying information:
23.28 + * "Portions Copyrighted [year] [name of copyright owner]"
23.29 + *
23.30 + * Contributor(s):
23.31 + *
23.32 + * The Original Software is NetBeans. The Initial Developer of the Original
23.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
23.34 + *
23.35 + * If you wish your version of this file to be governed by only the CDDL
23.36 + * or only the GPL Version 2, indicate your decision by adding
23.37 + * "[Contributor] elects to include this software in this distribution
23.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
23.39 + * single choice of license, a recipient has the option to distribute
23.40 + * your version of this file under either the CDDL, the GPL Version 2 or
23.41 + * to extend the choice of license to its licensees as provided above.
23.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
23.43 + * Version 2 license, then the option applies only if the new code is
23.44 + * made subject to such option by the copyright holder.
23.45 + */
23.46 +package org.netbeans.html.boot.fx;
23.47 +
23.48 +import java.lang.reflect.InvocationTargetException;
23.49 +import java.lang.reflect.Method;
23.50 +import javafx.application.Platform;
23.51 +import org.netbeans.html.boot.impl.FnContext;
23.52 +import org.apidesign.html.boot.spi.Fn;
23.53 +import org.testng.IHookCallBack;
23.54 +import org.testng.IHookable;
23.55 +import org.testng.ITest;
23.56 +import org.testng.ITestResult;
23.57 +import org.testng.annotations.Test;
23.58 +
23.59 +/**
23.60 + *
23.61 + * @author Jaroslav Tulach <jtulach@netbeans.org>
23.62 + */
23.63 +public final class KOFx implements ITest, IHookable, Runnable {
23.64 + private final Fn.Presenter p;
23.65 + private final Method m;
23.66 + private Object result;
23.67 + private Object inst;
23.68 +
23.69 + KOFx(Fn.Presenter p, Method m) {
23.70 + this.p = p;
23.71 + this.m = m;
23.72 + }
23.73 +
23.74 + @Override
23.75 + public String getTestName() {
23.76 + return m.getName();
23.77 + }
23.78 +
23.79 + @Test
23.80 + public synchronized void executeTest() throws Exception {
23.81 + if (result == null) {
23.82 + Platform.runLater(this);
23.83 + wait();
23.84 + }
23.85 + if (result instanceof Exception) {
23.86 + throw (Exception)result;
23.87 + }
23.88 + if (result instanceof Error) {
23.89 + throw (Error)result;
23.90 + }
23.91 + }
23.92 +
23.93 + @Override
23.94 + public synchronized void run() {
23.95 + boolean notify = true;
23.96 + try {
23.97 + FnContext.currentPresenter(p);
23.98 + if (inst == null) {
23.99 + inst = m.getDeclaringClass().newInstance();
23.100 + }
23.101 + result = m.invoke(inst);
23.102 + if (result == null) {
23.103 + result = this;
23.104 + }
23.105 + } catch (InvocationTargetException ex) {
23.106 + Throwable r = ex.getTargetException();
23.107 + if (r instanceof InterruptedException) {
23.108 + notify = false;
23.109 + Platform.runLater(this);
23.110 + return;
23.111 + }
23.112 + result = r;
23.113 + } catch (Exception ex) {
23.114 + result = ex;
23.115 + } finally {
23.116 + if (notify) {
23.117 + notifyAll();
23.118 + }
23.119 + FnContext.currentPresenter(null);
23.120 + }
23.121 + }
23.122 +
23.123 + @Override
23.124 + public void run(IHookCallBack ihcb, ITestResult itr) {
23.125 + ihcb.runTestMethod(itr);
23.126 + }
23.127 +
23.128 +}
24.1 --- a/boot-fx/src/test/resources/net/java/html/boot/fx/wnd.js Thu Dec 19 17:11:01 2013 +0100
24.2 +++ b/boot-fx/src/test/resources/net/java/html/boot/fx/wnd.js Tue Jan 07 08:21:57 2014 +0100
24.3 @@ -1,22 +1,44 @@
24.4 /*
24.5 - * HTML via Java(tm) Language Bindings
24.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
24.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
24.8 *
24.9 - * This program is free software: you can redistribute it and/or modify
24.10 - * it under the terms of the GNU General Public License as published by
24.11 - * the Free Software Foundation, version 2 of the License.
24.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
24.13 *
24.14 - * This program is distributed in the hope that it will be useful,
24.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
24.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24.17 - * GNU General Public License for more details. apidesign.org
24.18 - * designates this particular file as subject to the
24.19 - * "Classpath" exception as provided by apidesign.org
24.20 - * in the License file that accompanied this code.
24.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
24.22 + * Other names may be trademarks of their respective owners.
24.23 *
24.24 - * You should have received a copy of the GNU General Public License
24.25 - * along with this program. Look for COPYING file in the top folder.
24.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
24.27 + * The contents of this file are subject to the terms of either the GNU
24.28 + * General Public License Version 2 only ("GPL") or the Common
24.29 + * Development and Distribution License("CDDL") (collectively, the
24.30 + * "License"). You may not use this file except in compliance with the
24.31 + * License. You can obtain a copy of the License at
24.32 + * http://www.netbeans.org/cddl-gplv2.html
24.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
24.34 + * specific language governing permissions and limitations under the
24.35 + * License. When distributing the software, include this License Header
24.36 + * Notice in each file and include the License file at
24.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
24.38 + * particular file as subject to the "Classpath" exception as provided
24.39 + * by Oracle in the GPL Version 2 section of the License file that
24.40 + * accompanied this code. If applicable, add the following below the
24.41 + * License Header, with the fields enclosed by brackets [] replaced by
24.42 + * your own identifying information:
24.43 + * "Portions Copyrighted [year] [name of copyright owner]"
24.44 + *
24.45 + * Contributor(s):
24.46 + *
24.47 + * The Original Software is NetBeans. The Initial Developer of the Original
24.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
24.49 + *
24.50 + * If you wish your version of this file to be governed by only the CDDL
24.51 + * or only the GPL Version 2, indicate your decision by adding
24.52 + * "[Contributor] elects to include this software in this distribution
24.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
24.54 + * single choice of license, a recipient has the option to distribute
24.55 + * your version of this file under either the CDDL, the GPL Version 2 or
24.56 + * to extend the choice of license to its licensees as provided above.
24.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
24.58 + * Version 2 license, then the option applies only if the new code is
24.59 + * made subject to such option by the copyright holder.
24.60 */
24.61 if (typeof wnd !== 'undefined') {
24.62 throw 'Window should not be defined yet: ' + wnd;
25.1 --- a/boot-fx/src/test/resources/org/apidesign/html/boot/fx/empty.html Thu Dec 19 17:11:01 2013 +0100
25.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
25.3 @@ -1,33 +0,0 @@
25.4 -<!--
25.5 -
25.6 - HTML via Java(tm) Language Bindings
25.7 - Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
25.8 -
25.9 - This program is free software: you can redistribute it and/or modify
25.10 - it under the terms of the GNU General Public License as published by
25.11 - the Free Software Foundation, version 2 of the License.
25.12 -
25.13 - This program is distributed in the hope that it will be useful,
25.14 - but WITHOUT ANY WARRANTY; without even the implied warranty of
25.15 - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25.16 - GNU General Public License for more details. apidesign.org
25.17 - designates this particular file as subject to the
25.18 - "Classpath" exception as provided by apidesign.org
25.19 - in the License file that accompanied this code.
25.20 -
25.21 - You should have received a copy of the GNU General Public License
25.22 - along with this program. Look for COPYING file in the top folder.
25.23 - If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
25.24 -
25.25 --->
25.26 -<!DOCTYPE html>
25.27 -<html>
25.28 - <head>
25.29 - <title>FX Presenter Harness</title>
25.30 - <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
25.31 - <meta name="viewport" content="width=device-width">
25.32 - </head>
25.33 - <body>
25.34 - <div>FX Presenter Harness</div>
25.35 - </body>
25.36 -</html>
26.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
26.2 +++ b/boot-fx/src/test/resources/org/netbeans/html/boot/fx/empty.html Tue Jan 07 08:21:57 2014 +0100
26.3 @@ -0,0 +1,55 @@
26.4 +<!--
26.5 +
26.6 + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
26.7 +
26.8 + Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
26.9 +
26.10 + Oracle and Java are registered trademarks of Oracle and/or its affiliates.
26.11 + Other names may be trademarks of their respective owners.
26.12 +
26.13 + The contents of this file are subject to the terms of either the GNU
26.14 + General Public License Version 2 only ("GPL") or the Common
26.15 + Development and Distribution License("CDDL") (collectively, the
26.16 + "License"). You may not use this file except in compliance with the
26.17 + License. You can obtain a copy of the License at
26.18 + http://www.netbeans.org/cddl-gplv2.html
26.19 + or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
26.20 + specific language governing permissions and limitations under the
26.21 + License. When distributing the software, include this License Header
26.22 + Notice in each file and include the License file at
26.23 + nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
26.24 + particular file as subject to the "Classpath" exception as provided
26.25 + by Oracle in the GPL Version 2 section of the License file that
26.26 + accompanied this code. If applicable, add the following below the
26.27 + License Header, with the fields enclosed by brackets [] replaced by
26.28 + your own identifying information:
26.29 + "Portions Copyrighted [year] [name of copyright owner]"
26.30 +
26.31 + Contributor(s):
26.32 +
26.33 + The Original Software is NetBeans. The Initial Developer of the Original
26.34 + Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
26.35 +
26.36 + If you wish your version of this file to be governed by only the CDDL
26.37 + or only the GPL Version 2, indicate your decision by adding
26.38 + "[Contributor] elects to include this software in this distribution
26.39 + under the [CDDL or GPL Version 2] license." If you do not indicate a
26.40 + single choice of license, a recipient has the option to distribute
26.41 + your version of this file under either the CDDL, the GPL Version 2 or
26.42 + to extend the choice of license to its licensees as provided above.
26.43 + However, if you add GPL Version 2 code and therefore, elected the GPL
26.44 + Version 2 license, then the option applies only if the new code is
26.45 + made subject to such option by the copyright holder.
26.46 +
26.47 +-->
26.48 +<!DOCTYPE html>
26.49 +<html>
26.50 + <head>
26.51 + <title>FX Presenter Harness</title>
26.52 + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
26.53 + <meta name="viewport" content="width=device-width">
26.54 + </head>
26.55 + <body>
26.56 + <div>FX Presenter Harness</div>
26.57 + </body>
26.58 +</html>
27.1 --- a/boot/pom.xml Thu Dec 19 17:11:01 2013 +0100
27.2 +++ b/boot/pom.xml Tue Jan 07 08:21:57 2014 +0100
27.3 @@ -2,11 +2,11 @@
27.4 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
27.5 <modelVersion>4.0.0</modelVersion>
27.6 <parent>
27.7 - <groupId>org.apidesign</groupId>
27.8 - <artifactId>html</artifactId>
27.9 + <groupId>org.netbeans.html</groupId>
27.10 + <artifactId>pom</artifactId>
27.11 <version>0.7-SNAPSHOT</version>
27.12 </parent>
27.13 - <groupId>org.apidesign.html</groupId>
27.14 + <groupId>org.netbeans.html</groupId>
27.15 <artifactId>net.java.html.boot</artifactId>
27.16 <version>0.7-SNAPSHOT</version>
27.17 <packaging>bundle</packaging>
27.18 @@ -23,7 +23,8 @@
27.19 <artifactId>maven-bundle-plugin</artifactId>
27.20 <configuration>
27.21 <instructions>
27.22 - <Agent-Class>org.apidesign.html.boot.impl.JsAgent</Agent-Class>
27.23 + <Agent-Class>org.netbeans.html.boot.impl.JsAgent</Agent-Class>
27.24 + <Eclipse-BuddyPolicy>dependent</Eclipse-BuddyPolicy>
27.25 </instructions>
27.26 </configuration>
27.27 </plugin>
28.1 --- a/boot/src/main/java/net/java/html/boot/BrowserBuilder.java Thu Dec 19 17:11:01 2013 +0100
28.2 +++ b/boot/src/main/java/net/java/html/boot/BrowserBuilder.java Tue Jan 07 08:21:57 2014 +0100
28.3 @@ -1,22 +1,44 @@
28.4 /**
28.5 - * HTML via Java(tm) Language Bindings
28.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
28.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
28.8 *
28.9 - * This program is free software: you can redistribute it and/or modify
28.10 - * it under the terms of the GNU General Public License as published by
28.11 - * the Free Software Foundation, version 2 of the License.
28.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
28.13 *
28.14 - * This program is distributed in the hope that it will be useful,
28.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
28.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28.17 - * GNU General Public License for more details. apidesign.org
28.18 - * designates this particular file as subject to the
28.19 - * "Classpath" exception as provided by apidesign.org
28.20 - * in the License file that accompanied this code.
28.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
28.22 + * Other names may be trademarks of their respective owners.
28.23 *
28.24 - * You should have received a copy of the GNU General Public License
28.25 - * along with this program. Look for COPYING file in the top folder.
28.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
28.27 + * The contents of this file are subject to the terms of either the GNU
28.28 + * General Public License Version 2 only ("GPL") or the Common
28.29 + * Development and Distribution License("CDDL") (collectively, the
28.30 + * "License"). You may not use this file except in compliance with the
28.31 + * License. You can obtain a copy of the License at
28.32 + * http://www.netbeans.org/cddl-gplv2.html
28.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
28.34 + * specific language governing permissions and limitations under the
28.35 + * License. When distributing the software, include this License Header
28.36 + * Notice in each file and include the License file at
28.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
28.38 + * particular file as subject to the "Classpath" exception as provided
28.39 + * by Oracle in the GPL Version 2 section of the License file that
28.40 + * accompanied this code. If applicable, add the following below the
28.41 + * License Header, with the fields enclosed by brackets [] replaced by
28.42 + * your own identifying information:
28.43 + * "Portions Copyrighted [year] [name of copyright owner]"
28.44 + *
28.45 + * Contributor(s):
28.46 + *
28.47 + * The Original Software is NetBeans. The Initial Developer of the Original
28.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
28.49 + *
28.50 + * If you wish your version of this file to be governed by only the CDDL
28.51 + * or only the GPL Version 2, indicate your decision by adding
28.52 + * "[Contributor] elects to include this software in this distribution
28.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
28.54 + * single choice of license, a recipient has the option to distribute
28.55 + * your version of this file under either the CDDL, the GPL Version 2 or
28.56 + * to extend the choice of license to its licensees as provided above.
28.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
28.58 + * Version 2 license, then the option applies only if the new code is
28.59 + * made subject to such option by the copyright holder.
28.60 */
28.61 package net.java.html.boot;
28.62
28.63 @@ -32,10 +54,10 @@
28.64 import java.util.logging.Level;
28.65 import java.util.logging.Logger;
28.66 import net.java.html.js.JavaScriptBody;
28.67 -import org.apidesign.html.boot.impl.FnUtils;
28.68 +import org.netbeans.html.boot.impl.FnUtils;
28.69 import org.apidesign.html.boot.spi.Fn;
28.70 -import org.apidesign.html.boot.impl.FindResources;
28.71 -import org.apidesign.html.boot.impl.FnContext;
28.72 +import org.netbeans.html.boot.impl.FindResources;
28.73 +import org.netbeans.html.boot.impl.FnContext;
28.74
28.75 /** Use this builder to launch your Java/HTML based application. Typical
28.76 * usage in a main method of your application looks like this:
28.77 @@ -60,8 +82,8 @@
28.78 * also needs an implementation on the classpath of one's application. For example
28.79 * use: <pre>
28.80 * <dependency>
28.81 - * <groupId>org.apidesign.html</groupId>
28.82 - * <artifactId>boot-fx</artifactId>
28.83 + * <groupId>org.netbeans.html</groupId>
28.84 + * <artifactId>net.java.html.boot.fx</artifactId>
28.85 * <scope>runtime</scope>
28.86 * </dependency>
28.87 * </pre>
29.1 --- a/boot/src/main/java/net/java/html/boot/package.html Thu Dec 19 17:11:01 2013 +0100
29.2 +++ b/boot/src/main/java/net/java/html/boot/package.html Tue Jan 07 08:21:57 2014 +0100
29.3 @@ -1,23 +1,45 @@
29.4 <!--
29.5
29.6 - HTML via Java(tm) Language Bindings
29.7 - Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
29.8 + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
29.9
29.10 - This program is free software: you can redistribute it and/or modify
29.11 - it under the terms of the GNU General Public License as published by
29.12 - the Free Software Foundation, version 2 of the License.
29.13 + Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
29.14
29.15 - This program is distributed in the hope that it will be useful,
29.16 - but WITHOUT ANY WARRANTY; without even the implied warranty of
29.17 - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29.18 - GNU General Public License for more details. apidesign.org
29.19 - designates this particular file as subject to the
29.20 - "Classpath" exception as provided by apidesign.org
29.21 - in the License file that accompanied this code.
29.22 + Oracle and Java are registered trademarks of Oracle and/or its affiliates.
29.23 + Other names may be trademarks of their respective owners.
29.24
29.25 - You should have received a copy of the GNU General Public License
29.26 - along with this program. Look for COPYING file in the top folder.
29.27 - If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
29.28 + The contents of this file are subject to the terms of either the GNU
29.29 + General Public License Version 2 only ("GPL") or the Common
29.30 + Development and Distribution License("CDDL") (collectively, the
29.31 + "License"). You may not use this file except in compliance with the
29.32 + License. You can obtain a copy of the License at
29.33 + http://www.netbeans.org/cddl-gplv2.html
29.34 + or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
29.35 + specific language governing permissions and limitations under the
29.36 + License. When distributing the software, include this License Header
29.37 + Notice in each file and include the License file at
29.38 + nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
29.39 + particular file as subject to the "Classpath" exception as provided
29.40 + by Oracle in the GPL Version 2 section of the License file that
29.41 + accompanied this code. If applicable, add the following below the
29.42 + License Header, with the fields enclosed by brackets [] replaced by
29.43 + your own identifying information:
29.44 + "Portions Copyrighted [year] [name of copyright owner]"
29.45 +
29.46 + Contributor(s):
29.47 +
29.48 + The Original Software is NetBeans. The Initial Developer of the Original
29.49 + Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
29.50 +
29.51 + If you wish your version of this file to be governed by only the CDDL
29.52 + or only the GPL Version 2, indicate your decision by adding
29.53 + "[Contributor] elects to include this software in this distribution
29.54 + under the [CDDL or GPL Version 2] license." If you do not indicate a
29.55 + single choice of license, a recipient has the option to distribute
29.56 + your version of this file under either the CDDL, the GPL Version 2 or
29.57 + to extend the choice of license to its licensees as provided above.
29.58 + However, if you add GPL Version 2 code and therefore, elected the GPL
29.59 + Version 2 license, then the option applies only if the new code is
29.60 + made subject to such option by the copyright holder.
29.61
29.62 -->
29.63 <!DOCTYPE html>
30.1 --- a/boot/src/main/java/net/java/html/js/JavaScriptBody.java Thu Dec 19 17:11:01 2013 +0100
30.2 +++ b/boot/src/main/java/net/java/html/js/JavaScriptBody.java Tue Jan 07 08:21:57 2014 +0100
30.3 @@ -1,22 +1,44 @@
30.4 /**
30.5 - * HTML via Java(tm) Language Bindings
30.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
30.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
30.8 *
30.9 - * This program is free software: you can redistribute it and/or modify
30.10 - * it under the terms of the GNU General Public License as published by
30.11 - * the Free Software Foundation, version 2 of the License.
30.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
30.13 *
30.14 - * This program is distributed in the hope that it will be useful,
30.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
30.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30.17 - * GNU General Public License for more details. apidesign.org
30.18 - * designates this particular file as subject to the
30.19 - * "Classpath" exception as provided by apidesign.org
30.20 - * in the License file that accompanied this code.
30.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
30.22 + * Other names may be trademarks of their respective owners.
30.23 *
30.24 - * You should have received a copy of the GNU General Public License
30.25 - * along with this program. Look for COPYING file in the top folder.
30.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
30.27 + * The contents of this file are subject to the terms of either the GNU
30.28 + * General Public License Version 2 only ("GPL") or the Common
30.29 + * Development and Distribution License("CDDL") (collectively, the
30.30 + * "License"). You may not use this file except in compliance with the
30.31 + * License. You can obtain a copy of the License at
30.32 + * http://www.netbeans.org/cddl-gplv2.html
30.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
30.34 + * specific language governing permissions and limitations under the
30.35 + * License. When distributing the software, include this License Header
30.36 + * Notice in each file and include the License file at
30.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
30.38 + * particular file as subject to the "Classpath" exception as provided
30.39 + * by Oracle in the GPL Version 2 section of the License file that
30.40 + * accompanied this code. If applicable, add the following below the
30.41 + * License Header, with the fields enclosed by brackets [] replaced by
30.42 + * your own identifying information:
30.43 + * "Portions Copyrighted [year] [name of copyright owner]"
30.44 + *
30.45 + * Contributor(s):
30.46 + *
30.47 + * The Original Software is NetBeans. The Initial Developer of the Original
30.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
30.49 + *
30.50 + * If you wish your version of this file to be governed by only the CDDL
30.51 + * or only the GPL Version 2, indicate your decision by adding
30.52 + * "[Contributor] elects to include this software in this distribution
30.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
30.54 + * single choice of license, a recipient has the option to distribute
30.55 + * your version of this file under either the CDDL, the GPL Version 2 or
30.56 + * to extend the choice of license to its licensees as provided above.
30.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
30.58 + * Version 2 license, then the option applies only if the new code is
30.59 + * made subject to such option by the copyright holder.
30.60 */
30.61 package net.java.html.js;
30.62
31.1 --- a/boot/src/main/java/net/java/html/js/JavaScriptResource.java Thu Dec 19 17:11:01 2013 +0100
31.2 +++ b/boot/src/main/java/net/java/html/js/JavaScriptResource.java Tue Jan 07 08:21:57 2014 +0100
31.3 @@ -1,22 +1,44 @@
31.4 /**
31.5 - * HTML via Java(tm) Language Bindings
31.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
31.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
31.8 *
31.9 - * This program is free software: you can redistribute it and/or modify
31.10 - * it under the terms of the GNU General Public License as published by
31.11 - * the Free Software Foundation, version 2 of the License.
31.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
31.13 *
31.14 - * This program is distributed in the hope that it will be useful,
31.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
31.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31.17 - * GNU General Public License for more details. apidesign.org
31.18 - * designates this particular file as subject to the
31.19 - * "Classpath" exception as provided by apidesign.org
31.20 - * in the License file that accompanied this code.
31.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
31.22 + * Other names may be trademarks of their respective owners.
31.23 *
31.24 - * You should have received a copy of the GNU General Public License
31.25 - * along with this program. Look for COPYING file in the top folder.
31.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
31.27 + * The contents of this file are subject to the terms of either the GNU
31.28 + * General Public License Version 2 only ("GPL") or the Common
31.29 + * Development and Distribution License("CDDL") (collectively, the
31.30 + * "License"). You may not use this file except in compliance with the
31.31 + * License. You can obtain a copy of the License at
31.32 + * http://www.netbeans.org/cddl-gplv2.html
31.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
31.34 + * specific language governing permissions and limitations under the
31.35 + * License. When distributing the software, include this License Header
31.36 + * Notice in each file and include the License file at
31.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
31.38 + * particular file as subject to the "Classpath" exception as provided
31.39 + * by Oracle in the GPL Version 2 section of the License file that
31.40 + * accompanied this code. If applicable, add the following below the
31.41 + * License Header, with the fields enclosed by brackets [] replaced by
31.42 + * your own identifying information:
31.43 + * "Portions Copyrighted [year] [name of copyright owner]"
31.44 + *
31.45 + * Contributor(s):
31.46 + *
31.47 + * The Original Software is NetBeans. The Initial Developer of the Original
31.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
31.49 + *
31.50 + * If you wish your version of this file to be governed by only the CDDL
31.51 + * or only the GPL Version 2, indicate your decision by adding
31.52 + * "[Contributor] elects to include this software in this distribution
31.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
31.54 + * single choice of license, a recipient has the option to distribute
31.55 + * your version of this file under either the CDDL, the GPL Version 2 or
31.56 + * to extend the choice of license to its licensees as provided above.
31.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
31.58 + * Version 2 license, then the option applies only if the new code is
31.59 + * made subject to such option by the copyright holder.
31.60 */
31.61 package net.java.html.js;
31.62
32.1 --- a/boot/src/main/java/net/java/html/js/package.html Thu Dec 19 17:11:01 2013 +0100
32.2 +++ b/boot/src/main/java/net/java/html/js/package.html Tue Jan 07 08:21:57 2014 +0100
32.3 @@ -1,23 +1,45 @@
32.4 <!--
32.5
32.6 - HTML via Java(tm) Language Bindings
32.7 - Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
32.8 + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
32.9
32.10 - This program is free software: you can redistribute it and/or modify
32.11 - it under the terms of the GNU General Public License as published by
32.12 - the Free Software Foundation, version 2 of the License.
32.13 + Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
32.14
32.15 - This program is distributed in the hope that it will be useful,
32.16 - but WITHOUT ANY WARRANTY; without even the implied warranty of
32.17 - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32.18 - GNU General Public License for more details. apidesign.org
32.19 - designates this particular file as subject to the
32.20 - "Classpath" exception as provided by apidesign.org
32.21 - in the License file that accompanied this code.
32.22 + Oracle and Java are registered trademarks of Oracle and/or its affiliates.
32.23 + Other names may be trademarks of their respective owners.
32.24
32.25 - You should have received a copy of the GNU General Public License
32.26 - along with this program. Look for COPYING file in the top folder.
32.27 - If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
32.28 + The contents of this file are subject to the terms of either the GNU
32.29 + General Public License Version 2 only ("GPL") or the Common
32.30 + Development and Distribution License("CDDL") (collectively, the
32.31 + "License"). You may not use this file except in compliance with the
32.32 + License. You can obtain a copy of the License at
32.33 + http://www.netbeans.org/cddl-gplv2.html
32.34 + or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
32.35 + specific language governing permissions and limitations under the
32.36 + License. When distributing the software, include this License Header
32.37 + Notice in each file and include the License file at
32.38 + nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
32.39 + particular file as subject to the "Classpath" exception as provided
32.40 + by Oracle in the GPL Version 2 section of the License file that
32.41 + accompanied this code. If applicable, add the following below the
32.42 + License Header, with the fields enclosed by brackets [] replaced by
32.43 + your own identifying information:
32.44 + "Portions Copyrighted [year] [name of copyright owner]"
32.45 +
32.46 + Contributor(s):
32.47 +
32.48 + The Original Software is NetBeans. The Initial Developer of the Original
32.49 + Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
32.50 +
32.51 + If you wish your version of this file to be governed by only the CDDL
32.52 + or only the GPL Version 2, indicate your decision by adding
32.53 + "[Contributor] elects to include this software in this distribution
32.54 + under the [CDDL or GPL Version 2] license." If you do not indicate a
32.55 + single choice of license, a recipient has the option to distribute
32.56 + your version of this file under either the CDDL, the GPL Version 2 or
32.57 + to extend the choice of license to its licensees as provided above.
32.58 + However, if you add GPL Version 2 code and therefore, elected the GPL
32.59 + Version 2 license, then the option applies only if the new code is
32.60 + made subject to such option by the copyright holder.
32.61
32.62 -->
32.63 <!DOCTYPE html>
33.1 --- a/boot/src/main/java/org/apidesign/html/boot/impl/FindResources.java Thu Dec 19 17:11:01 2013 +0100
33.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
33.3 @@ -1,34 +0,0 @@
33.4 -/**
33.5 - * HTML via Java(tm) Language Bindings
33.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
33.7 - *
33.8 - * This program is free software: you can redistribute it and/or modify
33.9 - * it under the terms of the GNU General Public License as published by
33.10 - * the Free Software Foundation, version 2 of the License.
33.11 - *
33.12 - * This program is distributed in the hope that it will be useful,
33.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
33.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33.15 - * GNU General Public License for more details. apidesign.org
33.16 - * designates this particular file as subject to the
33.17 - * "Classpath" exception as provided by apidesign.org
33.18 - * in the License file that accompanied this code.
33.19 - *
33.20 - * You should have received a copy of the GNU General Public License
33.21 - * along with this program. Look for COPYING file in the top folder.
33.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
33.23 - */
33.24 -package org.apidesign.html.boot.impl;
33.25 -
33.26 -import java.net.URL;
33.27 -import java.util.Collection;
33.28 -
33.29 -/**
33.30 - *
33.31 - * @author Jaroslav Tulach <jtulach@netbeans.org>
33.32 - */
33.33 -public interface FindResources {
33.34 -
33.35 - public void findResources(String path, Collection<? super URL> results, boolean oneIsEnough);
33.36 -
33.37 -}
34.1 --- a/boot/src/main/java/org/apidesign/html/boot/impl/FnContext.java Thu Dec 19 17:11:01 2013 +0100
34.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
34.3 @@ -1,76 +0,0 @@
34.4 -/**
34.5 - * HTML via Java(tm) Language Bindings
34.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
34.7 - *
34.8 - * This program is free software: you can redistribute it and/or modify
34.9 - * it under the terms of the GNU General Public License as published by
34.10 - * the Free Software Foundation, version 2 of the License.
34.11 - *
34.12 - * This program is distributed in the hope that it will be useful,
34.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
34.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
34.15 - * GNU General Public License for more details. apidesign.org
34.16 - * designates this particular file as subject to the
34.17 - * "Classpath" exception as provided by apidesign.org
34.18 - * in the License file that accompanied this code.
34.19 - *
34.20 - * You should have received a copy of the GNU General Public License
34.21 - * along with this program. Look for COPYING file in the top folder.
34.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
34.23 - */
34.24 -package org.apidesign.html.boot.impl;
34.25 -
34.26 -import java.io.Closeable;
34.27 -import java.io.IOException;
34.28 -import java.util.logging.Logger;
34.29 -import org.apidesign.html.boot.spi.Fn;
34.30 -
34.31 -/**
34.32 - *
34.33 - * @author Jaroslav Tulach <jtulach@netbeans.org>
34.34 - */
34.35 -public final class FnContext implements Closeable {
34.36 - private static final Logger LOG = Logger.getLogger(FnContext.class.getName());
34.37 -
34.38 - private Object prev;
34.39 - private FnContext(Fn.Presenter p) {
34.40 - this.prev = p;
34.41 - }
34.42 -
34.43 - @Override
34.44 - public void close() throws IOException {
34.45 - if (prev != this) {
34.46 - currentPresenter((Fn.Presenter)prev);
34.47 - prev = this;
34.48 - }
34.49 - }
34.50 -/*
34.51 - @Override
34.52 - protected void finalize() throws Throwable {
34.53 - if (prev != null) {
34.54 - LOG.warning("Unclosed context!");
34.55 - }
34.56 - }
34.57 -*/
34.58 - public static Closeable activate(Fn.Presenter newP) {
34.59 - return new FnContext(currentPresenter(newP));
34.60 - }
34.61 -
34.62 -
34.63 - private static final ThreadLocal<Fn.Presenter> CURRENT = new ThreadLocal<Fn.Presenter>();
34.64 -
34.65 - public static Fn.Presenter currentPresenter(Fn.Presenter p) {
34.66 - Fn.Presenter prev = CURRENT.get();
34.67 - CURRENT.set(p);
34.68 - return prev;
34.69 - }
34.70 -
34.71 - public static Fn.Presenter currentPresenter(boolean canReturnNull) {
34.72 - Fn.Presenter p = CURRENT.get();
34.73 - if (p == null && !canReturnNull) {
34.74 - throw new IllegalStateException("No current WebView context around!");
34.75 - }
34.76 - return p;
34.77 - }
34.78 -
34.79 -}
35.1 --- a/boot/src/main/java/org/apidesign/html/boot/impl/FnUtils.java Thu Dec 19 17:11:01 2013 +0100
35.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
35.3 @@ -1,593 +0,0 @@
35.4 -/**
35.5 - * HTML via Java(tm) Language Bindings
35.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
35.7 - *
35.8 - * This program is free software: you can redistribute it and/or modify
35.9 - * it under the terms of the GNU General Public License as published by
35.10 - * the Free Software Foundation, version 2 of the License.
35.11 - *
35.12 - * This program is distributed in the hope that it will be useful,
35.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
35.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35.15 - * GNU General Public License for more details. apidesign.org
35.16 - * designates this particular file as subject to the
35.17 - * "Classpath" exception as provided by apidesign.org
35.18 - * in the License file that accompanied this code.
35.19 - *
35.20 - * You should have received a copy of the GNU General Public License
35.21 - * along with this program. Look for COPYING file in the top folder.
35.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
35.23 - */
35.24 -package org.apidesign.html.boot.impl;
35.25 -
35.26 -import java.io.Closeable;
35.27 -import java.io.IOException;
35.28 -import java.io.InputStream;
35.29 -import java.io.InputStreamReader;
35.30 -import java.io.Reader;
35.31 -import java.net.URL;
35.32 -import java.util.ArrayList;
35.33 -import java.util.Collections;
35.34 -import java.util.Enumeration;
35.35 -import java.util.List;
35.36 -import java.util.Map;
35.37 -import java.util.concurrent.Callable;
35.38 -import org.apidesign.html.boot.spi.Fn;
35.39 -import org.objectweb.asm.AnnotationVisitor;
35.40 -import org.objectweb.asm.ClassReader;
35.41 -import org.objectweb.asm.ClassVisitor;
35.42 -import org.objectweb.asm.ClassWriter;
35.43 -import org.objectweb.asm.Label;
35.44 -import org.objectweb.asm.MethodVisitor;
35.45 -import org.objectweb.asm.Opcodes;
35.46 -import org.objectweb.asm.Type;
35.47 -import org.objectweb.asm.signature.SignatureReader;
35.48 -import org.objectweb.asm.signature.SignatureVisitor;
35.49 -import org.objectweb.asm.signature.SignatureWriter;
35.50 -
35.51 -/**
35.52 - *
35.53 - * @author Jaroslav Tulach <jtulach@netbeans.org>
35.54 - */
35.55 -public final class FnUtils implements Fn.Presenter {
35.56 -
35.57 - private FnUtils() {
35.58 - }
35.59 -
35.60 - /** Seeks for {@link JavaScriptBody} and {@link JavaScriptResource} annotations
35.61 - * in the bytecode and converts them into real code. Used by Maven plugin
35.62 - * postprocessing classes.
35.63 - *
35.64 - * @param bytecode the original bytecode with javascript specific annotations
35.65 - * @param loader the loader to load resources (scripts and classes) when needed
35.66 - * @return the transformed bytecode
35.67 - * @since 0.7
35.68 - */
35.69 - public static byte[] transform(byte[] bytecode, ClassLoader loader) {
35.70 - ClassReader cr = new ClassReader(bytecode) {
35.71 - // to allow us to compile with -profile compact1 on
35.72 - // JDK8 while processing the class as JDK7, the highest
35.73 - // class format asm 4.1 understands to
35.74 - @Override
35.75 - public short readShort(int index) {
35.76 - short s = super.readShort(index);
35.77 - if (index == 6 && s > Opcodes.V1_7) {
35.78 - return Opcodes.V1_7;
35.79 - }
35.80 - return s;
35.81 - }
35.82 - };
35.83 - FindInClass tst = new FindInClass(loader, null);
35.84 - cr.accept(tst, 0);
35.85 - if (tst.found > 0) {
35.86 - ClassWriter w = new ClassWriterEx(loader, cr, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
35.87 - FindInClass fic = new FindInClass(loader, w);
35.88 - cr.accept(fic, 0);
35.89 - bytecode = w.toByteArray();
35.90 - }
35.91 - return bytecode;
35.92 - }
35.93 -
35.94 - public static boolean isJavaScriptCapable(ClassLoader l) {
35.95 - if (l instanceof JsClassLoader) {
35.96 - return true;
35.97 - }
35.98 - Class<?> clazz;
35.99 - Closeable c = Fn.activate(new FnUtils());
35.100 - try {
35.101 - clazz = Class.forName(Test.class.getName(), true, l);
35.102 - final Object is = ((Callable<?>)clazz.newInstance()).call();
35.103 - return Boolean.TRUE.equals(is);
35.104 - } catch (Exception ex) {
35.105 - return false;
35.106 - } finally {
35.107 - try {
35.108 - c.close();
35.109 - } catch (IOException ex) {
35.110 - throw new IllegalStateException(ex);
35.111 - }
35.112 - }
35.113 - }
35.114 -
35.115 - public static boolean isValid(Fn fn) {
35.116 - return fn != null && fn.isValid();
35.117 - }
35.118 -
35.119 - public static ClassLoader newLoader(final FindResources f, final Fn.Presenter d, ClassLoader parent) {
35.120 - return new JsClassLoader(parent) {
35.121 - @Override
35.122 - protected URL findResource(String name) {
35.123 - List<URL> l = res(name, true);
35.124 - return l.isEmpty() ? null : l.get(0);
35.125 - }
35.126 -
35.127 - @Override
35.128 - protected Enumeration<URL> findResources(String name) {
35.129 - return Collections.enumeration(res(name, false));
35.130 - }
35.131 -
35.132 - private List<URL> res(String name, boolean oneIsEnough) {
35.133 - List<URL> l = new ArrayList<URL>();
35.134 - f.findResources(name, l, oneIsEnough);
35.135 - return l;
35.136 - }
35.137 -
35.138 - @Override
35.139 - protected Fn defineFn(String code, String... names) {
35.140 - return d.defineFn(code, names);
35.141 - }
35.142 -
35.143 - @Override
35.144 - protected void loadScript(Reader code) throws Exception {
35.145 - d.loadScript(code);
35.146 - }
35.147 - };
35.148 - }
35.149 -
35.150 - static String callback(final String body) {
35.151 - return new JsCallback() {
35.152 - @Override
35.153 - protected CharSequence callMethod(
35.154 - String ident, String fqn, String method, String params
35.155 - ) {
35.156 - StringBuilder sb = new StringBuilder();
35.157 - sb.append("vm.").append(mangle(fqn, method, params));
35.158 - sb.append("(");
35.159 - if (ident != null) {
35.160 - sb.append(ident);
35.161 - }
35.162 - return sb;
35.163 - }
35.164 -
35.165 - }.parse(body);
35.166 - }
35.167 -
35.168 - static void loadScript(ClassLoader jcl, String resource) {
35.169 - final InputStream script = jcl.getResourceAsStream(resource);
35.170 - if (script == null) {
35.171 - throw new NullPointerException("Can't find " + resource);
35.172 - }
35.173 - try {
35.174 - Reader isr = null;
35.175 - try {
35.176 - isr = new InputStreamReader(script, "UTF-8");
35.177 - FnContext.currentPresenter(false).loadScript(isr);
35.178 - } finally {
35.179 - if (isr != null) {
35.180 - isr.close();
35.181 - }
35.182 - }
35.183 - } catch (Exception ex) {
35.184 - throw new IllegalStateException("Can't execute " + resource, ex);
35.185 - }
35.186 - }
35.187 -
35.188 - @Override
35.189 - public Fn defineFn(String code, String... names) {
35.190 - return new TrueFn();
35.191 - }
35.192 -
35.193 - @Override
35.194 - public void displayPage(URL page, Runnable onPageLoad) {
35.195 - }
35.196 -
35.197 - @Override
35.198 - public void loadScript(Reader code) throws Exception {
35.199 - }
35.200 -
35.201 - private static final class FindInClass extends ClassVisitor {
35.202 - private String name;
35.203 - private int found;
35.204 - private ClassLoader loader;
35.205 - private String resource;
35.206 -
35.207 - public FindInClass(ClassLoader l, ClassVisitor cv) {
35.208 - super(Opcodes.ASM4, cv);
35.209 - this.loader = l;
35.210 - }
35.211 -
35.212 - @Override
35.213 - public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
35.214 - this.name = name;
35.215 - super.visit(version, access, name, signature, superName, interfaces);
35.216 - }
35.217 -
35.218 - @Override
35.219 - public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
35.220 - if ("Lnet/java/html/js/JavaScriptResource;".equals(desc)) {
35.221 - return new LoadResource();
35.222 - }
35.223 - return super.visitAnnotation(desc, visible);
35.224 - }
35.225 -
35.226 - @Override
35.227 - public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
35.228 - return new FindInMethod(access, name, desc,
35.229 - super.visitMethod(access & (~Opcodes.ACC_NATIVE), name, desc, signature, exceptions)
35.230 - );
35.231 - }
35.232 -
35.233 - private final class FindInMethod extends MethodVisitor {
35.234 -
35.235 - private final String name;
35.236 - private final String desc;
35.237 - private final int access;
35.238 - private List<String> args;
35.239 - private String body;
35.240 - private boolean bodyGenerated;
35.241 -
35.242 - public FindInMethod(int access, String name, String desc, MethodVisitor mv) {
35.243 - super(Opcodes.ASM4, mv);
35.244 - this.access = access;
35.245 - this.name = name;
35.246 - this.desc = desc;
35.247 - }
35.248 -
35.249 - @Override
35.250 - public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
35.251 - if ("Lnet/java/html/js/JavaScriptBody;".equals(desc) // NOI18N
35.252 - || "Lorg/apidesign/bck2brwsr/core/JavaScriptBody;".equals(desc) // NOI18N
35.253 - ) {
35.254 - found++;
35.255 - return new FindInAnno();
35.256 - }
35.257 - return super.visitAnnotation(desc, visible);
35.258 - }
35.259 -
35.260 - private void generateJSBody(List<String> args, String body) {
35.261 - this.args = args;
35.262 - this.body = body;
35.263 - }
35.264 -
35.265 - @Override
35.266 - public void visitCode() {
35.267 - if (body == null) {
35.268 - return;
35.269 - }
35.270 - generateBody();
35.271 - }
35.272 -
35.273 - private boolean generateBody() {
35.274 - if (bodyGenerated) {
35.275 - return false;
35.276 - }
35.277 - bodyGenerated = true;
35.278 -
35.279 - super.visitFieldInsn(
35.280 - Opcodes.GETSTATIC, FindInClass.this.name,
35.281 - "$$fn$$" + name + "_" + found,
35.282 - "Lorg/apidesign/html/boot/spi/Fn;"
35.283 - );
35.284 - super.visitInsn(Opcodes.DUP);
35.285 - super.visitMethodInsn(
35.286 - Opcodes.INVOKESTATIC,
35.287 - "org/apidesign/html/boot/spi/Fn", "isValid",
35.288 - "(Lorg/apidesign/html/boot/spi/Fn;)Z"
35.289 - );
35.290 - Label ifNotNull = new Label();
35.291 - super.visitJumpInsn(Opcodes.IFNE, ifNotNull);
35.292 -
35.293 - // init Fn
35.294 - super.visitInsn(Opcodes.POP);
35.295 - super.visitLdcInsn(Type.getObjectType(FindInClass.this.name));
35.296 - super.visitLdcInsn(body);
35.297 - super.visitIntInsn(Opcodes.SIPUSH, args.size());
35.298 - super.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/String");
35.299 - boolean needsVM = false;
35.300 - for (int i = 0; i < args.size(); i++) {
35.301 - assert !needsVM;
35.302 - String argName = args.get(i);
35.303 - needsVM = "vm".equals(argName);
35.304 - super.visitInsn(Opcodes.DUP);
35.305 - super.visitIntInsn(Opcodes.BIPUSH, i);
35.306 - super.visitLdcInsn(argName);
35.307 - super.visitInsn(Opcodes.AASTORE);
35.308 - }
35.309 - super.visitMethodInsn(Opcodes.INVOKESTATIC,
35.310 - "org/apidesign/html/boot/spi/Fn", "define",
35.311 - "(Ljava/lang/Class;Ljava/lang/String;[Ljava/lang/String;)Lorg/apidesign/html/boot/spi/Fn;"
35.312 - );
35.313 - if (resource != null) {
35.314 - super.visitLdcInsn(Type.getObjectType(FindInClass.this.name));
35.315 - super.visitLdcInsn(resource);
35.316 - super.visitMethodInsn(Opcodes.INVOKESTATIC,
35.317 - "org/apidesign/html/boot/spi/Fn", "preload",
35.318 - "(Lorg/apidesign/html/boot/spi/Fn;Ljava/lang/Class;Ljava/lang/String;)Lorg/apidesign/html/boot/spi/Fn;"
35.319 - );
35.320 - }
35.321 - super.visitInsn(Opcodes.DUP);
35.322 - super.visitFieldInsn(
35.323 - Opcodes.PUTSTATIC, FindInClass.this.name,
35.324 - "$$fn$$" + name + "_" + found,
35.325 - "Lorg/apidesign/html/boot/spi/Fn;"
35.326 - );
35.327 - // end of Fn init
35.328 -
35.329 - super.visitLabel(ifNotNull);
35.330 -
35.331 - final int offset;
35.332 - if ((access & Opcodes.ACC_STATIC) == 0) {
35.333 - offset = 1;
35.334 - super.visitIntInsn(Opcodes.ALOAD, 0);
35.335 - } else {
35.336 - offset = 0;
35.337 - super.visitInsn(Opcodes.ACONST_NULL);
35.338 - }
35.339 -
35.340 - super.visitIntInsn(Opcodes.SIPUSH, args.size());
35.341 - super.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object");
35.342 -
35.343 - class SV extends SignatureVisitor {
35.344 -
35.345 - private boolean nowReturn;
35.346 - private Type returnType;
35.347 - private int index;
35.348 - private int loadIndex = offset;
35.349 -
35.350 - public SV() {
35.351 - super(Opcodes.ASM4);
35.352 - }
35.353 -
35.354 - @Override
35.355 - public void visitBaseType(char descriptor) {
35.356 - final Type t = Type.getType("" + descriptor);
35.357 - if (nowReturn) {
35.358 - returnType = t;
35.359 - return;
35.360 - }
35.361 - FindInMethod.super.visitInsn(Opcodes.DUP);
35.362 - FindInMethod.super.visitIntInsn(Opcodes.SIPUSH, index++);
35.363 - FindInMethod.super.visitVarInsn(t.getOpcode(Opcodes.ILOAD), loadIndex++);
35.364 - String factory;
35.365 - switch (descriptor) {
35.366 - case 'I':
35.367 - factory = "java/lang/Integer";
35.368 - break;
35.369 - case 'J':
35.370 - factory = "java/lang/Long";
35.371 - loadIndex++;
35.372 - break;
35.373 - case 'S':
35.374 - factory = "java/lang/Short";
35.375 - break;
35.376 - case 'F':
35.377 - factory = "java/lang/Float";
35.378 - break;
35.379 - case 'D':
35.380 - factory = "java/lang/Double";
35.381 - loadIndex++;
35.382 - break;
35.383 - case 'Z':
35.384 - factory = "java/lang/Boolean";
35.385 - break;
35.386 - case 'C':
35.387 - factory = "java/lang/Character";
35.388 - break;
35.389 - case 'B':
35.390 - factory = "java/lang/Byte";
35.391 - break;
35.392 - default:
35.393 - throw new IllegalStateException(t.toString());
35.394 - }
35.395 - FindInMethod.super.visitMethodInsn(Opcodes.INVOKESTATIC,
35.396 - factory, "valueOf", "(" + descriptor + ")L" + factory + ";"
35.397 - );
35.398 - FindInMethod.super.visitInsn(Opcodes.AASTORE);
35.399 - }
35.400 -
35.401 - @Override
35.402 - public SignatureVisitor visitArrayType() {
35.403 - if (nowReturn) {
35.404 - throw new IllegalStateException("Not supported yet");
35.405 - }
35.406 - loadObject();
35.407 - return new SignatureWriter();
35.408 - }
35.409 -
35.410 - @Override
35.411 - public void visitClassType(String name) {
35.412 - if (nowReturn) {
35.413 - returnType = Type.getObjectType(name);
35.414 - return;
35.415 - }
35.416 - loadObject();
35.417 - }
35.418 -
35.419 - @Override
35.420 - public SignatureVisitor visitReturnType() {
35.421 - nowReturn = true;
35.422 - return this;
35.423 - }
35.424 -
35.425 - private void loadObject() {
35.426 - FindInMethod.super.visitInsn(Opcodes.DUP);
35.427 - FindInMethod.super.visitIntInsn(Opcodes.SIPUSH, index++);
35.428 - FindInMethod.super.visitVarInsn(Opcodes.ALOAD, loadIndex++);
35.429 - FindInMethod.super.visitInsn(Opcodes.AASTORE);
35.430 - }
35.431 -
35.432 - }
35.433 - SV sv = new SV();
35.434 - SignatureReader sr = new SignatureReader(desc);
35.435 - sr.accept(sv);
35.436 -
35.437 - if (needsVM) {
35.438 - FindInMethod.super.visitInsn(Opcodes.DUP);
35.439 - FindInMethod.super.visitIntInsn(Opcodes.SIPUSH, sv.index);
35.440 - int lastSlash = FindInClass.this.name.lastIndexOf('/');
35.441 - String jsCallbacks = FindInClass.this.name.substring(0, lastSlash + 1) + "$JsCallbacks$";
35.442 - FindInMethod.super.visitFieldInsn(Opcodes.GETSTATIC, jsCallbacks, "VM", "L" + jsCallbacks + ";");
35.443 - FindInMethod.super.visitMethodInsn(Opcodes.INVOKEVIRTUAL, jsCallbacks, "current", "()L" + jsCallbacks + ";");
35.444 - FindInMethod.super.visitInsn(Opcodes.AASTORE);
35.445 - }
35.446 -
35.447 - super.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
35.448 - "org/apidesign/html/boot/spi/Fn", "invoke", "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;"
35.449 - );
35.450 - switch (sv.returnType.getSort()) {
35.451 - case Type.VOID:
35.452 - super.visitInsn(Opcodes.RETURN);
35.453 - break;
35.454 - case Type.ARRAY:
35.455 - case Type.OBJECT:
35.456 - super.visitTypeInsn(Opcodes.CHECKCAST, sv.returnType.getInternalName());
35.457 - super.visitInsn(Opcodes.ARETURN);
35.458 - break;
35.459 - case Type.BOOLEAN:
35.460 - super.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Boolean");
35.461 - super.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
35.462 - "java/lang/Boolean", "booleanValue", "()Z"
35.463 - );
35.464 - super.visitInsn(Opcodes.IRETURN);
35.465 - break;
35.466 - default:
35.467 - super.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Number");
35.468 - super.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
35.469 - "java/lang/Number", sv.returnType.getClassName() + "Value", "()" + sv.returnType.getDescriptor()
35.470 - );
35.471 - super.visitInsn(sv.returnType.getOpcode(Opcodes.IRETURN));
35.472 - }
35.473 - return true;
35.474 - }
35.475 -
35.476 - @Override
35.477 - public void visitEnd() {
35.478 - super.visitEnd();
35.479 - if (body != null) {
35.480 - if (generateBody()) {
35.481 - // native method
35.482 - super.visitMaxs(1, 0);
35.483 - }
35.484 - FindInClass.this.visitField(
35.485 - Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC,
35.486 - "$$fn$$" + name + "_" + found,
35.487 - "Lorg/apidesign/html/boot/spi/Fn;",
35.488 - null, null
35.489 - );
35.490 - }
35.491 - }
35.492 -
35.493 - private final class FindInAnno extends AnnotationVisitor {
35.494 -
35.495 - private List<String> args = new ArrayList<String>();
35.496 - private String body;
35.497 - private boolean javacall = false;
35.498 -
35.499 - public FindInAnno() {
35.500 - super(Opcodes.ASM4);
35.501 - }
35.502 -
35.503 - @Override
35.504 - public void visit(String name, Object value) {
35.505 - if (name == null) {
35.506 - args.add((String) value);
35.507 - return;
35.508 - }
35.509 - if (name.equals("javacall")) { // NOI18N
35.510 - javacall = (Boolean) value;
35.511 - return;
35.512 - }
35.513 - assert name.equals("body");
35.514 - body = (String) value;
35.515 - }
35.516 -
35.517 - @Override
35.518 - public AnnotationVisitor visitArray(String name) {
35.519 - return this;
35.520 - }
35.521 -
35.522 - @Override
35.523 - public void visitEnd() {
35.524 - if (body != null) {
35.525 - if (javacall) {
35.526 - body = callback(body);
35.527 - args.add("vm");
35.528 - }
35.529 - generateJSBody(args, body);
35.530 - }
35.531 - }
35.532 - }
35.533 - }
35.534 -
35.535 - private final class LoadResource extends AnnotationVisitor {
35.536 -
35.537 - public LoadResource() {
35.538 - super(Opcodes.ASM4);
35.539 - }
35.540 -
35.541 - @Override
35.542 - public void visit(String attrName, Object value) {
35.543 - String relPath = (String) value;
35.544 - if (relPath.startsWith("/")) {
35.545 - resource = relPath;
35.546 - } else {
35.547 - int last = name.lastIndexOf('/');
35.548 - String fullPath = name.substring(0, last + 1) + relPath;
35.549 - resource = fullPath;
35.550 - }
35.551 - }
35.552 - }
35.553 - }
35.554 -
35.555 - private static class ClassWriterEx extends ClassWriter {
35.556 -
35.557 - private ClassLoader loader;
35.558 -
35.559 - public ClassWriterEx(ClassLoader l, ClassReader classReader, int flags) {
35.560 - super(classReader, flags);
35.561 - this.loader = l;
35.562 - }
35.563 -
35.564 - @Override
35.565 - protected String getCommonSuperClass(final String type1, final String type2) {
35.566 - Class<?> c, d;
35.567 - try {
35.568 - c = Class.forName(type1.replace('/', '.'), false, loader);
35.569 - d = Class.forName(type2.replace('/', '.'), false, loader);
35.570 - } catch (Exception e) {
35.571 - throw new RuntimeException(e.toString());
35.572 - }
35.573 - if (c.isAssignableFrom(d)) {
35.574 - return type1;
35.575 - }
35.576 - if (d.isAssignableFrom(c)) {
35.577 - return type2;
35.578 - }
35.579 - if (c.isInterface() || d.isInterface()) {
35.580 - return "java/lang/Object";
35.581 - } else {
35.582 - do {
35.583 - c = c.getSuperclass();
35.584 - } while (!c.isAssignableFrom(d));
35.585 - return c.getName().replace('.', '/');
35.586 - }
35.587 - }
35.588 - }
35.589 -
35.590 - private static final class TrueFn extends Fn {
35.591 - @Override
35.592 - public Object invoke(Object thiz, Object... args) throws Exception {
35.593 - return Boolean.TRUE;
35.594 - }
35.595 - } // end of TrueFn
35.596 -}
36.1 --- a/boot/src/main/java/org/apidesign/html/boot/impl/JavaScriptProcesor.java Thu Dec 19 17:11:01 2013 +0100
36.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
36.3 @@ -1,347 +0,0 @@
36.4 -/**
36.5 - * HTML via Java(tm) Language Bindings
36.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
36.7 - *
36.8 - * This program is free software: you can redistribute it and/or modify
36.9 - * it under the terms of the GNU General Public License as published by
36.10 - * the Free Software Foundation, version 2 of the License.
36.11 - *
36.12 - * This program is distributed in the hope that it will be useful,
36.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
36.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
36.15 - * GNU General Public License for more details. apidesign.org
36.16 - * designates this particular file as subject to the
36.17 - * "Classpath" exception as provided by apidesign.org
36.18 - * in the License file that accompanied this code.
36.19 - *
36.20 - * You should have received a copy of the GNU General Public License
36.21 - * along with this program. Look for COPYING file in the top folder.
36.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
36.23 - */
36.24 -package org.apidesign.html.boot.impl;
36.25 -
36.26 -import java.io.IOException;
36.27 -import java.io.Writer;
36.28 -import java.util.Collections;
36.29 -import java.util.HashMap;
36.30 -import java.util.HashSet;
36.31 -import java.util.List;
36.32 -import java.util.Map;
36.33 -import java.util.Set;
36.34 -import java.util.TreeMap;
36.35 -import javax.annotation.processing.AbstractProcessor;
36.36 -import javax.annotation.processing.Completion;
36.37 -import javax.annotation.processing.Completions;
36.38 -import javax.annotation.processing.Messager;
36.39 -import javax.annotation.processing.Processor;
36.40 -import javax.annotation.processing.RoundEnvironment;
36.41 -import javax.lang.model.SourceVersion;
36.42 -import javax.lang.model.element.AnnotationMirror;
36.43 -import javax.lang.model.element.Element;
36.44 -import javax.lang.model.element.ElementKind;
36.45 -import javax.lang.model.element.ExecutableElement;
36.46 -import javax.lang.model.element.Modifier;
36.47 -import javax.lang.model.element.PackageElement;
36.48 -import javax.lang.model.element.TypeElement;
36.49 -import javax.lang.model.element.VariableElement;
36.50 -import javax.lang.model.type.ArrayType;
36.51 -import javax.lang.model.type.ExecutableType;
36.52 -import javax.lang.model.type.TypeKind;
36.53 -import javax.lang.model.type.TypeMirror;
36.54 -import javax.tools.Diagnostic;
36.55 -import javax.tools.FileObject;
36.56 -import javax.tools.StandardLocation;
36.57 -import net.java.html.js.JavaScriptBody;
36.58 -import net.java.html.js.JavaScriptResource;
36.59 -import org.openide.util.lookup.ServiceProvider;
36.60 -
36.61 -/**
36.62 - *
36.63 - * @author Jaroslav Tulach <jtulach@netbeans.org>
36.64 - */
36.65 -@ServiceProvider(service = Processor.class)
36.66 -public final class JavaScriptProcesor extends AbstractProcessor {
36.67 - private final Map<String,Map<String,ExecutableElement>> javacalls =
36.68 - new HashMap<String,Map<String,ExecutableElement>>();
36.69 -
36.70 - @Override
36.71 - public Set<String> getSupportedAnnotationTypes() {
36.72 - Set<String> set = new HashSet<String>();
36.73 - set.add(JavaScriptBody.class.getName());
36.74 - set.add(JavaScriptResource.class.getName());
36.75 - return set;
36.76 - }
36.77 -
36.78 - @Override
36.79 - public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
36.80 - final Messager msg = processingEnv.getMessager();
36.81 - for (Element e : roundEnv.getElementsAnnotatedWith(JavaScriptBody.class)) {
36.82 - if (e.getKind() != ElementKind.METHOD && e.getKind() != ElementKind.CONSTRUCTOR) {
36.83 - continue;
36.84 - }
36.85 - ExecutableElement ee = (ExecutableElement)e;
36.86 - List<? extends VariableElement> params = ee.getParameters();
36.87 -
36.88 - JavaScriptBody jsb = e.getAnnotation(JavaScriptBody.class);
36.89 - if (jsb == null) {
36.90 - continue;
36.91 - }
36.92 - String[] arr = jsb.args();
36.93 - if (params.size() != arr.length) {
36.94 - msg.printMessage(Diagnostic.Kind.ERROR, "Number of args arguments does not match real arguments!", e);
36.95 - }
36.96 - if (!jsb.javacall() && jsb.body().contains(".@")) {
36.97 - msg.printMessage(Diagnostic.Kind.WARNING, "Usage of .@ usually requires javacall=true", e);
36.98 - }
36.99 - if (jsb.javacall()) {
36.100 - JsCallback verify = new VerifyCallback(e);
36.101 - try {
36.102 - verify.parse(jsb.body());
36.103 - } catch (IllegalStateException ex) {
36.104 - msg.printMessage(Diagnostic.Kind.ERROR, ex.getLocalizedMessage(), e);
36.105 - }
36.106 - }
36.107 - }
36.108 - for (Element e : roundEnv.getElementsAnnotatedWith(JavaScriptResource.class)) {
36.109 - JavaScriptResource r = e.getAnnotation(JavaScriptResource.class);
36.110 - if (r == null) {
36.111 - continue;
36.112 - }
36.113 - final String res;
36.114 - if (r.value().startsWith("/")) {
36.115 - res = r.value();
36.116 - } else {
36.117 - res = findPkg(e).replace('.', '/') + "/" + r.value();
36.118 - }
36.119 -
36.120 - try {
36.121 - FileObject os = processingEnv.getFiler().getResource(StandardLocation.SOURCE_PATH, "", res);
36.122 - os.openInputStream().close();
36.123 - } catch (IOException ex1) {
36.124 - try {
36.125 - FileObject os2 = processingEnv.getFiler().getResource(StandardLocation.CLASS_OUTPUT, "", res);
36.126 - os2.openInputStream().close();
36.127 - } catch (IOException ex2) {
36.128 - msg.printMessage(Diagnostic.Kind.ERROR, "Cannot find " + res + " in " + res + " package", e);
36.129 - }
36.130 - }
36.131 - }
36.132 -
36.133 - if (roundEnv.processingOver()) {
36.134 - generateCallbackClass(javacalls);
36.135 - javacalls.clear();
36.136 - }
36.137 - return true;
36.138 - }
36.139 -
36.140 - @Override
36.141 - public Iterable<? extends Completion> getCompletions(Element e,
36.142 - AnnotationMirror annotation, ExecutableElement member, String userText
36.143 - ) {
36.144 - StringBuilder sb = new StringBuilder();
36.145 - if (e.getKind() == ElementKind.METHOD && member.getSimpleName().contentEquals("args")) {
36.146 - ExecutableElement ee = (ExecutableElement) e;
36.147 - String sep = "";
36.148 - sb.append("{ ");
36.149 - for (VariableElement ve : ee.getParameters()) {
36.150 - sb.append(sep).append('"').append(ve.getSimpleName())
36.151 - .append('"');
36.152 - sep = ", ";
36.153 - }
36.154 - sb.append(" }");
36.155 - return Collections.nCopies(1, Completions.of(sb.toString()));
36.156 - }
36.157 - return null;
36.158 - }
36.159 -
36.160 - private class VerifyCallback extends JsCallback {
36.161 - private final Element e;
36.162 - public VerifyCallback(Element e) {
36.163 - this.e = e;
36.164 - }
36.165 -
36.166 - @Override
36.167 - protected CharSequence callMethod(String ident, String fqn, String method, String params) {
36.168 - final TypeElement type = processingEnv.getElementUtils().getTypeElement(fqn);
36.169 - if (type == null) {
36.170 - processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
36.171 - "Callback to non-existing class " + fqn, e
36.172 - );
36.173 - return "";
36.174 - }
36.175 - ExecutableElement found = null;
36.176 - StringBuilder foundParams = new StringBuilder();
36.177 - for (Element m : type.getEnclosedElements()) {
36.178 - if (m.getKind() != ElementKind.METHOD) {
36.179 - continue;
36.180 - }
36.181 - if (m.getSimpleName().contentEquals(method)) {
36.182 - String paramTypes = findParamTypes((ExecutableElement)m);
36.183 - if (paramTypes.equals(params)) {
36.184 - found = (ExecutableElement) m;
36.185 - break;
36.186 - }
36.187 - foundParams.append(paramTypes).append("\n");
36.188 - }
36.189 - }
36.190 - if (found == null) {
36.191 - if (foundParams.length() == 0) {
36.192 - processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
36.193 - "Callback to class " + fqn + " with unknown method " + method, e
36.194 - );
36.195 - } else {
36.196 - processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
36.197 - "Callback to " + fqn + "." + method + " with wrong parameters: " +
36.198 - params + ". Only known parameters are " + foundParams, e
36.199 - );
36.200 - }
36.201 - } else {
36.202 - Map<String,ExecutableElement> mangledOnes = javacalls.get(findPkg(e));
36.203 - if (mangledOnes == null) {
36.204 - mangledOnes = new TreeMap<String, ExecutableElement>();
36.205 - javacalls.put(findPkg(e), mangledOnes);
36.206 - }
36.207 - String mangled = JsCallback.mangle(fqn, method, findParamTypes(found));
36.208 - mangledOnes.put(mangled, found);
36.209 - }
36.210 - return "";
36.211 - }
36.212 -
36.213 - private String findParamTypes(ExecutableElement method) {
36.214 - ExecutableType t = (ExecutableType) method.asType();
36.215 - StringBuilder sb = new StringBuilder();
36.216 - sb.append('(');
36.217 - for (TypeMirror tm : t.getParameterTypes()) {
36.218 - if (tm.getKind().isPrimitive()) {
36.219 - switch (tm.getKind()) {
36.220 - case INT: sb.append('I'); break;
36.221 - case BOOLEAN: sb.append('Z'); break;
36.222 - case BYTE: sb.append('B'); break;
36.223 - case CHAR: sb.append('C'); break;
36.224 - case SHORT: sb.append('S'); break;
36.225 - case DOUBLE: sb.append('D'); break;
36.226 - case FLOAT: sb.append('F'); break;
36.227 - case LONG: sb.append('J'); break;
36.228 - default:
36.229 - throw new IllegalStateException("Uknown " + tm.getKind());
36.230 - }
36.231 - } else {
36.232 - while (tm.getKind() == TypeKind.ARRAY) {
36.233 - sb.append('[');
36.234 - tm = ((ArrayType)tm).getComponentType();
36.235 - }
36.236 - sb.append('L');
36.237 - sb.append(tm.toString().replace('.', '/'));
36.238 - sb.append(';');
36.239 - }
36.240 - }
36.241 - sb.append(')');
36.242 - return sb.toString();
36.243 - }
36.244 - }
36.245 -
36.246 - private void generateCallbackClass(Map<String,Map<String, ExecutableElement>> process) {
36.247 - for (Map.Entry<String, Map<String, ExecutableElement>> pkgEn : process.entrySet()) {
36.248 - String pkgName = pkgEn.getKey();
36.249 - Map<String, ExecutableElement> map = pkgEn.getValue();
36.250 - StringBuilder source = new StringBuilder();
36.251 - source.append("package ").append(pkgName).append(";\n");
36.252 - source.append("public final class $JsCallbacks$ {\n");
36.253 - source.append(" static final $JsCallbacks$ VM = new $JsCallbacks$(null);\n");
36.254 - source.append(" private final org.apidesign.html.boot.spi.Fn.Presenter p;\n");
36.255 - source.append(" private $JsCallbacks$ last;\n");
36.256 - source.append(" private $JsCallbacks$(org.apidesign.html.boot.spi.Fn.Presenter p) {\n");
36.257 - source.append(" this.p = p;\n");
36.258 - source.append(" }\n");
36.259 - source.append(" final $JsCallbacks$ current() {\n");
36.260 - source.append(" org.apidesign.html.boot.spi.Fn.Presenter now = org.apidesign.html.boot.spi.Fn.activePresenter();\n");
36.261 - source.append(" if (now == p) return this;\n");
36.262 - source.append(" if (last != null && now == last.p) return last;\n");
36.263 - source.append(" return last = new $JsCallbacks$(now);\n");
36.264 - source.append(" }\n");
36.265 - for (Map.Entry<String, ExecutableElement> entry : map.entrySet()) {
36.266 - final String mangled = entry.getKey();
36.267 - final ExecutableElement m = entry.getValue();
36.268 - final boolean isStatic = m.getModifiers().contains(Modifier.STATIC);
36.269 -
36.270 - source.append("\n public java.lang.Object ")
36.271 - .append(mangled)
36.272 - .append("(");
36.273 -
36.274 - String sep = "";
36.275 - if (!isStatic) {
36.276 - source.append(((TypeElement)m.getEnclosingElement()).getQualifiedName());
36.277 - source.append(" self");
36.278 - sep = ", ";
36.279 - }
36.280 -
36.281 - int cnt = 0;
36.282 - for (VariableElement ve : m.getParameters()) {
36.283 - source.append(sep);
36.284 - source.append(ve.asType());
36.285 - source.append(" arg").append(++cnt);
36.286 - sep = ", ";
36.287 - }
36.288 - source.append(") throws Throwable {\n");
36.289 - if (processingEnv.getSourceVersion().compareTo(SourceVersion.RELEASE_7) >= 0) {
36.290 - source.append(" try (java.io.Closeable a = org.apidesign.html.boot.spi.Fn.activate(p)) { \n");
36.291 - } else {
36.292 - source.append(" java.io.Closeable a = org.apidesign.html.boot.spi.Fn.activate(p); try {\n");
36.293 - }
36.294 - source.append(" ");
36.295 - if (m.getReturnType().getKind() != TypeKind.VOID) {
36.296 - source.append("return ");
36.297 - }
36.298 - if (isStatic) {
36.299 - source.append(((TypeElement)m.getEnclosingElement()).getQualifiedName());
36.300 - source.append('.');
36.301 - } else {
36.302 - source.append("self.");
36.303 - }
36.304 - source.append(m.getSimpleName());
36.305 - source.append("(");
36.306 - cnt = 0;
36.307 - sep = "";
36.308 - for (VariableElement ve : m.getParameters()) {
36.309 - source.append(sep);
36.310 - source.append("arg").append(++cnt);
36.311 - sep = ", ";
36.312 - }
36.313 - source.append(");\n");
36.314 - if (m.getReturnType().getKind() == TypeKind.VOID) {
36.315 - source.append(" return null;\n");
36.316 - }
36.317 - if (processingEnv.getSourceVersion().compareTo(SourceVersion.RELEASE_7) >= 0) {
36.318 - source.append(" }\n");
36.319 - } else {
36.320 -
36.321 - source.append(" } finally {\n");
36.322 - source.append(" a.close();\n");
36.323 - source.append(" }\n");
36.324 - }
36.325 - source.append(" }\n");
36.326 - }
36.327 - source.append("}\n");
36.328 - final String srcName = pkgName + ".$JsCallbacks$";
36.329 - try {
36.330 - Writer w = processingEnv.getFiler().createSourceFile(srcName,
36.331 - map.values().toArray(new Element[map.size()])
36.332 - ).openWriter();
36.333 - w.write(source.toString());
36.334 - w.close();
36.335 - } catch (IOException ex) {
36.336 - processingEnv.getMessager().printMessage(
36.337 - Diagnostic.Kind.ERROR, "Can't write " + srcName + ": " + ex.getMessage()
36.338 - );
36.339 - }
36.340 - }
36.341 - }
36.342 -
36.343 - private static String findPkg(Element e) {
36.344 - while (e.getKind() != ElementKind.PACKAGE) {
36.345 - e = e.getEnclosingElement();
36.346 - }
36.347 - return ((PackageElement)e).getQualifiedName().toString();
36.348 - }
36.349 -
36.350 -}
37.1 --- a/boot/src/main/java/org/apidesign/html/boot/impl/JsAgent.java Thu Dec 19 17:11:01 2013 +0100
37.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
37.3 @@ -1,45 +0,0 @@
37.4 -/**
37.5 - * HTML via Java(tm) Language Bindings
37.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
37.7 - *
37.8 - * This program is free software: you can redistribute it and/or modify
37.9 - * it under the terms of the GNU General Public License as published by
37.10 - * the Free Software Foundation, version 2 of the License.
37.11 - *
37.12 - * This program is distributed in the hope that it will be useful,
37.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
37.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
37.15 - * GNU General Public License for more details. apidesign.org
37.16 - * designates this particular file as subject to the
37.17 - * "Classpath" exception as provided by apidesign.org
37.18 - * in the License file that accompanied this code.
37.19 - *
37.20 - * You should have received a copy of the GNU General Public License
37.21 - * along with this program. Look for COPYING file in the top folder.
37.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
37.23 - */
37.24 -package org.apidesign.html.boot.impl;
37.25 -
37.26 -import java.lang.instrument.ClassFileTransformer;
37.27 -import java.lang.instrument.IllegalClassFormatException;
37.28 -import java.lang.instrument.Instrumentation;
37.29 -import java.security.ProtectionDomain;
37.30 -
37.31 -/**
37.32 - *
37.33 - * @author Jaroslav Tulach <jtulach@netbeans.org>
37.34 - */
37.35 -public final class JsAgent implements ClassFileTransformer {
37.36 - public static void agentmain(String args, Instrumentation instr) {
37.37 - instr.addTransformer(new JsAgent());
37.38 - }
37.39 -
37.40 - @Override
37.41 - public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
37.42 - try {
37.43 - return FnUtils.transform(classfileBuffer, loader);
37.44 - } catch (Exception ex) {
37.45 - return classfileBuffer;
37.46 - }
37.47 - }
37.48 -}
38.1 --- a/boot/src/main/java/org/apidesign/html/boot/impl/JsCallback.java Thu Dec 19 17:11:01 2013 +0100
38.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
38.3 @@ -1,138 +0,0 @@
38.4 -/**
38.5 - * HTML via Java(tm) Language Bindings
38.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
38.7 - *
38.8 - * This program is free software: you can redistribute it and/or modify
38.9 - * it under the terms of the GNU General Public License as published by
38.10 - * the Free Software Foundation, version 2 of the License.
38.11 - *
38.12 - * This program is distributed in the hope that it will be useful,
38.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
38.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38.15 - * GNU General Public License for more details. apidesign.org
38.16 - * designates this particular file as subject to the
38.17 - * "Classpath" exception as provided by apidesign.org
38.18 - * in the License file that accompanied this code.
38.19 - *
38.20 - * You should have received a copy of the GNU General Public License
38.21 - * along with this program. Look for COPYING file in the top folder.
38.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
38.23 - */
38.24 -package org.apidesign.html.boot.impl;
38.25 -
38.26 -
38.27 -/**
38.28 - *
38.29 - * @author Jaroslav Tulach <jtulach@netbeans.org>
38.30 - */
38.31 -abstract class JsCallback {
38.32 - final String parse(String body) {
38.33 - StringBuilder sb = new StringBuilder();
38.34 - int pos = 0;
38.35 - for (;;) {
38.36 - int next = body.indexOf(".@", pos);
38.37 - if (next == -1) {
38.38 - sb.append(body.substring(pos));
38.39 - body = sb.toString();
38.40 - break;
38.41 - }
38.42 - int ident = next;
38.43 - while (ident > 0) {
38.44 - if (!Character.isJavaIdentifierPart(body.charAt(--ident))) {
38.45 - ident++;
38.46 - break;
38.47 - }
38.48 - }
38.49 - String refId = body.substring(ident, next);
38.50 -
38.51 - sb.append(body.substring(pos, ident));
38.52 -
38.53 - int sigBeg = body.indexOf('(', next);
38.54 - int sigEnd = body.indexOf(')', sigBeg);
38.55 - int colon4 = body.indexOf("::", next);
38.56 - if (sigBeg == -1 || sigEnd == -1 || colon4 == -1) {
38.57 - throw new IllegalStateException(
38.58 - "Wrong format of instance callback. "
38.59 - + "Should be: 'inst.@pkg.Class::method(Ljava/lang/Object;)(param)':\n"
38.60 - + body
38.61 - );
38.62 - }
38.63 - String fqn = body.substring(next + 2, colon4);
38.64 - String method = body.substring(colon4 + 2, sigBeg);
38.65 - String params = body.substring(sigBeg, sigEnd + 1);
38.66 -
38.67 - int paramBeg = body.indexOf('(', sigEnd + 1);
38.68 - if (paramBeg == -1) {
38.69 - throw new IllegalStateException(
38.70 - "Wrong format of instance callback. "
38.71 - + "Should be: 'inst.@pkg.Class::method(Ljava/lang/Object;)(param)':\n"
38.72 - + body
38.73 - );
38.74 - }
38.75 -
38.76 - sb.append(callMethod(refId, fqn, method, params));
38.77 - if (body.charAt(paramBeg + 1) != (')')) {
38.78 - sb.append(",");
38.79 - }
38.80 - pos = paramBeg + 1;
38.81 - }
38.82 - pos = 0;
38.83 - sb = null;
38.84 - for (;;) {
38.85 - int next = body.indexOf("@", pos);
38.86 - if (next == -1) {
38.87 - if (sb == null) {
38.88 - return body;
38.89 - }
38.90 - sb.append(body.substring(pos));
38.91 - return sb.toString();
38.92 - }
38.93 - if (sb == null) {
38.94 - sb = new StringBuilder();
38.95 - }
38.96 -
38.97 - sb.append(body.substring(pos, next));
38.98 -
38.99 - int sigBeg = body.indexOf('(', next);
38.100 - int sigEnd = body.indexOf(')', sigBeg);
38.101 - int colon4 = body.indexOf("::", next);
38.102 - if (sigBeg == -1 || sigEnd == -1 || colon4 == -1) {
38.103 - throw new IllegalStateException(
38.104 - "Wrong format of static callback. "
38.105 - + "Should be: '@pkg.Class::staticMethod(Ljava/lang/Object;)(param)':\n"
38.106 - + body
38.107 - );
38.108 - }
38.109 - String fqn = body.substring(next + 1, colon4);
38.110 - String method = body.substring(colon4 + 2, sigBeg);
38.111 - String params = body.substring(sigBeg, sigEnd + 1);
38.112 -
38.113 - int paramBeg = body.indexOf('(', sigEnd + 1);
38.114 -
38.115 - sb.append(callMethod(null, fqn, method, params));
38.116 - pos = paramBeg + 1;
38.117 - }
38.118 - }
38.119 -
38.120 - protected abstract CharSequence callMethod(
38.121 - String ident, String fqn, String method, String params
38.122 - );
38.123 -
38.124 - static String mangle(String fqn, String method, String params) {
38.125 - if (params.startsWith("(")) {
38.126 - params = params.substring(1);
38.127 - }
38.128 - if (params.endsWith(")")) {
38.129 - params = params.substring(0, params.length() - 1);
38.130 - }
38.131 - return
38.132 - replace(fqn) + "$" + replace(method) + "$" + replace(params);
38.133 - }
38.134 -
38.135 - private static String replace(String orig) {
38.136 - return orig.replace("_", "_1").
38.137 - replace(";", "_2").
38.138 - replace("[", "_3").
38.139 - replace('.', '_').replace('/', '_');
38.140 - }
38.141 -}
39.1 --- a/boot/src/main/java/org/apidesign/html/boot/impl/JsClassLoader.java Thu Dec 19 17:11:01 2013 +0100
39.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
39.3 @@ -1,111 +0,0 @@
39.4 -/**
39.5 - * HTML via Java(tm) Language Bindings
39.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
39.7 - *
39.8 - * This program is free software: you can redistribute it and/or modify
39.9 - * it under the terms of the GNU General Public License as published by
39.10 - * the Free Software Foundation, version 2 of the License.
39.11 - *
39.12 - * This program is distributed in the hope that it will be useful,
39.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
39.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39.15 - * GNU General Public License for more details. apidesign.org
39.16 - * designates this particular file as subject to the
39.17 - * "Classpath" exception as provided by apidesign.org
39.18 - * in the License file that accompanied this code.
39.19 - *
39.20 - * You should have received a copy of the GNU General Public License
39.21 - * along with this program. Look for COPYING file in the top folder.
39.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
39.23 - */
39.24 -package org.apidesign.html.boot.impl;
39.25 -
39.26 -import org.apidesign.html.boot.spi.Fn;
39.27 -import java.io.IOException;
39.28 -import java.io.InputStream;
39.29 -import java.io.Reader;
39.30 -import java.net.URL;
39.31 -import java.util.Enumeration;
39.32 -
39.33 -/**
39.34 - *
39.35 - * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
39.36 - */
39.37 -abstract class JsClassLoader extends ClassLoader {
39.38 - JsClassLoader(ClassLoader parent) {
39.39 - super(parent);
39.40 - setDefaultAssertionStatus(JsClassLoader.class.desiredAssertionStatus());
39.41 - }
39.42 -
39.43 - @Override
39.44 - protected abstract URL findResource(String name);
39.45 -
39.46 - @Override
39.47 - protected abstract Enumeration<URL> findResources(String name);
39.48 -
39.49 - @Override
39.50 - protected Class<?> findClass(String name) throws ClassNotFoundException {
39.51 - if (name.startsWith("javafx")) {
39.52 - return Class.forName(name);
39.53 - }
39.54 - if (name.startsWith("netscape")) {
39.55 - return Class.forName(name);
39.56 - }
39.57 - if (name.startsWith("com.sun")) {
39.58 - return Class.forName(name);
39.59 - }
39.60 - if (name.equals(JsClassLoader.class.getName())) {
39.61 - return JsClassLoader.class;
39.62 - }
39.63 - if (name.equals(Fn.class.getName())) {
39.64 - return Fn.class;
39.65 - }
39.66 - if (name.equals(Fn.Presenter.class.getName())) {
39.67 - return Fn.Presenter.class;
39.68 - }
39.69 - if (name.equals(FnUtils.class.getName())) {
39.70 - return FnUtils.class;
39.71 - }
39.72 - if (
39.73 - name.equals("org.apidesign.html.boot.spi.Fn") ||
39.74 - name.equals("org.apidesign.html.boot.impl.FnUtils") ||
39.75 - name.equals("org.apidesign.html.boot.impl.FnContext")
39.76 - ) {
39.77 - return Class.forName(name);
39.78 - }
39.79 - URL u = findResource(name.replace('.', '/') + ".class");
39.80 - if (u != null) {
39.81 - InputStream is = null;
39.82 - try {
39.83 - is = u.openStream();
39.84 - byte[] arr = new byte[is.available()];
39.85 - int len = 0;
39.86 - while (len < arr.length) {
39.87 - int read = is.read(arr, len, arr.length - len);
39.88 - if (read == -1) {
39.89 - throw new IOException("Can't read " + u);
39.90 - }
39.91 - len += read;
39.92 - }
39.93 - is.close();
39.94 - is = null;
39.95 - arr = FnUtils.transform(arr, JsClassLoader.this);
39.96 - if (arr != null) {
39.97 - return defineClass(name, arr, 0, arr.length);
39.98 - }
39.99 - } catch (IOException ex) {
39.100 - throw new ClassNotFoundException("Can't load " + name, ex);
39.101 - } finally {
39.102 - try {
39.103 - if (is != null) is.close();
39.104 - } catch (IOException ex) {
39.105 - throw new ClassNotFoundException(null, ex);
39.106 - }
39.107 - }
39.108 - }
39.109 - return super.findClass(name);
39.110 - }
39.111 -
39.112 - protected abstract Fn defineFn(String code, String... names);
39.113 - protected abstract void loadScript(Reader code) throws Exception;
39.114 -}
40.1 --- a/boot/src/main/java/org/apidesign/html/boot/impl/Test.java Thu Dec 19 17:11:01 2013 +0100
40.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
40.3 @@ -1,35 +0,0 @@
40.4 -/**
40.5 - * HTML via Java(tm) Language Bindings
40.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
40.7 - *
40.8 - * This program is free software: you can redistribute it and/or modify
40.9 - * it under the terms of the GNU General Public License as published by
40.10 - * the Free Software Foundation, version 2 of the License.
40.11 - *
40.12 - * This program is distributed in the hope that it will be useful,
40.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
40.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
40.15 - * GNU General Public License for more details. apidesign.org
40.16 - * designates this particular file as subject to the
40.17 - * "Classpath" exception as provided by apidesign.org
40.18 - * in the License file that accompanied this code.
40.19 - *
40.20 - * You should have received a copy of the GNU General Public License
40.21 - * along with this program. Look for COPYING file in the top folder.
40.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
40.23 - */
40.24 -package org.apidesign.html.boot.impl;
40.25 -
40.26 -import java.util.concurrent.Callable;
40.27 -import net.java.html.js.JavaScriptBody;
40.28 -
40.29 -/**
40.30 - *
40.31 - * @author Jaroslav Tulach <jtulach@netbeans.org>
40.32 - */
40.33 -public final class Test implements Callable<Boolean> {
40.34 - @Override @JavaScriptBody(args = {}, body = "return true;")
40.35 - public Boolean call() {
40.36 - return false;
40.37 - }
40.38 -}
41.1 --- a/boot/src/main/java/org/apidesign/html/boot/spi/Fn.java Thu Dec 19 17:11:01 2013 +0100
41.2 +++ b/boot/src/main/java/org/apidesign/html/boot/spi/Fn.java Tue Jan 07 08:21:57 2014 +0100
41.3 @@ -1,22 +1,44 @@
41.4 /**
41.5 - * HTML via Java(tm) Language Bindings
41.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
41.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
41.8 *
41.9 - * This program is free software: you can redistribute it and/or modify
41.10 - * it under the terms of the GNU General Public License as published by
41.11 - * the Free Software Foundation, version 2 of the License.
41.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
41.13 *
41.14 - * This program is distributed in the hope that it will be useful,
41.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
41.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
41.17 - * GNU General Public License for more details. apidesign.org
41.18 - * designates this particular file as subject to the
41.19 - * "Classpath" exception as provided by apidesign.org
41.20 - * in the License file that accompanied this code.
41.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
41.22 + * Other names may be trademarks of their respective owners.
41.23 *
41.24 - * You should have received a copy of the GNU General Public License
41.25 - * along with this program. Look for COPYING file in the top folder.
41.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
41.27 + * The contents of this file are subject to the terms of either the GNU
41.28 + * General Public License Version 2 only ("GPL") or the Common
41.29 + * Development and Distribution License("CDDL") (collectively, the
41.30 + * "License"). You may not use this file except in compliance with the
41.31 + * License. You can obtain a copy of the License at
41.32 + * http://www.netbeans.org/cddl-gplv2.html
41.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
41.34 + * specific language governing permissions and limitations under the
41.35 + * License. When distributing the software, include this License Header
41.36 + * Notice in each file and include the License file at
41.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
41.38 + * particular file as subject to the "Classpath" exception as provided
41.39 + * by Oracle in the GPL Version 2 section of the License file that
41.40 + * accompanied this code. If applicable, add the following below the
41.41 + * License Header, with the fields enclosed by brackets [] replaced by
41.42 + * your own identifying information:
41.43 + * "Portions Copyrighted [year] [name of copyright owner]"
41.44 + *
41.45 + * Contributor(s):
41.46 + *
41.47 + * The Original Software is NetBeans. The Initial Developer of the Original
41.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
41.49 + *
41.50 + * If you wish your version of this file to be governed by only the CDDL
41.51 + * or only the GPL Version 2, indicate your decision by adding
41.52 + * "[Contributor] elects to include this software in this distribution
41.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
41.54 + * single choice of license, a recipient has the option to distribute
41.55 + * your version of this file under either the CDDL, the GPL Version 2 or
41.56 + * to extend the choice of license to its licensees as provided above.
41.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
41.58 + * Version 2 license, then the option applies only if the new code is
41.59 + * made subject to such option by the copyright holder.
41.60 */
41.61 package org.apidesign.html.boot.spi;
41.62
41.63 @@ -29,9 +51,8 @@
41.64 import java.util.HashSet;
41.65 import java.util.Map;
41.66 import java.util.Set;
41.67 -import java.util.WeakHashMap;
41.68 import net.java.html.js.JavaScriptBody;
41.69 -import org.apidesign.html.boot.impl.FnContext;
41.70 +import org.netbeans.html.boot.impl.FnContext;
41.71
41.72 /** Represents single JavaScript function that can be invoked.
41.73 * Created via {@link Presenter#defineFn(java.lang.String, java.lang.String...)}.
42.1 --- a/boot/src/main/java/org/apidesign/html/boot/spi/package.html Thu Dec 19 17:11:01 2013 +0100
42.2 +++ b/boot/src/main/java/org/apidesign/html/boot/spi/package.html Tue Jan 07 08:21:57 2014 +0100
42.3 @@ -1,23 +1,45 @@
42.4 <!--
42.5
42.6 - HTML via Java(tm) Language Bindings
42.7 - Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
42.8 + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
42.9
42.10 - This program is free software: you can redistribute it and/or modify
42.11 - it under the terms of the GNU General Public License as published by
42.12 - the Free Software Foundation, version 2 of the License.
42.13 + Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
42.14
42.15 - This program is distributed in the hope that it will be useful,
42.16 - but WITHOUT ANY WARRANTY; without even the implied warranty of
42.17 - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
42.18 - GNU General Public License for more details. apidesign.org
42.19 - designates this particular file as subject to the
42.20 - "Classpath" exception as provided by apidesign.org
42.21 - in the License file that accompanied this code.
42.22 + Oracle and Java are registered trademarks of Oracle and/or its affiliates.
42.23 + Other names may be trademarks of their respective owners.
42.24
42.25 - You should have received a copy of the GNU General Public License
42.26 - along with this program. Look for COPYING file in the top folder.
42.27 - If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
42.28 + The contents of this file are subject to the terms of either the GNU
42.29 + General Public License Version 2 only ("GPL") or the Common
42.30 + Development and Distribution License("CDDL") (collectively, the
42.31 + "License"). You may not use this file except in compliance with the
42.32 + License. You can obtain a copy of the License at
42.33 + http://www.netbeans.org/cddl-gplv2.html
42.34 + or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
42.35 + specific language governing permissions and limitations under the
42.36 + License. When distributing the software, include this License Header
42.37 + Notice in each file and include the License file at
42.38 + nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
42.39 + particular file as subject to the "Classpath" exception as provided
42.40 + by Oracle in the GPL Version 2 section of the License file that
42.41 + accompanied this code. If applicable, add the following below the
42.42 + License Header, with the fields enclosed by brackets [] replaced by
42.43 + your own identifying information:
42.44 + "Portions Copyrighted [year] [name of copyright owner]"
42.45 +
42.46 + Contributor(s):
42.47 +
42.48 + The Original Software is NetBeans. The Initial Developer of the Original
42.49 + Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
42.50 +
42.51 + If you wish your version of this file to be governed by only the CDDL
42.52 + or only the GPL Version 2, indicate your decision by adding
42.53 + "[Contributor] elects to include this software in this distribution
42.54 + under the [CDDL or GPL Version 2] license." If you do not indicate a
42.55 + single choice of license, a recipient has the option to distribute
42.56 + your version of this file under either the CDDL, the GPL Version 2 or
42.57 + to extend the choice of license to its licensees as provided above.
42.58 + However, if you add GPL Version 2 code and therefore, elected the GPL
42.59 + Version 2 license, then the option applies only if the new code is
42.60 + made subject to such option by the copyright holder.
42.61
42.62 -->
42.63 <!DOCTYPE html>
43.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
43.2 +++ b/boot/src/main/java/org/netbeans/html/boot/impl/FindResources.java Tue Jan 07 08:21:57 2014 +0100
43.3 @@ -0,0 +1,56 @@
43.4 +/**
43.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
43.6 + *
43.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
43.8 + *
43.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
43.10 + * Other names may be trademarks of their respective owners.
43.11 + *
43.12 + * The contents of this file are subject to the terms of either the GNU
43.13 + * General Public License Version 2 only ("GPL") or the Common
43.14 + * Development and Distribution License("CDDL") (collectively, the
43.15 + * "License"). You may not use this file except in compliance with the
43.16 + * License. You can obtain a copy of the License at
43.17 + * http://www.netbeans.org/cddl-gplv2.html
43.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
43.19 + * specific language governing permissions and limitations under the
43.20 + * License. When distributing the software, include this License Header
43.21 + * Notice in each file and include the License file at
43.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
43.23 + * particular file as subject to the "Classpath" exception as provided
43.24 + * by Oracle in the GPL Version 2 section of the License file that
43.25 + * accompanied this code. If applicable, add the following below the
43.26 + * License Header, with the fields enclosed by brackets [] replaced by
43.27 + * your own identifying information:
43.28 + * "Portions Copyrighted [year] [name of copyright owner]"
43.29 + *
43.30 + * Contributor(s):
43.31 + *
43.32 + * The Original Software is NetBeans. The Initial Developer of the Original
43.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
43.34 + *
43.35 + * If you wish your version of this file to be governed by only the CDDL
43.36 + * or only the GPL Version 2, indicate your decision by adding
43.37 + * "[Contributor] elects to include this software in this distribution
43.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
43.39 + * single choice of license, a recipient has the option to distribute
43.40 + * your version of this file under either the CDDL, the GPL Version 2 or
43.41 + * to extend the choice of license to its licensees as provided above.
43.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
43.43 + * Version 2 license, then the option applies only if the new code is
43.44 + * made subject to such option by the copyright holder.
43.45 + */
43.46 +package org.netbeans.html.boot.impl;
43.47 +
43.48 +import java.net.URL;
43.49 +import java.util.Collection;
43.50 +
43.51 +/**
43.52 + *
43.53 + * @author Jaroslav Tulach <jtulach@netbeans.org>
43.54 + */
43.55 +public interface FindResources {
43.56 +
43.57 + public void findResources(String path, Collection<? super URL> results, boolean oneIsEnough);
43.58 +
43.59 +}
44.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
44.2 +++ b/boot/src/main/java/org/netbeans/html/boot/impl/FnContext.java Tue Jan 07 08:21:57 2014 +0100
44.3 @@ -0,0 +1,98 @@
44.4 +/**
44.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
44.6 + *
44.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
44.8 + *
44.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
44.10 + * Other names may be trademarks of their respective owners.
44.11 + *
44.12 + * The contents of this file are subject to the terms of either the GNU
44.13 + * General Public License Version 2 only ("GPL") or the Common
44.14 + * Development and Distribution License("CDDL") (collectively, the
44.15 + * "License"). You may not use this file except in compliance with the
44.16 + * License. You can obtain a copy of the License at
44.17 + * http://www.netbeans.org/cddl-gplv2.html
44.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
44.19 + * specific language governing permissions and limitations under the
44.20 + * License. When distributing the software, include this License Header
44.21 + * Notice in each file and include the License file at
44.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
44.23 + * particular file as subject to the "Classpath" exception as provided
44.24 + * by Oracle in the GPL Version 2 section of the License file that
44.25 + * accompanied this code. If applicable, add the following below the
44.26 + * License Header, with the fields enclosed by brackets [] replaced by
44.27 + * your own identifying information:
44.28 + * "Portions Copyrighted [year] [name of copyright owner]"
44.29 + *
44.30 + * Contributor(s):
44.31 + *
44.32 + * The Original Software is NetBeans. The Initial Developer of the Original
44.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
44.34 + *
44.35 + * If you wish your version of this file to be governed by only the CDDL
44.36 + * or only the GPL Version 2, indicate your decision by adding
44.37 + * "[Contributor] elects to include this software in this distribution
44.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
44.39 + * single choice of license, a recipient has the option to distribute
44.40 + * your version of this file under either the CDDL, the GPL Version 2 or
44.41 + * to extend the choice of license to its licensees as provided above.
44.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
44.43 + * Version 2 license, then the option applies only if the new code is
44.44 + * made subject to such option by the copyright holder.
44.45 + */
44.46 +package org.netbeans.html.boot.impl;
44.47 +
44.48 +import java.io.Closeable;
44.49 +import java.io.IOException;
44.50 +import java.util.logging.Logger;
44.51 +import org.apidesign.html.boot.spi.Fn;
44.52 +
44.53 +/**
44.54 + *
44.55 + * @author Jaroslav Tulach <jtulach@netbeans.org>
44.56 + */
44.57 +public final class FnContext implements Closeable {
44.58 + private static final Logger LOG = Logger.getLogger(FnContext.class.getName());
44.59 +
44.60 + private Object prev;
44.61 + private FnContext(Fn.Presenter p) {
44.62 + this.prev = p;
44.63 + }
44.64 +
44.65 + @Override
44.66 + public void close() throws IOException {
44.67 + if (prev != this) {
44.68 + currentPresenter((Fn.Presenter)prev);
44.69 + prev = this;
44.70 + }
44.71 + }
44.72 +/*
44.73 + @Override
44.74 + protected void finalize() throws Throwable {
44.75 + if (prev != null) {
44.76 + LOG.warning("Unclosed context!");
44.77 + }
44.78 + }
44.79 +*/
44.80 + public static Closeable activate(Fn.Presenter newP) {
44.81 + return new FnContext(currentPresenter(newP));
44.82 + }
44.83 +
44.84 +
44.85 + private static final ThreadLocal<Fn.Presenter> CURRENT = new ThreadLocal<Fn.Presenter>();
44.86 +
44.87 + public static Fn.Presenter currentPresenter(Fn.Presenter p) {
44.88 + Fn.Presenter prev = CURRENT.get();
44.89 + CURRENT.set(p);
44.90 + return prev;
44.91 + }
44.92 +
44.93 + public static Fn.Presenter currentPresenter(boolean canReturnNull) {
44.94 + Fn.Presenter p = CURRENT.get();
44.95 + if (p == null && !canReturnNull) {
44.96 + throw new IllegalStateException("No current WebView context around!");
44.97 + }
44.98 + return p;
44.99 + }
44.100 +
44.101 +}
45.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
45.2 +++ b/boot/src/main/java/org/netbeans/html/boot/impl/FnUtils.java Tue Jan 07 08:21:57 2014 +0100
45.3 @@ -0,0 +1,618 @@
45.4 +/**
45.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
45.6 + *
45.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
45.8 + *
45.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
45.10 + * Other names may be trademarks of their respective owners.
45.11 + *
45.12 + * The contents of this file are subject to the terms of either the GNU
45.13 + * General Public License Version 2 only ("GPL") or the Common
45.14 + * Development and Distribution License("CDDL") (collectively, the
45.15 + * "License"). You may not use this file except in compliance with the
45.16 + * License. You can obtain a copy of the License at
45.17 + * http://www.netbeans.org/cddl-gplv2.html
45.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
45.19 + * specific language governing permissions and limitations under the
45.20 + * License. When distributing the software, include this License Header
45.21 + * Notice in each file and include the License file at
45.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
45.23 + * particular file as subject to the "Classpath" exception as provided
45.24 + * by Oracle in the GPL Version 2 section of the License file that
45.25 + * accompanied this code. If applicable, add the following below the
45.26 + * License Header, with the fields enclosed by brackets [] replaced by
45.27 + * your own identifying information:
45.28 + * "Portions Copyrighted [year] [name of copyright owner]"
45.29 + *
45.30 + * Contributor(s):
45.31 + *
45.32 + * The Original Software is NetBeans. The Initial Developer of the Original
45.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
45.34 + *
45.35 + * If you wish your version of this file to be governed by only the CDDL
45.36 + * or only the GPL Version 2, indicate your decision by adding
45.37 + * "[Contributor] elects to include this software in this distribution
45.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
45.39 + * single choice of license, a recipient has the option to distribute
45.40 + * your version of this file under either the CDDL, the GPL Version 2 or
45.41 + * to extend the choice of license to its licensees as provided above.
45.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
45.43 + * Version 2 license, then the option applies only if the new code is
45.44 + * made subject to such option by the copyright holder.
45.45 + */
45.46 +package org.netbeans.html.boot.impl;
45.47 +
45.48 +import java.io.Closeable;
45.49 +import java.io.IOException;
45.50 +import java.io.InputStream;
45.51 +import java.io.InputStreamReader;
45.52 +import java.io.Reader;
45.53 +import java.net.URL;
45.54 +import java.util.ArrayList;
45.55 +import java.util.Collections;
45.56 +import java.util.Enumeration;
45.57 +import java.util.List;
45.58 +import java.util.concurrent.Callable;
45.59 +import org.apidesign.html.boot.spi.Fn;
45.60 +import org.objectweb.asm.AnnotationVisitor;
45.61 +import org.objectweb.asm.ClassReader;
45.62 +import org.objectweb.asm.ClassVisitor;
45.63 +import org.objectweb.asm.ClassWriter;
45.64 +import org.objectweb.asm.Label;
45.65 +import org.objectweb.asm.MethodVisitor;
45.66 +import org.objectweb.asm.Opcodes;
45.67 +import org.objectweb.asm.Type;
45.68 +import org.objectweb.asm.signature.SignatureReader;
45.69 +import org.objectweb.asm.signature.SignatureVisitor;
45.70 +import org.objectweb.asm.signature.SignatureWriter;
45.71 +
45.72 +/**
45.73 + *
45.74 + * @author Jaroslav Tulach <jtulach@netbeans.org>
45.75 + */
45.76 +public final class FnUtils implements Fn.Presenter {
45.77 +
45.78 + private FnUtils() {
45.79 + }
45.80 +
45.81 + /** Seeks for {@link JavaScriptBody} and {@link JavaScriptResource} annotations
45.82 + * in the bytecode and converts them into real code. Used by Maven plugin
45.83 + * postprocessing classes.
45.84 + *
45.85 + * @param bytecode the original bytecode with javascript specific annotations
45.86 + * @param loader the loader to load resources (scripts and classes) when needed
45.87 + * @return the transformed bytecode
45.88 + * @since 0.7
45.89 + */
45.90 + public static byte[] transform(byte[] bytecode, ClassLoader loader) {
45.91 + ClassReader cr = new ClassReader(bytecode) {
45.92 + // to allow us to compile with -profile compact1 on
45.93 + // JDK8 while processing the class as JDK7, the highest
45.94 + // class format asm 4.1 understands to
45.95 + @Override
45.96 + public short readShort(int index) {
45.97 + short s = super.readShort(index);
45.98 + if (index == 6 && s > Opcodes.V1_7) {
45.99 + return Opcodes.V1_7;
45.100 + }
45.101 + return s;
45.102 + }
45.103 + };
45.104 + FindInClass tst = new FindInClass(loader, null);
45.105 + cr.accept(tst, 0);
45.106 + if (tst.found > 0) {
45.107 + ClassWriter w = new ClassWriterEx(loader, cr, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
45.108 + FindInClass fic = new FindInClass(loader, w);
45.109 + cr.accept(fic, 0);
45.110 + bytecode = w.toByteArray();
45.111 + }
45.112 + return bytecode;
45.113 + }
45.114 +
45.115 + public static boolean isJavaScriptCapable(ClassLoader l) {
45.116 + if (l instanceof JsClassLoader) {
45.117 + return true;
45.118 + }
45.119 + Class<?> clazz;
45.120 + Closeable c = Fn.activate(new FnUtils());
45.121 + try {
45.122 + try {
45.123 + clazz = Class.forName(Test.class.getName(), true, l);
45.124 + } catch (ClassNotFoundException ex) {
45.125 + clazz = Test.class;
45.126 + }
45.127 + final Object is = ((Callable<?>)clazz.newInstance()).call();
45.128 + return Boolean.TRUE.equals(is);
45.129 + } catch (Exception ex) {
45.130 + return false;
45.131 + } finally {
45.132 + try {
45.133 + c.close();
45.134 + } catch (IOException ex) {
45.135 + throw new IllegalStateException(ex);
45.136 + }
45.137 + }
45.138 + }
45.139 +
45.140 + public static boolean isValid(Fn fn) {
45.141 + return fn != null && fn.isValid();
45.142 + }
45.143 +
45.144 + public static ClassLoader newLoader(final FindResources f, final Fn.Presenter d, ClassLoader parent) {
45.145 + return new JsClassLoader(parent) {
45.146 + @Override
45.147 + protected URL findResource(String name) {
45.148 + List<URL> l = res(name, true);
45.149 + return l.isEmpty() ? null : l.get(0);
45.150 + }
45.151 +
45.152 + @Override
45.153 + protected Enumeration<URL> findResources(String name) {
45.154 + return Collections.enumeration(res(name, false));
45.155 + }
45.156 +
45.157 + private List<URL> res(String name, boolean oneIsEnough) {
45.158 + List<URL> l = new ArrayList<URL>();
45.159 + f.findResources(name, l, oneIsEnough);
45.160 + return l;
45.161 + }
45.162 +
45.163 + @Override
45.164 + protected Fn defineFn(String code, String... names) {
45.165 + return d.defineFn(code, names);
45.166 + }
45.167 +
45.168 + @Override
45.169 + protected void loadScript(Reader code) throws Exception {
45.170 + d.loadScript(code);
45.171 + }
45.172 + };
45.173 + }
45.174 +
45.175 + static String callback(final String body) {
45.176 + return new JsCallback() {
45.177 + @Override
45.178 + protected CharSequence callMethod(
45.179 + String ident, String fqn, String method, String params
45.180 + ) {
45.181 + StringBuilder sb = new StringBuilder();
45.182 + sb.append("vm.").append(mangle(fqn, method, params));
45.183 + sb.append("(");
45.184 + if (ident != null) {
45.185 + sb.append(ident);
45.186 + }
45.187 + return sb;
45.188 + }
45.189 +
45.190 + }.parse(body);
45.191 + }
45.192 +
45.193 + static void loadScript(ClassLoader jcl, String resource) {
45.194 + final InputStream script = jcl.getResourceAsStream(resource);
45.195 + if (script == null) {
45.196 + throw new NullPointerException("Can't find " + resource);
45.197 + }
45.198 + try {
45.199 + Reader isr = null;
45.200 + try {
45.201 + isr = new InputStreamReader(script, "UTF-8");
45.202 + FnContext.currentPresenter(false).loadScript(isr);
45.203 + } finally {
45.204 + if (isr != null) {
45.205 + isr.close();
45.206 + }
45.207 + }
45.208 + } catch (Exception ex) {
45.209 + throw new IllegalStateException("Can't execute " + resource, ex);
45.210 + }
45.211 + }
45.212 +
45.213 + @Override
45.214 + public Fn defineFn(String code, String... names) {
45.215 + return new TrueFn();
45.216 + }
45.217 +
45.218 + @Override
45.219 + public void displayPage(URL page, Runnable onPageLoad) {
45.220 + }
45.221 +
45.222 + @Override
45.223 + public void loadScript(Reader code) throws Exception {
45.224 + }
45.225 +
45.226 + private static final class FindInClass extends ClassVisitor {
45.227 + private String name;
45.228 + private int found;
45.229 + private ClassLoader loader;
45.230 + private String resource;
45.231 +
45.232 + public FindInClass(ClassLoader l, ClassVisitor cv) {
45.233 + super(Opcodes.ASM4, cv);
45.234 + this.loader = l;
45.235 + }
45.236 +
45.237 + @Override
45.238 + public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
45.239 + this.name = name;
45.240 + super.visit(version, access, name, signature, superName, interfaces);
45.241 + }
45.242 +
45.243 + @Override
45.244 + public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
45.245 + if ("Lnet/java/html/js/JavaScriptResource;".equals(desc)) {
45.246 + return new LoadResource();
45.247 + }
45.248 + return super.visitAnnotation(desc, visible);
45.249 + }
45.250 +
45.251 + @Override
45.252 + public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
45.253 + return new FindInMethod(access, name, desc,
45.254 + super.visitMethod(access & (~Opcodes.ACC_NATIVE), name, desc, signature, exceptions)
45.255 + );
45.256 + }
45.257 +
45.258 + private final class FindInMethod extends MethodVisitor {
45.259 +
45.260 + private final String name;
45.261 + private final String desc;
45.262 + private final int access;
45.263 + private List<String> args;
45.264 + private String body;
45.265 + private boolean bodyGenerated;
45.266 +
45.267 + public FindInMethod(int access, String name, String desc, MethodVisitor mv) {
45.268 + super(Opcodes.ASM4, mv);
45.269 + this.access = access;
45.270 + this.name = name;
45.271 + this.desc = desc;
45.272 + }
45.273 +
45.274 + @Override
45.275 + public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
45.276 + if ("Lnet/java/html/js/JavaScriptBody;".equals(desc) // NOI18N
45.277 + || "Lorg/apidesign/bck2brwsr/core/JavaScriptBody;".equals(desc) // NOI18N
45.278 + ) {
45.279 + found++;
45.280 + return new FindInAnno();
45.281 + }
45.282 + return super.visitAnnotation(desc, visible);
45.283 + }
45.284 +
45.285 + private void generateJSBody(List<String> args, String body) {
45.286 + this.args = args;
45.287 + this.body = body;
45.288 + }
45.289 +
45.290 + @Override
45.291 + public void visitCode() {
45.292 + if (body == null) {
45.293 + return;
45.294 + }
45.295 + generateBody();
45.296 + }
45.297 +
45.298 + private boolean generateBody() {
45.299 + if (bodyGenerated) {
45.300 + return false;
45.301 + }
45.302 + bodyGenerated = true;
45.303 +
45.304 + super.visitFieldInsn(
45.305 + Opcodes.GETSTATIC, FindInClass.this.name,
45.306 + "$$fn$$" + name + "_" + found,
45.307 + "Lorg/apidesign/html/boot/spi/Fn;"
45.308 + );
45.309 + super.visitInsn(Opcodes.DUP);
45.310 + super.visitMethodInsn(
45.311 + Opcodes.INVOKESTATIC,
45.312 + "org/apidesign/html/boot/spi/Fn", "isValid",
45.313 + "(Lorg/apidesign/html/boot/spi/Fn;)Z"
45.314 + );
45.315 + Label ifNotNull = new Label();
45.316 + super.visitJumpInsn(Opcodes.IFNE, ifNotNull);
45.317 +
45.318 + // init Fn
45.319 + super.visitInsn(Opcodes.POP);
45.320 + super.visitLdcInsn(Type.getObjectType(FindInClass.this.name));
45.321 + super.visitLdcInsn(body);
45.322 + super.visitIntInsn(Opcodes.SIPUSH, args.size());
45.323 + super.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/String");
45.324 + boolean needsVM = false;
45.325 + for (int i = 0; i < args.size(); i++) {
45.326 + assert !needsVM;
45.327 + String argName = args.get(i);
45.328 + needsVM = "vm".equals(argName);
45.329 + super.visitInsn(Opcodes.DUP);
45.330 + super.visitIntInsn(Opcodes.BIPUSH, i);
45.331 + super.visitLdcInsn(argName);
45.332 + super.visitInsn(Opcodes.AASTORE);
45.333 + }
45.334 + super.visitMethodInsn(Opcodes.INVOKESTATIC,
45.335 + "org/apidesign/html/boot/spi/Fn", "define",
45.336 + "(Ljava/lang/Class;Ljava/lang/String;[Ljava/lang/String;)Lorg/apidesign/html/boot/spi/Fn;"
45.337 + );
45.338 + if (resource != null) {
45.339 + super.visitLdcInsn(Type.getObjectType(FindInClass.this.name));
45.340 + super.visitLdcInsn(resource);
45.341 + super.visitMethodInsn(Opcodes.INVOKESTATIC,
45.342 + "org/apidesign/html/boot/spi/Fn", "preload",
45.343 + "(Lorg/apidesign/html/boot/spi/Fn;Ljava/lang/Class;Ljava/lang/String;)Lorg/apidesign/html/boot/spi/Fn;"
45.344 + );
45.345 + }
45.346 + super.visitInsn(Opcodes.DUP);
45.347 + super.visitFieldInsn(
45.348 + Opcodes.PUTSTATIC, FindInClass.this.name,
45.349 + "$$fn$$" + name + "_" + found,
45.350 + "Lorg/apidesign/html/boot/spi/Fn;"
45.351 + );
45.352 + // end of Fn init
45.353 +
45.354 + super.visitLabel(ifNotNull);
45.355 +
45.356 + final int offset;
45.357 + if ((access & Opcodes.ACC_STATIC) == 0) {
45.358 + offset = 1;
45.359 + super.visitIntInsn(Opcodes.ALOAD, 0);
45.360 + } else {
45.361 + offset = 0;
45.362 + super.visitInsn(Opcodes.ACONST_NULL);
45.363 + }
45.364 +
45.365 + super.visitIntInsn(Opcodes.SIPUSH, args.size());
45.366 + super.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object");
45.367 +
45.368 + class SV extends SignatureVisitor {
45.369 +
45.370 + private boolean nowReturn;
45.371 + private Type returnType;
45.372 + private int index;
45.373 + private int loadIndex = offset;
45.374 +
45.375 + public SV() {
45.376 + super(Opcodes.ASM4);
45.377 + }
45.378 +
45.379 + @Override
45.380 + public void visitBaseType(char descriptor) {
45.381 + final Type t = Type.getType("" + descriptor);
45.382 + if (nowReturn) {
45.383 + returnType = t;
45.384 + return;
45.385 + }
45.386 + FindInMethod.super.visitInsn(Opcodes.DUP);
45.387 + FindInMethod.super.visitIntInsn(Opcodes.SIPUSH, index++);
45.388 + FindInMethod.super.visitVarInsn(t.getOpcode(Opcodes.ILOAD), loadIndex++);
45.389 + String factory;
45.390 + switch (descriptor) {
45.391 + case 'I':
45.392 + factory = "java/lang/Integer";
45.393 + break;
45.394 + case 'J':
45.395 + factory = "java/lang/Long";
45.396 + loadIndex++;
45.397 + break;
45.398 + case 'S':
45.399 + factory = "java/lang/Short";
45.400 + break;
45.401 + case 'F':
45.402 + factory = "java/lang/Float";
45.403 + break;
45.404 + case 'D':
45.405 + factory = "java/lang/Double";
45.406 + loadIndex++;
45.407 + break;
45.408 + case 'Z':
45.409 + factory = "java/lang/Boolean";
45.410 + break;
45.411 + case 'C':
45.412 + factory = "java/lang/Character";
45.413 + break;
45.414 + case 'B':
45.415 + factory = "java/lang/Byte";
45.416 + break;
45.417 + default:
45.418 + throw new IllegalStateException(t.toString());
45.419 + }
45.420 + FindInMethod.super.visitMethodInsn(Opcodes.INVOKESTATIC,
45.421 + factory, "valueOf", "(" + descriptor + ")L" + factory + ";"
45.422 + );
45.423 + FindInMethod.super.visitInsn(Opcodes.AASTORE);
45.424 + }
45.425 +
45.426 + @Override
45.427 + public SignatureVisitor visitArrayType() {
45.428 + if (nowReturn) {
45.429 + throw new IllegalStateException("Not supported yet");
45.430 + }
45.431 + loadObject();
45.432 + return new SignatureWriter();
45.433 + }
45.434 +
45.435 + @Override
45.436 + public void visitClassType(String name) {
45.437 + if (nowReturn) {
45.438 + returnType = Type.getObjectType(name);
45.439 + return;
45.440 + }
45.441 + loadObject();
45.442 + }
45.443 +
45.444 + @Override
45.445 + public SignatureVisitor visitReturnType() {
45.446 + nowReturn = true;
45.447 + return this;
45.448 + }
45.449 +
45.450 + private void loadObject() {
45.451 + FindInMethod.super.visitInsn(Opcodes.DUP);
45.452 + FindInMethod.super.visitIntInsn(Opcodes.SIPUSH, index++);
45.453 + FindInMethod.super.visitVarInsn(Opcodes.ALOAD, loadIndex++);
45.454 + FindInMethod.super.visitInsn(Opcodes.AASTORE);
45.455 + }
45.456 +
45.457 + }
45.458 + SV sv = new SV();
45.459 + SignatureReader sr = new SignatureReader(desc);
45.460 + sr.accept(sv);
45.461 +
45.462 + if (needsVM) {
45.463 + FindInMethod.super.visitInsn(Opcodes.DUP);
45.464 + FindInMethod.super.visitIntInsn(Opcodes.SIPUSH, sv.index);
45.465 + int lastSlash = FindInClass.this.name.lastIndexOf('/');
45.466 + String jsCallbacks = FindInClass.this.name.substring(0, lastSlash + 1) + "$JsCallbacks$";
45.467 + FindInMethod.super.visitFieldInsn(Opcodes.GETSTATIC, jsCallbacks, "VM", "L" + jsCallbacks + ";");
45.468 + FindInMethod.super.visitMethodInsn(Opcodes.INVOKEVIRTUAL, jsCallbacks, "current", "()L" + jsCallbacks + ";");
45.469 + FindInMethod.super.visitInsn(Opcodes.AASTORE);
45.470 + }
45.471 +
45.472 + super.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
45.473 + "org/apidesign/html/boot/spi/Fn", "invoke", "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;"
45.474 + );
45.475 + switch (sv.returnType.getSort()) {
45.476 + case Type.VOID:
45.477 + super.visitInsn(Opcodes.RETURN);
45.478 + break;
45.479 + case Type.ARRAY:
45.480 + case Type.OBJECT:
45.481 + super.visitTypeInsn(Opcodes.CHECKCAST, sv.returnType.getInternalName());
45.482 + super.visitInsn(Opcodes.ARETURN);
45.483 + break;
45.484 + case Type.BOOLEAN:
45.485 + super.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Boolean");
45.486 + super.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
45.487 + "java/lang/Boolean", "booleanValue", "()Z"
45.488 + );
45.489 + super.visitInsn(Opcodes.IRETURN);
45.490 + break;
45.491 + default:
45.492 + super.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Number");
45.493 + super.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
45.494 + "java/lang/Number", sv.returnType.getClassName() + "Value", "()" + sv.returnType.getDescriptor()
45.495 + );
45.496 + super.visitInsn(sv.returnType.getOpcode(Opcodes.IRETURN));
45.497 + }
45.498 + return true;
45.499 + }
45.500 +
45.501 + @Override
45.502 + public void visitEnd() {
45.503 + super.visitEnd();
45.504 + if (body != null) {
45.505 + if (generateBody()) {
45.506 + // native method
45.507 + super.visitMaxs(1, 0);
45.508 + }
45.509 + FindInClass.this.visitField(
45.510 + Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC,
45.511 + "$$fn$$" + name + "_" + found,
45.512 + "Lorg/apidesign/html/boot/spi/Fn;",
45.513 + null, null
45.514 + );
45.515 + }
45.516 + }
45.517 +
45.518 + private final class FindInAnno extends AnnotationVisitor {
45.519 +
45.520 + private List<String> args = new ArrayList<String>();
45.521 + private String body;
45.522 + private boolean javacall = false;
45.523 +
45.524 + public FindInAnno() {
45.525 + super(Opcodes.ASM4);
45.526 + }
45.527 +
45.528 + @Override
45.529 + public void visit(String name, Object value) {
45.530 + if (name == null) {
45.531 + args.add((String) value);
45.532 + return;
45.533 + }
45.534 + if (name.equals("javacall")) { // NOI18N
45.535 + javacall = (Boolean) value;
45.536 + return;
45.537 + }
45.538 + assert name.equals("body");
45.539 + body = (String) value;
45.540 + }
45.541 +
45.542 + @Override
45.543 + public AnnotationVisitor visitArray(String name) {
45.544 + return this;
45.545 + }
45.546 +
45.547 + @Override
45.548 + public void visitEnd() {
45.549 + if (body != null) {
45.550 + if (javacall) {
45.551 + body = callback(body);
45.552 + args.add("vm");
45.553 + }
45.554 + generateJSBody(args, body);
45.555 + }
45.556 + }
45.557 + }
45.558 + }
45.559 +
45.560 + private final class LoadResource extends AnnotationVisitor {
45.561 +
45.562 + public LoadResource() {
45.563 + super(Opcodes.ASM4);
45.564 + }
45.565 +
45.566 + @Override
45.567 + public void visit(String attrName, Object value) {
45.568 + String relPath = (String) value;
45.569 + if (relPath.startsWith("/")) {
45.570 + resource = relPath;
45.571 + } else {
45.572 + int last = name.lastIndexOf('/');
45.573 + String fullPath = name.substring(0, last + 1) + relPath;
45.574 + resource = fullPath;
45.575 + }
45.576 + }
45.577 + }
45.578 + }
45.579 +
45.580 + private static class ClassWriterEx extends ClassWriter {
45.581 +
45.582 + private ClassLoader loader;
45.583 +
45.584 + public ClassWriterEx(ClassLoader l, ClassReader classReader, int flags) {
45.585 + super(classReader, flags);
45.586 + this.loader = l;
45.587 + }
45.588 +
45.589 + @Override
45.590 + protected String getCommonSuperClass(final String type1, final String type2) {
45.591 + Class<?> c, d;
45.592 + try {
45.593 + c = Class.forName(type1.replace('/', '.'), false, loader);
45.594 + d = Class.forName(type2.replace('/', '.'), false, loader);
45.595 + } catch (Exception e) {
45.596 + throw new RuntimeException(e.toString());
45.597 + }
45.598 + if (c.isAssignableFrom(d)) {
45.599 + return type1;
45.600 + }
45.601 + if (d.isAssignableFrom(c)) {
45.602 + return type2;
45.603 + }
45.604 + if (c.isInterface() || d.isInterface()) {
45.605 + return "java/lang/Object";
45.606 + } else {
45.607 + do {
45.608 + c = c.getSuperclass();
45.609 + } while (!c.isAssignableFrom(d));
45.610 + return c.getName().replace('.', '/');
45.611 + }
45.612 + }
45.613 + }
45.614 +
45.615 + private static final class TrueFn extends Fn {
45.616 + @Override
45.617 + public Object invoke(Object thiz, Object... args) throws Exception {
45.618 + return Boolean.TRUE;
45.619 + }
45.620 + } // end of TrueFn
45.621 +}
46.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
46.2 +++ b/boot/src/main/java/org/netbeans/html/boot/impl/JavaScriptProcesor.java Tue Jan 07 08:21:57 2014 +0100
46.3 @@ -0,0 +1,369 @@
46.4 +/**
46.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
46.6 + *
46.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
46.8 + *
46.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
46.10 + * Other names may be trademarks of their respective owners.
46.11 + *
46.12 + * The contents of this file are subject to the terms of either the GNU
46.13 + * General Public License Version 2 only ("GPL") or the Common
46.14 + * Development and Distribution License("CDDL") (collectively, the
46.15 + * "License"). You may not use this file except in compliance with the
46.16 + * License. You can obtain a copy of the License at
46.17 + * http://www.netbeans.org/cddl-gplv2.html
46.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
46.19 + * specific language governing permissions and limitations under the
46.20 + * License. When distributing the software, include this License Header
46.21 + * Notice in each file and include the License file at
46.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
46.23 + * particular file as subject to the "Classpath" exception as provided
46.24 + * by Oracle in the GPL Version 2 section of the License file that
46.25 + * accompanied this code. If applicable, add the following below the
46.26 + * License Header, with the fields enclosed by brackets [] replaced by
46.27 + * your own identifying information:
46.28 + * "Portions Copyrighted [year] [name of copyright owner]"
46.29 + *
46.30 + * Contributor(s):
46.31 + *
46.32 + * The Original Software is NetBeans. The Initial Developer of the Original
46.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
46.34 + *
46.35 + * If you wish your version of this file to be governed by only the CDDL
46.36 + * or only the GPL Version 2, indicate your decision by adding
46.37 + * "[Contributor] elects to include this software in this distribution
46.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
46.39 + * single choice of license, a recipient has the option to distribute
46.40 + * your version of this file under either the CDDL, the GPL Version 2 or
46.41 + * to extend the choice of license to its licensees as provided above.
46.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
46.43 + * Version 2 license, then the option applies only if the new code is
46.44 + * made subject to such option by the copyright holder.
46.45 + */
46.46 +package org.netbeans.html.boot.impl;
46.47 +
46.48 +import java.io.IOException;
46.49 +import java.io.Writer;
46.50 +import java.util.Collections;
46.51 +import java.util.HashMap;
46.52 +import java.util.HashSet;
46.53 +import java.util.List;
46.54 +import java.util.Map;
46.55 +import java.util.Set;
46.56 +import java.util.TreeMap;
46.57 +import javax.annotation.processing.AbstractProcessor;
46.58 +import javax.annotation.processing.Completion;
46.59 +import javax.annotation.processing.Completions;
46.60 +import javax.annotation.processing.Messager;
46.61 +import javax.annotation.processing.Processor;
46.62 +import javax.annotation.processing.RoundEnvironment;
46.63 +import javax.lang.model.SourceVersion;
46.64 +import javax.lang.model.element.AnnotationMirror;
46.65 +import javax.lang.model.element.Element;
46.66 +import javax.lang.model.element.ElementKind;
46.67 +import javax.lang.model.element.ExecutableElement;
46.68 +import javax.lang.model.element.Modifier;
46.69 +import javax.lang.model.element.PackageElement;
46.70 +import javax.lang.model.element.TypeElement;
46.71 +import javax.lang.model.element.VariableElement;
46.72 +import javax.lang.model.type.ArrayType;
46.73 +import javax.lang.model.type.ExecutableType;
46.74 +import javax.lang.model.type.TypeKind;
46.75 +import javax.lang.model.type.TypeMirror;
46.76 +import javax.tools.Diagnostic;
46.77 +import javax.tools.FileObject;
46.78 +import javax.tools.StandardLocation;
46.79 +import net.java.html.js.JavaScriptBody;
46.80 +import net.java.html.js.JavaScriptResource;
46.81 +import org.openide.util.lookup.ServiceProvider;
46.82 +
46.83 +/**
46.84 + *
46.85 + * @author Jaroslav Tulach <jtulach@netbeans.org>
46.86 + */
46.87 +@ServiceProvider(service = Processor.class)
46.88 +public final class JavaScriptProcesor extends AbstractProcessor {
46.89 + private final Map<String,Map<String,ExecutableElement>> javacalls =
46.90 + new HashMap<String,Map<String,ExecutableElement>>();
46.91 +
46.92 + @Override
46.93 + public Set<String> getSupportedAnnotationTypes() {
46.94 + Set<String> set = new HashSet<String>();
46.95 + set.add(JavaScriptBody.class.getName());
46.96 + set.add(JavaScriptResource.class.getName());
46.97 + return set;
46.98 + }
46.99 +
46.100 + @Override
46.101 + public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
46.102 + final Messager msg = processingEnv.getMessager();
46.103 + for (Element e : roundEnv.getElementsAnnotatedWith(JavaScriptBody.class)) {
46.104 + if (e.getKind() != ElementKind.METHOD && e.getKind() != ElementKind.CONSTRUCTOR) {
46.105 + continue;
46.106 + }
46.107 + ExecutableElement ee = (ExecutableElement)e;
46.108 + List<? extends VariableElement> params = ee.getParameters();
46.109 +
46.110 + JavaScriptBody jsb = e.getAnnotation(JavaScriptBody.class);
46.111 + if (jsb == null) {
46.112 + continue;
46.113 + }
46.114 + String[] arr = jsb.args();
46.115 + if (params.size() != arr.length) {
46.116 + msg.printMessage(Diagnostic.Kind.ERROR, "Number of args arguments does not match real arguments!", e);
46.117 + }
46.118 + if (!jsb.javacall() && jsb.body().contains(".@")) {
46.119 + msg.printMessage(Diagnostic.Kind.WARNING, "Usage of .@ usually requires javacall=true", e);
46.120 + }
46.121 + if (jsb.javacall()) {
46.122 + JsCallback verify = new VerifyCallback(e);
46.123 + try {
46.124 + verify.parse(jsb.body());
46.125 + } catch (IllegalStateException ex) {
46.126 + msg.printMessage(Diagnostic.Kind.ERROR, ex.getLocalizedMessage(), e);
46.127 + }
46.128 + }
46.129 + }
46.130 + for (Element e : roundEnv.getElementsAnnotatedWith(JavaScriptResource.class)) {
46.131 + JavaScriptResource r = e.getAnnotation(JavaScriptResource.class);
46.132 + if (r == null) {
46.133 + continue;
46.134 + }
46.135 + final String res;
46.136 + if (r.value().startsWith("/")) {
46.137 + res = r.value();
46.138 + } else {
46.139 + res = findPkg(e).replace('.', '/') + "/" + r.value();
46.140 + }
46.141 +
46.142 + try {
46.143 + FileObject os = processingEnv.getFiler().getResource(StandardLocation.SOURCE_PATH, "", res);
46.144 + os.openInputStream().close();
46.145 + } catch (IOException ex1) {
46.146 + try {
46.147 + FileObject os2 = processingEnv.getFiler().getResource(StandardLocation.CLASS_OUTPUT, "", res);
46.148 + os2.openInputStream().close();
46.149 + } catch (IOException ex2) {
46.150 + msg.printMessage(Diagnostic.Kind.ERROR, "Cannot find " + res + " in " + res + " package", e);
46.151 + }
46.152 + }
46.153 + }
46.154 +
46.155 + if (roundEnv.processingOver()) {
46.156 + generateCallbackClass(javacalls);
46.157 + javacalls.clear();
46.158 + }
46.159 + return true;
46.160 + }
46.161 +
46.162 + @Override
46.163 + public Iterable<? extends Completion> getCompletions(Element e,
46.164 + AnnotationMirror annotation, ExecutableElement member, String userText
46.165 + ) {
46.166 + StringBuilder sb = new StringBuilder();
46.167 + if (e.getKind() == ElementKind.METHOD && member.getSimpleName().contentEquals("args")) {
46.168 + ExecutableElement ee = (ExecutableElement) e;
46.169 + String sep = "";
46.170 + sb.append("{ ");
46.171 + for (VariableElement ve : ee.getParameters()) {
46.172 + sb.append(sep).append('"').append(ve.getSimpleName())
46.173 + .append('"');
46.174 + sep = ", ";
46.175 + }
46.176 + sb.append(" }");
46.177 + return Collections.nCopies(1, Completions.of(sb.toString()));
46.178 + }
46.179 + return null;
46.180 + }
46.181 +
46.182 + private class VerifyCallback extends JsCallback {
46.183 + private final Element e;
46.184 + public VerifyCallback(Element e) {
46.185 + this.e = e;
46.186 + }
46.187 +
46.188 + @Override
46.189 + protected CharSequence callMethod(String ident, String fqn, String method, String params) {
46.190 + final TypeElement type = processingEnv.getElementUtils().getTypeElement(fqn);
46.191 + if (type == null) {
46.192 + processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
46.193 + "Callback to non-existing class " + fqn, e
46.194 + );
46.195 + return "";
46.196 + }
46.197 + ExecutableElement found = null;
46.198 + StringBuilder foundParams = new StringBuilder();
46.199 + for (Element m : type.getEnclosedElements()) {
46.200 + if (m.getKind() != ElementKind.METHOD) {
46.201 + continue;
46.202 + }
46.203 + if (m.getSimpleName().contentEquals(method)) {
46.204 + String paramTypes = findParamTypes((ExecutableElement)m);
46.205 + if (paramTypes.equals(params)) {
46.206 + found = (ExecutableElement) m;
46.207 + break;
46.208 + }
46.209 + foundParams.append(paramTypes).append("\n");
46.210 + }
46.211 + }
46.212 + if (found == null) {
46.213 + if (foundParams.length() == 0) {
46.214 + processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
46.215 + "Callback to class " + fqn + " with unknown method " + method, e
46.216 + );
46.217 + } else {
46.218 + processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
46.219 + "Callback to " + fqn + "." + method + " with wrong parameters: " +
46.220 + params + ". Only known parameters are " + foundParams, e
46.221 + );
46.222 + }
46.223 + } else {
46.224 + Map<String,ExecutableElement> mangledOnes = javacalls.get(findPkg(e));
46.225 + if (mangledOnes == null) {
46.226 + mangledOnes = new TreeMap<String, ExecutableElement>();
46.227 + javacalls.put(findPkg(e), mangledOnes);
46.228 + }
46.229 + String mangled = JsCallback.mangle(fqn, method, findParamTypes(found));
46.230 + mangledOnes.put(mangled, found);
46.231 + }
46.232 + return "";
46.233 + }
46.234 +
46.235 + private String findParamTypes(ExecutableElement method) {
46.236 + ExecutableType t = (ExecutableType) method.asType();
46.237 + StringBuilder sb = new StringBuilder();
46.238 + sb.append('(');
46.239 + for (TypeMirror tm : t.getParameterTypes()) {
46.240 + if (tm.getKind().isPrimitive()) {
46.241 + switch (tm.getKind()) {
46.242 + case INT: sb.append('I'); break;
46.243 + case BOOLEAN: sb.append('Z'); break;
46.244 + case BYTE: sb.append('B'); break;
46.245 + case CHAR: sb.append('C'); break;
46.246 + case SHORT: sb.append('S'); break;
46.247 + case DOUBLE: sb.append('D'); break;
46.248 + case FLOAT: sb.append('F'); break;
46.249 + case LONG: sb.append('J'); break;
46.250 + default:
46.251 + throw new IllegalStateException("Uknown " + tm.getKind());
46.252 + }
46.253 + } else {
46.254 + while (tm.getKind() == TypeKind.ARRAY) {
46.255 + sb.append('[');
46.256 + tm = ((ArrayType)tm).getComponentType();
46.257 + }
46.258 + sb.append('L');
46.259 + sb.append(tm.toString().replace('.', '/'));
46.260 + sb.append(';');
46.261 + }
46.262 + }
46.263 + sb.append(')');
46.264 + return sb.toString();
46.265 + }
46.266 + }
46.267 +
46.268 + private void generateCallbackClass(Map<String,Map<String, ExecutableElement>> process) {
46.269 + for (Map.Entry<String, Map<String, ExecutableElement>> pkgEn : process.entrySet()) {
46.270 + String pkgName = pkgEn.getKey();
46.271 + Map<String, ExecutableElement> map = pkgEn.getValue();
46.272 + StringBuilder source = new StringBuilder();
46.273 + source.append("package ").append(pkgName).append(";\n");
46.274 + source.append("public final class $JsCallbacks$ {\n");
46.275 + source.append(" static final $JsCallbacks$ VM = new $JsCallbacks$(null);\n");
46.276 + source.append(" private final org.apidesign.html.boot.spi.Fn.Presenter p;\n");
46.277 + source.append(" private $JsCallbacks$ last;\n");
46.278 + source.append(" private $JsCallbacks$(org.apidesign.html.boot.spi.Fn.Presenter p) {\n");
46.279 + source.append(" this.p = p;\n");
46.280 + source.append(" }\n");
46.281 + source.append(" final $JsCallbacks$ current() {\n");
46.282 + source.append(" org.apidesign.html.boot.spi.Fn.Presenter now = org.apidesign.html.boot.spi.Fn.activePresenter();\n");
46.283 + source.append(" if (now == p) return this;\n");
46.284 + source.append(" if (last != null && now == last.p) return last;\n");
46.285 + source.append(" return last = new $JsCallbacks$(now);\n");
46.286 + source.append(" }\n");
46.287 + for (Map.Entry<String, ExecutableElement> entry : map.entrySet()) {
46.288 + final String mangled = entry.getKey();
46.289 + final ExecutableElement m = entry.getValue();
46.290 + final boolean isStatic = m.getModifiers().contains(Modifier.STATIC);
46.291 +
46.292 + source.append("\n public java.lang.Object ")
46.293 + .append(mangled)
46.294 + .append("(");
46.295 +
46.296 + String sep = "";
46.297 + if (!isStatic) {
46.298 + source.append(((TypeElement)m.getEnclosingElement()).getQualifiedName());
46.299 + source.append(" self");
46.300 + sep = ", ";
46.301 + }
46.302 +
46.303 + int cnt = 0;
46.304 + for (VariableElement ve : m.getParameters()) {
46.305 + source.append(sep);
46.306 + source.append(ve.asType());
46.307 + source.append(" arg").append(++cnt);
46.308 + sep = ", ";
46.309 + }
46.310 + source.append(") throws Throwable {\n");
46.311 + if (processingEnv.getSourceVersion().compareTo(SourceVersion.RELEASE_7) >= 0) {
46.312 + source.append(" try (java.io.Closeable a = org.apidesign.html.boot.spi.Fn.activate(p)) { \n");
46.313 + } else {
46.314 + source.append(" java.io.Closeable a = org.apidesign.html.boot.spi.Fn.activate(p); try {\n");
46.315 + }
46.316 + source.append(" ");
46.317 + if (m.getReturnType().getKind() != TypeKind.VOID) {
46.318 + source.append("return ");
46.319 + }
46.320 + if (isStatic) {
46.321 + source.append(((TypeElement)m.getEnclosingElement()).getQualifiedName());
46.322 + source.append('.');
46.323 + } else {
46.324 + source.append("self.");
46.325 + }
46.326 + source.append(m.getSimpleName());
46.327 + source.append("(");
46.328 + cnt = 0;
46.329 + sep = "";
46.330 + for (VariableElement ve : m.getParameters()) {
46.331 + source.append(sep);
46.332 + source.append("arg").append(++cnt);
46.333 + sep = ", ";
46.334 + }
46.335 + source.append(");\n");
46.336 + if (m.getReturnType().getKind() == TypeKind.VOID) {
46.337 + source.append(" return null;\n");
46.338 + }
46.339 + if (processingEnv.getSourceVersion().compareTo(SourceVersion.RELEASE_7) >= 0) {
46.340 + source.append(" }\n");
46.341 + } else {
46.342 +
46.343 + source.append(" } finally {\n");
46.344 + source.append(" a.close();\n");
46.345 + source.append(" }\n");
46.346 + }
46.347 + source.append(" }\n");
46.348 + }
46.349 + source.append("}\n");
46.350 + final String srcName = pkgName + ".$JsCallbacks$";
46.351 + try {
46.352 + Writer w = processingEnv.getFiler().createSourceFile(srcName,
46.353 + map.values().toArray(new Element[map.size()])
46.354 + ).openWriter();
46.355 + w.write(source.toString());
46.356 + w.close();
46.357 + } catch (IOException ex) {
46.358 + processingEnv.getMessager().printMessage(
46.359 + Diagnostic.Kind.ERROR, "Can't write " + srcName + ": " + ex.getMessage()
46.360 + );
46.361 + }
46.362 + }
46.363 + }
46.364 +
46.365 + private static String findPkg(Element e) {
46.366 + while (e.getKind() != ElementKind.PACKAGE) {
46.367 + e = e.getEnclosingElement();
46.368 + }
46.369 + return ((PackageElement)e).getQualifiedName().toString();
46.370 + }
46.371 +
46.372 +}
47.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
47.2 +++ b/boot/src/main/java/org/netbeans/html/boot/impl/JsAgent.java Tue Jan 07 08:21:57 2014 +0100
47.3 @@ -0,0 +1,67 @@
47.4 +/**
47.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
47.6 + *
47.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
47.8 + *
47.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
47.10 + * Other names may be trademarks of their respective owners.
47.11 + *
47.12 + * The contents of this file are subject to the terms of either the GNU
47.13 + * General Public License Version 2 only ("GPL") or the Common
47.14 + * Development and Distribution License("CDDL") (collectively, the
47.15 + * "License"). You may not use this file except in compliance with the
47.16 + * License. You can obtain a copy of the License at
47.17 + * http://www.netbeans.org/cddl-gplv2.html
47.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
47.19 + * specific language governing permissions and limitations under the
47.20 + * License. When distributing the software, include this License Header
47.21 + * Notice in each file and include the License file at
47.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
47.23 + * particular file as subject to the "Classpath" exception as provided
47.24 + * by Oracle in the GPL Version 2 section of the License file that
47.25 + * accompanied this code. If applicable, add the following below the
47.26 + * License Header, with the fields enclosed by brackets [] replaced by
47.27 + * your own identifying information:
47.28 + * "Portions Copyrighted [year] [name of copyright owner]"
47.29 + *
47.30 + * Contributor(s):
47.31 + *
47.32 + * The Original Software is NetBeans. The Initial Developer of the Original
47.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
47.34 + *
47.35 + * If you wish your version of this file to be governed by only the CDDL
47.36 + * or only the GPL Version 2, indicate your decision by adding
47.37 + * "[Contributor] elects to include this software in this distribution
47.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
47.39 + * single choice of license, a recipient has the option to distribute
47.40 + * your version of this file under either the CDDL, the GPL Version 2 or
47.41 + * to extend the choice of license to its licensees as provided above.
47.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
47.43 + * Version 2 license, then the option applies only if the new code is
47.44 + * made subject to such option by the copyright holder.
47.45 + */
47.46 +package org.netbeans.html.boot.impl;
47.47 +
47.48 +import java.lang.instrument.ClassFileTransformer;
47.49 +import java.lang.instrument.IllegalClassFormatException;
47.50 +import java.lang.instrument.Instrumentation;
47.51 +import java.security.ProtectionDomain;
47.52 +
47.53 +/**
47.54 + *
47.55 + * @author Jaroslav Tulach <jtulach@netbeans.org>
47.56 + */
47.57 +public final class JsAgent implements ClassFileTransformer {
47.58 + public static void agentmain(String args, Instrumentation instr) {
47.59 + instr.addTransformer(new JsAgent());
47.60 + }
47.61 +
47.62 + @Override
47.63 + public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
47.64 + try {
47.65 + return FnUtils.transform(classfileBuffer, loader);
47.66 + } catch (Exception ex) {
47.67 + return classfileBuffer;
47.68 + }
47.69 + }
47.70 +}
48.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
48.2 +++ b/boot/src/main/java/org/netbeans/html/boot/impl/JsCallback.java Tue Jan 07 08:21:57 2014 +0100
48.3 @@ -0,0 +1,160 @@
48.4 +/**
48.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
48.6 + *
48.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
48.8 + *
48.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
48.10 + * Other names may be trademarks of their respective owners.
48.11 + *
48.12 + * The contents of this file are subject to the terms of either the GNU
48.13 + * General Public License Version 2 only ("GPL") or the Common
48.14 + * Development and Distribution License("CDDL") (collectively, the
48.15 + * "License"). You may not use this file except in compliance with the
48.16 + * License. You can obtain a copy of the License at
48.17 + * http://www.netbeans.org/cddl-gplv2.html
48.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
48.19 + * specific language governing permissions and limitations under the
48.20 + * License. When distributing the software, include this License Header
48.21 + * Notice in each file and include the License file at
48.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
48.23 + * particular file as subject to the "Classpath" exception as provided
48.24 + * by Oracle in the GPL Version 2 section of the License file that
48.25 + * accompanied this code. If applicable, add the following below the
48.26 + * License Header, with the fields enclosed by brackets [] replaced by
48.27 + * your own identifying information:
48.28 + * "Portions Copyrighted [year] [name of copyright owner]"
48.29 + *
48.30 + * Contributor(s):
48.31 + *
48.32 + * The Original Software is NetBeans. The Initial Developer of the Original
48.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
48.34 + *
48.35 + * If you wish your version of this file to be governed by only the CDDL
48.36 + * or only the GPL Version 2, indicate your decision by adding
48.37 + * "[Contributor] elects to include this software in this distribution
48.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
48.39 + * single choice of license, a recipient has the option to distribute
48.40 + * your version of this file under either the CDDL, the GPL Version 2 or
48.41 + * to extend the choice of license to its licensees as provided above.
48.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
48.43 + * Version 2 license, then the option applies only if the new code is
48.44 + * made subject to such option by the copyright holder.
48.45 + */
48.46 +package org.netbeans.html.boot.impl;
48.47 +
48.48 +
48.49 +/**
48.50 + *
48.51 + * @author Jaroslav Tulach <jtulach@netbeans.org>
48.52 + */
48.53 +abstract class JsCallback {
48.54 + final String parse(String body) {
48.55 + StringBuilder sb = new StringBuilder();
48.56 + int pos = 0;
48.57 + for (;;) {
48.58 + int next = body.indexOf(".@", pos);
48.59 + if (next == -1) {
48.60 + sb.append(body.substring(pos));
48.61 + body = sb.toString();
48.62 + break;
48.63 + }
48.64 + int ident = next;
48.65 + while (ident > 0) {
48.66 + if (!Character.isJavaIdentifierPart(body.charAt(--ident))) {
48.67 + ident++;
48.68 + break;
48.69 + }
48.70 + }
48.71 + String refId = body.substring(ident, next);
48.72 +
48.73 + sb.append(body.substring(pos, ident));
48.74 +
48.75 + int sigBeg = body.indexOf('(', next);
48.76 + int sigEnd = body.indexOf(')', sigBeg);
48.77 + int colon4 = body.indexOf("::", next);
48.78 + if (sigBeg == -1 || sigEnd == -1 || colon4 == -1) {
48.79 + throw new IllegalStateException(
48.80 + "Wrong format of instance callback. "
48.81 + + "Should be: 'inst.@pkg.Class::method(Ljava/lang/Object;)(param)':\n"
48.82 + + body
48.83 + );
48.84 + }
48.85 + String fqn = body.substring(next + 2, colon4);
48.86 + String method = body.substring(colon4 + 2, sigBeg);
48.87 + String params = body.substring(sigBeg, sigEnd + 1);
48.88 +
48.89 + int paramBeg = body.indexOf('(', sigEnd + 1);
48.90 + if (paramBeg == -1) {
48.91 + throw new IllegalStateException(
48.92 + "Wrong format of instance callback. "
48.93 + + "Should be: 'inst.@pkg.Class::method(Ljava/lang/Object;)(param)':\n"
48.94 + + body
48.95 + );
48.96 + }
48.97 +
48.98 + sb.append(callMethod(refId, fqn, method, params));
48.99 + if (body.charAt(paramBeg + 1) != (')')) {
48.100 + sb.append(",");
48.101 + }
48.102 + pos = paramBeg + 1;
48.103 + }
48.104 + pos = 0;
48.105 + sb = null;
48.106 + for (;;) {
48.107 + int next = body.indexOf("@", pos);
48.108 + if (next == -1) {
48.109 + if (sb == null) {
48.110 + return body;
48.111 + }
48.112 + sb.append(body.substring(pos));
48.113 + return sb.toString();
48.114 + }
48.115 + if (sb == null) {
48.116 + sb = new StringBuilder();
48.117 + }
48.118 +
48.119 + sb.append(body.substring(pos, next));
48.120 +
48.121 + int sigBeg = body.indexOf('(', next);
48.122 + int sigEnd = body.indexOf(')', sigBeg);
48.123 + int colon4 = body.indexOf("::", next);
48.124 + if (sigBeg == -1 || sigEnd == -1 || colon4 == -1) {
48.125 + throw new IllegalStateException(
48.126 + "Wrong format of static callback. "
48.127 + + "Should be: '@pkg.Class::staticMethod(Ljava/lang/Object;)(param)':\n"
48.128 + + body
48.129 + );
48.130 + }
48.131 + String fqn = body.substring(next + 1, colon4);
48.132 + String method = body.substring(colon4 + 2, sigBeg);
48.133 + String params = body.substring(sigBeg, sigEnd + 1);
48.134 +
48.135 + int paramBeg = body.indexOf('(', sigEnd + 1);
48.136 +
48.137 + sb.append(callMethod(null, fqn, method, params));
48.138 + pos = paramBeg + 1;
48.139 + }
48.140 + }
48.141 +
48.142 + protected abstract CharSequence callMethod(
48.143 + String ident, String fqn, String method, String params
48.144 + );
48.145 +
48.146 + static String mangle(String fqn, String method, String params) {
48.147 + if (params.startsWith("(")) {
48.148 + params = params.substring(1);
48.149 + }
48.150 + if (params.endsWith(")")) {
48.151 + params = params.substring(0, params.length() - 1);
48.152 + }
48.153 + return
48.154 + replace(fqn) + "$" + replace(method) + "$" + replace(params);
48.155 + }
48.156 +
48.157 + private static String replace(String orig) {
48.158 + return orig.replace("_", "_1").
48.159 + replace(";", "_2").
48.160 + replace("[", "_3").
48.161 + replace('.', '_').replace('/', '_');
48.162 + }
48.163 +}
49.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
49.2 +++ b/boot/src/main/java/org/netbeans/html/boot/impl/JsClassLoader.java Tue Jan 07 08:21:57 2014 +0100
49.3 @@ -0,0 +1,133 @@
49.4 +/**
49.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
49.6 + *
49.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
49.8 + *
49.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
49.10 + * Other names may be trademarks of their respective owners.
49.11 + *
49.12 + * The contents of this file are subject to the terms of either the GNU
49.13 + * General Public License Version 2 only ("GPL") or the Common
49.14 + * Development and Distribution License("CDDL") (collectively, the
49.15 + * "License"). You may not use this file except in compliance with the
49.16 + * License. You can obtain a copy of the License at
49.17 + * http://www.netbeans.org/cddl-gplv2.html
49.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
49.19 + * specific language governing permissions and limitations under the
49.20 + * License. When distributing the software, include this License Header
49.21 + * Notice in each file and include the License file at
49.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
49.23 + * particular file as subject to the "Classpath" exception as provided
49.24 + * by Oracle in the GPL Version 2 section of the License file that
49.25 + * accompanied this code. If applicable, add the following below the
49.26 + * License Header, with the fields enclosed by brackets [] replaced by
49.27 + * your own identifying information:
49.28 + * "Portions Copyrighted [year] [name of copyright owner]"
49.29 + *
49.30 + * Contributor(s):
49.31 + *
49.32 + * The Original Software is NetBeans. The Initial Developer of the Original
49.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
49.34 + *
49.35 + * If you wish your version of this file to be governed by only the CDDL
49.36 + * or only the GPL Version 2, indicate your decision by adding
49.37 + * "[Contributor] elects to include this software in this distribution
49.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
49.39 + * single choice of license, a recipient has the option to distribute
49.40 + * your version of this file under either the CDDL, the GPL Version 2 or
49.41 + * to extend the choice of license to its licensees as provided above.
49.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
49.43 + * Version 2 license, then the option applies only if the new code is
49.44 + * made subject to such option by the copyright holder.
49.45 + */
49.46 +package org.netbeans.html.boot.impl;
49.47 +
49.48 +import org.apidesign.html.boot.spi.Fn;
49.49 +import java.io.IOException;
49.50 +import java.io.InputStream;
49.51 +import java.io.Reader;
49.52 +import java.net.URL;
49.53 +import java.util.Enumeration;
49.54 +
49.55 +/**
49.56 + *
49.57 + * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
49.58 + */
49.59 +abstract class JsClassLoader extends ClassLoader {
49.60 + JsClassLoader(ClassLoader parent) {
49.61 + super(parent);
49.62 + setDefaultAssertionStatus(JsClassLoader.class.desiredAssertionStatus());
49.63 + }
49.64 +
49.65 + @Override
49.66 + protected abstract URL findResource(String name);
49.67 +
49.68 + @Override
49.69 + protected abstract Enumeration<URL> findResources(String name);
49.70 +
49.71 + @Override
49.72 + protected Class<?> findClass(String name) throws ClassNotFoundException {
49.73 + if (name.startsWith("javafx")) {
49.74 + return Class.forName(name);
49.75 + }
49.76 + if (name.startsWith("netscape")) {
49.77 + return Class.forName(name);
49.78 + }
49.79 + if (name.startsWith("com.sun")) {
49.80 + return Class.forName(name);
49.81 + }
49.82 + if (name.equals(JsClassLoader.class.getName())) {
49.83 + return JsClassLoader.class;
49.84 + }
49.85 + if (name.equals(Fn.class.getName())) {
49.86 + return Fn.class;
49.87 + }
49.88 + if (name.equals(Fn.Presenter.class.getName())) {
49.89 + return Fn.Presenter.class;
49.90 + }
49.91 + if (name.equals(FnUtils.class.getName())) {
49.92 + return FnUtils.class;
49.93 + }
49.94 + if (
49.95 + name.equals("org.apidesign.html.boot.spi.Fn") ||
49.96 + name.equals("org.netbeans.html.boot.impl.FnUtils") ||
49.97 + name.equals("org.netbeans.html.boot.impl.FnContext")
49.98 + ) {
49.99 + return Class.forName(name);
49.100 + }
49.101 + URL u = findResource(name.replace('.', '/') + ".class");
49.102 + if (u != null) {
49.103 + InputStream is = null;
49.104 + try {
49.105 + is = u.openStream();
49.106 + byte[] arr = new byte[is.available()];
49.107 + int len = 0;
49.108 + while (len < arr.length) {
49.109 + int read = is.read(arr, len, arr.length - len);
49.110 + if (read == -1) {
49.111 + throw new IOException("Can't read " + u);
49.112 + }
49.113 + len += read;
49.114 + }
49.115 + is.close();
49.116 + is = null;
49.117 + arr = FnUtils.transform(arr, JsClassLoader.this);
49.118 + if (arr != null) {
49.119 + return defineClass(name, arr, 0, arr.length);
49.120 + }
49.121 + } catch (IOException ex) {
49.122 + throw new ClassNotFoundException("Can't load " + name, ex);
49.123 + } finally {
49.124 + try {
49.125 + if (is != null) is.close();
49.126 + } catch (IOException ex) {
49.127 + throw new ClassNotFoundException(null, ex);
49.128 + }
49.129 + }
49.130 + }
49.131 + return super.findClass(name);
49.132 + }
49.133 +
49.134 + protected abstract Fn defineFn(String code, String... names);
49.135 + protected abstract void loadScript(Reader code) throws Exception;
49.136 +}
50.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
50.2 +++ b/boot/src/main/java/org/netbeans/html/boot/impl/Test.java Tue Jan 07 08:21:57 2014 +0100
50.3 @@ -0,0 +1,57 @@
50.4 +/**
50.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
50.6 + *
50.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
50.8 + *
50.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
50.10 + * Other names may be trademarks of their respective owners.
50.11 + *
50.12 + * The contents of this file are subject to the terms of either the GNU
50.13 + * General Public License Version 2 only ("GPL") or the Common
50.14 + * Development and Distribution License("CDDL") (collectively, the
50.15 + * "License"). You may not use this file except in compliance with the
50.16 + * License. You can obtain a copy of the License at
50.17 + * http://www.netbeans.org/cddl-gplv2.html
50.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
50.19 + * specific language governing permissions and limitations under the
50.20 + * License. When distributing the software, include this License Header
50.21 + * Notice in each file and include the License file at
50.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
50.23 + * particular file as subject to the "Classpath" exception as provided
50.24 + * by Oracle in the GPL Version 2 section of the License file that
50.25 + * accompanied this code. If applicable, add the following below the
50.26 + * License Header, with the fields enclosed by brackets [] replaced by
50.27 + * your own identifying information:
50.28 + * "Portions Copyrighted [year] [name of copyright owner]"
50.29 + *
50.30 + * Contributor(s):
50.31 + *
50.32 + * The Original Software is NetBeans. The Initial Developer of the Original
50.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
50.34 + *
50.35 + * If you wish your version of this file to be governed by only the CDDL
50.36 + * or only the GPL Version 2, indicate your decision by adding
50.37 + * "[Contributor] elects to include this software in this distribution
50.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
50.39 + * single choice of license, a recipient has the option to distribute
50.40 + * your version of this file under either the CDDL, the GPL Version 2 or
50.41 + * to extend the choice of license to its licensees as provided above.
50.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
50.43 + * Version 2 license, then the option applies only if the new code is
50.44 + * made subject to such option by the copyright holder.
50.45 + */
50.46 +package org.netbeans.html.boot.impl;
50.47 +
50.48 +import java.util.concurrent.Callable;
50.49 +import net.java.html.js.JavaScriptBody;
50.50 +
50.51 +/**
50.52 + *
50.53 + * @author Jaroslav Tulach <jtulach@netbeans.org>
50.54 + */
50.55 +public final class Test implements Callable<Boolean> {
50.56 + @Override @JavaScriptBody(args = {}, body = "return true;")
50.57 + public Boolean call() {
50.58 + return false;
50.59 + }
50.60 +}
51.1 --- a/boot/src/test/java/org/apidesign/html/boot/impl/Arithm.java Thu Dec 19 17:11:01 2013 +0100
51.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
51.3 @@ -1,31 +0,0 @@
51.4 -/**
51.5 - * HTML via Java(tm) Language Bindings
51.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
51.7 - *
51.8 - * This program is free software: you can redistribute it and/or modify
51.9 - * it under the terms of the GNU General Public License as published by
51.10 - * the Free Software Foundation, version 2 of the License.
51.11 - *
51.12 - * This program is distributed in the hope that it will be useful,
51.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
51.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
51.15 - * GNU General Public License for more details. apidesign.org
51.16 - * designates this particular file as subject to the
51.17 - * "Classpath" exception as provided by apidesign.org
51.18 - * in the License file that accompanied this code.
51.19 - *
51.20 - * You should have received a copy of the GNU General Public License
51.21 - * along with this program. Look for COPYING file in the top folder.
51.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
51.23 - */
51.24 -package org.apidesign.html.boot.impl;
51.25 -
51.26 -/**
51.27 - *
51.28 - * @author Jaroslav Tulach <jtulach@netbeans.org>
51.29 - */
51.30 -public class Arithm {
51.31 - public int sumTwo(int a, int b) {
51.32 - return a + b;
51.33 - }
51.34 -}
52.1 --- a/boot/src/test/java/org/apidesign/html/boot/impl/Compile.java Thu Dec 19 17:11:01 2013 +0100
52.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
52.3 @@ -1,269 +0,0 @@
52.4 -/**
52.5 - * HTML via Java(tm) Language Bindings
52.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
52.7 - *
52.8 - * This program is free software: you can redistribute it and/or modify
52.9 - * it under the terms of the GNU General Public License as published by
52.10 - * the Free Software Foundation, version 2 of the License.
52.11 - *
52.12 - * This program is distributed in the hope that it will be useful,
52.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
52.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
52.15 - * GNU General Public License for more details. apidesign.org
52.16 - * designates this particular file as subject to the
52.17 - * "Classpath" exception as provided by apidesign.org
52.18 - * in the License file that accompanied this code.
52.19 - *
52.20 - * You should have received a copy of the GNU General Public License
52.21 - * along with this program. Look for COPYING file in the top folder.
52.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
52.23 - */
52.24 -package org.apidesign.html.boot.impl;
52.25 -
52.26 -import java.io.ByteArrayInputStream;
52.27 -import java.io.ByteArrayOutputStream;
52.28 -import java.io.IOException;
52.29 -import java.io.InputStream;
52.30 -import java.io.OutputStream;
52.31 -import java.net.URI;
52.32 -import java.net.URISyntaxException;
52.33 -import java.util.ArrayList;
52.34 -import java.util.Arrays;
52.35 -import java.util.HashMap;
52.36 -import java.util.List;
52.37 -import java.util.Locale;
52.38 -import java.util.Map;
52.39 -import java.util.regex.Matcher;
52.40 -import java.util.regex.Pattern;
52.41 -import javax.tools.Diagnostic;
52.42 -import javax.tools.DiagnosticListener;
52.43 -import javax.tools.FileObject;
52.44 -import javax.tools.ForwardingJavaFileManager;
52.45 -import javax.tools.JavaFileManager;
52.46 -import javax.tools.JavaFileObject;
52.47 -import javax.tools.JavaFileObject.Kind;
52.48 -import javax.tools.SimpleJavaFileObject;
52.49 -import javax.tools.StandardJavaFileManager;
52.50 -import javax.tools.StandardLocation;
52.51 -import javax.tools.ToolProvider;
52.52 -import static org.testng.Assert.assertTrue;
52.53 -import static org.testng.Assert.assertFalse;
52.54 -import static org.testng.Assert.fail;
52.55 -
52.56 -/**
52.57 - *
52.58 - * @author Jaroslav Tulach <jtulach@netbeans.org>
52.59 - */
52.60 -final class Compile implements DiagnosticListener<JavaFileObject> {
52.61 - private final List<Diagnostic<? extends JavaFileObject>> errors =
52.62 - new ArrayList<Diagnostic<? extends JavaFileObject>>();
52.63 - private final Map<String, byte[]> classes;
52.64 - private final String pkg;
52.65 - private final String cls;
52.66 - private final String html;
52.67 - private final String sourceLevel;
52.68 -
52.69 - private Compile(String html, String code, String sl) throws IOException {
52.70 - this.pkg = findPkg(code);
52.71 - this.cls = findCls(code);
52.72 - this.html = html;
52.73 - this.sourceLevel = sl;
52.74 - classes = compile(html, code);
52.75 - }
52.76 -
52.77 - /** Performs compilation of given HTML page and associated Java code
52.78 - */
52.79 - public static Compile create(String html, String code) throws IOException {
52.80 - return create(html, code, "1.7");
52.81 - }
52.82 - static Compile create(String html, String code, String sourceLevel) throws IOException {
52.83 - return new Compile(html, code, sourceLevel);
52.84 - }
52.85 -
52.86 - /** Checks for given class among compiled resources */
52.87 - public byte[] get(String res) {
52.88 - return classes.get(res);
52.89 - }
52.90 -
52.91 - /** Obtains errors created during compilation.
52.92 - */
52.93 - public List<Diagnostic<? extends JavaFileObject>> getErrors() {
52.94 - List<Diagnostic<? extends JavaFileObject>> err;
52.95 - err = new ArrayList<Diagnostic<? extends JavaFileObject>>();
52.96 - for (Diagnostic<? extends JavaFileObject> diagnostic : errors) {
52.97 - if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
52.98 - err.add(diagnostic);
52.99 - }
52.100 - }
52.101 - return err;
52.102 - }
52.103 -
52.104 - private Map<String, byte[]> compile(final String html, final String code) throws IOException {
52.105 - StandardJavaFileManager sjfm = ToolProvider.getSystemJavaCompiler().getStandardFileManager(this, null, null);
52.106 -
52.107 - final Map<String, ByteArrayOutputStream> class2BAOS;
52.108 - class2BAOS = new HashMap<String, ByteArrayOutputStream>();
52.109 -
52.110 - JavaFileObject file = new SimpleJavaFileObject(URI.create("mem://mem"), Kind.SOURCE) {
52.111 - @Override
52.112 - public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
52.113 - return code;
52.114 - }
52.115 - };
52.116 - final JavaFileObject htmlFile = new SimpleJavaFileObject(URI.create("mem://mem2"), Kind.OTHER) {
52.117 - @Override
52.118 - public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
52.119 - return html;
52.120 - }
52.121 -
52.122 - @Override
52.123 - public InputStream openInputStream() throws IOException {
52.124 - return new ByteArrayInputStream(html.getBytes());
52.125 - }
52.126 - };
52.127 -
52.128 - final URI scratch;
52.129 - try {
52.130 - scratch = new URI("mem://mem3");
52.131 - } catch (URISyntaxException ex) {
52.132 - throw new IOException(ex);
52.133 - }
52.134 -
52.135 - JavaFileManager jfm = new ForwardingJavaFileManager<JavaFileManager>(sjfm) {
52.136 - @Override
52.137 - public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) throws IOException {
52.138 - if (kind == Kind.CLASS) {
52.139 - final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
52.140 -
52.141 - class2BAOS.put(className.replace('.', '/') + ".class", buffer);
52.142 - return new SimpleJavaFileObject(sibling.toUri(), kind) {
52.143 - @Override
52.144 - public OutputStream openOutputStream() throws IOException {
52.145 - return buffer;
52.146 - }
52.147 - };
52.148 - }
52.149 -
52.150 - if (kind == Kind.SOURCE) {
52.151 - final String n = className.replace('.', '/') + ".java";
52.152 - final URI un;
52.153 - try {
52.154 - un = new URI("mem://" + n);
52.155 - } catch (URISyntaxException ex) {
52.156 - throw new IOException(ex);
52.157 - }
52.158 - return new VirtFO(un/*sibling.toUri()*/, kind, n);
52.159 - }
52.160 -
52.161 - throw new IllegalStateException();
52.162 - }
52.163 -
52.164 - @Override
52.165 - public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException {
52.166 - if (location == StandardLocation.SOURCE_PATH) {
52.167 - if (packageName.equals(pkg)) {
52.168 - return htmlFile;
52.169 - }
52.170 - }
52.171 -
52.172 - return null;
52.173 - }
52.174 -
52.175 - @Override
52.176 - public boolean isSameFile(FileObject a, FileObject b) {
52.177 - if (a instanceof VirtFO && b instanceof VirtFO) {
52.178 - return ((VirtFO)a).getName().equals(((VirtFO)b).getName());
52.179 - }
52.180 -
52.181 - return super.isSameFile(a, b);
52.182 - }
52.183 -
52.184 - class VirtFO extends SimpleJavaFileObject {
52.185 -
52.186 - private final String n;
52.187 -
52.188 - public VirtFO(URI uri, Kind kind, String n) {
52.189 - super(uri, kind);
52.190 - this.n = n;
52.191 - }
52.192 - private final ByteArrayOutputStream data = new ByteArrayOutputStream();
52.193 -
52.194 - @Override
52.195 - public OutputStream openOutputStream() throws IOException {
52.196 - return data;
52.197 - }
52.198 -
52.199 - @Override
52.200 - public String getName() {
52.201 - return n;
52.202 - }
52.203 -
52.204 - @Override
52.205 - public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
52.206 - data.close();
52.207 - return new String(data.toByteArray());
52.208 - }
52.209 - }
52.210 - };
52.211 -
52.212 - ToolProvider.getSystemJavaCompiler().getTask(null, jfm, this, /*XXX:*/Arrays.asList("-source", sourceLevel, "-target", "1.7"), null, Arrays.asList(file)).call();
52.213 -
52.214 - Map<String, byte[]> result = new HashMap<String, byte[]>();
52.215 -
52.216 - for (Map.Entry<String, ByteArrayOutputStream> e : class2BAOS.entrySet()) {
52.217 - result.put(e.getKey(), e.getValue().toByteArray());
52.218 - }
52.219 -
52.220 - return result;
52.221 - }
52.222 -
52.223 -
52.224 - @Override
52.225 - public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
52.226 - errors.add(diagnostic);
52.227 - }
52.228 - private static String findPkg(String java) throws IOException {
52.229 - Pattern p = Pattern.compile("package\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}*;", Pattern.MULTILINE);
52.230 - Matcher m = p.matcher(java);
52.231 - if (!m.find()) {
52.232 - throw new IOException("Can't find package declaration in the java file");
52.233 - }
52.234 - String pkg = m.group(1);
52.235 - return pkg;
52.236 - }
52.237 - private static String findCls(String java) throws IOException {
52.238 - Pattern p = Pattern.compile("class\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}", Pattern.MULTILINE);
52.239 - Matcher m = p.matcher(java);
52.240 - if (!m.find()) {
52.241 - throw new IOException("Can't find package declaration in the java file");
52.242 - }
52.243 - String cls = m.group(1);
52.244 - return cls;
52.245 - }
52.246 -
52.247 - String getHtml() {
52.248 - String fqn = "'" + pkg + '.' + cls + "'";
52.249 - return html.replace("'${fqn}'", fqn);
52.250 - }
52.251 - void assertErrors() {
52.252 - assertFalse(getErrors().isEmpty(), "There are supposed to be some errors");
52.253 - }
52.254 -
52.255 - void assertError(String expMsg) {
52.256 - StringBuilder sb = new StringBuilder();
52.257 - sb.append("Can't find ").append(expMsg).append(" among:");
52.258 - for (Diagnostic<? extends JavaFileObject> e : errors) {
52.259 - String msg = e.getMessage(Locale.US);
52.260 - if (msg.contains(expMsg)) {
52.261 - return;
52.262 - }
52.263 - sb.append("\n");
52.264 - sb.append(msg);
52.265 - }
52.266 - fail(sb.toString());
52.267 - }
52.268 -
52.269 - void assertNoErrors() {
52.270 - assertTrue(getErrors().isEmpty(), "No errors expected: " + getErrors());
52.271 - }
52.272 -}
53.1 --- a/boot/src/test/java/org/apidesign/html/boot/impl/FnTest.java Thu Dec 19 17:11:01 2013 +0100
53.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
53.3 @@ -1,127 +0,0 @@
53.4 -/**
53.5 - * HTML via Java(tm) Language Bindings
53.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
53.7 - *
53.8 - * This program is free software: you can redistribute it and/or modify
53.9 - * it under the terms of the GNU General Public License as published by
53.10 - * the Free Software Foundation, version 2 of the License.
53.11 - *
53.12 - * This program is distributed in the hope that it will be useful,
53.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
53.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
53.15 - * GNU General Public License for more details. apidesign.org
53.16 - * designates this particular file as subject to the
53.17 - * "Classpath" exception as provided by apidesign.org
53.18 - * in the License file that accompanied this code.
53.19 - *
53.20 - * You should have received a copy of the GNU General Public License
53.21 - * along with this program. Look for COPYING file in the top folder.
53.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
53.23 - */
53.24 -
53.25 -package org.apidesign.html.boot.impl;
53.26 -
53.27 -import java.io.Closeable;
53.28 -import java.io.Reader;
53.29 -import java.net.URL;
53.30 -import java.net.URLClassLoader;
53.31 -import java.util.ArrayList;
53.32 -import java.util.Arrays;
53.33 -import java.util.Collection;
53.34 -import java.util.List;
53.35 -import javax.script.Invocable;
53.36 -import javax.script.ScriptEngine;
53.37 -import javax.script.ScriptEngineManager;
53.38 -import javax.script.ScriptException;
53.39 -import org.apidesign.html.boot.spi.Fn;
53.40 -import org.testng.annotations.BeforeClass;
53.41 -import org.testng.annotations.BeforeMethod;
53.42 -
53.43 -/**
53.44 - *
53.45 - * @author Jaroslav Tulach <jtulach@netbeans.org>
53.46 - */
53.47 -public class FnTest extends JsClassLoaderBase {
53.48 - private static Fn.Presenter presenter;
53.49 -
53.50 - public FnTest() {
53.51 - }
53.52 -
53.53 - @BeforeClass
53.54 - public static void createClassLoader() throws Exception {
53.55 - ScriptEngineManager sem = new ScriptEngineManager();
53.56 - final ScriptEngine eng = sem.getEngineByMimeType("text/javascript");
53.57 -
53.58 - final URL my = FnTest.class.getProtectionDomain().getCodeSource().getLocation();
53.59 - ClassLoader parent = JsClassLoaderTest.class.getClassLoader().getParent();
53.60 - final URLClassLoader ul = new URLClassLoader(new URL[] { my }, parent);
53.61 -
53.62 - class Impl implements FindResources, Fn.Presenter {
53.63 - @Override
53.64 - public void findResources(String path, Collection<? super URL> results, boolean oneIsEnough) {
53.65 - URL u = ul.findResource(path);
53.66 - if (u != null) {
53.67 - results.add(u);
53.68 - }
53.69 - }
53.70 -
53.71 - @Override
53.72 - public Fn defineFn(String code, String... names) {
53.73 - StringBuilder sb = new StringBuilder();
53.74 - sb.append("(function() {");
53.75 - sb.append("return function(");
53.76 - String sep = "";
53.77 - for (String n : names) {
53.78 - sb.append(sep);
53.79 - sb.append(n);
53.80 - sep = ", ";
53.81 - }
53.82 - sb.append(") {");
53.83 - sb.append(code);
53.84 - sb.append("};");
53.85 - sb.append("})()");
53.86 - try {
53.87 - final Object val = eng.eval(sb.toString());
53.88 - return new Fn(this) {
53.89 - @Override
53.90 - public Object invoke(Object thiz, Object... args) throws Exception {
53.91 - List<Object> all = new ArrayList<Object>(args.length + 1);
53.92 - all.add(thiz == null ? val : thiz);
53.93 - all.addAll(Arrays.asList(args));
53.94 - Invocable inv = (Invocable)eng;
53.95 - try {
53.96 - Object ret = inv.invokeMethod(val, "call", all.toArray());
53.97 - return val.equals(ret) ? null : ret;
53.98 - } catch (ScriptException ex) {
53.99 - throw ex;
53.100 - }
53.101 - }
53.102 - };
53.103 - } catch (ScriptException ex) {
53.104 - throw new LinkageError("Can't parse: " + sb, ex);
53.105 - }
53.106 - }
53.107 -
53.108 - @Override
53.109 - public void displayPage(URL resource, Runnable r) {
53.110 - throw new UnsupportedOperationException();
53.111 - }
53.112 -
53.113 - @Override
53.114 - public void loadScript(Reader code) throws Exception {
53.115 - eng.eval(code);
53.116 - }
53.117 - }
53.118 - Impl impl = new Impl();
53.119 - ClassLoader loader = FnUtils.newLoader(impl, impl, parent);
53.120 - presenter = impl;
53.121 -
53.122 - Closeable close = FnContext.activate(impl);
53.123 - methodClass = loader.loadClass(JsMethods.class.getName());
53.124 - close.close();
53.125 - }
53.126 -
53.127 - @BeforeMethod public void initPresenter() {
53.128 - FnContext.currentPresenter(presenter);
53.129 - }
53.130 -}
54.1 --- a/boot/src/test/java/org/apidesign/html/boot/impl/JavaScriptProcesorTest.java Thu Dec 19 17:11:01 2013 +0100
54.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
54.3 @@ -1,107 +0,0 @@
54.4 -/**
54.5 - * HTML via Java(tm) Language Bindings
54.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
54.7 - *
54.8 - * This program is free software: you can redistribute it and/or modify
54.9 - * it under the terms of the GNU General Public License as published by
54.10 - * the Free Software Foundation, version 2 of the License.
54.11 - *
54.12 - * This program is distributed in the hope that it will be useful,
54.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
54.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
54.15 - * GNU General Public License for more details. apidesign.org
54.16 - * designates this particular file as subject to the
54.17 - * "Classpath" exception as provided by apidesign.org
54.18 - * in the License file that accompanied this code.
54.19 - *
54.20 - * You should have received a copy of the GNU General Public License
54.21 - * along with this program. Look for COPYING file in the top folder.
54.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
54.23 - */
54.24 -package org.apidesign.html.boot.impl;
54.25 -
54.26 -import java.io.IOException;
54.27 -import java.lang.reflect.Field;
54.28 -import java.lang.reflect.Method;
54.29 -import static org.testng.Assert.assertEquals;
54.30 -import static org.testng.Assert.assertTrue;
54.31 -import org.testng.annotations.Test;
54.32 -
54.33 -/**
54.34 - *
54.35 - * @author Jaroslav Tulach <jtulach@netbeans.org>
54.36 - */
54.37 -public class JavaScriptProcesorTest {
54.38 -
54.39 - @Test public void detectCallbackToNonExistingClass() throws IOException {
54.40 - String code = "package x.y.z;\n"
54.41 - + "import net.java.html.js.JavaScriptBody;\n"
54.42 - + "class X {\n"
54.43 - + " @JavaScriptBody(args={\"r\"}, javacall=true, body =\n"
54.44 - + " \"r.@java.lang.Runable::run()();\"\n" // typo
54.45 - + " )\n"
54.46 - + " private static native void callback(Runnable r);\n"
54.47 - + "}\n";
54.48 -
54.49 - Compile c = Compile.create("", code);
54.50 - c.assertErrors();
54.51 - c.assertError("java.lang.Runable"); // typo
54.52 - }
54.53 -
54.54 - @Test public void detectCallbackToNonExistingMethod() throws IOException {
54.55 - String code = "package x.y.z;\n"
54.56 - + "import net.java.html.js.JavaScriptBody;\n"
54.57 - + "class X {\n"
54.58 - + " @JavaScriptBody(args={\"r\"}, javacall=true, body =\n"
54.59 - + " \"r.@java.lang.Runnable::cancel()();\"\n"
54.60 - + " )\n"
54.61 - + " private static native void callback(Runnable r);\n"
54.62 - + "}\n";
54.63 -
54.64 - Compile c = Compile.create("", code);
54.65 - c.assertErrors();
54.66 - c.assertError("method cancel");
54.67 - }
54.68 -
54.69 - @Test public void detectCallbackToNonExistingParams() throws IOException {
54.70 - String code = "package x.y.z;\n"
54.71 - + "import net.java.html.js.JavaScriptBody;\n"
54.72 - + "class X {\n"
54.73 - + " @JavaScriptBody(args={\"r\"}, javacall=true, body =\n"
54.74 - + " \"r.@java.lang.Runnable::run(I)(10);\"\n"
54.75 - + " )\n"
54.76 - + " private static native void callback(Runnable r);\n"
54.77 - + "}\n";
54.78 -
54.79 - Compile c = Compile.create("", code);
54.80 - c.assertErrors();
54.81 - c.assertError("wrong parameters: (I)");
54.82 - }
54.83 -
54.84 - @Test public void objectTypeParamsAreOK() throws IOException {
54.85 - String code = "package x.y.z;\n"
54.86 - + "import net.java.html.js.JavaScriptBody;\n"
54.87 - + "class X {\n"
54.88 - + " @JavaScriptBody(args={\"r\"}, javacall=true, body =\n"
54.89 - + " \"r.@java.lang.Object::equals(Ljava/lang/Object;)(null);\"\n"
54.90 - + " )\n"
54.91 - + " private static native void testEqual(Object r);\n"
54.92 - + "}\n";
54.93 -
54.94 - Compile c = Compile.create("", code);
54.95 - c.assertNoErrors();
54.96 - }
54.97 -
54.98 - @Test public void generatesCallbacksThatReturnObject() throws Exception {
54.99 - Class<?> callbacksForTestPkg = Class.forName("org.apidesign.html.boot.impl.$JsCallbacks$");
54.100 - Method m = callbacksForTestPkg.getDeclaredMethod("java_lang_Runnable$run$", Runnable.class);
54.101 - assertEquals(m.getReturnType(), Object.class, "All methods always return object");
54.102 - }
54.103 -
54.104 - @Test public void hasInstanceField() throws Exception {
54.105 - Class<?> callbacksForTestPkg = Class.forName("org.apidesign.html.boot.impl.$JsCallbacks$");
54.106 - Field f = callbacksForTestPkg.getDeclaredField("VM");
54.107 - f.setAccessible(true);
54.108 - assertTrue(callbacksForTestPkg.isInstance(f.get(null)), "Singleton field VM");
54.109 - }
54.110 -}
55.1 --- a/boot/src/test/java/org/apidesign/html/boot/impl/JsClassLoaderBase.java Thu Dec 19 17:11:01 2013 +0100
55.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
55.3 @@ -1,179 +0,0 @@
55.4 -/**
55.5 - * HTML via Java(tm) Language Bindings
55.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
55.7 - *
55.8 - * This program is free software: you can redistribute it and/or modify
55.9 - * it under the terms of the GNU General Public License as published by
55.10 - * the Free Software Foundation, version 2 of the License.
55.11 - *
55.12 - * This program is distributed in the hope that it will be useful,
55.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
55.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
55.15 - * GNU General Public License for more details. apidesign.org
55.16 - * designates this particular file as subject to the
55.17 - * "Classpath" exception as provided by apidesign.org
55.18 - * in the License file that accompanied this code.
55.19 - *
55.20 - * You should have received a copy of the GNU General Public License
55.21 - * along with this program. Look for COPYING file in the top folder.
55.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
55.23 - */
55.24 -package org.apidesign.html.boot.impl;
55.25 -
55.26 -import java.lang.reflect.InvocationTargetException;
55.27 -import java.lang.reflect.Method;
55.28 -import java.lang.reflect.Modifier;
55.29 -import static org.testng.Assert.*;
55.30 -import org.testng.annotations.BeforeMethod;
55.31 -import org.testng.annotations.Test;
55.32 -
55.33 -/**
55.34 - *
55.35 - * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
55.36 - */
55.37 -public class JsClassLoaderBase {
55.38 - protected static Class<?> methodClass;
55.39 -
55.40 - public JsClassLoaderBase() {
55.41 - }
55.42 -
55.43 - @BeforeMethod
55.44 - public void assertClassDefined() {
55.45 - assertNotNull(methodClass, "BeforeClass set up code should provide methodClass");
55.46 - }
55.47 -
55.48 - @Test public void noParamMethod() throws Throwable {
55.49 - Method plus = methodClass.getMethod("fortyTwo");
55.50 - try {
55.51 - final Object val = plus.invoke(null);
55.52 - assertTrue(val instanceof Number, "A number returned " + val);
55.53 - assertEquals(((Number)val).intValue(), 42);
55.54 - } catch (InvocationTargetException ex) {
55.55 - throw ex.getTargetException();
55.56 - }
55.57 - }
55.58 -
55.59 - @Test public void testExecuteScript() throws Throwable {
55.60 - Method plus = methodClass.getMethod("plus", int.class, int.class);
55.61 - try {
55.62 - assertEquals(plus.invoke(null, 10, 20), 30);
55.63 - } catch (InvocationTargetException ex) {
55.64 - throw ex.getTargetException();
55.65 - }
55.66 - }
55.67 -
55.68 - @Test public void overloadedMethod() throws Throwable {
55.69 - Method plus = methodClass.getMethod("plus", int.class);
55.70 - try {
55.71 - assertEquals(plus.invoke(null, 10), 10);
55.72 - } catch (InvocationTargetException ex) {
55.73 - throw ex.getTargetException();
55.74 - }
55.75 - }
55.76 -
55.77 - @Test public void instanceMethod() throws Throwable {
55.78 - Method plus = methodClass.getMethod("plusInst", int.class);
55.79 - Object inst = methodClass.newInstance();
55.80 - try {
55.81 - assertEquals(plus.invoke(inst, 10), 10);
55.82 - } catch (InvocationTargetException ex) {
55.83 - throw ex.getTargetException();
55.84 - }
55.85 - }
55.86 -
55.87 - @Test public void staticThis() throws Throwable {
55.88 - Method st = methodClass.getMethod("staticThis");
55.89 - try {
55.90 - assertNull(st.invoke(null));
55.91 - } catch (InvocationTargetException ex) {
55.92 - throw ex.getTargetException();
55.93 - }
55.94 - }
55.95 -
55.96 - @Test public void getThis() throws Throwable {
55.97 - Object th = methodClass.newInstance();
55.98 - Method st = methodClass.getMethod("getThis");
55.99 - try {
55.100 - assertEquals(st.invoke(th), th);
55.101 - } catch (InvocationTargetException ex) {
55.102 - throw ex.getTargetException();
55.103 - }
55.104 - }
55.105 -
55.106 - @Test public void truth() throws Throwable {
55.107 - Method st = methodClass.getMethod("truth");
55.108 - assertTrue((st.getModifiers() & Modifier.STATIC) != 0, "Is static");
55.109 - assertEquals(st.invoke(null), Boolean.TRUE, "Can return boolean");
55.110 - }
55.111 -
55.112 - @Test public void callback() throws Throwable {
55.113 - class R implements Runnable {
55.114 - int cnt;
55.115 -
55.116 - @Override
55.117 - public void run() {
55.118 - cnt++;
55.119 - }
55.120 - }
55.121 - R r = new R();
55.122 -
55.123 - Method inc = methodClass.getMethod("callback", Runnable.class);
55.124 - inc.invoke(null, r);
55.125 -
55.126 - assertEquals(r.cnt, 1, "Callback happened");
55.127 - }
55.128 -
55.129 - @Test public void sumArray() throws Throwable {
55.130 - Method st = methodClass.getMethod("sumArr", int[].class);
55.131 - assertEquals(st.invoke(null, new int[] { 1, 2, 3 }), 6, "1+2+3 is six");
55.132 - }
55.133 -
55.134 - @Test public void javaScriptResource() throws Throwable {
55.135 - try {
55.136 - Method st = methodClass.getMethod("useExternalMul", int.class, int.class);
55.137 - assertEquals(st.invoke(null, 6, 7), 42, "Meaning of JavaScript?");
55.138 - } catch (InvocationTargetException ex) {
55.139 - throw ex.getTargetException();
55.140 - }
55.141 - }
55.142 -
55.143 - @Test public void callJavaScriptMethodOnOwnClass() throws Throwable {
55.144 - try {
55.145 - Object thiz = methodClass.newInstance();
55.146 - Method st = methodClass.getMethod("returnYourSelf", methodClass);
55.147 - assertEquals(st.invoke(null, thiz), thiz, "Returns this");
55.148 - } catch (InvocationTargetException ex) {
55.149 - throw ex.getTargetException();
55.150 - }
55.151 - }
55.152 -
55.153 - @Test public void callStaticJavaMethod() throws Throwable {
55.154 - Method st = methodClass.getMethod("staticCallback", int.class, int.class);
55.155 - assertEquals(st.invoke(null, 6, 7), 42, "Meaning of JavaScript?");
55.156 - }
55.157 -
55.158 - @Test public void callStaticStringParamMethod() throws Throwable {
55.159 - Method st = methodClass.getMethod("parseInt", String.class);
55.160 - assertEquals(st.invoke(null, "42"), 42, "Meaning of JavaScript?");
55.161 - }
55.162 -
55.163 - @Test public void firstLong() throws Throwable {
55.164 - Method st = methodClass.getMethod("chooseLong", boolean.class, boolean.class, long.class, long.class);
55.165 - assertEquals(st.invoke(null, true, false, 10, 20), 10L, "Take first value");
55.166 - }
55.167 -
55.168 - @Test public void secondLong() throws Throwable {
55.169 - Method st = methodClass.getMethod("chooseLong", boolean.class, boolean.class, long.class, long.class);
55.170 - assertEquals(st.invoke(null, false, true, 10, 20), 20L, "Take 2nd value");
55.171 - }
55.172 -
55.173 - @Test public void bothLong() throws Throwable {
55.174 - Method st = methodClass.getMethod("chooseLong", boolean.class, boolean.class, long.class, long.class);
55.175 - assertEquals(st.invoke(null, true, true, 10, 20), 30L, "Take both values");
55.176 - }
55.177 -
55.178 - @Test public void recordError() throws Throwable {
55.179 - Method st = methodClass.getMethod("recordError", Object.class);
55.180 - assertEquals(st.invoke(methodClass.newInstance(), "Hello"), "Hello", "The same parameter returned");
55.181 - }
55.182 -}
55.183 \ No newline at end of file
56.1 --- a/boot/src/test/java/org/apidesign/html/boot/impl/JsClassLoaderTest.java Thu Dec 19 17:11:01 2013 +0100
56.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
56.3 @@ -1,133 +0,0 @@
56.4 -/**
56.5 - * HTML via Java(tm) Language Bindings
56.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
56.7 - *
56.8 - * This program is free software: you can redistribute it and/or modify
56.9 - * it under the terms of the GNU General Public License as published by
56.10 - * the Free Software Foundation, version 2 of the License.
56.11 - *
56.12 - * This program is distributed in the hope that it will be useful,
56.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
56.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
56.15 - * GNU General Public License for more details. apidesign.org
56.16 - * designates this particular file as subject to the
56.17 - * "Classpath" exception as provided by apidesign.org
56.18 - * in the License file that accompanied this code.
56.19 - *
56.20 - * You should have received a copy of the GNU General Public License
56.21 - * along with this program. Look for COPYING file in the top folder.
56.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
56.23 - */
56.24 -package org.apidesign.html.boot.impl;
56.25 -
56.26 -import java.io.Closeable;
56.27 -import java.io.Reader;
56.28 -import org.apidesign.html.boot.spi.Fn;
56.29 -import java.net.URL;
56.30 -import java.net.URLClassLoader;
56.31 -import java.util.ArrayList;
56.32 -import java.util.Arrays;
56.33 -import java.util.Enumeration;
56.34 -import java.util.List;
56.35 -import javax.script.Invocable;
56.36 -import javax.script.ScriptEngine;
56.37 -import javax.script.ScriptEngineManager;
56.38 -import javax.script.ScriptException;
56.39 -import org.testng.annotations.AfterClass;
56.40 -import org.testng.annotations.BeforeClass;
56.41 -import org.testng.annotations.BeforeMethod;
56.42 -
56.43 -/**
56.44 - *
56.45 - * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
56.46 - */
56.47 -public class JsClassLoaderTest extends JsClassLoaderBase{
56.48 - private static Fn.Presenter loader;
56.49 -
56.50 - @BeforeClass
56.51 - public static void setUpClass() throws Exception {
56.52 - ScriptEngineManager sem = new ScriptEngineManager();
56.53 - final ScriptEngine eng = sem.getEngineByMimeType("text/javascript");
56.54 -
56.55 - final URL my = JsClassLoaderTest.class.getProtectionDomain().getCodeSource().getLocation();
56.56 - ClassLoader parent = JsClassLoaderTest.class.getClassLoader().getParent();
56.57 - final URLClassLoader ul = new URLClassLoader(new URL[] { my }, parent);
56.58 - class MyCL extends JsClassLoader implements Fn.Presenter {
56.59 -
56.60 - public MyCL(ClassLoader parent) {
56.61 - super(parent);
56.62 - }
56.63 -
56.64 - @Override
56.65 - protected URL findResource(String name) {
56.66 - return ul.getResource(name);
56.67 - }
56.68 - @Override
56.69 - public Fn defineFn(String code, String... names) {
56.70 - StringBuilder sb = new StringBuilder();
56.71 - sb.append("(function() {");
56.72 - sb.append("return function(");
56.73 - String sep = "";
56.74 - for (String n : names) {
56.75 - sb.append(sep);
56.76 - sb.append(n);
56.77 - sep = ", ";
56.78 - }
56.79 - sb.append(") {");
56.80 - sb.append(code);
56.81 - sb.append("};");
56.82 - sb.append("})()");
56.83 - try {
56.84 - final Object val = eng.eval(sb.toString());
56.85 - return new Fn(this) {
56.86 - @Override
56.87 - public Object invoke(Object thiz, Object... args) throws Exception {
56.88 - List<Object> all = new ArrayList<Object>(args.length + 1);
56.89 - all.add(thiz == null ? val : thiz);
56.90 - all.addAll(Arrays.asList(args));
56.91 - Invocable inv = (Invocable)eng;
56.92 - try {
56.93 - Object ret = inv.invokeMethod(val, "call", all.toArray());
56.94 - return val.equals(ret) ? null : ret;
56.95 - } catch (Exception ex) {
56.96 - throw ex;
56.97 - }
56.98 - }
56.99 - };
56.100 - } catch (ScriptException ex) {
56.101 - throw new LinkageError("Can't parse: " + sb, ex);
56.102 - }
56.103 - }
56.104 -
56.105 - @Override
56.106 - protected Enumeration<URL> findResources(String name) {
56.107 - throw new UnsupportedOperationException();
56.108 - }
56.109 -
56.110 - @Override
56.111 - public void loadScript(Reader code) throws ScriptException {
56.112 - eng.eval(code);
56.113 - }
56.114 -
56.115 - @Override
56.116 - public void displayPage(URL page, Runnable onPageLoad) {
56.117 - throw new UnsupportedOperationException();
56.118 - }
56.119 - };
56.120 -
56.121 - MyCL l = new MyCL(parent);
56.122 - Closeable close = FnContext.activate(l);
56.123 - methodClass = l.loadClass(JsMethods.class.getName());
56.124 - close.close();
56.125 - loader = l;
56.126 - }
56.127 -
56.128 - @BeforeMethod public void initPresenter() {
56.129 - FnContext.currentPresenter(loader);
56.130 - }
56.131 -
56.132 - @AfterClass
56.133 - public static void cleanUp() {
56.134 - methodClass = null;
56.135 - }
56.136 -}
56.137 \ No newline at end of file
57.1 --- a/boot/src/test/java/org/apidesign/html/boot/impl/JsMethods.java Thu Dec 19 17:11:01 2013 +0100
57.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
57.3 @@ -1,107 +0,0 @@
57.4 -/**
57.5 - * HTML via Java(tm) Language Bindings
57.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
57.7 - *
57.8 - * This program is free software: you can redistribute it and/or modify
57.9 - * it under the terms of the GNU General Public License as published by
57.10 - * the Free Software Foundation, version 2 of the License.
57.11 - *
57.12 - * This program is distributed in the hope that it will be useful,
57.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
57.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
57.15 - * GNU General Public License for more details. apidesign.org
57.16 - * designates this particular file as subject to the
57.17 - * "Classpath" exception as provided by apidesign.org
57.18 - * in the License file that accompanied this code.
57.19 - *
57.20 - * You should have received a copy of the GNU General Public License
57.21 - * along with this program. Look for COPYING file in the top folder.
57.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
57.23 - */
57.24 -package org.apidesign.html.boot.impl;
57.25 -
57.26 -import net.java.html.js.JavaScriptBody;
57.27 -import net.java.html.js.JavaScriptResource;
57.28 -
57.29 -
57.30 -/**
57.31 - *
57.32 - * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
57.33 - */
57.34 -@JavaScriptResource("jsmethods.js")
57.35 -public class JsMethods {
57.36 - private Object value;
57.37 -
57.38 - @JavaScriptBody(args = {}, body = "return 42;")
57.39 - public static Object fortyTwo() {
57.40 - return -42;
57.41 - }
57.42 -
57.43 - @JavaScriptBody(args = {"x", "y" }, body = "return x + y;")
57.44 - public static native int plus(int x, int y);
57.45 -
57.46 - @JavaScriptBody(args = {"x"}, body = "return x;")
57.47 - public static native int plus(int x);
57.48 -
57.49 - @JavaScriptBody(args = {}, body = "return this;")
57.50 - public static native Object staticThis();
57.51 -
57.52 - @JavaScriptBody(args = {}, body = "return this;")
57.53 - public native Object getThis();
57.54 - @JavaScriptBody(args = {"x"}, body = "return x;")
57.55 - public native int plusInst(int x);
57.56 -
57.57 - @JavaScriptBody(args = {}, body = "return true;")
57.58 - public static boolean truth() {
57.59 - return false;
57.60 - }
57.61 -
57.62 - @JavaScriptBody(args = { "r" }, javacall=true, body = "r.@java.lang.Runnable::run()();")
57.63 - public static native void callback(Runnable r);
57.64 -
57.65 - @JavaScriptBody(args = { "at", "arr" }, javacall = true, body =
57.66 - "var a = 0;\n"
57.67 - + "for (var i = 0; i < arr.length; i++) {\n"
57.68 - + " a = at.@org.apidesign.html.boot.impl.Arithm::sumTwo(II)(a, arr[i]);\n"
57.69 - + "}\n"
57.70 - + "return a;"
57.71 - )
57.72 - private static native int sumArr(Arithm at, int... arr);
57.73 -
57.74 - public static int sumArr(int... arr) {
57.75 - return sumArr(new Arithm(), arr);
57.76 - }
57.77 -
57.78 - @JavaScriptBody(args = { "x", "y" }, body = "return mul(x, y);")
57.79 - public static native int useExternalMul(int x, int y);
57.80 -
57.81 - @JavaScriptBody(args = { "m" }, javacall = true, body = "return m.@org.apidesign.html.boot.impl.JsMethods::getThis()();")
57.82 - public static native JsMethods returnYourSelf(JsMethods m);
57.83 -
57.84 - @JavaScriptBody(args = { "x", "y" }, javacall = true, body = "return @org.apidesign.html.boot.impl.JsMethods::useExternalMul(II)(x, y);")
57.85 - public static native int staticCallback(int x, int y);
57.86 -
57.87 - @JavaScriptBody(args = { "v" }, javacall = true, body = "return @java.lang.Integer::parseInt(Ljava/lang/String;)(v);")
57.88 - public static native int parseInt(String v);
57.89 -
57.90 - @JavaScriptBody(args = { "useA", "useB", "a", "b" }, body = "var l = 0;"
57.91 - + "if (useA) l += a;\n"
57.92 - + "if (useB) l += b;\n"
57.93 - + "return l;\n"
57.94 - )
57.95 - public static native long chooseLong(boolean useA, boolean useB, long a, long b);
57.96 -
57.97 - protected void onError(Object o) throws Exception {
57.98 - value = o;
57.99 - }
57.100 -
57.101 - Object getError() {
57.102 - return value;
57.103 - }
57.104 -
57.105 - @JavaScriptBody(args = { "err" }, javacall = true, body =
57.106 - "this.@org.apidesign.html.boot.impl.JsMethods::onError(Ljava/lang/Object;)(err);"
57.107 - + "return this.@org.apidesign.html.boot.impl.JsMethods::getError()();"
57.108 - )
57.109 - public native Object recordError(Object err);
57.110 -}
58.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
58.2 +++ b/boot/src/test/java/org/netbeans/html/boot/impl/Arithm.java Tue Jan 07 08:21:57 2014 +0100
58.3 @@ -0,0 +1,53 @@
58.4 +/**
58.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
58.6 + *
58.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
58.8 + *
58.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
58.10 + * Other names may be trademarks of their respective owners.
58.11 + *
58.12 + * The contents of this file are subject to the terms of either the GNU
58.13 + * General Public License Version 2 only ("GPL") or the Common
58.14 + * Development and Distribution License("CDDL") (collectively, the
58.15 + * "License"). You may not use this file except in compliance with the
58.16 + * License. You can obtain a copy of the License at
58.17 + * http://www.netbeans.org/cddl-gplv2.html
58.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
58.19 + * specific language governing permissions and limitations under the
58.20 + * License. When distributing the software, include this License Header
58.21 + * Notice in each file and include the License file at
58.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
58.23 + * particular file as subject to the "Classpath" exception as provided
58.24 + * by Oracle in the GPL Version 2 section of the License file that
58.25 + * accompanied this code. If applicable, add the following below the
58.26 + * License Header, with the fields enclosed by brackets [] replaced by
58.27 + * your own identifying information:
58.28 + * "Portions Copyrighted [year] [name of copyright owner]"
58.29 + *
58.30 + * Contributor(s):
58.31 + *
58.32 + * The Original Software is NetBeans. The Initial Developer of the Original
58.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
58.34 + *
58.35 + * If you wish your version of this file to be governed by only the CDDL
58.36 + * or only the GPL Version 2, indicate your decision by adding
58.37 + * "[Contributor] elects to include this software in this distribution
58.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
58.39 + * single choice of license, a recipient has the option to distribute
58.40 + * your version of this file under either the CDDL, the GPL Version 2 or
58.41 + * to extend the choice of license to its licensees as provided above.
58.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
58.43 + * Version 2 license, then the option applies only if the new code is
58.44 + * made subject to such option by the copyright holder.
58.45 + */
58.46 +package org.netbeans.html.boot.impl;
58.47 +
58.48 +/**
58.49 + *
58.50 + * @author Jaroslav Tulach <jtulach@netbeans.org>
58.51 + */
58.52 +public class Arithm {
58.53 + public int sumTwo(int a, int b) {
58.54 + return a + b;
58.55 + }
58.56 +}
59.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
59.2 +++ b/boot/src/test/java/org/netbeans/html/boot/impl/Compile.java Tue Jan 07 08:21:57 2014 +0100
59.3 @@ -0,0 +1,291 @@
59.4 +/**
59.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
59.6 + *
59.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
59.8 + *
59.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
59.10 + * Other names may be trademarks of their respective owners.
59.11 + *
59.12 + * The contents of this file are subject to the terms of either the GNU
59.13 + * General Public License Version 2 only ("GPL") or the Common
59.14 + * Development and Distribution License("CDDL") (collectively, the
59.15 + * "License"). You may not use this file except in compliance with the
59.16 + * License. You can obtain a copy of the License at
59.17 + * http://www.netbeans.org/cddl-gplv2.html
59.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
59.19 + * specific language governing permissions and limitations under the
59.20 + * License. When distributing the software, include this License Header
59.21 + * Notice in each file and include the License file at
59.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
59.23 + * particular file as subject to the "Classpath" exception as provided
59.24 + * by Oracle in the GPL Version 2 section of the License file that
59.25 + * accompanied this code. If applicable, add the following below the
59.26 + * License Header, with the fields enclosed by brackets [] replaced by
59.27 + * your own identifying information:
59.28 + * "Portions Copyrighted [year] [name of copyright owner]"
59.29 + *
59.30 + * Contributor(s):
59.31 + *
59.32 + * The Original Software is NetBeans. The Initial Developer of the Original
59.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
59.34 + *
59.35 + * If you wish your version of this file to be governed by only the CDDL
59.36 + * or only the GPL Version 2, indicate your decision by adding
59.37 + * "[Contributor] elects to include this software in this distribution
59.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
59.39 + * single choice of license, a recipient has the option to distribute
59.40 + * your version of this file under either the CDDL, the GPL Version 2 or
59.41 + * to extend the choice of license to its licensees as provided above.
59.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
59.43 + * Version 2 license, then the option applies only if the new code is
59.44 + * made subject to such option by the copyright holder.
59.45 + */
59.46 +package org.netbeans.html.boot.impl;
59.47 +
59.48 +import java.io.ByteArrayInputStream;
59.49 +import java.io.ByteArrayOutputStream;
59.50 +import java.io.IOException;
59.51 +import java.io.InputStream;
59.52 +import java.io.OutputStream;
59.53 +import java.net.URI;
59.54 +import java.net.URISyntaxException;
59.55 +import java.util.ArrayList;
59.56 +import java.util.Arrays;
59.57 +import java.util.HashMap;
59.58 +import java.util.List;
59.59 +import java.util.Locale;
59.60 +import java.util.Map;
59.61 +import java.util.regex.Matcher;
59.62 +import java.util.regex.Pattern;
59.63 +import javax.tools.Diagnostic;
59.64 +import javax.tools.DiagnosticListener;
59.65 +import javax.tools.FileObject;
59.66 +import javax.tools.ForwardingJavaFileManager;
59.67 +import javax.tools.JavaFileManager;
59.68 +import javax.tools.JavaFileObject;
59.69 +import javax.tools.JavaFileObject.Kind;
59.70 +import javax.tools.SimpleJavaFileObject;
59.71 +import javax.tools.StandardJavaFileManager;
59.72 +import javax.tools.StandardLocation;
59.73 +import javax.tools.ToolProvider;
59.74 +import static org.testng.Assert.assertTrue;
59.75 +import static org.testng.Assert.assertFalse;
59.76 +import static org.testng.Assert.fail;
59.77 +
59.78 +/**
59.79 + *
59.80 + * @author Jaroslav Tulach <jtulach@netbeans.org>
59.81 + */
59.82 +final class Compile implements DiagnosticListener<JavaFileObject> {
59.83 + private final List<Diagnostic<? extends JavaFileObject>> errors =
59.84 + new ArrayList<Diagnostic<? extends JavaFileObject>>();
59.85 + private final Map<String, byte[]> classes;
59.86 + private final String pkg;
59.87 + private final String cls;
59.88 + private final String html;
59.89 + private final String sourceLevel;
59.90 +
59.91 + private Compile(String html, String code, String sl) throws IOException {
59.92 + this.pkg = findPkg(code);
59.93 + this.cls = findCls(code);
59.94 + this.html = html;
59.95 + this.sourceLevel = sl;
59.96 + classes = compile(html, code);
59.97 + }
59.98 +
59.99 + /** Performs compilation of given HTML page and associated Java code
59.100 + */
59.101 + public static Compile create(String html, String code) throws IOException {
59.102 + return create(html, code, "1.7");
59.103 + }
59.104 + static Compile create(String html, String code, String sourceLevel) throws IOException {
59.105 + return new Compile(html, code, sourceLevel);
59.106 + }
59.107 +
59.108 + /** Checks for given class among compiled resources */
59.109 + public byte[] get(String res) {
59.110 + return classes.get(res);
59.111 + }
59.112 +
59.113 + /** Obtains errors created during compilation.
59.114 + */
59.115 + public List<Diagnostic<? extends JavaFileObject>> getErrors() {
59.116 + List<Diagnostic<? extends JavaFileObject>> err;
59.117 + err = new ArrayList<Diagnostic<? extends JavaFileObject>>();
59.118 + for (Diagnostic<? extends JavaFileObject> diagnostic : errors) {
59.119 + if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
59.120 + err.add(diagnostic);
59.121 + }
59.122 + }
59.123 + return err;
59.124 + }
59.125 +
59.126 + private Map<String, byte[]> compile(final String html, final String code) throws IOException {
59.127 + StandardJavaFileManager sjfm = ToolProvider.getSystemJavaCompiler().getStandardFileManager(this, null, null);
59.128 +
59.129 + final Map<String, ByteArrayOutputStream> class2BAOS;
59.130 + class2BAOS = new HashMap<String, ByteArrayOutputStream>();
59.131 +
59.132 + JavaFileObject file = new SimpleJavaFileObject(URI.create("mem://mem"), Kind.SOURCE) {
59.133 + @Override
59.134 + public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
59.135 + return code;
59.136 + }
59.137 + };
59.138 + final JavaFileObject htmlFile = new SimpleJavaFileObject(URI.create("mem://mem2"), Kind.OTHER) {
59.139 + @Override
59.140 + public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
59.141 + return html;
59.142 + }
59.143 +
59.144 + @Override
59.145 + public InputStream openInputStream() throws IOException {
59.146 + return new ByteArrayInputStream(html.getBytes());
59.147 + }
59.148 + };
59.149 +
59.150 + final URI scratch;
59.151 + try {
59.152 + scratch = new URI("mem://mem3");
59.153 + } catch (URISyntaxException ex) {
59.154 + throw new IOException(ex);
59.155 + }
59.156 +
59.157 + JavaFileManager jfm = new ForwardingJavaFileManager<JavaFileManager>(sjfm) {
59.158 + @Override
59.159 + public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) throws IOException {
59.160 + if (kind == Kind.CLASS) {
59.161 + final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
59.162 +
59.163 + class2BAOS.put(className.replace('.', '/') + ".class", buffer);
59.164 + return new SimpleJavaFileObject(sibling.toUri(), kind) {
59.165 + @Override
59.166 + public OutputStream openOutputStream() throws IOException {
59.167 + return buffer;
59.168 + }
59.169 + };
59.170 + }
59.171 +
59.172 + if (kind == Kind.SOURCE) {
59.173 + final String n = className.replace('.', '/') + ".java";
59.174 + final URI un;
59.175 + try {
59.176 + un = new URI("mem://" + n);
59.177 + } catch (URISyntaxException ex) {
59.178 + throw new IOException(ex);
59.179 + }
59.180 + return new VirtFO(un/*sibling.toUri()*/, kind, n);
59.181 + }
59.182 +
59.183 + throw new IllegalStateException();
59.184 + }
59.185 +
59.186 + @Override
59.187 + public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException {
59.188 + if (location == StandardLocation.SOURCE_PATH) {
59.189 + if (packageName.equals(pkg)) {
59.190 + return htmlFile;
59.191 + }
59.192 + }
59.193 +
59.194 + return null;
59.195 + }
59.196 +
59.197 + @Override
59.198 + public boolean isSameFile(FileObject a, FileObject b) {
59.199 + if (a instanceof VirtFO && b instanceof VirtFO) {
59.200 + return ((VirtFO)a).getName().equals(((VirtFO)b).getName());
59.201 + }
59.202 +
59.203 + return super.isSameFile(a, b);
59.204 + }
59.205 +
59.206 + class VirtFO extends SimpleJavaFileObject {
59.207 +
59.208 + private final String n;
59.209 +
59.210 + public VirtFO(URI uri, Kind kind, String n) {
59.211 + super(uri, kind);
59.212 + this.n = n;
59.213 + }
59.214 + private final ByteArrayOutputStream data = new ByteArrayOutputStream();
59.215 +
59.216 + @Override
59.217 + public OutputStream openOutputStream() throws IOException {
59.218 + return data;
59.219 + }
59.220 +
59.221 + @Override
59.222 + public String getName() {
59.223 + return n;
59.224 + }
59.225 +
59.226 + @Override
59.227 + public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
59.228 + data.close();
59.229 + return new String(data.toByteArray());
59.230 + }
59.231 + }
59.232 + };
59.233 +
59.234 + ToolProvider.getSystemJavaCompiler().getTask(null, jfm, this, /*XXX:*/Arrays.asList("-source", sourceLevel, "-target", "1.7"), null, Arrays.asList(file)).call();
59.235 +
59.236 + Map<String, byte[]> result = new HashMap<String, byte[]>();
59.237 +
59.238 + for (Map.Entry<String, ByteArrayOutputStream> e : class2BAOS.entrySet()) {
59.239 + result.put(e.getKey(), e.getValue().toByteArray());
59.240 + }
59.241 +
59.242 + return result;
59.243 + }
59.244 +
59.245 +
59.246 + @Override
59.247 + public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
59.248 + errors.add(diagnostic);
59.249 + }
59.250 + private static String findPkg(String java) throws IOException {
59.251 + Pattern p = Pattern.compile("package\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}*;", Pattern.MULTILINE);
59.252 + Matcher m = p.matcher(java);
59.253 + if (!m.find()) {
59.254 + throw new IOException("Can't find package declaration in the java file");
59.255 + }
59.256 + String pkg = m.group(1);
59.257 + return pkg;
59.258 + }
59.259 + private static String findCls(String java) throws IOException {
59.260 + Pattern p = Pattern.compile("class\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}", Pattern.MULTILINE);
59.261 + Matcher m = p.matcher(java);
59.262 + if (!m.find()) {
59.263 + throw new IOException("Can't find package declaration in the java file");
59.264 + }
59.265 + String cls = m.group(1);
59.266 + return cls;
59.267 + }
59.268 +
59.269 + String getHtml() {
59.270 + String fqn = "'" + pkg + '.' + cls + "'";
59.271 + return html.replace("'${fqn}'", fqn);
59.272 + }
59.273 + void assertErrors() {
59.274 + assertFalse(getErrors().isEmpty(), "There are supposed to be some errors");
59.275 + }
59.276 +
59.277 + void assertError(String expMsg) {
59.278 + StringBuilder sb = new StringBuilder();
59.279 + sb.append("Can't find ").append(expMsg).append(" among:");
59.280 + for (Diagnostic<? extends JavaFileObject> e : errors) {
59.281 + String msg = e.getMessage(Locale.US);
59.282 + if (msg.contains(expMsg)) {
59.283 + return;
59.284 + }
59.285 + sb.append("\n");
59.286 + sb.append(msg);
59.287 + }
59.288 + fail(sb.toString());
59.289 + }
59.290 +
59.291 + void assertNoErrors() {
59.292 + assertTrue(getErrors().isEmpty(), "No errors expected: " + getErrors());
59.293 + }
59.294 +}
60.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
60.2 +++ b/boot/src/test/java/org/netbeans/html/boot/impl/FnTest.java Tue Jan 07 08:21:57 2014 +0100
60.3 @@ -0,0 +1,148 @@
60.4 +/**
60.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
60.6 + *
60.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
60.8 + *
60.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
60.10 + * Other names may be trademarks of their respective owners.
60.11 + *
60.12 + * The contents of this file are subject to the terms of either the GNU
60.13 + * General Public License Version 2 only ("GPL") or the Common
60.14 + * Development and Distribution License("CDDL") (collectively, the
60.15 + * "License"). You may not use this file except in compliance with the
60.16 + * License. You can obtain a copy of the License at
60.17 + * http://www.netbeans.org/cddl-gplv2.html
60.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
60.19 + * specific language governing permissions and limitations under the
60.20 + * License. When distributing the software, include this License Header
60.21 + * Notice in each file and include the License file at
60.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
60.23 + * particular file as subject to the "Classpath" exception as provided
60.24 + * by Oracle in the GPL Version 2 section of the License file that
60.25 + * accompanied this code. If applicable, add the following below the
60.26 + * License Header, with the fields enclosed by brackets [] replaced by
60.27 + * your own identifying information:
60.28 + * "Portions Copyrighted [year] [name of copyright owner]"
60.29 + *
60.30 + * Contributor(s):
60.31 + *
60.32 + * The Original Software is NetBeans. The Initial Developer of the Original
60.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
60.34 + *
60.35 + * If you wish your version of this file to be governed by only the CDDL
60.36 + * or only the GPL Version 2, indicate your decision by adding
60.37 + * "[Contributor] elects to include this software in this distribution
60.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
60.39 + * single choice of license, a recipient has the option to distribute
60.40 + * your version of this file under either the CDDL, the GPL Version 2 or
60.41 + * to extend the choice of license to its licensees as provided above.
60.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
60.43 + * Version 2 license, then the option applies only if the new code is
60.44 + * made subject to such option by the copyright holder.
60.45 + */
60.46 +package org.netbeans.html.boot.impl;
60.47 +
60.48 +import java.io.Closeable;
60.49 +import java.io.Reader;
60.50 +import java.net.URL;
60.51 +import java.net.URLClassLoader;
60.52 +import java.util.ArrayList;
60.53 +import java.util.Arrays;
60.54 +import java.util.Collection;
60.55 +import java.util.List;
60.56 +import javax.script.Invocable;
60.57 +import javax.script.ScriptEngine;
60.58 +import javax.script.ScriptEngineManager;
60.59 +import javax.script.ScriptException;
60.60 +import org.apidesign.html.boot.spi.Fn;
60.61 +import org.testng.annotations.BeforeClass;
60.62 +import org.testng.annotations.BeforeMethod;
60.63 +
60.64 +/**
60.65 + *
60.66 + * @author Jaroslav Tulach <jtulach@netbeans.org>
60.67 + */
60.68 +public class FnTest extends JsClassLoaderBase {
60.69 + private static Fn.Presenter presenter;
60.70 +
60.71 + public FnTest() {
60.72 + }
60.73 +
60.74 + @BeforeClass
60.75 + public static void createClassLoader() throws Exception {
60.76 + ScriptEngineManager sem = new ScriptEngineManager();
60.77 + final ScriptEngine eng = sem.getEngineByMimeType("text/javascript");
60.78 +
60.79 + final URL my = FnTest.class.getProtectionDomain().getCodeSource().getLocation();
60.80 + ClassLoader parent = JsClassLoaderTest.class.getClassLoader().getParent();
60.81 + final URLClassLoader ul = new URLClassLoader(new URL[] { my }, parent);
60.82 +
60.83 + class Impl implements FindResources, Fn.Presenter {
60.84 + @Override
60.85 + public void findResources(String path, Collection<? super URL> results, boolean oneIsEnough) {
60.86 + URL u = ul.findResource(path);
60.87 + if (u != null) {
60.88 + results.add(u);
60.89 + }
60.90 + }
60.91 +
60.92 + @Override
60.93 + public Fn defineFn(String code, String... names) {
60.94 + StringBuilder sb = new StringBuilder();
60.95 + sb.append("(function() {");
60.96 + sb.append("return function(");
60.97 + String sep = "";
60.98 + for (String n : names) {
60.99 + sb.append(sep);
60.100 + sb.append(n);
60.101 + sep = ", ";
60.102 + }
60.103 + sb.append(") {");
60.104 + sb.append(code);
60.105 + sb.append("};");
60.106 + sb.append("})()");
60.107 + try {
60.108 + final Object val = eng.eval(sb.toString());
60.109 + return new Fn(this) {
60.110 + @Override
60.111 + public Object invoke(Object thiz, Object... args) throws Exception {
60.112 + List<Object> all = new ArrayList<Object>(args.length + 1);
60.113 + all.add(thiz == null ? val : thiz);
60.114 + all.addAll(Arrays.asList(args));
60.115 + Invocable inv = (Invocable)eng;
60.116 + try {
60.117 + Object ret = inv.invokeMethod(val, "call", all.toArray());
60.118 + return val.equals(ret) ? null : ret;
60.119 + } catch (ScriptException ex) {
60.120 + throw ex;
60.121 + }
60.122 + }
60.123 + };
60.124 + } catch (ScriptException ex) {
60.125 + throw new LinkageError("Can't parse: " + sb, ex);
60.126 + }
60.127 + }
60.128 +
60.129 + @Override
60.130 + public void displayPage(URL resource, Runnable r) {
60.131 + throw new UnsupportedOperationException();
60.132 + }
60.133 +
60.134 + @Override
60.135 + public void loadScript(Reader code) throws Exception {
60.136 + eng.eval(code);
60.137 + }
60.138 + }
60.139 + Impl impl = new Impl();
60.140 + ClassLoader loader = FnUtils.newLoader(impl, impl, parent);
60.141 + presenter = impl;
60.142 +
60.143 + Closeable close = FnContext.activate(impl);
60.144 + methodClass = loader.loadClass(JsMethods.class.getName());
60.145 + close.close();
60.146 + }
60.147 +
60.148 + @BeforeMethod public void initPresenter() {
60.149 + FnContext.currentPresenter(presenter);
60.150 + }
60.151 +}
61.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
61.2 +++ b/boot/src/test/java/org/netbeans/html/boot/impl/JavaScriptProcesorTest.java Tue Jan 07 08:21:57 2014 +0100
61.3 @@ -0,0 +1,129 @@
61.4 +/**
61.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
61.6 + *
61.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
61.8 + *
61.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
61.10 + * Other names may be trademarks of their respective owners.
61.11 + *
61.12 + * The contents of this file are subject to the terms of either the GNU
61.13 + * General Public License Version 2 only ("GPL") or the Common
61.14 + * Development and Distribution License("CDDL") (collectively, the
61.15 + * "License"). You may not use this file except in compliance with the
61.16 + * License. You can obtain a copy of the License at
61.17 + * http://www.netbeans.org/cddl-gplv2.html
61.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
61.19 + * specific language governing permissions and limitations under the
61.20 + * License. When distributing the software, include this License Header
61.21 + * Notice in each file and include the License file at
61.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
61.23 + * particular file as subject to the "Classpath" exception as provided
61.24 + * by Oracle in the GPL Version 2 section of the License file that
61.25 + * accompanied this code. If applicable, add the following below the
61.26 + * License Header, with the fields enclosed by brackets [] replaced by
61.27 + * your own identifying information:
61.28 + * "Portions Copyrighted [year] [name of copyright owner]"
61.29 + *
61.30 + * Contributor(s):
61.31 + *
61.32 + * The Original Software is NetBeans. The Initial Developer of the Original
61.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
61.34 + *
61.35 + * If you wish your version of this file to be governed by only the CDDL
61.36 + * or only the GPL Version 2, indicate your decision by adding
61.37 + * "[Contributor] elects to include this software in this distribution
61.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
61.39 + * single choice of license, a recipient has the option to distribute
61.40 + * your version of this file under either the CDDL, the GPL Version 2 or
61.41 + * to extend the choice of license to its licensees as provided above.
61.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
61.43 + * Version 2 license, then the option applies only if the new code is
61.44 + * made subject to such option by the copyright holder.
61.45 + */
61.46 +package org.netbeans.html.boot.impl;
61.47 +
61.48 +import java.io.IOException;
61.49 +import java.lang.reflect.Field;
61.50 +import java.lang.reflect.Method;
61.51 +import static org.testng.Assert.assertEquals;
61.52 +import static org.testng.Assert.assertTrue;
61.53 +import org.testng.annotations.Test;
61.54 +
61.55 +/**
61.56 + *
61.57 + * @author Jaroslav Tulach <jtulach@netbeans.org>
61.58 + */
61.59 +public class JavaScriptProcesorTest {
61.60 +
61.61 + @Test public void detectCallbackToNonExistingClass() throws IOException {
61.62 + String code = "package x.y.z;\n"
61.63 + + "import net.java.html.js.JavaScriptBody;\n"
61.64 + + "class X {\n"
61.65 + + " @JavaScriptBody(args={\"r\"}, javacall=true, body =\n"
61.66 + + " \"r.@java.lang.Runable::run()();\"\n" // typo
61.67 + + " )\n"
61.68 + + " private static native void callback(Runnable r);\n"
61.69 + + "}\n";
61.70 +
61.71 + Compile c = Compile.create("", code);
61.72 + c.assertErrors();
61.73 + c.assertError("java.lang.Runable"); // typo
61.74 + }
61.75 +
61.76 + @Test public void detectCallbackToNonExistingMethod() throws IOException {
61.77 + String code = "package x.y.z;\n"
61.78 + + "import net.java.html.js.JavaScriptBody;\n"
61.79 + + "class X {\n"
61.80 + + " @JavaScriptBody(args={\"r\"}, javacall=true, body =\n"
61.81 + + " \"r.@java.lang.Runnable::cancel()();\"\n"
61.82 + + " )\n"
61.83 + + " private static native void callback(Runnable r);\n"
61.84 + + "}\n";
61.85 +
61.86 + Compile c = Compile.create("", code);
61.87 + c.assertErrors();
61.88 + c.assertError("method cancel");
61.89 + }
61.90 +
61.91 + @Test public void detectCallbackToNonExistingParams() throws IOException {
61.92 + String code = "package x.y.z;\n"
61.93 + + "import net.java.html.js.JavaScriptBody;\n"
61.94 + + "class X {\n"
61.95 + + " @JavaScriptBody(args={\"r\"}, javacall=true, body =\n"
61.96 + + " \"r.@java.lang.Runnable::run(I)(10);\"\n"
61.97 + + " )\n"
61.98 + + " private static native void callback(Runnable r);\n"
61.99 + + "}\n";
61.100 +
61.101 + Compile c = Compile.create("", code);
61.102 + c.assertErrors();
61.103 + c.assertError("wrong parameters: (I)");
61.104 + }
61.105 +
61.106 + @Test public void objectTypeParamsAreOK() throws IOException {
61.107 + String code = "package x.y.z;\n"
61.108 + + "import net.java.html.js.JavaScriptBody;\n"
61.109 + + "class X {\n"
61.110 + + " @JavaScriptBody(args={\"r\"}, javacall=true, body =\n"
61.111 + + " \"r.@java.lang.Object::equals(Ljava/lang/Object;)(null);\"\n"
61.112 + + " )\n"
61.113 + + " private static native void testEqual(Object r);\n"
61.114 + + "}\n";
61.115 +
61.116 + Compile c = Compile.create("", code);
61.117 + c.assertNoErrors();
61.118 + }
61.119 +
61.120 + @Test public void generatesCallbacksThatReturnObject() throws Exception {
61.121 + Class<?> callbacksForTestPkg = Class.forName("org.netbeans.html.boot.impl.$JsCallbacks$");
61.122 + Method m = callbacksForTestPkg.getDeclaredMethod("java_lang_Runnable$run$", Runnable.class);
61.123 + assertEquals(m.getReturnType(), Object.class, "All methods always return object");
61.124 + }
61.125 +
61.126 + @Test public void hasInstanceField() throws Exception {
61.127 + Class<?> callbacksForTestPkg = Class.forName("org.netbeans.html.boot.impl.$JsCallbacks$");
61.128 + Field f = callbacksForTestPkg.getDeclaredField("VM");
61.129 + f.setAccessible(true);
61.130 + assertTrue(callbacksForTestPkg.isInstance(f.get(null)), "Singleton field VM");
61.131 + }
61.132 +}
62.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
62.2 +++ b/boot/src/test/java/org/netbeans/html/boot/impl/JsClassLoaderBase.java Tue Jan 07 08:21:57 2014 +0100
62.3 @@ -0,0 +1,201 @@
62.4 +/**
62.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
62.6 + *
62.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
62.8 + *
62.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
62.10 + * Other names may be trademarks of their respective owners.
62.11 + *
62.12 + * The contents of this file are subject to the terms of either the GNU
62.13 + * General Public License Version 2 only ("GPL") or the Common
62.14 + * Development and Distribution License("CDDL") (collectively, the
62.15 + * "License"). You may not use this file except in compliance with the
62.16 + * License. You can obtain a copy of the License at
62.17 + * http://www.netbeans.org/cddl-gplv2.html
62.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
62.19 + * specific language governing permissions and limitations under the
62.20 + * License. When distributing the software, include this License Header
62.21 + * Notice in each file and include the License file at
62.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
62.23 + * particular file as subject to the "Classpath" exception as provided
62.24 + * by Oracle in the GPL Version 2 section of the License file that
62.25 + * accompanied this code. If applicable, add the following below the
62.26 + * License Header, with the fields enclosed by brackets [] replaced by
62.27 + * your own identifying information:
62.28 + * "Portions Copyrighted [year] [name of copyright owner]"
62.29 + *
62.30 + * Contributor(s):
62.31 + *
62.32 + * The Original Software is NetBeans. The Initial Developer of the Original
62.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
62.34 + *
62.35 + * If you wish your version of this file to be governed by only the CDDL
62.36 + * or only the GPL Version 2, indicate your decision by adding
62.37 + * "[Contributor] elects to include this software in this distribution
62.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
62.39 + * single choice of license, a recipient has the option to distribute
62.40 + * your version of this file under either the CDDL, the GPL Version 2 or
62.41 + * to extend the choice of license to its licensees as provided above.
62.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
62.43 + * Version 2 license, then the option applies only if the new code is
62.44 + * made subject to such option by the copyright holder.
62.45 + */
62.46 +package org.netbeans.html.boot.impl;
62.47 +
62.48 +import java.lang.reflect.InvocationTargetException;
62.49 +import java.lang.reflect.Method;
62.50 +import java.lang.reflect.Modifier;
62.51 +import static org.testng.Assert.*;
62.52 +import org.testng.annotations.BeforeMethod;
62.53 +import org.testng.annotations.Test;
62.54 +
62.55 +/**
62.56 + *
62.57 + * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
62.58 + */
62.59 +public class JsClassLoaderBase {
62.60 + protected static Class<?> methodClass;
62.61 +
62.62 + public JsClassLoaderBase() {
62.63 + }
62.64 +
62.65 + @BeforeMethod
62.66 + public void assertClassDefined() {
62.67 + assertNotNull(methodClass, "BeforeClass set up code should provide methodClass");
62.68 + }
62.69 +
62.70 + @Test public void noParamMethod() throws Throwable {
62.71 + Method plus = methodClass.getMethod("fortyTwo");
62.72 + try {
62.73 + final Object val = plus.invoke(null);
62.74 + assertTrue(val instanceof Number, "A number returned " + val);
62.75 + assertEquals(((Number)val).intValue(), 42);
62.76 + } catch (InvocationTargetException ex) {
62.77 + throw ex.getTargetException();
62.78 + }
62.79 + }
62.80 +
62.81 + @Test public void testExecuteScript() throws Throwable {
62.82 + Method plus = methodClass.getMethod("plus", int.class, int.class);
62.83 + try {
62.84 + assertEquals(plus.invoke(null, 10, 20), 30);
62.85 + } catch (InvocationTargetException ex) {
62.86 + throw ex.getTargetException();
62.87 + }
62.88 + }
62.89 +
62.90 + @Test public void overloadedMethod() throws Throwable {
62.91 + Method plus = methodClass.getMethod("plus", int.class);
62.92 + try {
62.93 + assertEquals(plus.invoke(null, 10), 10);
62.94 + } catch (InvocationTargetException ex) {
62.95 + throw ex.getTargetException();
62.96 + }
62.97 + }
62.98 +
62.99 + @Test public void instanceMethod() throws Throwable {
62.100 + Method plus = methodClass.getMethod("plusInst", int.class);
62.101 + Object inst = methodClass.newInstance();
62.102 + try {
62.103 + assertEquals(plus.invoke(inst, 10), 10);
62.104 + } catch (InvocationTargetException ex) {
62.105 + throw ex.getTargetException();
62.106 + }
62.107 + }
62.108 +
62.109 + @Test public void staticThis() throws Throwable {
62.110 + Method st = methodClass.getMethod("staticThis");
62.111 + try {
62.112 + assertNull(st.invoke(null));
62.113 + } catch (InvocationTargetException ex) {
62.114 + throw ex.getTargetException();
62.115 + }
62.116 + }
62.117 +
62.118 + @Test public void getThis() throws Throwable {
62.119 + Object th = methodClass.newInstance();
62.120 + Method st = methodClass.getMethod("getThis");
62.121 + try {
62.122 + assertEquals(st.invoke(th), th);
62.123 + } catch (InvocationTargetException ex) {
62.124 + throw ex.getTargetException();
62.125 + }
62.126 + }
62.127 +
62.128 + @Test public void truth() throws Throwable {
62.129 + Method st = methodClass.getMethod("truth");
62.130 + assertTrue((st.getModifiers() & Modifier.STATIC) != 0, "Is static");
62.131 + assertEquals(st.invoke(null), Boolean.TRUE, "Can return boolean");
62.132 + }
62.133 +
62.134 + @Test public void callback() throws Throwable {
62.135 + class R implements Runnable {
62.136 + int cnt;
62.137 +
62.138 + @Override
62.139 + public void run() {
62.140 + cnt++;
62.141 + }
62.142 + }
62.143 + R r = new R();
62.144 +
62.145 + Method inc = methodClass.getMethod("callback", Runnable.class);
62.146 + inc.invoke(null, r);
62.147 +
62.148 + assertEquals(r.cnt, 1, "Callback happened");
62.149 + }
62.150 +
62.151 + @Test public void sumArray() throws Throwable {
62.152 + Method st = methodClass.getMethod("sumArr", int[].class);
62.153 + assertEquals(st.invoke(null, new int[] { 1, 2, 3 }), 6, "1+2+3 is six");
62.154 + }
62.155 +
62.156 + @Test public void javaScriptResource() throws Throwable {
62.157 + try {
62.158 + Method st = methodClass.getMethod("useExternalMul", int.class, int.class);
62.159 + assertEquals(st.invoke(null, 6, 7), 42, "Meaning of JavaScript?");
62.160 + } catch (InvocationTargetException ex) {
62.161 + throw ex.getTargetException();
62.162 + }
62.163 + }
62.164 +
62.165 + @Test public void callJavaScriptMethodOnOwnClass() throws Throwable {
62.166 + try {
62.167 + Object thiz = methodClass.newInstance();
62.168 + Method st = methodClass.getMethod("returnYourSelf", methodClass);
62.169 + assertEquals(st.invoke(null, thiz), thiz, "Returns this");
62.170 + } catch (InvocationTargetException ex) {
62.171 + throw ex.getTargetException();
62.172 + }
62.173 + }
62.174 +
62.175 + @Test public void callStaticJavaMethod() throws Throwable {
62.176 + Method st = methodClass.getMethod("staticCallback", int.class, int.class);
62.177 + assertEquals(st.invoke(null, 6, 7), 42, "Meaning of JavaScript?");
62.178 + }
62.179 +
62.180 + @Test public void callStaticStringParamMethod() throws Throwable {
62.181 + Method st = methodClass.getMethod("parseInt", String.class);
62.182 + assertEquals(st.invoke(null, "42"), 42, "Meaning of JavaScript?");
62.183 + }
62.184 +
62.185 + @Test public void firstLong() throws Throwable {
62.186 + Method st = methodClass.getMethod("chooseLong", boolean.class, boolean.class, long.class, long.class);
62.187 + assertEquals(st.invoke(null, true, false, 10, 20), 10L, "Take first value");
62.188 + }
62.189 +
62.190 + @Test public void secondLong() throws Throwable {
62.191 + Method st = methodClass.getMethod("chooseLong", boolean.class, boolean.class, long.class, long.class);
62.192 + assertEquals(st.invoke(null, false, true, 10, 20), 20L, "Take 2nd value");
62.193 + }
62.194 +
62.195 + @Test public void bothLong() throws Throwable {
62.196 + Method st = methodClass.getMethod("chooseLong", boolean.class, boolean.class, long.class, long.class);
62.197 + assertEquals(st.invoke(null, true, true, 10, 20), 30L, "Take both values");
62.198 + }
62.199 +
62.200 + @Test public void recordError() throws Throwable {
62.201 + Method st = methodClass.getMethod("recordError", Object.class);
62.202 + assertEquals(st.invoke(methodClass.newInstance(), "Hello"), "Hello", "The same parameter returned");
62.203 + }
62.204 +}
62.205 \ No newline at end of file
63.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
63.2 +++ b/boot/src/test/java/org/netbeans/html/boot/impl/JsClassLoaderTest.java Tue Jan 07 08:21:57 2014 +0100
63.3 @@ -0,0 +1,155 @@
63.4 +/**
63.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
63.6 + *
63.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
63.8 + *
63.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
63.10 + * Other names may be trademarks of their respective owners.
63.11 + *
63.12 + * The contents of this file are subject to the terms of either the GNU
63.13 + * General Public License Version 2 only ("GPL") or the Common
63.14 + * Development and Distribution License("CDDL") (collectively, the
63.15 + * "License"). You may not use this file except in compliance with the
63.16 + * License. You can obtain a copy of the License at
63.17 + * http://www.netbeans.org/cddl-gplv2.html
63.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
63.19 + * specific language governing permissions and limitations under the
63.20 + * License. When distributing the software, include this License Header
63.21 + * Notice in each file and include the License file at
63.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
63.23 + * particular file as subject to the "Classpath" exception as provided
63.24 + * by Oracle in the GPL Version 2 section of the License file that
63.25 + * accompanied this code. If applicable, add the following below the
63.26 + * License Header, with the fields enclosed by brackets [] replaced by
63.27 + * your own identifying information:
63.28 + * "Portions Copyrighted [year] [name of copyright owner]"
63.29 + *
63.30 + * Contributor(s):
63.31 + *
63.32 + * The Original Software is NetBeans. The Initial Developer of the Original
63.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
63.34 + *
63.35 + * If you wish your version of this file to be governed by only the CDDL
63.36 + * or only the GPL Version 2, indicate your decision by adding
63.37 + * "[Contributor] elects to include this software in this distribution
63.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
63.39 + * single choice of license, a recipient has the option to distribute
63.40 + * your version of this file under either the CDDL, the GPL Version 2 or
63.41 + * to extend the choice of license to its licensees as provided above.
63.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
63.43 + * Version 2 license, then the option applies only if the new code is
63.44 + * made subject to such option by the copyright holder.
63.45 + */
63.46 +package org.netbeans.html.boot.impl;
63.47 +
63.48 +import java.io.Closeable;
63.49 +import java.io.Reader;
63.50 +import org.apidesign.html.boot.spi.Fn;
63.51 +import java.net.URL;
63.52 +import java.net.URLClassLoader;
63.53 +import java.util.ArrayList;
63.54 +import java.util.Arrays;
63.55 +import java.util.Enumeration;
63.56 +import java.util.List;
63.57 +import javax.script.Invocable;
63.58 +import javax.script.ScriptEngine;
63.59 +import javax.script.ScriptEngineManager;
63.60 +import javax.script.ScriptException;
63.61 +import org.testng.annotations.AfterClass;
63.62 +import org.testng.annotations.BeforeClass;
63.63 +import org.testng.annotations.BeforeMethod;
63.64 +
63.65 +/**
63.66 + *
63.67 + * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
63.68 + */
63.69 +public class JsClassLoaderTest extends JsClassLoaderBase{
63.70 + private static Fn.Presenter loader;
63.71 +
63.72 + @BeforeClass
63.73 + public static void setUpClass() throws Exception {
63.74 + ScriptEngineManager sem = new ScriptEngineManager();
63.75 + final ScriptEngine eng = sem.getEngineByMimeType("text/javascript");
63.76 +
63.77 + final URL my = JsClassLoaderTest.class.getProtectionDomain().getCodeSource().getLocation();
63.78 + ClassLoader parent = JsClassLoaderTest.class.getClassLoader().getParent();
63.79 + final URLClassLoader ul = new URLClassLoader(new URL[] { my }, parent);
63.80 + class MyCL extends JsClassLoader implements Fn.Presenter {
63.81 +
63.82 + public MyCL(ClassLoader parent) {
63.83 + super(parent);
63.84 + }
63.85 +
63.86 + @Override
63.87 + protected URL findResource(String name) {
63.88 + return ul.getResource(name);
63.89 + }
63.90 + @Override
63.91 + public Fn defineFn(String code, String... names) {
63.92 + StringBuilder sb = new StringBuilder();
63.93 + sb.append("(function() {");
63.94 + sb.append("return function(");
63.95 + String sep = "";
63.96 + for (String n : names) {
63.97 + sb.append(sep);
63.98 + sb.append(n);
63.99 + sep = ", ";
63.100 + }
63.101 + sb.append(") {");
63.102 + sb.append(code);
63.103 + sb.append("};");
63.104 + sb.append("})()");
63.105 + try {
63.106 + final Object val = eng.eval(sb.toString());
63.107 + return new Fn(this) {
63.108 + @Override
63.109 + public Object invoke(Object thiz, Object... args) throws Exception {
63.110 + List<Object> all = new ArrayList<Object>(args.length + 1);
63.111 + all.add(thiz == null ? val : thiz);
63.112 + all.addAll(Arrays.asList(args));
63.113 + Invocable inv = (Invocable)eng;
63.114 + try {
63.115 + Object ret = inv.invokeMethod(val, "call", all.toArray());
63.116 + return val.equals(ret) ? null : ret;
63.117 + } catch (Exception ex) {
63.118 + throw ex;
63.119 + }
63.120 + }
63.121 + };
63.122 + } catch (ScriptException ex) {
63.123 + throw new LinkageError("Can't parse: " + sb, ex);
63.124 + }
63.125 + }
63.126 +
63.127 + @Override
63.128 + protected Enumeration<URL> findResources(String name) {
63.129 + throw new UnsupportedOperationException();
63.130 + }
63.131 +
63.132 + @Override
63.133 + public void loadScript(Reader code) throws ScriptException {
63.134 + eng.eval(code);
63.135 + }
63.136 +
63.137 + @Override
63.138 + public void displayPage(URL page, Runnable onPageLoad) {
63.139 + throw new UnsupportedOperationException();
63.140 + }
63.141 + };
63.142 +
63.143 + MyCL l = new MyCL(parent);
63.144 + Closeable close = FnContext.activate(l);
63.145 + methodClass = l.loadClass(JsMethods.class.getName());
63.146 + close.close();
63.147 + loader = l;
63.148 + }
63.149 +
63.150 + @BeforeMethod public void initPresenter() {
63.151 + FnContext.currentPresenter(loader);
63.152 + }
63.153 +
63.154 + @AfterClass
63.155 + public static void cleanUp() {
63.156 + methodClass = null;
63.157 + }
63.158 +}
63.159 \ No newline at end of file
64.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
64.2 +++ b/boot/src/test/java/org/netbeans/html/boot/impl/JsMethods.java Tue Jan 07 08:21:57 2014 +0100
64.3 @@ -0,0 +1,129 @@
64.4 +/**
64.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
64.6 + *
64.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
64.8 + *
64.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
64.10 + * Other names may be trademarks of their respective owners.
64.11 + *
64.12 + * The contents of this file are subject to the terms of either the GNU
64.13 + * General Public License Version 2 only ("GPL") or the Common
64.14 + * Development and Distribution License("CDDL") (collectively, the
64.15 + * "License"). You may not use this file except in compliance with the
64.16 + * License. You can obtain a copy of the License at
64.17 + * http://www.netbeans.org/cddl-gplv2.html
64.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
64.19 + * specific language governing permissions and limitations under the
64.20 + * License. When distributing the software, include this License Header
64.21 + * Notice in each file and include the License file at
64.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
64.23 + * particular file as subject to the "Classpath" exception as provided
64.24 + * by Oracle in the GPL Version 2 section of the License file that
64.25 + * accompanied this code. If applicable, add the following below the
64.26 + * License Header, with the fields enclosed by brackets [] replaced by
64.27 + * your own identifying information:
64.28 + * "Portions Copyrighted [year] [name of copyright owner]"
64.29 + *
64.30 + * Contributor(s):
64.31 + *
64.32 + * The Original Software is NetBeans. The Initial Developer of the Original
64.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
64.34 + *
64.35 + * If you wish your version of this file to be governed by only the CDDL
64.36 + * or only the GPL Version 2, indicate your decision by adding
64.37 + * "[Contributor] elects to include this software in this distribution
64.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
64.39 + * single choice of license, a recipient has the option to distribute
64.40 + * your version of this file under either the CDDL, the GPL Version 2 or
64.41 + * to extend the choice of license to its licensees as provided above.
64.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
64.43 + * Version 2 license, then the option applies only if the new code is
64.44 + * made subject to such option by the copyright holder.
64.45 + */
64.46 +package org.netbeans.html.boot.impl;
64.47 +
64.48 +import net.java.html.js.JavaScriptBody;
64.49 +import net.java.html.js.JavaScriptResource;
64.50 +
64.51 +
64.52 +/**
64.53 + *
64.54 + * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
64.55 + */
64.56 +@JavaScriptResource("jsmethods.js")
64.57 +public class JsMethods {
64.58 + private Object value;
64.59 +
64.60 + @JavaScriptBody(args = {}, body = "return 42;")
64.61 + public static Object fortyTwo() {
64.62 + return -42;
64.63 + }
64.64 +
64.65 + @JavaScriptBody(args = {"x", "y" }, body = "return x + y;")
64.66 + public static native int plus(int x, int y);
64.67 +
64.68 + @JavaScriptBody(args = {"x"}, body = "return x;")
64.69 + public static native int plus(int x);
64.70 +
64.71 + @JavaScriptBody(args = {}, body = "return this;")
64.72 + public static native Object staticThis();
64.73 +
64.74 + @JavaScriptBody(args = {}, body = "return this;")
64.75 + public native Object getThis();
64.76 + @JavaScriptBody(args = {"x"}, body = "return x;")
64.77 + public native int plusInst(int x);
64.78 +
64.79 + @JavaScriptBody(args = {}, body = "return true;")
64.80 + public static boolean truth() {
64.81 + return false;
64.82 + }
64.83 +
64.84 + @JavaScriptBody(args = { "r" }, javacall=true, body = "r.@java.lang.Runnable::run()();")
64.85 + public static native void callback(Runnable r);
64.86 +
64.87 + @JavaScriptBody(args = { "at", "arr" }, javacall = true, body =
64.88 + "var a = 0;\n"
64.89 + + "for (var i = 0; i < arr.length; i++) {\n"
64.90 + + " a = at.@org.netbeans.html.boot.impl.Arithm::sumTwo(II)(a, arr[i]);\n"
64.91 + + "}\n"
64.92 + + "return a;"
64.93 + )
64.94 + private static native int sumArr(Arithm at, int... arr);
64.95 +
64.96 + public static int sumArr(int... arr) {
64.97 + return sumArr(new Arithm(), arr);
64.98 + }
64.99 +
64.100 + @JavaScriptBody(args = { "x", "y" }, body = "return mul(x, y);")
64.101 + public static native int useExternalMul(int x, int y);
64.102 +
64.103 + @JavaScriptBody(args = { "m" }, javacall = true, body = "return m.@org.netbeans.html.boot.impl.JsMethods::getThis()();")
64.104 + public static native JsMethods returnYourSelf(JsMethods m);
64.105 +
64.106 + @JavaScriptBody(args = { "x", "y" }, javacall = true, body = "return @org.netbeans.html.boot.impl.JsMethods::useExternalMul(II)(x, y);")
64.107 + public static native int staticCallback(int x, int y);
64.108 +
64.109 + @JavaScriptBody(args = { "v" }, javacall = true, body = "return @java.lang.Integer::parseInt(Ljava/lang/String;)(v);")
64.110 + public static native int parseInt(String v);
64.111 +
64.112 + @JavaScriptBody(args = { "useA", "useB", "a", "b" }, body = "var l = 0;"
64.113 + + "if (useA) l += a;\n"
64.114 + + "if (useB) l += b;\n"
64.115 + + "return l;\n"
64.116 + )
64.117 + public static native long chooseLong(boolean useA, boolean useB, long a, long b);
64.118 +
64.119 + protected void onError(Object o) throws Exception {
64.120 + value = o;
64.121 + }
64.122 +
64.123 + Object getError() {
64.124 + return value;
64.125 + }
64.126 +
64.127 + @JavaScriptBody(args = { "err" }, javacall = true, body =
64.128 + "this.@org.netbeans.html.boot.impl.JsMethods::onError(Ljava/lang/Object;)(err);"
64.129 + + "return this.@org.netbeans.html.boot.impl.JsMethods::getError()();"
64.130 + )
64.131 + public native Object recordError(Object err);
64.132 +}
65.1 --- a/boot/src/test/resources/org/apidesign/html/boot/impl/jsmethods.js Thu Dec 19 17:11:01 2013 +0100
65.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
65.3 @@ -1,22 +0,0 @@
65.4 -/*
65.5 - * HTML via Java(tm) Language Bindings
65.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
65.7 - *
65.8 - * This program is free software: you can redistribute it and/or modify
65.9 - * it under the terms of the GNU General Public License as published by
65.10 - * the Free Software Foundation, version 2 of the License.
65.11 - *
65.12 - * This program is distributed in the hope that it will be useful,
65.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
65.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
65.15 - * GNU General Public License for more details. apidesign.org
65.16 - * designates this particular file as subject to the
65.17 - * "Classpath" exception as provided by apidesign.org
65.18 - * in the License file that accompanied this code.
65.19 - *
65.20 - * You should have received a copy of the GNU General Public License
65.21 - * along with this program. Look for COPYING file in the top folder.
65.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
65.23 - */
65.24 -
65.25 -function mul(x, y) { return x * y; }
66.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
66.2 +++ b/boot/src/test/resources/org/netbeans/html/boot/impl/jsmethods.js Tue Jan 07 08:21:57 2014 +0100
66.3 @@ -0,0 +1,43 @@
66.4 +/*
66.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
66.6 + *
66.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
66.8 + *
66.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
66.10 + * Other names may be trademarks of their respective owners.
66.11 + *
66.12 + * The contents of this file are subject to the terms of either the GNU
66.13 + * General Public License Version 2 only ("GPL") or the Common
66.14 + * Development and Distribution License("CDDL") (collectively, the
66.15 + * "License"). You may not use this file except in compliance with the
66.16 + * License. You can obtain a copy of the License at
66.17 + * http://www.netbeans.org/cddl-gplv2.html
66.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
66.19 + * specific language governing permissions and limitations under the
66.20 + * License. When distributing the software, include this License Header
66.21 + * Notice in each file and include the License file at
66.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
66.23 + * particular file as subject to the "Classpath" exception as provided
66.24 + * by Oracle in the GPL Version 2 section of the License file that
66.25 + * accompanied this code. If applicable, add the following below the
66.26 + * License Header, with the fields enclosed by brackets [] replaced by
66.27 + * your own identifying information:
66.28 + * "Portions Copyrighted [year] [name of copyright owner]"
66.29 + *
66.30 + * Contributor(s):
66.31 + *
66.32 + * The Original Software is NetBeans. The Initial Developer of the Original
66.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
66.34 + *
66.35 + * If you wish your version of this file to be governed by only the CDDL
66.36 + * or only the GPL Version 2, indicate your decision by adding
66.37 + * "[Contributor] elects to include this software in this distribution
66.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
66.39 + * single choice of license, a recipient has the option to distribute
66.40 + * your version of this file under either the CDDL, the GPL Version 2 or
66.41 + * to extend the choice of license to its licensees as provided above.
66.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
66.43 + * Version 2 license, then the option applies only if the new code is
66.44 + * made subject to such option by the copyright holder.
66.45 + */
66.46 +function mul(x, y) { return x * y; }
67.1 --- a/context/pom.xml Thu Dec 19 17:11:01 2013 +0100
67.2 +++ b/context/pom.xml Tue Jan 07 08:21:57 2014 +0100
67.3 @@ -2,11 +2,11 @@
67.4 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
67.5 <modelVersion>4.0.0</modelVersion>
67.6 <parent>
67.7 - <groupId>org.apidesign</groupId>
67.8 - <artifactId>html</artifactId>
67.9 + <groupId>org.netbeans.html</groupId>
67.10 + <artifactId>pom</artifactId>
67.11 <version>0.7-SNAPSHOT</version>
67.12 </parent>
67.13 - <groupId>org.apidesign.html</groupId>
67.14 + <groupId>org.netbeans.html</groupId>
67.15 <artifactId>net.java.html</artifactId>
67.16 <version>0.7-SNAPSHOT</version>
67.17 <packaging>bundle</packaging>
68.1 --- a/context/src/main/java/net/java/html/BrwsrCtx.java Thu Dec 19 17:11:01 2013 +0100
68.2 +++ b/context/src/main/java/net/java/html/BrwsrCtx.java Tue Jan 07 08:21:57 2014 +0100
68.3 @@ -1,29 +1,51 @@
68.4 /**
68.5 - * HTML via Java(tm) Language Bindings
68.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
68.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
68.8 *
68.9 - * This program is free software: you can redistribute it and/or modify
68.10 - * it under the terms of the GNU General Public License as published by
68.11 - * the Free Software Foundation, version 2 of the License.
68.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
68.13 *
68.14 - * This program is distributed in the hope that it will be useful,
68.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
68.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
68.17 - * GNU General Public License for more details. apidesign.org
68.18 - * designates this particular file as subject to the
68.19 - * "Classpath" exception as provided by apidesign.org
68.20 - * in the License file that accompanied this code.
68.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
68.22 + * Other names may be trademarks of their respective owners.
68.23 *
68.24 - * You should have received a copy of the GNU General Public License
68.25 - * along with this program. Look for COPYING file in the top folder.
68.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
68.27 + * The contents of this file are subject to the terms of either the GNU
68.28 + * General Public License Version 2 only ("GPL") or the Common
68.29 + * Development and Distribution License("CDDL") (collectively, the
68.30 + * "License"). You may not use this file except in compliance with the
68.31 + * License. You can obtain a copy of the License at
68.32 + * http://www.netbeans.org/cddl-gplv2.html
68.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
68.34 + * specific language governing permissions and limitations under the
68.35 + * License. When distributing the software, include this License Header
68.36 + * Notice in each file and include the License file at
68.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
68.38 + * particular file as subject to the "Classpath" exception as provided
68.39 + * by Oracle in the GPL Version 2 section of the License file that
68.40 + * accompanied this code. If applicable, add the following below the
68.41 + * License Header, with the fields enclosed by brackets [] replaced by
68.42 + * your own identifying information:
68.43 + * "Portions Copyrighted [year] [name of copyright owner]"
68.44 + *
68.45 + * Contributor(s):
68.46 + *
68.47 + * The Original Software is NetBeans. The Initial Developer of the Original
68.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
68.49 + *
68.50 + * If you wish your version of this file to be governed by only the CDDL
68.51 + * or only the GPL Version 2, indicate your decision by adding
68.52 + * "[Contributor] elects to include this software in this distribution
68.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
68.54 + * single choice of license, a recipient has the option to distribute
68.55 + * your version of this file under either the CDDL, the GPL Version 2 or
68.56 + * to extend the choice of license to its licensees as provided above.
68.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
68.58 + * Version 2 license, then the option applies only if the new code is
68.59 + * made subject to such option by the copyright holder.
68.60 */
68.61 package net.java.html;
68.62
68.63 import java.util.ServiceLoader;
68.64 import java.util.logging.Logger;
68.65 -import org.apidesign.html.context.impl.CtxAccssr;
68.66 -import org.apidesign.html.context.impl.CtxImpl;
68.67 +import org.netbeans.html.context.impl.CtxAccssr;
68.68 +import org.netbeans.html.context.impl.CtxImpl;
68.69 import org.apidesign.html.context.spi.Contexts;
68.70
68.71 /** Represents context where the <code>net.java.html.json.Model</code>
69.1 --- a/context/src/main/java/org/apidesign/html/context/impl/CtxAccssr.java Thu Dec 19 17:11:01 2013 +0100
69.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
69.3 @@ -1,52 +0,0 @@
69.4 -/**
69.5 - * HTML via Java(tm) Language Bindings
69.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
69.7 - *
69.8 - * This program is free software: you can redistribute it and/or modify
69.9 - * it under the terms of the GNU General Public License as published by
69.10 - * the Free Software Foundation, version 2 of the License.
69.11 - *
69.12 - * This program is distributed in the hope that it will be useful,
69.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
69.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
69.15 - * GNU General Public License for more details. apidesign.org
69.16 - * designates this particular file as subject to the
69.17 - * "Classpath" exception as provided by apidesign.org
69.18 - * in the License file that accompanied this code.
69.19 - *
69.20 - * You should have received a copy of the GNU General Public License
69.21 - * along with this program. Look for COPYING file in the top folder.
69.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
69.23 - */
69.24 -package org.apidesign.html.context.impl;
69.25 -
69.26 -import net.java.html.BrwsrCtx;
69.27 -
69.28 -/** Internal communication between API (e.g. {@link BrwsrCtx}), SPI
69.29 - * (e.g. {@link ContextBuilder}) and the implementation package.
69.30 - *
69.31 - * @author Jaroslav Tulach <jtulach@netbeans.org>
69.32 - */
69.33 -public abstract class CtxAccssr {
69.34 - private static CtxAccssr DEFAULT;
69.35 - static {
69.36 - // run initializers
69.37 - try {
69.38 - BrwsrCtx.EMPTY.getClass();
69.39 - } catch (NullPointerException ex) {
69.40 - // ignore
69.41 - }
69.42 - }
69.43 -
69.44 - protected CtxAccssr() {
69.45 - if (DEFAULT != null) throw new IllegalStateException();
69.46 - DEFAULT = this;
69.47 - }
69.48 -
69.49 - protected abstract BrwsrCtx newContext(CtxImpl impl);
69.50 - protected abstract CtxImpl find(BrwsrCtx context);
69.51 -
69.52 - static CtxAccssr getDefault() {
69.53 - return DEFAULT;
69.54 - }
69.55 -}
70.1 --- a/context/src/main/java/org/apidesign/html/context/impl/CtxImpl.java Thu Dec 19 17:11:01 2013 +0100
70.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
70.3 @@ -1,88 +0,0 @@
70.4 -/**
70.5 - * HTML via Java(tm) Language Bindings
70.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
70.7 - *
70.8 - * This program is free software: you can redistribute it and/or modify
70.9 - * it under the terms of the GNU General Public License as published by
70.10 - * the Free Software Foundation, version 2 of the License.
70.11 - *
70.12 - * This program is distributed in the hope that it will be useful,
70.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
70.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
70.15 - * GNU General Public License for more details. apidesign.org
70.16 - * designates this particular file as subject to the
70.17 - * "Classpath" exception as provided by apidesign.org
70.18 - * in the License file that accompanied this code.
70.19 - *
70.20 - * You should have received a copy of the GNU General Public License
70.21 - * along with this program. Look for COPYING file in the top folder.
70.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
70.23 - */
70.24 -package org.apidesign.html.context.impl;
70.25 -
70.26 -import java.util.ArrayList;
70.27 -import java.util.Collections;
70.28 -import java.util.List;
70.29 -import net.java.html.BrwsrCtx;
70.30 -
70.31 -/** Implementation detail. Holds list of technologies for particular
70.32 - * {@link BrwsrCtx}.
70.33 - *
70.34 - * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
70.35 - */
70.36 -public final class CtxImpl {
70.37 - private final List<Bind<?>> techs;
70.38 -
70.39 - public CtxImpl() {
70.40 - techs = new ArrayList<Bind<?>>();
70.41 - }
70.42 -
70.43 - private CtxImpl(List<Bind<?>> techs) {
70.44 - this.techs = techs;
70.45 - }
70.46 -
70.47 - public static <Tech> Tech find(BrwsrCtx context, Class<Tech> technology) {
70.48 - CtxImpl impl = CtxAccssr.getDefault().find(context);
70.49 - for (Bind<?> bind : impl.techs) {
70.50 - if (technology == bind.clazz) {
70.51 - return technology.cast(bind.impl);
70.52 - }
70.53 - }
70.54 - return null;
70.55 - }
70.56 -
70.57 - public BrwsrCtx build() {
70.58 - Collections.sort(techs);
70.59 - CtxImpl impl = new CtxImpl(Collections.unmodifiableList(techs));
70.60 - return CtxAccssr.getDefault().newContext(impl);
70.61 - }
70.62 -
70.63 - public <Tech> void register(Class<Tech> type, Tech impl, int priority) {
70.64 - techs.add(new Bind<Tech>(type, impl, priority));
70.65 - }
70.66 -
70.67 - private static final class Bind<Tech> implements Comparable<Bind<?>> {
70.68 - private final Class<Tech> clazz;
70.69 - private final Tech impl;
70.70 - private final int priority;
70.71 -
70.72 - public Bind(Class<Tech> clazz, Tech impl, int priority) {
70.73 - this.clazz = clazz;
70.74 - this.impl = impl;
70.75 - this.priority = priority;
70.76 - }
70.77 -
70.78 - @Override
70.79 - public int compareTo(Bind<?> o) {
70.80 - if (priority != o.priority) {
70.81 - return priority - o.priority;
70.82 - }
70.83 - return clazz.getName().compareTo(o.clazz.getName());
70.84 - }
70.85 -
70.86 - @Override
70.87 - public String toString() {
70.88 - return "Bind{" + "clazz=" + clazz + "@" + clazz.getClassLoader() + ", impl=" + impl + ", priority=" + priority + '}';
70.89 - }
70.90 - }
70.91 -}
71.1 --- a/context/src/main/java/org/apidesign/html/context/spi/Contexts.java Thu Dec 19 17:11:01 2013 +0100
71.2 +++ b/context/src/main/java/org/apidesign/html/context/spi/Contexts.java Tue Jan 07 08:21:57 2014 +0100
71.3 @@ -1,27 +1,49 @@
71.4 /**
71.5 - * HTML via Java(tm) Language Bindings
71.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
71.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
71.8 *
71.9 - * This program is free software: you can redistribute it and/or modify
71.10 - * it under the terms of the GNU General Public License as published by
71.11 - * the Free Software Foundation, version 2 of the License.
71.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
71.13 *
71.14 - * This program is distributed in the hope that it will be useful,
71.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
71.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
71.17 - * GNU General Public License for more details. apidesign.org
71.18 - * designates this particular file as subject to the
71.19 - * "Classpath" exception as provided by apidesign.org
71.20 - * in the License file that accompanied this code.
71.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
71.22 + * Other names may be trademarks of their respective owners.
71.23 *
71.24 - * You should have received a copy of the GNU General Public License
71.25 - * along with this program. Look for COPYING file in the top folder.
71.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
71.27 + * The contents of this file are subject to the terms of either the GNU
71.28 + * General Public License Version 2 only ("GPL") or the Common
71.29 + * Development and Distribution License("CDDL") (collectively, the
71.30 + * "License"). You may not use this file except in compliance with the
71.31 + * License. You can obtain a copy of the License at
71.32 + * http://www.netbeans.org/cddl-gplv2.html
71.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
71.34 + * specific language governing permissions and limitations under the
71.35 + * License. When distributing the software, include this License Header
71.36 + * Notice in each file and include the License file at
71.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
71.38 + * particular file as subject to the "Classpath" exception as provided
71.39 + * by Oracle in the GPL Version 2 section of the License file that
71.40 + * accompanied this code. If applicable, add the following below the
71.41 + * License Header, with the fields enclosed by brackets [] replaced by
71.42 + * your own identifying information:
71.43 + * "Portions Copyrighted [year] [name of copyright owner]"
71.44 + *
71.45 + * Contributor(s):
71.46 + *
71.47 + * The Original Software is NetBeans. The Initial Developer of the Original
71.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
71.49 + *
71.50 + * If you wish your version of this file to be governed by only the CDDL
71.51 + * or only the GPL Version 2, indicate your decision by adding
71.52 + * "[Contributor] elects to include this software in this distribution
71.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
71.54 + * single choice of license, a recipient has the option to distribute
71.55 + * your version of this file under either the CDDL, the GPL Version 2 or
71.56 + * to extend the choice of license to its licensees as provided above.
71.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
71.58 + * Version 2 license, then the option applies only if the new code is
71.59 + * made subject to such option by the copyright holder.
71.60 */
71.61 package org.apidesign.html.context.spi;
71.62
71.63 import net.java.html.BrwsrCtx;
71.64 -import org.apidesign.html.context.impl.CtxImpl;
71.65 +import org.netbeans.html.context.impl.CtxImpl;
71.66
71.67 /**
71.68 *
72.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
72.2 +++ b/context/src/main/java/org/netbeans/html/context/impl/CtxAccssr.java Tue Jan 07 08:21:57 2014 +0100
72.3 @@ -0,0 +1,74 @@
72.4 +/**
72.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
72.6 + *
72.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
72.8 + *
72.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
72.10 + * Other names may be trademarks of their respective owners.
72.11 + *
72.12 + * The contents of this file are subject to the terms of either the GNU
72.13 + * General Public License Version 2 only ("GPL") or the Common
72.14 + * Development and Distribution License("CDDL") (collectively, the
72.15 + * "License"). You may not use this file except in compliance with the
72.16 + * License. You can obtain a copy of the License at
72.17 + * http://www.netbeans.org/cddl-gplv2.html
72.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
72.19 + * specific language governing permissions and limitations under the
72.20 + * License. When distributing the software, include this License Header
72.21 + * Notice in each file and include the License file at
72.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
72.23 + * particular file as subject to the "Classpath" exception as provided
72.24 + * by Oracle in the GPL Version 2 section of the License file that
72.25 + * accompanied this code. If applicable, add the following below the
72.26 + * License Header, with the fields enclosed by brackets [] replaced by
72.27 + * your own identifying information:
72.28 + * "Portions Copyrighted [year] [name of copyright owner]"
72.29 + *
72.30 + * Contributor(s):
72.31 + *
72.32 + * The Original Software is NetBeans. The Initial Developer of the Original
72.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
72.34 + *
72.35 + * If you wish your version of this file to be governed by only the CDDL
72.36 + * or only the GPL Version 2, indicate your decision by adding
72.37 + * "[Contributor] elects to include this software in this distribution
72.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
72.39 + * single choice of license, a recipient has the option to distribute
72.40 + * your version of this file under either the CDDL, the GPL Version 2 or
72.41 + * to extend the choice of license to its licensees as provided above.
72.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
72.43 + * Version 2 license, then the option applies only if the new code is
72.44 + * made subject to such option by the copyright holder.
72.45 + */
72.46 +package org.netbeans.html.context.impl;
72.47 +
72.48 +import net.java.html.BrwsrCtx;
72.49 +
72.50 +/** Internal communication between API (e.g. {@link BrwsrCtx}), SPI
72.51 + * (e.g. {@link ContextBuilder}) and the implementation package.
72.52 + *
72.53 + * @author Jaroslav Tulach <jtulach@netbeans.org>
72.54 + */
72.55 +public abstract class CtxAccssr {
72.56 + private static CtxAccssr DEFAULT;
72.57 + static {
72.58 + // run initializers
72.59 + try {
72.60 + BrwsrCtx.EMPTY.getClass();
72.61 + } catch (NullPointerException ex) {
72.62 + // ignore
72.63 + }
72.64 + }
72.65 +
72.66 + protected CtxAccssr() {
72.67 + if (DEFAULT != null) throw new IllegalStateException();
72.68 + DEFAULT = this;
72.69 + }
72.70 +
72.71 + protected abstract BrwsrCtx newContext(CtxImpl impl);
72.72 + protected abstract CtxImpl find(BrwsrCtx context);
72.73 +
72.74 + static CtxAccssr getDefault() {
72.75 + return DEFAULT;
72.76 + }
72.77 +}
73.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
73.2 +++ b/context/src/main/java/org/netbeans/html/context/impl/CtxImpl.java Tue Jan 07 08:21:57 2014 +0100
73.3 @@ -0,0 +1,110 @@
73.4 +/**
73.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
73.6 + *
73.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
73.8 + *
73.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
73.10 + * Other names may be trademarks of their respective owners.
73.11 + *
73.12 + * The contents of this file are subject to the terms of either the GNU
73.13 + * General Public License Version 2 only ("GPL") or the Common
73.14 + * Development and Distribution License("CDDL") (collectively, the
73.15 + * "License"). You may not use this file except in compliance with the
73.16 + * License. You can obtain a copy of the License at
73.17 + * http://www.netbeans.org/cddl-gplv2.html
73.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
73.19 + * specific language governing permissions and limitations under the
73.20 + * License. When distributing the software, include this License Header
73.21 + * Notice in each file and include the License file at
73.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
73.23 + * particular file as subject to the "Classpath" exception as provided
73.24 + * by Oracle in the GPL Version 2 section of the License file that
73.25 + * accompanied this code. If applicable, add the following below the
73.26 + * License Header, with the fields enclosed by brackets [] replaced by
73.27 + * your own identifying information:
73.28 + * "Portions Copyrighted [year] [name of copyright owner]"
73.29 + *
73.30 + * Contributor(s):
73.31 + *
73.32 + * The Original Software is NetBeans. The Initial Developer of the Original
73.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
73.34 + *
73.35 + * If you wish your version of this file to be governed by only the CDDL
73.36 + * or only the GPL Version 2, indicate your decision by adding
73.37 + * "[Contributor] elects to include this software in this distribution
73.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
73.39 + * single choice of license, a recipient has the option to distribute
73.40 + * your version of this file under either the CDDL, the GPL Version 2 or
73.41 + * to extend the choice of license to its licensees as provided above.
73.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
73.43 + * Version 2 license, then the option applies only if the new code is
73.44 + * made subject to such option by the copyright holder.
73.45 + */
73.46 +package org.netbeans.html.context.impl;
73.47 +
73.48 +import java.util.ArrayList;
73.49 +import java.util.Collections;
73.50 +import java.util.List;
73.51 +import net.java.html.BrwsrCtx;
73.52 +
73.53 +/** Implementation detail. Holds list of technologies for particular
73.54 + * {@link BrwsrCtx}.
73.55 + *
73.56 + * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
73.57 + */
73.58 +public final class CtxImpl {
73.59 + private final List<Bind<?>> techs;
73.60 +
73.61 + public CtxImpl() {
73.62 + techs = new ArrayList<Bind<?>>();
73.63 + }
73.64 +
73.65 + private CtxImpl(List<Bind<?>> techs) {
73.66 + this.techs = techs;
73.67 + }
73.68 +
73.69 + public static <Tech> Tech find(BrwsrCtx context, Class<Tech> technology) {
73.70 + CtxImpl impl = CtxAccssr.getDefault().find(context);
73.71 + for (Bind<?> bind : impl.techs) {
73.72 + if (technology == bind.clazz) {
73.73 + return technology.cast(bind.impl);
73.74 + }
73.75 + }
73.76 + return null;
73.77 + }
73.78 +
73.79 + public BrwsrCtx build() {
73.80 + Collections.sort(techs);
73.81 + CtxImpl impl = new CtxImpl(Collections.unmodifiableList(techs));
73.82 + return CtxAccssr.getDefault().newContext(impl);
73.83 + }
73.84 +
73.85 + public <Tech> void register(Class<Tech> type, Tech impl, int priority) {
73.86 + techs.add(new Bind<Tech>(type, impl, priority));
73.87 + }
73.88 +
73.89 + private static final class Bind<Tech> implements Comparable<Bind<?>> {
73.90 + private final Class<Tech> clazz;
73.91 + private final Tech impl;
73.92 + private final int priority;
73.93 +
73.94 + public Bind(Class<Tech> clazz, Tech impl, int priority) {
73.95 + this.clazz = clazz;
73.96 + this.impl = impl;
73.97 + this.priority = priority;
73.98 + }
73.99 +
73.100 + @Override
73.101 + public int compareTo(Bind<?> o) {
73.102 + if (priority != o.priority) {
73.103 + return priority - o.priority;
73.104 + }
73.105 + return clazz.getName().compareTo(o.clazz.getName());
73.106 + }
73.107 +
73.108 + @Override
73.109 + public String toString() {
73.110 + return "Bind{" + "clazz=" + clazz + "@" + clazz.getClassLoader() + ", impl=" + impl + ", priority=" + priority + '}';
73.111 + }
73.112 + }
73.113 +}
74.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
74.2 +++ b/equinox-agentclass-hook/pom.xml Tue Jan 07 08:21:57 2014 +0100
74.3 @@ -0,0 +1,42 @@
74.4 +<?xml version="1.0" encoding="UTF-8"?>
74.5 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
74.6 + <modelVersion>4.0.0</modelVersion>
74.7 + <parent>
74.8 + <groupId>org.netbeans.html</groupId>
74.9 + <artifactId>pom</artifactId>
74.10 + <version>0.7-SNAPSHOT</version>
74.11 + </parent>
74.12 + <name>AgentClass Hook for Equinox</name>
74.13 + <artifactId>equinox-agentclass-hook</artifactId>
74.14 + <packaging>bundle</packaging>
74.15 + <build>
74.16 + <plugins>
74.17 + <plugin>
74.18 + <groupId>org.apache.felix</groupId>
74.19 + <artifactId>maven-bundle-plugin</artifactId>
74.20 + <configuration>
74.21 + <instructions>
74.22 + <Fragment-Host>org.eclipse.osgi;bundle-version="[3.8.0,4.0)"</Fragment-Host>
74.23 + <Import-Package></Import-Package>
74.24 + </instructions>
74.25 + </configuration>
74.26 + </plugin>
74.27 + <plugin>
74.28 + <groupId>org.apache.maven.plugins</groupId>
74.29 + <artifactId>maven-compiler-plugin</artifactId>
74.30 + <version>2.3.2</version>
74.31 + <configuration>
74.32 + <source>1.5</source>
74.33 + <target>1.5</target>
74.34 + </configuration>
74.35 + </plugin>
74.36 + </plugins>
74.37 + </build>
74.38 + <dependencies>
74.39 + <dependency>
74.40 + <groupId>org.eclipse</groupId>
74.41 + <artifactId>org.eclipse.osgi</artifactId>
74.42 + <version>3.8.0.v20120529-1548</version>
74.43 + </dependency>
74.44 + </dependencies>
74.45 +</project>
74.46 \ No newline at end of file
75.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
75.2 +++ b/equinox-agentclass-hook/src/main/java/org/netbeans/html/equinox/agentclass/AgentHook.java Tue Jan 07 08:21:57 2014 +0100
75.3 @@ -0,0 +1,164 @@
75.4 +/**
75.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
75.6 + *
75.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
75.8 + *
75.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
75.10 + * Other names may be trademarks of their respective owners.
75.11 + *
75.12 + * The contents of this file are subject to the terms of either the GNU
75.13 + * General Public License Version 2 only ("GPL") or the Common
75.14 + * Development and Distribution License("CDDL") (collectively, the
75.15 + * "License"). You may not use this file except in compliance with the
75.16 + * License. You can obtain a copy of the License at
75.17 + * http://www.netbeans.org/cddl-gplv2.html
75.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
75.19 + * specific language governing permissions and limitations under the
75.20 + * License. When distributing the software, include this License Header
75.21 + * Notice in each file and include the License file at
75.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
75.23 + * particular file as subject to the "Classpath" exception as provided
75.24 + * by Oracle in the GPL Version 2 section of the License file that
75.25 + * accompanied this code. If applicable, add the following below the
75.26 + * License Header, with the fields enclosed by brackets [] replaced by
75.27 + * your own identifying information:
75.28 + * "Portions Copyrighted [year] [name of copyright owner]"
75.29 + *
75.30 + * Contributor(s):
75.31 + *
75.32 + * The Original Software is NetBeans. The Initial Developer of the Original
75.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
75.34 + *
75.35 + * If you wish your version of this file to be governed by only the CDDL
75.36 + * or only the GPL Version 2, indicate your decision by adding
75.37 + * "[Contributor] elects to include this software in this distribution
75.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
75.39 + * single choice of license, a recipient has the option to distribute
75.40 + * your version of this file under either the CDDL, the GPL Version 2 or
75.41 + * to extend the choice of license to its licensees as provided above.
75.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
75.43 + * Version 2 license, then the option applies only if the new code is
75.44 + * made subject to such option by the copyright holder.
75.45 + */
75.46 +package org.netbeans.html.equinox.agentclass;
75.47 +
75.48 +import java.lang.instrument.IllegalClassFormatException;
75.49 +import java.security.ProtectionDomain;
75.50 +import java.util.ArrayList;
75.51 +import java.util.logging.Logger;
75.52 +
75.53 +import org.eclipse.osgi.baseadaptor.BaseData;
75.54 +import org.eclipse.osgi.baseadaptor.HookConfigurator;
75.55 +import org.eclipse.osgi.baseadaptor.HookRegistry;
75.56 +import org.eclipse.osgi.baseadaptor.bundlefile.BundleEntry;
75.57 +import org.eclipse.osgi.baseadaptor.hooks.ClassLoadingHook;
75.58 +import org.eclipse.osgi.baseadaptor.loader.BaseClassLoader;
75.59 +import org.eclipse.osgi.baseadaptor.loader.ClasspathEntry;
75.60 +import org.eclipse.osgi.baseadaptor.loader.ClasspathManager;
75.61 +import org.eclipse.osgi.framework.adaptor.BundleProtectionDomain;
75.62 +import org.eclipse.osgi.framework.adaptor.BundleWatcher;
75.63 +import org.eclipse.osgi.framework.adaptor.ClassLoaderDelegate;
75.64 +import org.osgi.framework.Bundle;
75.65 +import org.osgi.framework.BundleContext;
75.66 +import org.osgi.framework.wiring.BundleWiring;
75.67 +
75.68 +public class AgentHook implements HookConfigurator, BundleWatcher, ClassLoadingHook {
75.69 + private static final Logger LOG = Logger.getLogger(AgentHook.class.getName());
75.70 + private boolean all;
75.71 +
75.72 + @Override
75.73 + public void addHooks(HookRegistry hookRegistry) {
75.74 + LOG.info("Agent hook for Equinox initialized!");
75.75 + hookRegistry.addWatcher(this);
75.76 + hookRegistry.addClassLoadingHook(this);
75.77 + }
75.78 +
75.79 + @Override
75.80 + public void watchBundle(Bundle bundle, int type) {
75.81 + if (!all) {
75.82 + BundleContext c = bundle.getBundleContext();
75.83 + if (c != null) {
75.84 + Bundle[] arr = bundle.getBundleContext().getBundles();
75.85 + for (Bundle b : arr) {
75.86 + agentBundle(b);
75.87 + }
75.88 + all = true;
75.89 + }
75.90 + }
75.91 + if (type == BundleWatcher.END_ACTIVATION) {
75.92 + agentBundle(bundle);
75.93 + }
75.94 + }
75.95 +
75.96 + private void agentBundle(Bundle bundle) {
75.97 + String agentClass = (String)bundle.getHeaders().get("Agent-Class");
75.98 + if (agentClass != null) {
75.99 + Class<?> agent;
75.100 + try {
75.101 + agent = bundle.loadClass(agentClass);
75.102 + NbInstrumentation.registerAgent(agent.getClassLoader(), agent.getName());
75.103 + } catch (ClassNotFoundException e) {
75.104 + throw new IllegalStateException(e);
75.105 + }
75.106 + }
75.107 + }
75.108 +
75.109 + @Override
75.110 + public byte[] processClass(String name, byte[] bytes,
75.111 + ClasspathEntry ce, BundleEntry entry,
75.112 + ClasspathManager manager) {
75.113 + final BaseData bd = ce.getBaseData();
75.114 + if (bd == null) {
75.115 + return bytes;
75.116 + }
75.117 + final Bundle b = bd.getBundle();
75.118 + if (b == null) {
75.119 + return bytes;
75.120 + }
75.121 + BundleWiring w = (BundleWiring)b.adapt(BundleWiring.class);
75.122 + if (w == null) {
75.123 + return bytes;
75.124 + }
75.125 + ClassLoader loader = w.getClassLoader();
75.126 + try {
75.127 + return NbInstrumentation.patchByteCode(loader, name, ce.getDomain(), bytes);
75.128 + } catch (IllegalClassFormatException e) {
75.129 + return bytes;
75.130 + }
75.131 + }
75.132 +
75.133 + @Override
75.134 + public boolean addClassPathEntry(ArrayList cpEntries,
75.135 + String cp, ClasspathManager hostmanager, BaseData sourcedata,
75.136 + ProtectionDomain sourcedomain) {
75.137 + // TODO Auto-generated method stub
75.138 + return false;
75.139 + }
75.140 +
75.141 + @Override
75.142 + public String findLibrary(BaseData data, String libName) {
75.143 + // TODO Auto-generated method stub
75.144 + return null;
75.145 + }
75.146 +
75.147 + @Override
75.148 + public ClassLoader getBundleClassLoaderParent() {
75.149 + // TODO Auto-generated method stub
75.150 + return null;
75.151 + }
75.152 +
75.153 + @Override
75.154 + public BaseClassLoader createClassLoader(ClassLoader parent,
75.155 + ClassLoaderDelegate delegate, BundleProtectionDomain domain,
75.156 + BaseData data, String[] bundleclasspath) {
75.157 + // TODO Auto-generated method stub
75.158 + return null;
75.159 + }
75.160 +
75.161 + @Override
75.162 + public void initializedClassLoader(BaseClassLoader baseClassLoader,
75.163 + BaseData data) {
75.164 + // TODO Auto-generated method stub
75.165 +
75.166 + }
75.167 +}
76.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
76.2 +++ b/equinox-agentclass-hook/src/main/java/org/netbeans/html/equinox/agentclass/NbInstrumentation.java Tue Jan 07 08:21:57 2014 +0100
76.3 @@ -0,0 +1,214 @@
76.4 +/**
76.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
76.6 + *
76.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
76.8 + *
76.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
76.10 + * Other names may be trademarks of their respective owners.
76.11 + *
76.12 + * The contents of this file are subject to the terms of either the GNU
76.13 + * General Public License Version 2 only ("GPL") or the Common
76.14 + * Development and Distribution License("CDDL") (collectively, the
76.15 + * "License"). You may not use this file except in compliance with the
76.16 + * License. You can obtain a copy of the License at
76.17 + * http://www.netbeans.org/cddl-gplv2.html
76.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
76.19 + * specific language governing permissions and limitations under the
76.20 + * License. When distributing the software, include this License Header
76.21 + * Notice in each file and include the License file at
76.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
76.23 + * particular file as subject to the "Classpath" exception as provided
76.24 + * by Oracle in the GPL Version 2 section of the License file that
76.25 + * accompanied this code. If applicable, add the following below the
76.26 + * License Header, with the fields enclosed by brackets [] replaced by
76.27 + * your own identifying information:
76.28 + * "Portions Copyrighted [year] [name of copyright owner]"
76.29 + *
76.30 + * Contributor(s):
76.31 + *
76.32 + * The Original Software is NetBeans. The Initial Developer of the Original
76.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
76.34 + *
76.35 + * If you wish your version of this file to be governed by only the CDDL
76.36 + * or only the GPL Version 2, indicate your decision by adding
76.37 + * "[Contributor] elects to include this software in this distribution
76.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
76.39 + * single choice of license, a recipient has the option to distribute
76.40 + * your version of this file under either the CDDL, the GPL Version 2 or
76.41 + * to extend the choice of license to its licensees as provided above.
76.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
76.43 + * Version 2 license, then the option applies only if the new code is
76.44 + * made subject to such option by the copyright holder.
76.45 + */
76.46 +
76.47 +package org.netbeans.html.equinox.agentclass;
76.48 +
76.49 +import java.lang.instrument.ClassDefinition;
76.50 +import java.lang.instrument.ClassFileTransformer;
76.51 +import java.lang.instrument.IllegalClassFormatException;
76.52 +import java.lang.instrument.Instrumentation;
76.53 +import java.lang.instrument.UnmodifiableClassException;
76.54 +import java.lang.reflect.InvocationTargetException;
76.55 +import java.lang.reflect.Method;
76.56 +import java.security.ProtectionDomain;
76.57 +import java.util.Collection;
76.58 +import java.util.HashSet;
76.59 +import java.util.List;
76.60 +import java.util.Set;
76.61 +import java.util.concurrent.CopyOnWriteArrayList;
76.62 +import java.util.jar.JarFile;
76.63 +import java.util.logging.Level;
76.64 +import java.util.logging.Logger;
76.65 +
76.66 +/**
76.67 + *
76.68 + * @author Jaroslav Tulach <jtulach@netbeans.org>
76.69 + */
76.70 +final class NbInstrumentation implements Instrumentation {
76.71 + private static final Logger LOG = Logger.getLogger(NbInstrumentation.class.getName());
76.72 + private static final Object LOCK = new Object();
76.73 + private static volatile Collection<NbInstrumentation> ACTIVE;
76.74 +
76.75 + private final List<ClassFileTransformer> transformers = new CopyOnWriteArrayList<ClassFileTransformer>();
76.76 + private static final ThreadLocal<Boolean> IN = new ThreadLocal<Boolean>();
76.77 +
76.78 + static NbInstrumentation registerAgent(ClassLoader l, String agentClassName) {
76.79 + try {
76.80 + return registerImpl(agentClassName, l);
76.81 + } catch (Throwable ex) {
76.82 + LOG.log(Level.WARNING, "Cannot register " + agentClassName, ex);
76.83 + return null;
76.84 + }
76.85 + }
76.86 + static void unregisterAgent(NbInstrumentation instr) {
76.87 + synchronized (LOCK) {
76.88 + if (ACTIVE != null) {
76.89 + Collection<NbInstrumentation> clone = new HashSet<NbInstrumentation>();
76.90 + clone.addAll(ACTIVE);
76.91 + clone.remove(instr);
76.92 + ACTIVE = clone;
76.93 + }
76.94 + }
76.95 + }
76.96 + private static NbInstrumentation registerImpl(String agentClassName, ClassLoader l) throws ClassNotFoundException, IllegalArgumentException, NoSuchMethodException, SecurityException, IllegalAccessException, InvocationTargetException {
76.97 + final NbInstrumentation inst = new NbInstrumentation();
76.98 + synchronized (LOCK) {
76.99 + if (ACTIVE == null) {
76.100 + ACTIVE = new HashSet<NbInstrumentation>();
76.101 + } else {
76.102 + Set<NbInstrumentation> s = new HashSet<NbInstrumentation>();
76.103 + s.addAll(ACTIVE);
76.104 + ACTIVE = s;
76.105 + }
76.106 + ACTIVE.add(inst);
76.107 + }
76.108 + Class<?> agentClass = Class.forName(agentClassName, true, l);
76.109 + try {
76.110 + Method m = agentClass.getMethod("agentmain", String.class, Instrumentation.class); // NOI18N
76.111 + m.invoke(null, "", inst);
76.112 + } catch (NoSuchMethodException ex) {
76.113 + Method m = agentClass.getMethod("agentmain", String.class); // NOI18N
76.114 + m.invoke(null, "");
76.115 + }
76.116 + return inst;
76.117 + }
76.118 +
76.119 + public static byte[] patchByteCode(ClassLoader l, String className, ProtectionDomain pd, byte[] arr) throws IllegalClassFormatException {
76.120 + if (ACTIVE == null) {
76.121 + return arr;
76.122 + }
76.123 + if (Boolean.TRUE.equals(IN.get())) {
76.124 + return arr;
76.125 + }
76.126 + try {
76.127 + IN.set(Boolean.TRUE);
76.128 + for (NbInstrumentation inst : ACTIVE) {
76.129 + for (ClassFileTransformer t : inst.transformers) {
76.130 + arr = t.transform(l, className, null, pd, arr);
76.131 + }
76.132 + }
76.133 + } finally {
76.134 + IN.set(null);
76.135 + }
76.136 + return arr;
76.137 + }
76.138 +
76.139 + //
76.140 + // Instrumentation methods
76.141 + //
76.142 +
76.143 + @Override
76.144 + public void addTransformer(ClassFileTransformer transformer, boolean canRetransform) {
76.145 + transformers.add(transformer);
76.146 + }
76.147 +
76.148 + @Override
76.149 + public void addTransformer(ClassFileTransformer transformer) {
76.150 + transformers.add(transformer);
76.151 + }
76.152 +
76.153 + @Override
76.154 + public boolean removeTransformer(ClassFileTransformer transformer) {
76.155 + return transformers.remove(transformer);
76.156 + }
76.157 +
76.158 + @Override
76.159 + public boolean isRetransformClassesSupported() {
76.160 + return false;
76.161 + }
76.162 +
76.163 + @Override
76.164 + public void retransformClasses(Class<?>... classes) throws UnmodifiableClassException {
76.165 + throw new UnmodifiableClassException();
76.166 + }
76.167 +
76.168 + @Override
76.169 + public boolean isRedefineClassesSupported() {
76.170 + return false;
76.171 + }
76.172 +
76.173 + @Override
76.174 + public void redefineClasses(ClassDefinition... definitions) throws ClassNotFoundException, UnmodifiableClassException {
76.175 + throw new UnmodifiableClassException();
76.176 + }
76.177 +
76.178 + @Override
76.179 + public boolean isModifiableClass(Class<?> theClass) {
76.180 + return false;
76.181 + }
76.182 +
76.183 + @Override
76.184 + public Class[] getAllLoadedClasses() {
76.185 + return new Class[0];
76.186 + }
76.187 +
76.188 + @Override
76.189 + public Class[] getInitiatedClasses(ClassLoader loader) {
76.190 + return new Class[0];
76.191 + }
76.192 +
76.193 + @Override
76.194 + public long getObjectSize(Object objectToSize) {
76.195 + return 42;
76.196 + }
76.197 +
76.198 + @Override
76.199 + public void appendToBootstrapClassLoaderSearch(JarFile jarfile) {
76.200 + }
76.201 +
76.202 + @Override
76.203 + public void appendToSystemClassLoaderSearch(JarFile jarfile) {
76.204 + throw new UnsupportedOperationException();
76.205 + }
76.206 +
76.207 + @Override
76.208 + public boolean isNativeMethodPrefixSupported() {
76.209 + return false;
76.210 + }
76.211 +
76.212 + @Override
76.213 + public void setNativeMethodPrefix(ClassFileTransformer transformer, String prefix) {
76.214 + throw new UnsupportedOperationException();
76.215 + }
76.216 +
76.217 +}
77.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
77.2 +++ b/equinox-agentclass-hook/src/main/resources/hookconfigurators.properties Tue Jan 07 08:21:57 2014 +0100
77.3 @@ -0,0 +1,44 @@
77.4 +#
77.5 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
77.6 +#
77.7 +# Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
77.8 +#
77.9 +# Oracle and Java are registered trademarks of Oracle and/or its affiliates.
77.10 +# Other names may be trademarks of their respective owners.
77.11 +#
77.12 +# The contents of this file are subject to the terms of either the GNU
77.13 +# General Public License Version 2 only ("GPL") or the Common
77.14 +# Development and Distribution License("CDDL") (collectively, the
77.15 +# "License"). You may not use this file except in compliance with the
77.16 +# License. You can obtain a copy of the License at
77.17 +# http://www.netbeans.org/cddl-gplv2.html
77.18 +# or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
77.19 +# specific language governing permissions and limitations under the
77.20 +# License. When distributing the software, include this License Header
77.21 +# Notice in each file and include the License file at
77.22 +# nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
77.23 +# particular file as subject to the "Classpath" exception as provided
77.24 +# by Oracle in the GPL Version 2 section of the License file that
77.25 +# accompanied this code. If applicable, add the following below the
77.26 +# License Header, with the fields enclosed by brackets [] replaced by
77.27 +# your own identifying information:
77.28 +# "Portions Copyrighted [year] [name of copyright owner]"
77.29 +#
77.30 +# Contributor(s):
77.31 +#
77.32 +# The Original Software is NetBeans. The Initial Developer of the Original
77.33 +# Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
77.34 +#
77.35 +# If you wish your version of this file to be governed by only the CDDL
77.36 +# or only the GPL Version 2, indicate your decision by adding
77.37 +# "[Contributor] elects to include this software in this distribution
77.38 +# under the [CDDL or GPL Version 2] license." If you do not indicate a
77.39 +# single choice of license, a recipient has the option to distribute
77.40 +# your version of this file under either the CDDL, the GPL Version 2 or
77.41 +# to extend the choice of license to its licensees as provided above.
77.42 +# However, if you add GPL Version 2 code and therefore, elected the GPL
77.43 +# Version 2 license, then the option applies only if the new code is
77.44 +# made subject to such option by the copyright holder.
77.45 +#
77.46 +
77.47 +hook.configurators=org.netbeans.equinox.agentclass.AgentHook
78.1 --- a/geo/pom.xml Thu Dec 19 17:11:01 2013 +0100
78.2 +++ b/geo/pom.xml Tue Jan 07 08:21:57 2014 +0100
78.3 @@ -2,11 +2,11 @@
78.4 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
78.5 <modelVersion>4.0.0</modelVersion>
78.6 <parent>
78.7 - <groupId>org.apidesign</groupId>
78.8 - <artifactId>html</artifactId>
78.9 + <groupId>org.netbeans.html</groupId>
78.10 + <artifactId>pom</artifactId>
78.11 <version>0.7-SNAPSHOT</version>
78.12 </parent>
78.13 - <groupId>org.apidesign.html</groupId>
78.14 + <groupId>org.netbeans.html</groupId>
78.15 <artifactId>net.java.html.geo</artifactId>
78.16 <version>0.7-SNAPSHOT</version>
78.17 <packaging>bundle</packaging>
78.18 @@ -35,7 +35,7 @@
78.19 <type>jar</type>
78.20 </dependency>
78.21 <dependency>
78.22 - <groupId>org.apidesign.html</groupId>
78.23 + <groupId>org.netbeans.html</groupId>
78.24 <artifactId>net.java.html.boot</artifactId>
78.25 <version>${project.version}</version>
78.26 <type>jar</type>
79.1 --- a/geo/src/main/java/net/java/html/geo/OnLocation.java Thu Dec 19 17:11:01 2013 +0100
79.2 +++ b/geo/src/main/java/net/java/html/geo/OnLocation.java Tue Jan 07 08:21:57 2014 +0100
79.3 @@ -1,22 +1,44 @@
79.4 /**
79.5 - * HTML via Java(tm) Language Bindings
79.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
79.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
79.8 *
79.9 - * This program is free software: you can redistribute it and/or modify
79.10 - * it under the terms of the GNU General Public License as published by
79.11 - * the Free Software Foundation, version 2 of the License.
79.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
79.13 *
79.14 - * This program is distributed in the hope that it will be useful,
79.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
79.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
79.17 - * GNU General Public License for more details. apidesign.org
79.18 - * designates this particular file as subject to the
79.19 - * "Classpath" exception as provided by apidesign.org
79.20 - * in the License file that accompanied this code.
79.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
79.22 + * Other names may be trademarks of their respective owners.
79.23 *
79.24 - * You should have received a copy of the GNU General Public License
79.25 - * along with this program. Look for COPYING file in the top folder.
79.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
79.27 + * The contents of this file are subject to the terms of either the GNU
79.28 + * General Public License Version 2 only ("GPL") or the Common
79.29 + * Development and Distribution License("CDDL") (collectively, the
79.30 + * "License"). You may not use this file except in compliance with the
79.31 + * License. You can obtain a copy of the License at
79.32 + * http://www.netbeans.org/cddl-gplv2.html
79.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
79.34 + * specific language governing permissions and limitations under the
79.35 + * License. When distributing the software, include this License Header
79.36 + * Notice in each file and include the License file at
79.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
79.38 + * particular file as subject to the "Classpath" exception as provided
79.39 + * by Oracle in the GPL Version 2 section of the License file that
79.40 + * accompanied this code. If applicable, add the following below the
79.41 + * License Header, with the fields enclosed by brackets [] replaced by
79.42 + * your own identifying information:
79.43 + * "Portions Copyrighted [year] [name of copyright owner]"
79.44 + *
79.45 + * Contributor(s):
79.46 + *
79.47 + * The Original Software is NetBeans. The Initial Developer of the Original
79.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
79.49 + *
79.50 + * If you wish your version of this file to be governed by only the CDDL
79.51 + * or only the GPL Version 2, indicate your decision by adding
79.52 + * "[Contributor] elects to include this software in this distribution
79.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
79.54 + * single choice of license, a recipient has the option to distribute
79.55 + * your version of this file under either the CDDL, the GPL Version 2 or
79.56 + * to extend the choice of license to its licensees as provided above.
79.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
79.58 + * Version 2 license, then the option applies only if the new code is
79.59 + * made subject to such option by the copyright holder.
79.60 */
79.61 package net.java.html.geo;
79.62
80.1 --- a/geo/src/main/java/net/java/html/geo/Position.java Thu Dec 19 17:11:01 2013 +0100
80.2 +++ b/geo/src/main/java/net/java/html/geo/Position.java Tue Jan 07 08:21:57 2014 +0100
80.3 @@ -1,28 +1,50 @@
80.4 /**
80.5 - * HTML via Java(tm) Language Bindings
80.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
80.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
80.8 *
80.9 - * This program is free software: you can redistribute it and/or modify
80.10 - * it under the terms of the GNU General Public License as published by
80.11 - * the Free Software Foundation, version 2 of the License.
80.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
80.13 *
80.14 - * This program is distributed in the hope that it will be useful,
80.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
80.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
80.17 - * GNU General Public License for more details. apidesign.org
80.18 - * designates this particular file as subject to the
80.19 - * "Classpath" exception as provided by apidesign.org
80.20 - * in the License file that accompanied this code.
80.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
80.22 + * Other names may be trademarks of their respective owners.
80.23 *
80.24 - * You should have received a copy of the GNU General Public License
80.25 - * along with this program. Look for COPYING file in the top folder.
80.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
80.27 + * The contents of this file are subject to the terms of either the GNU
80.28 + * General Public License Version 2 only ("GPL") or the Common
80.29 + * Development and Distribution License("CDDL") (collectively, the
80.30 + * "License"). You may not use this file except in compliance with the
80.31 + * License. You can obtain a copy of the License at
80.32 + * http://www.netbeans.org/cddl-gplv2.html
80.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
80.34 + * specific language governing permissions and limitations under the
80.35 + * License. When distributing the software, include this License Header
80.36 + * Notice in each file and include the License file at
80.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
80.38 + * particular file as subject to the "Classpath" exception as provided
80.39 + * by Oracle in the GPL Version 2 section of the License file that
80.40 + * accompanied this code. If applicable, add the following below the
80.41 + * License Header, with the fields enclosed by brackets [] replaced by
80.42 + * your own identifying information:
80.43 + * "Portions Copyrighted [year] [name of copyright owner]"
80.44 + *
80.45 + * Contributor(s):
80.46 + *
80.47 + * The Original Software is NetBeans. The Initial Developer of the Original
80.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
80.49 + *
80.50 + * If you wish your version of this file to be governed by only the CDDL
80.51 + * or only the GPL Version 2, indicate your decision by adding
80.52 + * "[Contributor] elects to include this software in this distribution
80.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
80.54 + * single choice of license, a recipient has the option to distribute
80.55 + * your version of this file under either the CDDL, the GPL Version 2 or
80.56 + * to extend the choice of license to its licensees as provided above.
80.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
80.58 + * Version 2 license, then the option applies only if the new code is
80.59 + * made subject to such option by the copyright holder.
80.60 */
80.61 package net.java.html.geo;
80.62
80.63 import java.util.logging.Level;
80.64 import java.util.logging.Logger;
80.65 -import org.apidesign.html.geo.impl.JsG;
80.66 +import org.netbeans.html.geo.impl.JsG;
80.67
80.68 /** Class that represents a geolocation position provided as a callback
80.69 * to {@link Handle#onLocation(net.java.html.geo.Position)} method. The
81.1 --- a/geo/src/main/java/net/java/html/geo/package.html Thu Dec 19 17:11:01 2013 +0100
81.2 +++ b/geo/src/main/java/net/java/html/geo/package.html Tue Jan 07 08:21:57 2014 +0100
81.3 @@ -1,23 +1,45 @@
81.4 <!--
81.5
81.6 - HTML via Java(tm) Language Bindings
81.7 - Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
81.8 + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
81.9
81.10 - This program is free software: you can redistribute it and/or modify
81.11 - it under the terms of the GNU General Public License as published by
81.12 - the Free Software Foundation, version 2 of the License.
81.13 + Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
81.14
81.15 - This program is distributed in the hope that it will be useful,
81.16 - but WITHOUT ANY WARRANTY; without even the implied warranty of
81.17 - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
81.18 - GNU General Public License for more details. apidesign.org
81.19 - designates this particular file as subject to the
81.20 - "Classpath" exception as provided by apidesign.org
81.21 - in the License file that accompanied this code.
81.22 + Oracle and Java are registered trademarks of Oracle and/or its affiliates.
81.23 + Other names may be trademarks of their respective owners.
81.24
81.25 - You should have received a copy of the GNU General Public License
81.26 - along with this program. Look for COPYING file in the top folder.
81.27 - If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
81.28 + The contents of this file are subject to the terms of either the GNU
81.29 + General Public License Version 2 only ("GPL") or the Common
81.30 + Development and Distribution License("CDDL") (collectively, the
81.31 + "License"). You may not use this file except in compliance with the
81.32 + License. You can obtain a copy of the License at
81.33 + http://www.netbeans.org/cddl-gplv2.html
81.34 + or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
81.35 + specific language governing permissions and limitations under the
81.36 + License. When distributing the software, include this License Header
81.37 + Notice in each file and include the License file at
81.38 + nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
81.39 + particular file as subject to the "Classpath" exception as provided
81.40 + by Oracle in the GPL Version 2 section of the License file that
81.41 + accompanied this code. If applicable, add the following below the
81.42 + License Header, with the fields enclosed by brackets [] replaced by
81.43 + your own identifying information:
81.44 + "Portions Copyrighted [year] [name of copyright owner]"
81.45 +
81.46 + Contributor(s):
81.47 +
81.48 + The Original Software is NetBeans. The Initial Developer of the Original
81.49 + Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
81.50 +
81.51 + If you wish your version of this file to be governed by only the CDDL
81.52 + or only the GPL Version 2, indicate your decision by adding
81.53 + "[Contributor] elects to include this software in this distribution
81.54 + under the [CDDL or GPL Version 2] license." If you do not indicate a
81.55 + single choice of license, a recipient has the option to distribute
81.56 + your version of this file under either the CDDL, the GPL Version 2 or
81.57 + to extend the choice of license to its licensees as provided above.
81.58 + However, if you add GPL Version 2 code and therefore, elected the GPL
81.59 + Version 2 license, then the option applies only if the new code is
81.60 + made subject to such option by the copyright holder.
81.61
81.62 -->
81.63 <!DOCTYPE html>
82.1 --- a/geo/src/main/java/org/apidesign/html/geo/impl/GeoProcessor.java Thu Dec 19 17:11:01 2013 +0100
82.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
82.3 @@ -1,267 +0,0 @@
82.4 -/**
82.5 - * HTML via Java(tm) Language Bindings
82.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
82.7 - *
82.8 - * This program is free software: you can redistribute it and/or modify
82.9 - * it under the terms of the GNU General Public License as published by
82.10 - * the Free Software Foundation, version 2 of the License.
82.11 - *
82.12 - * This program is distributed in the hope that it will be useful,
82.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
82.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
82.15 - * GNU General Public License for more details. apidesign.org
82.16 - * designates this particular file as subject to the
82.17 - * "Classpath" exception as provided by apidesign.org
82.18 - * in the License file that accompanied this code.
82.19 - *
82.20 - * You should have received a copy of the GNU General Public License
82.21 - * along with this program. Look for COPYING file in the top folder.
82.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
82.23 - */
82.24 -package org.apidesign.html.geo.impl;
82.25 -
82.26 -import java.io.IOException;
82.27 -import java.io.Writer;
82.28 -import java.util.List;
82.29 -import java.util.Locale;
82.30 -import java.util.Set;
82.31 -import java.util.logging.Level;
82.32 -import java.util.logging.Logger;
82.33 -import javax.annotation.processing.AbstractProcessor;
82.34 -import javax.annotation.processing.Processor;
82.35 -import javax.annotation.processing.RoundEnvironment;
82.36 -import javax.annotation.processing.SupportedAnnotationTypes;
82.37 -import javax.annotation.processing.SupportedSourceVersion;
82.38 -import javax.lang.model.SourceVersion;
82.39 -import javax.lang.model.element.Element;
82.40 -import javax.lang.model.element.ElementKind;
82.41 -import javax.lang.model.element.ExecutableElement;
82.42 -import javax.lang.model.element.Modifier;
82.43 -import javax.lang.model.element.PackageElement;
82.44 -import javax.lang.model.element.TypeElement;
82.45 -import javax.lang.model.element.VariableElement;
82.46 -import javax.lang.model.type.TypeMirror;
82.47 -import javax.tools.Diagnostic;
82.48 -import javax.tools.JavaFileObject;
82.49 -import net.java.html.geo.OnLocation;
82.50 -import net.java.html.geo.Position;
82.51 -import org.openide.util.lookup.ServiceProvider;
82.52 -
82.53 -/** Annotation processor to generate callbacks from {@link GeoHandle} class.
82.54 - *
82.55 - * @author Jaroslav Tulach <jtulach@netbeans.org>
82.56 - */
82.57 -@ServiceProvider(service=Processor.class)
82.58 -@SupportedSourceVersion(SourceVersion.RELEASE_6)
82.59 -@SupportedAnnotationTypes({
82.60 - "net.java.html.geo.OnLocation"
82.61 -})
82.62 -public final class GeoProcessor extends AbstractProcessor {
82.63 - private static final Logger LOG = Logger.getLogger(GeoProcessor.class.getName());
82.64 - @Override
82.65 - public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
82.66 - boolean ok = true;
82.67 - for (Element e : roundEnv.getElementsAnnotatedWith(OnLocation.class)) {
82.68 - if (!processLocation(e)) {
82.69 - ok = false;
82.70 - }
82.71 - }
82.72 - return ok;
82.73 - }
82.74 -
82.75 - private void error(String msg, Element e) {
82.76 - processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, msg, e);
82.77 - }
82.78 -
82.79 - private boolean processLocation(Element e) {
82.80 - if (e.getKind() != ElementKind.METHOD) {
82.81 - return false;
82.82 - }
82.83 - ExecutableElement me = (ExecutableElement) e;
82.84 - OnLocation ol = e.getAnnotation(OnLocation.class);
82.85 - if (ol == null) {
82.86 - return true;
82.87 - }
82.88 - if (me.getModifiers().contains(Modifier.PRIVATE)) {
82.89 - error("Method annotated by @OnLocation cannot be private", e);
82.90 - return false;
82.91 - }
82.92 - TypeMirror positionClass = processingEnv.getElementUtils().getTypeElement(Position.class.getName()).asType();
82.93 - final List<? extends VariableElement> params = me.getParameters();
82.94 - if (params.size() < 1 || !params.get(0).asType().equals(positionClass)) {
82.95 - error("Method annotated by @OnLocation first argument must be net.java.html.geo.Position!", e);
82.96 - return false;
82.97 - }
82.98 - String className = ol.className();
82.99 - if (className.isEmpty()) {
82.100 - String n = e.getSimpleName().toString();
82.101 - if (n.isEmpty()) {
82.102 - error("Empty method name", e);
82.103 - return false;
82.104 - }
82.105 - final String firstLetter = n.substring(0, 1).toUpperCase(Locale.ENGLISH);
82.106 - className = firstLetter + n.substring(1) + "Handle";
82.107 - }
82.108 - TypeElement te = (TypeElement)e.getEnclosingElement();
82.109 - PackageElement pe = (PackageElement) te.getEnclosingElement();
82.110 - final String pkg = pe.getQualifiedName().toString();
82.111 - final String fqn = pkg + "." + className;
82.112 - final boolean isStatic = me.getModifiers().contains(Modifier.STATIC);
82.113 - String sep;
82.114 - try {
82.115 - JavaFileObject fo = processingEnv.getFiler().createSourceFile(fqn, e);
82.116 - Writer w = fo.openWriter();
82.117 - w.append("package ").append(pkg).append(";\n");
82.118 - w.append("class ").append(className).append(" extends net.java.html.geo.Position.Handle {\n");
82.119 - if (!isStatic) {
82.120 - w.append(" private final ").append(te.getSimpleName()).append(" $i;\n");
82.121 - }
82.122 - for (int i = 1; i < params.size(); i++) {
82.123 - final VariableElement p = params.get(i);
82.124 - w.append(" private final ").append(p.asType().toString()).append(" ").append(p.getSimpleName()).append(";\n");
82.125 - }
82.126 - w.append(" private ").append(className).append("(boolean oneTime");
82.127 - w.append(", ").append(te.getSimpleName()).append(" i");
82.128 - for (int i = 1; i < params.size(); i++) {
82.129 - final VariableElement p = params.get(i);
82.130 - w.append(", ").append(p.asType().toString()).append(" ").append(p.getSimpleName());
82.131 - }
82.132 - w.append(") {\n super(oneTime);\n");
82.133 - if (!isStatic) {
82.134 - w.append(" this.$i = i;\n");
82.135 - }
82.136 - for (int i = 1; i < params.size(); i++) {
82.137 - final VariableElement p = params.get(i);
82.138 - w.append(" this.").append(p.getSimpleName()).append(" = ").append(p.getSimpleName()).append(";\n");
82.139 - }
82.140 - w.append("}\n");
82.141 - w.append(" static net.java.html.geo.Position.Handle createQuery(");
82.142 - String inst;
82.143 - if (!isStatic) {
82.144 - w.append(te.getSimpleName()).append(" instance");
82.145 - inst = "instance";
82.146 - sep = ", ";
82.147 - } else {
82.148 - inst = "null";
82.149 - sep = "";
82.150 - }
82.151 - for (int i = 1; i < params.size(); i++) {
82.152 - final VariableElement p = params.get(i);
82.153 - w.append(sep).append(p.asType().toString()).append(" ").append(p.getSimpleName());
82.154 - sep = ", ";
82.155 - }
82.156 - w.append(") { return new ").append(className).append("(true, ").append(inst);
82.157 - for (int i = 1; i < params.size(); i++) {
82.158 - final VariableElement p = params.get(i);
82.159 - w.append(", ").append(p.getSimpleName());
82.160 - }
82.161 - w.append("); }\n");
82.162 - w.append(" static net.java.html.geo.Position.Handle createWatch(");
82.163 - if (!isStatic) {
82.164 - w.append(te.getSimpleName()).append(" instance");
82.165 - sep = ", ";
82.166 - } else {
82.167 - sep = "";
82.168 - }
82.169 - for (int i = 1; i < params.size(); i++) {
82.170 - final VariableElement p = params.get(i);
82.171 - w.append(sep).append(p.asType().toString()).append(" ").append(p.getSimpleName());
82.172 - }
82.173 - w.append(") { return new ").append(className).append("(false, ").append(inst);
82.174 - for (int i = 1; i < params.size(); i++) {
82.175 - final VariableElement p = params.get(i);
82.176 - w.append(", ").append(p.getSimpleName());
82.177 - }
82.178 - w.append("); }\n");
82.179 - w.append(" @Override protected void onError(Exception t) throws Throwable {\n");
82.180 - if (ol.onError().isEmpty()) {
82.181 - w.append(" t.printStackTrace();");
82.182 - } else {
82.183 - if (!findOnError(me, te, ol.onError(), isStatic)) {
82.184 - return false;
82.185 - }
82.186 - if (isStatic) {
82.187 - w.append(" ").append(te.getSimpleName()).append(".");
82.188 - } else {
82.189 - w.append(" $i.");
82.190 - }
82.191 - w.append(ol.onError()).append("(t");
82.192 - for (int i = 1; i < params.size(); i++) {
82.193 - final VariableElement p = params.get(i);
82.194 - w.append(", ").append(p.getSimpleName());
82.195 - }
82.196 - w.append(");\n");
82.197 - }
82.198 - w.append(" }\n");
82.199 - w.append(" @Override protected void onLocation(net.java.html.geo.Position p) throws Throwable {\n");
82.200 - if (isStatic) {
82.201 - w.append(" ").append(te.getSimpleName()).append(".");
82.202 - } else {
82.203 - w.append(" $i.");
82.204 - }
82.205 - w.append(me.getSimpleName()).append("(p");
82.206 - for (int i = 1; i < params.size(); i++) {
82.207 - final VariableElement p = params.get(i);
82.208 - w.append(", ").append(p.getSimpleName());
82.209 - }
82.210 - w.append(");\n");
82.211 - w.append(" }\n");
82.212 - w.append("}\n");
82.213 - w.close();
82.214 - } catch (IOException ex) {
82.215 - Logger.getLogger(GeoProcessor.class.getName()).log(Level.SEVERE, null, ex);
82.216 - error("Can't write handler class: " + ex.getMessage(), e);
82.217 - return false;
82.218 - }
82.219 -
82.220 - return true;
82.221 - }
82.222 -
82.223 - private boolean findOnError(ExecutableElement errElem, TypeElement te, String name, boolean onlyStatic) {
82.224 - String err = null;
82.225 - METHODS: for (Element e : te.getEnclosedElements()) {
82.226 - if (e.getKind() != ElementKind.METHOD) {
82.227 - continue;
82.228 - }
82.229 - if (!e.getSimpleName().contentEquals(name)) {
82.230 - continue;
82.231 - }
82.232 - if (onlyStatic && !e.getModifiers().contains(Modifier.STATIC)) {
82.233 - errElem = (ExecutableElement) e;
82.234 - err = "Would have to be static";
82.235 - continue;
82.236 - }
82.237 - ExecutableElement ee = (ExecutableElement) e;
82.238 - TypeMirror excType = processingEnv.getElementUtils().getTypeElement(Exception.class.getName()).asType();
82.239 - final List<? extends VariableElement> params = ee.getParameters();
82.240 - if (params.size() < 1 ||
82.241 - !processingEnv.getTypeUtils().isAssignable(excType, ee.getParameters().get(0).asType())
82.242 - ) {
82.243 - errElem = (ExecutableElement) e;
82.244 - err = "Error method first argument needs to be Exception";
82.245 - continue;
82.246 - }
82.247 - final List<? extends Element> origParams = errElem.getParameters();
82.248 - if (params.size() != origParams.size()) {
82.249 - errElem = (ExecutableElement) e;
82.250 - err = "Error method must have the same parameters as @OnLocation one";
82.251 - continue;
82.252 - }
82.253 - for (int i = 1; i < origParams.size(); i++) {
82.254 - final TypeMirror t1 = params.get(i).asType();
82.255 - final TypeMirror t2 = origParams.get(i).asType();
82.256 - if (!processingEnv.getTypeUtils().isSameType(t1, t2)) {
82.257 - errElem = (ExecutableElement) e;
82.258 - err = "Error method must have the same parameters as @OnLocation one";
82.259 - continue METHODS;
82.260 - }
82.261 - }
82.262 - return true;
82.263 - }
82.264 - if (err == null) {
82.265 - err = "Cannot find " + name + "(Exception) method in this class";
82.266 - }
82.267 - error(err, errElem);
82.268 - return false;
82.269 - }
82.270 -}
83.1 --- a/geo/src/main/java/org/apidesign/html/geo/impl/JsG.java Thu Dec 19 17:11:01 2013 +0100
83.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
83.3 @@ -1,85 +0,0 @@
83.4 -/**
83.5 - * HTML via Java(tm) Language Bindings
83.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
83.7 - *
83.8 - * This program is free software: you can redistribute it and/or modify
83.9 - * it under the terms of the GNU General Public License as published by
83.10 - * the Free Software Foundation, version 2 of the License.
83.11 - *
83.12 - * This program is distributed in the hope that it will be useful,
83.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
83.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
83.15 - * GNU General Public License for more details. apidesign.org
83.16 - * designates this particular file as subject to the
83.17 - * "Classpath" exception as provided by apidesign.org
83.18 - * in the License file that accompanied this code.
83.19 - *
83.20 - * You should have received a copy of the GNU General Public License
83.21 - * along with this program. Look for COPYING file in the top folder.
83.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
83.23 - */
83.24 -package org.apidesign.html.geo.impl;
83.25 -
83.26 -import net.java.html.js.JavaScriptBody;
83.27 -
83.28 -/** Implementation class to deal with browser's <code>navigator.geolocation</code>
83.29 - * object.
83.30 - *
83.31 - * @author Jaroslav Tulach <jtulach@netbeans.org>
83.32 - */
83.33 -public abstract class JsG {
83.34 - protected JsG() {
83.35 - if (!getClass().getName().equals("net.java.html.geo.Position$Handle$JsH")) {
83.36 - throw new IllegalStateException();
83.37 - }
83.38 - }
83.39 -
83.40 - public abstract void onLocation(Object position);
83.41 - public abstract void onError(Object error);
83.42 -
83.43 - @JavaScriptBody(args = {}, body = "return !!navigator.geolocation;")
83.44 - public static boolean hasGeolocation() {
83.45 - return false;
83.46 - }
83.47 -
83.48 - @JavaScriptBody(
83.49 - args = { "onlyOnce", "enableHighAccuracy", "timeout", "maximumAge" },
83.50 - javacall = true,
83.51 - body =
83.52 - "var self = this;\n" +
83.53 - "var ok = function (position) {\n" +
83.54 - " self.@org.apidesign.html.geo.impl.JsG::onLocation(Ljava/lang/Object;)(position);\n" +
83.55 - "};\n" +
83.56 - "var fail = function (error) {\n" +
83.57 - " self.@org.apidesign.html.geo.impl.JsG::onError(Ljava/lang/Object;)(error);\n" +
83.58 - "};\n" +
83.59 - "var options = {};\n" +
83.60 - "options.enableHighAccuracy = enableHighAccuracy;\n" +
83.61 - "if (timeout >= 0) options.timeout = timeout;\n" +
83.62 - "if (maximumAge >= 0) options.maximumAge = maximumAge;\n" +
83.63 - "if (onlyOnce) {\n" +
83.64 - " navigator.geolocation.getCurrentPosition(ok, fail);\n" +
83.65 - " return 0;\n" +
83.66 - "} else {\n" +
83.67 - " return navigator.geolocation.watchPosition(ok, fail);\n" +
83.68 - "}\n"
83.69 - )
83.70 - protected long start(
83.71 - boolean onlyOnce,
83.72 - boolean enableHighAccuracy,
83.73 - long timeout,
83.74 - long maximumAge
83.75 - ) {
83.76 - return -1;
83.77 - }
83.78 -
83.79 - @JavaScriptBody(args = { "watch" }, body = "navigator.geolocation.clearWatch(watch);")
83.80 - protected void stop(long watch) {
83.81 - }
83.82 -
83.83 - @JavaScriptBody(args = { "self", "property" }, body = "return self[property];")
83.84 - public static Object get(Object self, String property) {
83.85 - return null;
83.86 - }
83.87 -
83.88 -}
84.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
84.2 +++ b/geo/src/main/java/org/netbeans/html/geo/impl/GeoProcessor.java Tue Jan 07 08:21:57 2014 +0100
84.3 @@ -0,0 +1,289 @@
84.4 +/**
84.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
84.6 + *
84.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
84.8 + *
84.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
84.10 + * Other names may be trademarks of their respective owners.
84.11 + *
84.12 + * The contents of this file are subject to the terms of either the GNU
84.13 + * General Public License Version 2 only ("GPL") or the Common
84.14 + * Development and Distribution License("CDDL") (collectively, the
84.15 + * "License"). You may not use this file except in compliance with the
84.16 + * License. You can obtain a copy of the License at
84.17 + * http://www.netbeans.org/cddl-gplv2.html
84.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
84.19 + * specific language governing permissions and limitations under the
84.20 + * License. When distributing the software, include this License Header
84.21 + * Notice in each file and include the License file at
84.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
84.23 + * particular file as subject to the "Classpath" exception as provided
84.24 + * by Oracle in the GPL Version 2 section of the License file that
84.25 + * accompanied this code. If applicable, add the following below the
84.26 + * License Header, with the fields enclosed by brackets [] replaced by
84.27 + * your own identifying information:
84.28 + * "Portions Copyrighted [year] [name of copyright owner]"
84.29 + *
84.30 + * Contributor(s):
84.31 + *
84.32 + * The Original Software is NetBeans. The Initial Developer of the Original
84.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
84.34 + *
84.35 + * If you wish your version of this file to be governed by only the CDDL
84.36 + * or only the GPL Version 2, indicate your decision by adding
84.37 + * "[Contributor] elects to include this software in this distribution
84.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
84.39 + * single choice of license, a recipient has the option to distribute
84.40 + * your version of this file under either the CDDL, the GPL Version 2 or
84.41 + * to extend the choice of license to its licensees as provided above.
84.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
84.43 + * Version 2 license, then the option applies only if the new code is
84.44 + * made subject to such option by the copyright holder.
84.45 + */
84.46 +package org.netbeans.html.geo.impl;
84.47 +
84.48 +import java.io.IOException;
84.49 +import java.io.Writer;
84.50 +import java.util.List;
84.51 +import java.util.Locale;
84.52 +import java.util.Set;
84.53 +import java.util.logging.Level;
84.54 +import java.util.logging.Logger;
84.55 +import javax.annotation.processing.AbstractProcessor;
84.56 +import javax.annotation.processing.Processor;
84.57 +import javax.annotation.processing.RoundEnvironment;
84.58 +import javax.annotation.processing.SupportedAnnotationTypes;
84.59 +import javax.annotation.processing.SupportedSourceVersion;
84.60 +import javax.lang.model.SourceVersion;
84.61 +import javax.lang.model.element.Element;
84.62 +import javax.lang.model.element.ElementKind;
84.63 +import javax.lang.model.element.ExecutableElement;
84.64 +import javax.lang.model.element.Modifier;
84.65 +import javax.lang.model.element.PackageElement;
84.66 +import javax.lang.model.element.TypeElement;
84.67 +import javax.lang.model.element.VariableElement;
84.68 +import javax.lang.model.type.TypeMirror;
84.69 +import javax.tools.Diagnostic;
84.70 +import javax.tools.JavaFileObject;
84.71 +import net.java.html.geo.OnLocation;
84.72 +import net.java.html.geo.Position;
84.73 +import org.openide.util.lookup.ServiceProvider;
84.74 +
84.75 +/** Annotation processor to generate callbacks from {@link GeoHandle} class.
84.76 + *
84.77 + * @author Jaroslav Tulach <jtulach@netbeans.org>
84.78 + */
84.79 +@ServiceProvider(service=Processor.class)
84.80 +@SupportedSourceVersion(SourceVersion.RELEASE_6)
84.81 +@SupportedAnnotationTypes({
84.82 + "net.java.html.geo.OnLocation"
84.83 +})
84.84 +public final class GeoProcessor extends AbstractProcessor {
84.85 + private static final Logger LOG = Logger.getLogger(GeoProcessor.class.getName());
84.86 + @Override
84.87 + public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
84.88 + boolean ok = true;
84.89 + for (Element e : roundEnv.getElementsAnnotatedWith(OnLocation.class)) {
84.90 + if (!processLocation(e)) {
84.91 + ok = false;
84.92 + }
84.93 + }
84.94 + return ok;
84.95 + }
84.96 +
84.97 + private void error(String msg, Element e) {
84.98 + processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, msg, e);
84.99 + }
84.100 +
84.101 + private boolean processLocation(Element e) {
84.102 + if (e.getKind() != ElementKind.METHOD) {
84.103 + return false;
84.104 + }
84.105 + ExecutableElement me = (ExecutableElement) e;
84.106 + OnLocation ol = e.getAnnotation(OnLocation.class);
84.107 + if (ol == null) {
84.108 + return true;
84.109 + }
84.110 + if (me.getModifiers().contains(Modifier.PRIVATE)) {
84.111 + error("Method annotated by @OnLocation cannot be private", e);
84.112 + return false;
84.113 + }
84.114 + TypeMirror positionClass = processingEnv.getElementUtils().getTypeElement(Position.class.getName()).asType();
84.115 + final List<? extends VariableElement> params = me.getParameters();
84.116 + if (params.size() < 1 || !params.get(0).asType().equals(positionClass)) {
84.117 + error("Method annotated by @OnLocation first argument must be net.java.html.geo.Position!", e);
84.118 + return false;
84.119 + }
84.120 + String className = ol.className();
84.121 + if (className.isEmpty()) {
84.122 + String n = e.getSimpleName().toString();
84.123 + if (n.isEmpty()) {
84.124 + error("Empty method name", e);
84.125 + return false;
84.126 + }
84.127 + final String firstLetter = n.substring(0, 1).toUpperCase(Locale.ENGLISH);
84.128 + className = firstLetter + n.substring(1) + "Handle";
84.129 + }
84.130 + TypeElement te = (TypeElement)e.getEnclosingElement();
84.131 + PackageElement pe = (PackageElement) te.getEnclosingElement();
84.132 + final String pkg = pe.getQualifiedName().toString();
84.133 + final String fqn = pkg + "." + className;
84.134 + final boolean isStatic = me.getModifiers().contains(Modifier.STATIC);
84.135 + String sep;
84.136 + try {
84.137 + JavaFileObject fo = processingEnv.getFiler().createSourceFile(fqn, e);
84.138 + Writer w = fo.openWriter();
84.139 + w.append("package ").append(pkg).append(";\n");
84.140 + w.append("class ").append(className).append(" extends net.java.html.geo.Position.Handle {\n");
84.141 + if (!isStatic) {
84.142 + w.append(" private final ").append(te.getSimpleName()).append(" $i;\n");
84.143 + }
84.144 + for (int i = 1; i < params.size(); i++) {
84.145 + final VariableElement p = params.get(i);
84.146 + w.append(" private final ").append(p.asType().toString()).append(" ").append(p.getSimpleName()).append(";\n");
84.147 + }
84.148 + w.append(" private ").append(className).append("(boolean oneTime");
84.149 + w.append(", ").append(te.getSimpleName()).append(" i");
84.150 + for (int i = 1; i < params.size(); i++) {
84.151 + final VariableElement p = params.get(i);
84.152 + w.append(", ").append(p.asType().toString()).append(" ").append(p.getSimpleName());
84.153 + }
84.154 + w.append(") {\n super(oneTime);\n");
84.155 + if (!isStatic) {
84.156 + w.append(" this.$i = i;\n");
84.157 + }
84.158 + for (int i = 1; i < params.size(); i++) {
84.159 + final VariableElement p = params.get(i);
84.160 + w.append(" this.").append(p.getSimpleName()).append(" = ").append(p.getSimpleName()).append(";\n");
84.161 + }
84.162 + w.append("}\n");
84.163 + w.append(" static net.java.html.geo.Position.Handle createQuery(");
84.164 + String inst;
84.165 + if (!isStatic) {
84.166 + w.append(te.getSimpleName()).append(" instance");
84.167 + inst = "instance";
84.168 + sep = ", ";
84.169 + } else {
84.170 + inst = "null";
84.171 + sep = "";
84.172 + }
84.173 + for (int i = 1; i < params.size(); i++) {
84.174 + final VariableElement p = params.get(i);
84.175 + w.append(sep).append(p.asType().toString()).append(" ").append(p.getSimpleName());
84.176 + sep = ", ";
84.177 + }
84.178 + w.append(") { return new ").append(className).append("(true, ").append(inst);
84.179 + for (int i = 1; i < params.size(); i++) {
84.180 + final VariableElement p = params.get(i);
84.181 + w.append(", ").append(p.getSimpleName());
84.182 + }
84.183 + w.append("); }\n");
84.184 + w.append(" static net.java.html.geo.Position.Handle createWatch(");
84.185 + if (!isStatic) {
84.186 + w.append(te.getSimpleName()).append(" instance");
84.187 + sep = ", ";
84.188 + } else {
84.189 + sep = "";
84.190 + }
84.191 + for (int i = 1; i < params.size(); i++) {
84.192 + final VariableElement p = params.get(i);
84.193 + w.append(sep).append(p.asType().toString()).append(" ").append(p.getSimpleName());
84.194 + }
84.195 + w.append(") { return new ").append(className).append("(false, ").append(inst);
84.196 + for (int i = 1; i < params.size(); i++) {
84.197 + final VariableElement p = params.get(i);
84.198 + w.append(", ").append(p.getSimpleName());
84.199 + }
84.200 + w.append("); }\n");
84.201 + w.append(" @Override protected void onError(Exception t) throws Throwable {\n");
84.202 + if (ol.onError().isEmpty()) {
84.203 + w.append(" t.printStackTrace();");
84.204 + } else {
84.205 + if (!findOnError(me, te, ol.onError(), isStatic)) {
84.206 + return false;
84.207 + }
84.208 + if (isStatic) {
84.209 + w.append(" ").append(te.getSimpleName()).append(".");
84.210 + } else {
84.211 + w.append(" $i.");
84.212 + }
84.213 + w.append(ol.onError()).append("(t");
84.214 + for (int i = 1; i < params.size(); i++) {
84.215 + final VariableElement p = params.get(i);
84.216 + w.append(", ").append(p.getSimpleName());
84.217 + }
84.218 + w.append(");\n");
84.219 + }
84.220 + w.append(" }\n");
84.221 + w.append(" @Override protected void onLocation(net.java.html.geo.Position p) throws Throwable {\n");
84.222 + if (isStatic) {
84.223 + w.append(" ").append(te.getSimpleName()).append(".");
84.224 + } else {
84.225 + w.append(" $i.");
84.226 + }
84.227 + w.append(me.getSimpleName()).append("(p");
84.228 + for (int i = 1; i < params.size(); i++) {
84.229 + final VariableElement p = params.get(i);
84.230 + w.append(", ").append(p.getSimpleName());
84.231 + }
84.232 + w.append(");\n");
84.233 + w.append(" }\n");
84.234 + w.append("}\n");
84.235 + w.close();
84.236 + } catch (IOException ex) {
84.237 + Logger.getLogger(GeoProcessor.class.getName()).log(Level.SEVERE, null, ex);
84.238 + error("Can't write handler class: " + ex.getMessage(), e);
84.239 + return false;
84.240 + }
84.241 +
84.242 + return true;
84.243 + }
84.244 +
84.245 + private boolean findOnError(ExecutableElement errElem, TypeElement te, String name, boolean onlyStatic) {
84.246 + String err = null;
84.247 + METHODS: for (Element e : te.getEnclosedElements()) {
84.248 + if (e.getKind() != ElementKind.METHOD) {
84.249 + continue;
84.250 + }
84.251 + if (!e.getSimpleName().contentEquals(name)) {
84.252 + continue;
84.253 + }
84.254 + if (onlyStatic && !e.getModifiers().contains(Modifier.STATIC)) {
84.255 + errElem = (ExecutableElement) e;
84.256 + err = "Would have to be static";
84.257 + continue;
84.258 + }
84.259 + ExecutableElement ee = (ExecutableElement) e;
84.260 + TypeMirror excType = processingEnv.getElementUtils().getTypeElement(Exception.class.getName()).asType();
84.261 + final List<? extends VariableElement> params = ee.getParameters();
84.262 + if (params.size() < 1 ||
84.263 + !processingEnv.getTypeUtils().isAssignable(excType, ee.getParameters().get(0).asType())
84.264 + ) {
84.265 + errElem = (ExecutableElement) e;
84.266 + err = "Error method first argument needs to be Exception";
84.267 + continue;
84.268 + }
84.269 + final List<? extends Element> origParams = errElem.getParameters();
84.270 + if (params.size() != origParams.size()) {
84.271 + errElem = (ExecutableElement) e;
84.272 + err = "Error method must have the same parameters as @OnLocation one";
84.273 + continue;
84.274 + }
84.275 + for (int i = 1; i < origParams.size(); i++) {
84.276 + final TypeMirror t1 = params.get(i).asType();
84.277 + final TypeMirror t2 = origParams.get(i).asType();
84.278 + if (!processingEnv.getTypeUtils().isSameType(t1, t2)) {
84.279 + errElem = (ExecutableElement) e;
84.280 + err = "Error method must have the same parameters as @OnLocation one";
84.281 + continue METHODS;
84.282 + }
84.283 + }
84.284 + return true;
84.285 + }
84.286 + if (err == null) {
84.287 + err = "Cannot find " + name + "(Exception) method in this class";
84.288 + }
84.289 + error(err, errElem);
84.290 + return false;
84.291 + }
84.292 +}
85.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
85.2 +++ b/geo/src/main/java/org/netbeans/html/geo/impl/JsG.java Tue Jan 07 08:21:57 2014 +0100
85.3 @@ -0,0 +1,107 @@
85.4 +/**
85.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
85.6 + *
85.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
85.8 + *
85.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
85.10 + * Other names may be trademarks of their respective owners.
85.11 + *
85.12 + * The contents of this file are subject to the terms of either the GNU
85.13 + * General Public License Version 2 only ("GPL") or the Common
85.14 + * Development and Distribution License("CDDL") (collectively, the
85.15 + * "License"). You may not use this file except in compliance with the
85.16 + * License. You can obtain a copy of the License at
85.17 + * http://www.netbeans.org/cddl-gplv2.html
85.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
85.19 + * specific language governing permissions and limitations under the
85.20 + * License. When distributing the software, include this License Header
85.21 + * Notice in each file and include the License file at
85.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
85.23 + * particular file as subject to the "Classpath" exception as provided
85.24 + * by Oracle in the GPL Version 2 section of the License file that
85.25 + * accompanied this code. If applicable, add the following below the
85.26 + * License Header, with the fields enclosed by brackets [] replaced by
85.27 + * your own identifying information:
85.28 + * "Portions Copyrighted [year] [name of copyright owner]"
85.29 + *
85.30 + * Contributor(s):
85.31 + *
85.32 + * The Original Software is NetBeans. The Initial Developer of the Original
85.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
85.34 + *
85.35 + * If you wish your version of this file to be governed by only the CDDL
85.36 + * or only the GPL Version 2, indicate your decision by adding
85.37 + * "[Contributor] elects to include this software in this distribution
85.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
85.39 + * single choice of license, a recipient has the option to distribute
85.40 + * your version of this file under either the CDDL, the GPL Version 2 or
85.41 + * to extend the choice of license to its licensees as provided above.
85.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
85.43 + * Version 2 license, then the option applies only if the new code is
85.44 + * made subject to such option by the copyright holder.
85.45 + */
85.46 +package org.netbeans.html.geo.impl;
85.47 +
85.48 +import net.java.html.js.JavaScriptBody;
85.49 +
85.50 +/** Implementation class to deal with browser's <code>navigator.geolocation</code>
85.51 + * object.
85.52 + *
85.53 + * @author Jaroslav Tulach <jtulach@netbeans.org>
85.54 + */
85.55 +public abstract class JsG {
85.56 + protected JsG() {
85.57 + if (!getClass().getName().equals("net.java.html.geo.Position$Handle$JsH")) {
85.58 + throw new IllegalStateException();
85.59 + }
85.60 + }
85.61 +
85.62 + public abstract void onLocation(Object position);
85.63 + public abstract void onError(Object error);
85.64 +
85.65 + @JavaScriptBody(args = {}, body = "return !!navigator.geolocation;")
85.66 + public static boolean hasGeolocation() {
85.67 + return false;
85.68 + }
85.69 +
85.70 + @JavaScriptBody(
85.71 + args = { "onlyOnce", "enableHighAccuracy", "timeout", "maximumAge" },
85.72 + javacall = true,
85.73 + body =
85.74 + "var self = this;\n" +
85.75 + "var ok = function (position) {\n" +
85.76 + " self.@org.netbeans.html.geo.impl.JsG::onLocation(Ljava/lang/Object;)(position);\n" +
85.77 + "};\n" +
85.78 + "var fail = function (error) {\n" +
85.79 + " self.@org.netbeans.html.geo.impl.JsG::onError(Ljava/lang/Object;)(error);\n" +
85.80 + "};\n" +
85.81 + "var options = {};\n" +
85.82 + "options.enableHighAccuracy = enableHighAccuracy;\n" +
85.83 + "if (timeout >= 0) options.timeout = timeout;\n" +
85.84 + "if (maximumAge >= 0) options.maximumAge = maximumAge;\n" +
85.85 + "if (onlyOnce) {\n" +
85.86 + " navigator.geolocation.getCurrentPosition(ok, fail);\n" +
85.87 + " return 0;\n" +
85.88 + "} else {\n" +
85.89 + " return navigator.geolocation.watchPosition(ok, fail);\n" +
85.90 + "}\n"
85.91 + )
85.92 + protected long start(
85.93 + boolean onlyOnce,
85.94 + boolean enableHighAccuracy,
85.95 + long timeout,
85.96 + long maximumAge
85.97 + ) {
85.98 + return -1;
85.99 + }
85.100 +
85.101 + @JavaScriptBody(args = { "watch" }, body = "navigator.geolocation.clearWatch(watch);")
85.102 + protected void stop(long watch) {
85.103 + }
85.104 +
85.105 + @JavaScriptBody(args = { "self", "property" }, body = "return self[property];")
85.106 + public static Object get(Object self, String property) {
85.107 + return null;
85.108 + }
85.109 +
85.110 +}
86.1 --- a/geo/src/test/java/net/java/html/geo/OnLocationTest.java Thu Dec 19 17:11:01 2013 +0100
86.2 +++ b/geo/src/test/java/net/java/html/geo/OnLocationTest.java Tue Jan 07 08:21:57 2014 +0100
86.3 @@ -1,22 +1,44 @@
86.4 /**
86.5 - * HTML via Java(tm) Language Bindings
86.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
86.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
86.8 *
86.9 - * This program is free software: you can redistribute it and/or modify
86.10 - * it under the terms of the GNU General Public License as published by
86.11 - * the Free Software Foundation, version 2 of the License.
86.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
86.13 *
86.14 - * This program is distributed in the hope that it will be useful,
86.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
86.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
86.17 - * GNU General Public License for more details. apidesign.org
86.18 - * designates this particular file as subject to the
86.19 - * "Classpath" exception as provided by apidesign.org
86.20 - * in the License file that accompanied this code.
86.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
86.22 + * Other names may be trademarks of their respective owners.
86.23 *
86.24 - * You should have received a copy of the GNU General Public License
86.25 - * along with this program. Look for COPYING file in the top folder.
86.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
86.27 + * The contents of this file are subject to the terms of either the GNU
86.28 + * General Public License Version 2 only ("GPL") or the Common
86.29 + * Development and Distribution License("CDDL") (collectively, the
86.30 + * "License"). You may not use this file except in compliance with the
86.31 + * License. You can obtain a copy of the License at
86.32 + * http://www.netbeans.org/cddl-gplv2.html
86.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
86.34 + * specific language governing permissions and limitations under the
86.35 + * License. When distributing the software, include this License Header
86.36 + * Notice in each file and include the License file at
86.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
86.38 + * particular file as subject to the "Classpath" exception as provided
86.39 + * by Oracle in the GPL Version 2 section of the License file that
86.40 + * accompanied this code. If applicable, add the following below the
86.41 + * License Header, with the fields enclosed by brackets [] replaced by
86.42 + * your own identifying information:
86.43 + * "Portions Copyrighted [year] [name of copyright owner]"
86.44 + *
86.45 + * Contributor(s):
86.46 + *
86.47 + * The Original Software is NetBeans. The Initial Developer of the Original
86.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
86.49 + *
86.50 + * If you wish your version of this file to be governed by only the CDDL
86.51 + * or only the GPL Version 2, indicate your decision by adding
86.52 + * "[Contributor] elects to include this software in this distribution
86.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
86.54 + * single choice of license, a recipient has the option to distribute
86.55 + * your version of this file under either the CDDL, the GPL Version 2 or
86.56 + * to extend the choice of license to its licensees as provided above.
86.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
86.58 + * Version 2 license, then the option applies only if the new code is
86.59 + * made subject to such option by the copyright holder.
86.60 */
86.61 package net.java.html.geo;
86.62
87.1 --- a/geo/src/test/java/org/apidesign/html/geo/impl/Compile.java Thu Dec 19 17:11:01 2013 +0100
87.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
87.3 @@ -1,264 +0,0 @@
87.4 -/**
87.5 - * HTML via Java(tm) Language Bindings
87.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
87.7 - *
87.8 - * This program is free software: you can redistribute it and/or modify
87.9 - * it under the terms of the GNU General Public License as published by
87.10 - * the Free Software Foundation, version 2 of the License.
87.11 - *
87.12 - * This program is distributed in the hope that it will be useful,
87.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
87.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
87.15 - * GNU General Public License for more details. apidesign.org
87.16 - * designates this particular file as subject to the
87.17 - * "Classpath" exception as provided by apidesign.org
87.18 - * in the License file that accompanied this code.
87.19 - *
87.20 - * You should have received a copy of the GNU General Public License
87.21 - * along with this program. Look for COPYING file in the top folder.
87.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
87.23 - */
87.24 -package org.apidesign.html.geo.impl;
87.25 -
87.26 -import java.io.ByteArrayInputStream;
87.27 -import java.io.ByteArrayOutputStream;
87.28 -import java.io.IOException;
87.29 -import java.io.InputStream;
87.30 -import java.io.OutputStream;
87.31 -import java.net.URI;
87.32 -import java.net.URISyntaxException;
87.33 -import java.util.ArrayList;
87.34 -import java.util.Arrays;
87.35 -import java.util.HashMap;
87.36 -import java.util.List;
87.37 -import java.util.Locale;
87.38 -import java.util.Map;
87.39 -import java.util.regex.Matcher;
87.40 -import java.util.regex.Pattern;
87.41 -import javax.tools.Diagnostic;
87.42 -import javax.tools.DiagnosticListener;
87.43 -import javax.tools.FileObject;
87.44 -import javax.tools.ForwardingJavaFileManager;
87.45 -import javax.tools.JavaFileManager;
87.46 -import javax.tools.JavaFileObject;
87.47 -import javax.tools.JavaFileObject.Kind;
87.48 -import javax.tools.SimpleJavaFileObject;
87.49 -import javax.tools.StandardJavaFileManager;
87.50 -import javax.tools.StandardLocation;
87.51 -import javax.tools.ToolProvider;
87.52 -import static org.testng.Assert.*;
87.53 -
87.54 -/**
87.55 - *
87.56 - * @author Jaroslav Tulach <jtulach@netbeans.org>
87.57 - */
87.58 -final class Compile implements DiagnosticListener<JavaFileObject> {
87.59 - private final List<Diagnostic<? extends JavaFileObject>> errors =
87.60 - new ArrayList<Diagnostic<? extends JavaFileObject>>();
87.61 - private final Map<String, byte[]> classes;
87.62 - private final String pkg;
87.63 - private final String cls;
87.64 - private final String html;
87.65 - private final String sourceLevel;
87.66 -
87.67 - private Compile(String html, String code, String sl) throws IOException {
87.68 - this.pkg = findPkg(code);
87.69 - this.cls = findCls(code);
87.70 - this.html = html;
87.71 - this.sourceLevel = sl;
87.72 - classes = compile(html, code);
87.73 - }
87.74 -
87.75 - /** Performs compilation of given HTML page and associated Java code
87.76 - */
87.77 - public static Compile create(String html, String code) throws IOException {
87.78 - return create(html, code, "1.7");
87.79 - }
87.80 - static Compile create(String html, String code, String sourceLevel) throws IOException {
87.81 - return new Compile(html, code, sourceLevel);
87.82 - }
87.83 -
87.84 - /** Checks for given class among compiled resources */
87.85 - public byte[] get(String res) {
87.86 - return classes.get(res);
87.87 - }
87.88 -
87.89 - /** Obtains errors created during compilation.
87.90 - */
87.91 - public List<Diagnostic<? extends JavaFileObject>> getErrors() {
87.92 - List<Diagnostic<? extends JavaFileObject>> err;
87.93 - err = new ArrayList<Diagnostic<? extends JavaFileObject>>();
87.94 - for (Diagnostic<? extends JavaFileObject> diagnostic : errors) {
87.95 - if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
87.96 - err.add(diagnostic);
87.97 - }
87.98 - }
87.99 - return err;
87.100 - }
87.101 -
87.102 - private Map<String, byte[]> compile(final String html, final String code) throws IOException {
87.103 - StandardJavaFileManager sjfm = ToolProvider.getSystemJavaCompiler().getStandardFileManager(this, null, null);
87.104 -
87.105 - final Map<String, ByteArrayOutputStream> class2BAOS;
87.106 - class2BAOS = new HashMap<String, ByteArrayOutputStream>();
87.107 -
87.108 - JavaFileObject file = new SimpleJavaFileObject(URI.create("mem://mem"), Kind.SOURCE) {
87.109 - @Override
87.110 - public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
87.111 - return code;
87.112 - }
87.113 - };
87.114 - final JavaFileObject htmlFile = new SimpleJavaFileObject(URI.create("mem://mem2"), Kind.OTHER) {
87.115 - @Override
87.116 - public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
87.117 - return html;
87.118 - }
87.119 -
87.120 - @Override
87.121 - public InputStream openInputStream() throws IOException {
87.122 - return new ByteArrayInputStream(html.getBytes());
87.123 - }
87.124 - };
87.125 -
87.126 - final URI scratch;
87.127 - try {
87.128 - scratch = new URI("mem://mem3");
87.129 - } catch (URISyntaxException ex) {
87.130 - throw new IOException(ex);
87.131 - }
87.132 -
87.133 - JavaFileManager jfm = new ForwardingJavaFileManager<JavaFileManager>(sjfm) {
87.134 - @Override
87.135 - public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) throws IOException {
87.136 - if (kind == Kind.CLASS) {
87.137 - final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
87.138 -
87.139 - class2BAOS.put(className.replace('.', '/') + ".class", buffer);
87.140 - return new SimpleJavaFileObject(sibling.toUri(), kind) {
87.141 - @Override
87.142 - public OutputStream openOutputStream() throws IOException {
87.143 - return buffer;
87.144 - }
87.145 - };
87.146 - }
87.147 -
87.148 - if (kind == Kind.SOURCE) {
87.149 - final String n = className.replace('.', '/') + ".java";
87.150 - final URI un;
87.151 - try {
87.152 - un = new URI("mem://" + n);
87.153 - } catch (URISyntaxException ex) {
87.154 - throw new IOException(ex);
87.155 - }
87.156 - return new VirtFO(un/*sibling.toUri()*/, kind, n);
87.157 - }
87.158 -
87.159 - throw new IllegalStateException();
87.160 - }
87.161 -
87.162 - @Override
87.163 - public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException {
87.164 - if (location == StandardLocation.SOURCE_PATH) {
87.165 - if (packageName.equals(pkg)) {
87.166 - return htmlFile;
87.167 - }
87.168 - }
87.169 -
87.170 - return null;
87.171 - }
87.172 -
87.173 - @Override
87.174 - public boolean isSameFile(FileObject a, FileObject b) {
87.175 - if (a instanceof VirtFO && b instanceof VirtFO) {
87.176 - return ((VirtFO)a).getName().equals(((VirtFO)b).getName());
87.177 - }
87.178 -
87.179 - return super.isSameFile(a, b);
87.180 - }
87.181 -
87.182 - class VirtFO extends SimpleJavaFileObject {
87.183 -
87.184 - private final String n;
87.185 -
87.186 - public VirtFO(URI uri, Kind kind, String n) {
87.187 - super(uri, kind);
87.188 - this.n = n;
87.189 - }
87.190 - private final ByteArrayOutputStream data = new ByteArrayOutputStream();
87.191 -
87.192 - @Override
87.193 - public OutputStream openOutputStream() throws IOException {
87.194 - return data;
87.195 - }
87.196 -
87.197 - @Override
87.198 - public String getName() {
87.199 - return n;
87.200 - }
87.201 -
87.202 - @Override
87.203 - public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
87.204 - data.close();
87.205 - return new String(data.toByteArray());
87.206 - }
87.207 - }
87.208 - };
87.209 -
87.210 - ToolProvider.getSystemJavaCompiler().getTask(null, jfm, this, /*XXX:*/Arrays.asList("-source", sourceLevel, "-target", "1.7"), null, Arrays.asList(file)).call();
87.211 -
87.212 - Map<String, byte[]> result = new HashMap<String, byte[]>();
87.213 -
87.214 - for (Map.Entry<String, ByteArrayOutputStream> e : class2BAOS.entrySet()) {
87.215 - result.put(e.getKey(), e.getValue().toByteArray());
87.216 - }
87.217 -
87.218 - return result;
87.219 - }
87.220 -
87.221 -
87.222 - @Override
87.223 - public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
87.224 - errors.add(diagnostic);
87.225 - }
87.226 - private static String findPkg(String java) throws IOException {
87.227 - Pattern p = Pattern.compile("package\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}*;", Pattern.MULTILINE);
87.228 - Matcher m = p.matcher(java);
87.229 - if (!m.find()) {
87.230 - throw new IOException("Can't find package declaration in the java file");
87.231 - }
87.232 - String pkg = m.group(1);
87.233 - return pkg;
87.234 - }
87.235 - private static String findCls(String java) throws IOException {
87.236 - Pattern p = Pattern.compile("class\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}", Pattern.MULTILINE);
87.237 - Matcher m = p.matcher(java);
87.238 - if (!m.find()) {
87.239 - throw new IOException("Can't find package declaration in the java file");
87.240 - }
87.241 - String cls = m.group(1);
87.242 - return cls;
87.243 - }
87.244 -
87.245 - String getHtml() {
87.246 - String fqn = "'" + pkg + '.' + cls + "'";
87.247 - return html.replace("'${fqn}'", fqn);
87.248 - }
87.249 -
87.250 - void assertErrors() {
87.251 - assertFalse(getErrors().isEmpty(), "There are supposed to be some errors");
87.252 - }
87.253 -
87.254 - void assertError(String expMsg) {
87.255 - StringBuilder sb = new StringBuilder();
87.256 - sb.append("Can't find ").append(expMsg).append(" among:");
87.257 - for (Diagnostic<? extends JavaFileObject> e : errors) {
87.258 - String msg = e.getMessage(Locale.US);
87.259 - if (msg.contains(expMsg)) {
87.260 - return;
87.261 - }
87.262 - sb.append("\n");
87.263 - sb.append(msg);
87.264 - }
87.265 - fail(sb.toString());
87.266 - }
87.267 -}
88.1 --- a/geo/src/test/java/org/apidesign/html/geo/impl/GeoProcessorTest.java Thu Dec 19 17:11:01 2013 +0100
88.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
88.3 @@ -1,92 +0,0 @@
88.4 -/**
88.5 - * HTML via Java(tm) Language Bindings
88.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
88.7 - *
88.8 - * This program is free software: you can redistribute it and/or modify
88.9 - * it under the terms of the GNU General Public License as published by
88.10 - * the Free Software Foundation, version 2 of the License.
88.11 - *
88.12 - * This program is distributed in the hope that it will be useful,
88.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
88.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
88.15 - * GNU General Public License for more details. apidesign.org
88.16 - * designates this particular file as subject to the
88.17 - * "Classpath" exception as provided by apidesign.org
88.18 - * in the License file that accompanied this code.
88.19 - *
88.20 - * You should have received a copy of the GNU General Public License
88.21 - * along with this program. Look for COPYING file in the top folder.
88.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
88.23 - */
88.24 -package org.apidesign.html.geo.impl;
88.25 -
88.26 -import java.io.IOException;
88.27 -import org.testng.annotations.Test;
88.28 -
88.29 -/** Test whether the annotation processor detects errors correctly.
88.30 - *
88.31 - * @author Jaroslav Tulach <jtulach@netbeans.org>
88.32 - */
88.33 -public class GeoProcessorTest {
88.34 -
88.35 - public GeoProcessorTest() {
88.36 - }
88.37 -
88.38 - @Test public void onLocationMethodHasToTakePositionParameter() throws IOException {
88.39 - Compile res = Compile.create("", "package x;\n"
88.40 - + "class UseOnLocation {\n"
88.41 - + " @net.java.html.geo.OnLocation\n"
88.42 - + " public static void cantCallMe() {}\n"
88.43 - + "}\n"
88.44 - );
88.45 - res.assertErrors();
88.46 - res.assertError("first argument must be net.java.html.geo.Position");
88.47 - }
88.48 -
88.49 - @Test public void onLocationMethodCannotBePrivate() throws IOException {
88.50 - Compile res = Compile.create("", "package x;\n"
88.51 - + "class UseOnLocation {\n"
88.52 - + " @net.java.html.geo.OnLocation\n"
88.53 - + " private static void cantCallMe(net.java.html.geo.Position p) {}\n"
88.54 - + "}\n"
88.55 - );
88.56 - res.assertErrors();
88.57 - res.assertError("cannot be private");
88.58 - }
88.59 -
88.60 - @Test public void onErrorHasToExist() throws IOException {
88.61 - Compile res = Compile.create("", "package x;\n"
88.62 - + "class UseOnLocation {\n"
88.63 - + " @net.java.html.geo.OnLocation(onError=\"doesNotExist\")\n"
88.64 - + " static void cantCallMe(net.java.html.geo.Position p) {}\n"
88.65 - + "}\n"
88.66 - );
88.67 - res.assertErrors();
88.68 - res.assertError("not find doesNotExist");
88.69 - }
88.70 -
88.71 - @Test public void onErrorWouldHaveToBeStatic() throws IOException {
88.72 - Compile res = Compile.create("", "package x;\n"
88.73 - + "class UseOnLocation {\n"
88.74 - + " @net.java.html.geo.OnLocation(onError=\"notStatic\")\n"
88.75 - + " static void cantCallMe(net.java.html.geo.Position p) {}\n"
88.76 - + " void notStatic(Exception e) {}\n"
88.77 - + "}\n"
88.78 - );
88.79 - res.assertErrors();
88.80 - res.assertError("have to be static");
88.81 - }
88.82 -
88.83 - @Test public void onErrorMustAcceptExceptionArgument() throws IOException {
88.84 - Compile res = Compile.create("", "package x;\n"
88.85 - + "class UseOnLocation {\n"
88.86 - + " @net.java.html.geo.OnLocation(onError=\"notStatic\")\n"
88.87 - + " static void cantCallMe(net.java.html.geo.Position p) {}\n"
88.88 - + " static void notStatic(java.io.IOException e) {}\n"
88.89 - + "}\n"
88.90 - );
88.91 - res.assertErrors();
88.92 - res.assertError("Error method first argument needs to be Exception");
88.93 - }
88.94 -
88.95 -}
89.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
89.2 +++ b/geo/src/test/java/org/netbeans/html/geo/impl/Compile.java Tue Jan 07 08:21:57 2014 +0100
89.3 @@ -0,0 +1,286 @@
89.4 +/**
89.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
89.6 + *
89.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
89.8 + *
89.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
89.10 + * Other names may be trademarks of their respective owners.
89.11 + *
89.12 + * The contents of this file are subject to the terms of either the GNU
89.13 + * General Public License Version 2 only ("GPL") or the Common
89.14 + * Development and Distribution License("CDDL") (collectively, the
89.15 + * "License"). You may not use this file except in compliance with the
89.16 + * License. You can obtain a copy of the License at
89.17 + * http://www.netbeans.org/cddl-gplv2.html
89.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
89.19 + * specific language governing permissions and limitations under the
89.20 + * License. When distributing the software, include this License Header
89.21 + * Notice in each file and include the License file at
89.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
89.23 + * particular file as subject to the "Classpath" exception as provided
89.24 + * by Oracle in the GPL Version 2 section of the License file that
89.25 + * accompanied this code. If applicable, add the following below the
89.26 + * License Header, with the fields enclosed by brackets [] replaced by
89.27 + * your own identifying information:
89.28 + * "Portions Copyrighted [year] [name of copyright owner]"
89.29 + *
89.30 + * Contributor(s):
89.31 + *
89.32 + * The Original Software is NetBeans. The Initial Developer of the Original
89.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
89.34 + *
89.35 + * If you wish your version of this file to be governed by only the CDDL
89.36 + * or only the GPL Version 2, indicate your decision by adding
89.37 + * "[Contributor] elects to include this software in this distribution
89.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
89.39 + * single choice of license, a recipient has the option to distribute
89.40 + * your version of this file under either the CDDL, the GPL Version 2 or
89.41 + * to extend the choice of license to its licensees as provided above.
89.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
89.43 + * Version 2 license, then the option applies only if the new code is
89.44 + * made subject to such option by the copyright holder.
89.45 + */
89.46 +package org.netbeans.html.geo.impl;
89.47 +
89.48 +import java.io.ByteArrayInputStream;
89.49 +import java.io.ByteArrayOutputStream;
89.50 +import java.io.IOException;
89.51 +import java.io.InputStream;
89.52 +import java.io.OutputStream;
89.53 +import java.net.URI;
89.54 +import java.net.URISyntaxException;
89.55 +import java.util.ArrayList;
89.56 +import java.util.Arrays;
89.57 +import java.util.HashMap;
89.58 +import java.util.List;
89.59 +import java.util.Locale;
89.60 +import java.util.Map;
89.61 +import java.util.regex.Matcher;
89.62 +import java.util.regex.Pattern;
89.63 +import javax.tools.Diagnostic;
89.64 +import javax.tools.DiagnosticListener;
89.65 +import javax.tools.FileObject;
89.66 +import javax.tools.ForwardingJavaFileManager;
89.67 +import javax.tools.JavaFileManager;
89.68 +import javax.tools.JavaFileObject;
89.69 +import javax.tools.JavaFileObject.Kind;
89.70 +import javax.tools.SimpleJavaFileObject;
89.71 +import javax.tools.StandardJavaFileManager;
89.72 +import javax.tools.StandardLocation;
89.73 +import javax.tools.ToolProvider;
89.74 +import static org.testng.Assert.*;
89.75 +
89.76 +/**
89.77 + *
89.78 + * @author Jaroslav Tulach <jtulach@netbeans.org>
89.79 + */
89.80 +final class Compile implements DiagnosticListener<JavaFileObject> {
89.81 + private final List<Diagnostic<? extends JavaFileObject>> errors =
89.82 + new ArrayList<Diagnostic<? extends JavaFileObject>>();
89.83 + private final Map<String, byte[]> classes;
89.84 + private final String pkg;
89.85 + private final String cls;
89.86 + private final String html;
89.87 + private final String sourceLevel;
89.88 +
89.89 + private Compile(String html, String code, String sl) throws IOException {
89.90 + this.pkg = findPkg(code);
89.91 + this.cls = findCls(code);
89.92 + this.html = html;
89.93 + this.sourceLevel = sl;
89.94 + classes = compile(html, code);
89.95 + }
89.96 +
89.97 + /** Performs compilation of given HTML page and associated Java code
89.98 + */
89.99 + public static Compile create(String html, String code) throws IOException {
89.100 + return create(html, code, "1.7");
89.101 + }
89.102 + static Compile create(String html, String code, String sourceLevel) throws IOException {
89.103 + return new Compile(html, code, sourceLevel);
89.104 + }
89.105 +
89.106 + /** Checks for given class among compiled resources */
89.107 + public byte[] get(String res) {
89.108 + return classes.get(res);
89.109 + }
89.110 +
89.111 + /** Obtains errors created during compilation.
89.112 + */
89.113 + public List<Diagnostic<? extends JavaFileObject>> getErrors() {
89.114 + List<Diagnostic<? extends JavaFileObject>> err;
89.115 + err = new ArrayList<Diagnostic<? extends JavaFileObject>>();
89.116 + for (Diagnostic<? extends JavaFileObject> diagnostic : errors) {
89.117 + if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
89.118 + err.add(diagnostic);
89.119 + }
89.120 + }
89.121 + return err;
89.122 + }
89.123 +
89.124 + private Map<String, byte[]> compile(final String html, final String code) throws IOException {
89.125 + StandardJavaFileManager sjfm = ToolProvider.getSystemJavaCompiler().getStandardFileManager(this, null, null);
89.126 +
89.127 + final Map<String, ByteArrayOutputStream> class2BAOS;
89.128 + class2BAOS = new HashMap<String, ByteArrayOutputStream>();
89.129 +
89.130 + JavaFileObject file = new SimpleJavaFileObject(URI.create("mem://mem"), Kind.SOURCE) {
89.131 + @Override
89.132 + public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
89.133 + return code;
89.134 + }
89.135 + };
89.136 + final JavaFileObject htmlFile = new SimpleJavaFileObject(URI.create("mem://mem2"), Kind.OTHER) {
89.137 + @Override
89.138 + public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
89.139 + return html;
89.140 + }
89.141 +
89.142 + @Override
89.143 + public InputStream openInputStream() throws IOException {
89.144 + return new ByteArrayInputStream(html.getBytes());
89.145 + }
89.146 + };
89.147 +
89.148 + final URI scratch;
89.149 + try {
89.150 + scratch = new URI("mem://mem3");
89.151 + } catch (URISyntaxException ex) {
89.152 + throw new IOException(ex);
89.153 + }
89.154 +
89.155 + JavaFileManager jfm = new ForwardingJavaFileManager<JavaFileManager>(sjfm) {
89.156 + @Override
89.157 + public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) throws IOException {
89.158 + if (kind == Kind.CLASS) {
89.159 + final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
89.160 +
89.161 + class2BAOS.put(className.replace('.', '/') + ".class", buffer);
89.162 + return new SimpleJavaFileObject(sibling.toUri(), kind) {
89.163 + @Override
89.164 + public OutputStream openOutputStream() throws IOException {
89.165 + return buffer;
89.166 + }
89.167 + };
89.168 + }
89.169 +
89.170 + if (kind == Kind.SOURCE) {
89.171 + final String n = className.replace('.', '/') + ".java";
89.172 + final URI un;
89.173 + try {
89.174 + un = new URI("mem://" + n);
89.175 + } catch (URISyntaxException ex) {
89.176 + throw new IOException(ex);
89.177 + }
89.178 + return new VirtFO(un/*sibling.toUri()*/, kind, n);
89.179 + }
89.180 +
89.181 + throw new IllegalStateException();
89.182 + }
89.183 +
89.184 + @Override
89.185 + public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException {
89.186 + if (location == StandardLocation.SOURCE_PATH) {
89.187 + if (packageName.equals(pkg)) {
89.188 + return htmlFile;
89.189 + }
89.190 + }
89.191 +
89.192 + return null;
89.193 + }
89.194 +
89.195 + @Override
89.196 + public boolean isSameFile(FileObject a, FileObject b) {
89.197 + if (a instanceof VirtFO && b instanceof VirtFO) {
89.198 + return ((VirtFO)a).getName().equals(((VirtFO)b).getName());
89.199 + }
89.200 +
89.201 + return super.isSameFile(a, b);
89.202 + }
89.203 +
89.204 + class VirtFO extends SimpleJavaFileObject {
89.205 +
89.206 + private final String n;
89.207 +
89.208 + public VirtFO(URI uri, Kind kind, String n) {
89.209 + super(uri, kind);
89.210 + this.n = n;
89.211 + }
89.212 + private final ByteArrayOutputStream data = new ByteArrayOutputStream();
89.213 +
89.214 + @Override
89.215 + public OutputStream openOutputStream() throws IOException {
89.216 + return data;
89.217 + }
89.218 +
89.219 + @Override
89.220 + public String getName() {
89.221 + return n;
89.222 + }
89.223 +
89.224 + @Override
89.225 + public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
89.226 + data.close();
89.227 + return new String(data.toByteArray());
89.228 + }
89.229 + }
89.230 + };
89.231 +
89.232 + ToolProvider.getSystemJavaCompiler().getTask(null, jfm, this, /*XXX:*/Arrays.asList("-source", sourceLevel, "-target", "1.7"), null, Arrays.asList(file)).call();
89.233 +
89.234 + Map<String, byte[]> result = new HashMap<String, byte[]>();
89.235 +
89.236 + for (Map.Entry<String, ByteArrayOutputStream> e : class2BAOS.entrySet()) {
89.237 + result.put(e.getKey(), e.getValue().toByteArray());
89.238 + }
89.239 +
89.240 + return result;
89.241 + }
89.242 +
89.243 +
89.244 + @Override
89.245 + public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
89.246 + errors.add(diagnostic);
89.247 + }
89.248 + private static String findPkg(String java) throws IOException {
89.249 + Pattern p = Pattern.compile("package\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}*;", Pattern.MULTILINE);
89.250 + Matcher m = p.matcher(java);
89.251 + if (!m.find()) {
89.252 + throw new IOException("Can't find package declaration in the java file");
89.253 + }
89.254 + String pkg = m.group(1);
89.255 + return pkg;
89.256 + }
89.257 + private static String findCls(String java) throws IOException {
89.258 + Pattern p = Pattern.compile("class\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}", Pattern.MULTILINE);
89.259 + Matcher m = p.matcher(java);
89.260 + if (!m.find()) {
89.261 + throw new IOException("Can't find package declaration in the java file");
89.262 + }
89.263 + String cls = m.group(1);
89.264 + return cls;
89.265 + }
89.266 +
89.267 + String getHtml() {
89.268 + String fqn = "'" + pkg + '.' + cls + "'";
89.269 + return html.replace("'${fqn}'", fqn);
89.270 + }
89.271 +
89.272 + void assertErrors() {
89.273 + assertFalse(getErrors().isEmpty(), "There are supposed to be some errors");
89.274 + }
89.275 +
89.276 + void assertError(String expMsg) {
89.277 + StringBuilder sb = new StringBuilder();
89.278 + sb.append("Can't find ").append(expMsg).append(" among:");
89.279 + for (Diagnostic<? extends JavaFileObject> e : errors) {
89.280 + String msg = e.getMessage(Locale.US);
89.281 + if (msg.contains(expMsg)) {
89.282 + return;
89.283 + }
89.284 + sb.append("\n");
89.285 + sb.append(msg);
89.286 + }
89.287 + fail(sb.toString());
89.288 + }
89.289 +}
90.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
90.2 +++ b/geo/src/test/java/org/netbeans/html/geo/impl/GeoProcessorTest.java Tue Jan 07 08:21:57 2014 +0100
90.3 @@ -0,0 +1,114 @@
90.4 +/**
90.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
90.6 + *
90.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
90.8 + *
90.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
90.10 + * Other names may be trademarks of their respective owners.
90.11 + *
90.12 + * The contents of this file are subject to the terms of either the GNU
90.13 + * General Public License Version 2 only ("GPL") or the Common
90.14 + * Development and Distribution License("CDDL") (collectively, the
90.15 + * "License"). You may not use this file except in compliance with the
90.16 + * License. You can obtain a copy of the License at
90.17 + * http://www.netbeans.org/cddl-gplv2.html
90.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
90.19 + * specific language governing permissions and limitations under the
90.20 + * License. When distributing the software, include this License Header
90.21 + * Notice in each file and include the License file at
90.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
90.23 + * particular file as subject to the "Classpath" exception as provided
90.24 + * by Oracle in the GPL Version 2 section of the License file that
90.25 + * accompanied this code. If applicable, add the following below the
90.26 + * License Header, with the fields enclosed by brackets [] replaced by
90.27 + * your own identifying information:
90.28 + * "Portions Copyrighted [year] [name of copyright owner]"
90.29 + *
90.30 + * Contributor(s):
90.31 + *
90.32 + * The Original Software is NetBeans. The Initial Developer of the Original
90.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
90.34 + *
90.35 + * If you wish your version of this file to be governed by only the CDDL
90.36 + * or only the GPL Version 2, indicate your decision by adding
90.37 + * "[Contributor] elects to include this software in this distribution
90.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
90.39 + * single choice of license, a recipient has the option to distribute
90.40 + * your version of this file under either the CDDL, the GPL Version 2 or
90.41 + * to extend the choice of license to its licensees as provided above.
90.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
90.43 + * Version 2 license, then the option applies only if the new code is
90.44 + * made subject to such option by the copyright holder.
90.45 + */
90.46 +package org.netbeans.html.geo.impl;
90.47 +
90.48 +import java.io.IOException;
90.49 +import org.testng.annotations.Test;
90.50 +
90.51 +/** Test whether the annotation processor detects errors correctly.
90.52 + *
90.53 + * @author Jaroslav Tulach <jtulach@netbeans.org>
90.54 + */
90.55 +public class GeoProcessorTest {
90.56 +
90.57 + public GeoProcessorTest() {
90.58 + }
90.59 +
90.60 + @Test public void onLocationMethodHasToTakePositionParameter() throws IOException {
90.61 + Compile res = Compile.create("", "package x;\n"
90.62 + + "class UseOnLocation {\n"
90.63 + + " @net.java.html.geo.OnLocation\n"
90.64 + + " public static void cantCallMe() {}\n"
90.65 + + "}\n"
90.66 + );
90.67 + res.assertErrors();
90.68 + res.assertError("first argument must be net.java.html.geo.Position");
90.69 + }
90.70 +
90.71 + @Test public void onLocationMethodCannotBePrivate() throws IOException {
90.72 + Compile res = Compile.create("", "package x;\n"
90.73 + + "class UseOnLocation {\n"
90.74 + + " @net.java.html.geo.OnLocation\n"
90.75 + + " private static void cantCallMe(net.java.html.geo.Position p) {}\n"
90.76 + + "}\n"
90.77 + );
90.78 + res.assertErrors();
90.79 + res.assertError("cannot be private");
90.80 + }
90.81 +
90.82 + @Test public void onErrorHasToExist() throws IOException {
90.83 + Compile res = Compile.create("", "package x;\n"
90.84 + + "class UseOnLocation {\n"
90.85 + + " @net.java.html.geo.OnLocation(onError=\"doesNotExist\")\n"
90.86 + + " static void cantCallMe(net.java.html.geo.Position p) {}\n"
90.87 + + "}\n"
90.88 + );
90.89 + res.assertErrors();
90.90 + res.assertError("not find doesNotExist");
90.91 + }
90.92 +
90.93 + @Test public void onErrorWouldHaveToBeStatic() throws IOException {
90.94 + Compile res = Compile.create("", "package x;\n"
90.95 + + "class UseOnLocation {\n"
90.96 + + " @net.java.html.geo.OnLocation(onError=\"notStatic\")\n"
90.97 + + " static void cantCallMe(net.java.html.geo.Position p) {}\n"
90.98 + + " void notStatic(Exception e) {}\n"
90.99 + + "}\n"
90.100 + );
90.101 + res.assertErrors();
90.102 + res.assertError("have to be static");
90.103 + }
90.104 +
90.105 + @Test public void onErrorMustAcceptExceptionArgument() throws IOException {
90.106 + Compile res = Compile.create("", "package x;\n"
90.107 + + "class UseOnLocation {\n"
90.108 + + " @net.java.html.geo.OnLocation(onError=\"notStatic\")\n"
90.109 + + " static void cantCallMe(net.java.html.geo.Position p) {}\n"
90.110 + + " static void notStatic(java.io.IOException e) {}\n"
90.111 + + "}\n"
90.112 + );
90.113 + res.assertErrors();
90.114 + res.assertError("Error method first argument needs to be Exception");
90.115 + }
90.116 +
90.117 +}
91.1 --- a/html4j-maven-plugin/src/main/java/org/apidesign/html/mojo/ProcessJsAnnotationsMojo.java Thu Dec 19 17:11:01 2013 +0100
91.2 +++ b/html4j-maven-plugin/src/main/java/org/apidesign/html/mojo/ProcessJsAnnotationsMojo.java Tue Jan 07 08:21:57 2014 +0100
91.3 @@ -1,22 +1,44 @@
91.4 /**
91.5 - * HTML via Java(tm) Language Bindings
91.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
91.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
91.8 *
91.9 - * This program is free software: you can redistribute it and/or modify
91.10 - * it under the terms of the GNU General Public License as published by
91.11 - * the Free Software Foundation, version 2 of the License.
91.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
91.13 *
91.14 - * This program is distributed in the hope that it will be useful,
91.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
91.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
91.17 - * GNU General Public License for more details. apidesign.org
91.18 - * designates this particular file as subject to the
91.19 - * "Classpath" exception as provided by apidesign.org
91.20 - * in the License file that accompanied this code.
91.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
91.22 + * Other names may be trademarks of their respective owners.
91.23 *
91.24 - * You should have received a copy of the GNU General Public License
91.25 - * along with this program. Look for COPYING file in the top folder.
91.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
91.27 + * The contents of this file are subject to the terms of either the GNU
91.28 + * General Public License Version 2 only ("GPL") or the Common
91.29 + * Development and Distribution License("CDDL") (collectively, the
91.30 + * "License"). You may not use this file except in compliance with the
91.31 + * License. You can obtain a copy of the License at
91.32 + * http://www.netbeans.org/cddl-gplv2.html
91.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
91.34 + * specific language governing permissions and limitations under the
91.35 + * License. When distributing the software, include this License Header
91.36 + * Notice in each file and include the License file at
91.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
91.38 + * particular file as subject to the "Classpath" exception as provided
91.39 + * by Oracle in the GPL Version 2 section of the License file that
91.40 + * accompanied this code. If applicable, add the following below the
91.41 + * License Header, with the fields enclosed by brackets [] replaced by
91.42 + * your own identifying information:
91.43 + * "Portions Copyrighted [year] [name of copyright owner]"
91.44 + *
91.45 + * Contributor(s):
91.46 + *
91.47 + * The Original Software is NetBeans. The Initial Developer of the Original
91.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
91.49 + *
91.50 + * If you wish your version of this file to be governed by only the CDDL
91.51 + * or only the GPL Version 2, indicate your decision by adding
91.52 + * "[Contributor] elects to include this software in this distribution
91.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
91.54 + * single choice of license, a recipient has the option to distribute
91.55 + * your version of this file under either the CDDL, the GPL Version 2 or
91.56 + * to extend the choice of license to its licensees as provided above.
91.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
91.58 + * Version 2 license, then the option applies only if the new code is
91.59 + * made subject to such option by the copyright holder.
91.60 */
91.61 package org.apidesign.html.mojo;
91.62
92.1 --- a/html4j-maven-plugin/src/test/java/org/apidesign/html/mojo/GenerateBodyTest.java Thu Dec 19 17:11:01 2013 +0100
92.2 +++ b/html4j-maven-plugin/src/test/java/org/apidesign/html/mojo/GenerateBodyTest.java Tue Jan 07 08:21:57 2014 +0100
92.3 @@ -1,22 +1,44 @@
92.4 /**
92.5 - * HTML via Java(tm) Language Bindings
92.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
92.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
92.8 *
92.9 - * This program is free software: you can redistribute it and/or modify
92.10 - * it under the terms of the GNU General Public License as published by
92.11 - * the Free Software Foundation, version 2 of the License.
92.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
92.13 *
92.14 - * This program is distributed in the hope that it will be useful,
92.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
92.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
92.17 - * GNU General Public License for more details. apidesign.org
92.18 - * designates this particular file as subject to the
92.19 - * "Classpath" exception as provided by apidesign.org
92.20 - * in the License file that accompanied this code.
92.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
92.22 + * Other names may be trademarks of their respective owners.
92.23 *
92.24 - * You should have received a copy of the GNU General Public License
92.25 - * along with this program. Look for COPYING file in the top folder.
92.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
92.27 + * The contents of this file are subject to the terms of either the GNU
92.28 + * General Public License Version 2 only ("GPL") or the Common
92.29 + * Development and Distribution License("CDDL") (collectively, the
92.30 + * "License"). You may not use this file except in compliance with the
92.31 + * License. You can obtain a copy of the License at
92.32 + * http://www.netbeans.org/cddl-gplv2.html
92.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
92.34 + * specific language governing permissions and limitations under the
92.35 + * License. When distributing the software, include this License Header
92.36 + * Notice in each file and include the License file at
92.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
92.38 + * particular file as subject to the "Classpath" exception as provided
92.39 + * by Oracle in the GPL Version 2 section of the License file that
92.40 + * accompanied this code. If applicable, add the following below the
92.41 + * License Header, with the fields enclosed by brackets [] replaced by
92.42 + * your own identifying information:
92.43 + * "Portions Copyrighted [year] [name of copyright owner]"
92.44 + *
92.45 + * Contributor(s):
92.46 + *
92.47 + * The Original Software is NetBeans. The Initial Developer of the Original
92.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
92.49 + *
92.50 + * If you wish your version of this file to be governed by only the CDDL
92.51 + * or only the GPL Version 2, indicate your decision by adding
92.52 + * "[Contributor] elects to include this software in this distribution
92.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
92.54 + * single choice of license, a recipient has the option to distribute
92.55 + * your version of this file under either the CDDL, the GPL Version 2 or
92.56 + * to extend the choice of license to its licensees as provided above.
92.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
92.58 + * Version 2 license, then the option applies only if the new code is
92.59 + * made subject to such option by the copyright holder.
92.60 */
92.61 package org.apidesign.html.mojo;
92.62
93.1 --- a/json-tck/pom.xml Thu Dec 19 17:11:01 2013 +0100
93.2 +++ b/json-tck/pom.xml Tue Jan 07 08:21:57 2014 +0100
93.3 @@ -2,11 +2,11 @@
93.4 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
93.5 <modelVersion>4.0.0</modelVersion>
93.6 <parent>
93.7 - <groupId>org.apidesign</groupId>
93.8 - <artifactId>html</artifactId>
93.9 + <groupId>org.netbeans.html</groupId>
93.10 + <artifactId>pom</artifactId>
93.11 <version>0.7-SNAPSHOT</version>
93.12 </parent>
93.13 - <groupId>org.apidesign.html</groupId>
93.14 + <groupId>org.netbeans.html</groupId>
93.15 <artifactId>net.java.html.json.tck</artifactId>
93.16 <version>0.7-SNAPSHOT</version>
93.17 <packaging>bundle</packaging>
93.18 @@ -35,7 +35,7 @@
93.19 </build>
93.20 <dependencies>
93.21 <dependency>
93.22 - <groupId>org.apidesign.html</groupId>
93.23 + <groupId>org.netbeans.html</groupId>
93.24 <artifactId>net.java.html.json</artifactId>
93.25 <version>0.7-SNAPSHOT</version>
93.26 <type>jar</type>
94.1 --- a/json-tck/src/main/java/net/java/html/js/tests/Bodies.java Thu Dec 19 17:11:01 2013 +0100
94.2 +++ b/json-tck/src/main/java/net/java/html/js/tests/Bodies.java Tue Jan 07 08:21:57 2014 +0100
94.3 @@ -1,24 +1,45 @@
94.4 /**
94.5 - * HTML via Java(tm) Language Bindings
94.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
94.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
94.8 *
94.9 - * This program is free software: you can redistribute it and/or modify
94.10 - * it under the terms of the GNU General Public License as published by
94.11 - * the Free Software Foundation, version 2 of the License.
94.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
94.13 *
94.14 - * This program is distributed in the hope that it will be useful,
94.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
94.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
94.17 - * GNU General Public License for more details. apidesign.org
94.18 - * designates this particular file as subject to the
94.19 - * "Classpath" exception as provided by apidesign.org
94.20 - * in the License file that accompanied this code.
94.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
94.22 + * Other names may be trademarks of their respective owners.
94.23 *
94.24 - * You should have received a copy of the GNU General Public License
94.25 - * along with this program. Look for COPYING file in the top folder.
94.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
94.27 + * The contents of this file are subject to the terms of either the GNU
94.28 + * General Public License Version 2 only ("GPL") or the Common
94.29 + * Development and Distribution License("CDDL") (collectively, the
94.30 + * "License"). You may not use this file except in compliance with the
94.31 + * License. You can obtain a copy of the License at
94.32 + * http://www.netbeans.org/cddl-gplv2.html
94.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
94.34 + * specific language governing permissions and limitations under the
94.35 + * License. When distributing the software, include this License Header
94.36 + * Notice in each file and include the License file at
94.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
94.38 + * particular file as subject to the "Classpath" exception as provided
94.39 + * by Oracle in the GPL Version 2 section of the License file that
94.40 + * accompanied this code. If applicable, add the following below the
94.41 + * License Header, with the fields enclosed by brackets [] replaced by
94.42 + * your own identifying information:
94.43 + * "Portions Copyrighted [year] [name of copyright owner]"
94.44 + *
94.45 + * Contributor(s):
94.46 + *
94.47 + * The Original Software is NetBeans. The Initial Developer of the Original
94.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
94.49 + *
94.50 + * If you wish your version of this file to be governed by only the CDDL
94.51 + * or only the GPL Version 2, indicate your decision by adding
94.52 + * "[Contributor] elects to include this software in this distribution
94.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
94.54 + * single choice of license, a recipient has the option to distribute
94.55 + * your version of this file under either the CDDL, the GPL Version 2 or
94.56 + * to extend the choice of license to its licensees as provided above.
94.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
94.58 + * Version 2 license, then the option applies only if the new code is
94.59 + * made subject to such option by the copyright holder.
94.60 */
94.61 -
94.62 package net.java.html.js.tests;
94.63
94.64 import java.util.concurrent.Callable;
95.1 --- a/json-tck/src/main/java/net/java/html/js/tests/Factorial.java Thu Dec 19 17:11:01 2013 +0100
95.2 +++ b/json-tck/src/main/java/net/java/html/js/tests/Factorial.java Tue Jan 07 08:21:57 2014 +0100
95.3 @@ -1,23 +1,45 @@
95.4 /**
95.5 - * HTML via Java(tm) Language Bindings Copyright (C) 2013 Jaroslav Tulach
95.6 - * <jaroslav.tulach@apidesign.org>
95.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
95.8 *
95.9 - * This program is free software: you can redistribute it and/or modify it under
95.10 - * the terms of the GNU General Public License as published by the Free Software
95.11 - * Foundation, version 2 of the License.
95.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
95.13 *
95.14 - * This program is distributed in the hope that it will be useful, but WITHOUT
95.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
95.16 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
95.17 - * details. apidesign.org designates this particular file as subject to the
95.18 - * "Classpath" exception as provided by apidesign.org in the License file that
95.19 - * accompanied this code.
95.20 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
95.21 + * Other names may be trademarks of their respective owners.
95.22 *
95.23 - * You should have received a copy of the GNU General Public License along with
95.24 - * this program. Look for COPYING file in the top folder. If not, see
95.25 - * http://wiki.apidesign.org/wiki/GPLwithClassPathException
95.26 + * The contents of this file are subject to the terms of either the GNU
95.27 + * General Public License Version 2 only ("GPL") or the Common
95.28 + * Development and Distribution License("CDDL") (collectively, the
95.29 + * "License"). You may not use this file except in compliance with the
95.30 + * License. You can obtain a copy of the License at
95.31 + * http://www.netbeans.org/cddl-gplv2.html
95.32 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
95.33 + * specific language governing permissions and limitations under the
95.34 + * License. When distributing the software, include this License Header
95.35 + * Notice in each file and include the License file at
95.36 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
95.37 + * particular file as subject to the "Classpath" exception as provided
95.38 + * by Oracle in the GPL Version 2 section of the License file that
95.39 + * accompanied this code. If applicable, add the following below the
95.40 + * License Header, with the fields enclosed by brackets [] replaced by
95.41 + * your own identifying information:
95.42 + * "Portions Copyrighted [year] [name of copyright owner]"
95.43 + *
95.44 + * Contributor(s):
95.45 + *
95.46 + * The Original Software is NetBeans. The Initial Developer of the Original
95.47 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
95.48 + *
95.49 + * If you wish your version of this file to be governed by only the CDDL
95.50 + * or only the GPL Version 2, indicate your decision by adding
95.51 + * "[Contributor] elects to include this software in this distribution
95.52 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
95.53 + * single choice of license, a recipient has the option to distribute
95.54 + * your version of this file under either the CDDL, the GPL Version 2 or
95.55 + * to extend the choice of license to its licensees as provided above.
95.56 + * However, if you add GPL Version 2 code and therefore, elected the GPL
95.57 + * Version 2 license, then the option applies only if the new code is
95.58 + * made subject to such option by the copyright holder.
95.59 */
95.60 -
95.61 package net.java.html.js.tests;
95.62
95.63 import net.java.html.js.JavaScriptBody;
96.1 --- a/json-tck/src/main/java/net/java/html/js/tests/JavaScriptBodyTest.java Thu Dec 19 17:11:01 2013 +0100
96.2 +++ b/json-tck/src/main/java/net/java/html/js/tests/JavaScriptBodyTest.java Tue Jan 07 08:21:57 2014 +0100
96.3 @@ -1,22 +1,44 @@
96.4 /**
96.5 - * HTML via Java(tm) Language Bindings
96.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
96.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
96.8 *
96.9 - * This program is free software: you can redistribute it and/or modify
96.10 - * it under the terms of the GNU General Public License as published by
96.11 - * the Free Software Foundation, version 2 of the License.
96.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
96.13 *
96.14 - * This program is distributed in the hope that it will be useful,
96.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
96.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
96.17 - * GNU General Public License for more details. apidesign.org
96.18 - * designates this particular file as subject to the
96.19 - * "Classpath" exception as provided by apidesign.org
96.20 - * in the License file that accompanied this code.
96.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
96.22 + * Other names may be trademarks of their respective owners.
96.23 *
96.24 - * You should have received a copy of the GNU General Public License
96.25 - * along with this program. Look for COPYING file in the top folder.
96.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
96.27 + * The contents of this file are subject to the terms of either the GNU
96.28 + * General Public License Version 2 only ("GPL") or the Common
96.29 + * Development and Distribution License("CDDL") (collectively, the
96.30 + * "License"). You may not use this file except in compliance with the
96.31 + * License. You can obtain a copy of the License at
96.32 + * http://www.netbeans.org/cddl-gplv2.html
96.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
96.34 + * specific language governing permissions and limitations under the
96.35 + * License. When distributing the software, include this License Header
96.36 + * Notice in each file and include the License file at
96.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
96.38 + * particular file as subject to the "Classpath" exception as provided
96.39 + * by Oracle in the GPL Version 2 section of the License file that
96.40 + * accompanied this code. If applicable, add the following below the
96.41 + * License Header, with the fields enclosed by brackets [] replaced by
96.42 + * your own identifying information:
96.43 + * "Portions Copyrighted [year] [name of copyright owner]"
96.44 + *
96.45 + * Contributor(s):
96.46 + *
96.47 + * The Original Software is NetBeans. The Initial Developer of the Original
96.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
96.49 + *
96.50 + * If you wish your version of this file to be governed by only the CDDL
96.51 + * or only the GPL Version 2, indicate your decision by adding
96.52 + * "[Contributor] elects to include this software in this distribution
96.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
96.54 + * single choice of license, a recipient has the option to distribute
96.55 + * your version of this file under either the CDDL, the GPL Version 2 or
96.56 + * to extend the choice of license to its licensees as provided above.
96.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
96.58 + * Version 2 license, then the option applies only if the new code is
96.59 + * made subject to such option by the copyright holder.
96.60 */
96.61 package net.java.html.js.tests;
96.62
97.1 --- a/json-tck/src/main/java/net/java/html/js/tests/Sum.java Thu Dec 19 17:11:01 2013 +0100
97.2 +++ b/json-tck/src/main/java/net/java/html/js/tests/Sum.java Tue Jan 07 08:21:57 2014 +0100
97.3 @@ -1,24 +1,45 @@
97.4 /**
97.5 - * HTML via Java(tm) Language Bindings
97.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
97.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
97.8 *
97.9 - * This program is free software: you can redistribute it and/or modify
97.10 - * it under the terms of the GNU General Public License as published by
97.11 - * the Free Software Foundation, version 2 of the License.
97.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
97.13 *
97.14 - * This program is distributed in the hope that it will be useful,
97.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
97.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
97.17 - * GNU General Public License for more details. apidesign.org
97.18 - * designates this particular file as subject to the
97.19 - * "Classpath" exception as provided by apidesign.org
97.20 - * in the License file that accompanied this code.
97.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
97.22 + * Other names may be trademarks of their respective owners.
97.23 *
97.24 - * You should have received a copy of the GNU General Public License
97.25 - * along with this program. Look for COPYING file in the top folder.
97.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
97.27 + * The contents of this file are subject to the terms of either the GNU
97.28 + * General Public License Version 2 only ("GPL") or the Common
97.29 + * Development and Distribution License("CDDL") (collectively, the
97.30 + * "License"). You may not use this file except in compliance with the
97.31 + * License. You can obtain a copy of the License at
97.32 + * http://www.netbeans.org/cddl-gplv2.html
97.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
97.34 + * specific language governing permissions and limitations under the
97.35 + * License. When distributing the software, include this License Header
97.36 + * Notice in each file and include the License file at
97.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
97.38 + * particular file as subject to the "Classpath" exception as provided
97.39 + * by Oracle in the GPL Version 2 section of the License file that
97.40 + * accompanied this code. If applicable, add the following below the
97.41 + * License Header, with the fields enclosed by brackets [] replaced by
97.42 + * your own identifying information:
97.43 + * "Portions Copyrighted [year] [name of copyright owner]"
97.44 + *
97.45 + * Contributor(s):
97.46 + *
97.47 + * The Original Software is NetBeans. The Initial Developer of the Original
97.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
97.49 + *
97.50 + * If you wish your version of this file to be governed by only the CDDL
97.51 + * or only the GPL Version 2, indicate your decision by adding
97.52 + * "[Contributor] elects to include this software in this distribution
97.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
97.54 + * single choice of license, a recipient has the option to distribute
97.55 + * your version of this file under either the CDDL, the GPL Version 2 or
97.56 + * to extend the choice of license to its licensees as provided above.
97.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
97.58 + * Version 2 license, then the option applies only if the new code is
97.59 + * made subject to such option by the copyright holder.
97.60 */
97.61 -
97.62 package net.java.html.js.tests;
97.63
97.64 /**
98.1 --- a/json-tck/src/main/java/net/java/html/json/tests/ConvertTypesTest.java Thu Dec 19 17:11:01 2013 +0100
98.2 +++ b/json-tck/src/main/java/net/java/html/json/tests/ConvertTypesTest.java Tue Jan 07 08:21:57 2014 +0100
98.3 @@ -1,22 +1,44 @@
98.4 /**
98.5 - * HTML via Java(tm) Language Bindings
98.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
98.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
98.8 *
98.9 - * This program is free software: you can redistribute it and/or modify
98.10 - * it under the terms of the GNU General Public License as published by
98.11 - * the Free Software Foundation, version 2 of the License.
98.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
98.13 *
98.14 - * This program is distributed in the hope that it will be useful,
98.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
98.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
98.17 - * GNU General Public License for more details. apidesign.org
98.18 - * designates this particular file as subject to the
98.19 - * "Classpath" exception as provided by apidesign.org
98.20 - * in the License file that accompanied this code.
98.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
98.22 + * Other names may be trademarks of their respective owners.
98.23 *
98.24 - * You should have received a copy of the GNU General Public License
98.25 - * along with this program. Look for COPYING file in the top folder.
98.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
98.27 + * The contents of this file are subject to the terms of either the GNU
98.28 + * General Public License Version 2 only ("GPL") or the Common
98.29 + * Development and Distribution License("CDDL") (collectively, the
98.30 + * "License"). You may not use this file except in compliance with the
98.31 + * License. You can obtain a copy of the License at
98.32 + * http://www.netbeans.org/cddl-gplv2.html
98.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
98.34 + * specific language governing permissions and limitations under the
98.35 + * License. When distributing the software, include this License Header
98.36 + * Notice in each file and include the License file at
98.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
98.38 + * particular file as subject to the "Classpath" exception as provided
98.39 + * by Oracle in the GPL Version 2 section of the License file that
98.40 + * accompanied this code. If applicable, add the following below the
98.41 + * License Header, with the fields enclosed by brackets [] replaced by
98.42 + * your own identifying information:
98.43 + * "Portions Copyrighted [year] [name of copyright owner]"
98.44 + *
98.45 + * Contributor(s):
98.46 + *
98.47 + * The Original Software is NetBeans. The Initial Developer of the Original
98.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
98.49 + *
98.50 + * If you wish your version of this file to be governed by only the CDDL
98.51 + * or only the GPL Version 2, indicate your decision by adding
98.52 + * "[Contributor] elects to include this software in this distribution
98.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
98.54 + * single choice of license, a recipient has the option to distribute
98.55 + * your version of this file under either the CDDL, the GPL Version 2 or
98.56 + * to extend the choice of license to its licensees as provided above.
98.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
98.58 + * Version 2 license, then the option applies only if the new code is
98.59 + * made subject to such option by the copyright holder.
98.60 */
98.61 package net.java.html.json.tests;
98.62
98.63 @@ -27,7 +49,6 @@
98.64 import java.util.Map;
98.65 import net.java.html.BrwsrCtx;
98.66 import net.java.html.json.Models;
98.67 -import org.apidesign.html.json.impl.JSON;
98.68 import org.apidesign.html.json.tck.KOTest;
98.69
98.70 /**
98.71 @@ -64,7 +85,7 @@
98.72 public void testConvertToPeople() throws Exception {
98.73 final Object o = createJSON(true);
98.74
98.75 - Person p = JSON.read(newContext(), Person.class, o);
98.76 + Person p = Models.fromRaw(newContext(), Person.class, o);
98.77
98.78 assert "son".equals(p.getFirstName()) : "First name: " + p.getFirstName();
98.79 assert "dj".equals(p.getLastName()) : "Last name: " + p.getLastName();
98.80 @@ -101,7 +122,7 @@
98.81 public void testConvertToPeopleWithoutSex() throws Exception {
98.82 final Object o = createJSON(false);
98.83
98.84 - Person p = JSON.read(newContext(), Person.class, o);
98.85 + Person p = Models.fromRaw(newContext(), Person.class, o);
98.86
98.87 assert "son".equals(p.getFirstName()) : "First name: " + p.getFirstName();
98.88 assert "dj".equals(p.getLastName()) : "Last name: " + p.getLastName();
99.1 --- a/json-tck/src/main/java/net/java/html/json/tests/JSONTest.java Thu Dec 19 17:11:01 2013 +0100
99.2 +++ b/json-tck/src/main/java/net/java/html/json/tests/JSONTest.java Tue Jan 07 08:21:57 2014 +0100
99.3 @@ -1,22 +1,44 @@
99.4 /**
99.5 - * HTML via Java(tm) Language Bindings
99.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
99.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
99.8 *
99.9 - * This program is free software: you can redistribute it and/or modify
99.10 - * it under the terms of the GNU General Public License as published by
99.11 - * the Free Software Foundation, version 2 of the License.
99.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
99.13 *
99.14 - * This program is distributed in the hope that it will be useful,
99.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
99.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
99.17 - * GNU General Public License for more details. apidesign.org
99.18 - * designates this particular file as subject to the
99.19 - * "Classpath" exception as provided by apidesign.org
99.20 - * in the License file that accompanied this code.
99.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
99.22 + * Other names may be trademarks of their respective owners.
99.23 *
99.24 - * You should have received a copy of the GNU General Public License
99.25 - * along with this program. Look for COPYING file in the top folder.
99.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
99.27 + * The contents of this file are subject to the terms of either the GNU
99.28 + * General Public License Version 2 only ("GPL") or the Common
99.29 + * Development and Distribution License("CDDL") (collectively, the
99.30 + * "License"). You may not use this file except in compliance with the
99.31 + * License. You can obtain a copy of the License at
99.32 + * http://www.netbeans.org/cddl-gplv2.html
99.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
99.34 + * specific language governing permissions and limitations under the
99.35 + * License. When distributing the software, include this License Header
99.36 + * Notice in each file and include the License file at
99.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
99.38 + * particular file as subject to the "Classpath" exception as provided
99.39 + * by Oracle in the GPL Version 2 section of the License file that
99.40 + * accompanied this code. If applicable, add the following below the
99.41 + * License Header, with the fields enclosed by brackets [] replaced by
99.42 + * your own identifying information:
99.43 + * "Portions Copyrighted [year] [name of copyright owner]"
99.44 + *
99.45 + * Contributor(s):
99.46 + *
99.47 + * The Original Software is NetBeans. The Initial Developer of the Original
99.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
99.49 + *
99.50 + * If you wish your version of this file to be governed by only the CDDL
99.51 + * or only the GPL Version 2, indicate your decision by adding
99.52 + * "[Contributor] elects to include this software in this distribution
99.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
99.54 + * single choice of license, a recipient has the option to distribute
99.55 + * your version of this file under either the CDDL, the GPL Version 2 or
99.56 + * to extend the choice of license to its licensees as provided above.
99.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
99.58 + * Version 2 license, then the option applies only if the new code is
99.59 + * made subject to such option by the copyright holder.
99.60 */
99.61 package net.java.html.json.tests;
99.62
99.63 @@ -27,7 +49,6 @@
99.64 import net.java.html.json.Models;
99.65 import net.java.html.json.OnReceive;
99.66 import net.java.html.json.Property;
99.67 -import org.apidesign.html.json.impl.JSON;
99.68 import org.apidesign.html.json.tck.KOTest;
99.69
99.70 /** Need to verify that models produce reasonable JSON objects.
99.71 @@ -62,7 +83,7 @@
99.72 throw new IllegalStateException("Can't parse " + p).initCause(ex);
99.73 }
99.74
99.75 - Person p2 = JSON.read(newContext(), Person.class, json);
99.76 + Person p2 = Models.fromRaw(newContext(), Person.class, json);
99.77
99.78 assert p2.getFirstName().equals(p.getFirstName()) :
99.79 "Should be the same: " + p.getFirstName() + " != " + p2.getFirstName();
99.80 @@ -82,7 +103,7 @@
99.81 throw new IllegalStateException("Can't parse " + txt).initCause(ex);
99.82 }
99.83
99.84 - Person p2 = JSON.read(newContext(), Person.class, json);
99.85 + Person p2 = Models.fromRaw(newContext(), Person.class, json);
99.86
99.87 assert p2.getFirstName().equals(p.getFirstName()) :
99.88 "Should be the same: " + p.getFirstName() + " != " + p2.getFirstName();
99.89 @@ -102,7 +123,7 @@
99.90 throw new IllegalStateException("Can't parse " + txt).initCause(ex);
99.91 }
99.92
99.93 - Person p2 = JSON.read(newContext(), Person.class, json);
99.94 + Person p2 = Models.fromRaw(newContext(), Person.class, json);
99.95
99.96 assert p2.getFirstName().equals(p.getFirstName()) :
99.97 "Should be the same: " + p.getFirstName() + " != " + p2.getFirstName();
99.98 @@ -122,7 +143,7 @@
99.99 throw new IllegalStateException("Can't parse " + txt).initCause(ex);
99.100 }
99.101
99.102 - Person p2 = JSON.read(newContext(), Person.class, json);
99.103 + Person p2 = Models.fromRaw(newContext(), Person.class, json);
99.104
99.105 assert p2.getFirstName().equals(p.getFirstName()) :
99.106 "Should be the same: " + p.getFirstName() + " != " + p2.getFirstName();
100.1 --- a/json-tck/src/main/java/net/java/html/json/tests/KnockoutTest.java Thu Dec 19 17:11:01 2013 +0100
100.2 +++ b/json-tck/src/main/java/net/java/html/json/tests/KnockoutTest.java Tue Jan 07 08:21:57 2014 +0100
100.3 @@ -1,22 +1,44 @@
100.4 /**
100.5 - * HTML via Java(tm) Language Bindings
100.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
100.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
100.8 *
100.9 - * This program is free software: you can redistribute it and/or modify
100.10 - * it under the terms of the GNU General Public License as published by
100.11 - * the Free Software Foundation, version 2 of the License.
100.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
100.13 *
100.14 - * This program is distributed in the hope that it will be useful,
100.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
100.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
100.17 - * GNU General Public License for more details. apidesign.org
100.18 - * designates this particular file as subject to the
100.19 - * "Classpath" exception as provided by apidesign.org
100.20 - * in the License file that accompanied this code.
100.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
100.22 + * Other names may be trademarks of their respective owners.
100.23 *
100.24 - * You should have received a copy of the GNU General Public License
100.25 - * along with this program. Look for COPYING file in the top folder.
100.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
100.27 + * The contents of this file are subject to the terms of either the GNU
100.28 + * General Public License Version 2 only ("GPL") or the Common
100.29 + * Development and Distribution License("CDDL") (collectively, the
100.30 + * "License"). You may not use this file except in compliance with the
100.31 + * License. You can obtain a copy of the License at
100.32 + * http://www.netbeans.org/cddl-gplv2.html
100.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
100.34 + * specific language governing permissions and limitations under the
100.35 + * License. When distributing the software, include this License Header
100.36 + * Notice in each file and include the License file at
100.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
100.38 + * particular file as subject to the "Classpath" exception as provided
100.39 + * by Oracle in the GPL Version 2 section of the License file that
100.40 + * accompanied this code. If applicable, add the following below the
100.41 + * License Header, with the fields enclosed by brackets [] replaced by
100.42 + * your own identifying information:
100.43 + * "Portions Copyrighted [year] [name of copyright owner]"
100.44 + *
100.45 + * Contributor(s):
100.46 + *
100.47 + * The Original Software is NetBeans. The Initial Developer of the Original
100.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
100.49 + *
100.50 + * If you wish your version of this file to be governed by only the CDDL
100.51 + * or only the GPL Version 2, indicate your decision by adding
100.52 + * "[Contributor] elects to include this software in this distribution
100.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
100.54 + * single choice of license, a recipient has the option to distribute
100.55 + * your version of this file under either the CDDL, the GPL Version 2 or
100.56 + * to extend the choice of license to its licensees as provided above.
100.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
100.58 + * Version 2 license, then the option applies only if the new code is
100.59 + * made subject to such option by the copyright holder.
100.60 */
100.61 package net.java.html.json.tests;
100.62
100.63 @@ -28,6 +50,7 @@
100.64 import net.java.html.json.Models;
100.65 import net.java.html.json.Property;
100.66 import org.apidesign.html.json.tck.KOTest;
100.67 +import org.apidesign.html.json.tck.KnockoutTCK;
100.68
100.69 /**
100.70 *
101.1 --- a/json-tck/src/main/java/net/java/html/json/tests/OperationsTest.java Thu Dec 19 17:11:01 2013 +0100
101.2 +++ b/json-tck/src/main/java/net/java/html/json/tests/OperationsTest.java Tue Jan 07 08:21:57 2014 +0100
101.3 @@ -1,22 +1,44 @@
101.4 /**
101.5 - * HTML via Java(tm) Language Bindings
101.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
101.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
101.8 *
101.9 - * This program is free software: you can redistribute it and/or modify
101.10 - * it under the terms of the GNU General Public License as published by
101.11 - * the Free Software Foundation, version 2 of the License.
101.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
101.13 *
101.14 - * This program is distributed in the hope that it will be useful,
101.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
101.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
101.17 - * GNU General Public License for more details. apidesign.org
101.18 - * designates this particular file as subject to the
101.19 - * "Classpath" exception as provided by apidesign.org
101.20 - * in the License file that accompanied this code.
101.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
101.22 + * Other names may be trademarks of their respective owners.
101.23 *
101.24 - * You should have received a copy of the GNU General Public License
101.25 - * along with this program. Look for COPYING file in the top folder.
101.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
101.27 + * The contents of this file are subject to the terms of either the GNU
101.28 + * General Public License Version 2 only ("GPL") or the Common
101.29 + * Development and Distribution License("CDDL") (collectively, the
101.30 + * "License"). You may not use this file except in compliance with the
101.31 + * License. You can obtain a copy of the License at
101.32 + * http://www.netbeans.org/cddl-gplv2.html
101.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
101.34 + * specific language governing permissions and limitations under the
101.35 + * License. When distributing the software, include this License Header
101.36 + * Notice in each file and include the License file at
101.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
101.38 + * particular file as subject to the "Classpath" exception as provided
101.39 + * by Oracle in the GPL Version 2 section of the License file that
101.40 + * accompanied this code. If applicable, add the following below the
101.41 + * License Header, with the fields enclosed by brackets [] replaced by
101.42 + * your own identifying information:
101.43 + * "Portions Copyrighted [year] [name of copyright owner]"
101.44 + *
101.45 + * Contributor(s):
101.46 + *
101.47 + * The Original Software is NetBeans. The Initial Developer of the Original
101.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
101.49 + *
101.50 + * If you wish your version of this file to be governed by only the CDDL
101.51 + * or only the GPL Version 2, indicate your decision by adding
101.52 + * "[Contributor] elects to include this software in this distribution
101.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
101.54 + * single choice of license, a recipient has the option to distribute
101.55 + * your version of this file under either the CDDL, the GPL Version 2 or
101.56 + * to extend the choice of license to its licensees as provided above.
101.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
101.58 + * Version 2 license, then the option applies only if the new code is
101.59 + * made subject to such option by the copyright holder.
101.60 */
101.61 package net.java.html.json.tests;
101.62
102.1 --- a/json-tck/src/main/java/net/java/html/json/tests/PairModel.java Thu Dec 19 17:11:01 2013 +0100
102.2 +++ b/json-tck/src/main/java/net/java/html/json/tests/PairModel.java Tue Jan 07 08:21:57 2014 +0100
102.3 @@ -1,22 +1,44 @@
102.4 /**
102.5 - * HTML via Java(tm) Language Bindings
102.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
102.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
102.8 *
102.9 - * This program is free software: you can redistribute it and/or modify
102.10 - * it under the terms of the GNU General Public License as published by
102.11 - * the Free Software Foundation, version 2 of the License.
102.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
102.13 *
102.14 - * This program is distributed in the hope that it will be useful,
102.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
102.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
102.17 - * GNU General Public License for more details. apidesign.org
102.18 - * designates this particular file as subject to the
102.19 - * "Classpath" exception as provided by apidesign.org
102.20 - * in the License file that accompanied this code.
102.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
102.22 + * Other names may be trademarks of their respective owners.
102.23 *
102.24 - * You should have received a copy of the GNU General Public License
102.25 - * along with this program. Look for COPYING file in the top folder.
102.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
102.27 + * The contents of this file are subject to the terms of either the GNU
102.28 + * General Public License Version 2 only ("GPL") or the Common
102.29 + * Development and Distribution License("CDDL") (collectively, the
102.30 + * "License"). You may not use this file except in compliance with the
102.31 + * License. You can obtain a copy of the License at
102.32 + * http://www.netbeans.org/cddl-gplv2.html
102.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
102.34 + * specific language governing permissions and limitations under the
102.35 + * License. When distributing the software, include this License Header
102.36 + * Notice in each file and include the License file at
102.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
102.38 + * particular file as subject to the "Classpath" exception as provided
102.39 + * by Oracle in the GPL Version 2 section of the License file that
102.40 + * accompanied this code. If applicable, add the following below the
102.41 + * License Header, with the fields enclosed by brackets [] replaced by
102.42 + * your own identifying information:
102.43 + * "Portions Copyrighted [year] [name of copyright owner]"
102.44 + *
102.45 + * Contributor(s):
102.46 + *
102.47 + * The Original Software is NetBeans. The Initial Developer of the Original
102.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
102.49 + *
102.50 + * If you wish your version of this file to be governed by only the CDDL
102.51 + * or only the GPL Version 2, indicate your decision by adding
102.52 + * "[Contributor] elects to include this software in this distribution
102.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
102.54 + * single choice of license, a recipient has the option to distribute
102.55 + * your version of this file under either the CDDL, the GPL Version 2 or
102.56 + * to extend the choice of license to its licensees as provided above.
102.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
102.58 + * Version 2 license, then the option applies only if the new code is
102.59 + * made subject to such option by the copyright holder.
102.60 */
102.61 package net.java.html.json.tests;
102.62
103.1 --- a/json-tck/src/main/java/net/java/html/json/tests/PersonImpl.java Thu Dec 19 17:11:01 2013 +0100
103.2 +++ b/json-tck/src/main/java/net/java/html/json/tests/PersonImpl.java Tue Jan 07 08:21:57 2014 +0100
103.3 @@ -1,22 +1,44 @@
103.4 /**
103.5 - * HTML via Java(tm) Language Bindings
103.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
103.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
103.8 *
103.9 - * This program is free software: you can redistribute it and/or modify
103.10 - * it under the terms of the GNU General Public License as published by
103.11 - * the Free Software Foundation, version 2 of the License.
103.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
103.13 *
103.14 - * This program is distributed in the hope that it will be useful,
103.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
103.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
103.17 - * GNU General Public License for more details. apidesign.org
103.18 - * designates this particular file as subject to the
103.19 - * "Classpath" exception as provided by apidesign.org
103.20 - * in the License file that accompanied this code.
103.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
103.22 + * Other names may be trademarks of their respective owners.
103.23 *
103.24 - * You should have received a copy of the GNU General Public License
103.25 - * along with this program. Look for COPYING file in the top folder.
103.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
103.27 + * The contents of this file are subject to the terms of either the GNU
103.28 + * General Public License Version 2 only ("GPL") or the Common
103.29 + * Development and Distribution License("CDDL") (collectively, the
103.30 + * "License"). You may not use this file except in compliance with the
103.31 + * License. You can obtain a copy of the License at
103.32 + * http://www.netbeans.org/cddl-gplv2.html
103.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
103.34 + * specific language governing permissions and limitations under the
103.35 + * License. When distributing the software, include this License Header
103.36 + * Notice in each file and include the License file at
103.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
103.38 + * particular file as subject to the "Classpath" exception as provided
103.39 + * by Oracle in the GPL Version 2 section of the License file that
103.40 + * accompanied this code. If applicable, add the following below the
103.41 + * License Header, with the fields enclosed by brackets [] replaced by
103.42 + * your own identifying information:
103.43 + * "Portions Copyrighted [year] [name of copyright owner]"
103.44 + *
103.45 + * Contributor(s):
103.46 + *
103.47 + * The Original Software is NetBeans. The Initial Developer of the Original
103.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
103.49 + *
103.50 + * If you wish your version of this file to be governed by only the CDDL
103.51 + * or only the GPL Version 2, indicate your decision by adding
103.52 + * "[Contributor] elects to include this software in this distribution
103.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
103.54 + * single choice of license, a recipient has the option to distribute
103.55 + * your version of this file under either the CDDL, the GPL Version 2 or
103.56 + * to extend the choice of license to its licensees as provided above.
103.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
103.58 + * Version 2 license, then the option applies only if the new code is
103.59 + * made subject to such option by the copyright holder.
103.60 */
103.61 package net.java.html.json.tests;
103.62
104.1 --- a/json-tck/src/main/java/net/java/html/json/tests/Sex.java Thu Dec 19 17:11:01 2013 +0100
104.2 +++ b/json-tck/src/main/java/net/java/html/json/tests/Sex.java Tue Jan 07 08:21:57 2014 +0100
104.3 @@ -1,22 +1,44 @@
104.4 /**
104.5 - * HTML via Java(tm) Language Bindings
104.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
104.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
104.8 *
104.9 - * This program is free software: you can redistribute it and/or modify
104.10 - * it under the terms of the GNU General Public License as published by
104.11 - * the Free Software Foundation, version 2 of the License.
104.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
104.13 *
104.14 - * This program is distributed in the hope that it will be useful,
104.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
104.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
104.17 - * GNU General Public License for more details. apidesign.org
104.18 - * designates this particular file as subject to the
104.19 - * "Classpath" exception as provided by apidesign.org
104.20 - * in the License file that accompanied this code.
104.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
104.22 + * Other names may be trademarks of their respective owners.
104.23 *
104.24 - * You should have received a copy of the GNU General Public License
104.25 - * along with this program. Look for COPYING file in the top folder.
104.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
104.27 + * The contents of this file are subject to the terms of either the GNU
104.28 + * General Public License Version 2 only ("GPL") or the Common
104.29 + * Development and Distribution License("CDDL") (collectively, the
104.30 + * "License"). You may not use this file except in compliance with the
104.31 + * License. You can obtain a copy of the License at
104.32 + * http://www.netbeans.org/cddl-gplv2.html
104.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
104.34 + * specific language governing permissions and limitations under the
104.35 + * License. When distributing the software, include this License Header
104.36 + * Notice in each file and include the License file at
104.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
104.38 + * particular file as subject to the "Classpath" exception as provided
104.39 + * by Oracle in the GPL Version 2 section of the License file that
104.40 + * accompanied this code. If applicable, add the following below the
104.41 + * License Header, with the fields enclosed by brackets [] replaced by
104.42 + * your own identifying information:
104.43 + * "Portions Copyrighted [year] [name of copyright owner]"
104.44 + *
104.45 + * Contributor(s):
104.46 + *
104.47 + * The Original Software is NetBeans. The Initial Developer of the Original
104.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
104.49 + *
104.50 + * If you wish your version of this file to be governed by only the CDDL
104.51 + * or only the GPL Version 2, indicate your decision by adding
104.52 + * "[Contributor] elects to include this software in this distribution
104.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
104.54 + * single choice of license, a recipient has the option to distribute
104.55 + * your version of this file under either the CDDL, the GPL Version 2 or
104.56 + * to extend the choice of license to its licensees as provided above.
104.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
104.58 + * Version 2 license, then the option applies only if the new code is
104.59 + * made subject to such option by the copyright holder.
104.60 */
104.61 package net.java.html.json.tests;
104.62
105.1 --- a/json-tck/src/main/java/net/java/html/json/tests/Utils.java Thu Dec 19 17:11:01 2013 +0100
105.2 +++ b/json-tck/src/main/java/net/java/html/json/tests/Utils.java Tue Jan 07 08:21:57 2014 +0100
105.3 @@ -1,26 +1,49 @@
105.4 /**
105.5 - * HTML via Java(tm) Language Bindings
105.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
105.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
105.8 *
105.9 - * This program is free software: you can redistribute it and/or modify
105.10 - * it under the terms of the GNU General Public License as published by
105.11 - * the Free Software Foundation, version 2 of the License.
105.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
105.13 *
105.14 - * This program is distributed in the hope that it will be useful,
105.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
105.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
105.17 - * GNU General Public License for more details. apidesign.org
105.18 - * designates this particular file as subject to the
105.19 - * "Classpath" exception as provided by apidesign.org
105.20 - * in the License file that accompanied this code.
105.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
105.22 + * Other names may be trademarks of their respective owners.
105.23 *
105.24 - * You should have received a copy of the GNU General Public License
105.25 - * along with this program. Look for COPYING file in the top folder.
105.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
105.27 + * The contents of this file are subject to the terms of either the GNU
105.28 + * General Public License Version 2 only ("GPL") or the Common
105.29 + * Development and Distribution License("CDDL") (collectively, the
105.30 + * "License"). You may not use this file except in compliance with the
105.31 + * License. You can obtain a copy of the License at
105.32 + * http://www.netbeans.org/cddl-gplv2.html
105.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
105.34 + * specific language governing permissions and limitations under the
105.35 + * License. When distributing the software, include this License Header
105.36 + * Notice in each file and include the License file at
105.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
105.38 + * particular file as subject to the "Classpath" exception as provided
105.39 + * by Oracle in the GPL Version 2 section of the License file that
105.40 + * accompanied this code. If applicable, add the following below the
105.41 + * License Header, with the fields enclosed by brackets [] replaced by
105.42 + * your own identifying information:
105.43 + * "Portions Copyrighted [year] [name of copyright owner]"
105.44 + *
105.45 + * Contributor(s):
105.46 + *
105.47 + * The Original Software is NetBeans. The Initial Developer of the Original
105.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
105.49 + *
105.50 + * If you wish your version of this file to be governed by only the CDDL
105.51 + * or only the GPL Version 2, indicate your decision by adding
105.52 + * "[Contributor] elects to include this software in this distribution
105.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
105.54 + * single choice of license, a recipient has the option to distribute
105.55 + * your version of this file under either the CDDL, the GPL Version 2 or
105.56 + * to extend the choice of license to its licensees as provided above.
105.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
105.58 + * Version 2 license, then the option applies only if the new code is
105.59 + * made subject to such option by the copyright holder.
105.60 */
105.61 package net.java.html.json.tests;
105.62
105.63 import java.net.URI;
105.64 +import java.util.Collections;
105.65 import java.util.Map;
105.66 import java.util.ServiceLoader;
105.67 import net.java.html.BrwsrCtx;
105.68 @@ -30,12 +53,18 @@
105.69 *
105.70 * @author Jaroslav Tulach <jtulach@netbeans.org>
105.71 */
105.72 -final class Utils {
105.73 +public final class Utils {
105.74 + private static KnockoutTCK instantiatedTCK;
105.75 +
105.76 private Utils() {
105.77 }
105.78 +
105.79 + public static void registerTCK(KnockoutTCK tck) {
105.80 + instantiatedTCK = tck;
105.81 + }
105.82
105.83 static BrwsrCtx newContext(Class<?> clazz) {
105.84 - for (KnockoutTCK tck : ServiceLoader.load(KnockoutTCK.class, cl(clazz))) {
105.85 + for (KnockoutTCK tck : tcks(clazz)) {
105.86 BrwsrCtx c = tck.createContext();
105.87 if (c != null) {
105.88 return c;
105.89 @@ -44,7 +73,7 @@
105.90 throw new AssertionError("Can't find appropriate Context in ServiceLoader!");
105.91 }
105.92 static Object createObject(Map<String,Object> values, Class<?> clazz) {
105.93 - for (KnockoutTCK tck : ServiceLoader.load(KnockoutTCK.class, cl(clazz))) {
105.94 + for (KnockoutTCK tck : tcks(clazz)) {
105.95 Object o = tck.createJSON(values);
105.96 if (o != null) {
105.97 return o;
105.98 @@ -55,11 +84,18 @@
105.99 static Object executeScript(Class<?> clazz,
105.100 String script, Object... arguments
105.101 ) throws Exception {
105.102 - for (KnockoutTCK tck : ServiceLoader.load(KnockoutTCK.class, cl(clazz))) {
105.103 + for (KnockoutTCK tck : tcks(clazz)) {
105.104 return tck.executeScript(script, arguments);
105.105 }
105.106 throw new AssertionError("Can't find appropriate Context in ServiceLoader!");
105.107 }
105.108 +
105.109 + private static Iterable<KnockoutTCK> tcks(Class<?> clazz) {
105.110 + if (instantiatedTCK != null) {
105.111 + return Collections.singleton(instantiatedTCK);
105.112 + }
105.113 + return ServiceLoader.load(KnockoutTCK.class, cl(clazz));
105.114 + }
105.115
105.116 static Object exposeHTML(Class<?> clazz, String html) throws Exception {
105.117 String s =
105.118 @@ -76,7 +112,7 @@
105.119
105.120 static String prepareURL(
105.121 Class<?> clazz, String content, String mimeType, String... parameters) {
105.122 - for (KnockoutTCK tck : ServiceLoader.load(KnockoutTCK.class, cl(clazz))) {
105.123 + for (KnockoutTCK tck : tcks(clazz)) {
105.124 URI o = tck.prepareURL(content, mimeType, parameters);
105.125 if (o != null) {
105.126 return o.toString();
105.127 @@ -87,7 +123,7 @@
105.128
105.129 static boolean canFailWebSockets(
105.130 Class<?> clazz) {
105.131 - for (KnockoutTCK tck : ServiceLoader.load(KnockoutTCK.class, cl(clazz))) {
105.132 + for (KnockoutTCK tck : tcks(clazz)) {
105.133 if (tck.canFailWebSocketTest()) {
105.134 return true;
105.135 }
106.1 --- a/json-tck/src/main/java/net/java/html/json/tests/WebSocketTest.java Thu Dec 19 17:11:01 2013 +0100
106.2 +++ b/json-tck/src/main/java/net/java/html/json/tests/WebSocketTest.java Tue Jan 07 08:21:57 2014 +0100
106.3 @@ -1,22 +1,44 @@
106.4 /**
106.5 - * HTML via Java(tm) Language Bindings
106.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
106.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
106.8 *
106.9 - * This program is free software: you can redistribute it and/or modify
106.10 - * it under the terms of the GNU General Public License as published by
106.11 - * the Free Software Foundation, version 2 of the License.
106.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
106.13 *
106.14 - * This program is distributed in the hope that it will be useful,
106.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
106.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
106.17 - * GNU General Public License for more details. apidesign.org
106.18 - * designates this particular file as subject to the
106.19 - * "Classpath" exception as provided by apidesign.org
106.20 - * in the License file that accompanied this code.
106.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
106.22 + * Other names may be trademarks of their respective owners.
106.23 *
106.24 - * You should have received a copy of the GNU General Public License
106.25 - * along with this program. Look for COPYING file in the top folder.
106.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
106.27 + * The contents of this file are subject to the terms of either the GNU
106.28 + * General Public License Version 2 only ("GPL") or the Common
106.29 + * Development and Distribution License("CDDL") (collectively, the
106.30 + * "License"). You may not use this file except in compliance with the
106.31 + * License. You can obtain a copy of the License at
106.32 + * http://www.netbeans.org/cddl-gplv2.html
106.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
106.34 + * specific language governing permissions and limitations under the
106.35 + * License. When distributing the software, include this License Header
106.36 + * Notice in each file and include the License file at
106.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
106.38 + * particular file as subject to the "Classpath" exception as provided
106.39 + * by Oracle in the GPL Version 2 section of the License file that
106.40 + * accompanied this code. If applicable, add the following below the
106.41 + * License Header, with the fields enclosed by brackets [] replaced by
106.42 + * your own identifying information:
106.43 + * "Portions Copyrighted [year] [name of copyright owner]"
106.44 + *
106.45 + * Contributor(s):
106.46 + *
106.47 + * The Original Software is NetBeans. The Initial Developer of the Original
106.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
106.49 + *
106.50 + * If you wish your version of this file to be governed by only the CDDL
106.51 + * or only the GPL Version 2, indicate your decision by adding
106.52 + * "[Contributor] elects to include this software in this distribution
106.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
106.54 + * single choice of license, a recipient has the option to distribute
106.55 + * your version of this file under either the CDDL, the GPL Version 2 or
106.56 + * to extend the choice of license to its licensees as provided above.
106.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
106.58 + * Version 2 license, then the option applies only if the new code is
106.59 + * made subject to such option by the copyright holder.
106.60 */
106.61 package net.java.html.json.tests;
106.62
107.1 --- a/json-tck/src/main/java/org/apidesign/html/json/tck/JavaScriptTCK.java Thu Dec 19 17:11:01 2013 +0100
107.2 +++ b/json-tck/src/main/java/org/apidesign/html/json/tck/JavaScriptTCK.java Tue Jan 07 08:21:57 2014 +0100
107.3 @@ -1,22 +1,44 @@
107.4 /**
107.5 - * HTML via Java(tm) Language Bindings
107.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
107.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
107.8 *
107.9 - * This program is free software: you can redistribute it and/or modify
107.10 - * it under the terms of the GNU General Public License as published by
107.11 - * the Free Software Foundation, version 2 of the License.
107.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
107.13 *
107.14 - * This program is distributed in the hope that it will be useful,
107.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
107.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
107.17 - * GNU General Public License for more details. apidesign.org
107.18 - * designates this particular file as subject to the
107.19 - * "Classpath" exception as provided by apidesign.org
107.20 - * in the License file that accompanied this code.
107.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
107.22 + * Other names may be trademarks of their respective owners.
107.23 *
107.24 - * You should have received a copy of the GNU General Public License
107.25 - * along with this program. Look for COPYING file in the top folder.
107.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
107.27 + * The contents of this file are subject to the terms of either the GNU
107.28 + * General Public License Version 2 only ("GPL") or the Common
107.29 + * Development and Distribution License("CDDL") (collectively, the
107.30 + * "License"). You may not use this file except in compliance with the
107.31 + * License. You can obtain a copy of the License at
107.32 + * http://www.netbeans.org/cddl-gplv2.html
107.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
107.34 + * specific language governing permissions and limitations under the
107.35 + * License. When distributing the software, include this License Header
107.36 + * Notice in each file and include the License file at
107.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
107.38 + * particular file as subject to the "Classpath" exception as provided
107.39 + * by Oracle in the GPL Version 2 section of the License file that
107.40 + * accompanied this code. If applicable, add the following below the
107.41 + * License Header, with the fields enclosed by brackets [] replaced by
107.42 + * your own identifying information:
107.43 + * "Portions Copyrighted [year] [name of copyright owner]"
107.44 + *
107.45 + * Contributor(s):
107.46 + *
107.47 + * The Original Software is NetBeans. The Initial Developer of the Original
107.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
107.49 + *
107.50 + * If you wish your version of this file to be governed by only the CDDL
107.51 + * or only the GPL Version 2, indicate your decision by adding
107.52 + * "[Contributor] elects to include this software in this distribution
107.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
107.54 + * single choice of license, a recipient has the option to distribute
107.55 + * your version of this file under either the CDDL, the GPL Version 2 or
107.56 + * to extend the choice of license to its licensees as provided above.
107.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
107.58 + * Version 2 license, then the option applies only if the new code is
107.59 + * made subject to such option by the copyright holder.
107.60 */
107.61 package org.apidesign.html.json.tck;
107.62
108.1 --- a/json-tck/src/main/java/org/apidesign/html/json/tck/KOTest.java Thu Dec 19 17:11:01 2013 +0100
108.2 +++ b/json-tck/src/main/java/org/apidesign/html/json/tck/KOTest.java Tue Jan 07 08:21:57 2014 +0100
108.3 @@ -1,22 +1,44 @@
108.4 /**
108.5 - * HTML via Java(tm) Language Bindings
108.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
108.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
108.8 *
108.9 - * This program is free software: you can redistribute it and/or modify
108.10 - * it under the terms of the GNU General Public License as published by
108.11 - * the Free Software Foundation, version 2 of the License.
108.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
108.13 *
108.14 - * This program is distributed in the hope that it will be useful,
108.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
108.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
108.17 - * GNU General Public License for more details. apidesign.org
108.18 - * designates this particular file as subject to the
108.19 - * "Classpath" exception as provided by apidesign.org
108.20 - * in the License file that accompanied this code.
108.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
108.22 + * Other names may be trademarks of their respective owners.
108.23 *
108.24 - * You should have received a copy of the GNU General Public License
108.25 - * along with this program. Look for COPYING file in the top folder.
108.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
108.27 + * The contents of this file are subject to the terms of either the GNU
108.28 + * General Public License Version 2 only ("GPL") or the Common
108.29 + * Development and Distribution License("CDDL") (collectively, the
108.30 + * "License"). You may not use this file except in compliance with the
108.31 + * License. You can obtain a copy of the License at
108.32 + * http://www.netbeans.org/cddl-gplv2.html
108.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
108.34 + * specific language governing permissions and limitations under the
108.35 + * License. When distributing the software, include this License Header
108.36 + * Notice in each file and include the License file at
108.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
108.38 + * particular file as subject to the "Classpath" exception as provided
108.39 + * by Oracle in the GPL Version 2 section of the License file that
108.40 + * accompanied this code. If applicable, add the following below the
108.41 + * License Header, with the fields enclosed by brackets [] replaced by
108.42 + * your own identifying information:
108.43 + * "Portions Copyrighted [year] [name of copyright owner]"
108.44 + *
108.45 + * Contributor(s):
108.46 + *
108.47 + * The Original Software is NetBeans. The Initial Developer of the Original
108.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
108.49 + *
108.50 + * If you wish your version of this file to be governed by only the CDDL
108.51 + * or only the GPL Version 2, indicate your decision by adding
108.52 + * "[Contributor] elects to include this software in this distribution
108.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
108.54 + * single choice of license, a recipient has the option to distribute
108.55 + * your version of this file under either the CDDL, the GPL Version 2 or
108.56 + * to extend the choice of license to its licensees as provided above.
108.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
108.58 + * Version 2 license, then the option applies only if the new code is
108.59 + * made subject to such option by the copyright holder.
108.60 */
108.61 package org.apidesign.html.json.tck;
108.62
109.1 --- a/json-tck/src/main/java/org/apidesign/html/json/tck/KnockoutTCK.java Thu Dec 19 17:11:01 2013 +0100
109.2 +++ b/json-tck/src/main/java/org/apidesign/html/json/tck/KnockoutTCK.java Tue Jan 07 08:21:57 2014 +0100
109.3 @@ -1,22 +1,44 @@
109.4 /**
109.5 - * HTML via Java(tm) Language Bindings
109.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
109.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
109.8 *
109.9 - * This program is free software: you can redistribute it and/or modify
109.10 - * it under the terms of the GNU General Public License as published by
109.11 - * the Free Software Foundation, version 2 of the License.
109.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
109.13 *
109.14 - * This program is distributed in the hope that it will be useful,
109.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
109.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
109.17 - * GNU General Public License for more details. apidesign.org
109.18 - * designates this particular file as subject to the
109.19 - * "Classpath" exception as provided by apidesign.org
109.20 - * in the License file that accompanied this code.
109.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
109.22 + * Other names may be trademarks of their respective owners.
109.23 *
109.24 - * You should have received a copy of the GNU General Public License
109.25 - * along with this program. Look for COPYING file in the top folder.
109.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
109.27 + * The contents of this file are subject to the terms of either the GNU
109.28 + * General Public License Version 2 only ("GPL") or the Common
109.29 + * Development and Distribution License("CDDL") (collectively, the
109.30 + * "License"). You may not use this file except in compliance with the
109.31 + * License. You can obtain a copy of the License at
109.32 + * http://www.netbeans.org/cddl-gplv2.html
109.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
109.34 + * specific language governing permissions and limitations under the
109.35 + * License. When distributing the software, include this License Header
109.36 + * Notice in each file and include the License file at
109.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
109.38 + * particular file as subject to the "Classpath" exception as provided
109.39 + * by Oracle in the GPL Version 2 section of the License file that
109.40 + * accompanied this code. If applicable, add the following below the
109.41 + * License Header, with the fields enclosed by brackets [] replaced by
109.42 + * your own identifying information:
109.43 + * "Portions Copyrighted [year] [name of copyright owner]"
109.44 + *
109.45 + * Contributor(s):
109.46 + *
109.47 + * The Original Software is NetBeans. The Initial Developer of the Original
109.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
109.49 + *
109.50 + * If you wish your version of this file to be governed by only the CDDL
109.51 + * or only the GPL Version 2, indicate your decision by adding
109.52 + * "[Contributor] elects to include this software in this distribution
109.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
109.54 + * single choice of license, a recipient has the option to distribute
109.55 + * your version of this file under either the CDDL, the GPL Version 2 or
109.56 + * to extend the choice of license to its licensees as provided above.
109.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
109.58 + * Version 2 license, then the option applies only if the new code is
109.59 + * made subject to such option by the copyright holder.
109.60 */
109.61 package org.apidesign.html.json.tck;
109.62
109.63 @@ -24,9 +46,10 @@
109.64 import java.util.Map;
109.65 import net.java.html.BrwsrCtx;
109.66 import net.java.html.json.tests.ConvertTypesTest;
109.67 +import net.java.html.json.tests.JSONTest;
109.68 import net.java.html.json.tests.KnockoutTest;
109.69 -import net.java.html.json.tests.JSONTest;
109.70 import net.java.html.json.tests.OperationsTest;
109.71 +import net.java.html.json.tests.Utils;
109.72 import net.java.html.json.tests.WebSocketTest;
109.73 import org.openide.util.lookup.ServiceProvider;
109.74
109.75 @@ -50,6 +73,7 @@
109.76 */
109.77 public abstract class KnockoutTCK {
109.78 protected KnockoutTCK() {
109.79 + Utils.registerTCK(this);
109.80 }
109.81
109.82 /** Implement to create new context for the test.
110.1 --- a/json-tck/src/main/resources/org/apidesign/html/json/tck/package.html Thu Dec 19 17:11:01 2013 +0100
110.2 +++ b/json-tck/src/main/resources/org/apidesign/html/json/tck/package.html Tue Jan 07 08:21:57 2014 +0100
110.3 @@ -1,23 +1,45 @@
110.4 <!--
110.5
110.6 - HTML via Java(tm) Language Bindings
110.7 - Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
110.8 + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
110.9
110.10 - This program is free software: you can redistribute it and/or modify
110.11 - it under the terms of the GNU General Public License as published by
110.12 - the Free Software Foundation, version 2 of the License.
110.13 + Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
110.14
110.15 - This program is distributed in the hope that it will be useful,
110.16 - but WITHOUT ANY WARRANTY; without even the implied warranty of
110.17 - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
110.18 - GNU General Public License for more details. apidesign.org
110.19 - designates this particular file as subject to the
110.20 - "Classpath" exception as provided by apidesign.org
110.21 - in the License file that accompanied this code.
110.22 + Oracle and Java are registered trademarks of Oracle and/or its affiliates.
110.23 + Other names may be trademarks of their respective owners.
110.24
110.25 - You should have received a copy of the GNU General Public License
110.26 - along with this program. Look for COPYING file in the top folder.
110.27 - If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
110.28 + The contents of this file are subject to the terms of either the GNU
110.29 + General Public License Version 2 only ("GPL") or the Common
110.30 + Development and Distribution License("CDDL") (collectively, the
110.31 + "License"). You may not use this file except in compliance with the
110.32 + License. You can obtain a copy of the License at
110.33 + http://www.netbeans.org/cddl-gplv2.html
110.34 + or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
110.35 + specific language governing permissions and limitations under the
110.36 + License. When distributing the software, include this License Header
110.37 + Notice in each file and include the License file at
110.38 + nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
110.39 + particular file as subject to the "Classpath" exception as provided
110.40 + by Oracle in the GPL Version 2 section of the License file that
110.41 + accompanied this code. If applicable, add the following below the
110.42 + License Header, with the fields enclosed by brackets [] replaced by
110.43 + your own identifying information:
110.44 + "Portions Copyrighted [year] [name of copyright owner]"
110.45 +
110.46 + Contributor(s):
110.47 +
110.48 + The Original Software is NetBeans. The Initial Developer of the Original
110.49 + Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
110.50 +
110.51 + If you wish your version of this file to be governed by only the CDDL
110.52 + or only the GPL Version 2, indicate your decision by adding
110.53 + "[Contributor] elects to include this software in this distribution
110.54 + under the [CDDL or GPL Version 2] license." If you do not indicate a
110.55 + single choice of license, a recipient has the option to distribute
110.56 + your version of this file under either the CDDL, the GPL Version 2 or
110.57 + to extend the choice of license to its licensees as provided above.
110.58 + However, if you add GPL Version 2 code and therefore, elected the GPL
110.59 + Version 2 license, then the option applies only if the new code is
110.60 + made subject to such option by the copyright holder.
110.61
110.62 -->
110.63 <!DOCTYPE html>
111.1 --- a/json/pom.xml Thu Dec 19 17:11:01 2013 +0100
111.2 +++ b/json/pom.xml Tue Jan 07 08:21:57 2014 +0100
111.3 @@ -2,11 +2,11 @@
111.4 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
111.5 <modelVersion>4.0.0</modelVersion>
111.6 <parent>
111.7 - <groupId>org.apidesign</groupId>
111.8 - <artifactId>html</artifactId>
111.9 + <groupId>org.netbeans.html</groupId>
111.10 + <artifactId>pom</artifactId>
111.11 <version>0.7-SNAPSHOT</version>
111.12 </parent>
111.13 - <groupId>org.apidesign.html</groupId>
111.14 + <groupId>org.netbeans.html</groupId>
111.15 <artifactId>net.java.html.json</artifactId>
111.16 <version>0.7-SNAPSHOT</version>
111.17 <packaging>bundle</packaging>
112.1 --- a/json/src/main/java/net/java/html/json/ComputedProperty.java Thu Dec 19 17:11:01 2013 +0100
112.2 +++ b/json/src/main/java/net/java/html/json/ComputedProperty.java Tue Jan 07 08:21:57 2014 +0100
112.3 @@ -1,22 +1,44 @@
112.4 /**
112.5 - * HTML via Java(tm) Language Bindings
112.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
112.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
112.8 *
112.9 - * This program is free software: you can redistribute it and/or modify
112.10 - * it under the terms of the GNU General Public License as published by
112.11 - * the Free Software Foundation, version 2 of the License.
112.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
112.13 *
112.14 - * This program is distributed in the hope that it will be useful,
112.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
112.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
112.17 - * GNU General Public License for more details. apidesign.org
112.18 - * designates this particular file as subject to the
112.19 - * "Classpath" exception as provided by apidesign.org
112.20 - * in the License file that accompanied this code.
112.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
112.22 + * Other names may be trademarks of their respective owners.
112.23 *
112.24 - * You should have received a copy of the GNU General Public License
112.25 - * along with this program. Look for COPYING file in the top folder.
112.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
112.27 + * The contents of this file are subject to the terms of either the GNU
112.28 + * General Public License Version 2 only ("GPL") or the Common
112.29 + * Development and Distribution License("CDDL") (collectively, the
112.30 + * "License"). You may not use this file except in compliance with the
112.31 + * License. You can obtain a copy of the License at
112.32 + * http://www.netbeans.org/cddl-gplv2.html
112.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
112.34 + * specific language governing permissions and limitations under the
112.35 + * License. When distributing the software, include this License Header
112.36 + * Notice in each file and include the License file at
112.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
112.38 + * particular file as subject to the "Classpath" exception as provided
112.39 + * by Oracle in the GPL Version 2 section of the License file that
112.40 + * accompanied this code. If applicable, add the following below the
112.41 + * License Header, with the fields enclosed by brackets [] replaced by
112.42 + * your own identifying information:
112.43 + * "Portions Copyrighted [year] [name of copyright owner]"
112.44 + *
112.45 + * Contributor(s):
112.46 + *
112.47 + * The Original Software is NetBeans. The Initial Developer of the Original
112.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
112.49 + *
112.50 + * If you wish your version of this file to be governed by only the CDDL
112.51 + * or only the GPL Version 2, indicate your decision by adding
112.52 + * "[Contributor] elects to include this software in this distribution
112.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
112.54 + * single choice of license, a recipient has the option to distribute
112.55 + * your version of this file under either the CDDL, the GPL Version 2 or
112.56 + * to extend the choice of license to its licensees as provided above.
112.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
112.58 + * Version 2 license, then the option applies only if the new code is
112.59 + * made subject to such option by the copyright holder.
112.60 */
112.61 package net.java.html.json;
112.62
113.1 --- a/json/src/main/java/net/java/html/json/Function.java Thu Dec 19 17:11:01 2013 +0100
113.2 +++ b/json/src/main/java/net/java/html/json/Function.java Tue Jan 07 08:21:57 2014 +0100
113.3 @@ -1,22 +1,44 @@
113.4 /**
113.5 - * HTML via Java(tm) Language Bindings
113.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
113.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
113.8 *
113.9 - * This program is free software: you can redistribute it and/or modify
113.10 - * it under the terms of the GNU General Public License as published by
113.11 - * the Free Software Foundation, version 2 of the License.
113.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
113.13 *
113.14 - * This program is distributed in the hope that it will be useful,
113.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
113.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
113.17 - * GNU General Public License for more details. apidesign.org
113.18 - * designates this particular file as subject to the
113.19 - * "Classpath" exception as provided by apidesign.org
113.20 - * in the License file that accompanied this code.
113.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
113.22 + * Other names may be trademarks of their respective owners.
113.23 *
113.24 - * You should have received a copy of the GNU General Public License
113.25 - * along with this program. Look for COPYING file in the top folder.
113.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
113.27 + * The contents of this file are subject to the terms of either the GNU
113.28 + * General Public License Version 2 only ("GPL") or the Common
113.29 + * Development and Distribution License("CDDL") (collectively, the
113.30 + * "License"). You may not use this file except in compliance with the
113.31 + * License. You can obtain a copy of the License at
113.32 + * http://www.netbeans.org/cddl-gplv2.html
113.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
113.34 + * specific language governing permissions and limitations under the
113.35 + * License. When distributing the software, include this License Header
113.36 + * Notice in each file and include the License file at
113.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
113.38 + * particular file as subject to the "Classpath" exception as provided
113.39 + * by Oracle in the GPL Version 2 section of the License file that
113.40 + * accompanied this code. If applicable, add the following below the
113.41 + * License Header, with the fields enclosed by brackets [] replaced by
113.42 + * your own identifying information:
113.43 + * "Portions Copyrighted [year] [name of copyright owner]"
113.44 + *
113.45 + * Contributor(s):
113.46 + *
113.47 + * The Original Software is NetBeans. The Initial Developer of the Original
113.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
113.49 + *
113.50 + * If you wish your version of this file to be governed by only the CDDL
113.51 + * or only the GPL Version 2, indicate your decision by adding
113.52 + * "[Contributor] elects to include this software in this distribution
113.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
113.54 + * single choice of license, a recipient has the option to distribute
113.55 + * your version of this file under either the CDDL, the GPL Version 2 or
113.56 + * to extend the choice of license to its licensees as provided above.
113.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
113.58 + * Version 2 license, then the option applies only if the new code is
113.59 + * made subject to such option by the copyright holder.
113.60 */
113.61 package net.java.html.json;
113.62
114.1 --- a/json/src/main/java/net/java/html/json/Model.java Thu Dec 19 17:11:01 2013 +0100
114.2 +++ b/json/src/main/java/net/java/html/json/Model.java Tue Jan 07 08:21:57 2014 +0100
114.3 @@ -1,22 +1,44 @@
114.4 /**
114.5 - * HTML via Java(tm) Language Bindings
114.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
114.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
114.8 *
114.9 - * This program is free software: you can redistribute it and/or modify
114.10 - * it under the terms of the GNU General Public License as published by
114.11 - * the Free Software Foundation, version 2 of the License.
114.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
114.13 *
114.14 - * This program is distributed in the hope that it will be useful,
114.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
114.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
114.17 - * GNU General Public License for more details. apidesign.org
114.18 - * designates this particular file as subject to the
114.19 - * "Classpath" exception as provided by apidesign.org
114.20 - * in the License file that accompanied this code.
114.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
114.22 + * Other names may be trademarks of their respective owners.
114.23 *
114.24 - * You should have received a copy of the GNU General Public License
114.25 - * along with this program. Look for COPYING file in the top folder.
114.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
114.27 + * The contents of this file are subject to the terms of either the GNU
114.28 + * General Public License Version 2 only ("GPL") or the Common
114.29 + * Development and Distribution License("CDDL") (collectively, the
114.30 + * "License"). You may not use this file except in compliance with the
114.31 + * License. You can obtain a copy of the License at
114.32 + * http://www.netbeans.org/cddl-gplv2.html
114.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
114.34 + * specific language governing permissions and limitations under the
114.35 + * License. When distributing the software, include this License Header
114.36 + * Notice in each file and include the License file at
114.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
114.38 + * particular file as subject to the "Classpath" exception as provided
114.39 + * by Oracle in the GPL Version 2 section of the License file that
114.40 + * accompanied this code. If applicable, add the following below the
114.41 + * License Header, with the fields enclosed by brackets [] replaced by
114.42 + * your own identifying information:
114.43 + * "Portions Copyrighted [year] [name of copyright owner]"
114.44 + *
114.45 + * Contributor(s):
114.46 + *
114.47 + * The Original Software is NetBeans. The Initial Developer of the Original
114.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
114.49 + *
114.50 + * If you wish your version of this file to be governed by only the CDDL
114.51 + * or only the GPL Version 2, indicate your decision by adding
114.52 + * "[Contributor] elects to include this software in this distribution
114.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
114.54 + * single choice of license, a recipient has the option to distribute
114.55 + * your version of this file under either the CDDL, the GPL Version 2 or
114.56 + * to extend the choice of license to its licensees as provided above.
114.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
114.58 + * Version 2 license, then the option applies only if the new code is
114.59 + * made subject to such option by the copyright holder.
114.60 */
114.61 package net.java.html.json;
114.62
115.1 --- a/json/src/main/java/net/java/html/json/ModelOperation.java Thu Dec 19 17:11:01 2013 +0100
115.2 +++ b/json/src/main/java/net/java/html/json/ModelOperation.java Tue Jan 07 08:21:57 2014 +0100
115.3 @@ -1,22 +1,44 @@
115.4 /**
115.5 - * HTML via Java(tm) Language Bindings
115.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
115.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
115.8 *
115.9 - * This program is free software: you can redistribute it and/or modify
115.10 - * it under the terms of the GNU General Public License as published by
115.11 - * the Free Software Foundation, version 2 of the License.
115.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
115.13 *
115.14 - * This program is distributed in the hope that it will be useful,
115.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
115.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
115.17 - * GNU General Public License for more details. apidesign.org
115.18 - * designates this particular file as subject to the
115.19 - * "Classpath" exception as provided by apidesign.org
115.20 - * in the License file that accompanied this code.
115.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
115.22 + * Other names may be trademarks of their respective owners.
115.23 *
115.24 - * You should have received a copy of the GNU General Public License
115.25 - * along with this program. Look for COPYING file in the top folder.
115.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
115.27 + * The contents of this file are subject to the terms of either the GNU
115.28 + * General Public License Version 2 only ("GPL") or the Common
115.29 + * Development and Distribution License("CDDL") (collectively, the
115.30 + * "License"). You may not use this file except in compliance with the
115.31 + * License. You can obtain a copy of the License at
115.32 + * http://www.netbeans.org/cddl-gplv2.html
115.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
115.34 + * specific language governing permissions and limitations under the
115.35 + * License. When distributing the software, include this License Header
115.36 + * Notice in each file and include the License file at
115.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
115.38 + * particular file as subject to the "Classpath" exception as provided
115.39 + * by Oracle in the GPL Version 2 section of the License file that
115.40 + * accompanied this code. If applicable, add the following below the
115.41 + * License Header, with the fields enclosed by brackets [] replaced by
115.42 + * your own identifying information:
115.43 + * "Portions Copyrighted [year] [name of copyright owner]"
115.44 + *
115.45 + * Contributor(s):
115.46 + *
115.47 + * The Original Software is NetBeans. The Initial Developer of the Original
115.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
115.49 + *
115.50 + * If you wish your version of this file to be governed by only the CDDL
115.51 + * or only the GPL Version 2, indicate your decision by adding
115.52 + * "[Contributor] elects to include this software in this distribution
115.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
115.54 + * single choice of license, a recipient has the option to distribute
115.55 + * your version of this file under either the CDDL, the GPL Version 2 or
115.56 + * to extend the choice of license to its licensees as provided above.
115.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
115.58 + * Version 2 license, then the option applies only if the new code is
115.59 + * made subject to such option by the copyright holder.
115.60 */
115.61 package net.java.html.json;
115.62
116.1 --- a/json/src/main/java/net/java/html/json/Models.java Thu Dec 19 17:11:01 2013 +0100
116.2 +++ b/json/src/main/java/net/java/html/json/Models.java Tue Jan 07 08:21:57 2014 +0100
116.3 @@ -1,29 +1,51 @@
116.4 /**
116.5 - * HTML via Java(tm) Language Bindings
116.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
116.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
116.8 *
116.9 - * This program is free software: you can redistribute it and/or modify
116.10 - * it under the terms of the GNU General Public License as published by
116.11 - * the Free Software Foundation, version 2 of the License.
116.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
116.13 *
116.14 - * This program is distributed in the hope that it will be useful,
116.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
116.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
116.17 - * GNU General Public License for more details. apidesign.org
116.18 - * designates this particular file as subject to the
116.19 - * "Classpath" exception as provided by apidesign.org
116.20 - * in the License file that accompanied this code.
116.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
116.22 + * Other names may be trademarks of their respective owners.
116.23 *
116.24 - * You should have received a copy of the GNU General Public License
116.25 - * along with this program. Look for COPYING file in the top folder.
116.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
116.27 + * The contents of this file are subject to the terms of either the GNU
116.28 + * General Public License Version 2 only ("GPL") or the Common
116.29 + * Development and Distribution License("CDDL") (collectively, the
116.30 + * "License"). You may not use this file except in compliance with the
116.31 + * License. You can obtain a copy of the License at
116.32 + * http://www.netbeans.org/cddl-gplv2.html
116.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
116.34 + * specific language governing permissions and limitations under the
116.35 + * License. When distributing the software, include this License Header
116.36 + * Notice in each file and include the License file at
116.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
116.38 + * particular file as subject to the "Classpath" exception as provided
116.39 + * by Oracle in the GPL Version 2 section of the License file that
116.40 + * accompanied this code. If applicable, add the following below the
116.41 + * License Header, with the fields enclosed by brackets [] replaced by
116.42 + * your own identifying information:
116.43 + * "Portions Copyrighted [year] [name of copyright owner]"
116.44 + *
116.45 + * Contributor(s):
116.46 + *
116.47 + * The Original Software is NetBeans. The Initial Developer of the Original
116.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
116.49 + *
116.50 + * If you wish your version of this file to be governed by only the CDDL
116.51 + * or only the GPL Version 2, indicate your decision by adding
116.52 + * "[Contributor] elects to include this software in this distribution
116.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
116.54 + * single choice of license, a recipient has the option to distribute
116.55 + * your version of this file under either the CDDL, the GPL Version 2 or
116.56 + * to extend the choice of license to its licensees as provided above.
116.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
116.58 + * Version 2 license, then the option applies only if the new code is
116.59 + * made subject to such option by the copyright holder.
116.60 */
116.61 package net.java.html.json;
116.62
116.63 import net.java.html.BrwsrCtx;
116.64 import java.io.IOException;
116.65 import java.io.InputStream;
116.66 -import org.apidesign.html.json.impl.JSON;
116.67 +import org.netbeans.html.json.impl.JSON;
116.68
116.69 /** Information about and
116.70 * operations for classes generated by the {@link Model @Model}
117.1 --- a/json/src/main/java/net/java/html/json/OnPropertyChange.java Thu Dec 19 17:11:01 2013 +0100
117.2 +++ b/json/src/main/java/net/java/html/json/OnPropertyChange.java Tue Jan 07 08:21:57 2014 +0100
117.3 @@ -1,22 +1,44 @@
117.4 /**
117.5 - * HTML via Java(tm) Language Bindings
117.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
117.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
117.8 *
117.9 - * This program is free software: you can redistribute it and/or modify
117.10 - * it under the terms of the GNU General Public License as published by
117.11 - * the Free Software Foundation, version 2 of the License.
117.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
117.13 *
117.14 - * This program is distributed in the hope that it will be useful,
117.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
117.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
117.17 - * GNU General Public License for more details. apidesign.org
117.18 - * designates this particular file as subject to the
117.19 - * "Classpath" exception as provided by apidesign.org
117.20 - * in the License file that accompanied this code.
117.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
117.22 + * Other names may be trademarks of their respective owners.
117.23 *
117.24 - * You should have received a copy of the GNU General Public License
117.25 - * along with this program. Look for COPYING file in the top folder.
117.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
117.27 + * The contents of this file are subject to the terms of either the GNU
117.28 + * General Public License Version 2 only ("GPL") or the Common
117.29 + * Development and Distribution License("CDDL") (collectively, the
117.30 + * "License"). You may not use this file except in compliance with the
117.31 + * License. You can obtain a copy of the License at
117.32 + * http://www.netbeans.org/cddl-gplv2.html
117.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
117.34 + * specific language governing permissions and limitations under the
117.35 + * License. When distributing the software, include this License Header
117.36 + * Notice in each file and include the License file at
117.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
117.38 + * particular file as subject to the "Classpath" exception as provided
117.39 + * by Oracle in the GPL Version 2 section of the License file that
117.40 + * accompanied this code. If applicable, add the following below the
117.41 + * License Header, with the fields enclosed by brackets [] replaced by
117.42 + * your own identifying information:
117.43 + * "Portions Copyrighted [year] [name of copyright owner]"
117.44 + *
117.45 + * Contributor(s):
117.46 + *
117.47 + * The Original Software is NetBeans. The Initial Developer of the Original
117.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
117.49 + *
117.50 + * If you wish your version of this file to be governed by only the CDDL
117.51 + * or only the GPL Version 2, indicate your decision by adding
117.52 + * "[Contributor] elects to include this software in this distribution
117.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
117.54 + * single choice of license, a recipient has the option to distribute
117.55 + * your version of this file under either the CDDL, the GPL Version 2 or
117.56 + * to extend the choice of license to its licensees as provided above.
117.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
117.58 + * Version 2 license, then the option applies only if the new code is
117.59 + * made subject to such option by the copyright holder.
117.60 */
117.61 package net.java.html.json;
117.62
118.1 --- a/json/src/main/java/net/java/html/json/OnReceive.java Thu Dec 19 17:11:01 2013 +0100
118.2 +++ b/json/src/main/java/net/java/html/json/OnReceive.java Tue Jan 07 08:21:57 2014 +0100
118.3 @@ -1,22 +1,44 @@
118.4 /**
118.5 - * HTML via Java(tm) Language Bindings
118.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
118.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
118.8 *
118.9 - * This program is free software: you can redistribute it and/or modify
118.10 - * it under the terms of the GNU General Public License as published by
118.11 - * the Free Software Foundation, version 2 of the License.
118.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
118.13 *
118.14 - * This program is distributed in the hope that it will be useful,
118.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
118.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
118.17 - * GNU General Public License for more details. apidesign.org
118.18 - * designates this particular file as subject to the
118.19 - * "Classpath" exception as provided by apidesign.org
118.20 - * in the License file that accompanied this code.
118.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
118.22 + * Other names may be trademarks of their respective owners.
118.23 *
118.24 - * You should have received a copy of the GNU General Public License
118.25 - * along with this program. Look for COPYING file in the top folder.
118.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
118.27 + * The contents of this file are subject to the terms of either the GNU
118.28 + * General Public License Version 2 only ("GPL") or the Common
118.29 + * Development and Distribution License("CDDL") (collectively, the
118.30 + * "License"). You may not use this file except in compliance with the
118.31 + * License. You can obtain a copy of the License at
118.32 + * http://www.netbeans.org/cddl-gplv2.html
118.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
118.34 + * specific language governing permissions and limitations under the
118.35 + * License. When distributing the software, include this License Header
118.36 + * Notice in each file and include the License file at
118.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
118.38 + * particular file as subject to the "Classpath" exception as provided
118.39 + * by Oracle in the GPL Version 2 section of the License file that
118.40 + * accompanied this code. If applicable, add the following below the
118.41 + * License Header, with the fields enclosed by brackets [] replaced by
118.42 + * your own identifying information:
118.43 + * "Portions Copyrighted [year] [name of copyright owner]"
118.44 + *
118.45 + * Contributor(s):
118.46 + *
118.47 + * The Original Software is NetBeans. The Initial Developer of the Original
118.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
118.49 + *
118.50 + * If you wish your version of this file to be governed by only the CDDL
118.51 + * or only the GPL Version 2, indicate your decision by adding
118.52 + * "[Contributor] elects to include this software in this distribution
118.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
118.54 + * single choice of license, a recipient has the option to distribute
118.55 + * your version of this file under either the CDDL, the GPL Version 2 or
118.56 + * to extend the choice of license to its licensees as provided above.
118.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
118.58 + * Version 2 license, then the option applies only if the new code is
118.59 + * made subject to such option by the copyright holder.
118.60 */
118.61 package net.java.html.json;
118.62
119.1 --- a/json/src/main/java/net/java/html/json/Property.java Thu Dec 19 17:11:01 2013 +0100
119.2 +++ b/json/src/main/java/net/java/html/json/Property.java Tue Jan 07 08:21:57 2014 +0100
119.3 @@ -1,22 +1,44 @@
119.4 /**
119.5 - * HTML via Java(tm) Language Bindings
119.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
119.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
119.8 *
119.9 - * This program is free software: you can redistribute it and/or modify
119.10 - * it under the terms of the GNU General Public License as published by
119.11 - * the Free Software Foundation, version 2 of the License.
119.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
119.13 *
119.14 - * This program is distributed in the hope that it will be useful,
119.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
119.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
119.17 - * GNU General Public License for more details. apidesign.org
119.18 - * designates this particular file as subject to the
119.19 - * "Classpath" exception as provided by apidesign.org
119.20 - * in the License file that accompanied this code.
119.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
119.22 + * Other names may be trademarks of their respective owners.
119.23 *
119.24 - * You should have received a copy of the GNU General Public License
119.25 - * along with this program. Look for COPYING file in the top folder.
119.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
119.27 + * The contents of this file are subject to the terms of either the GNU
119.28 + * General Public License Version 2 only ("GPL") or the Common
119.29 + * Development and Distribution License("CDDL") (collectively, the
119.30 + * "License"). You may not use this file except in compliance with the
119.31 + * License. You can obtain a copy of the License at
119.32 + * http://www.netbeans.org/cddl-gplv2.html
119.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
119.34 + * specific language governing permissions and limitations under the
119.35 + * License. When distributing the software, include this License Header
119.36 + * Notice in each file and include the License file at
119.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
119.38 + * particular file as subject to the "Classpath" exception as provided
119.39 + * by Oracle in the GPL Version 2 section of the License file that
119.40 + * accompanied this code. If applicable, add the following below the
119.41 + * License Header, with the fields enclosed by brackets [] replaced by
119.42 + * your own identifying information:
119.43 + * "Portions Copyrighted [year] [name of copyright owner]"
119.44 + *
119.45 + * Contributor(s):
119.46 + *
119.47 + * The Original Software is NetBeans. The Initial Developer of the Original
119.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
119.49 + *
119.50 + * If you wish your version of this file to be governed by only the CDDL
119.51 + * or only the GPL Version 2, indicate your decision by adding
119.52 + * "[Contributor] elects to include this software in this distribution
119.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
119.54 + * single choice of license, a recipient has the option to distribute
119.55 + * your version of this file under either the CDDL, the GPL Version 2 or
119.56 + * to extend the choice of license to its licensees as provided above.
119.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
119.58 + * Version 2 license, then the option applies only if the new code is
119.59 + * made subject to such option by the copyright holder.
119.60 */
119.61 package net.java.html.json;
119.62
120.1 --- a/json/src/main/java/net/java/html/json/doc-files/websockets.html Thu Dec 19 17:11:01 2013 +0100
120.2 +++ b/json/src/main/java/net/java/html/json/doc-files/websockets.html Tue Jan 07 08:21:57 2014 +0100
120.3 @@ -1,23 +1,45 @@
120.4 <!--
120.5
120.6 - HTML via Java(tm) Language Bindings
120.7 - Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
120.8 + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
120.9
120.10 - This program is free software: you can redistribute it and/or modify
120.11 - it under the terms of the GNU General Public License as published by
120.12 - the Free Software Foundation, version 2 of the License.
120.13 + Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
120.14
120.15 - This program is distributed in the hope that it will be useful,
120.16 - but WITHOUT ANY WARRANTY; without even the implied warranty of
120.17 - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
120.18 - GNU General Public License for more details. apidesign.org
120.19 - designates this particular file as subject to the
120.20 - "Classpath" exception as provided by apidesign.org
120.21 - in the License file that accompanied this code.
120.22 + Oracle and Java are registered trademarks of Oracle and/or its affiliates.
120.23 + Other names may be trademarks of their respective owners.
120.24
120.25 - You should have received a copy of the GNU General Public License
120.26 - along with this program. Look for COPYING file in the top folder.
120.27 - If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
120.28 + The contents of this file are subject to the terms of either the GNU
120.29 + General Public License Version 2 only ("GPL") or the Common
120.30 + Development and Distribution License("CDDL") (collectively, the
120.31 + "License"). You may not use this file except in compliance with the
120.32 + License. You can obtain a copy of the License at
120.33 + http://www.netbeans.org/cddl-gplv2.html
120.34 + or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
120.35 + specific language governing permissions and limitations under the
120.36 + License. When distributing the software, include this License Header
120.37 + Notice in each file and include the License file at
120.38 + nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
120.39 + particular file as subject to the "Classpath" exception as provided
120.40 + by Oracle in the GPL Version 2 section of the License file that
120.41 + accompanied this code. If applicable, add the following below the
120.42 + License Header, with the fields enclosed by brackets [] replaced by
120.43 + your own identifying information:
120.44 + "Portions Copyrighted [year] [name of copyright owner]"
120.45 +
120.46 + Contributor(s):
120.47 +
120.48 + The Original Software is NetBeans. The Initial Developer of the Original
120.49 + Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
120.50 +
120.51 + If you wish your version of this file to be governed by only the CDDL
120.52 + or only the GPL Version 2, indicate your decision by adding
120.53 + "[Contributor] elects to include this software in this distribution
120.54 + under the [CDDL or GPL Version 2] license." If you do not indicate a
120.55 + single choice of license, a recipient has the option to distribute
120.56 + your version of this file under either the CDDL, the GPL Version 2 or
120.57 + to extend the choice of license to its licensees as provided above.
120.58 + However, if you add GPL Version 2 code and therefore, elected the GPL
120.59 + Version 2 license, then the option applies only if the new code is
120.60 + made subject to such option by the copyright holder.
120.61
120.62 -->
120.63 <!DOCTYPE html>
121.1 --- a/json/src/main/java/net/java/html/json/package.html Thu Dec 19 17:11:01 2013 +0100
121.2 +++ b/json/src/main/java/net/java/html/json/package.html Tue Jan 07 08:21:57 2014 +0100
121.3 @@ -1,23 +1,45 @@
121.4 <!--
121.5
121.6 - HTML via Java(tm) Language Bindings
121.7 - Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
121.8 + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
121.9
121.10 - This program is free software: you can redistribute it and/or modify
121.11 - it under the terms of the GNU General Public License as published by
121.12 - the Free Software Foundation, version 2 of the License.
121.13 + Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
121.14
121.15 - This program is distributed in the hope that it will be useful,
121.16 - but WITHOUT ANY WARRANTY; without even the implied warranty of
121.17 - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
121.18 - GNU General Public License for more details. apidesign.org
121.19 - designates this particular file as subject to the
121.20 - "Classpath" exception as provided by apidesign.org
121.21 - in the License file that accompanied this code.
121.22 + Oracle and Java are registered trademarks of Oracle and/or its affiliates.
121.23 + Other names may be trademarks of their respective owners.
121.24
121.25 - You should have received a copy of the GNU General Public License
121.26 - along with this program. Look for COPYING file in the top folder.
121.27 - If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
121.28 + The contents of this file are subject to the terms of either the GNU
121.29 + General Public License Version 2 only ("GPL") or the Common
121.30 + Development and Distribution License("CDDL") (collectively, the
121.31 + "License"). You may not use this file except in compliance with the
121.32 + License. You can obtain a copy of the License at
121.33 + http://www.netbeans.org/cddl-gplv2.html
121.34 + or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
121.35 + specific language governing permissions and limitations under the
121.36 + License. When distributing the software, include this License Header
121.37 + Notice in each file and include the License file at
121.38 + nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
121.39 + particular file as subject to the "Classpath" exception as provided
121.40 + by Oracle in the GPL Version 2 section of the License file that
121.41 + accompanied this code. If applicable, add the following below the
121.42 + License Header, with the fields enclosed by brackets [] replaced by
121.43 + your own identifying information:
121.44 + "Portions Copyrighted [year] [name of copyright owner]"
121.45 +
121.46 + Contributor(s):
121.47 +
121.48 + The Original Software is NetBeans. The Initial Developer of the Original
121.49 + Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
121.50 +
121.51 + If you wish your version of this file to be governed by only the CDDL
121.52 + or only the GPL Version 2, indicate your decision by adding
121.53 + "[Contributor] elects to include this software in this distribution
121.54 + under the [CDDL or GPL Version 2] license." If you do not indicate a
121.55 + single choice of license, a recipient has the option to distribute
121.56 + your version of this file under either the CDDL, the GPL Version 2 or
121.57 + to extend the choice of license to its licensees as provided above.
121.58 + However, if you add GPL Version 2 code and therefore, elected the GPL
121.59 + Version 2 license, then the option applies only if the new code is
121.60 + made subject to such option by the copyright holder.
121.61
121.62 -->
121.63 <body>
122.1 --- a/json/src/main/java/org/apidesign/html/json/impl/Bindings.java Thu Dec 19 17:11:01 2013 +0100
122.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
122.3 @@ -1,91 +0,0 @@
122.4 -/**
122.5 - * HTML via Java(tm) Language Bindings
122.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
122.7 - *
122.8 - * This program is free software: you can redistribute it and/or modify
122.9 - * it under the terms of the GNU General Public License as published by
122.10 - * the Free Software Foundation, version 2 of the License.
122.11 - *
122.12 - * This program is distributed in the hope that it will be useful,
122.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
122.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
122.15 - * GNU General Public License for more details. apidesign.org
122.16 - * designates this particular file as subject to the
122.17 - * "Classpath" exception as provided by apidesign.org
122.18 - * in the License file that accompanied this code.
122.19 - *
122.20 - * You should have received a copy of the GNU General Public License
122.21 - * along with this program. Look for COPYING file in the top folder.
122.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
122.23 - */
122.24 -package org.apidesign.html.json.impl;
122.25 -
122.26 -import org.apidesign.html.json.spi.PropertyBinding;
122.27 -import net.java.html.BrwsrCtx;
122.28 -import org.apidesign.html.json.impl.PropertyBindingAccessor.FBData;
122.29 -import org.apidesign.html.json.impl.PropertyBindingAccessor.PBData;
122.30 -import org.apidesign.html.json.spi.FunctionBinding;
122.31 -import org.apidesign.html.json.spi.Technology;
122.32 -
122.33 -/**
122.34 - *
122.35 - * @author Jaroslav Tulach <jtulach@netbeans.org>
122.36 - */
122.37 -public final class Bindings<Data> {
122.38 - private Data data;
122.39 - private final Technology<Data> bp;
122.40 -
122.41 - private Bindings(Technology<Data> bp) {
122.42 - this.bp = bp;
122.43 - }
122.44 -
122.45 - public <M> PropertyBinding registerProperty(String propName, M model, SetAndGet<M> access, boolean readOnly) {
122.46 - return PropertyBindingAccessor.create(new PBData<M>(this, propName, model, access, readOnly));
122.47 - }
122.48 -
122.49 - public <M> FunctionBinding registerFunction(String name, M model, Callback<M> access) {
122.50 - return PropertyBindingAccessor.createFunction(new FBData<M>(name, model, access));
122.51 - }
122.52 -
122.53 - public static Bindings<?> apply(BrwsrCtx c, Object model) {
122.54 - Technology<?> bp = JSON.findTechnology(c);
122.55 - return apply(bp);
122.56 - }
122.57 -
122.58 - private static <Data> Bindings<Data> apply(Technology<Data> bp) {
122.59 - return new Bindings<Data>(bp);
122.60 - }
122.61 -
122.62 - public final void finish(Object model, PropertyBinding[] propArr, FunctionBinding[] funcArr) {
122.63 - assert data == null;
122.64 - if (bp instanceof Technology.BatchInit) {
122.65 - Technology.BatchInit<Data> bi = (Technology.BatchInit<Data>)bp;
122.66 - data = bi.wrapModel(model, propArr, funcArr);
122.67 - } else {
122.68 - data = bp.wrapModel(model);
122.69 - for (PropertyBinding b : propArr) {
122.70 - bp.bind(b, model, data);
122.71 - }
122.72 - for (FunctionBinding b : funcArr) {
122.73 - bp.expose(b, model, data);
122.74 - }
122.75 - }
122.76 - }
122.77 -
122.78 -
122.79 - public Data koData() {
122.80 - return data;
122.81 - }
122.82 -
122.83 - public void valueHasMutated(String firstName) {
122.84 - bp.valueHasMutated(data, firstName);
122.85 - }
122.86 -
122.87 - public void applyBindings() {
122.88 - bp.applyBindings(data);
122.89 - }
122.90 -
122.91 - Object wrapArray(Object[] arr) {
122.92 - return bp.wrapArray(arr);
122.93 - }
122.94 -}
123.1 --- a/json/src/main/java/org/apidesign/html/json/impl/Callback.java Thu Dec 19 17:11:01 2013 +0100
123.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
123.3 @@ -1,30 +0,0 @@
123.4 -/**
123.5 - * HTML via Java(tm) Language Bindings
123.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
123.7 - *
123.8 - * This program is free software: you can redistribute it and/or modify
123.9 - * it under the terms of the GNU General Public License as published by
123.10 - * the Free Software Foundation, version 2 of the License.
123.11 - *
123.12 - * This program is distributed in the hope that it will be useful,
123.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
123.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
123.15 - * GNU General Public License for more details. apidesign.org
123.16 - * designates this particular file as subject to the
123.17 - * "Classpath" exception as provided by apidesign.org
123.18 - * in the License file that accompanied this code.
123.19 - *
123.20 - * You should have received a copy of the GNU General Public License
123.21 - * along with this program. Look for COPYING file in the top folder.
123.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
123.23 - */
123.24 -
123.25 -package org.apidesign.html.json.impl;
123.26 -
123.27 -/**
123.28 - *
123.29 - * @author Jaroslav Tulach <jtulach@netbeans.org>
123.30 - */
123.31 -public interface Callback<Data> {
123.32 - public void call(Data model, Object data, Object ev);
123.33 -}
124.1 --- a/json/src/main/java/org/apidesign/html/json/impl/FromJSON.java Thu Dec 19 17:11:01 2013 +0100
124.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
124.3 @@ -1,34 +0,0 @@
124.4 -/**
124.5 - * HTML via Java(tm) Language Bindings
124.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
124.7 - *
124.8 - * This program is free software: you can redistribute it and/or modify
124.9 - * it under the terms of the GNU General Public License as published by
124.10 - * the Free Software Foundation, version 2 of the License.
124.11 - *
124.12 - * This program is distributed in the hope that it will be useful,
124.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
124.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
124.15 - * GNU General Public License for more details. apidesign.org
124.16 - * designates this particular file as subject to the
124.17 - * "Classpath" exception as provided by apidesign.org
124.18 - * in the License file that accompanied this code.
124.19 - *
124.20 - * You should have received a copy of the GNU General Public License
124.21 - * along with this program. Look for COPYING file in the top folder.
124.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
124.23 - */
124.24 -
124.25 -package org.apidesign.html.json.impl;
124.26 -
124.27 -import net.java.html.BrwsrCtx;
124.28 -
124.29 -/**
124.30 - *
124.31 - * @author Jaroslav Tulach <jtulach@netbeans.org>
124.32 - */
124.33 -public interface FromJSON<Data> {
124.34 - public Class<Data> factoryFor();
124.35 - public Data read(BrwsrCtx c, Object d);
124.36 - public Data cloneTo(Object d, BrwsrCtx c);
124.37 -}
125.1 --- a/json/src/main/java/org/apidesign/html/json/impl/JSON.java Thu Dec 19 17:11:01 2013 +0100
125.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
125.3 @@ -1,452 +0,0 @@
125.4 -/**
125.5 - * HTML via Java(tm) Language Bindings
125.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
125.7 - *
125.8 - * This program is free software: you can redistribute it and/or modify
125.9 - * it under the terms of the GNU General Public License as published by
125.10 - * the Free Software Foundation, version 2 of the License.
125.11 - *
125.12 - * This program is distributed in the hope that it will be useful,
125.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
125.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
125.15 - * GNU General Public License for more details. apidesign.org
125.16 - * designates this particular file as subject to the
125.17 - * "Classpath" exception as provided by apidesign.org
125.18 - * in the License file that accompanied this code.
125.19 - *
125.20 - * You should have received a copy of the GNU General Public License
125.21 - * along with this program. Look for COPYING file in the top folder.
125.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
125.23 - */
125.24 -package org.apidesign.html.json.impl;
125.25 -
125.26 -import java.io.IOException;
125.27 -import java.io.InputStream;
125.28 -import java.util.HashMap;
125.29 -import java.util.Map;
125.30 -import net.java.html.BrwsrCtx;
125.31 -import org.apidesign.html.context.spi.Contexts;
125.32 -import org.apidesign.html.json.spi.FunctionBinding;
125.33 -import org.apidesign.html.json.spi.JSONCall;
125.34 -import org.apidesign.html.json.spi.PropertyBinding;
125.35 -import org.apidesign.html.json.spi.Technology;
125.36 -import org.apidesign.html.json.spi.Transfer;
125.37 -import org.apidesign.html.json.spi.WSTransfer;
125.38 -
125.39 -/**
125.40 - *
125.41 - * @author Jaroslav Tulach <jtulach@netbeans.org>
125.42 - */
125.43 -public final class JSON {
125.44 - private JSON() {
125.45 - }
125.46 -
125.47 - static Technology<?> findTechnology(BrwsrCtx c) {
125.48 - Technology<?> t = Contexts.find(c, Technology.class);
125.49 - return t == null ? EmptyTech.EMPTY : t;
125.50 - }
125.51 -
125.52 - static Transfer findTransfer(BrwsrCtx c) {
125.53 - Transfer t = Contexts.find(c, Transfer.class);
125.54 - return t == null ? EmptyTech.EMPTY : t;
125.55 - }
125.56 -
125.57 - static WSTransfer<?> findWSTransfer(BrwsrCtx c) {
125.58 - WSTransfer<?> t = Contexts.find(c, WSTransfer.class);
125.59 - return t == null ? EmptyTech.EMPTY : t;
125.60 - }
125.61 -
125.62 - public static void runInBrowser(BrwsrCtx c, Runnable runnable) {
125.63 - findTechnology(c).runSafe(runnable);
125.64 - }
125.65 -
125.66 - public static void extract(BrwsrCtx c, Object value, String[] props, Object[] values) {
125.67 - Transfer t = findTransfer(c);
125.68 - t.extract(value, props, values);
125.69 - }
125.70 -
125.71 - private static Object getProperty(BrwsrCtx c, Object obj, String prop) {
125.72 - if (prop == null) return obj;
125.73 -
125.74 - String[] arr = { prop };
125.75 - Object[] val = { null };
125.76 - extract(c, obj, arr, val);
125.77 - return val[0];
125.78 - }
125.79 -
125.80 - public static Object toJSON(Object value) {
125.81 - if (value == null) {
125.82 - return "null";
125.83 - }
125.84 - if (value instanceof Enum) {
125.85 - value = value.toString();
125.86 - }
125.87 - if (value instanceof String) {
125.88 - String s = (String)value;
125.89 - int len = s.length();
125.90 - StringBuilder sb = new StringBuilder(len + 10);
125.91 - sb.append('"');
125.92 - for (int i = 0; i < len; i++) {
125.93 - char ch = s.charAt(i);
125.94 - switch (ch) {
125.95 - case '\"': sb.append("\\\""); break;
125.96 - case '\n': sb.append("\\n"); break;
125.97 - case '\r': sb.append("\\r"); break;
125.98 - case '\t': sb.append("\\t"); break;
125.99 - case '\\': sb.append("\\\\"); break;
125.100 - default: sb.append(ch);
125.101 - }
125.102 - }
125.103 - sb.append('"');
125.104 - return sb.toString();
125.105 - }
125.106 - return value.toString();
125.107 - }
125.108 -
125.109 - public static String toString(BrwsrCtx c, Object obj, String prop) {
125.110 - obj = getProperty(c, obj, prop);
125.111 - return obj instanceof String ? (String)obj : null;
125.112 - }
125.113 - public static Number toNumber(BrwsrCtx c, Object obj, String prop) {
125.114 - obj = getProperty(c, obj, prop);
125.115 - if (!(obj instanceof Number)) {
125.116 - obj = Double.NaN;
125.117 - }
125.118 - return (Number)obj;
125.119 - }
125.120 - public static <M> M toModel(BrwsrCtx c, Class<M> aClass, Object data, Object object) {
125.121 - Technology<?> t = findTechnology(c);
125.122 - Object o = t.toModel(aClass, data);
125.123 - return aClass.cast(o);
125.124 - }
125.125 -
125.126 - public static boolean isSame(int a, int b) {
125.127 - return a == b;
125.128 - }
125.129 -
125.130 - public static boolean isSame(double a, double b) {
125.131 - return a == b;
125.132 - }
125.133 -
125.134 - public static boolean isSame(Object a, Object b) {
125.135 - if (a == b) {
125.136 - return true;
125.137 - }
125.138 - if (a == null || b == null) {
125.139 - return false;
125.140 - }
125.141 - return a.equals(b);
125.142 - }
125.143 -
125.144 - public static int hashPlus(Object o, int h) {
125.145 - return o == null ? h : h ^ o.hashCode();
125.146 - }
125.147 -
125.148 - public static <T> T extractValue(Class<T> type, Object val) {
125.149 - if (Number.class.isAssignableFrom(type)) {
125.150 - val = numberValue(val);
125.151 - }
125.152 - if (Boolean.class == type) {
125.153 - val = boolValue(val);
125.154 - }
125.155 - if (String.class == type) {
125.156 - val = stringValue(val);
125.157 - }
125.158 - if (Character.class == type) {
125.159 - val = charValue(val);
125.160 - }
125.161 - if (Integer.class == type) {
125.162 - val = val instanceof Number ? ((Number)val).intValue() : 0;
125.163 - }
125.164 - if (Long.class == type) {
125.165 - val = val instanceof Number ? ((Number)val).longValue() : 0;
125.166 - }
125.167 - if (Short.class == type) {
125.168 - val = val instanceof Number ? ((Number)val).shortValue() : 0;
125.169 - }
125.170 - if (Byte.class == type) {
125.171 - val = val instanceof Number ? ((Number)val).byteValue() : 0;
125.172 - }
125.173 - if (Double.class == type) {
125.174 - val = val instanceof Number ? ((Number)val).doubleValue() : Double.NaN;
125.175 - }
125.176 - if (Float.class == type) {
125.177 - val = val instanceof Number ? ((Number)val).floatValue() : Float.NaN;
125.178 - }
125.179 - return type.cast(val);
125.180 - }
125.181 -
125.182 - protected static boolean isNumeric(Object val) {
125.183 - return ((val instanceof Integer) || (val instanceof Long) || (val instanceof Short) || (val instanceof Byte));
125.184 - }
125.185 -
125.186 - public static String stringValue(Object val) {
125.187 - if (val instanceof Boolean) {
125.188 - return ((Boolean)val ? "true" : "false");
125.189 - }
125.190 - if (isNumeric(val)) {
125.191 - return Long.toString(((Number)val).longValue());
125.192 - }
125.193 - if (val instanceof Float) {
125.194 - return Float.toString((Float)val);
125.195 - }
125.196 - if (val instanceof Double) {
125.197 - return Double.toString((Double)val);
125.198 - }
125.199 - return (String)val;
125.200 - }
125.201 -
125.202 - public static Number numberValue(Object val) {
125.203 - if (val instanceof String) {
125.204 - try {
125.205 - return Double.valueOf((String)val);
125.206 - } catch (NumberFormatException ex) {
125.207 - return Double.NaN;
125.208 - }
125.209 - }
125.210 - if (val instanceof Boolean) {
125.211 - return (Boolean)val ? 1 : 0;
125.212 - }
125.213 - return (Number)val;
125.214 - }
125.215 -
125.216 - public static Character charValue(Object val) {
125.217 - if (val instanceof Number) {
125.218 - return Character.toChars(numberValue(val).intValue())[0];
125.219 - }
125.220 - if (val instanceof Boolean) {
125.221 - return (Boolean)val ? (char)1 : (char)0;
125.222 - }
125.223 - if (val instanceof String) {
125.224 - String s = (String)val;
125.225 - return s.isEmpty() ? (char)0 : s.charAt(0);
125.226 - }
125.227 - return (Character)val;
125.228 - }
125.229 -
125.230 - public static Boolean boolValue(Object val) {
125.231 - if (val instanceof String) {
125.232 - return Boolean.parseBoolean((String)val);
125.233 - }
125.234 - if (val instanceof Number) {
125.235 - return numberValue(val).doubleValue() != 0.0;
125.236 - }
125.237 -
125.238 - return Boolean.TRUE.equals(val);
125.239 - }
125.240 -
125.241 - public static void loadJSON(
125.242 - BrwsrCtx c, RcvrJSON callback,
125.243 - String urlBefore, String urlAfter, String method,
125.244 - Object data
125.245 - ) {
125.246 - JSONCall call = PropertyBindingAccessor.createCall(c, callback, urlBefore, urlAfter, method, data);
125.247 - Transfer t = findTransfer(c);
125.248 - t.loadJSON(call);
125.249 - }
125.250 - public static WS openWS(
125.251 - BrwsrCtx c, RcvrJSON r, String url, Object data
125.252 - ) {
125.253 - WS ws = WSImpl.create(findWSTransfer(c), r);
125.254 - ws.send(c, url, data);
125.255 - return ws;
125.256 - }
125.257 -
125.258 - public static abstract class WS {
125.259 - private WS() {
125.260 - }
125.261 -
125.262 - public abstract void send(BrwsrCtx ctx, String url, Object model);
125.263 - }
125.264 -
125.265 - private static final class WSImpl<Socket> extends WS {
125.266 -
125.267 - private final WSTransfer<Socket> trans;
125.268 - private final RcvrJSON rcvr;
125.269 - private Socket socket;
125.270 - private String prevURL;
125.271 -
125.272 - private WSImpl(WSTransfer<Socket> trans, RcvrJSON rcvr) {
125.273 - this.trans = trans;
125.274 - this.rcvr = rcvr;
125.275 - }
125.276 -
125.277 - static <Socket> WS create(WSTransfer<Socket> t, RcvrJSON r) {
125.278 - return new WSImpl<Socket>(t, r);
125.279 - }
125.280 -
125.281 - @Override
125.282 - public void send(BrwsrCtx ctx, String url, Object data) {
125.283 - Socket s = socket;
125.284 - if (s == null) {
125.285 - if (data != null) {
125.286 - throw new IllegalStateException("WebSocket is not opened yet. Call with null data, was: " + data);
125.287 - }
125.288 - JSONCall call = PropertyBindingAccessor.createCall(ctx, rcvr, url, null, "WebSocket", null);
125.289 - socket = trans.open(url, call);
125.290 - prevURL = url;
125.291 - return;
125.292 - }
125.293 - if (data == null) {
125.294 - trans.close(s);
125.295 - socket = null;
125.296 - return;
125.297 - }
125.298 - if (!prevURL.equals(url)) {
125.299 - throw new IllegalStateException(
125.300 - "Can't call to different URL " + url + " was: " + prevURL + "!"
125.301 - + " Close the socket by calling it will null data first!"
125.302 - );
125.303 - }
125.304 - JSONCall call = PropertyBindingAccessor.createCall(ctx, rcvr, prevURL, null, "WebSocket", data);
125.305 - trans.send(s, call);
125.306 - }
125.307 -
125.308 - }
125.309 -
125.310 - private static final Map<Class,FromJSON<?>> froms;
125.311 - static {
125.312 - Map<Class,FromJSON<?>> m = new HashMap<Class,FromJSON<?>>();
125.313 - froms = m;
125.314 - }
125.315 - public static void register(FromJSON<?> from) {
125.316 - froms.put(from.factoryFor(), from);
125.317 - }
125.318 -
125.319 - public static boolean isModel(Class<?> clazz) {
125.320 - return findFrom(clazz) != null;
125.321 - }
125.322 -
125.323 - private static FromJSON<?> findFrom(Class<?> clazz) {
125.324 - for (int i = 0; i < 2; i++) {
125.325 - FromJSON<?> from = froms.get(clazz);
125.326 - if (from == null) {
125.327 - initClass(clazz);
125.328 - } else {
125.329 - return from;
125.330 - }
125.331 - }
125.332 - return null;
125.333 - }
125.334 -
125.335 - public static <Model> Model bindTo(Model model, BrwsrCtx c) {
125.336 - FromJSON<?> from = findFrom(model.getClass());
125.337 - if (from == null) {
125.338 - throw new IllegalArgumentException();
125.339 - }
125.340 - return (Model) from.cloneTo(model, c);
125.341 - }
125.342 -
125.343 - public static <T> T readStream(BrwsrCtx c, Class<T> modelClazz, InputStream data)
125.344 - throws IOException {
125.345 - Transfer tr = findTransfer(c);
125.346 - return read(c, modelClazz, tr.toJSON((InputStream)data));
125.347 - }
125.348 - public static <T> T read(BrwsrCtx c, Class<T> modelClazz, Object data) {
125.349 - if (data == null) {
125.350 - return null;
125.351 - }
125.352 - if (modelClazz == String.class) {
125.353 - return modelClazz.cast(data.toString());
125.354 - }
125.355 - for (int i = 0; i < 2; i++) {
125.356 - FromJSON<?> from = froms.get(modelClazz);
125.357 - if (from == null) {
125.358 - initClass(modelClazz);
125.359 - } else {
125.360 - return modelClazz.cast(from.read(c, data));
125.361 - }
125.362 - }
125.363 - throw new NullPointerException();
125.364 - }
125.365 - static void initClass(Class<?> modelClazz) {
125.366 - try {
125.367 - // try to resolve the class
125.368 - ClassLoader l;
125.369 - try {
125.370 - l = modelClazz.getClassLoader();
125.371 - } catch (SecurityException ex) {
125.372 - l = null;
125.373 - }
125.374 - if (l != null) {
125.375 - Class.forName(modelClazz.getName(), true, l);
125.376 - }
125.377 - modelClazz.newInstance();
125.378 - } catch (Exception ex) {
125.379 - // ignore and try again
125.380 - }
125.381 - }
125.382 -
125.383 - private static final class EmptyTech
125.384 - implements Technology<Object>, Transfer, WSTransfer<Void> {
125.385 - private static final EmptyTech EMPTY = new EmptyTech();
125.386 -
125.387 - @Override
125.388 - public Object wrapModel(Object model) {
125.389 - return model;
125.390 - }
125.391 -
125.392 - @Override
125.393 - public void valueHasMutated(Object data, String propertyName) {
125.394 - }
125.395 -
125.396 - @Override
125.397 - public void bind(PropertyBinding b, Object model, Object data) {
125.398 - }
125.399 -
125.400 - @Override
125.401 - public void expose(FunctionBinding fb, Object model, Object d) {
125.402 - }
125.403 -
125.404 - @Override
125.405 - public void applyBindings(Object data) {
125.406 - }
125.407 -
125.408 - @Override
125.409 - public Object wrapArray(Object[] arr) {
125.410 - return arr;
125.411 - }
125.412 -
125.413 - @Override
125.414 - public void extract(Object obj, String[] props, Object[] values) {
125.415 - for (int i = 0; i < values.length; i++) {
125.416 - values[i] = null;
125.417 - }
125.418 - }
125.419 -
125.420 - @Override
125.421 - public void loadJSON(JSONCall call) {
125.422 - call.notifyError(new UnsupportedOperationException());
125.423 - }
125.424 -
125.425 - @Override
125.426 - public <M> M toModel(Class<M> modelClass, Object data) {
125.427 - return modelClass.cast(data);
125.428 - }
125.429 -
125.430 - @Override
125.431 - public Object toJSON(InputStream is) throws IOException {
125.432 - throw new IOException("Not supported");
125.433 - }
125.434 -
125.435 - @Override
125.436 - public synchronized void runSafe(Runnable r) {
125.437 - r.run();
125.438 - }
125.439 -
125.440 - @Override
125.441 - public Void open(String url, JSONCall onReply) {
125.442 - onReply.notifyError(new UnsupportedOperationException("WebSockets not supported!"));
125.443 - return null;
125.444 - }
125.445 -
125.446 - @Override
125.447 - public void send(Void socket, JSONCall data) {
125.448 - }
125.449 -
125.450 - @Override
125.451 - public void close(Void socket) {
125.452 - }
125.453 - }
125.454 -
125.455 -}
126.1 --- a/json/src/main/java/org/apidesign/html/json/impl/JSONList.java Thu Dec 19 17:11:01 2013 +0100
126.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
126.3 @@ -1,214 +0,0 @@
126.4 -/**
126.5 - * HTML via Java(tm) Language Bindings
126.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
126.7 - *
126.8 - * This program is free software: you can redistribute it and/or modify
126.9 - * it under the terms of the GNU General Public License as published by
126.10 - * the Free Software Foundation, version 2 of the License.
126.11 - *
126.12 - * This program is distributed in the hope that it will be useful,
126.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
126.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
126.15 - * GNU General Public License for more details. apidesign.org
126.16 - * designates this particular file as subject to the
126.17 - * "Classpath" exception as provided by apidesign.org
126.18 - * in the License file that accompanied this code.
126.19 - *
126.20 - * You should have received a copy of the GNU General Public License
126.21 - * along with this program. Look for COPYING file in the top folder.
126.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
126.23 - */
126.24 -package org.apidesign.html.json.impl;
126.25 -
126.26 -import java.lang.reflect.Array;
126.27 -import java.util.ArrayList;
126.28 -import java.util.Arrays;
126.29 -import java.util.Collection;
126.30 -import java.util.Iterator;
126.31 -import java.util.List;
126.32 -import net.java.html.BrwsrCtx;
126.33 -
126.34 -/**
126.35 - *
126.36 - * @author Jaroslav Tulach <jtulach@netbeans.org>
126.37 - */
126.38 -public final class JSONList<T> extends ArrayList<T> {
126.39 - private final String name;
126.40 - private final String[] deps;
126.41 - private Bindings[] model;
126.42 - private Runnable onchange;
126.43 -
126.44 - public JSONList(Bindings[] model, String name, String... deps) {
126.45 - assert model.length == 1;
126.46 - this.model = model;
126.47 - this.name = name;
126.48 - this.deps = deps;
126.49 - }
126.50 -
126.51 - public void init(T... values) {
126.52 - if (values == null || values.length == 0) {
126.53 - return;
126.54 - }
126.55 - if (this.model[0] != null || !isEmpty()) {
126.56 - throw new IllegalStateException();
126.57 - }
126.58 - super.addAll(Arrays.asList(values));
126.59 - }
126.60 -
126.61 - public void init(Object values) {
126.62 - int len;
126.63 - if (values == null || (len = Array.getLength(values)) == 0) {
126.64 - return;
126.65 - }
126.66 - if (this.model[0] != null || !isEmpty()) {
126.67 - throw new IllegalStateException();
126.68 - }
126.69 - for (int i = 0; i < len; i++) {
126.70 - Object data = Array.get(values, i);
126.71 - super.add((T)data);
126.72 - }
126.73 - }
126.74 -
126.75 - public JSONList<T> onChange(Runnable r) {
126.76 - if (this.onchange != null) {
126.77 - throw new IllegalStateException();
126.78 - }
126.79 - this.onchange = r;
126.80 - return this;
126.81 - }
126.82 -
126.83 - @Override
126.84 - public boolean add(T e) {
126.85 - boolean ret = super.add(e);
126.86 - notifyChange();
126.87 - return ret;
126.88 - }
126.89 -
126.90 - @Override
126.91 - public boolean addAll(Collection<? extends T> c) {
126.92 - boolean ret = super.addAll(c);
126.93 - notifyChange();
126.94 - return ret;
126.95 - }
126.96 -
126.97 - @Override
126.98 - public boolean addAll(int index, Collection<? extends T> c) {
126.99 - boolean ret = super.addAll(index, c);
126.100 - notifyChange();
126.101 - return ret;
126.102 - }
126.103 -
126.104 - @Override
126.105 - public boolean remove(Object o) {
126.106 - boolean ret = super.remove(o);
126.107 - notifyChange();
126.108 - return ret;
126.109 - }
126.110 -
126.111 - @Override
126.112 - public void clear() {
126.113 - super.clear();
126.114 - notifyChange();
126.115 - }
126.116 -
126.117 - @Override
126.118 - public boolean removeAll(Collection<?> c) {
126.119 - boolean ret = super.removeAll(c);
126.120 - notifyChange();
126.121 - return ret;
126.122 - }
126.123 -
126.124 - @Override
126.125 - public boolean retainAll(Collection<?> c) {
126.126 - boolean ret = super.retainAll(c);
126.127 - notifyChange();
126.128 - return ret;
126.129 - }
126.130 -
126.131 - @Override
126.132 - public T set(int index, T element) {
126.133 - T ret = super.set(index, element);
126.134 - notifyChange();
126.135 - return ret;
126.136 - }
126.137 -
126.138 - @Override
126.139 - public void add(int index, T element) {
126.140 - super.add(index, element);
126.141 - notifyChange();
126.142 - }
126.143 -
126.144 - @Override
126.145 - public T remove(int index) {
126.146 - T ret = super.remove(index);
126.147 - notifyChange();
126.148 - return ret;
126.149 - }
126.150 -
126.151 - @Override
126.152 - public String toString() {
126.153 - Iterator<T> it = iterator();
126.154 - if (!it.hasNext()) {
126.155 - return "[]";
126.156 - }
126.157 - String sep = "";
126.158 - StringBuilder sb = new StringBuilder();
126.159 - sb.append('[');
126.160 - while (it.hasNext()) {
126.161 - T t = it.next();
126.162 - sb.append(sep);
126.163 - sb.append(JSON.toJSON(t));
126.164 - sep = ",";
126.165 - }
126.166 - sb.append(']');
126.167 - return sb.toString();
126.168 - }
126.169 -
126.170 - private void notifyChange() {
126.171 - Bindings m = model[0];
126.172 - if (m != null) {
126.173 - m.valueHasMutated(name);
126.174 - for (String dependant : deps) {
126.175 - m.valueHasMutated(dependant);
126.176 - }
126.177 - Runnable r = onchange;
126.178 - if (r != null) {
126.179 - r.run();
126.180 - }
126.181 - }
126.182 - }
126.183 -
126.184 - public void cloneAll(BrwsrCtx c, Collection<T> other) {
126.185 - Boolean isModel = null;
126.186 - for (T t : other) {
126.187 - if (isModel == null) {
126.188 - isModel = JSON.isModel(t.getClass());
126.189 - }
126.190 - if (isModel) {
126.191 - add(JSON.bindTo(t, c));
126.192 - } else {
126.193 - add(t);
126.194 - }
126.195 - }
126.196 - }
126.197 -
126.198 - @Override
126.199 - public JSONList clone() {
126.200 - throw new UnsupportedOperationException();
126.201 - }
126.202 -
126.203 - static final Object koData(Collection<?> c, Bindings m) {
126.204 - Object[] arr = c.toArray(new Object[c.size()]);
126.205 - for (int i = 0; i < arr.length; i++) {
126.206 - Object r = WrapperObject.find(arr[i], m);
126.207 - if (r != null) {
126.208 - arr[i] = r;
126.209 - }
126.210 - }
126.211 - return m.wrapArray(arr);
126.212 - }
126.213 -
126.214 - final Object koData() {
126.215 - return koData(this, model[0]);
126.216 - }
126.217 -}
127.1 --- a/json/src/main/java/org/apidesign/html/json/impl/ModelProcessor.java Thu Dec 19 17:11:01 2013 +0100
127.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
127.3 @@ -1,1745 +0,0 @@
127.4 -/**
127.5 - * HTML via Java(tm) Language Bindings
127.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
127.7 - *
127.8 - * This program is free software: you can redistribute it and/or modify
127.9 - * it under the terms of the GNU General Public License as published by
127.10 - * the Free Software Foundation, version 2 of the License.
127.11 - *
127.12 - * This program is distributed in the hope that it will be useful,
127.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
127.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
127.15 - * GNU General Public License for more details. apidesign.org
127.16 - * designates this particular file as subject to the
127.17 - * "Classpath" exception as provided by apidesign.org
127.18 - * in the License file that accompanied this code.
127.19 - *
127.20 - * You should have received a copy of the GNU General Public License
127.21 - * along with this program. Look for COPYING file in the top folder.
127.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
127.23 - */
127.24 -package org.apidesign.html.json.impl;
127.25 -
127.26 -import java.io.IOException;
127.27 -import java.io.OutputStreamWriter;
127.28 -import java.io.StringWriter;
127.29 -import java.io.Writer;
127.30 -import java.lang.annotation.AnnotationTypeMismatchException;
127.31 -import java.lang.annotation.IncompleteAnnotationException;
127.32 -import java.lang.reflect.Method;
127.33 -import java.util.ArrayList;
127.34 -import java.util.Arrays;
127.35 -import java.util.Collection;
127.36 -import java.util.Collections;
127.37 -import java.util.HashMap;
127.38 -import java.util.HashSet;
127.39 -import java.util.LinkedHashSet;
127.40 -import java.util.List;
127.41 -import java.util.Map;
127.42 -import java.util.ResourceBundle;
127.43 -import java.util.Set;
127.44 -import java.util.WeakHashMap;
127.45 -import java.util.logging.Level;
127.46 -import java.util.logging.Logger;
127.47 -import javax.annotation.processing.AbstractProcessor;
127.48 -import javax.annotation.processing.Completion;
127.49 -import javax.annotation.processing.Completions;
127.50 -import javax.annotation.processing.ProcessingEnvironment;
127.51 -import javax.annotation.processing.Processor;
127.52 -import javax.annotation.processing.RoundEnvironment;
127.53 -import javax.annotation.processing.SupportedAnnotationTypes;
127.54 -import javax.annotation.processing.SupportedSourceVersion;
127.55 -import javax.lang.model.SourceVersion;
127.56 -import javax.lang.model.element.AnnotationMirror;
127.57 -import javax.lang.model.element.AnnotationValue;
127.58 -import javax.lang.model.element.Element;
127.59 -import javax.lang.model.element.ElementKind;
127.60 -import javax.lang.model.element.ExecutableElement;
127.61 -import javax.lang.model.element.Modifier;
127.62 -import javax.lang.model.element.PackageElement;
127.63 -import javax.lang.model.element.TypeElement;
127.64 -import javax.lang.model.element.VariableElement;
127.65 -import javax.lang.model.type.ArrayType;
127.66 -import javax.lang.model.type.DeclaredType;
127.67 -import javax.lang.model.type.MirroredTypeException;
127.68 -import javax.lang.model.type.TypeKind;
127.69 -import javax.lang.model.type.TypeMirror;
127.70 -import javax.lang.model.util.Elements;
127.71 -import javax.lang.model.util.Types;
127.72 -import javax.tools.Diagnostic;
127.73 -import javax.tools.FileObject;
127.74 -import net.java.html.json.ComputedProperty;
127.75 -import net.java.html.json.Model;
127.76 -import net.java.html.json.Function;
127.77 -import net.java.html.json.ModelOperation;
127.78 -import net.java.html.json.OnPropertyChange;
127.79 -import net.java.html.json.OnReceive;
127.80 -import net.java.html.json.Property;
127.81 -import org.openide.util.lookup.ServiceProvider;
127.82 -
127.83 -/** Annotation processor to process {@link Model @Model} annotations and
127.84 - * generate appropriate model classes.
127.85 - *
127.86 - * @author Jaroslav Tulach <jtulach@netbeans.org>
127.87 - */
127.88 -@ServiceProvider(service=Processor.class)
127.89 -@SupportedSourceVersion(SourceVersion.RELEASE_6)
127.90 -@SupportedAnnotationTypes({
127.91 - "net.java.html.json.Model",
127.92 - "net.java.html.json.ModelOperation",
127.93 - "net.java.html.json.Function",
127.94 - "net.java.html.json.OnReceive",
127.95 - "net.java.html.json.OnPropertyChange",
127.96 - "net.java.html.json.ComputedProperty",
127.97 - "net.java.html.json.Property"
127.98 -})
127.99 -public final class ModelProcessor extends AbstractProcessor {
127.100 - private static final Logger LOG = Logger.getLogger(ModelProcessor.class.getName());
127.101 - private final Map<Element,String> models = new WeakHashMap<Element,String>();
127.102 - private final Map<Element,Prprt[]> verify = new WeakHashMap<Element,Prprt[]>();
127.103 - @Override
127.104 - public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
127.105 - boolean ok = true;
127.106 - for (Element e : roundEnv.getElementsAnnotatedWith(Model.class)) {
127.107 - if (!processModel(e)) {
127.108 - ok = false;
127.109 - }
127.110 - }
127.111 - if (roundEnv.processingOver()) {
127.112 - models.clear();
127.113 - for (Map.Entry<Element, Prprt[]> entry : verify.entrySet()) {
127.114 - TypeElement te = (TypeElement)entry.getKey();
127.115 - String fqn = processingEnv.getElementUtils().getBinaryName(te).toString();
127.116 - Element finalElem = processingEnv.getElementUtils().getTypeElement(fqn);
127.117 - if (finalElem == null) {
127.118 - continue;
127.119 - }
127.120 - Prprt[] props;
127.121 - Model m = finalElem.getAnnotation(Model.class);
127.122 - if (m == null) {
127.123 - continue;
127.124 - }
127.125 - props = Prprt.wrap(processingEnv, finalElem, m.properties());
127.126 - for (Prprt p : props) {
127.127 - boolean[] isModel = { false };
127.128 - boolean[] isEnum = { false };
127.129 - boolean[] isPrimitive = { false };
127.130 - String t = checkType(p, isModel, isEnum, isPrimitive);
127.131 - if (isEnum[0]) {
127.132 - continue;
127.133 - }
127.134 - if (isPrimitive[0]) {
127.135 - continue;
127.136 - }
127.137 - if (isModel[0]) {
127.138 - continue;
127.139 - }
127.140 - if ("java.lang.String".equals(t)) {
127.141 - continue;
127.142 - }
127.143 - error("The type " + t + " should be defined by @Model annotation", entry.getKey());
127.144 - }
127.145 - }
127.146 - verify.clear();
127.147 - }
127.148 - return ok;
127.149 - }
127.150 -
127.151 - private void error(String msg, Element e) {
127.152 - processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, msg, e);
127.153 - }
127.154 -
127.155 - private boolean processModel(Element e) {
127.156 - boolean ok = true;
127.157 - Model m = e.getAnnotation(Model.class);
127.158 - if (m == null) {
127.159 - return true;
127.160 - }
127.161 - String pkg = findPkgName(e);
127.162 - Writer w;
127.163 - String className = m.className();
127.164 - models.put(e, className);
127.165 - try {
127.166 - StringWriter body = new StringWriter();
127.167 - List<String> propsGetSet = new ArrayList<String>();
127.168 - List<String> functions = new ArrayList<String>();
127.169 - Map<String, Collection<String>> propsDeps = new HashMap<String, Collection<String>>();
127.170 - Map<String, Collection<String>> functionDeps = new HashMap<String, Collection<String>>();
127.171 - Prprt[] props = createProps(e, m.properties());
127.172 -
127.173 - if (!generateComputedProperties(body, props, e.getEnclosedElements(), propsGetSet, propsDeps)) {
127.174 - ok = false;
127.175 - }
127.176 - if (!generateOnChange(e, propsDeps, props, className, functionDeps)) {
127.177 - ok = false;
127.178 - }
127.179 - if (!generateProperties(e, body, props, propsGetSet, propsDeps, functionDeps)) {
127.180 - ok = false;
127.181 - }
127.182 - if (!generateFunctions(e, body, className, e.getEnclosedElements(), functions)) {
127.183 - ok = false;
127.184 - }
127.185 - if (!generateReceive(e, body, className, e.getEnclosedElements(), functions)) {
127.186 - ok = false;
127.187 - }
127.188 - if (!generateOperation(e, body, className, e.getEnclosedElements())) {
127.189 - ok = false;
127.190 - }
127.191 - FileObject java = processingEnv.getFiler().createSourceFile(pkg + '.' + className, e);
127.192 - w = new OutputStreamWriter(java.openOutputStream());
127.193 - try {
127.194 - w.append("package " + pkg + ";\n");
127.195 - w.append("import net.java.html.json.*;\n");
127.196 - w.append("public final class ").append(className).append(" implements Cloneable {\n");
127.197 - w.append(" private boolean locked;\n");
127.198 - w.append(" private net.java.html.BrwsrCtx context;\n");
127.199 - w.append(" private org.apidesign.html.json.impl.Bindings[] ko = { null };\n");
127.200 - w.append(body.toString());
127.201 - w.append(" private static Class<" + inPckName(e) + "> modelFor() { return null; }\n");
127.202 - w.append(" private ").append(className).append("(net.java.html.BrwsrCtx context) {\n");
127.203 - w.append(" this.context = context;\n");
127.204 - w.append(" };\n");
127.205 - w.append(" public ").append(className).append("() {\n");
127.206 - w.append(" this(net.java.html.BrwsrCtx.findDefault(").append(className).append(".class));\n");
127.207 - for (Prprt p : props) {
127.208 - if (p.array()) {
127.209 - continue;
127.210 - }
127.211 - boolean[] isModel = {false};
127.212 - boolean[] isEnum = {false};
127.213 - boolean isPrimitive[] = {false};
127.214 - String tn = checkType(p, isModel, isEnum, isPrimitive);
127.215 - if (isModel[0]) {
127.216 - w.write(" prop_" + p.name() + " = new " + tn + "();\n");
127.217 - }
127.218 - }
127.219 - w.append(" };\n");
127.220 - if (props.length > 0) {
127.221 - w.append(" public ").append(className).append("(");
127.222 - Prprt firstArray = null;
127.223 - String sep = "";
127.224 - for (Prprt p : props) {
127.225 - if (p.array()) {
127.226 - if (firstArray == null) {
127.227 - firstArray = p;
127.228 - }
127.229 - continue;
127.230 - }
127.231 - String tn = typeName(e, p);
127.232 - w.write(sep);
127.233 - w.write(tn);
127.234 - w.write(" " + p.name());
127.235 - sep = ", ";
127.236 - }
127.237 - if (firstArray != null) {
127.238 - String tn;
127.239 - boolean[] isModel = {false};
127.240 - boolean[] isEnum = {false};
127.241 - boolean isPrimitive[] = {false};
127.242 - tn = checkType(firstArray, isModel, isEnum, isPrimitive);
127.243 - w.write(sep);
127.244 - w.write(tn);
127.245 - w.write("... " + firstArray.name());
127.246 - }
127.247 - w.append(") {\n");
127.248 - w.append(" this(net.java.html.BrwsrCtx.findDefault(").append(className).append(".class));\n");
127.249 - for (Prprt p : props) {
127.250 - if (p.array()) {
127.251 - continue;
127.252 - }
127.253 - w.write(" this.prop_" + p.name() + " = " + p.name() + ";\n");
127.254 - }
127.255 - if (firstArray != null) {
127.256 - w.write(" this.prop_" + firstArray.name() + ".init(" + firstArray.name() + ");\n");
127.257 - }
127.258 - w.append(" };\n");
127.259 - }
127.260 - w.append(" private org.apidesign.html.json.impl.Bindings intKnckt() {\n");
127.261 - w.append(" if (ko[0] != null) return ko[0];\n");
127.262 - w.append(" ko[0] = org.apidesign.html.json.impl.Bindings.apply(context, this);\n");
127.263 - {
127.264 - w.append(" org.apidesign.html.json.spi.PropertyBinding[] propArr = {\n");
127.265 - for (int i = 0; i < propsGetSet.size(); i += 5) {
127.266 - w.append(" ko[0].registerProperty(\"").append(propsGetSet.get(i)).append("\", this, new P(");
127.267 - w.append((i / 5) + "), " + (propsGetSet.get(i + 2) == null) + "),\n");
127.268 - }
127.269 - w.append(" };\n");
127.270 - }
127.271 - {
127.272 - w.append(" org.apidesign.html.json.spi.FunctionBinding[] funcArr = {\n");
127.273 - for (int i = 0; i < functions.size(); i += 2) {
127.274 - w.append(" ko[0].registerFunction(\"").append(functions.get(i)).append("\", this, new P(");
127.275 - w.append((i / 2) + ")),\n");
127.276 - }
127.277 - w.append(" };\n");
127.278 - }
127.279 - w.append(" ko[0].finish(this, propArr, funcArr);\n");
127.280 - w.append(" return ko[0];\n");
127.281 - w.append(" };\n");
127.282 - w.append(" private static final class P implements org.apidesign.html.json.impl.SetAndGet<" + className + ">,\n");
127.283 - w.append(" org.apidesign.html.json.impl.Callback<" + className + ">,\n");
127.284 - w.append(" org.apidesign.html.json.impl.FromJSON<" + className + "> {\n");
127.285 - w.append(" private final int type;\n");
127.286 - w.append(" P(int t) { type = t; };\n");
127.287 - w.append(" public void setValue(" + className + " data, Object value) {\n");
127.288 - w.append(" switch (type) {\n");
127.289 - for (int i = 0; i < propsGetSet.size(); i += 5) {
127.290 - final String set = propsGetSet.get(i + 2);
127.291 - String tn = propsGetSet.get(i + 4);
127.292 - String btn = findBoxedType(tn);
127.293 - if (btn != null) {
127.294 - tn = btn;
127.295 - }
127.296 - if (set != null) {
127.297 - w.append(" case " + (i / 5) + ": data." + strip(set) + "(org.apidesign.html.json.impl.JSON.extractValue(" + tn + ".class, value)); return;\n");
127.298 - }
127.299 - }
127.300 - w.append(" }\n");
127.301 - w.append(" }\n");
127.302 - w.append(" public Object getValue(" + className + " data) {\n");
127.303 - w.append(" switch (type) {\n");
127.304 - for (int i = 0; i < propsGetSet.size(); i += 5) {
127.305 - final String get = propsGetSet.get(i + 1);
127.306 - if (get != null) {
127.307 - w.append(" case " + (i / 5) + ": return data." + strip(get) + "();\n");
127.308 - }
127.309 - }
127.310 - w.append(" }\n");
127.311 - w.append(" throw new UnsupportedOperationException();\n");
127.312 - w.append(" }\n");
127.313 - w.append(" public void call(" + className + " model, Object data, Object ev) {\n");
127.314 - w.append(" switch (type) {\n");
127.315 - for (int i = 0; i < functions.size(); i += 2) {
127.316 - final String name = functions.get(i);
127.317 - w.append(" case " + (i / 2) + ": model." + name + "(data, ev); return;\n");
127.318 - }
127.319 - w.append(" }\n");
127.320 - w.append(" throw new UnsupportedOperationException();\n");
127.321 - w.append(" }\n");
127.322 - w.append(" public Class<" + className + "> factoryFor() { return " + className + ".class; }\n");
127.323 - w.append(" public " + className + " read(net.java.html.BrwsrCtx c, Object json) { return new " + className + "(c, json); }\n");
127.324 - w.append(" public " + className + " cloneTo(Object o, net.java.html.BrwsrCtx c) { return ((" + className + ")o).clone(c); }\n");
127.325 - w.append(" }\n");
127.326 - w.append(" static { org.apidesign.html.json.impl.JSON.register(new P(0)); }\n");
127.327 - w.append(" private ").append(className).append("(net.java.html.BrwsrCtx c, Object json) {\n");
127.328 - w.append(" this.context = c;\n");
127.329 - int values = 0;
127.330 - for (int i = 0; i < propsGetSet.size(); i += 5) {
127.331 - Prprt p = findPrprt(props, propsGetSet.get(i));
127.332 - if (p == null) {
127.333 - continue;
127.334 - }
127.335 - values++;
127.336 - }
127.337 - w.append(" Object[] ret = new Object[" + values + "];\n");
127.338 - w.append(" org.apidesign.html.json.impl.JSON.extract(context, json, new String[] {\n");
127.339 - for (int i = 0; i < propsGetSet.size(); i += 5) {
127.340 - Prprt p = findPrprt(props, propsGetSet.get(i));
127.341 - if (p == null) {
127.342 - continue;
127.343 - }
127.344 - w.append(" \"").append(propsGetSet.get(i)).append("\",\n");
127.345 - }
127.346 - w.append(" }, ret);\n");
127.347 - for (int i = 0, cnt = 0, prop = 0; i < propsGetSet.size(); i += 5) {
127.348 - final String pn = propsGetSet.get(i);
127.349 - Prprt p = findPrprt(props, pn);
127.350 - if (p == null) {
127.351 - continue;
127.352 - }
127.353 - boolean[] isModel = { false };
127.354 - boolean[] isEnum = { false };
127.355 - boolean isPrimitive[] = { false };
127.356 - String type = checkType(props[prop++], isModel, isEnum, isPrimitive);
127.357 - if (p.array()) {
127.358 - w.append(" if (ret[" + cnt + "] instanceof Object[]) {\n");
127.359 - w.append(" for (Object e : ((Object[])ret[" + cnt + "])) {\n");
127.360 - if (isModel[0]) {
127.361 - w.append(" this.prop_").append(pn).append(".add(org.apidesign.html.json.impl.JSON.read");
127.362 - w.append("(c, " + type + ".class, e));\n");
127.363 - } else if (isEnum[0]) {
127.364 - w.append(" this.prop_").append(pn);
127.365 - w.append(".add(e == null ? null : ");
127.366 - w.append(type).append(".valueOf(org.apidesign.html.json.impl.JSON.stringValue(e)));\n");
127.367 - } else {
127.368 - if (isPrimitive(type)) {
127.369 - w.append(" this.prop_").append(pn).append(".add(org.apidesign.html.json.impl.JSON.numberValue(e).");
127.370 - w.append(type).append("Value());\n");
127.371 - } else {
127.372 - w.append(" this.prop_").append(pn).append(".add((");
127.373 - w.append(type).append(")e);\n");
127.374 - }
127.375 - }
127.376 - w.append(" }\n");
127.377 - w.append(" }\n");
127.378 - } else {
127.379 - if (isEnum[0]) {
127.380 - w.append(" try {\n");
127.381 - w.append(" this.prop_").append(pn);
127.382 - w.append(" = ret[" + cnt + "] == null ? null : ");
127.383 - w.append(type).append(".valueOf(org.apidesign.html.json.impl.JSON.stringValue(ret[" + cnt + "]));\n");
127.384 - w.append(" } catch (IllegalArgumentException ex) {\n");
127.385 - w.append(" ex.printStackTrace();\n");
127.386 - w.append(" }\n");
127.387 - } else if (isPrimitive(type)) {
127.388 - w.append(" this.prop_").append(pn);
127.389 - w.append(" = ret[" + cnt + "] == null ? ");
127.390 - if ("char".equals(type)) {
127.391 - w.append("0 : (org.apidesign.html.json.impl.JSON.charValue(");
127.392 - } else if ("boolean".equals(type)) {
127.393 - w.append("false : (org.apidesign.html.json.impl.JSON.boolValue(");
127.394 - } else {
127.395 - w.append("0 : (org.apidesign.html.json.impl.JSON.numberValue(");
127.396 - }
127.397 - w.append("ret[" + cnt + "])).");
127.398 - w.append(type).append("Value();\n");
127.399 - } else if (isModel[0]) {
127.400 - w.append(" this.prop_").append(pn).append(" = org.apidesign.html.json.impl.JSON.read");
127.401 - w.append("(c, " + type + ".class, ");
127.402 - w.append("ret[" + cnt + "]);\n");
127.403 - }else {
127.404 - w.append(" this.prop_").append(pn);
127.405 - w.append(" = (").append(type).append(')');
127.406 - w.append("ret[" + cnt + "];\n");
127.407 - }
127.408 - }
127.409 - cnt++;
127.410 - }
127.411 - w.append(" };\n");
127.412 - writeToString(props, w);
127.413 - writeClone(className, props, w);
127.414 - w.write(" /** Activates this model instance in the current {@link \n"
127.415 - + "net.java.html.json.Models#bind(java.lang.Object, net.java.html.BrwsrCtx) browser context}. \n"
127.416 - + "In case of using Knockout technology, this means to \n"
127.417 - + "bind JSON like data in this model instance with Knockout tags in \n"
127.418 - + "the surrounding HTML page.\n"
127.419 - + "*/\n"
127.420 - );
127.421 - w.write(" public " + className + " applyBindings() {\n");
127.422 - w.write(" intKnckt().applyBindings();\n");
127.423 - w.write(" return this;\n");
127.424 - w.write(" }\n");
127.425 - w.write(" public boolean equals(Object o) {\n");
127.426 - w.write(" if (o == this) return true;\n");
127.427 - w.write(" if (o instanceof org.apidesign.html.json.impl.WrapperObject) {\n");
127.428 - w.write(" ((org.apidesign.html.json.impl.WrapperObject)o).setRealObject(intKnckt().koData());\n");
127.429 - w.write(" return false;\n");
127.430 - w.write(" }\n");
127.431 - w.write(" if (!(o instanceof " + className + ")) return false;\n");
127.432 - w.write(" " + className + " p = (" + className + ")o;\n");
127.433 - for (Prprt p : props) {
127.434 - w.write(" if (!org.apidesign.html.json.impl.JSON.isSame(prop_" + p.name() + ", p.prop_" + p.name() + ")) return false;\n");
127.435 - }
127.436 - w.write(" return true;\n");
127.437 - w.write(" }\n");
127.438 - w.write(" public int hashCode() {\n");
127.439 - w.write(" int h = " + className + ".class.getName().hashCode();\n");
127.440 - for (Prprt p : props) {
127.441 - w.write(" h = org.apidesign.html.json.impl.JSON.hashPlus(prop_" + p.name() + ", h);\n");
127.442 - }
127.443 - w.write(" return h;\n");
127.444 - w.write(" }\n");
127.445 - w.write("}\n");
127.446 - } finally {
127.447 - w.close();
127.448 - }
127.449 - } catch (IOException ex) {
127.450 - error("Can't create " + className + ".java", e);
127.451 - return false;
127.452 - }
127.453 - return ok;
127.454 - }
127.455 -
127.456 - private boolean generateProperties(
127.457 - Element where,
127.458 - Writer w, Prprt[] properties,
127.459 - Collection<String> props,
127.460 - Map<String,Collection<String>> deps,
127.461 - Map<String,Collection<String>> functionDeps
127.462 - ) throws IOException {
127.463 - boolean ok = true;
127.464 - for (Prprt p : properties) {
127.465 - final String tn;
127.466 - tn = typeName(where, p);
127.467 - String[] gs = toGetSet(p.name(), tn, p.array());
127.468 - String castTo;
127.469 -
127.470 - if (p.array()) {
127.471 - w.write(" private org.apidesign.html.json.impl.JSONList<" + tn + "> prop_" + p.name() + " = new org.apidesign.html.json.impl.JSONList<" + tn + ">(ko, \""
127.472 - + p.name() + "\"");
127.473 - Collection<String> dependants = deps.get(p.name());
127.474 - if (dependants != null) {
127.475 - for (String depProp : dependants) {
127.476 - w.write(", ");
127.477 - w.write('\"');
127.478 - w.write(depProp);
127.479 - w.write('\"');
127.480 - }
127.481 - }
127.482 - w.write(")");
127.483 -
127.484 - dependants = functionDeps.get(p.name());
127.485 - if (dependants != null) {
127.486 - w.write(".onChange(new Runnable() { public void run() {\n");
127.487 - for (String call : dependants) {
127.488 - w.append(" ").append(call);
127.489 - }
127.490 - w.write(" }})");
127.491 - }
127.492 - w.write(";\n");
127.493 -
127.494 - castTo = "java.util.List";
127.495 - w.write(" public java.util.List<" + tn + "> " + gs[0] + "() {\n");
127.496 - w.write(" if (locked) throw new IllegalStateException();\n");
127.497 - w.write(" return prop_" + p.name() + ";\n");
127.498 - w.write(" }\n");
127.499 - } else {
127.500 - castTo = tn;
127.501 - w.write(" private " + tn + " prop_" + p.name() + ";\n");
127.502 - w.write(" public " + tn + " " + gs[0] + "() {\n");
127.503 - w.write(" if (locked) throw new IllegalStateException();\n");
127.504 - w.write(" return prop_" + p.name() + ";\n");
127.505 - w.write(" }\n");
127.506 - w.write(" public void " + gs[1] + "(" + tn + " v) {\n");
127.507 - w.write(" if (locked) throw new IllegalStateException();\n");
127.508 - w.write(" if (org.apidesign.html.json.impl.JSON.isSame(prop_" + p.name() + ", v)) return;\n");
127.509 - w.write(" prop_" + p.name() + " = v;\n");
127.510 - w.write(" org.apidesign.html.json.impl.Bindings b = ko[0];\n");
127.511 - w.write(" if (b != null) {\n");
127.512 - w.write(" b.valueHasMutated(\"" + p.name() + "\");\n");
127.513 - Collection<String> dependants = deps.get(p.name());
127.514 - if (dependants != null) {
127.515 - for (String depProp : dependants) {
127.516 - w.write(" b.valueHasMutated(\"" + depProp + "\");\n");
127.517 - }
127.518 - }
127.519 - w.write(" }\n");
127.520 - dependants = functionDeps.get(p.name());
127.521 - if (dependants != null) {
127.522 - for (String call : dependants) {
127.523 - w.append(" ").append(call);
127.524 - }
127.525 - }
127.526 - w.write(" }\n");
127.527 - }
127.528 -
127.529 - props.add(p.name());
127.530 - props.add(gs[2]);
127.531 - props.add(gs[3]);
127.532 - props.add(gs[0]);
127.533 - props.add(castTo);
127.534 - }
127.535 - return ok;
127.536 - }
127.537 -
127.538 - private boolean generateComputedProperties(
127.539 - Writer w, Prprt[] fixedProps,
127.540 - Collection<? extends Element> arr, Collection<String> props,
127.541 - Map<String,Collection<String>> deps
127.542 - ) throws IOException {
127.543 - boolean ok = true;
127.544 - for (Element e : arr) {
127.545 - if (e.getKind() != ElementKind.METHOD) {
127.546 - continue;
127.547 - }
127.548 - if (e.getAnnotation(ComputedProperty.class) == null) {
127.549 - continue;
127.550 - }
127.551 - if (!e.getModifiers().contains(Modifier.STATIC)) {
127.552 - error("Method " + e.getSimpleName() + " has to be static when annotated by @ComputedProperty", e);
127.553 - ok = false;
127.554 - continue;
127.555 - }
127.556 - ExecutableElement ee = (ExecutableElement)e;
127.557 - final TypeMirror rt = ee.getReturnType();
127.558 - final Types tu = processingEnv.getTypeUtils();
127.559 - TypeMirror ert = tu.erasure(rt);
127.560 - String tn = fqn(ert, ee);
127.561 - boolean array = false;
127.562 - final TypeMirror toCheck;
127.563 - if (tn.equals("java.util.List")) {
127.564 - array = true;
127.565 - toCheck = ((DeclaredType)rt).getTypeArguments().get(0);
127.566 - } else {
127.567 - toCheck = rt;
127.568 - }
127.569 -
127.570 - final String sn = ee.getSimpleName().toString();
127.571 -
127.572 - if (toCheck.getKind().isPrimitive()) {
127.573 - // OK
127.574 - } else {
127.575 - TypeMirror stringType = processingEnv.getElementUtils().getTypeElement("java.lang.String").asType();
127.576 - TypeMirror enumType = processingEnv.getElementUtils().getTypeElement("java.lang.Enum").asType();
127.577 -
127.578 - if (tu.isSubtype(toCheck, stringType)) {
127.579 - // OK
127.580 - } else if (tu.isSubtype(tu.erasure(toCheck), tu.erasure(enumType))) {
127.581 - // OK
127.582 - } else if (isModel(toCheck)) {
127.583 - // OK
127.584 - } else {
127.585 - ok = false;
127.586 - error(sn + " cannot return " + toCheck, e);
127.587 - }
127.588 - }
127.589 -
127.590 - String[] gs = toGetSet(sn, tn, array);
127.591 -
127.592 - w.write(" public " + tn + " " + gs[0] + "() {\n");
127.593 - w.write(" if (locked) throw new IllegalStateException();\n");
127.594 - int arg = 0;
127.595 - for (VariableElement pe : ee.getParameters()) {
127.596 - final String dn = pe.getSimpleName().toString();
127.597 -
127.598 - if (!verifyPropName(pe, dn, fixedProps)) {
127.599 - ok = false;
127.600 - }
127.601 -
127.602 - final String dt = fqn(pe.asType(), ee);
127.603 - String[] call = toGetSet(dn, dt, false);
127.604 - w.write(" " + dt + " arg" + (++arg) + " = ");
127.605 - w.write(call[0] + "();\n");
127.606 -
127.607 - Collection<String> depends = deps.get(dn);
127.608 - if (depends == null) {
127.609 - depends = new LinkedHashSet<String>();
127.610 - deps.put(dn, depends);
127.611 - }
127.612 - depends.add(sn);
127.613 - }
127.614 - w.write(" try {\n");
127.615 - w.write(" locked = true;\n");
127.616 - w.write(" return " + fqn(ee.getEnclosingElement().asType(), ee) + '.' + e.getSimpleName() + "(");
127.617 - String sep = "";
127.618 - for (int i = 1; i <= arg; i++) {
127.619 - w.write(sep);
127.620 - w.write("arg" + i);
127.621 - sep = ", ";
127.622 - }
127.623 - w.write(");\n");
127.624 - w.write(" } finally {\n");
127.625 - w.write(" locked = false;\n");
127.626 - w.write(" }\n");
127.627 - w.write(" }\n");
127.628 -
127.629 - props.add(e.getSimpleName().toString());
127.630 - props.add(gs[2]);
127.631 - props.add(null);
127.632 - props.add(gs[0]);
127.633 - props.add(tn);
127.634 - }
127.635 -
127.636 - return ok;
127.637 - }
127.638 -
127.639 - private static String[] toGetSet(String name, String type, boolean array) {
127.640 - String n = Character.toUpperCase(name.charAt(0)) + name.substring(1);
127.641 - String bck2brwsrType = "L" + type.replace('.', '_') + "_2";
127.642 - if ("int".equals(type)) {
127.643 - bck2brwsrType = "I";
127.644 - }
127.645 - if ("double".equals(type)) {
127.646 - bck2brwsrType = "D";
127.647 - }
127.648 - String pref = "get";
127.649 - if ("boolean".equals(type)) {
127.650 - pref = "is";
127.651 - bck2brwsrType = "Z";
127.652 - }
127.653 - final String nu = n.replace('.', '_');
127.654 - if (array) {
127.655 - return new String[] {
127.656 - "get" + n,
127.657 - null,
127.658 - "get" + nu + "__Ljava_util_List_2",
127.659 - null
127.660 - };
127.661 - }
127.662 - return new String[]{
127.663 - pref + n,
127.664 - "set" + n,
127.665 - pref + nu + "__" + bck2brwsrType,
127.666 - "set" + nu + "__V" + bck2brwsrType
127.667 - };
127.668 - }
127.669 -
127.670 - private String typeName(Element where, Prprt p) {
127.671 - String ret;
127.672 - boolean[] isModel = { false };
127.673 - boolean[] isEnum = { false };
127.674 - boolean isPrimitive[] = { false };
127.675 - ret = checkType(p, isModel, isEnum, isPrimitive);
127.676 - if (p.array()) {
127.677 - String bt = findBoxedType(ret);
127.678 - if (bt != null) {
127.679 - return bt;
127.680 - }
127.681 - }
127.682 - return ret;
127.683 - }
127.684 -
127.685 - private static String findBoxedType(String ret) {
127.686 - if (ret.equals("boolean")) {
127.687 - return Boolean.class.getName();
127.688 - }
127.689 - if (ret.equals("byte")) {
127.690 - return Byte.class.getName();
127.691 - }
127.692 - if (ret.equals("short")) {
127.693 - return Short.class.getName();
127.694 - }
127.695 - if (ret.equals("char")) {
127.696 - return Character.class.getName();
127.697 - }
127.698 - if (ret.equals("int")) {
127.699 - return Integer.class.getName();
127.700 - }
127.701 - if (ret.equals("long")) {
127.702 - return Long.class.getName();
127.703 - }
127.704 - if (ret.equals("float")) {
127.705 - return Float.class.getName();
127.706 - }
127.707 - if (ret.equals("double")) {
127.708 - return Double.class.getName();
127.709 - }
127.710 - return null;
127.711 - }
127.712 -
127.713 - private boolean verifyPropName(Element e, String propName, Prprt[] existingProps) {
127.714 - StringBuilder sb = new StringBuilder();
127.715 - String sep = "";
127.716 - for (Prprt Prprt : existingProps) {
127.717 - if (Prprt.name().equals(propName)) {
127.718 - return true;
127.719 - }
127.720 - sb.append(sep);
127.721 - sb.append('"');
127.722 - sb.append(Prprt.name());
127.723 - sb.append('"');
127.724 - sep = ", ";
127.725 - }
127.726 - error(
127.727 - propName + " is not one of known properties: " + sb
127.728 - , e
127.729 - );
127.730 - return false;
127.731 - }
127.732 -
127.733 - private static String findPkgName(Element e) {
127.734 - for (;;) {
127.735 - if (e.getKind() == ElementKind.PACKAGE) {
127.736 - return ((PackageElement)e).getQualifiedName().toString();
127.737 - }
127.738 - e = e.getEnclosingElement();
127.739 - }
127.740 - }
127.741 -
127.742 - private boolean generateFunctions(
127.743 - Element clazz, StringWriter body, String className,
127.744 - List<? extends Element> enclosedElements, List<String> functions
127.745 - ) {
127.746 - for (Element m : enclosedElements) {
127.747 - if (m.getKind() != ElementKind.METHOD) {
127.748 - continue;
127.749 - }
127.750 - ExecutableElement e = (ExecutableElement)m;
127.751 - Function onF = e.getAnnotation(Function.class);
127.752 - if (onF == null) {
127.753 - continue;
127.754 - }
127.755 - if (!e.getModifiers().contains(Modifier.STATIC)) {
127.756 - error("@OnFunction method needs to be static", e);
127.757 - return false;
127.758 - }
127.759 - if (e.getModifiers().contains(Modifier.PRIVATE)) {
127.760 - error("@OnFunction method cannot be private", e);
127.761 - return false;
127.762 - }
127.763 - if (e.getReturnType().getKind() != TypeKind.VOID) {
127.764 - error("@OnFunction method should return void", e);
127.765 - return false;
127.766 - }
127.767 - String n = e.getSimpleName().toString();
127.768 - body.append(" private void ").append(n).append("(Object data, Object ev) {\n");
127.769 - body.append(" ").append(((TypeElement)clazz).getQualifiedName()).append(".").append(n).append("(");
127.770 - body.append(wrapParams(e, null, className, "ev", "data"));
127.771 - body.append(");\n");
127.772 - body.append(" }\n");
127.773 -
127.774 - functions.add(n);
127.775 - functions.add(n + "__VLjava_lang_Object_2Ljava_lang_Object_2");
127.776 - }
127.777 - return true;
127.778 - }
127.779 -
127.780 - private boolean generateOnChange(Element clazz, Map<String,Collection<String>> propDeps,
127.781 - Prprt[] properties, String className,
127.782 - Map<String, Collection<String>> functionDeps
127.783 - ) {
127.784 - for (Element m : clazz.getEnclosedElements()) {
127.785 - if (m.getKind() != ElementKind.METHOD) {
127.786 - continue;
127.787 - }
127.788 - ExecutableElement e = (ExecutableElement) m;
127.789 - OnPropertyChange onPC = e.getAnnotation(OnPropertyChange.class);
127.790 - if (onPC == null) {
127.791 - continue;
127.792 - }
127.793 - for (String pn : onPC.value()) {
127.794 - if (findPrprt(properties, pn) == null && findDerivedFrom(propDeps, pn).isEmpty()) {
127.795 - error("No Prprt named '" + pn + "' in the model", clazz);
127.796 - return false;
127.797 - }
127.798 - }
127.799 - if (!e.getModifiers().contains(Modifier.STATIC)) {
127.800 - error("@OnPrprtChange method needs to be static", e);
127.801 - return false;
127.802 - }
127.803 - if (e.getModifiers().contains(Modifier.PRIVATE)) {
127.804 - error("@OnPrprtChange method cannot be private", e);
127.805 - return false;
127.806 - }
127.807 - if (e.getReturnType().getKind() != TypeKind.VOID) {
127.808 - error("@OnPrprtChange method should return void", e);
127.809 - return false;
127.810 - }
127.811 - String n = e.getSimpleName().toString();
127.812 -
127.813 -
127.814 - for (String pn : onPC.value()) {
127.815 - StringBuilder call = new StringBuilder();
127.816 - call.append(" ").append(clazz.getSimpleName()).append(".").append(n).append("(");
127.817 - call.append(wrapPropName(e, className, "name", pn));
127.818 - call.append(");\n");
127.819 -
127.820 - Collection<String> change = functionDeps.get(pn);
127.821 - if (change == null) {
127.822 - change = new ArrayList<String>();
127.823 - functionDeps.put(pn, change);
127.824 - }
127.825 - change.add(call.toString());
127.826 - for (String dpn : findDerivedFrom(propDeps, pn)) {
127.827 - change = functionDeps.get(dpn);
127.828 - if (change == null) {
127.829 - change = new ArrayList<String>();
127.830 - functionDeps.put(dpn, change);
127.831 - }
127.832 - change.add(call.toString());
127.833 - }
127.834 - }
127.835 - }
127.836 - return true;
127.837 - }
127.838 -
127.839 - private boolean generateOperation(Element clazz,
127.840 - StringWriter body, String className,
127.841 - List<? extends Element> enclosedElements
127.842 - ) {
127.843 - for (Element m : enclosedElements) {
127.844 - if (m.getKind() != ElementKind.METHOD) {
127.845 - continue;
127.846 - }
127.847 - ExecutableElement e = (ExecutableElement)m;
127.848 - ModelOperation mO = e.getAnnotation(ModelOperation.class);
127.849 - if (mO == null) {
127.850 - continue;
127.851 - }
127.852 - if (!e.getModifiers().contains(Modifier.STATIC)) {
127.853 - error("@ModelOperation method needs to be static", e);
127.854 - return false;
127.855 - }
127.856 - if (e.getModifiers().contains(Modifier.PRIVATE)) {
127.857 - error("@ModelOperation method cannot be private", e);
127.858 - return false;
127.859 - }
127.860 - if (e.getReturnType().getKind() != TypeKind.VOID) {
127.861 - error("@ModelOperation method should return void", e);
127.862 - return false;
127.863 - }
127.864 - List<String> args = new ArrayList<String>();
127.865 - {
127.866 - body.append(" public void ").append(m.getSimpleName()).append("(");
127.867 - String sep = "";
127.868 - boolean checkFirst = true;
127.869 - for (VariableElement ve : e.getParameters()) {
127.870 - final TypeMirror type = ve.asType();
127.871 - CharSequence simpleName;
127.872 - if (type.getKind() == TypeKind.DECLARED) {
127.873 - simpleName = ((DeclaredType)type).asElement().getSimpleName();
127.874 - } else {
127.875 - simpleName = type.toString();
127.876 - }
127.877 - if (simpleName.toString().equals(className)) {
127.878 - checkFirst = false;
127.879 - } else {
127.880 - if (checkFirst) {
127.881 - error("First parameter of @ModelOperation method must be " + className, m);
127.882 - return false;
127.883 - }
127.884 - args.add(ve.getSimpleName().toString());
127.885 - body.append(sep).append("final ");
127.886 - body.append(ve.asType().toString()).append(" ");
127.887 - body.append(ve.toString());
127.888 - sep = ", ";
127.889 - }
127.890 - }
127.891 - body.append(") {\n");
127.892 - body.append(" org.apidesign.html.json.impl.JSON.runInBrowser(this.context, new Runnable() { public void run() {\n");
127.893 - body.append(" ").append(clazz.getSimpleName()).append(".").append(m.getSimpleName()).append("(");
127.894 - body.append(className).append(".this");
127.895 - for (String s : args) {
127.896 - body.append(", ").append(s);
127.897 - }
127.898 - body.append(");\n");
127.899 - body.append(" }});\n");
127.900 - body.append(" }\n");
127.901 - }
127.902 -
127.903 - }
127.904 - return true;
127.905 - }
127.906 -
127.907 -
127.908 - private boolean generateReceive(
127.909 - Element clazz, StringWriter body, String className,
127.910 - List<? extends Element> enclosedElements, List<String> functions
127.911 - ) {
127.912 - for (Element m : enclosedElements) {
127.913 - if (m.getKind() != ElementKind.METHOD) {
127.914 - continue;
127.915 - }
127.916 - ExecutableElement e = (ExecutableElement)m;
127.917 - OnReceive onR = e.getAnnotation(OnReceive.class);
127.918 - if (onR == null) {
127.919 - continue;
127.920 - }
127.921 - if (!e.getModifiers().contains(Modifier.STATIC)) {
127.922 - error("@OnReceive method needs to be static", e);
127.923 - return false;
127.924 - }
127.925 - if (e.getModifiers().contains(Modifier.PRIVATE)) {
127.926 - error("@OnReceive method cannot be private", e);
127.927 - return false;
127.928 - }
127.929 - if (e.getReturnType().getKind() != TypeKind.VOID) {
127.930 - error("@OnReceive method should return void", e);
127.931 - return false;
127.932 - }
127.933 - if (!onR.jsonp().isEmpty() && !"GET".equals(onR.method())) {
127.934 - error("JSONP works only with GET transport method", e);
127.935 - }
127.936 - String dataMirror = findDataSpecified(e, onR);
127.937 - if ("PUT".equals(onR.method()) && dataMirror == null) {
127.938 - error("PUT method needs to specify a data() class", e);
127.939 - return false;
127.940 - }
127.941 - if ("POST".equals(onR.method()) && dataMirror == null) {
127.942 - error("POST method needs to specify a data() class", e);
127.943 - return false;
127.944 - }
127.945 - String modelClass = null;
127.946 - boolean expectsList = false;
127.947 - List<String> args = new ArrayList<String>();
127.948 - {
127.949 - for (VariableElement ve : e.getParameters()) {
127.950 - TypeMirror modelType = null;
127.951 - final TypeMirror type = ve.asType();
127.952 - CharSequence simpleName;
127.953 - if (type.getKind() == TypeKind.DECLARED) {
127.954 - simpleName = ((DeclaredType)type).asElement().getSimpleName();
127.955 - } else {
127.956 - simpleName = type.toString();
127.957 - }
127.958 - if (simpleName.toString().equals(className)) {
127.959 - args.add(className + ".this");
127.960 - } else if (isModel(ve.asType())) {
127.961 - modelType = ve.asType();
127.962 - } else if (ve.asType().getKind() == TypeKind.ARRAY) {
127.963 - modelType = ((ArrayType)ve.asType()).getComponentType();
127.964 - expectsList = true;
127.965 - } else if (ve.asType().toString().equals("java.lang.String")) {
127.966 - modelType = ve.asType();
127.967 - }
127.968 - if (modelType != null) {
127.969 - if (modelClass != null) {
127.970 - error("There can be only one model class among arguments", e);
127.971 - } else {
127.972 - modelClass = modelType.toString();
127.973 - if (expectsList) {
127.974 - args.add("arr");
127.975 - } else {
127.976 - args.add("arr[0]");
127.977 - }
127.978 - }
127.979 - }
127.980 - }
127.981 - }
127.982 - if (modelClass == null) {
127.983 - error("The method needs to have one @Model class as parameter", e);
127.984 - }
127.985 - String n = e.getSimpleName().toString();
127.986 - if ("WebSocket".equals(onR.method())) {
127.987 - body.append(" /** Performs WebSocket communication. Call with <code>null</code> data parameter\n");
127.988 - body.append(" * to open the connection (even if not required). Call with non-null data to\n");
127.989 - body.append(" * send messages to server. Call again with <code>null</code> data to close the socket.\n");
127.990 - body.append(" */\n");
127.991 - }
127.992 - body.append(" public void ").append(n).append("(");
127.993 - StringBuilder urlBefore = new StringBuilder();
127.994 - StringBuilder urlAfter = new StringBuilder();
127.995 - String jsonpVarName = null;
127.996 - {
127.997 - String sep = "";
127.998 - boolean skipJSONP = onR.jsonp().isEmpty();
127.999 - for (String p : findParamNames(e, onR.url(), onR.jsonp(), urlBefore, urlAfter)) {
127.1000 - if (!skipJSONP && p.equals(onR.jsonp())) {
127.1001 - skipJSONP = true;
127.1002 - jsonpVarName = p;
127.1003 - continue;
127.1004 - }
127.1005 - body.append(sep);
127.1006 - body.append("String ").append(p);
127.1007 - sep = ", ";
127.1008 - }
127.1009 - if (!skipJSONP) {
127.1010 - error(
127.1011 - "Name of jsonp attribute ('" + onR.jsonp() +
127.1012 - "') is not used in url attribute '" + onR.url() + "'", e
127.1013 - );
127.1014 - }
127.1015 - if (dataMirror != null) {
127.1016 - body.append(sep).append(dataMirror.toString()).append(" data");
127.1017 - }
127.1018 - }
127.1019 - body.append(") {\n");
127.1020 - boolean webSocket = onR.method().equals("WebSocket");
127.1021 - if (webSocket) {
127.1022 - if (generateWSReceiveBody(body, onR, e, clazz, className, expectsList, modelClass, n, args, urlBefore, jsonpVarName, urlAfter, dataMirror)) {
127.1023 - return false;
127.1024 - }
127.1025 - body.append(" }\n");
127.1026 - body.append(" private org.apidesign.html.json.impl.JSON.WS ws_" + e.getSimpleName() + ";\n");
127.1027 - } else {
127.1028 - if (generateJSONReceiveBody(body, onR, e, clazz, className, expectsList, modelClass, n, args, urlBefore, jsonpVarName, urlAfter, dataMirror)) {
127.1029 - return false;
127.1030 - }
127.1031 - body.append(" }\n");
127.1032 - }
127.1033 - }
127.1034 - return true;
127.1035 - }
127.1036 -
127.1037 - private boolean generateJSONReceiveBody(StringWriter body, OnReceive onR, ExecutableElement e, Element clazz, String className, boolean expectsList, String modelClass, String n, List<String> args, StringBuilder urlBefore, String jsonpVarName, StringBuilder urlAfter, String dataMirror) {
127.1038 - body.append(
127.1039 - " class ProcessResult extends org.apidesign.html.json.impl.RcvrJSON {\n" +
127.1040 - " @Override\n" +
127.1041 - " public void onError(org.apidesign.html.json.impl.RcvrJSON.MsgEvnt ev) {\n" +
127.1042 - " Exception value = ev.getException();\n"
127.1043 - );
127.1044 - if (onR.onError().isEmpty()) {
127.1045 - body.append(
127.1046 - " value.printStackTrace();\n"
127.1047 - );
127.1048 - } else {
127.1049 - if (!findOnError(e, ((TypeElement)clazz), onR.onError(), className)) {
127.1050 - return true;
127.1051 - }
127.1052 - body.append(" ").append(clazz.getSimpleName()).append(".").append(onR.onError()).append("(");
127.1053 - body.append(className).append(".this, value);\n");
127.1054 - }
127.1055 - body.append(
127.1056 - " }\n" +
127.1057 - " @Override\n" +
127.1058 - " public void onMessage(org.apidesign.html.json.impl.RcvrJSON.MsgEvnt ev) {\n"
127.1059 - );
127.1060 - if (expectsList) {
127.1061 - body.append(
127.1062 - " " + modelClass + "[] arr = new " + modelClass + "[ev.dataSize()];\n"
127.1063 - );
127.1064 - } else {
127.1065 - body.append(
127.1066 - " " + modelClass + "[] arr = { null };\n"
127.1067 - );
127.1068 - }
127.1069 - body.append(
127.1070 - " ev.dataRead(context, " + modelClass + ".class, arr);\n"
127.1071 - );
127.1072 - {
127.1073 - body.append(" ").append(clazz.getSimpleName()).append(".").append(n).append("(");
127.1074 - String sep = "";
127.1075 - for (String arg : args) {
127.1076 - body.append(sep);
127.1077 - body.append(arg);
127.1078 - sep = ", ";
127.1079 - }
127.1080 - body.append(");\n");
127.1081 - }
127.1082 - body.append(
127.1083 - " }\n" +
127.1084 - " }\n"
127.1085 - );
127.1086 - body.append(" ProcessResult pr = new ProcessResult();\n");
127.1087 - body.append(" org.apidesign.html.json.impl.JSON.loadJSON(context, pr,\n ");
127.1088 - body.append(urlBefore).append(", ");
127.1089 - if (jsonpVarName != null) {
127.1090 - body.append(urlAfter);
127.1091 - } else {
127.1092 - body.append("null");
127.1093 - }
127.1094 - if (!"GET".equals(onR.method()) || dataMirror != null) {
127.1095 - body.append(", \"").append(onR.method()).append('"');
127.1096 - if (dataMirror != null) {
127.1097 - body.append(", data");
127.1098 - } else {
127.1099 - body.append(", null");
127.1100 - }
127.1101 - } else {
127.1102 - body.append(", null, null");
127.1103 - }
127.1104 - body.append(");\n");
127.1105 - return false;
127.1106 - }
127.1107 -
127.1108 - private boolean generateWSReceiveBody(StringWriter body, OnReceive onR, ExecutableElement e, Element clazz, String className, boolean expectsList, String modelClass, String n, List<String> args, StringBuilder urlBefore, String jsonpVarName, StringBuilder urlAfter, String dataMirror) {
127.1109 - body.append(
127.1110 - " class ProcessResult extends org.apidesign.html.json.impl.RcvrJSON {\n" +
127.1111 - " @Override\n" +
127.1112 - " public void onOpen(org.apidesign.html.json.impl.RcvrJSON.MsgEvnt ev) {\n"
127.1113 - );
127.1114 - body.append(" ").append(clazz.getSimpleName()).append(".").append(n).append("(");
127.1115 - {
127.1116 - String sep = "";
127.1117 - for (String arg : args) {
127.1118 - body.append(sep);
127.1119 - if (arg.startsWith("arr")) {
127.1120 - body.append("null");
127.1121 - } else {
127.1122 - body.append(arg);
127.1123 - }
127.1124 - sep = ", ";
127.1125 - }
127.1126 - }
127.1127 - body.append(");\n");
127.1128 - body.append(
127.1129 - " }\n" +
127.1130 - " @Override\n" +
127.1131 - " public void onError(org.apidesign.html.json.impl.RcvrJSON.MsgEvnt ev) {\n" +
127.1132 - " Exception value = ev.getException();\n"
127.1133 - );
127.1134 - if (onR.onError().isEmpty()) {
127.1135 - body.append(
127.1136 - " value.printStackTrace();\n"
127.1137 - );
127.1138 - } else {
127.1139 - if (!findOnError(e, ((TypeElement)clazz), onR.onError(), className)) {
127.1140 - return true;
127.1141 - }
127.1142 - body.append(" ").append(clazz.getSimpleName()).append(".").append(onR.onError()).append("(");
127.1143 - body.append(className).append(".this, value);\n");
127.1144 - }
127.1145 - body.append(
127.1146 - " }\n" +
127.1147 - " @Override\n" +
127.1148 - " public void onMessage(org.apidesign.html.json.impl.RcvrJSON.MsgEvnt ev) {\n"
127.1149 - );
127.1150 - if (expectsList) {
127.1151 - body.append(
127.1152 - " " + modelClass + "[] arr = new " + modelClass + "[ev.dataSize()];\n"
127.1153 - );
127.1154 - } else {
127.1155 - body.append(
127.1156 - " " + modelClass + "[] arr = { null };\n"
127.1157 - );
127.1158 - }
127.1159 - body.append(
127.1160 - " ev.dataRead(context, " + modelClass + ".class, arr);\n"
127.1161 - );
127.1162 - {
127.1163 - body.append(" ").append(clazz.getSimpleName()).append(".").append(n).append("(");
127.1164 - String sep = "";
127.1165 - for (String arg : args) {
127.1166 - body.append(sep);
127.1167 - body.append(arg);
127.1168 - sep = ", ";
127.1169 - }
127.1170 - body.append(");\n");
127.1171 - }
127.1172 - body.append(
127.1173 - " }\n"
127.1174 - );
127.1175 - if (!onR.onError().isEmpty()) {
127.1176 - body.append(
127.1177 - " @Override\n"
127.1178 - + " public void onClose(org.apidesign.html.json.impl.RcvrJSON.MsgEvnt ev) {\n"
127.1179 - );
127.1180 - body.append(" ").append(clazz.getSimpleName()).append(".").append(onR.onError()).append("(");
127.1181 - body.append(className).append(".this, null);\n");
127.1182 - body.append(
127.1183 - " }\n"
127.1184 - );
127.1185 - }
127.1186 - body.append(" }\n");
127.1187 - body.append(" if (this.ws_").append(e.getSimpleName()).append(" == null) {\n");
127.1188 - body.append(" ProcessResult pr = new ProcessResult();\n");
127.1189 - body.append(" this.ws_").append(e.getSimpleName());
127.1190 - body.append("= org.apidesign.html.json.impl.JSON.openWS(context, pr,\n ");
127.1191 - body.append(urlBefore).append(", data);\n");
127.1192 - body.append(" } else {\n");
127.1193 - body.append(" this.ws_").append(e.getSimpleName()).append(".send(context, ").append(urlBefore).append(", data);\n");
127.1194 - body.append(" }\n");
127.1195 - return false;
127.1196 - }
127.1197 -
127.1198 - private CharSequence wrapParams(
127.1199 - ExecutableElement ee, String id, String className, String evName, String dataName
127.1200 - ) {
127.1201 - TypeMirror stringType = processingEnv.getElementUtils().getTypeElement("java.lang.String").asType();
127.1202 - StringBuilder params = new StringBuilder();
127.1203 - boolean first = true;
127.1204 - for (VariableElement ve : ee.getParameters()) {
127.1205 - if (!first) {
127.1206 - params.append(", ");
127.1207 - }
127.1208 - first = false;
127.1209 - String toCall = null;
127.1210 - String toFinish = null;
127.1211 - if (ve.asType() == stringType) {
127.1212 - if (ve.getSimpleName().contentEquals("id")) {
127.1213 - params.append('"').append(id).append('"');
127.1214 - continue;
127.1215 - }
127.1216 - toCall = "org.apidesign.html.json.impl.JSON.toString(context, ";
127.1217 - }
127.1218 - if (ve.asType().getKind() == TypeKind.DOUBLE) {
127.1219 - toCall = "org.apidesign.html.json.impl.JSON.toNumber(context, ";
127.1220 - toFinish = ".doubleValue()";
127.1221 - }
127.1222 - if (ve.asType().getKind() == TypeKind.INT) {
127.1223 - toCall = "org.apidesign.html.json.impl.JSON.toNumber(context, ";
127.1224 - toFinish = ".intValue()";
127.1225 - }
127.1226 - if (dataName != null && ve.getSimpleName().contentEquals(dataName) && isModel(ve.asType())) {
127.1227 - toCall = "org.apidesign.html.json.impl.JSON.toModel(context, " + ve.asType() + ".class, ";
127.1228 - }
127.1229 -
127.1230 - if (toCall != null) {
127.1231 - params.append(toCall);
127.1232 - if (dataName != null && ve.getSimpleName().contentEquals(dataName)) {
127.1233 - params.append(dataName);
127.1234 - params.append(", null");
127.1235 - } else {
127.1236 - if (evName == null) {
127.1237 - final StringBuilder sb = new StringBuilder();
127.1238 - sb.append("Unexpected string parameter name.");
127.1239 - if (dataName != null) {
127.1240 - sb.append(" Try \"").append(dataName).append("\"");
127.1241 - }
127.1242 - error(sb.toString(), ee);
127.1243 - }
127.1244 - params.append(evName);
127.1245 - params.append(", \"");
127.1246 - params.append(ve.getSimpleName().toString());
127.1247 - params.append("\"");
127.1248 - }
127.1249 - params.append(")");
127.1250 - if (toFinish != null) {
127.1251 - params.append(toFinish);
127.1252 - }
127.1253 - continue;
127.1254 - }
127.1255 - String rn = fqn(ve.asType(), ee);
127.1256 - int last = rn.lastIndexOf('.');
127.1257 - if (last >= 0) {
127.1258 - rn = rn.substring(last + 1);
127.1259 - }
127.1260 - if (rn.equals(className)) {
127.1261 - params.append(className).append(".this");
127.1262 - continue;
127.1263 - }
127.1264 - error(
127.1265 - "The annotated method can only accept " + className + " argument or argument named 'data'",
127.1266 - ee
127.1267 - );
127.1268 - }
127.1269 - return params;
127.1270 - }
127.1271 -
127.1272 -
127.1273 - private CharSequence wrapPropName(
127.1274 - ExecutableElement ee, String className, String propName, String propValue
127.1275 - ) {
127.1276 - TypeMirror stringType = processingEnv.getElementUtils().getTypeElement("java.lang.String").asType();
127.1277 - StringBuilder params = new StringBuilder();
127.1278 - boolean first = true;
127.1279 - for (VariableElement ve : ee.getParameters()) {
127.1280 - if (!first) {
127.1281 - params.append(", ");
127.1282 - }
127.1283 - first = false;
127.1284 - if (ve.asType() == stringType) {
127.1285 - if (propName != null && ve.getSimpleName().contentEquals(propName)) {
127.1286 - params.append('"').append(propValue).append('"');
127.1287 - } else {
127.1288 - error("Unexpected string parameter name. Try \"" + propName + "\".", ee);
127.1289 - }
127.1290 - continue;
127.1291 - }
127.1292 - String rn = fqn(ve.asType(), ee);
127.1293 - int last = rn.lastIndexOf('.');
127.1294 - if (last >= 0) {
127.1295 - rn = rn.substring(last + 1);
127.1296 - }
127.1297 - if (rn.equals(className)) {
127.1298 - params.append(className).append(".this");
127.1299 - continue;
127.1300 - }
127.1301 - error(
127.1302 - "@OnPrprtChange method can only accept String or " + className + " arguments",
127.1303 - ee);
127.1304 - }
127.1305 - return params;
127.1306 - }
127.1307 -
127.1308 - private boolean isModel(TypeMirror tm) {
127.1309 - if (tm.getKind() == TypeKind.ERROR) {
127.1310 - return true;
127.1311 - }
127.1312 - final Element e = processingEnv.getTypeUtils().asElement(tm);
127.1313 - if (e == null) {
127.1314 - return false;
127.1315 - }
127.1316 - for (Element ch : e.getEnclosedElements()) {
127.1317 - if (ch.getKind() == ElementKind.METHOD) {
127.1318 - ExecutableElement ee = (ExecutableElement)ch;
127.1319 - if (ee.getParameters().isEmpty() && ee.getSimpleName().contentEquals("modelFor")) {
127.1320 - return true;
127.1321 - }
127.1322 - }
127.1323 - }
127.1324 - return models.values().contains(e.getSimpleName().toString());
127.1325 - }
127.1326 -
127.1327 - private void writeToString(Prprt[] props, Writer w) throws IOException {
127.1328 - w.write(" public String toString() {\n");
127.1329 - w.write(" StringBuilder sb = new StringBuilder();\n");
127.1330 - w.write(" sb.append('{');\n");
127.1331 - String sep = "";
127.1332 - for (Prprt p : props) {
127.1333 - w.write(sep);
127.1334 - w.append(" sb.append('\"').append(\"" + p.name() + "\")");
127.1335 - w.append(".append('\"').append(\":\");\n");
127.1336 - w.append(" sb.append(org.apidesign.html.json.impl.JSON.toJSON(prop_");
127.1337 - w.append(p.name()).append("));\n");
127.1338 - sep = " sb.append(',');\n";
127.1339 - }
127.1340 - w.write(" sb.append('}');\n");
127.1341 - w.write(" return sb.toString();\n");
127.1342 - w.write(" }\n");
127.1343 - }
127.1344 - private void writeClone(String className, Prprt[] props, Writer w) throws IOException {
127.1345 - w.write(" public " + className + " clone() {\n");
127.1346 - w.write(" return clone(context);\n");
127.1347 - w.write(" }\n");
127.1348 - w.write(" private " + className + " clone(net.java.html.BrwsrCtx ctx) {\n");
127.1349 - w.write(" " + className + " ret = new " + className + "(ctx);\n");
127.1350 - for (Prprt p : props) {
127.1351 - if (!p.array()) {
127.1352 - boolean isModel[] = { false };
127.1353 - boolean isEnum[] = { false };
127.1354 - boolean isPrimitive[] = { false };
127.1355 - checkType(p, isModel, isEnum, isPrimitive);
127.1356 - if (!isModel[0]) {
127.1357 - w.write(" ret.prop_" + p.name() + " = prop_" + p.name() + ";\n");
127.1358 - continue;
127.1359 - }
127.1360 - w.write(" ret.prop_" + p.name() + " = prop_" + p.name() + " == null ? null : prop_" + p.name() + ".clone();\n");
127.1361 - } else {
127.1362 - w.write(" ret.prop_" + p.name() + ".cloneAll(ctx, prop_" + p.name() + ");\n");
127.1363 - }
127.1364 - }
127.1365 -
127.1366 - w.write(" return ret;\n");
127.1367 - w.write(" }\n");
127.1368 - }
127.1369 -
127.1370 - private String inPckName(Element e) {
127.1371 - StringBuilder sb = new StringBuilder();
127.1372 - while (e.getKind() != ElementKind.PACKAGE) {
127.1373 - if (sb.length() == 0) {
127.1374 - sb.append(e.getSimpleName());
127.1375 - } else {
127.1376 - sb.insert(0, '.');
127.1377 - sb.insert(0, e.getSimpleName());
127.1378 - }
127.1379 - e = e.getEnclosingElement();
127.1380 - }
127.1381 - return sb.toString();
127.1382 - }
127.1383 -
127.1384 - private String fqn(TypeMirror pt, Element relative) {
127.1385 - if (pt.getKind() == TypeKind.ERROR) {
127.1386 - final Elements eu = processingEnv.getElementUtils();
127.1387 - PackageElement pckg = eu.getPackageOf(relative);
127.1388 - return pckg.getQualifiedName() + "." + pt.toString();
127.1389 - }
127.1390 - return pt.toString();
127.1391 - }
127.1392 -
127.1393 - private String checkType(Prprt p, boolean[] isModel, boolean[] isEnum, boolean[] isPrimitive) {
127.1394 - TypeMirror tm;
127.1395 - try {
127.1396 - String ret = p.typeName(processingEnv);
127.1397 - TypeElement e = processingEnv.getElementUtils().getTypeElement(ret);
127.1398 - if (e == null) {
127.1399 - isModel[0] = true;
127.1400 - isEnum[0] = false;
127.1401 - isPrimitive[0] = false;
127.1402 - return ret;
127.1403 - }
127.1404 - tm = e.asType();
127.1405 - } catch (MirroredTypeException ex) {
127.1406 - tm = ex.getTypeMirror();
127.1407 - }
127.1408 - tm = processingEnv.getTypeUtils().erasure(tm);
127.1409 - if (isPrimitive[0] = tm.getKind().isPrimitive()) {
127.1410 - isEnum[0] = false;
127.1411 - isModel[0] = false;
127.1412 - return tm.toString();
127.1413 - }
127.1414 - final Element e = processingEnv.getTypeUtils().asElement(tm);
127.1415 - if (e.getKind() == ElementKind.CLASS && tm.getKind() == TypeKind.ERROR) {
127.1416 - isModel[0] = true;
127.1417 - isEnum[0] = false;
127.1418 - return e.getSimpleName().toString();
127.1419 - }
127.1420 -
127.1421 - final Model m = e == null ? null : e.getAnnotation(Model.class);
127.1422 - String ret;
127.1423 - if (m != null) {
127.1424 - ret = findPkgName(e) + '.' + m.className();
127.1425 - isModel[0] = true;
127.1426 - models.put(e, m.className());
127.1427 - } else if (findModelForMthd(e)) {
127.1428 - ret = ((TypeElement)e).getQualifiedName().toString();
127.1429 - isModel[0] = true;
127.1430 - } else {
127.1431 - ret = tm.toString();
127.1432 - }
127.1433 - TypeMirror enm = processingEnv.getElementUtils().getTypeElement("java.lang.Enum").asType();
127.1434 - enm = processingEnv.getTypeUtils().erasure(enm);
127.1435 - isEnum[0] = processingEnv.getTypeUtils().isSubtype(tm, enm);
127.1436 - return ret;
127.1437 - }
127.1438 -
127.1439 - private static boolean findModelForMthd(Element clazz) {
127.1440 - if (clazz == null) {
127.1441 - return false;
127.1442 - }
127.1443 - for (Element e : clazz.getEnclosedElements()) {
127.1444 - if (e.getKind() == ElementKind.METHOD) {
127.1445 - ExecutableElement ee = (ExecutableElement)e;
127.1446 - if (
127.1447 - ee.getSimpleName().contentEquals("modelFor") &&
127.1448 - ee.getParameters().isEmpty()
127.1449 - ) {
127.1450 - return true;
127.1451 - }
127.1452 - }
127.1453 - }
127.1454 - return false;
127.1455 - }
127.1456 -
127.1457 - private Iterable<String> findParamNames(
127.1458 - Element e, String url, String jsonParam, StringBuilder... both
127.1459 - ) {
127.1460 - List<String> params = new ArrayList<String>();
127.1461 - int wasJSON = 0;
127.1462 -
127.1463 - for (int pos = 0; ;) {
127.1464 - int next = url.indexOf('{', pos);
127.1465 - if (next == -1) {
127.1466 - both[wasJSON].append('"')
127.1467 - .append(url.substring(pos))
127.1468 - .append('"');
127.1469 - return params;
127.1470 - }
127.1471 - int close = url.indexOf('}', next);
127.1472 - if (close == -1) {
127.1473 - error("Unbalanced '{' and '}' in " + url, e);
127.1474 - return params;
127.1475 - }
127.1476 - final String paramName = url.substring(next + 1, close);
127.1477 - params.add(paramName);
127.1478 - if (paramName.equals(jsonParam) && !jsonParam.isEmpty()) {
127.1479 - both[wasJSON].append('"')
127.1480 - .append(url.substring(pos, next))
127.1481 - .append('"');
127.1482 - wasJSON = 1;
127.1483 - } else {
127.1484 - both[wasJSON].append('"')
127.1485 - .append(url.substring(pos, next))
127.1486 - .append("\" + ").append(paramName).append(" + ");
127.1487 - }
127.1488 - pos = close + 1;
127.1489 - }
127.1490 - }
127.1491 -
127.1492 - private static Prprt findPrprt(Prprt[] properties, String propName) {
127.1493 - for (Prprt p : properties) {
127.1494 - if (propName.equals(p.name())) {
127.1495 - return p;
127.1496 - }
127.1497 - }
127.1498 - return null;
127.1499 - }
127.1500 -
127.1501 - private boolean isPrimitive(String type) {
127.1502 - return
127.1503 - "int".equals(type) ||
127.1504 - "double".equals(type) ||
127.1505 - "long".equals(type) ||
127.1506 - "short".equals(type) ||
127.1507 - "byte".equals(type) ||
127.1508 - "char".equals(type) ||
127.1509 - "boolean".equals(type) ||
127.1510 - "float".equals(type);
127.1511 - }
127.1512 -
127.1513 - private static Collection<String> findDerivedFrom(Map<String, Collection<String>> propsDeps, String derivedProp) {
127.1514 - Set<String> names = new HashSet<String>();
127.1515 - for (Map.Entry<String, Collection<String>> e : propsDeps.entrySet()) {
127.1516 - if (e.getValue().contains(derivedProp)) {
127.1517 - names.add(e.getKey());
127.1518 - }
127.1519 - }
127.1520 - return names;
127.1521 - }
127.1522 -
127.1523 - private Prprt[] createProps(Element e, Property[] arr) {
127.1524 - Prprt[] ret = Prprt.wrap(processingEnv, e, arr);
127.1525 - Prprt[] prev = verify.put(e, ret);
127.1526 - if (prev != null) {
127.1527 - error("Two sets of properties for ", e);
127.1528 - }
127.1529 - return ret;
127.1530 - }
127.1531 -
127.1532 - private static String strip(String s) {
127.1533 - int indx = s.indexOf("__");
127.1534 - if (indx >= 0) {
127.1535 - return s.substring(0, indx);
127.1536 - } else {
127.1537 - return s;
127.1538 - }
127.1539 - }
127.1540 -
127.1541 - private String findDataSpecified(ExecutableElement e, OnReceive onR) {
127.1542 - try {
127.1543 - return onR.data().getName();
127.1544 - } catch (MirroredTypeException ex) {
127.1545 - final TypeMirror tm = ex.getTypeMirror();
127.1546 - String name;
127.1547 - final Element te = processingEnv.getTypeUtils().asElement(tm);
127.1548 - if (te.getKind() == ElementKind.CLASS && tm.getKind() == TypeKind.ERROR) {
127.1549 - name = te.getSimpleName().toString();
127.1550 - } else {
127.1551 - name = tm.toString();
127.1552 - }
127.1553 - return "java.lang.Object".equals(name) ? null : name;
127.1554 - } catch (Exception ex) {
127.1555 - // fallback
127.1556 - }
127.1557 -
127.1558 - AnnotationMirror found = null;
127.1559 - for (AnnotationMirror am : e.getAnnotationMirrors()) {
127.1560 - if (am.getAnnotationType().toString().equals(OnReceive.class.getName())) {
127.1561 - found = am;
127.1562 - }
127.1563 - }
127.1564 - if (found == null) {
127.1565 - return null;
127.1566 - }
127.1567 -
127.1568 - for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : found.getElementValues().entrySet()) {
127.1569 - ExecutableElement ee = entry.getKey();
127.1570 - AnnotationValue av = entry.getValue();
127.1571 - if (ee.getSimpleName().contentEquals("data")) {
127.1572 - List<? extends Object> values = getAnnoValues(processingEnv, e, found);
127.1573 - for (Object v : values) {
127.1574 - String sv = v.toString();
127.1575 - if (sv.startsWith("data = ") && sv.endsWith(".class")) {
127.1576 - return sv.substring(7, sv.length() - 6);
127.1577 - }
127.1578 - }
127.1579 - return "error";
127.1580 - }
127.1581 - }
127.1582 - return null;
127.1583 - }
127.1584 -
127.1585 - static List<? extends Object> getAnnoValues(ProcessingEnvironment pe, Element e, AnnotationMirror am) {
127.1586 - try {
127.1587 - Class<?> trees = Class.forName("com.sun.tools.javac.api.JavacTrees");
127.1588 - Method m = trees.getMethod("instance", ProcessingEnvironment.class);
127.1589 - Object instance = m.invoke(null, pe);
127.1590 - m = instance.getClass().getMethod("getPath", Element.class, AnnotationMirror.class);
127.1591 - Object path = m.invoke(instance, e, am);
127.1592 - m = path.getClass().getMethod("getLeaf");
127.1593 - Object leaf = m.invoke(path);
127.1594 - m = leaf.getClass().getMethod("getArguments");
127.1595 - return (List) m.invoke(leaf);
127.1596 - } catch (Exception ex) {
127.1597 - return Collections.emptyList();
127.1598 - }
127.1599 - }
127.1600 -
127.1601 - private static class Prprt {
127.1602 - private final Element e;
127.1603 - private final AnnotationMirror tm;
127.1604 - private final Property p;
127.1605 -
127.1606 - public Prprt(Element e, AnnotationMirror tm, Property p) {
127.1607 - this.e = e;
127.1608 - this.tm = tm;
127.1609 - this.p = p;
127.1610 - }
127.1611 -
127.1612 - String name() {
127.1613 - return p.name();
127.1614 - }
127.1615 -
127.1616 - boolean array() {
127.1617 - return p.array();
127.1618 - }
127.1619 -
127.1620 - String typeName(ProcessingEnvironment env) {
127.1621 - RuntimeException ex;
127.1622 - try {
127.1623 - return p.type().getName();
127.1624 - } catch (IncompleteAnnotationException e) {
127.1625 - ex = e;
127.1626 - } catch (AnnotationTypeMismatchException e) {
127.1627 - ex = e;
127.1628 - }
127.1629 - for (Object v : getAnnoValues(env, e, tm)) {
127.1630 - String s = v.toString().replace(" ", "");
127.1631 - if (s.startsWith("type=") && s.endsWith(".class")) {
127.1632 - return s.substring(5, s.length() - 6);
127.1633 - }
127.1634 - }
127.1635 - throw ex;
127.1636 - }
127.1637 -
127.1638 -
127.1639 - static Prprt[] wrap(ProcessingEnvironment pe, Element e, Property[] arr) {
127.1640 - if (arr.length == 0) {
127.1641 - return new Prprt[0];
127.1642 - }
127.1643 -
127.1644 - if (e.getKind() != ElementKind.CLASS) {
127.1645 - throw new IllegalStateException("" + e.getKind());
127.1646 - }
127.1647 - TypeElement te = (TypeElement)e;
127.1648 - List<? extends AnnotationValue> val = null;
127.1649 - for (AnnotationMirror an : te.getAnnotationMirrors()) {
127.1650 - for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : an.getElementValues().entrySet()) {
127.1651 - if (entry.getKey().getSimpleName().contentEquals("properties")) {
127.1652 - val = (List)entry.getValue().getValue();
127.1653 - break;
127.1654 - }
127.1655 - }
127.1656 - }
127.1657 - if (val == null || val.size() != arr.length) {
127.1658 - pe.getMessager().printMessage(Diagnostic.Kind.ERROR, "" + val, e);
127.1659 - return new Prprt[0];
127.1660 - }
127.1661 - Prprt[] ret = new Prprt[arr.length];
127.1662 - BIG: for (int i = 0; i < ret.length; i++) {
127.1663 - AnnotationMirror am = (AnnotationMirror)val.get(i).getValue();
127.1664 - ret[i] = new Prprt(e, am, arr[i]);
127.1665 -
127.1666 - }
127.1667 - return ret;
127.1668 - }
127.1669 - }
127.1670 -
127.1671 - @Override
127.1672 - public Iterable<? extends Completion> getCompletions(Element element, AnnotationMirror annotation, ExecutableElement member, String userText) {
127.1673 - final Level l = Level.FINE;
127.1674 - LOG.log(l, " element: {0}", element);
127.1675 - LOG.log(l, " annotation: {0}", annotation);
127.1676 - LOG.log(l, " member: {0}", member);
127.1677 - LOG.log(l, " userText: {0}", userText);
127.1678 - LOG.log(l, "str: {0}", annotation.getAnnotationType().toString());
127.1679 - if (annotation.getAnnotationType().toString().equals(OnReceive.class.getName())) {
127.1680 - if (member.getSimpleName().contentEquals("method")) {
127.1681 - return Arrays.asList(
127.1682 - methodOf("GET"),
127.1683 - methodOf("POST"),
127.1684 - methodOf("PUT"),
127.1685 - methodOf("DELETE"),
127.1686 - methodOf("HEAD"),
127.1687 - methodOf("WebSocket")
127.1688 - );
127.1689 - }
127.1690 - }
127.1691 -
127.1692 - return super.getCompletions(element, annotation, member, userText);
127.1693 - }
127.1694 -
127.1695 - private static final Completion methodOf(String method) {
127.1696 - ResourceBundle rb = ResourceBundle.getBundle("org.apidesign.html.json.impl.Bundle");
127.1697 - return Completions.of('"' + method + '"', rb.getString("MSG_Completion_" + method));
127.1698 - }
127.1699 -
127.1700 - private boolean findOnError(ExecutableElement errElem, TypeElement te, String name, String className) {
127.1701 - String err = null;
127.1702 - METHODS:
127.1703 - for (Element e : te.getEnclosedElements()) {
127.1704 - if (e.getKind() != ElementKind.METHOD) {
127.1705 - continue;
127.1706 - }
127.1707 - if (!e.getSimpleName().contentEquals(name)) {
127.1708 - continue;
127.1709 - }
127.1710 - if (!e.getModifiers().contains(Modifier.STATIC)) {
127.1711 - errElem = (ExecutableElement) e;
127.1712 - err = "Would have to be static";
127.1713 - continue;
127.1714 - }
127.1715 - ExecutableElement ee = (ExecutableElement) e;
127.1716 - TypeMirror excType = processingEnv.getElementUtils().getTypeElement(Exception.class.getName()).asType();
127.1717 - final List<? extends VariableElement> params = ee.getParameters();
127.1718 - boolean error = false;
127.1719 - if (params.size() != 2) {
127.1720 - error = true;
127.1721 - } else {
127.1722 - String firstType = params.get(0).asType().toString();
127.1723 - int lastDot = firstType.lastIndexOf('.');
127.1724 - if (lastDot != -1) {
127.1725 - firstType = firstType.substring(lastDot + 1);
127.1726 - }
127.1727 - if (!firstType.equals(className)) {
127.1728 - error = true;
127.1729 - }
127.1730 - if (!processingEnv.getTypeUtils().isAssignable(excType, params.get(1).asType())) {
127.1731 - error = true;
127.1732 - }
127.1733 - }
127.1734 - if (error) {
127.1735 - errElem = (ExecutableElement) e;
127.1736 - err = "Error method first argument needs to be " + className + " and second Exception";
127.1737 - continue;
127.1738 - }
127.1739 - return true;
127.1740 - }
127.1741 - if (err == null) {
127.1742 - err = "Cannot find " + name + "(" + className + ", Exception) method in this class";
127.1743 - }
127.1744 - error(err, errElem);
127.1745 - return false;
127.1746 - }
127.1747 -
127.1748 -}
128.1 --- a/json/src/main/java/org/apidesign/html/json/impl/PropertyBindingAccessor.java Thu Dec 19 17:11:01 2013 +0100
128.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
128.3 @@ -1,113 +0,0 @@
128.4 -/**
128.5 - * HTML via Java(tm) Language Bindings
128.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
128.7 - *
128.8 - * This program is free software: you can redistribute it and/or modify
128.9 - * it under the terms of the GNU General Public License as published by
128.10 - * the Free Software Foundation, version 2 of the License.
128.11 - *
128.12 - * This program is distributed in the hope that it will be useful,
128.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
128.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
128.15 - * GNU General Public License for more details. apidesign.org
128.16 - * designates this particular file as subject to the
128.17 - * "Classpath" exception as provided by apidesign.org
128.18 - * in the License file that accompanied this code.
128.19 - *
128.20 - * You should have received a copy of the GNU General Public License
128.21 - * along with this program. Look for COPYING file in the top folder.
128.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
128.23 - */
128.24 -package org.apidesign.html.json.impl;
128.25 -
128.26 -import net.java.html.BrwsrCtx;
128.27 -import org.apidesign.html.json.spi.FunctionBinding;
128.28 -import org.apidesign.html.json.spi.JSONCall;
128.29 -import org.apidesign.html.json.spi.PropertyBinding;
128.30 -
128.31 -/**
128.32 - *
128.33 - * @author Jaroslav Tulach <jtulach@netbeans.org>
128.34 - */
128.35 -public abstract class PropertyBindingAccessor {
128.36 - private static PropertyBindingAccessor DEFAULT;
128.37 -
128.38 - protected PropertyBindingAccessor() {
128.39 - if (DEFAULT != null) throw new IllegalStateException();
128.40 - DEFAULT = this;
128.41 - }
128.42 -
128.43 - static {
128.44 - JSON.initClass(PropertyBinding.class);
128.45 - }
128.46 -
128.47 - protected abstract <M> PropertyBinding newBinding(PBData<M> d);
128.48 - protected abstract <M> FunctionBinding newFunction(FBData<M> d);
128.49 - protected abstract JSONCall newCall(
128.50 - BrwsrCtx ctx, RcvrJSON callback, String urlBefore, String urlAfter,
128.51 - String method, Object data
128.52 - );
128.53 -
128.54 -
128.55 - static <M> PropertyBinding create(PBData<M> d) {
128.56 - return DEFAULT.newBinding(d);
128.57 - }
128.58 - static <M> FunctionBinding createFunction(FBData<M> d) {
128.59 - return DEFAULT.newFunction(d);
128.60 - }
128.61 - static JSONCall createCall(
128.62 - BrwsrCtx ctx, RcvrJSON callback, String urlBefore, String urlAfter,
128.63 - String method, Object data
128.64 - ) {
128.65 - return DEFAULT.newCall(ctx, callback, urlBefore, urlAfter, method, data);
128.66 - }
128.67 -
128.68 - public static final class PBData<M> {
128.69 - public final String name;
128.70 - public final boolean readOnly;
128.71 - private final M model;
128.72 - private final SetAndGet<M> access;
128.73 - private final Bindings<?> bindings;
128.74 -
128.75 - public PBData(Bindings<?> bindings, String name, M model, SetAndGet<M> access, boolean readOnly) {
128.76 - this.bindings = bindings;
128.77 - this.name = name;
128.78 - this.model = model;
128.79 - this.access = access;
128.80 - this.readOnly = readOnly;
128.81 - }
128.82 -
128.83 - public void setValue(Object v) {
128.84 - access.setValue(model, v);
128.85 - }
128.86 -
128.87 - public Object getValue() {
128.88 - return access.getValue(model);
128.89 - }
128.90 -
128.91 - public boolean isReadOnly() {
128.92 - return readOnly;
128.93 - }
128.94 -
128.95 - public Bindings getBindings() {
128.96 - return bindings;
128.97 - }
128.98 - } // end of PBData
128.99 -
128.100 - public static final class FBData<M> {
128.101 - public final String name;
128.102 - private final M model;
128.103 - private final Callback<M> access;
128.104 -
128.105 - public FBData(String name, M model, Callback<M> access) {
128.106 - this.name = name;
128.107 - this.model = model;
128.108 - this.access = access;
128.109 - }
128.110 -
128.111 -
128.112 - public void call(Object data, Object ev) {
128.113 - access.call(model, data, ev);
128.114 - }
128.115 - } // end of FBData
128.116 -}
129.1 --- a/json/src/main/java/org/apidesign/html/json/impl/RcvrJSON.java Thu Dec 19 17:11:01 2013 +0100
129.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
129.3 @@ -1,127 +0,0 @@
129.4 -/**
129.5 - * HTML via Java(tm) Language Bindings
129.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
129.7 - *
129.8 - * This program is free software: you can redistribute it and/or modify
129.9 - * it under the terms of the GNU General Public License as published by
129.10 - * the Free Software Foundation, version 2 of the License.
129.11 - *
129.12 - * This program is distributed in the hope that it will be useful,
129.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
129.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
129.15 - * GNU General Public License for more details. apidesign.org
129.16 - * designates this particular file as subject to the
129.17 - * "Classpath" exception as provided by apidesign.org
129.18 - * in the License file that accompanied this code.
129.19 - *
129.20 - * You should have received a copy of the GNU General Public License
129.21 - * along with this program. Look for COPYING file in the top folder.
129.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
129.23 - */
129.24 -package org.apidesign.html.json.impl;
129.25 -
129.26 -import net.java.html.BrwsrCtx;
129.27 -
129.28 -/** Super type for those who wish to receive JSON messages.
129.29 - *
129.30 - * @author Jaroslav Tulach <jtulach@netbeans.org>
129.31 - */
129.32 -public abstract class RcvrJSON {
129.33 - protected void onOpen(MsgEvnt msg) {}
129.34 - protected abstract void onMessage(MsgEvnt msg);
129.35 - protected void onClose(MsgEvnt msg) {}
129.36 - protected abstract void onError(MsgEvnt msg);
129.37 -
129.38 - public abstract static class MsgEvnt {
129.39 - MsgEvnt() {
129.40 - }
129.41 -
129.42 - public Throwable getError() {
129.43 - return null;
129.44 - }
129.45 -
129.46 - public final Exception getException() {
129.47 - Throwable t = getError();
129.48 - if (t instanceof Exception) {
129.49 - return (Exception)t;
129.50 - }
129.51 - if (t == null) {
129.52 - return null;
129.53 - }
129.54 - return new Exception(t);
129.55 - }
129.56 -
129.57 - public int dataSize() {
129.58 - return -1;
129.59 - }
129.60 -
129.61 - public <Data> void dataRead(BrwsrCtx ctx, Class<? extends Data> type, Data[] fillTheArray) {
129.62 - }
129.63 -
129.64 - public abstract void dispatch(RcvrJSON r);
129.65 -
129.66 - public static MsgEvnt createError(final Throwable t) {
129.67 - return new MsgEvnt() {
129.68 - @Override
129.69 - public Throwable getError() {
129.70 - return t;
129.71 - }
129.72 -
129.73 - @Override
129.74 - public void dispatch(RcvrJSON r) {
129.75 - r.onError(this);
129.76 - }
129.77 - };
129.78 - }
129.79 -
129.80 - public static MsgEvnt createMessage(final Object value) {
129.81 - return new MsgEvnt() {
129.82 - @Override
129.83 - public int dataSize() {
129.84 - if (value instanceof Object[]) {
129.85 - return ((Object[])value).length;
129.86 - } else {
129.87 - return 1;
129.88 - }
129.89 - }
129.90 -
129.91 - @Override
129.92 - public <Data> void dataRead(BrwsrCtx context, Class<? extends Data> type, Data[] arr) {
129.93 - if (value instanceof Object[]) {
129.94 - Object[] data = ((Object[]) value);
129.95 - for (int i = 0; i < data.length && i < arr.length; i++) {
129.96 - arr[i] = org.apidesign.html.json.impl.JSON.read(context, type, data[i]);
129.97 - }
129.98 - } else {
129.99 - if (arr.length > 0) {
129.100 - arr[0] = org.apidesign.html.json.impl.JSON.read(context, type, value);
129.101 - }
129.102 - }
129.103 - }
129.104 -
129.105 - @Override
129.106 - public void dispatch(RcvrJSON r) {
129.107 - r.onMessage(this);
129.108 - }
129.109 - };
129.110 - }
129.111 -
129.112 - public static MsgEvnt createOpen() {
129.113 - return new MsgEvnt() {
129.114 - @Override
129.115 - public void dispatch(RcvrJSON r) {
129.116 - r.onOpen(this);
129.117 - }
129.118 - };
129.119 - }
129.120 -
129.121 - public static MsgEvnt createClose() {
129.122 - return new MsgEvnt() {
129.123 - @Override
129.124 - public void dispatch(RcvrJSON r) {
129.125 - r.onClose(this);
129.126 - }
129.127 - };
129.128 - }
129.129 - } // end MsgEvnt
129.130 -}
130.1 --- a/json/src/main/java/org/apidesign/html/json/impl/SetAndGet.java Thu Dec 19 17:11:01 2013 +0100
130.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
130.3 @@ -1,33 +0,0 @@
130.4 -/**
130.5 - * HTML via Java(tm) Language Bindings
130.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
130.7 - *
130.8 - * This program is free software: you can redistribute it and/or modify
130.9 - * it under the terms of the GNU General Public License as published by
130.10 - * the Free Software Foundation, version 2 of the License.
130.11 - *
130.12 - * This program is distributed in the hope that it will be useful,
130.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
130.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
130.15 - * GNU General Public License for more details. apidesign.org
130.16 - * designates this particular file as subject to the
130.17 - * "Classpath" exception as provided by apidesign.org
130.18 - * in the License file that accompanied this code.
130.19 - *
130.20 - * You should have received a copy of the GNU General Public License
130.21 - * along with this program. Look for COPYING file in the top folder.
130.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
130.23 - */
130.24 -
130.25 -package org.apidesign.html.json.impl;
130.26 -
130.27 -import org.apidesign.html.json.spi.PropertyBinding;
130.28 -
130.29 -/** A way to implement a {@link PropertyBinding}.
130.30 - *
130.31 - * @author Jaroslav Tulach <jtulach@netbeans.org>
130.32 - */
130.33 -public interface SetAndGet<Data> {
130.34 - public void setValue(Data data, Object value);
130.35 - public Object getValue(Data data);
130.36 -}
131.1 --- a/json/src/main/java/org/apidesign/html/json/impl/WrapperObject.java Thu Dec 19 17:11:01 2013 +0100
131.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
131.3 @@ -1,61 +0,0 @@
131.4 -/**
131.5 - * HTML via Java(tm) Language Bindings
131.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
131.7 - *
131.8 - * This program is free software: you can redistribute it and/or modify
131.9 - * it under the terms of the GNU General Public License as published by
131.10 - * the Free Software Foundation, version 2 of the License.
131.11 - *
131.12 - * This program is distributed in the hope that it will be useful,
131.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
131.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
131.15 - * GNU General Public License for more details. apidesign.org
131.16 - * designates this particular file as subject to the
131.17 - * "Classpath" exception as provided by apidesign.org
131.18 - * in the License file that accompanied this code.
131.19 - *
131.20 - * You should have received a copy of the GNU General Public License
131.21 - * along with this program. Look for COPYING file in the top folder.
131.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
131.23 - */
131.24 -
131.25 -package org.apidesign.html.json.impl;
131.26 -
131.27 -import java.util.Collection;
131.28 -import org.apidesign.html.json.impl.PropertyBindingAccessor.PBData;
131.29 -
131.30 -/** A way to extract real object from a model classes.
131.31 - *
131.32 - * @author Jaroslav Tulach <jtulach@netbeans.org>
131.33 - */
131.34 -public final class WrapperObject {
131.35 - private Object ko;
131.36 -
131.37 - private WrapperObject() {
131.38 - }
131.39 -
131.40 - public void setRealObject(Object ko) {
131.41 - this.ko = ko;
131.42 - }
131.43 -
131.44 - public static Object find(Object object) {
131.45 - return find(object, null);
131.46 - }
131.47 -
131.48 - public static Object find(Object object, Bindings model) {
131.49 - if (object == null) {
131.50 - return null;
131.51 - }
131.52 -
131.53 - if (object instanceof JSONList) {
131.54 - return ((JSONList<?>)object).koData();
131.55 - }
131.56 - if (object instanceof Collection) {
131.57 - return JSONList.koData((Collection<?>)object, model);
131.58 - }
131.59 -
131.60 - WrapperObject ro = new WrapperObject();
131.61 - object.equals(ro);
131.62 - return ro.ko;
131.63 - }
131.64 -}
132.1 --- a/json/src/main/java/org/apidesign/html/json/spi/FunctionBinding.java Thu Dec 19 17:11:01 2013 +0100
132.2 +++ b/json/src/main/java/org/apidesign/html/json/spi/FunctionBinding.java Tue Jan 07 08:21:57 2014 +0100
132.3 @@ -1,56 +1,102 @@
132.4 /**
132.5 - * HTML via Java(tm) Language Bindings
132.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
132.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
132.8 *
132.9 - * This program is free software: you can redistribute it and/or modify
132.10 - * it under the terms of the GNU General Public License as published by
132.11 - * the Free Software Foundation, version 2 of the License.
132.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
132.13 *
132.14 - * This program is distributed in the hope that it will be useful,
132.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
132.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
132.17 - * GNU General Public License for more details. apidesign.org
132.18 - * designates this particular file as subject to the
132.19 - * "Classpath" exception as provided by apidesign.org
132.20 - * in the License file that accompanied this code.
132.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
132.22 + * Other names may be trademarks of their respective owners.
132.23 *
132.24 - * You should have received a copy of the GNU General Public License
132.25 - * along with this program. Look for COPYING file in the top folder.
132.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
132.27 + * The contents of this file are subject to the terms of either the GNU
132.28 + * General Public License Version 2 only ("GPL") or the Common
132.29 + * Development and Distribution License("CDDL") (collectively, the
132.30 + * "License"). You may not use this file except in compliance with the
132.31 + * License. You can obtain a copy of the License at
132.32 + * http://www.netbeans.org/cddl-gplv2.html
132.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
132.34 + * specific language governing permissions and limitations under the
132.35 + * License. When distributing the software, include this License Header
132.36 + * Notice in each file and include the License file at
132.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
132.38 + * particular file as subject to the "Classpath" exception as provided
132.39 + * by Oracle in the GPL Version 2 section of the License file that
132.40 + * accompanied this code. If applicable, add the following below the
132.41 + * License Header, with the fields enclosed by brackets [] replaced by
132.42 + * your own identifying information:
132.43 + * "Portions Copyrighted [year] [name of copyright owner]"
132.44 + *
132.45 + * Contributor(s):
132.46 + *
132.47 + * The Original Software is NetBeans. The Initial Developer of the Original
132.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
132.49 + *
132.50 + * If you wish your version of this file to be governed by only the CDDL
132.51 + * or only the GPL Version 2, indicate your decision by adding
132.52 + * "[Contributor] elects to include this software in this distribution
132.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
132.54 + * single choice of license, a recipient has the option to distribute
132.55 + * your version of this file under either the CDDL, the GPL Version 2 or
132.56 + * to extend the choice of license to its licensees as provided above.
132.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
132.58 + * Version 2 license, then the option applies only if the new code is
132.59 + * made subject to such option by the copyright holder.
132.60 */
132.61 package org.apidesign.html.json.spi;
132.62
132.63 import net.java.html.json.Function;
132.64 import net.java.html.json.Model;
132.65 -import org.apidesign.html.json.impl.PropertyBindingAccessor.FBData;
132.66
132.67 /** Describes a function provided by the {@link Model} and
132.68 * annotated by {@link Function} annotation.
132.69 *
132.70 * @author Jaroslav Tulach <jtulach@netbeans.org>
132.71 */
132.72 -public final class FunctionBinding {
132.73 - private final FBData<?> fb;
132.74 -
132.75 - FunctionBinding(FBData<?> fb) {
132.76 - this.fb = fb;
132.77 - }
132.78 -
132.79 - public String getFunctionName() {
132.80 - return fb.name;
132.81 +public abstract class FunctionBinding {
132.82 + FunctionBinding() {
132.83 }
132.84
132.85 - /** Calls the function provided data associated with current element,
132.86 - * as well as information about the event that triggered the event.
132.87 - *
132.88 + /** Returns name of the function.
132.89 + * @return function name
132.90 + */
132.91 + public abstract String getFunctionName();
132.92 +
132.93 + /**
132.94 + * Calls the function provided data associated with current element, as well
132.95 + * as information about the event that triggered the event.
132.96 + *
132.97 * @param data data associated with selected element
132.98 * @param ev event (with additional properties) that triggered the event
132.99 */
132.100 - public void call(Object data, Object ev) {
132.101 - try {
132.102 - fb.call(data, ev);
132.103 - } catch (Throwable ex) {
132.104 - ex.printStackTrace();
132.105 + public abstract void call(Object data, Object ev);
132.106 +
132.107 + static <M> FunctionBinding registerFunction(String name, int index, M model, Proto.Type<M> access) {
132.108 + return new Impl<M>(name, index, model, access);
132.109 + }
132.110 +
132.111 + private static final class Impl<M> extends FunctionBinding {
132.112 + final String name;
132.113 + private final M model;
132.114 + private final Proto.Type<M> access;
132.115 + private final int index;
132.116 +
132.117 + public Impl(String name, int index, M model, Proto.Type<M> access) {
132.118 + this.name = name;
132.119 + this.index = index;
132.120 + this.model = model;
132.121 + this.access = access;
132.122 + }
132.123 +
132.124 + @Override
132.125 + public String getFunctionName() {
132.126 + return name;
132.127 + }
132.128 +
132.129 + @Override
132.130 + public void call(Object data, Object ev) {
132.131 + try {
132.132 + access.call(model, index, data, ev);
132.133 + } catch (Throwable ex) {
132.134 + ex.printStackTrace();
132.135 + }
132.136 }
132.137 }
132.138 }
133.1 --- a/json/src/main/java/org/apidesign/html/json/spi/JSONCall.java Thu Dec 19 17:11:01 2013 +0100
133.2 +++ b/json/src/main/java/org/apidesign/html/json/spi/JSONCall.java Tue Jan 07 08:21:57 2014 +0100
133.3 @@ -1,31 +1,52 @@
133.4 /**
133.5 - * HTML via Java(tm) Language Bindings
133.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
133.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
133.8 *
133.9 - * This program is free software: you can redistribute it and/or modify
133.10 - * it under the terms of the GNU General Public License as published by
133.11 - * the Free Software Foundation, version 2 of the License.
133.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
133.13 *
133.14 - * This program is distributed in the hope that it will be useful,
133.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
133.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
133.17 - * GNU General Public License for more details. apidesign.org
133.18 - * designates this particular file as subject to the
133.19 - * "Classpath" exception as provided by apidesign.org
133.20 - * in the License file that accompanied this code.
133.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
133.22 + * Other names may be trademarks of their respective owners.
133.23 *
133.24 - * You should have received a copy of the GNU General Public License
133.25 - * along with this program. Look for COPYING file in the top folder.
133.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
133.27 + * The contents of this file are subject to the terms of either the GNU
133.28 + * General Public License Version 2 only ("GPL") or the Common
133.29 + * Development and Distribution License("CDDL") (collectively, the
133.30 + * "License"). You may not use this file except in compliance with the
133.31 + * License. You can obtain a copy of the License at
133.32 + * http://www.netbeans.org/cddl-gplv2.html
133.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
133.34 + * specific language governing permissions and limitations under the
133.35 + * License. When distributing the software, include this License Header
133.36 + * Notice in each file and include the License file at
133.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
133.38 + * particular file as subject to the "Classpath" exception as provided
133.39 + * by Oracle in the GPL Version 2 section of the License file that
133.40 + * accompanied this code. If applicable, add the following below the
133.41 + * License Header, with the fields enclosed by brackets [] replaced by
133.42 + * your own identifying information:
133.43 + * "Portions Copyrighted [year] [name of copyright owner]"
133.44 + *
133.45 + * Contributor(s):
133.46 + *
133.47 + * The Original Software is NetBeans. The Initial Developer of the Original
133.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
133.49 + *
133.50 + * If you wish your version of this file to be governed by only the CDDL
133.51 + * or only the GPL Version 2, indicate your decision by adding
133.52 + * "[Contributor] elects to include this software in this distribution
133.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
133.54 + * single choice of license, a recipient has the option to distribute
133.55 + * your version of this file under either the CDDL, the GPL Version 2 or
133.56 + * to extend the choice of license to its licensees as provided above.
133.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
133.58 + * Version 2 license, then the option applies only if the new code is
133.59 + * made subject to such option by the copyright holder.
133.60 */
133.61 -
133.62 package org.apidesign.html.json.spi;
133.63
133.64 import java.io.IOException;
133.65 import java.io.OutputStream;
133.66 import net.java.html.BrwsrCtx;
133.67 -import org.apidesign.html.json.impl.JSON;
133.68 -import org.apidesign.html.json.impl.RcvrJSON;
133.69 +import org.netbeans.html.json.impl.JSON;
133.70 +import org.netbeans.html.json.impl.RcvrJSON;
133.71
133.72 /** Description of a JSON call request that is supposed to be processed
133.73 * by {@link Transfer#loadJSON(org.apidesign.html.json.spi.JSONCall)} implementors.
134.1 --- a/json/src/main/java/org/apidesign/html/json/spi/PropertyBinding.java Thu Dec 19 17:11:01 2013 +0100
134.2 +++ b/json/src/main/java/org/apidesign/html/json/spi/PropertyBinding.java Tue Jan 07 08:21:57 2014 +0100
134.3 @@ -1,77 +1,168 @@
134.4 /**
134.5 - * HTML via Java(tm) Language Bindings
134.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
134.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
134.8 *
134.9 - * This program is free software: you can redistribute it and/or modify
134.10 - * it under the terms of the GNU General Public License as published by
134.11 - * the Free Software Foundation, version 2 of the License.
134.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
134.13 *
134.14 - * This program is distributed in the hope that it will be useful,
134.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
134.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
134.17 - * GNU General Public License for more details. apidesign.org
134.18 - * designates this particular file as subject to the
134.19 - * "Classpath" exception as provided by apidesign.org
134.20 - * in the License file that accompanied this code.
134.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
134.22 + * Other names may be trademarks of their respective owners.
134.23 *
134.24 - * You should have received a copy of the GNU General Public License
134.25 - * along with this program. Look for COPYING file in the top folder.
134.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
134.27 + * The contents of this file are subject to the terms of either the GNU
134.28 + * General Public License Version 2 only ("GPL") or the Common
134.29 + * Development and Distribution License("CDDL") (collectively, the
134.30 + * "License"). You may not use this file except in compliance with the
134.31 + * License. You can obtain a copy of the License at
134.32 + * http://www.netbeans.org/cddl-gplv2.html
134.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
134.34 + * specific language governing permissions and limitations under the
134.35 + * License. When distributing the software, include this License Header
134.36 + * Notice in each file and include the License file at
134.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
134.38 + * particular file as subject to the "Classpath" exception as provided
134.39 + * by Oracle in the GPL Version 2 section of the License file that
134.40 + * accompanied this code. If applicable, add the following below the
134.41 + * License Header, with the fields enclosed by brackets [] replaced by
134.42 + * your own identifying information:
134.43 + * "Portions Copyrighted [year] [name of copyright owner]"
134.44 + *
134.45 + * Contributor(s):
134.46 + *
134.47 + * The Original Software is NetBeans. The Initial Developer of the Original
134.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
134.49 + *
134.50 + * If you wish your version of this file to be governed by only the CDDL
134.51 + * or only the GPL Version 2, indicate your decision by adding
134.52 + * "[Contributor] elects to include this software in this distribution
134.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
134.54 + * single choice of license, a recipient has the option to distribute
134.55 + * your version of this file under either the CDDL, the GPL Version 2 or
134.56 + * to extend the choice of license to its licensees as provided above.
134.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
134.58 + * Version 2 license, then the option applies only if the new code is
134.59 + * made subject to such option by the copyright holder.
134.60 */
134.61 package org.apidesign.html.json.spi;
134.62
134.63 import net.java.html.BrwsrCtx;
134.64 -import org.apidesign.html.json.impl.PropertyBindingAccessor;
134.65 -import org.apidesign.html.json.impl.PropertyBindingAccessor.PBData;
134.66 -import org.apidesign.html.json.impl.RcvrJSON;
134.67 -import org.apidesign.html.json.impl.WrapperObject;
134.68 +import org.netbeans.html.json.impl.Bindings;
134.69 +import org.netbeans.html.json.impl.JSON;
134.70 +import org.netbeans.html.json.impl.PropertyBindingAccessor;
134.71 +import org.netbeans.html.json.impl.RcvrJSON;
134.72
134.73 /** Describes a property when one is asked to
134.74 * bind it
134.75 *
134.76 * @author Jaroslav Tulach <jtulach@netbeans.org>
134.77 */
134.78 -public final class PropertyBinding {
134.79 - private final PBData<?> data;
134.80 -
134.81 - private PropertyBinding(PBData<?> p) {
134.82 - this.data = p;
134.83 +public abstract class PropertyBinding {
134.84 + PropertyBinding() {
134.85 }
134.86
134.87 static {
134.88 new PropertyBindingAccessor() {
134.89 @Override
134.90 - protected <M> PropertyBinding newBinding(PBData<M> d) {
134.91 - return new PropertyBinding(d);
134.92 + protected JSONCall newCall(BrwsrCtx ctx, RcvrJSON callback, String urlBefore, String urlAfter, String method, Object data) {
134.93 + return new JSONCall(ctx, callback, urlBefore, urlAfter, method, data);
134.94 }
134.95
134.96 @Override
134.97 - protected <M> FunctionBinding newFunction(FBData<M> d) {
134.98 - return new FunctionBinding(d);
134.99 + protected Bindings bindings(Proto proto, boolean initialize) {
134.100 + return initialize ? proto.initBindings() : proto.getBindings();
134.101 }
134.102
134.103 @Override
134.104 - protected JSONCall newCall(BrwsrCtx ctx, RcvrJSON callback, String urlBefore, String urlAfter, String method, Object data) {
134.105 - return new JSONCall(ctx, callback, urlBefore, urlAfter, method, data);
134.106 + protected void notifyChange(Proto proto, int propIndex) {
134.107 + proto.onChange(propIndex);
134.108 + }
134.109 +
134.110 + @Override
134.111 + protected Proto findProto(Proto.Type<?> type, Object object) {
134.112 + return type.protoFor(object);
134.113 + }
134.114 +
134.115 + @Override
134.116 + protected <Model> Model cloneTo(Proto.Type<Model> type, Model model, BrwsrCtx c) {
134.117 + return type.cloneTo(model, c);
134.118 + }
134.119 +
134.120 + @Override
134.121 + protected Object read(Proto.Type<?> from, BrwsrCtx c, Object data) {
134.122 + return from.read(c, data);
134.123 + }
134.124 +
134.125 + @Override
134.126 + protected <M> PropertyBinding newBinding(
134.127 + Proto.Type<M> access, Bindings<?> bindings, String name,
134.128 + int index, M model, boolean readOnly
134.129 + ) {
134.130 + return new Impl(bindings, name, index, model, access, readOnly);
134.131 }
134.132 };
134.133 }
134.134
134.135 - public String getPropertyName() {
134.136 - return data.name;
134.137 - }
134.138 + /** Name of the property this binding represents.
134.139 + * @return name of the property
134.140 + */
134.141 + public abstract String getPropertyName();
134.142
134.143 - public void setValue(Object v) {
134.144 - data.setValue(v);
134.145 - }
134.146 + /** Changes value of the property. Can be called only on dedicated
134.147 + * thread. See {@link Technology#runSafe(java.lang.Runnable)}.
134.148 + *
134.149 + * @param v new value of the property
134.150 + */
134.151 + public abstract void setValue(Object v);
134.152
134.153 - public Object getValue() {
134.154 - Object v = data.getValue();
134.155 - Object r = WrapperObject.find(v, data.getBindings());
134.156 - return r == null ? v : r;
134.157 - }
134.158 + /** Obtains current value of the property this binding represents.
134.159 + * Can be called only on dedicated
134.160 + * thread. See {@link Technology#runSafe(java.lang.Runnable)}.
134.161 + *
134.162 + * @return the value or <code>null</code>
134.163 + */
134.164 + public abstract Object getValue();
134.165
134.166 - public boolean isReadOnly() {
134.167 - return data.isReadOnly();
134.168 - }
134.169 + /** Is this property read only? Or can one call {@link #setValue(java.lang.Object)}?
134.170 + *
134.171 + * @return true, if this property is read only
134.172 + */
134.173 + public abstract boolean isReadOnly();
134.174 +
134.175 + private static final class Impl<M> extends PropertyBinding {
134.176 + public final String name;
134.177 + public final boolean readOnly;
134.178 + private final M model;
134.179 + private final Proto.Type<M> access;
134.180 + private final Bindings<?> bindings;
134.181 + private final int index;
134.182 +
134.183 + public Impl(Bindings<?> bindings, String name, int index, M model, Proto.Type<M> access, boolean readOnly) {
134.184 + this.bindings = bindings;
134.185 + this.name = name;
134.186 + this.index = index;
134.187 + this.model = model;
134.188 + this.access = access;
134.189 + this.readOnly = readOnly;
134.190 + }
134.191 +
134.192 + @Override
134.193 + public void setValue(Object v) {
134.194 + access.setValue(model, index, v);
134.195 + }
134.196 +
134.197 + @Override
134.198 + public Object getValue() {
134.199 + Object v = access.getValue(model, index);
134.200 + Object r = JSON.find(v, bindings);
134.201 + return r == null ? v : r;
134.202 + }
134.203 +
134.204 + @Override
134.205 + public boolean isReadOnly() {
134.206 + return readOnly;
134.207 + }
134.208 +
134.209 + @Override
134.210 + public String getPropertyName() {
134.211 + return name;
134.212 + }
134.213 + } // end of PBData
134.214 +
134.215 }
135.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
135.2 +++ b/json/src/main/java/org/apidesign/html/json/spi/Proto.java Tue Jan 07 08:21:57 2014 +0100
135.3 @@ -0,0 +1,660 @@
135.4 +/**
135.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
135.6 + *
135.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
135.8 + *
135.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
135.10 + * Other names may be trademarks of their respective owners.
135.11 + *
135.12 + * The contents of this file are subject to the terms of either the GNU
135.13 + * General Public License Version 2 only ("GPL") or the Common
135.14 + * Development and Distribution License("CDDL") (collectively, the
135.15 + * "License"). You may not use this file except in compliance with the
135.16 + * License. You can obtain a copy of the License at
135.17 + * http://www.netbeans.org/cddl-gplv2.html
135.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
135.19 + * specific language governing permissions and limitations under the
135.20 + * License. When distributing the software, include this License Header
135.21 + * Notice in each file and include the License file at
135.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
135.23 + * particular file as subject to the "Classpath" exception as provided
135.24 + * by Oracle in the GPL Version 2 section of the License file that
135.25 + * accompanied this code. If applicable, add the following below the
135.26 + * License Header, with the fields enclosed by brackets [] replaced by
135.27 + * your own identifying information:
135.28 + * "Portions Copyrighted [year] [name of copyright owner]"
135.29 + *
135.30 + * Contributor(s):
135.31 + *
135.32 + * The Original Software is NetBeans. The Initial Developer of the Original
135.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
135.34 + *
135.35 + * If you wish your version of this file to be governed by only the CDDL
135.36 + * or only the GPL Version 2, indicate your decision by adding
135.37 + * "[Contributor] elects to include this software in this distribution
135.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
135.39 + * single choice of license, a recipient has the option to distribute
135.40 + * your version of this file under either the CDDL, the GPL Version 2 or
135.41 + * to extend the choice of license to its licensees as provided above.
135.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
135.43 + * Version 2 license, then the option applies only if the new code is
135.44 + * made subject to such option by the copyright holder.
135.45 + */
135.46 +package org.apidesign.html.json.spi;
135.47 +
135.48 +import java.util.Collection;
135.49 +import java.util.List;
135.50 +import net.java.html.BrwsrCtx;
135.51 +import net.java.html.json.ComputedProperty;
135.52 +import net.java.html.json.Model;
135.53 +import org.netbeans.html.json.impl.Bindings;
135.54 +import org.netbeans.html.json.impl.JSON;
135.55 +import org.netbeans.html.json.impl.JSONList;
135.56 +import org.netbeans.html.json.impl.RcvrJSON;
135.57 +import org.netbeans.html.json.impl.RcvrJSON.MsgEvnt;
135.58 +
135.59 +/** Object associated with one instance of a model generated by the
135.60 + * {@link Model} annotation. Contains methods the generated class can
135.61 + * use to communicate with behind the scene associated {@link Technology}.
135.62 + * Each {@link Proto} object is associated with <a href="http://wiki.apidesign.org/wiki/Singletonizer">
135.63 + * singletonizer</a>-like interface {@link Type} which provides the
135.64 + * associated {@link Technology} the necessary information about the
135.65 + * generated {@link Model} class.
135.66 + *
135.67 + * @author Jaroslav Tulach <jtulach@netbeans.org>
135.68 + * @since 0.7
135.69 + */
135.70 +public final class Proto {
135.71 + private final Object obj;
135.72 + private final Type type;
135.73 + private final net.java.html.BrwsrCtx context;
135.74 + private boolean locked;
135.75 + private org.netbeans.html.json.impl.Bindings ko;
135.76 +
135.77 + Proto(Object obj, Type type, BrwsrCtx context) {
135.78 + this.obj = obj;
135.79 + this.type = type;
135.80 + this.context = context;
135.81 + }
135.82 +
135.83 + /** Browser context this proto object and its associated model
135.84 + * are operating-in.
135.85 + *
135.86 + * @return the associated context
135.87 + */
135.88 + public BrwsrCtx getContext() {
135.89 + return context;
135.90 + }
135.91 +
135.92 + /** Before doing modification of the model properties, the
135.93 + * generated code enters write lock by calling this method.
135.94 + * @throws IllegalStateException if already locked
135.95 + */
135.96 + public void acquireLock() throws IllegalStateException {
135.97 + if (locked) throw new IllegalStateException();
135.98 + locked = true;
135.99 + }
135.100 +
135.101 + /** Verifies the model is not locked otherwise throws an exception.
135.102 + * @throws IllegalStateException if the model is locked
135.103 + */
135.104 + public void verifyUnlocked() throws IllegalStateException {
135.105 + if (locked) throw new IllegalStateException();
135.106 + }
135.107 +
135.108 + /** When modifications are over, the model is switched into
135.109 + * unlocked state by calling this method.
135.110 + */
135.111 + public void releaseLock() {
135.112 + locked = false;
135.113 + }
135.114 +
135.115 + /** Whenever model changes a property. It should notify the
135.116 + * associated technology by calling this method.
135.117 + *
135.118 + *@param propName name of the changed property
135.119 + */
135.120 + public void valueHasMutated(String propName) {
135.121 + if (ko != null) {
135.122 + ko.valueHasMutated(propName);
135.123 + }
135.124 + }
135.125 +
135.126 + /** Initializes the associated model in the current {@link #getContext() context}.
135.127 + * In case of <em>knockout.js</em> technology, applies given bindings
135.128 + * of the current model to the <em>body</em> element of the page.
135.129 + */
135.130 + public void applyBindings() {
135.131 + initBindings().applyBindings();
135.132 + }
135.133 +
135.134 + /** Invokes the provided runnable in the {@link #getContext() context}
135.135 + * of the browser. If the caller is already on the right thread, the
135.136 + * <code>run.run()</code> is invoked immediately and synchronously.
135.137 + * Otherwise the method returns immediately and the <code>run()</code>
135.138 + * method is performed later
135.139 + *
135.140 + * @param run the action to execute
135.141 + */
135.142 + public void runInBrowser(Runnable run) {
135.143 + JSON.runInBrowser(context, run);
135.144 + }
135.145 +
135.146 + /** Initializes the provided collection with a content of the <code>array</code>.
135.147 + * The initialization can only be done soon after the the collection
135.148 + * is created, otherwise an exception is throw
135.149 + *
135.150 + * @param to the collection to initialize (assumed to be empty)
135.151 + * @param array the array to add to the collection
135.152 + * @throws IllegalStateException if the system has already been initialized
135.153 + */
135.154 + public void initTo(Collection<?> to, Object array) {
135.155 + if (ko != null) {
135.156 + throw new IllegalStateException();
135.157 + }
135.158 + if (to instanceof JSONList) {
135.159 + ((JSONList)to).init(array);
135.160 + } else {
135.161 + JSONList.init(to, array);
135.162 + }
135.163 + }
135.164 +
135.165 + /** Takes an object representing JSON result and extract some of its
135.166 + * properties. It is assumed that the <code>props</code> and
135.167 + * <code>values</code> arrays have the same length.
135.168 + *
135.169 + * @param json the JSON object (actual type depends on the associated
135.170 + * {@link Technology})
135.171 + * @param props list of properties to extract
135.172 + * @param values array that will be filled with extracted values
135.173 + */
135.174 + public void extract(Object json, String[] props, Object[] values) {
135.175 + JSON.extract(context, json, props, values);
135.176 + }
135.177 +
135.178 + /** Converts raw JSON <code>data</code> into a Java {@link Model} class.
135.179 + *
135.180 + * @param <T> type of the model class
135.181 + * @param modelClass the type of the class to create
135.182 + * @param data the raw JSON data
135.183 + * @return newly created instance of the model class
135.184 + */
135.185 + public <T> T read(Class<T> modelClass, Object data) {
135.186 + return JSON.read(context, modelClass, data);
135.187 + }
135.188 +
135.189 + /** Initializes asynchronous JSON connection to specified URL. The
135.190 + * method returns immediately and later does callback later.
135.191 + *
135.192 + * @param index the callback index to be used when a reply is received
135.193 + * to call {@link Type#onMessage(java.lang.Object, int, int, java.lang.Object)}.
135.194 + *
135.195 + * @param urlBefore the part of the URL before JSON-P callback parameter
135.196 + * @param urlAfter the rest of the URL or <code>null</code> if no JSON-P is used
135.197 + * @param method method to use for connection to the server
135.198 + * @param data string, number or a {@link Model} generated class to send to
135.199 + * the server when doing a query
135.200 + */
135.201 + public void loadJSON(final int index,
135.202 + String urlBefore, String urlAfter, String method,
135.203 + final Object data
135.204 + ) {
135.205 + class Rcvr extends RcvrJSON {
135.206 + @Override
135.207 + protected void onMessage(MsgEvnt msg) {
135.208 + type.onMessage(obj, index, 1, msg.getValues());
135.209 + }
135.210 +
135.211 + @Override
135.212 + protected void onError(MsgEvnt msg) {
135.213 + type.onMessage(obj, index, 2, msg.getException());
135.214 + }
135.215 + }
135.216 + JSON.loadJSON(context, new Rcvr(), urlBefore, urlAfter, method, data);
135.217 + }
135.218 +
135.219 + /** Opens new WebSocket connection to the specified URL.
135.220 + *
135.221 + * @param index the index to use later during callbacks to
135.222 + * {@link Type#onMessage(java.lang.Object, int, int, java.lang.Object)}
135.223 + * @param url the <code>ws://</code> or <code>wss://</code> URL to connect to
135.224 + * @param data data to send to server (usually <code>null</code>)
135.225 + * @return returns a non-null object representing the socket
135.226 + * which can be used when calling {@link #wsSend(java.lang.Object, java.lang.String, java.lang.Object) }
135.227 + */
135.228 + public Object wsOpen(final int index, String url, Object data) {
135.229 + class WSrcvr extends RcvrJSON {
135.230 + @Override
135.231 + protected void onError(MsgEvnt msg) {
135.232 + type.onMessage(obj, index, 2, msg.getException());
135.233 + }
135.234 +
135.235 + @Override
135.236 + protected void onMessage(MsgEvnt msg) {
135.237 + type.onMessage(obj, index, 1, msg.getValues());
135.238 + }
135.239 +
135.240 + @Override
135.241 + protected void onClose(MsgEvnt msg) {
135.242 + type.onMessage(obj, index, 3, null);
135.243 + }
135.244 +
135.245 + @Override
135.246 + protected void onOpen(MsgEvnt msg) {
135.247 + type.onMessage(obj, index, 0, null);
135.248 + }
135.249 + }
135.250 + return JSON.openWS(context, new WSrcvr(), url, data);
135.251 + }
135.252 +
135.253 + /** Sends a message to existing socket.
135.254 + *
135.255 + * @param webSocket the socket to send message to
135.256 + * @param url the <code>ws://</code> or <code>wss://</code> URL to connect to,
135.257 + * preferably the same as the one used when the socket was
135.258 + * {@link #wsOpen(int, java.lang.String, java.lang.Object) opened}
135.259 + * @param data the data to send or <code>null</code> if the socket is
135.260 + * supposed to be closed
135.261 + */
135.262 + public void wsSend(Object webSocket, String url, Object data) {
135.263 + ((JSON.WS)webSocket).send(context, url, data);
135.264 + }
135.265 +
135.266 + /** Converts raw data (one of its properties) to string representation.
135.267 + *
135.268 + * @param data the object
135.269 + * @param propName the name of object property or <code>null</code>
135.270 + * if the whole object should be converted
135.271 + * @return the string representation of the object or its property
135.272 + */
135.273 + public String toString(Object data, String propName) {
135.274 + return JSON.toString(context, data, propName);
135.275 + }
135.276 +
135.277 + /** Converts raw data (one of its properties) to a number representation.
135.278 + *
135.279 + * @param data the object
135.280 + * @param propName the name of object property or <code>null</code>
135.281 + * if the whole object should be converted
135.282 + * @return the number representation of the object or its property
135.283 + */
135.284 + public Number toNumber(Object data, String propName) {
135.285 + return JSON.toNumber(context, data, propName);
135.286 + }
135.287 +
135.288 + /** Converts raw JSON data into a {@link Model} class representation.
135.289 + *
135.290 + * @param <T> type of the model to create
135.291 + * @param type class of the model to create
135.292 + * @param data raw JSON data (depends on associated {@link Technology})
135.293 + * @return new instances of the model class filled with values from the
135.294 + * <code>data</code> object
135.295 + */
135.296 + public <T> T toModel(Class<T> type, Object data) {
135.297 + return JSON.toModel(context, type, data, null);
135.298 + }
135.299 +
135.300 + /** Creates new JSON like observable list.
135.301 + *
135.302 + * @param <T> the type of the list elements
135.303 + * @param propName name of a property this list is associated with
135.304 + * @param onChange index of the property to use when the list is modified
135.305 + * during callback to {@link Type#onChange(java.lang.Object, int)}
135.306 + * @param dependingProps the array of {@link ComputedProperty derived properties}
135.307 + * that depend on the value of the list
135.308 + * @return new, empty list associated with this proto-object and its model
135.309 + */
135.310 + public <T> List<T> createList(String propName, int onChange, String... dependingProps) {
135.311 + return new JSONList<T>(this, propName, onChange, dependingProps);
135.312 + }
135.313 +
135.314 + /** Copies content of one collection to another, re-assigning all its
135.315 + * elements from their current context to the new <code>ctx</code>.
135.316 + *
135.317 + * @param <T> type of the collections
135.318 + * @param to the target collection to be filled with cloned values
135.319 + * @param ctx context for the new collection
135.320 + * @param from original collection with its data
135.321 + */
135.322 + public <T> void cloneList(Collection<T> to, BrwsrCtx ctx, Collection<T> from) {
135.323 + Boolean isModel = null;
135.324 + for (T t : from) {
135.325 + if (isModel == null) {
135.326 + isModel = JSON.isModel(t.getClass());
135.327 + }
135.328 + if (isModel) {
135.329 + to.add(JSON.bindTo(t, ctx));
135.330 + } else {
135.331 + to.add(t);
135.332 + }
135.333 + }
135.334 + }
135.335 +
135.336 + //
135.337 + // internal state
135.338 + //
135.339 +
135.340 +
135.341 + final Bindings initBindings() {
135.342 + if (ko == null) {
135.343 + Bindings b = Bindings.apply(context, obj);
135.344 + PropertyBinding[] pb = new PropertyBinding[type.propertyNames.length];
135.345 + for (int i = 0; i < pb.length; i++) {
135.346 + pb[i] = b.registerProperty(
135.347 + type.propertyNames[i], i, obj, type, type.propertyReadOnly[i]
135.348 + );
135.349 + }
135.350 + FunctionBinding[] fb = new FunctionBinding[type.functions.length];
135.351 + for (int i = 0; i < fb.length; i++) {
135.352 + fb[i] = FunctionBinding.registerFunction(
135.353 + type.functions[i], i, obj, type
135.354 + );
135.355 + }
135.356 + ko = b;
135.357 + b.finish(obj, pb, fb);
135.358 + }
135.359 + return ko;
135.360 + }
135.361 +
135.362 + final Bindings getBindings() {
135.363 + return ko;
135.364 + }
135.365 +
135.366 + final void onChange(int index) {
135.367 + type.onChange(obj, index);
135.368 + }
135.369 +
135.370 + /** Functionality used by the code generated by annotation
135.371 + * processor for the {@link net.java.html.json.Model} annotation.
135.372 + *
135.373 + * @param <Model> the generated class
135.374 + * @since 0.7
135.375 + */
135.376 + public static abstract class Type<Model> {
135.377 + private final Class<Model> clazz;
135.378 + private final String[] propertyNames;
135.379 + private final boolean[] propertyReadOnly;
135.380 + private final String[] functions;
135.381 +
135.382 + /** Constructor for subclasses generated by the annotation processor
135.383 + * associated with {@link net.java.html.json.Model} annotation.
135.384 + *
135.385 + * @param clazz the generated model class
135.386 + * @param modelFor the original class annotated by the {@link net.java.html.json.Model} annotation.
135.387 + * @param properties number of properties the class has
135.388 + * @param functions number of functions the class has
135.389 + */
135.390 + protected Type(
135.391 + Class<Model> clazz, Class<?> modelFor, int properties, int functions
135.392 + ) {
135.393 + assert getClass().getName().endsWith("$Html4JavaType");
135.394 + try {
135.395 + assert getClass().getDeclaringClass() == clazz;
135.396 + } catch (SecurityException ex) {
135.397 + // OK, no check
135.398 + }
135.399 + this.clazz = clazz;
135.400 + this.propertyNames = new String[properties];
135.401 + this.propertyReadOnly = new boolean[properties];
135.402 + this.functions = new String[functions];
135.403 + JSON.register(clazz, this);
135.404 + }
135.405 +
135.406 + /** Registers property for the type. It is expected each index
135.407 + * is initialized only once.
135.408 + *
135.409 + * @param name name of the property
135.410 + * @param index index of the property
135.411 + * @param readOnly is the property read only?
135.412 + */
135.413 + protected final void registerProperty(String name, int index, boolean readOnly) {
135.414 + assert propertyNames[index] == null;
135.415 + propertyNames[index] = name;
135.416 + propertyReadOnly[index] = readOnly;
135.417 + }
135.418 +
135.419 + /** Registers function of given name at given index.
135.420 + *
135.421 + * @param name name of the function
135.422 + * @param index name of the type
135.423 + */
135.424 + protected final void registerFunction(String name, int index) {
135.425 + assert functions[index] == null;
135.426 + functions[index] = name;
135.427 + }
135.428 +
135.429 + /** Creates new proto-object for given {@link Model} class bound to
135.430 + * provided context.
135.431 + *
135.432 + * @param obj instance of appropriate {@link Model} class
135.433 + * @param context the browser context
135.434 + * @return new proto-object that the generated class can use for
135.435 + * communication with the infrastructure
135.436 + */
135.437 + public Proto createProto(Object obj, BrwsrCtx context) {
135.438 + return new Proto(obj, this, context);
135.439 + }
135.440 +
135.441 + //
135.442 + // Implemented by subclasses
135.443 + //
135.444 +
135.445 + /** Sets value of a {@link #registerProperty(java.lang.String, int, boolean) registered property}
135.446 + * to new value.
135.447 + *
135.448 + * @param model the instance of {@link Model model class}
135.449 + * @param index index of the property used during registration
135.450 + * @param value the value to set the property to
135.451 + */
135.452 + protected abstract void setValue(Model model, int index, Object value);
135.453 +
135.454 + /** Obtains and returns value of a
135.455 + * {@link #registerProperty(java.lang.String, int, boolean) registered property}.
135.456 + *
135.457 + * @param model the instance of {@link Model model class}
135.458 + * @param index index of the property used during registration
135.459 + * @return current value of the property
135.460 + */
135.461 + protected abstract Object getValue(Model model, int index);
135.462 +
135.463 + /** Invokes a {@link #registerFunction(java.lang.String, int)} registered function
135.464 + * on given object.
135.465 + *
135.466 + * @param model the instance of {@link Model model class}
135.467 + * @param index index of the property used during registration
135.468 + * @param data the currently selected object the function is about to operate on
135.469 + * @param event the event that triggered the event
135.470 + */
135.471 + protected abstract void call(Model model, int index, Object data, Object event);
135.472 +
135.473 + /** Re-binds the model object to new browser context.
135.474 + *
135.475 + * @param model the instance of {@link Model model class}
135.476 + * @param ctx browser context to clone the object to
135.477 + * @return new instance of the model suitable for new context
135.478 + */
135.479 + protected abstract Model cloneTo(Model model, BrwsrCtx ctx);
135.480 +
135.481 + /** Reads raw JSON data and converts them to our model class.
135.482 + *
135.483 + * @param c the browser context to work in
135.484 + * @param json raw JSON data to get values from
135.485 + * @return new instance of model class filled by the data
135.486 + */
135.487 + protected abstract Model read(BrwsrCtx c, Object json);
135.488 +
135.489 + /** Called when a {@link #registerProperty(java.lang.String, int, boolean) registered property}
135.490 + * changes its value.
135.491 + *
135.492 + * @param model the object that has the property
135.493 + * @param index the index of the property during registration
135.494 + */
135.495 + protected abstract void onChange(Model model, int index);
135.496 +
135.497 + /** Finds out if there is an associated proto-object for given
135.498 + * object.
135.499 + *
135.500 + * @param object an object, presumably (but not necessarily) instance of Model class
135.501 + * @return associated proto-object or <code>null</code>
135.502 + */
135.503 + protected abstract Proto protoFor(Object object);
135.504 +
135.505 + /** Called to report results of asynchronous over-the-wire
135.506 + * communication. Result of calling {@link Proto#wsOpen(int, java.lang.String, java.lang.Object)}
135.507 + * or {@link Proto#loadJSON(int, java.lang.String, java.lang.String, java.lang.String, java.lang.Object)}.
135.508 + *
135.509 + * @param model the instance of the model class
135.510 + * @param index index used during initiating the communication (via <code>loadJSON</code> or <code>wsOpen</code> calls)
135.511 + * @param type type of the message: 0 - onOpen, 1 - onMessage, 2 - onError, 3 - onClose -
135.512 + * not all messages are applicable to all communication protocols (JSON has only 1 and 2).
135.513 + * @param data <code>null</code> or string, number or a {@link Model} class
135.514 + * obtained to the server as a response
135.515 + */
135.516 + protected abstract void onMessage(Model model, int index, int type, Object data);
135.517 +
135.518 + //
135.519 + // Various support methods the generated classes use
135.520 + //
135.521 +
135.522 + /** Converts and array of raw JSON objects into an array of typed
135.523 + * Java {@lin Model} classes.
135.524 + *
135.525 + * @param <T> the type of the destination array
135.526 + * @param context browser context to use
135.527 + * @param src array of raw JSON objects
135.528 + * @param destType type of the individual array elements
135.529 + * @param dest array to be filled with read type instances
135.530 + */
135.531 + public <T> void copyJSON(BrwsrCtx context, Object[] src, Class<T> destType, T[] dest) {
135.532 + for (int i = 0; i < src.length && i < dest.length; i++) {
135.533 + dest[i] = org.netbeans.html.json.impl.JSON.read(context, destType, src[i]);
135.534 + }
135.535 + }
135.536 +
135.537 + /** Compares two objects that can be converted to integers.
135.538 + * @return true if they are the same
135.539 + */
135.540 + public final boolean isSame(int a, int b) {
135.541 + return a == b;
135.542 + }
135.543 +
135.544 + /** Compares two objects that can be converted to (floating point)
135.545 + * numbers.
135.546 + * @return true if they are the same
135.547 + */
135.548 + public final boolean isSame(double a, double b) {
135.549 + return a == b;
135.550 + }
135.551 +
135.552 + /** Compares two objects for being the same - e.g. either <code>==</code>
135.553 + * or <code>equals</code>.
135.554 + * @return true if they are equals
135.555 + */
135.556 + public final boolean isSame(Object a, Object b) {
135.557 + if (a == b) {
135.558 + return true;
135.559 + }
135.560 + if (a == null || b == null) {
135.561 + return false;
135.562 + }
135.563 + return a.equals(b);
135.564 + }
135.565 +
135.566 + /** Cumulative hash function. Adds hashcode of the object to the
135.567 + * previous value.
135.568 + * @param o the object (or <code>null</code>)
135.569 + * @param h the previous value of the hash
135.570 + * @return new hash - the old one xor the object's one
135.571 + */
135.572 + public final int hashPlus(Object o, int h) {
135.573 + return o == null ? h : h ^ o.hashCode();
135.574 + }
135.575 +
135.576 + /** Converts an object to its JSON value.
135.577 + *
135.578 + * @param obj the object to convert
135.579 + * @return JSON representation of the object
135.580 + */
135.581 + public final String toJSON(Object obj) {
135.582 + return JSON.toJSON(obj);
135.583 + }
135.584 +
135.585 + /** Converts the value to string.
135.586 + *
135.587 + * @param val the value
135.588 + * @return the converted value
135.589 + */
135.590 + public final String stringValue(Object val) {
135.591 + return JSON.stringValue(val);
135.592 + }
135.593 +
135.594 + /** Converts the value to number.
135.595 + *
135.596 + * @param val the value
135.597 + * @return the converted value
135.598 + */
135.599 + public final Number numberValue(Object val) {
135.600 + return JSON.numberValue(val);
135.601 + }
135.602 +
135.603 + /** Converts the value to character.
135.604 + *
135.605 + * @param val the value
135.606 + * @return the converted value
135.607 + */
135.608 + public final Character charValue(Object val) {
135.609 + return JSON.charValue(val);
135.610 + }
135.611 +
135.612 + /** Converts the value to boolean.
135.613 + *
135.614 + * @param val the value
135.615 + * @return the converted value
135.616 + */
135.617 + public final Boolean boolValue(Object val) {
135.618 + return JSON.boolValue(val);
135.619 + }
135.620 +
135.621 + /** Extracts value of specific type from given object.
135.622 + *
135.623 + * @param <T> the type of object one is interested in
135.624 + * @param type the type
135.625 + * @param val the object to convert to type
135.626 + * @return the converted value
135.627 + */
135.628 + public final <T> T extractValue(Class<T> type, Object val) {
135.629 + if (Number.class.isAssignableFrom(type)) {
135.630 + val = numberValue(val);
135.631 + }
135.632 + if (Boolean.class == type) {
135.633 + val = boolValue(val);
135.634 + }
135.635 + if (String.class == type) {
135.636 + val = stringValue(val);
135.637 + }
135.638 + if (Character.class == type) {
135.639 + val = charValue(val);
135.640 + }
135.641 + if (Integer.class == type) {
135.642 + val = val instanceof Number ? ((Number) val).intValue() : 0;
135.643 + }
135.644 + if (Long.class == type) {
135.645 + val = val instanceof Number ? ((Number) val).longValue() : 0;
135.646 + }
135.647 + if (Short.class == type) {
135.648 + val = val instanceof Number ? ((Number) val).shortValue() : 0;
135.649 + }
135.650 + if (Byte.class == type) {
135.651 + val = val instanceof Number ? ((Number) val).byteValue() : 0;
135.652 + }
135.653 + if (Double.class == type) {
135.654 + val = val instanceof Number ? ((Number) val).doubleValue() : Double.NaN;
135.655 + }
135.656 + if (Float.class == type) {
135.657 + val = val instanceof Number ? ((Number) val).floatValue() : Float.NaN;
135.658 + }
135.659 + return type.cast(val);
135.660 + }
135.661 +
135.662 + }
135.663 +}
136.1 --- a/json/src/main/java/org/apidesign/html/json/spi/Technology.java Thu Dec 19 17:11:01 2013 +0100
136.2 +++ b/json/src/main/java/org/apidesign/html/json/spi/Technology.java Tue Jan 07 08:21:57 2014 +0100
136.3 @@ -1,22 +1,44 @@
136.4 /**
136.5 - * HTML via Java(tm) Language Bindings
136.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
136.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
136.8 *
136.9 - * This program is free software: you can redistribute it and/or modify
136.10 - * it under the terms of the GNU General Public License as published by
136.11 - * the Free Software Foundation, version 2 of the License.
136.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
136.13 *
136.14 - * This program is distributed in the hope that it will be useful,
136.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
136.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
136.17 - * GNU General Public License for more details. apidesign.org
136.18 - * designates this particular file as subject to the
136.19 - * "Classpath" exception as provided by apidesign.org
136.20 - * in the License file that accompanied this code.
136.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
136.22 + * Other names may be trademarks of their respective owners.
136.23 *
136.24 - * You should have received a copy of the GNU General Public License
136.25 - * along with this program. Look for COPYING file in the top folder.
136.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
136.27 + * The contents of this file are subject to the terms of either the GNU
136.28 + * General Public License Version 2 only ("GPL") or the Common
136.29 + * Development and Distribution License("CDDL") (collectively, the
136.30 + * "License"). You may not use this file except in compliance with the
136.31 + * License. You can obtain a copy of the License at
136.32 + * http://www.netbeans.org/cddl-gplv2.html
136.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
136.34 + * specific language governing permissions and limitations under the
136.35 + * License. When distributing the software, include this License Header
136.36 + * Notice in each file and include the License file at
136.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
136.38 + * particular file as subject to the "Classpath" exception as provided
136.39 + * by Oracle in the GPL Version 2 section of the License file that
136.40 + * accompanied this code. If applicable, add the following below the
136.41 + * License Header, with the fields enclosed by brackets [] replaced by
136.42 + * your own identifying information:
136.43 + * "Portions Copyrighted [year] [name of copyright owner]"
136.44 + *
136.45 + * Contributor(s):
136.46 + *
136.47 + * The Original Software is NetBeans. The Initial Developer of the Original
136.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
136.49 + *
136.50 + * If you wish your version of this file to be governed by only the CDDL
136.51 + * or only the GPL Version 2, indicate your decision by adding
136.52 + * "[Contributor] elects to include this software in this distribution
136.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
136.54 + * single choice of license, a recipient has the option to distribute
136.55 + * your version of this file under either the CDDL, the GPL Version 2 or
136.56 + * to extend the choice of license to its licensees as provided above.
136.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
136.58 + * Version 2 license, then the option applies only if the new code is
136.59 + * made subject to such option by the copyright holder.
136.60 */
136.61 package org.apidesign.html.json.spi;
136.62
137.1 --- a/json/src/main/java/org/apidesign/html/json/spi/Transfer.java Thu Dec 19 17:11:01 2013 +0100
137.2 +++ b/json/src/main/java/org/apidesign/html/json/spi/Transfer.java Tue Jan 07 08:21:57 2014 +0100
137.3 @@ -1,24 +1,45 @@
137.4 /**
137.5 - * HTML via Java(tm) Language Bindings
137.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
137.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
137.8 *
137.9 - * This program is free software: you can redistribute it and/or modify
137.10 - * it under the terms of the GNU General Public License as published by
137.11 - * the Free Software Foundation, version 2 of the License.
137.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
137.13 *
137.14 - * This program is distributed in the hope that it will be useful,
137.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
137.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
137.17 - * GNU General Public License for more details. apidesign.org
137.18 - * designates this particular file as subject to the
137.19 - * "Classpath" exception as provided by apidesign.org
137.20 - * in the License file that accompanied this code.
137.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
137.22 + * Other names may be trademarks of their respective owners.
137.23 *
137.24 - * You should have received a copy of the GNU General Public License
137.25 - * along with this program. Look for COPYING file in the top folder.
137.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
137.27 + * The contents of this file are subject to the terms of either the GNU
137.28 + * General Public License Version 2 only ("GPL") or the Common
137.29 + * Development and Distribution License("CDDL") (collectively, the
137.30 + * "License"). You may not use this file except in compliance with the
137.31 + * License. You can obtain a copy of the License at
137.32 + * http://www.netbeans.org/cddl-gplv2.html
137.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
137.34 + * specific language governing permissions and limitations under the
137.35 + * License. When distributing the software, include this License Header
137.36 + * Notice in each file and include the License file at
137.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
137.38 + * particular file as subject to the "Classpath" exception as provided
137.39 + * by Oracle in the GPL Version 2 section of the License file that
137.40 + * accompanied this code. If applicable, add the following below the
137.41 + * License Header, with the fields enclosed by brackets [] replaced by
137.42 + * your own identifying information:
137.43 + * "Portions Copyrighted [year] [name of copyright owner]"
137.44 + *
137.45 + * Contributor(s):
137.46 + *
137.47 + * The Original Software is NetBeans. The Initial Developer of the Original
137.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
137.49 + *
137.50 + * If you wish your version of this file to be governed by only the CDDL
137.51 + * or only the GPL Version 2, indicate your decision by adding
137.52 + * "[Contributor] elects to include this software in this distribution
137.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
137.54 + * single choice of license, a recipient has the option to distribute
137.55 + * your version of this file under either the CDDL, the GPL Version 2 or
137.56 + * to extend the choice of license to its licensees as provided above.
137.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
137.58 + * Version 2 license, then the option applies only if the new code is
137.59 + * made subject to such option by the copyright holder.
137.60 */
137.61 -
137.62 package org.apidesign.html.json.spi;
137.63
137.64 import java.io.IOException;
138.1 --- a/json/src/main/java/org/apidesign/html/json/spi/WSTransfer.java Thu Dec 19 17:11:01 2013 +0100
138.2 +++ b/json/src/main/java/org/apidesign/html/json/spi/WSTransfer.java Tue Jan 07 08:21:57 2014 +0100
138.3 @@ -1,22 +1,44 @@
138.4 /**
138.5 - * HTML via Java(tm) Language Bindings
138.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
138.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
138.8 *
138.9 - * This program is free software: you can redistribute it and/or modify
138.10 - * it under the terms of the GNU General Public License as published by
138.11 - * the Free Software Foundation, version 2 of the License.
138.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
138.13 *
138.14 - * This program is distributed in the hope that it will be useful,
138.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
138.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
138.17 - * GNU General Public License for more details. apidesign.org
138.18 - * designates this particular file as subject to the
138.19 - * "Classpath" exception as provided by apidesign.org
138.20 - * in the License file that accompanied this code.
138.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
138.22 + * Other names may be trademarks of their respective owners.
138.23 *
138.24 - * You should have received a copy of the GNU General Public License
138.25 - * along with this program. Look for COPYING file in the top folder.
138.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
138.27 + * The contents of this file are subject to the terms of either the GNU
138.28 + * General Public License Version 2 only ("GPL") or the Common
138.29 + * Development and Distribution License("CDDL") (collectively, the
138.30 + * "License"). You may not use this file except in compliance with the
138.31 + * License. You can obtain a copy of the License at
138.32 + * http://www.netbeans.org/cddl-gplv2.html
138.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
138.34 + * specific language governing permissions and limitations under the
138.35 + * License. When distributing the software, include this License Header
138.36 + * Notice in each file and include the License file at
138.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
138.38 + * particular file as subject to the "Classpath" exception as provided
138.39 + * by Oracle in the GPL Version 2 section of the License file that
138.40 + * accompanied this code. If applicable, add the following below the
138.41 + * License Header, with the fields enclosed by brackets [] replaced by
138.42 + * your own identifying information:
138.43 + * "Portions Copyrighted [year] [name of copyright owner]"
138.44 + *
138.45 + * Contributor(s):
138.46 + *
138.47 + * The Original Software is NetBeans. The Initial Developer of the Original
138.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
138.49 + *
138.50 + * If you wish your version of this file to be governed by only the CDDL
138.51 + * or only the GPL Version 2, indicate your decision by adding
138.52 + * "[Contributor] elects to include this software in this distribution
138.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
138.54 + * single choice of license, a recipient has the option to distribute
138.55 + * your version of this file under either the CDDL, the GPL Version 2 or
138.56 + * to extend the choice of license to its licensees as provided above.
138.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
138.58 + * Version 2 license, then the option applies only if the new code is
138.59 + * made subject to such option by the copyright holder.
138.60 */
138.61 package org.apidesign.html.json.spi;
138.62
139.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
139.2 +++ b/json/src/main/java/org/apidesign/html/json/spi/package.html Tue Jan 07 08:21:57 2014 +0100
139.3 @@ -0,0 +1,51 @@
139.4 +<!--
139.5 +
139.6 + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
139.7 +
139.8 + Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
139.9 +
139.10 + Oracle and Java are registered trademarks of Oracle and/or its affiliates.
139.11 + Other names may be trademarks of their respective owners.
139.12 +
139.13 + The contents of this file are subject to the terms of either the GNU
139.14 + General Public License Version 2 only ("GPL") or the Common
139.15 + Development and Distribution License("CDDL") (collectively, the
139.16 + "License"). You may not use this file except in compliance with the
139.17 + License. You can obtain a copy of the License at
139.18 + http://www.netbeans.org/cddl-gplv2.html
139.19 + or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
139.20 + specific language governing permissions and limitations under the
139.21 + License. When distributing the software, include this License Header
139.22 + Notice in each file and include the License file at
139.23 + nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
139.24 + particular file as subject to the "Classpath" exception as provided
139.25 + by Oracle in the GPL Version 2 section of the License file that
139.26 + accompanied this code. If applicable, add the following below the
139.27 + License Header, with the fields enclosed by brackets [] replaced by
139.28 + your own identifying information:
139.29 + "Portions Copyrighted [year] [name of copyright owner]"
139.30 +
139.31 + Contributor(s):
139.32 +
139.33 + The Original Software is NetBeans. The Initial Developer of the Original
139.34 + Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
139.35 +
139.36 + If you wish your version of this file to be governed by only the CDDL
139.37 + or only the GPL Version 2, indicate your decision by adding
139.38 + "[Contributor] elects to include this software in this distribution
139.39 + under the [CDDL or GPL Version 2] license." If you do not indicate a
139.40 + single choice of license, a recipient has the option to distribute
139.41 + your version of this file under either the CDDL, the GPL Version 2 or
139.42 + to extend the choice of license to its licensees as provided above.
139.43 + However, if you add GPL Version 2 code and therefore, elected the GPL
139.44 + Version 2 license, then the option applies only if the new code is
139.45 + made subject to such option by the copyright holder.
139.46 +
139.47 +-->
139.48 +<html>
139.49 + <body>
139.50 + <div>Service Provider Interfaces for those who wish to integrate own
139.51 + <a href="Technology.html">technology</a> with the HTML for Java API.
139.52 + </div>
139.53 + </body>
139.54 +</html>
140.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
140.2 +++ b/json/src/main/java/org/netbeans/html/json/impl/Bindings.java Tue Jan 07 08:21:57 2014 +0100
140.3 @@ -0,0 +1,108 @@
140.4 +/**
140.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
140.6 + *
140.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
140.8 + *
140.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
140.10 + * Other names may be trademarks of their respective owners.
140.11 + *
140.12 + * The contents of this file are subject to the terms of either the GNU
140.13 + * General Public License Version 2 only ("GPL") or the Common
140.14 + * Development and Distribution License("CDDL") (collectively, the
140.15 + * "License"). You may not use this file except in compliance with the
140.16 + * License. You can obtain a copy of the License at
140.17 + * http://www.netbeans.org/cddl-gplv2.html
140.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
140.19 + * specific language governing permissions and limitations under the
140.20 + * License. When distributing the software, include this License Header
140.21 + * Notice in each file and include the License file at
140.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
140.23 + * particular file as subject to the "Classpath" exception as provided
140.24 + * by Oracle in the GPL Version 2 section of the License file that
140.25 + * accompanied this code. If applicable, add the following below the
140.26 + * License Header, with the fields enclosed by brackets [] replaced by
140.27 + * your own identifying information:
140.28 + * "Portions Copyrighted [year] [name of copyright owner]"
140.29 + *
140.30 + * Contributor(s):
140.31 + *
140.32 + * The Original Software is NetBeans. The Initial Developer of the Original
140.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
140.34 + *
140.35 + * If you wish your version of this file to be governed by only the CDDL
140.36 + * or only the GPL Version 2, indicate your decision by adding
140.37 + * "[Contributor] elects to include this software in this distribution
140.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
140.39 + * single choice of license, a recipient has the option to distribute
140.40 + * your version of this file under either the CDDL, the GPL Version 2 or
140.41 + * to extend the choice of license to its licensees as provided above.
140.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
140.43 + * Version 2 license, then the option applies only if the new code is
140.44 + * made subject to such option by the copyright holder.
140.45 + */
140.46 +package org.netbeans.html.json.impl;
140.47 +
140.48 +import net.java.html.BrwsrCtx;
140.49 +import org.apidesign.html.json.spi.FunctionBinding;
140.50 +import org.apidesign.html.json.spi.PropertyBinding;
140.51 +import org.apidesign.html.json.spi.Proto;
140.52 +import org.apidesign.html.json.spi.Technology;
140.53 +
140.54 +/**
140.55 + *
140.56 + * @author Jaroslav Tulach <jtulach@netbeans.org>
140.57 + */
140.58 +public final class Bindings<Data> {
140.59 + private Data data;
140.60 + private final Technology<Data> bp;
140.61 +
140.62 + private Bindings(Technology<Data> bp) {
140.63 + this.bp = bp;
140.64 + }
140.65 +
140.66 + public <M> PropertyBinding registerProperty(String propName, int index, M model, Proto.Type<M> access, boolean readOnly) {
140.67 + return PropertyBindingAccessor.create(access, this, propName, index, model, readOnly);
140.68 + }
140.69 +
140.70 + public static Bindings<?> apply(BrwsrCtx c, Object model) {
140.71 + Technology<?> bp = JSON.findTechnology(c);
140.72 + return apply(bp);
140.73 + }
140.74 +
140.75 + private static <Data> Bindings<Data> apply(Technology<Data> bp) {
140.76 + return new Bindings<Data>(bp);
140.77 + }
140.78 +
140.79 + public final void finish(Object model, PropertyBinding[] propArr, FunctionBinding[] funcArr) {
140.80 + assert data == null;
140.81 + if (bp instanceof Technology.BatchInit) {
140.82 + Technology.BatchInit<Data> bi = (Technology.BatchInit<Data>)bp;
140.83 + data = bi.wrapModel(model, propArr, funcArr);
140.84 + } else {
140.85 + data = bp.wrapModel(model);
140.86 + for (PropertyBinding b : propArr) {
140.87 + bp.bind(b, model, data);
140.88 + }
140.89 + for (FunctionBinding b : funcArr) {
140.90 + bp.expose(b, model, data);
140.91 + }
140.92 + }
140.93 + }
140.94 +
140.95 +
140.96 + public Data koData() {
140.97 + return data;
140.98 + }
140.99 +
140.100 + public void valueHasMutated(String firstName) {
140.101 + bp.valueHasMutated(data, firstName);
140.102 + }
140.103 +
140.104 + public void applyBindings() {
140.105 + bp.applyBindings(data);
140.106 + }
140.107 +
140.108 + Object wrapArray(Object[] arr) {
140.109 + return bp.wrapArray(arr);
140.110 + }
140.111 +}
141.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
141.2 +++ b/json/src/main/java/org/netbeans/html/json/impl/JSON.java Tue Jan 07 08:21:57 2014 +0100
141.3 @@ -0,0 +1,501 @@
141.4 +/**
141.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
141.6 + *
141.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
141.8 + *
141.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
141.10 + * Other names may be trademarks of their respective owners.
141.11 + *
141.12 + * The contents of this file are subject to the terms of either the GNU
141.13 + * General Public License Version 2 only ("GPL") or the Common
141.14 + * Development and Distribution License("CDDL") (collectively, the
141.15 + * "License"). You may not use this file except in compliance with the
141.16 + * License. You can obtain a copy of the License at
141.17 + * http://www.netbeans.org/cddl-gplv2.html
141.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
141.19 + * specific language governing permissions and limitations under the
141.20 + * License. When distributing the software, include this License Header
141.21 + * Notice in each file and include the License file at
141.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
141.23 + * particular file as subject to the "Classpath" exception as provided
141.24 + * by Oracle in the GPL Version 2 section of the License file that
141.25 + * accompanied this code. If applicable, add the following below the
141.26 + * License Header, with the fields enclosed by brackets [] replaced by
141.27 + * your own identifying information:
141.28 + * "Portions Copyrighted [year] [name of copyright owner]"
141.29 + *
141.30 + * Contributor(s):
141.31 + *
141.32 + * The Original Software is NetBeans. The Initial Developer of the Original
141.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
141.34 + *
141.35 + * If you wish your version of this file to be governed by only the CDDL
141.36 + * or only the GPL Version 2, indicate your decision by adding
141.37 + * "[Contributor] elects to include this software in this distribution
141.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
141.39 + * single choice of license, a recipient has the option to distribute
141.40 + * your version of this file under either the CDDL, the GPL Version 2 or
141.41 + * to extend the choice of license to its licensees as provided above.
141.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
141.43 + * Version 2 license, then the option applies only if the new code is
141.44 + * made subject to such option by the copyright holder.
141.45 + */
141.46 +package org.netbeans.html.json.impl;
141.47 +
141.48 +import java.io.IOException;
141.49 +import java.io.InputStream;
141.50 +import java.util.Collection;
141.51 +import java.util.HashMap;
141.52 +import java.util.Map;
141.53 +import net.java.html.BrwsrCtx;
141.54 +import org.apidesign.html.context.spi.Contexts;
141.55 +import org.apidesign.html.json.spi.FunctionBinding;
141.56 +import org.apidesign.html.json.spi.JSONCall;
141.57 +import org.apidesign.html.json.spi.PropertyBinding;
141.58 +import org.apidesign.html.json.spi.Proto;
141.59 +import org.apidesign.html.json.spi.Technology;
141.60 +import org.apidesign.html.json.spi.Transfer;
141.61 +import org.apidesign.html.json.spi.WSTransfer;
141.62 +
141.63 +/**
141.64 + *
141.65 + * @author Jaroslav Tulach <jtulach@netbeans.org>
141.66 + */
141.67 +public final class JSON {
141.68 + private JSON() {
141.69 + }
141.70 +
141.71 + static Technology<?> findTechnology(BrwsrCtx c) {
141.72 + Technology<?> t = Contexts.find(c, Technology.class);
141.73 + return t == null ? EmptyTech.EMPTY : t;
141.74 + }
141.75 +
141.76 + static Transfer findTransfer(BrwsrCtx c) {
141.77 + Transfer t = Contexts.find(c, Transfer.class);
141.78 + return t == null ? EmptyTech.EMPTY : t;
141.79 + }
141.80 +
141.81 + static WSTransfer<?> findWSTransfer(BrwsrCtx c) {
141.82 + WSTransfer<?> t = Contexts.find(c, WSTransfer.class);
141.83 + return t == null ? EmptyTech.EMPTY : t;
141.84 + }
141.85 +
141.86 + public static void runInBrowser(BrwsrCtx c, Runnable runnable) {
141.87 + findTechnology(c).runSafe(runnable);
141.88 + }
141.89 +
141.90 + public static void extract(BrwsrCtx c, Object value, String[] props, Object[] values) {
141.91 + Transfer t = findTransfer(c);
141.92 + t.extract(value, props, values);
141.93 + }
141.94 +
141.95 + private static Object getProperty(BrwsrCtx c, Object obj, String prop) {
141.96 + if (prop == null) return obj;
141.97 +
141.98 + String[] arr = { prop };
141.99 + Object[] val = { null };
141.100 + extract(c, obj, arr, val);
141.101 + return val[0];
141.102 + }
141.103 +
141.104 + public static String toJSON(Object value) {
141.105 + if (value == null) {
141.106 + return "null";
141.107 + }
141.108 + if (value instanceof Enum) {
141.109 + value = value.toString();
141.110 + }
141.111 + if (value instanceof String) {
141.112 + String s = (String)value;
141.113 + int len = s.length();
141.114 + StringBuilder sb = new StringBuilder(len + 10);
141.115 + sb.append('"');
141.116 + for (int i = 0; i < len; i++) {
141.117 + char ch = s.charAt(i);
141.118 + switch (ch) {
141.119 + case '\"': sb.append("\\\""); break;
141.120 + case '\n': sb.append("\\n"); break;
141.121 + case '\r': sb.append("\\r"); break;
141.122 + case '\t': sb.append("\\t"); break;
141.123 + case '\\': sb.append("\\\\"); break;
141.124 + default: sb.append(ch);
141.125 + }
141.126 + }
141.127 + sb.append('"');
141.128 + return sb.toString();
141.129 + }
141.130 + return value.toString();
141.131 + }
141.132 +
141.133 + public static String toString(BrwsrCtx c, Object obj, String prop) {
141.134 + obj = getProperty(c, obj, prop);
141.135 + return obj instanceof String ? (String)obj : null;
141.136 + }
141.137 + public static Number toNumber(BrwsrCtx c, Object obj, String prop) {
141.138 + obj = getProperty(c, obj, prop);
141.139 + if (!(obj instanceof Number)) {
141.140 + obj = Double.NaN;
141.141 + }
141.142 + return (Number)obj;
141.143 + }
141.144 + public static <M> M toModel(BrwsrCtx c, Class<M> aClass, Object data, Object object) {
141.145 + Technology<?> t = findTechnology(c);
141.146 + Object o = t.toModel(aClass, data);
141.147 + return aClass.cast(o);
141.148 + }
141.149 +
141.150 + public static boolean isSame(int a, int b) {
141.151 + return a == b;
141.152 + }
141.153 +
141.154 + public static boolean isSame(double a, double b) {
141.155 + return a == b;
141.156 + }
141.157 +
141.158 + public static boolean isSame(Object a, Object b) {
141.159 + if (a == b) {
141.160 + return true;
141.161 + }
141.162 + if (a == null || b == null) {
141.163 + return false;
141.164 + }
141.165 + return a.equals(b);
141.166 + }
141.167 +
141.168 + public static int hashPlus(Object o, int h) {
141.169 + return o == null ? h : h ^ o.hashCode();
141.170 + }
141.171 +
141.172 + public static <T> T extractValue(Class<T> type, Object val) {
141.173 + if (Number.class.isAssignableFrom(type)) {
141.174 + val = numberValue(val);
141.175 + }
141.176 + if (Boolean.class == type) {
141.177 + val = boolValue(val);
141.178 + }
141.179 + if (String.class == type) {
141.180 + val = stringValue(val);
141.181 + }
141.182 + if (Character.class == type) {
141.183 + val = charValue(val);
141.184 + }
141.185 + if (Integer.class == type) {
141.186 + val = val instanceof Number ? ((Number)val).intValue() : 0;
141.187 + }
141.188 + if (Long.class == type) {
141.189 + val = val instanceof Number ? ((Number)val).longValue() : 0;
141.190 + }
141.191 + if (Short.class == type) {
141.192 + val = val instanceof Number ? ((Number)val).shortValue() : 0;
141.193 + }
141.194 + if (Byte.class == type) {
141.195 + val = val instanceof Number ? ((Number)val).byteValue() : 0;
141.196 + }
141.197 + if (Double.class == type) {
141.198 + val = val instanceof Number ? ((Number)val).doubleValue() : Double.NaN;
141.199 + }
141.200 + if (Float.class == type) {
141.201 + val = val instanceof Number ? ((Number)val).floatValue() : Float.NaN;
141.202 + }
141.203 + return type.cast(val);
141.204 + }
141.205 +
141.206 + static boolean isNumeric(Object val) {
141.207 + return ((val instanceof Integer) || (val instanceof Long) || (val instanceof Short) || (val instanceof Byte));
141.208 + }
141.209 +
141.210 + public static String stringValue(Object val) {
141.211 + if (val instanceof Boolean) {
141.212 + return ((Boolean)val ? "true" : "false");
141.213 + }
141.214 + if (isNumeric(val)) {
141.215 + return Long.toString(((Number)val).longValue());
141.216 + }
141.217 + if (val instanceof Float) {
141.218 + return Float.toString((Float)val);
141.219 + }
141.220 + if (val instanceof Double) {
141.221 + return Double.toString((Double)val);
141.222 + }
141.223 + return (String)val;
141.224 + }
141.225 +
141.226 + public static Number numberValue(Object val) {
141.227 + if (val instanceof String) {
141.228 + try {
141.229 + return Double.valueOf((String)val);
141.230 + } catch (NumberFormatException ex) {
141.231 + return Double.NaN;
141.232 + }
141.233 + }
141.234 + if (val instanceof Boolean) {
141.235 + return (Boolean)val ? 1 : 0;
141.236 + }
141.237 + return (Number)val;
141.238 + }
141.239 +
141.240 + public static Character charValue(Object val) {
141.241 + if (val instanceof Number) {
141.242 + return Character.toChars(numberValue(val).intValue())[0];
141.243 + }
141.244 + if (val instanceof Boolean) {
141.245 + return (Boolean)val ? (char)1 : (char)0;
141.246 + }
141.247 + if (val instanceof String) {
141.248 + String s = (String)val;
141.249 + return s.isEmpty() ? (char)0 : s.charAt(0);
141.250 + }
141.251 + return (Character)val;
141.252 + }
141.253 +
141.254 + public static Boolean boolValue(Object val) {
141.255 + if (val instanceof String) {
141.256 + return Boolean.parseBoolean((String)val);
141.257 + }
141.258 + if (val instanceof Number) {
141.259 + return numberValue(val).doubleValue() != 0.0;
141.260 + }
141.261 +
141.262 + return Boolean.TRUE.equals(val);
141.263 + }
141.264 +
141.265 + public static Object find(Object object, Bindings model) {
141.266 + if (object == null) {
141.267 + return null;
141.268 + }
141.269 + if (object instanceof JSONList) {
141.270 + return ((JSONList<?>) object).koData();
141.271 + }
141.272 + if (object instanceof Collection) {
141.273 + return JSONList.koData((Collection<?>) object, model);
141.274 + }
141.275 + Proto.Type<?> type = JSON.findType(object.getClass());
141.276 + if (type == null) {
141.277 + return null;
141.278 + }
141.279 + final Proto proto = PropertyBindingAccessor.protoFor(type, object);
141.280 + if (proto == null) {
141.281 + return null;
141.282 + }
141.283 + final Bindings b = PropertyBindingAccessor.getBindings(proto, true);
141.284 + return b == null ? null : b.koData();
141.285 + }
141.286 +
141.287 + public static Object find(Object object) {
141.288 + return find(object, null);
141.289 + }
141.290 +
141.291 + public static void loadJSON(
141.292 + BrwsrCtx c, RcvrJSON callback,
141.293 + String urlBefore, String urlAfter, String method,
141.294 + Object data
141.295 + ) {
141.296 + JSONCall call = PropertyBindingAccessor.createCall(c, callback, urlBefore, urlAfter, method, data);
141.297 + Transfer t = findTransfer(c);
141.298 + t.loadJSON(call);
141.299 + }
141.300 + public static WS openWS(
141.301 + BrwsrCtx c, RcvrJSON r, String url, Object data
141.302 + ) {
141.303 + WS ws = WSImpl.create(findWSTransfer(c), r);
141.304 + ws.send(c, url, data);
141.305 + return ws;
141.306 + }
141.307 +
141.308 + public static abstract class WS {
141.309 + private WS() {
141.310 + }
141.311 +
141.312 + public abstract void send(BrwsrCtx ctx, String url, Object model);
141.313 + }
141.314 +
141.315 + private static final class WSImpl<Socket> extends WS {
141.316 +
141.317 + private final WSTransfer<Socket> trans;
141.318 + private final RcvrJSON rcvr;
141.319 + private Socket socket;
141.320 + private String prevURL;
141.321 +
141.322 + private WSImpl(WSTransfer<Socket> trans, RcvrJSON rcvr) {
141.323 + this.trans = trans;
141.324 + this.rcvr = rcvr;
141.325 + }
141.326 +
141.327 + static <Socket> WS create(WSTransfer<Socket> t, RcvrJSON r) {
141.328 + return new WSImpl<Socket>(t, r);
141.329 + }
141.330 +
141.331 + @Override
141.332 + public void send(BrwsrCtx ctx, String url, Object data) {
141.333 + Socket s = socket;
141.334 + if (s == null) {
141.335 + if (data != null) {
141.336 + throw new IllegalStateException("WebSocket is not opened yet. Call with null data, was: " + data);
141.337 + }
141.338 + JSONCall call = PropertyBindingAccessor.createCall(ctx, rcvr, url, null, "WebSocket", null);
141.339 + socket = trans.open(url, call);
141.340 + prevURL = url;
141.341 + return;
141.342 + }
141.343 + if (data == null) {
141.344 + trans.close(s);
141.345 + socket = null;
141.346 + return;
141.347 + }
141.348 + if (!prevURL.equals(url)) {
141.349 + throw new IllegalStateException(
141.350 + "Can't call to different URL " + url + " was: " + prevURL + "!"
141.351 + + " Close the socket by calling it will null data first!"
141.352 + );
141.353 + }
141.354 + JSONCall call = PropertyBindingAccessor.createCall(ctx, rcvr, prevURL, null, "WebSocket", data);
141.355 + trans.send(s, call);
141.356 + }
141.357 +
141.358 + }
141.359 +
141.360 + private static final Map<Class,Proto.Type<?>> modelTypes;
141.361 + static {
141.362 + modelTypes = new HashMap<Class, Proto.Type<?>>();
141.363 + }
141.364 + public static void register(Class c, Proto.Type<?> type) {
141.365 + modelTypes.put(c, type);
141.366 + }
141.367 +
141.368 + public static boolean isModel(Class<?> clazz) {
141.369 + return findType(clazz) != null;
141.370 + }
141.371 +
141.372 + static Proto.Type<?> findType(Class<?> clazz) {
141.373 + for (int i = 0; i < 2; i++) {
141.374 + Proto.Type<?> from = modelTypes.get(clazz);
141.375 + if (from == null) {
141.376 + initClass(clazz);
141.377 + } else {
141.378 + return from;
141.379 + }
141.380 + }
141.381 + return null;
141.382 + }
141.383 +
141.384 + public static <Model> Model bindTo(Model model, BrwsrCtx c) {
141.385 + Proto.Type<Model> from = (Proto.Type<Model>) findType(model.getClass());
141.386 + if (from == null) {
141.387 + throw new IllegalArgumentException();
141.388 + }
141.389 + return PropertyBindingAccessor.clone(from, model, c);
141.390 + }
141.391 +
141.392 + public static <T> T readStream(BrwsrCtx c, Class<T> modelClazz, InputStream data)
141.393 + throws IOException {
141.394 + Transfer tr = findTransfer(c);
141.395 + return read(c, modelClazz, tr.toJSON((InputStream)data));
141.396 + }
141.397 + public static <T> T read(BrwsrCtx c, Class<T> modelClazz, Object data) {
141.398 + if (data == null) {
141.399 + return null;
141.400 + }
141.401 + if (modelClazz == String.class) {
141.402 + return modelClazz.cast(data.toString());
141.403 + }
141.404 + for (int i = 0; i < 2; i++) {
141.405 + Proto.Type<?> from = modelTypes.get(modelClazz);
141.406 + if (from == null) {
141.407 + initClass(modelClazz);
141.408 + } else {
141.409 + return modelClazz.cast(PropertyBindingAccessor.readFrom(from, c, data));
141.410 + }
141.411 + }
141.412 + throw new NullPointerException();
141.413 + }
141.414 + static void initClass(Class<?> modelClazz) {
141.415 + try {
141.416 + // try to resolve the class
141.417 + ClassLoader l;
141.418 + try {
141.419 + l = modelClazz.getClassLoader();
141.420 + } catch (SecurityException ex) {
141.421 + l = null;
141.422 + }
141.423 + if (l != null) {
141.424 + Class.forName(modelClazz.getName(), true, l);
141.425 + }
141.426 + modelClazz.newInstance();
141.427 + } catch (Exception ex) {
141.428 + // ignore and try again
141.429 + }
141.430 + }
141.431 +
141.432 + private static final class EmptyTech
141.433 + implements Technology<Object>, Transfer, WSTransfer<Void> {
141.434 + private static final EmptyTech EMPTY = new EmptyTech();
141.435 +
141.436 + @Override
141.437 + public Object wrapModel(Object model) {
141.438 + return model;
141.439 + }
141.440 +
141.441 + @Override
141.442 + public void valueHasMutated(Object data, String propertyName) {
141.443 + }
141.444 +
141.445 + @Override
141.446 + public void bind(PropertyBinding b, Object model, Object data) {
141.447 + }
141.448 +
141.449 + @Override
141.450 + public void expose(FunctionBinding fb, Object model, Object d) {
141.451 + }
141.452 +
141.453 + @Override
141.454 + public void applyBindings(Object data) {
141.455 + }
141.456 +
141.457 + @Override
141.458 + public Object wrapArray(Object[] arr) {
141.459 + return arr;
141.460 + }
141.461 +
141.462 + @Override
141.463 + public void extract(Object obj, String[] props, Object[] values) {
141.464 + for (int i = 0; i < values.length; i++) {
141.465 + values[i] = null;
141.466 + }
141.467 + }
141.468 +
141.469 + @Override
141.470 + public void loadJSON(JSONCall call) {
141.471 + call.notifyError(new UnsupportedOperationException());
141.472 + }
141.473 +
141.474 + @Override
141.475 + public <M> M toModel(Class<M> modelClass, Object data) {
141.476 + return modelClass.cast(data);
141.477 + }
141.478 +
141.479 + @Override
141.480 + public Object toJSON(InputStream is) throws IOException {
141.481 + throw new IOException("Not supported");
141.482 + }
141.483 +
141.484 + @Override
141.485 + public synchronized void runSafe(Runnable r) {
141.486 + r.run();
141.487 + }
141.488 +
141.489 + @Override
141.490 + public Void open(String url, JSONCall onReply) {
141.491 + onReply.notifyError(new UnsupportedOperationException("WebSockets not supported!"));
141.492 + return null;
141.493 + }
141.494 +
141.495 + @Override
141.496 + public void send(Void socket, JSONCall data) {
141.497 + }
141.498 +
141.499 + @Override
141.500 + public void close(Void socket) {
141.501 + }
141.502 + }
141.503 +
141.504 +}
142.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
142.2 +++ b/json/src/main/java/org/netbeans/html/json/impl/JSONList.java Tue Jan 07 08:21:57 2014 +0100
142.3 @@ -0,0 +1,208 @@
142.4 +/**
142.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
142.6 + *
142.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
142.8 + *
142.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
142.10 + * Other names may be trademarks of their respective owners.
142.11 + *
142.12 + * The contents of this file are subject to the terms of either the GNU
142.13 + * General Public License Version 2 only ("GPL") or the Common
142.14 + * Development and Distribution License("CDDL") (collectively, the
142.15 + * "License"). You may not use this file except in compliance with the
142.16 + * License. You can obtain a copy of the License at
142.17 + * http://www.netbeans.org/cddl-gplv2.html
142.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
142.19 + * specific language governing permissions and limitations under the
142.20 + * License. When distributing the software, include this License Header
142.21 + * Notice in each file and include the License file at
142.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
142.23 + * particular file as subject to the "Classpath" exception as provided
142.24 + * by Oracle in the GPL Version 2 section of the License file that
142.25 + * accompanied this code. If applicable, add the following below the
142.26 + * License Header, with the fields enclosed by brackets [] replaced by
142.27 + * your own identifying information:
142.28 + * "Portions Copyrighted [year] [name of copyright owner]"
142.29 + *
142.30 + * Contributor(s):
142.31 + *
142.32 + * The Original Software is NetBeans. The Initial Developer of the Original
142.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
142.34 + *
142.35 + * If you wish your version of this file to be governed by only the CDDL
142.36 + * or only the GPL Version 2, indicate your decision by adding
142.37 + * "[Contributor] elects to include this software in this distribution
142.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
142.39 + * single choice of license, a recipient has the option to distribute
142.40 + * your version of this file under either the CDDL, the GPL Version 2 or
142.41 + * to extend the choice of license to its licensees as provided above.
142.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
142.43 + * Version 2 license, then the option applies only if the new code is
142.44 + * made subject to such option by the copyright holder.
142.45 + */
142.46 +package org.netbeans.html.json.impl;
142.47 +
142.48 +import java.lang.reflect.Array;
142.49 +import java.util.ArrayList;
142.50 +import java.util.Collection;
142.51 +import java.util.Iterator;
142.52 +import org.apidesign.html.json.spi.Proto;
142.53 +
142.54 +/**
142.55 + *
142.56 + * @author Jaroslav Tulach <jtulach@netbeans.org>
142.57 + */
142.58 +public final class JSONList<T> extends ArrayList<T> {
142.59 + private final Proto proto;
142.60 + private final String name;
142.61 + private final String[] deps;
142.62 + private final int index;
142.63 +
142.64 + public JSONList(Proto proto, String name, int changeIndex, String... deps) {
142.65 + this.proto = proto;
142.66 + this.name = name;
142.67 + this.deps = deps;
142.68 + this.index = changeIndex;
142.69 + }
142.70 +
142.71 + public void init(Object values) {
142.72 + int len;
142.73 + if (values == null || (len = Array.getLength(values)) == 0) {
142.74 + return;
142.75 + }
142.76 + for (int i = 0; i < len; i++) {
142.77 + Object data = Array.get(values, i);
142.78 + super.add((T)data);
142.79 + }
142.80 + }
142.81 + public static <T> void init(Collection<T> to, Object values) {
142.82 + int len;
142.83 + if (values == null || (len = Array.getLength(values)) == 0) {
142.84 + return;
142.85 + }
142.86 + for (int i = 0; i < len; i++) {
142.87 + Object data = Array.get(values, i);
142.88 + to.add((T)data);
142.89 + }
142.90 + }
142.91 +
142.92 + @Override
142.93 + public boolean add(T e) {
142.94 + boolean ret = super.add(e);
142.95 + notifyChange();
142.96 + return ret;
142.97 + }
142.98 +
142.99 + @Override
142.100 + public boolean addAll(Collection<? extends T> c) {
142.101 + boolean ret = super.addAll(c);
142.102 + notifyChange();
142.103 + return ret;
142.104 + }
142.105 +
142.106 + @Override
142.107 + public boolean addAll(int index, Collection<? extends T> c) {
142.108 + boolean ret = super.addAll(index, c);
142.109 + notifyChange();
142.110 + return ret;
142.111 + }
142.112 +
142.113 + @Override
142.114 + public boolean remove(Object o) {
142.115 + boolean ret = super.remove(o);
142.116 + notifyChange();
142.117 + return ret;
142.118 + }
142.119 +
142.120 + @Override
142.121 + public void clear() {
142.122 + super.clear();
142.123 + notifyChange();
142.124 + }
142.125 +
142.126 + @Override
142.127 + public boolean removeAll(Collection<?> c) {
142.128 + boolean ret = super.removeAll(c);
142.129 + notifyChange();
142.130 + return ret;
142.131 + }
142.132 +
142.133 + @Override
142.134 + public boolean retainAll(Collection<?> c) {
142.135 + boolean ret = super.retainAll(c);
142.136 + notifyChange();
142.137 + return ret;
142.138 + }
142.139 +
142.140 + @Override
142.141 + public T set(int index, T element) {
142.142 + T ret = super.set(index, element);
142.143 + notifyChange();
142.144 + return ret;
142.145 + }
142.146 +
142.147 + @Override
142.148 + public void add(int index, T element) {
142.149 + super.add(index, element);
142.150 + notifyChange();
142.151 + }
142.152 +
142.153 + @Override
142.154 + public T remove(int index) {
142.155 + T ret = super.remove(index);
142.156 + notifyChange();
142.157 + return ret;
142.158 + }
142.159 +
142.160 + @Override
142.161 + public String toString() {
142.162 + Iterator<T> it = iterator();
142.163 + if (!it.hasNext()) {
142.164 + return "[]";
142.165 + }
142.166 + String sep = "";
142.167 + StringBuilder sb = new StringBuilder();
142.168 + sb.append('[');
142.169 + while (it.hasNext()) {
142.170 + T t = it.next();
142.171 + sb.append(sep);
142.172 + sb.append(JSON.toJSON(t));
142.173 + sep = ",";
142.174 + }
142.175 + sb.append(']');
142.176 + return sb.toString();
142.177 + }
142.178 +
142.179 + private void notifyChange() {
142.180 + Bindings m = PropertyBindingAccessor.getBindings(proto, false);
142.181 + if (m != null) {
142.182 + m.valueHasMutated(name);
142.183 + for (String dependant : deps) {
142.184 + m.valueHasMutated(dependant);
142.185 + }
142.186 + if (index >= 0) {
142.187 + PropertyBindingAccessor.notifyProtoChange(proto, index);
142.188 + }
142.189 + }
142.190 + }
142.191 +
142.192 + @Override
142.193 + public JSONList clone() {
142.194 + throw new UnsupportedOperationException();
142.195 + }
142.196 +
142.197 + static final Object koData(Collection<?> c, Bindings m) {
142.198 + Object[] arr = c.toArray(new Object[c.size()]);
142.199 + for (int i = 0; i < arr.length; i++) {
142.200 + Object r = JSON.find(arr[i], m);
142.201 + if (r != null) {
142.202 + arr[i] = r;
142.203 + }
142.204 + }
142.205 + return m.wrapArray(arr);
142.206 + }
142.207 +
142.208 + final Object koData() {
142.209 + return koData(this, PropertyBindingAccessor.getBindings(proto, true));
142.210 + }
142.211 +}
143.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
143.2 +++ b/json/src/main/java/org/netbeans/html/json/impl/ModelProcessor.java Tue Jan 07 08:21:57 2014 +0100
143.3 @@ -0,0 +1,1778 @@
143.4 +/**
143.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
143.6 + *
143.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
143.8 + *
143.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
143.10 + * Other names may be trademarks of their respective owners.
143.11 + *
143.12 + * The contents of this file are subject to the terms of either the GNU
143.13 + * General Public License Version 2 only ("GPL") or the Common
143.14 + * Development and Distribution License("CDDL") (collectively, the
143.15 + * "License"). You may not use this file except in compliance with the
143.16 + * License. You can obtain a copy of the License at
143.17 + * http://www.netbeans.org/cddl-gplv2.html
143.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
143.19 + * specific language governing permissions and limitations under the
143.20 + * License. When distributing the software, include this License Header
143.21 + * Notice in each file and include the License file at
143.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
143.23 + * particular file as subject to the "Classpath" exception as provided
143.24 + * by Oracle in the GPL Version 2 section of the License file that
143.25 + * accompanied this code. If applicable, add the following below the
143.26 + * License Header, with the fields enclosed by brackets [] replaced by
143.27 + * your own identifying information:
143.28 + * "Portions Copyrighted [year] [name of copyright owner]"
143.29 + *
143.30 + * Contributor(s):
143.31 + *
143.32 + * The Original Software is NetBeans. The Initial Developer of the Original
143.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
143.34 + *
143.35 + * If you wish your version of this file to be governed by only the CDDL
143.36 + * or only the GPL Version 2, indicate your decision by adding
143.37 + * "[Contributor] elects to include this software in this distribution
143.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
143.39 + * single choice of license, a recipient has the option to distribute
143.40 + * your version of this file under either the CDDL, the GPL Version 2 or
143.41 + * to extend the choice of license to its licensees as provided above.
143.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
143.43 + * Version 2 license, then the option applies only if the new code is
143.44 + * made subject to such option by the copyright holder.
143.45 + */
143.46 +package org.netbeans.html.json.impl;
143.47 +
143.48 +import java.io.IOException;
143.49 +import java.io.OutputStreamWriter;
143.50 +import java.io.StringWriter;
143.51 +import java.io.Writer;
143.52 +import java.lang.annotation.AnnotationTypeMismatchException;
143.53 +import java.lang.annotation.IncompleteAnnotationException;
143.54 +import java.lang.reflect.Method;
143.55 +import java.util.ArrayList;
143.56 +import java.util.Arrays;
143.57 +import java.util.Collection;
143.58 +import java.util.Collections;
143.59 +import java.util.HashMap;
143.60 +import java.util.HashSet;
143.61 +import java.util.LinkedHashSet;
143.62 +import java.util.List;
143.63 +import java.util.Map;
143.64 +import java.util.ResourceBundle;
143.65 +import java.util.Set;
143.66 +import java.util.WeakHashMap;
143.67 +import java.util.logging.Level;
143.68 +import java.util.logging.Logger;
143.69 +import javax.annotation.processing.AbstractProcessor;
143.70 +import javax.annotation.processing.Completion;
143.71 +import javax.annotation.processing.Completions;
143.72 +import javax.annotation.processing.ProcessingEnvironment;
143.73 +import javax.annotation.processing.Processor;
143.74 +import javax.annotation.processing.RoundEnvironment;
143.75 +import javax.annotation.processing.SupportedAnnotationTypes;
143.76 +import javax.annotation.processing.SupportedSourceVersion;
143.77 +import javax.lang.model.SourceVersion;
143.78 +import javax.lang.model.element.AnnotationMirror;
143.79 +import javax.lang.model.element.AnnotationValue;
143.80 +import javax.lang.model.element.Element;
143.81 +import javax.lang.model.element.ElementKind;
143.82 +import javax.lang.model.element.ExecutableElement;
143.83 +import javax.lang.model.element.Modifier;
143.84 +import javax.lang.model.element.PackageElement;
143.85 +import javax.lang.model.element.TypeElement;
143.86 +import javax.lang.model.element.VariableElement;
143.87 +import javax.lang.model.type.ArrayType;
143.88 +import javax.lang.model.type.DeclaredType;
143.89 +import javax.lang.model.type.MirroredTypeException;
143.90 +import javax.lang.model.type.TypeKind;
143.91 +import javax.lang.model.type.TypeMirror;
143.92 +import javax.lang.model.util.Elements;
143.93 +import javax.lang.model.util.Types;
143.94 +import javax.tools.Diagnostic;
143.95 +import javax.tools.FileObject;
143.96 +import net.java.html.json.ComputedProperty;
143.97 +import net.java.html.json.Model;
143.98 +import net.java.html.json.Function;
143.99 +import net.java.html.json.ModelOperation;
143.100 +import net.java.html.json.OnPropertyChange;
143.101 +import net.java.html.json.OnReceive;
143.102 +import net.java.html.json.Property;
143.103 +import org.openide.util.lookup.ServiceProvider;
143.104 +
143.105 +/** Annotation processor to process {@link Model @Model} annotations and
143.106 + * generate appropriate model classes.
143.107 + *
143.108 + * @author Jaroslav Tulach <jtulach@netbeans.org>
143.109 + */
143.110 +@ServiceProvider(service=Processor.class)
143.111 +@SupportedSourceVersion(SourceVersion.RELEASE_6)
143.112 +@SupportedAnnotationTypes({
143.113 + "net.java.html.json.Model",
143.114 + "net.java.html.json.ModelOperation",
143.115 + "net.java.html.json.Function",
143.116 + "net.java.html.json.OnReceive",
143.117 + "net.java.html.json.OnPropertyChange",
143.118 + "net.java.html.json.ComputedProperty",
143.119 + "net.java.html.json.Property"
143.120 +})
143.121 +public final class ModelProcessor extends AbstractProcessor {
143.122 + private static final Logger LOG = Logger.getLogger(ModelProcessor.class.getName());
143.123 + private final Map<Element,String> models = new WeakHashMap<Element,String>();
143.124 + private final Map<Element,Prprt[]> verify = new WeakHashMap<Element,Prprt[]>();
143.125 + @Override
143.126 + public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
143.127 + boolean ok = true;
143.128 + for (Element e : roundEnv.getElementsAnnotatedWith(Model.class)) {
143.129 + if (!processModel(e)) {
143.130 + ok = false;
143.131 + }
143.132 + }
143.133 + if (roundEnv.processingOver()) {
143.134 + models.clear();
143.135 + for (Map.Entry<Element, Prprt[]> entry : verify.entrySet()) {
143.136 + TypeElement te = (TypeElement)entry.getKey();
143.137 + String fqn = processingEnv.getElementUtils().getBinaryName(te).toString();
143.138 + Element finalElem = processingEnv.getElementUtils().getTypeElement(fqn);
143.139 + if (finalElem == null) {
143.140 + continue;
143.141 + }
143.142 + Prprt[] props;
143.143 + Model m = finalElem.getAnnotation(Model.class);
143.144 + if (m == null) {
143.145 + continue;
143.146 + }
143.147 + props = Prprt.wrap(processingEnv, finalElem, m.properties());
143.148 + for (Prprt p : props) {
143.149 + boolean[] isModel = { false };
143.150 + boolean[] isEnum = { false };
143.151 + boolean[] isPrimitive = { false };
143.152 + String t = checkType(p, isModel, isEnum, isPrimitive);
143.153 + if (isEnum[0]) {
143.154 + continue;
143.155 + }
143.156 + if (isPrimitive[0]) {
143.157 + continue;
143.158 + }
143.159 + if (isModel[0]) {
143.160 + continue;
143.161 + }
143.162 + if ("java.lang.String".equals(t)) {
143.163 + continue;
143.164 + }
143.165 + error("The type " + t + " should be defined by @Model annotation", entry.getKey());
143.166 + }
143.167 + }
143.168 + verify.clear();
143.169 + }
143.170 + return ok;
143.171 + }
143.172 +
143.173 + private void error(String msg, Element e) {
143.174 + processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, msg, e);
143.175 + }
143.176 +
143.177 + private boolean processModel(Element e) {
143.178 + boolean ok = true;
143.179 + Model m = e.getAnnotation(Model.class);
143.180 + if (m == null) {
143.181 + return true;
143.182 + }
143.183 + String pkg = findPkgName(e);
143.184 + Writer w;
143.185 + String className = m.className();
143.186 + models.put(e, className);
143.187 + try {
143.188 + StringWriter body = new StringWriter();
143.189 + StringBuilder onReceiveType = new StringBuilder();
143.190 + List<String> propsGetSet = new ArrayList<String>();
143.191 + List<String> functions = new ArrayList<String>();
143.192 + Map<String, Collection<String>> propsDeps = new HashMap<String, Collection<String>>();
143.193 + Map<String, Collection<String>> functionDeps = new HashMap<String, Collection<String>>();
143.194 + Prprt[] props = createProps(e, m.properties());
143.195 +
143.196 + if (!generateComputedProperties(body, props, e.getEnclosedElements(), propsGetSet, propsDeps)) {
143.197 + ok = false;
143.198 + }
143.199 + if (!generateOnChange(e, propsDeps, props, className, functionDeps)) {
143.200 + ok = false;
143.201 + }
143.202 + if (!generateProperties(e, body, className, props, propsGetSet, propsDeps, functionDeps)) {
143.203 + ok = false;
143.204 + }
143.205 + if (!generateFunctions(e, body, className, e.getEnclosedElements(), functions)) {
143.206 + ok = false;
143.207 + }
143.208 + if (!generateReceive(e, body, className, e.getEnclosedElements(), onReceiveType)) {
143.209 + ok = false;
143.210 + }
143.211 + if (!generateOperation(e, body, className, e.getEnclosedElements())) {
143.212 + ok = false;
143.213 + }
143.214 + FileObject java = processingEnv.getFiler().createSourceFile(pkg + '.' + className, e);
143.215 + w = new OutputStreamWriter(java.openOutputStream());
143.216 + try {
143.217 + w.append("package " + pkg + ";\n");
143.218 + w.append("import net.java.html.json.*;\n");
143.219 + w.append("public final class ").append(className).append(" implements Cloneable {\n");
143.220 + w.append(" private static final Html4JavaType TYPE = new Html4JavaType();\n");
143.221 + w.append(" private final org.apidesign.html.json.spi.Proto proto;\n");
143.222 + w.append(body.toString());
143.223 + w.append(" private static Class<" + inPckName(e) + "> modelFor() { return null; }\n");
143.224 + w.append(" private ").append(className).append("(net.java.html.BrwsrCtx context) {\n");
143.225 + w.append(" this.proto = TYPE.createProto(this, context);\n");
143.226 + for (Prprt p : props) {
143.227 + if (p.array()) {
143.228 + final String tn = typeName(e, p);
143.229 + String[] gs = toGetSet(p.name(), tn, p.array());
143.230 + w.write(" this.prop_" + p.name() + " = proto.createList(\""
143.231 + + p.name() + "\"");
143.232 + if (functionDeps.containsKey(p.name())) {
143.233 + int index = Arrays.asList(functionDeps.keySet().toArray()).indexOf(p.name());
143.234 + w.write(", " + index);
143.235 + } else {
143.236 + w.write(", -1");
143.237 + }
143.238 + Collection<String> dependants = propsDeps.get(p.name());
143.239 + if (dependants != null) {
143.240 + for (String depProp : dependants) {
143.241 + w.write(", ");
143.242 + w.write('\"');
143.243 + w.write(depProp);
143.244 + w.write('\"');
143.245 + }
143.246 + }
143.247 + w.write(")");
143.248 + w.write(";\n");
143.249 + }
143.250 + }
143.251 + w.append(" };\n");
143.252 + w.append(" public ").append(className).append("() {\n");
143.253 + w.append(" this(net.java.html.BrwsrCtx.findDefault(").append(className).append(".class));\n");
143.254 + for (Prprt p : props) {
143.255 + if (!p.array()) {
143.256 + boolean[] isModel = {false};
143.257 + boolean[] isEnum = {false};
143.258 + boolean isPrimitive[] = {false};
143.259 + String tn = checkType(p, isModel, isEnum, isPrimitive);
143.260 + if (isModel[0]) {
143.261 + w.write(" prop_" + p.name() + " = new " + tn + "();\n");
143.262 + }
143.263 + }
143.264 + }
143.265 + w.append(" };\n");
143.266 + if (props.length > 0) {
143.267 + w.append(" public ").append(className).append("(");
143.268 + Prprt firstArray = null;
143.269 + String sep = "";
143.270 + for (Prprt p : props) {
143.271 + if (p.array()) {
143.272 + if (firstArray == null) {
143.273 + firstArray = p;
143.274 + }
143.275 + continue;
143.276 + }
143.277 + String tn = typeName(e, p);
143.278 + w.write(sep);
143.279 + w.write(tn);
143.280 + w.write(" " + p.name());
143.281 + sep = ", ";
143.282 + }
143.283 + if (firstArray != null) {
143.284 + String tn;
143.285 + boolean[] isModel = {false};
143.286 + boolean[] isEnum = {false};
143.287 + boolean isPrimitive[] = {false};
143.288 + tn = checkType(firstArray, isModel, isEnum, isPrimitive);
143.289 + w.write(sep);
143.290 + w.write(tn);
143.291 + w.write("... " + firstArray.name());
143.292 + }
143.293 + w.append(") {\n");
143.294 + w.append(" this(net.java.html.BrwsrCtx.findDefault(").append(className).append(".class));\n");
143.295 + for (Prprt p : props) {
143.296 + if (p.array()) {
143.297 + continue;
143.298 + }
143.299 + w.write(" this.prop_" + p.name() + " = " + p.name() + ";\n");
143.300 + }
143.301 + if (firstArray != null) {
143.302 + w.write(" proto.initTo(this.prop_" + firstArray.name() + ", " + firstArray.name() + ");\n");
143.303 + }
143.304 + w.append(" };\n");
143.305 + }
143.306 + w.append(" private static class Html4JavaType extends org.apidesign.html.json.spi.Proto.Type<").append(className).append("> {\n");
143.307 + w.append(" private Html4JavaType() {\n super(").append(className).append(".class, ").
143.308 + append(inPckName(e)).append(".class, " + (propsGetSet.size() / 5) + ", "
143.309 + + (functions.size() / 2) + ");\n");
143.310 + {
143.311 + for (int i = 0; i < propsGetSet.size(); i += 5) {
143.312 + w.append(" registerProperty(\"").append(propsGetSet.get(i)).append("\", ");
143.313 + w.append((i / 5) + ", " + (propsGetSet.get(i + 2) == null) + ");\n");
143.314 + }
143.315 + }
143.316 + {
143.317 + for (int i = 0; i < functions.size(); i += 2) {
143.318 + w.append(" registerFunction(\"").append(functions.get(i)).append("\", ");
143.319 + w.append((i / 2) + ");\n");
143.320 + }
143.321 + }
143.322 + w.append(" }\n");
143.323 + w.append(" @Override public void setValue(" + className + " data, int type, Object value) {\n");
143.324 + w.append(" switch (type) {\n");
143.325 + for (int i = 0; i < propsGetSet.size(); i += 5) {
143.326 + final String set = propsGetSet.get(i + 2);
143.327 + String tn = propsGetSet.get(i + 4);
143.328 + String btn = findBoxedType(tn);
143.329 + if (btn != null) {
143.330 + tn = btn;
143.331 + }
143.332 + if (set != null) {
143.333 + w.append(" case " + (i / 5) + ": data." + strip(set) + "(TYPE.extractValue(" + tn + ".class, value)); return;\n");
143.334 + }
143.335 + }
143.336 + w.append(" }\n");
143.337 + w.append(" }\n");
143.338 + w.append(" @Override public Object getValue(" + className + " data, int type) {\n");
143.339 + w.append(" switch (type) {\n");
143.340 + for (int i = 0; i < propsGetSet.size(); i += 5) {
143.341 + final String get = propsGetSet.get(i + 1);
143.342 + if (get != null) {
143.343 + w.append(" case " + (i / 5) + ": return data." + strip(get) + "();\n");
143.344 + }
143.345 + }
143.346 + w.append(" }\n");
143.347 + w.append(" throw new UnsupportedOperationException();\n");
143.348 + w.append(" }\n");
143.349 + w.append(" @Override public void call(" + className + " model, int type, Object data, Object ev) {\n");
143.350 + w.append(" switch (type) {\n");
143.351 + for (int i = 0; i < functions.size(); i += 2) {
143.352 + final String name = functions.get(i);
143.353 + w.append(" case " + (i / 2) + ": model." + name + "(data, ev); return;\n");
143.354 + }
143.355 + w.append(" }\n");
143.356 + w.append(" throw new UnsupportedOperationException();\n");
143.357 + w.append(" }\n");
143.358 + w.append(" @Override public org.apidesign.html.json.spi.Proto protoFor(Object obj) {\n");
143.359 + w.append(" return ((" + className + ")obj).proto;");
143.360 + w.append(" }\n");
143.361 + w.append(" @Override public void onChange(" + className + " model, int type) {\n");
143.362 + w.append(" switch (type) {\n");
143.363 + {
143.364 + String[] arr = functionDeps.keySet().toArray(new String[0]);
143.365 + for (int i = 0; i < arr.length; i++) {
143.366 + Collection<String> onChange = functionDeps.get(arr[i]);
143.367 + if (onChange != null) {
143.368 + w.append(" case " + i + ":\n");
143.369 + for (String call : onChange) {
143.370 + w.append(" ").append(call).append("\n");
143.371 + }
143.372 + w.write(" return;\n");
143.373 + }
143.374 + }
143.375 + }
143.376 + w.append(" }\n");
143.377 + w.append(" throw new UnsupportedOperationException();\n");
143.378 + w.append(" }\n");
143.379 + w.append(onReceiveType);
143.380 + w.append(" @Override public " + className + " read(net.java.html.BrwsrCtx c, Object json) { return new " + className + "(c, json); }\n");
143.381 + w.append(" @Override public " + className + " cloneTo(" + className + " o, net.java.html.BrwsrCtx c) { return o.clone(c); }\n");
143.382 + w.append(" }\n");
143.383 + w.append(" private ").append(className).append("(net.java.html.BrwsrCtx c, Object json) {\n");
143.384 + w.append(" this(c);\n");
143.385 + int values = 0;
143.386 + for (int i = 0; i < propsGetSet.size(); i += 5) {
143.387 + Prprt p = findPrprt(props, propsGetSet.get(i));
143.388 + if (p == null) {
143.389 + continue;
143.390 + }
143.391 + values++;
143.392 + }
143.393 + w.append(" Object[] ret = new Object[" + values + "];\n");
143.394 + w.append(" proto.extract(json, new String[] {\n");
143.395 + for (int i = 0; i < propsGetSet.size(); i += 5) {
143.396 + Prprt p = findPrprt(props, propsGetSet.get(i));
143.397 + if (p == null) {
143.398 + continue;
143.399 + }
143.400 + w.append(" \"").append(propsGetSet.get(i)).append("\",\n");
143.401 + }
143.402 + w.append(" }, ret);\n");
143.403 + for (int i = 0, cnt = 0, prop = 0; i < propsGetSet.size(); i += 5) {
143.404 + final String pn = propsGetSet.get(i);
143.405 + Prprt p = findPrprt(props, pn);
143.406 + if (p == null) {
143.407 + continue;
143.408 + }
143.409 + boolean[] isModel = { false };
143.410 + boolean[] isEnum = { false };
143.411 + boolean isPrimitive[] = { false };
143.412 + String type = checkType(props[prop++], isModel, isEnum, isPrimitive);
143.413 + if (p.array()) {
143.414 + w.append(" if (ret[" + cnt + "] instanceof Object[]) {\n");
143.415 + w.append(" for (Object e : ((Object[])ret[" + cnt + "])) {\n");
143.416 + if (isModel[0]) {
143.417 + w.append(" this.prop_").append(pn).append(".add(proto.read");
143.418 + w.append("(" + type + ".class, e));\n");
143.419 + } else if (isEnum[0]) {
143.420 + w.append(" this.prop_").append(pn);
143.421 + w.append(".add(e == null ? null : ");
143.422 + w.append(type).append(".valueOf(TYPE.stringValue(e)));\n");
143.423 + } else {
143.424 + if (isPrimitive(type)) {
143.425 + w.append(" this.prop_").append(pn).append(".add(TYPE.numberValue(e).");
143.426 + w.append(type).append("Value());\n");
143.427 + } else {
143.428 + w.append(" this.prop_").append(pn).append(".add((");
143.429 + w.append(type).append(")e);\n");
143.430 + }
143.431 + }
143.432 + w.append(" }\n");
143.433 + w.append(" }\n");
143.434 + } else {
143.435 + if (isEnum[0]) {
143.436 + w.append(" try {\n");
143.437 + w.append(" this.prop_").append(pn);
143.438 + w.append(" = ret[" + cnt + "] == null ? null : ");
143.439 + w.append(type).append(".valueOf(TYPE.stringValue(ret[" + cnt + "]));\n");
143.440 + w.append(" } catch (IllegalArgumentException ex) {\n");
143.441 + w.append(" ex.printStackTrace();\n");
143.442 + w.append(" }\n");
143.443 + } else if (isPrimitive(type)) {
143.444 + w.append(" this.prop_").append(pn);
143.445 + w.append(" = ret[" + cnt + "] == null ? ");
143.446 + if ("char".equals(type)) {
143.447 + w.append("0 : (TYPE.charValue(");
143.448 + } else if ("boolean".equals(type)) {
143.449 + w.append("false : (TYPE.boolValue(");
143.450 + } else {
143.451 + w.append("0 : (TYPE.numberValue(");
143.452 + }
143.453 + w.append("ret[" + cnt + "])).");
143.454 + w.append(type).append("Value();\n");
143.455 + } else if (isModel[0]) {
143.456 + w.append(" this.prop_").append(pn).append(" = proto.read");
143.457 + w.append("(" + type + ".class, ");
143.458 + w.append("ret[" + cnt + "]);\n");
143.459 + }else {
143.460 + w.append(" this.prop_").append(pn);
143.461 + w.append(" = (").append(type).append(')');
143.462 + w.append("ret[" + cnt + "];\n");
143.463 + }
143.464 + }
143.465 + cnt++;
143.466 + }
143.467 + w.append(" }\n");
143.468 + writeToString(props, w);
143.469 + writeClone(className, props, w);
143.470 + w.write(" /** Activates this model instance in the current {@link \n"
143.471 + + "net.java.html.json.Models#bind(java.lang.Object, net.java.html.BrwsrCtx) browser context}. \n"
143.472 + + "In case of using Knockout technology, this means to \n"
143.473 + + "bind JSON like data in this model instance with Knockout tags in \n"
143.474 + + "the surrounding HTML page.\n"
143.475 + + "*/\n"
143.476 + );
143.477 + w.write(" public " + className + " applyBindings() {\n");
143.478 + w.write(" proto.applyBindings();\n");
143.479 + w.write(" return this;\n");
143.480 + w.write(" }\n");
143.481 + w.write(" public boolean equals(Object o) {\n");
143.482 + w.write(" if (o == this) return true;\n");
143.483 + w.write(" if (!(o instanceof " + className + ")) return false;\n");
143.484 + w.write(" " + className + " p = (" + className + ")o;\n");
143.485 + for (Prprt p : props) {
143.486 + w.write(" if (!TYPE.isSame(prop_" + p.name() + ", p.prop_" + p.name() + ")) return false;\n");
143.487 + }
143.488 + w.write(" return true;\n");
143.489 + w.write(" }\n");
143.490 + w.write(" public int hashCode() {\n");
143.491 + w.write(" int h = " + className + ".class.getName().hashCode();\n");
143.492 + for (Prprt p : props) {
143.493 + w.write(" h = TYPE.hashPlus(prop_" + p.name() + ", h);\n");
143.494 + }
143.495 + w.write(" return h;\n");
143.496 + w.write(" }\n");
143.497 + w.write("}\n");
143.498 + } finally {
143.499 + w.close();
143.500 + }
143.501 + } catch (IOException ex) {
143.502 + error("Can't create " + className + ".java", e);
143.503 + return false;
143.504 + }
143.505 + return ok;
143.506 + }
143.507 +
143.508 + private boolean generateProperties(
143.509 + Element where,
143.510 + Writer w, String className, Prprt[] properties,
143.511 + Collection<String> props,
143.512 + Map<String,Collection<String>> deps,
143.513 + Map<String,Collection<String>> functionDeps
143.514 + ) throws IOException {
143.515 + boolean ok = true;
143.516 + for (Prprt p : properties) {
143.517 + final String tn;
143.518 + tn = typeName(where, p);
143.519 + String[] gs = toGetSet(p.name(), tn, p.array());
143.520 + String castTo;
143.521 +
143.522 + if (p.array()) {
143.523 + w.write(" private final java.util.List<" + tn + "> prop_" + p.name() + ";\n");
143.524 +
143.525 + castTo = "java.util.List";
143.526 + w.write(" public java.util.List<" + tn + "> " + gs[0] + "() {\n");
143.527 + w.write(" proto.verifyUnlocked();\n");
143.528 + w.write(" return prop_" + p.name() + ";\n");
143.529 + w.write(" }\n");
143.530 + } else {
143.531 + castTo = tn;
143.532 + w.write(" private " + tn + " prop_" + p.name() + ";\n");
143.533 + w.write(" public " + tn + " " + gs[0] + "() {\n");
143.534 + w.write(" proto.verifyUnlocked();\n");
143.535 + w.write(" return prop_" + p.name() + ";\n");
143.536 + w.write(" }\n");
143.537 + w.write(" public void " + gs[1] + "(" + tn + " v) {\n");
143.538 + w.write(" proto.verifyUnlocked();\n");
143.539 + w.write(" if (TYPE.isSame(prop_" + p.name() + ", v)) return;\n");
143.540 + w.write(" prop_" + p.name() + " = v;\n");
143.541 + w.write(" proto.valueHasMutated(\"" + p.name() + "\");\n");
143.542 + Collection<String> dependants = deps.get(p.name());
143.543 + if (dependants != null) {
143.544 + for (String depProp : dependants) {
143.545 + w.write(" proto.valueHasMutated(\"" + depProp + "\");\n");
143.546 + }
143.547 + }
143.548 + dependants = functionDeps.get(p.name());
143.549 + if (dependants != null) {
143.550 + w.append(className).append(" model = ").append(className).append(".this;\n");
143.551 + for (String call : dependants) {
143.552 + w.append(" ").append(call);
143.553 + }
143.554 + }
143.555 + w.write(" }\n");
143.556 + }
143.557 +
143.558 + props.add(p.name());
143.559 + props.add(gs[2]);
143.560 + props.add(gs[3]);
143.561 + props.add(gs[0]);
143.562 + props.add(castTo);
143.563 + }
143.564 + return ok;
143.565 + }
143.566 +
143.567 + private boolean generateComputedProperties(
143.568 + Writer w, Prprt[] fixedProps,
143.569 + Collection<? extends Element> arr, Collection<String> props,
143.570 + Map<String,Collection<String>> deps
143.571 + ) throws IOException {
143.572 + boolean ok = true;
143.573 + for (Element e : arr) {
143.574 + if (e.getKind() != ElementKind.METHOD) {
143.575 + continue;
143.576 + }
143.577 + if (e.getAnnotation(ComputedProperty.class) == null) {
143.578 + continue;
143.579 + }
143.580 + if (!e.getModifiers().contains(Modifier.STATIC)) {
143.581 + error("Method " + e.getSimpleName() + " has to be static when annotated by @ComputedProperty", e);
143.582 + ok = false;
143.583 + continue;
143.584 + }
143.585 + ExecutableElement ee = (ExecutableElement)e;
143.586 + final TypeMirror rt = ee.getReturnType();
143.587 + final Types tu = processingEnv.getTypeUtils();
143.588 + TypeMirror ert = tu.erasure(rt);
143.589 + String tn = fqn(ert, ee);
143.590 + boolean array = false;
143.591 + final TypeMirror toCheck;
143.592 + if (tn.equals("java.util.List")) {
143.593 + array = true;
143.594 + toCheck = ((DeclaredType)rt).getTypeArguments().get(0);
143.595 + } else {
143.596 + toCheck = rt;
143.597 + }
143.598 +
143.599 + final String sn = ee.getSimpleName().toString();
143.600 +
143.601 + if (toCheck.getKind().isPrimitive()) {
143.602 + // OK
143.603 + } else {
143.604 + TypeMirror stringType = processingEnv.getElementUtils().getTypeElement("java.lang.String").asType();
143.605 + TypeMirror enumType = processingEnv.getElementUtils().getTypeElement("java.lang.Enum").asType();
143.606 +
143.607 + if (tu.isSubtype(toCheck, stringType)) {
143.608 + // OK
143.609 + } else if (tu.isSubtype(tu.erasure(toCheck), tu.erasure(enumType))) {
143.610 + // OK
143.611 + } else if (isModel(toCheck)) {
143.612 + // OK
143.613 + } else {
143.614 + ok = false;
143.615 + error(sn + " cannot return " + toCheck, e);
143.616 + }
143.617 + }
143.618 +
143.619 + String[] gs = toGetSet(sn, tn, array);
143.620 +
143.621 + w.write(" public " + tn + " " + gs[0] + "() {\n");
143.622 + int arg = 0;
143.623 + for (VariableElement pe : ee.getParameters()) {
143.624 + final String dn = pe.getSimpleName().toString();
143.625 +
143.626 + if (!verifyPropName(pe, dn, fixedProps)) {
143.627 + ok = false;
143.628 + }
143.629 +
143.630 + final String dt = fqn(pe.asType(), ee);
143.631 + String[] call = toGetSet(dn, dt, false);
143.632 + w.write(" " + dt + " arg" + (++arg) + " = ");
143.633 + w.write(call[0] + "();\n");
143.634 +
143.635 + Collection<String> depends = deps.get(dn);
143.636 + if (depends == null) {
143.637 + depends = new LinkedHashSet<String>();
143.638 + deps.put(dn, depends);
143.639 + }
143.640 + depends.add(sn);
143.641 + }
143.642 + w.write(" try {\n");
143.643 + w.write(" proto.acquireLock();\n");
143.644 + w.write(" return " + fqn(ee.getEnclosingElement().asType(), ee) + '.' + e.getSimpleName() + "(");
143.645 + String sep = "";
143.646 + for (int i = 1; i <= arg; i++) {
143.647 + w.write(sep);
143.648 + w.write("arg" + i);
143.649 + sep = ", ";
143.650 + }
143.651 + w.write(");\n");
143.652 + w.write(" } finally {\n");
143.653 + w.write(" proto.releaseLock();\n");
143.654 + w.write(" }\n");
143.655 + w.write(" }\n");
143.656 +
143.657 + props.add(e.getSimpleName().toString());
143.658 + props.add(gs[2]);
143.659 + props.add(null);
143.660 + props.add(gs[0]);
143.661 + props.add(tn);
143.662 + }
143.663 +
143.664 + return ok;
143.665 + }
143.666 +
143.667 + private static String[] toGetSet(String name, String type, boolean array) {
143.668 + String n = Character.toUpperCase(name.charAt(0)) + name.substring(1);
143.669 + String bck2brwsrType = "L" + type.replace('.', '_') + "_2";
143.670 + if ("int".equals(type)) {
143.671 + bck2brwsrType = "I";
143.672 + }
143.673 + if ("double".equals(type)) {
143.674 + bck2brwsrType = "D";
143.675 + }
143.676 + String pref = "get";
143.677 + if ("boolean".equals(type)) {
143.678 + pref = "is";
143.679 + bck2brwsrType = "Z";
143.680 + }
143.681 + final String nu = n.replace('.', '_');
143.682 + if (array) {
143.683 + return new String[] {
143.684 + "get" + n,
143.685 + null,
143.686 + "get" + nu + "__Ljava_util_List_2",
143.687 + null
143.688 + };
143.689 + }
143.690 + return new String[]{
143.691 + pref + n,
143.692 + "set" + n,
143.693 + pref + nu + "__" + bck2brwsrType,
143.694 + "set" + nu + "__V" + bck2brwsrType
143.695 + };
143.696 + }
143.697 +
143.698 + private String typeName(Element where, Prprt p) {
143.699 + String ret;
143.700 + boolean[] isModel = { false };
143.701 + boolean[] isEnum = { false };
143.702 + boolean isPrimitive[] = { false };
143.703 + ret = checkType(p, isModel, isEnum, isPrimitive);
143.704 + if (p.array()) {
143.705 + String bt = findBoxedType(ret);
143.706 + if (bt != null) {
143.707 + return bt;
143.708 + }
143.709 + }
143.710 + return ret;
143.711 + }
143.712 +
143.713 + private static String findBoxedType(String ret) {
143.714 + if (ret.equals("boolean")) {
143.715 + return Boolean.class.getName();
143.716 + }
143.717 + if (ret.equals("byte")) {
143.718 + return Byte.class.getName();
143.719 + }
143.720 + if (ret.equals("short")) {
143.721 + return Short.class.getName();
143.722 + }
143.723 + if (ret.equals("char")) {
143.724 + return Character.class.getName();
143.725 + }
143.726 + if (ret.equals("int")) {
143.727 + return Integer.class.getName();
143.728 + }
143.729 + if (ret.equals("long")) {
143.730 + return Long.class.getName();
143.731 + }
143.732 + if (ret.equals("float")) {
143.733 + return Float.class.getName();
143.734 + }
143.735 + if (ret.equals("double")) {
143.736 + return Double.class.getName();
143.737 + }
143.738 + return null;
143.739 + }
143.740 +
143.741 + private boolean verifyPropName(Element e, String propName, Prprt[] existingProps) {
143.742 + StringBuilder sb = new StringBuilder();
143.743 + String sep = "";
143.744 + for (Prprt Prprt : existingProps) {
143.745 + if (Prprt.name().equals(propName)) {
143.746 + return true;
143.747 + }
143.748 + sb.append(sep);
143.749 + sb.append('"');
143.750 + sb.append(Prprt.name());
143.751 + sb.append('"');
143.752 + sep = ", ";
143.753 + }
143.754 + error(
143.755 + propName + " is not one of known properties: " + sb
143.756 + , e
143.757 + );
143.758 + return false;
143.759 + }
143.760 +
143.761 + private static String findPkgName(Element e) {
143.762 + for (;;) {
143.763 + if (e.getKind() == ElementKind.PACKAGE) {
143.764 + return ((PackageElement)e).getQualifiedName().toString();
143.765 + }
143.766 + e = e.getEnclosingElement();
143.767 + }
143.768 + }
143.769 +
143.770 + private boolean generateFunctions(
143.771 + Element clazz, StringWriter body, String className,
143.772 + List<? extends Element> enclosedElements, List<String> functions
143.773 + ) {
143.774 + for (Element m : enclosedElements) {
143.775 + if (m.getKind() != ElementKind.METHOD) {
143.776 + continue;
143.777 + }
143.778 + ExecutableElement e = (ExecutableElement)m;
143.779 + Function onF = e.getAnnotation(Function.class);
143.780 + if (onF == null) {
143.781 + continue;
143.782 + }
143.783 + if (!e.getModifiers().contains(Modifier.STATIC)) {
143.784 + error("@OnFunction method needs to be static", e);
143.785 + return false;
143.786 + }
143.787 + if (e.getModifiers().contains(Modifier.PRIVATE)) {
143.788 + error("@OnFunction method cannot be private", e);
143.789 + return false;
143.790 + }
143.791 + if (e.getReturnType().getKind() != TypeKind.VOID) {
143.792 + error("@OnFunction method should return void", e);
143.793 + return false;
143.794 + }
143.795 + String n = e.getSimpleName().toString();
143.796 + body.append(" private void ").append(n).append("(Object data, Object ev) {\n");
143.797 + body.append(" ").append(((TypeElement)clazz).getQualifiedName()).append(".").append(n).append("(");
143.798 + body.append(wrapParams(e, null, className, "ev", "data"));
143.799 + body.append(");\n");
143.800 + body.append(" }\n");
143.801 +
143.802 + functions.add(n);
143.803 + functions.add(n + "__VLjava_lang_Object_2Ljava_lang_Object_2");
143.804 + }
143.805 + return true;
143.806 + }
143.807 +
143.808 + private boolean generateOnChange(Element clazz, Map<String,Collection<String>> propDeps,
143.809 + Prprt[] properties, String className,
143.810 + Map<String, Collection<String>> functionDeps
143.811 + ) {
143.812 + for (Element m : clazz.getEnclosedElements()) {
143.813 + if (m.getKind() != ElementKind.METHOD) {
143.814 + continue;
143.815 + }
143.816 + ExecutableElement e = (ExecutableElement) m;
143.817 + OnPropertyChange onPC = e.getAnnotation(OnPropertyChange.class);
143.818 + if (onPC == null) {
143.819 + continue;
143.820 + }
143.821 + for (String pn : onPC.value()) {
143.822 + if (findPrprt(properties, pn) == null && findDerivedFrom(propDeps, pn).isEmpty()) {
143.823 + error("No Prprt named '" + pn + "' in the model", clazz);
143.824 + return false;
143.825 + }
143.826 + }
143.827 + if (!e.getModifiers().contains(Modifier.STATIC)) {
143.828 + error("@OnPrprtChange method needs to be static", e);
143.829 + return false;
143.830 + }
143.831 + if (e.getModifiers().contains(Modifier.PRIVATE)) {
143.832 + error("@OnPrprtChange method cannot be private", e);
143.833 + return false;
143.834 + }
143.835 + if (e.getReturnType().getKind() != TypeKind.VOID) {
143.836 + error("@OnPrprtChange method should return void", e);
143.837 + return false;
143.838 + }
143.839 + String n = e.getSimpleName().toString();
143.840 +
143.841 +
143.842 + for (String pn : onPC.value()) {
143.843 + StringBuilder call = new StringBuilder();
143.844 + call.append(" ").append(clazz.getSimpleName()).append(".").append(n).append("(");
143.845 + call.append(wrapPropName(e, className, "name", pn));
143.846 + call.append(");\n");
143.847 +
143.848 + Collection<String> change = functionDeps.get(pn);
143.849 + if (change == null) {
143.850 + change = new ArrayList<String>();
143.851 + functionDeps.put(pn, change);
143.852 + }
143.853 + change.add(call.toString());
143.854 + for (String dpn : findDerivedFrom(propDeps, pn)) {
143.855 + change = functionDeps.get(dpn);
143.856 + if (change == null) {
143.857 + change = new ArrayList<String>();
143.858 + functionDeps.put(dpn, change);
143.859 + }
143.860 + change.add(call.toString());
143.861 + }
143.862 + }
143.863 + }
143.864 + return true;
143.865 + }
143.866 +
143.867 + private boolean generateOperation(Element clazz,
143.868 + StringWriter body, String className,
143.869 + List<? extends Element> enclosedElements
143.870 + ) {
143.871 + for (Element m : enclosedElements) {
143.872 + if (m.getKind() != ElementKind.METHOD) {
143.873 + continue;
143.874 + }
143.875 + ExecutableElement e = (ExecutableElement)m;
143.876 + ModelOperation mO = e.getAnnotation(ModelOperation.class);
143.877 + if (mO == null) {
143.878 + continue;
143.879 + }
143.880 + if (!e.getModifiers().contains(Modifier.STATIC)) {
143.881 + error("@ModelOperation method needs to be static", e);
143.882 + return false;
143.883 + }
143.884 + if (e.getModifiers().contains(Modifier.PRIVATE)) {
143.885 + error("@ModelOperation method cannot be private", e);
143.886 + return false;
143.887 + }
143.888 + if (e.getReturnType().getKind() != TypeKind.VOID) {
143.889 + error("@ModelOperation method should return void", e);
143.890 + return false;
143.891 + }
143.892 + List<String> args = new ArrayList<String>();
143.893 + {
143.894 + body.append(" public void ").append(m.getSimpleName()).append("(");
143.895 + String sep = "";
143.896 + boolean checkFirst = true;
143.897 + for (VariableElement ve : e.getParameters()) {
143.898 + final TypeMirror type = ve.asType();
143.899 + CharSequence simpleName;
143.900 + if (type.getKind() == TypeKind.DECLARED) {
143.901 + simpleName = ((DeclaredType)type).asElement().getSimpleName();
143.902 + } else {
143.903 + simpleName = type.toString();
143.904 + }
143.905 + if (simpleName.toString().equals(className)) {
143.906 + checkFirst = false;
143.907 + } else {
143.908 + if (checkFirst) {
143.909 + error("First parameter of @ModelOperation method must be " + className, m);
143.910 + return false;
143.911 + }
143.912 + args.add(ve.getSimpleName().toString());
143.913 + body.append(sep).append("final ");
143.914 + body.append(ve.asType().toString()).append(" ");
143.915 + body.append(ve.toString());
143.916 + sep = ", ";
143.917 + }
143.918 + }
143.919 + body.append(") {\n");
143.920 + body.append(" proto.runInBrowser(new Runnable() { public void run() {\n");
143.921 + body.append(" ").append(clazz.getSimpleName()).append(".").append(m.getSimpleName()).append("(");
143.922 + body.append(className).append(".this");
143.923 + for (String s : args) {
143.924 + body.append(", ").append(s);
143.925 + }
143.926 + body.append(");\n");
143.927 + body.append(" }});\n");
143.928 + body.append(" }\n");
143.929 + }
143.930 +
143.931 + }
143.932 + return true;
143.933 + }
143.934 +
143.935 +
143.936 + private boolean generateReceive(
143.937 + Element clazz, StringWriter body, String className,
143.938 + List<? extends Element> enclosedElements, StringBuilder inType
143.939 + ) {
143.940 + inType.append(" @Override public void onMessage(").append(className).append(" model, int index, int type, Object data) {\n");
143.941 + inType.append(" switch (index) {\n");
143.942 + int index = 0;
143.943 + for (Element m : enclosedElements) {
143.944 + if (m.getKind() != ElementKind.METHOD) {
143.945 + continue;
143.946 + }
143.947 + ExecutableElement e = (ExecutableElement)m;
143.948 + OnReceive onR = e.getAnnotation(OnReceive.class);
143.949 + if (onR == null) {
143.950 + continue;
143.951 + }
143.952 + if (!e.getModifiers().contains(Modifier.STATIC)) {
143.953 + error("@OnReceive method needs to be static", e);
143.954 + return false;
143.955 + }
143.956 + if (e.getModifiers().contains(Modifier.PRIVATE)) {
143.957 + error("@OnReceive method cannot be private", e);
143.958 + return false;
143.959 + }
143.960 + if (e.getReturnType().getKind() != TypeKind.VOID) {
143.961 + error("@OnReceive method should return void", e);
143.962 + return false;
143.963 + }
143.964 + if (!onR.jsonp().isEmpty() && !"GET".equals(onR.method())) {
143.965 + error("JSONP works only with GET transport method", e);
143.966 + }
143.967 + String dataMirror = findDataSpecified(e, onR);
143.968 + if ("PUT".equals(onR.method()) && dataMirror == null) {
143.969 + error("PUT method needs to specify a data() class", e);
143.970 + return false;
143.971 + }
143.972 + if ("POST".equals(onR.method()) && dataMirror == null) {
143.973 + error("POST method needs to specify a data() class", e);
143.974 + return false;
143.975 + }
143.976 + String modelClass = null;
143.977 + boolean expectsList = false;
143.978 + List<String> args = new ArrayList<String>();
143.979 + {
143.980 + for (VariableElement ve : e.getParameters()) {
143.981 + TypeMirror modelType = null;
143.982 + final TypeMirror type = ve.asType();
143.983 + CharSequence simpleName;
143.984 + if (type.getKind() == TypeKind.DECLARED) {
143.985 + simpleName = ((DeclaredType)type).asElement().getSimpleName();
143.986 + } else {
143.987 + simpleName = type.toString();
143.988 + }
143.989 + if (simpleName.toString().equals(className)) {
143.990 + args.add("model");
143.991 + } else if (isModel(ve.asType())) {
143.992 + modelType = ve.asType();
143.993 + } else if (ve.asType().getKind() == TypeKind.ARRAY) {
143.994 + modelType = ((ArrayType)ve.asType()).getComponentType();
143.995 + expectsList = true;
143.996 + } else if (ve.asType().toString().equals("java.lang.String")) {
143.997 + modelType = ve.asType();
143.998 + }
143.999 + if (modelType != null) {
143.1000 + if (modelClass != null) {
143.1001 + error("There can be only one model class among arguments", e);
143.1002 + } else {
143.1003 + modelClass = modelType.toString();
143.1004 + if (expectsList) {
143.1005 + args.add("arr");
143.1006 + } else {
143.1007 + args.add("arr[0]");
143.1008 + }
143.1009 + }
143.1010 + }
143.1011 + }
143.1012 + }
143.1013 + if (modelClass == null) {
143.1014 + error("The method needs to have one @Model class as parameter", e);
143.1015 + }
143.1016 + String n = e.getSimpleName().toString();
143.1017 + if ("WebSocket".equals(onR.method())) {
143.1018 + body.append(" /** Performs WebSocket communication. Call with <code>null</code> data parameter\n");
143.1019 + body.append(" * to open the connection (even if not required). Call with non-null data to\n");
143.1020 + body.append(" * send messages to server. Call again with <code>null</code> data to close the socket.\n");
143.1021 + body.append(" */\n");
143.1022 + }
143.1023 + body.append(" public void ").append(n).append("(");
143.1024 + StringBuilder urlBefore = new StringBuilder();
143.1025 + StringBuilder urlAfter = new StringBuilder();
143.1026 + String jsonpVarName = null;
143.1027 + {
143.1028 + String sep = "";
143.1029 + boolean skipJSONP = onR.jsonp().isEmpty();
143.1030 + for (String p : findParamNames(e, onR.url(), onR.jsonp(), urlBefore, urlAfter)) {
143.1031 + if (!skipJSONP && p.equals(onR.jsonp())) {
143.1032 + skipJSONP = true;
143.1033 + jsonpVarName = p;
143.1034 + continue;
143.1035 + }
143.1036 + body.append(sep);
143.1037 + body.append("String ").append(p);
143.1038 + sep = ", ";
143.1039 + }
143.1040 + if (!skipJSONP) {
143.1041 + error(
143.1042 + "Name of jsonp attribute ('" + onR.jsonp() +
143.1043 + "') is not used in url attribute '" + onR.url() + "'", e
143.1044 + );
143.1045 + }
143.1046 + if (dataMirror != null) {
143.1047 + body.append(sep).append(dataMirror.toString()).append(" data");
143.1048 + }
143.1049 + }
143.1050 + body.append(") {\n");
143.1051 + boolean webSocket = onR.method().equals("WebSocket");
143.1052 + if (webSocket) {
143.1053 + if (generateWSReceiveBody(index++, body, inType, onR, e, clazz, className, expectsList, modelClass, n, args, urlBefore, jsonpVarName, urlAfter, dataMirror)) {
143.1054 + return false;
143.1055 + }
143.1056 + body.append(" }\n");
143.1057 + body.append(" private Object ws_" + e.getSimpleName() + ";\n");
143.1058 + } else {
143.1059 + if (generateJSONReceiveBody(index++, body, inType, onR, e, clazz, className, expectsList, modelClass, n, args, urlBefore, jsonpVarName, urlAfter, dataMirror)) {
143.1060 + return false;
143.1061 + }
143.1062 + body.append(" }\n");
143.1063 + }
143.1064 + }
143.1065 + inType.append(" }\n");
143.1066 + inType.append(" throw new UnsupportedOperationException(\"index: \" + index + \" type: \" + type);\n");
143.1067 + inType.append(" }\n");
143.1068 + return true;
143.1069 + }
143.1070 +
143.1071 + private boolean generateJSONReceiveBody(int index, StringWriter method, StringBuilder body, OnReceive onR, ExecutableElement e, Element clazz, String className, boolean expectsList, String modelClass, String n, List<String> args, StringBuilder urlBefore, String jsonpVarName, StringBuilder urlAfter, String dataMirror) {
143.1072 + body.append(
143.1073 + " case " + index + ": {\n" +
143.1074 + " if (type == 2) { /* on error */\n" +
143.1075 + " Exception ex = (Exception)data;\n"
143.1076 + );
143.1077 + if (onR.onError().isEmpty()) {
143.1078 + body.append(
143.1079 + " ex.printStackTrace();\n"
143.1080 + );
143.1081 + } else {
143.1082 + if (!findOnError(e, ((TypeElement)clazz), onR.onError(), className)) {
143.1083 + return true;
143.1084 + }
143.1085 + body.append(" ").append(clazz.getSimpleName()).append(".").append(onR.onError()).append("(");
143.1086 + body.append("model, ex);\n");
143.1087 + }
143.1088 + body.append(
143.1089 + " return;\n" +
143.1090 + " } else if (type == 1) {\n" +
143.1091 + " Object[] ev = (Object[])data;\n"
143.1092 + );
143.1093 + if (expectsList) {
143.1094 + body.append(
143.1095 + " " + modelClass + "[] arr = new " + modelClass + "[ev.length];\n"
143.1096 + );
143.1097 + } else {
143.1098 + body.append(
143.1099 + " " + modelClass + "[] arr = { null };\n"
143.1100 + );
143.1101 + }
143.1102 + body.append(
143.1103 + " TYPE.copyJSON(model.proto.getContext(), ev, " + modelClass + ".class, arr);\n"
143.1104 + );
143.1105 + {
143.1106 + body.append(" ").append(clazz.getSimpleName()).append(".").append(n).append("(");
143.1107 + String sep = "";
143.1108 + for (String arg : args) {
143.1109 + body.append(sep);
143.1110 + body.append(arg);
143.1111 + sep = ", ";
143.1112 + }
143.1113 + body.append(");\n");
143.1114 + }
143.1115 + body.append(
143.1116 + " return;\n" +
143.1117 + " }\n" +
143.1118 + " }\n"
143.1119 + );
143.1120 + method.append(" proto.loadJSON(" + index + ",\n ");
143.1121 + method.append(urlBefore).append(", ");
143.1122 + if (jsonpVarName != null) {
143.1123 + method.append(urlAfter);
143.1124 + } else {
143.1125 + method.append("null");
143.1126 + }
143.1127 + if (!"GET".equals(onR.method()) || dataMirror != null) {
143.1128 + method.append(", \"").append(onR.method()).append('"');
143.1129 + if (dataMirror != null) {
143.1130 + method.append(", data");
143.1131 + } else {
143.1132 + method.append(", null");
143.1133 + }
143.1134 + } else {
143.1135 + method.append(", null, null");
143.1136 + }
143.1137 + method.append(");\n");
143.1138 + return false;
143.1139 + }
143.1140 +
143.1141 + private boolean generateWSReceiveBody(int index, StringWriter method, StringBuilder body, OnReceive onR, ExecutableElement e, Element clazz, String className, boolean expectsList, String modelClass, String n, List<String> args, StringBuilder urlBefore, String jsonpVarName, StringBuilder urlAfter, String dataMirror) {
143.1142 + body.append(
143.1143 + " case " + index + ": {\n" +
143.1144 + " if (type == 0) { /* on open */\n" +
143.1145 + " ").append(clazz.getSimpleName()).append(".").append(n).append("(");
143.1146 + {
143.1147 + String sep = "";
143.1148 + for (String arg : args) {
143.1149 + body.append(sep);
143.1150 + if (arg.startsWith("arr")) {
143.1151 + body.append("null");
143.1152 + } else {
143.1153 + body.append(arg);
143.1154 + }
143.1155 + sep = ", ";
143.1156 + }
143.1157 + }
143.1158 + body.append(");\n");
143.1159 + body.append(
143.1160 + " return;\n" +
143.1161 + " } else if (type == 2) { /* on error */\n" +
143.1162 + " Exception value = (Exception)data;\n"
143.1163 + );
143.1164 + if (onR.onError().isEmpty()) {
143.1165 + body.append(
143.1166 + " value.printStackTrace();\n"
143.1167 + );
143.1168 + } else {
143.1169 + if (!findOnError(e, ((TypeElement)clazz), onR.onError(), className)) {
143.1170 + return true;
143.1171 + }
143.1172 + body.append(" ").append(clazz.getSimpleName()).append(".").append(onR.onError()).append("(");
143.1173 + body.append("model, value);\n");
143.1174 + }
143.1175 + body.append(
143.1176 + " return;\n" +
143.1177 + " } else if (type == 1) {\n" +
143.1178 + " Object[] ev = (Object[])data;\n"
143.1179 + );
143.1180 + if (expectsList) {
143.1181 + body.append(
143.1182 + " " + modelClass + "[] arr = new " + modelClass + "[ev.length];\n"
143.1183 + );
143.1184 + } else {
143.1185 + body.append(
143.1186 + " " + modelClass + "[] arr = { null };\n"
143.1187 + );
143.1188 + }
143.1189 + body.append(
143.1190 + " TYPE.copyJSON(model.proto.getContext(), ev, " + modelClass + ".class, arr);\n"
143.1191 + );
143.1192 + {
143.1193 + body.append(" ").append(clazz.getSimpleName()).append(".").append(n).append("(");
143.1194 + String sep = "";
143.1195 + for (String arg : args) {
143.1196 + body.append(sep);
143.1197 + body.append(arg);
143.1198 + sep = ", ";
143.1199 + }
143.1200 + body.append(");\n");
143.1201 + }
143.1202 + body.append(
143.1203 + " return;\n" +
143.1204 + " }"
143.1205 + );
143.1206 + if (!onR.onError().isEmpty()) {
143.1207 + body.append(" else if (type == 3) { /* on close */\n");
143.1208 + body.append(" ").append(clazz.getSimpleName()).append(".").append(onR.onError()).append("(");
143.1209 + body.append("model, null);\n");
143.1210 + body.append(
143.1211 + " return;" +
143.1212 + " }"
143.1213 + );
143.1214 + }
143.1215 + body.append("\n");
143.1216 + body.append(" }\n");
143.1217 + method.append(" if (this.ws_").append(e.getSimpleName()).append(" == null) {\n");
143.1218 + method.append(" this.ws_").append(e.getSimpleName());
143.1219 + method.append("= proto.wsOpen(" + index + ", ");
143.1220 + method.append(urlBefore).append(", data);\n");
143.1221 + method.append(" } else {\n");
143.1222 + method.append(" proto.wsSend(this.ws_").append(e.getSimpleName()).append(", ").append(urlBefore).append(", data);\n");
143.1223 + method.append(" }\n");
143.1224 + return false;
143.1225 + }
143.1226 +
143.1227 + private CharSequence wrapParams(
143.1228 + ExecutableElement ee, String id, String className, String evName, String dataName
143.1229 + ) {
143.1230 + TypeMirror stringType = processingEnv.getElementUtils().getTypeElement("java.lang.String").asType();
143.1231 + StringBuilder params = new StringBuilder();
143.1232 + boolean first = true;
143.1233 + for (VariableElement ve : ee.getParameters()) {
143.1234 + if (!first) {
143.1235 + params.append(", ");
143.1236 + }
143.1237 + first = false;
143.1238 + String toCall = null;
143.1239 + String toFinish = null;
143.1240 + boolean addNull = true;
143.1241 + if (ve.asType() == stringType) {
143.1242 + if (ve.getSimpleName().contentEquals("id")) {
143.1243 + params.append('"').append(id).append('"');
143.1244 + continue;
143.1245 + }
143.1246 + toCall = "proto.toString(";
143.1247 + }
143.1248 + if (ve.asType().getKind() == TypeKind.DOUBLE) {
143.1249 + toCall = "proto.toNumber(";
143.1250 + toFinish = ".doubleValue()";
143.1251 + }
143.1252 + if (ve.asType().getKind() == TypeKind.INT) {
143.1253 + toCall = "proto.toNumber(";
143.1254 + toFinish = ".intValue()";
143.1255 + }
143.1256 + if (dataName != null && ve.getSimpleName().contentEquals(dataName) && isModel(ve.asType())) {
143.1257 + toCall = "proto.toModel(" + ve.asType() + ".class, ";
143.1258 + addNull = false;
143.1259 + }
143.1260 +
143.1261 + if (toCall != null) {
143.1262 + params.append(toCall);
143.1263 + if (dataName != null && ve.getSimpleName().contentEquals(dataName)) {
143.1264 + params.append(dataName);
143.1265 + if (addNull) {
143.1266 + params.append(", null");
143.1267 + }
143.1268 + } else {
143.1269 + if (evName == null) {
143.1270 + final StringBuilder sb = new StringBuilder();
143.1271 + sb.append("Unexpected string parameter name.");
143.1272 + if (dataName != null) {
143.1273 + sb.append(" Try \"").append(dataName).append("\"");
143.1274 + }
143.1275 + error(sb.toString(), ee);
143.1276 + }
143.1277 + params.append(evName);
143.1278 + params.append(", \"");
143.1279 + params.append(ve.getSimpleName().toString());
143.1280 + params.append("\"");
143.1281 + }
143.1282 + params.append(")");
143.1283 + if (toFinish != null) {
143.1284 + params.append(toFinish);
143.1285 + }
143.1286 + continue;
143.1287 + }
143.1288 + String rn = fqn(ve.asType(), ee);
143.1289 + int last = rn.lastIndexOf('.');
143.1290 + if (last >= 0) {
143.1291 + rn = rn.substring(last + 1);
143.1292 + }
143.1293 + if (rn.equals(className)) {
143.1294 + params.append(className).append(".this");
143.1295 + continue;
143.1296 + }
143.1297 + error(
143.1298 + "The annotated method can only accept " + className + " argument or argument named 'data'",
143.1299 + ee
143.1300 + );
143.1301 + }
143.1302 + return params;
143.1303 + }
143.1304 +
143.1305 +
143.1306 + private CharSequence wrapPropName(
143.1307 + ExecutableElement ee, String className, String propName, String propValue
143.1308 + ) {
143.1309 + TypeMirror stringType = processingEnv.getElementUtils().getTypeElement("java.lang.String").asType();
143.1310 + StringBuilder params = new StringBuilder();
143.1311 + boolean first = true;
143.1312 + for (VariableElement ve : ee.getParameters()) {
143.1313 + if (!first) {
143.1314 + params.append(", ");
143.1315 + }
143.1316 + first = false;
143.1317 + if (ve.asType() == stringType) {
143.1318 + if (propName != null && ve.getSimpleName().contentEquals(propName)) {
143.1319 + params.append('"').append(propValue).append('"');
143.1320 + } else {
143.1321 + error("Unexpected string parameter name. Try \"" + propName + "\".", ee);
143.1322 + }
143.1323 + continue;
143.1324 + }
143.1325 + String rn = fqn(ve.asType(), ee);
143.1326 + int last = rn.lastIndexOf('.');
143.1327 + if (last >= 0) {
143.1328 + rn = rn.substring(last + 1);
143.1329 + }
143.1330 + if (rn.equals(className)) {
143.1331 + params.append("model");
143.1332 + continue;
143.1333 + }
143.1334 + error(
143.1335 + "@OnPrprtChange method can only accept String or " + className + " arguments",
143.1336 + ee);
143.1337 + }
143.1338 + return params;
143.1339 + }
143.1340 +
143.1341 + private boolean isModel(TypeMirror tm) {
143.1342 + if (tm.getKind() == TypeKind.ERROR) {
143.1343 + return true;
143.1344 + }
143.1345 + final Element e = processingEnv.getTypeUtils().asElement(tm);
143.1346 + if (e == null) {
143.1347 + return false;
143.1348 + }
143.1349 + for (Element ch : e.getEnclosedElements()) {
143.1350 + if (ch.getKind() == ElementKind.METHOD) {
143.1351 + ExecutableElement ee = (ExecutableElement)ch;
143.1352 + if (ee.getParameters().isEmpty() && ee.getSimpleName().contentEquals("modelFor")) {
143.1353 + return true;
143.1354 + }
143.1355 + }
143.1356 + }
143.1357 + return models.values().contains(e.getSimpleName().toString());
143.1358 + }
143.1359 +
143.1360 + private void writeToString(Prprt[] props, Writer w) throws IOException {
143.1361 + w.write(" public String toString() {\n");
143.1362 + w.write(" StringBuilder sb = new StringBuilder();\n");
143.1363 + w.write(" sb.append('{');\n");
143.1364 + String sep = "";
143.1365 + for (Prprt p : props) {
143.1366 + w.write(sep);
143.1367 + w.append(" sb.append('\"').append(\"" + p.name() + "\")");
143.1368 + w.append(".append('\"').append(\":\");\n");
143.1369 + w.append(" sb.append(TYPE.toJSON(prop_");
143.1370 + w.append(p.name()).append("));\n");
143.1371 + sep = " sb.append(',');\n";
143.1372 + }
143.1373 + w.write(" sb.append('}');\n");
143.1374 + w.write(" return sb.toString();\n");
143.1375 + w.write(" }\n");
143.1376 + }
143.1377 + private void writeClone(String className, Prprt[] props, Writer w) throws IOException {
143.1378 + w.write(" public " + className + " clone() {\n");
143.1379 + w.write(" return clone(proto.getContext());\n");
143.1380 + w.write(" }\n");
143.1381 + w.write(" private " + className + " clone(net.java.html.BrwsrCtx ctx) {\n");
143.1382 + w.write(" " + className + " ret = new " + className + "(ctx);\n");
143.1383 + for (Prprt p : props) {
143.1384 + if (!p.array()) {
143.1385 + boolean isModel[] = { false };
143.1386 + boolean isEnum[] = { false };
143.1387 + boolean isPrimitive[] = { false };
143.1388 + checkType(p, isModel, isEnum, isPrimitive);
143.1389 + if (!isModel[0]) {
143.1390 + w.write(" ret.prop_" + p.name() + " = prop_" + p.name() + ";\n");
143.1391 + continue;
143.1392 + }
143.1393 + w.write(" ret.prop_" + p.name() + " = prop_" + p.name() + " == null ? null : prop_" + p.name() + ".clone();\n");
143.1394 + } else {
143.1395 + w.write(" proto.cloneList(ret.prop_" + p.name() + ", ctx, prop_" + p.name() + ");\n");
143.1396 + }
143.1397 + }
143.1398 +
143.1399 + w.write(" return ret;\n");
143.1400 + w.write(" }\n");
143.1401 + }
143.1402 +
143.1403 + private String inPckName(Element e) {
143.1404 + StringBuilder sb = new StringBuilder();
143.1405 + while (e.getKind() != ElementKind.PACKAGE) {
143.1406 + if (sb.length() == 0) {
143.1407 + sb.append(e.getSimpleName());
143.1408 + } else {
143.1409 + sb.insert(0, '.');
143.1410 + sb.insert(0, e.getSimpleName());
143.1411 + }
143.1412 + e = e.getEnclosingElement();
143.1413 + }
143.1414 + return sb.toString();
143.1415 + }
143.1416 +
143.1417 + private String fqn(TypeMirror pt, Element relative) {
143.1418 + if (pt.getKind() == TypeKind.ERROR) {
143.1419 + final Elements eu = processingEnv.getElementUtils();
143.1420 + PackageElement pckg = eu.getPackageOf(relative);
143.1421 + return pckg.getQualifiedName() + "." + pt.toString();
143.1422 + }
143.1423 + return pt.toString();
143.1424 + }
143.1425 +
143.1426 + private String checkType(Prprt p, boolean[] isModel, boolean[] isEnum, boolean[] isPrimitive) {
143.1427 + TypeMirror tm;
143.1428 + try {
143.1429 + String ret = p.typeName(processingEnv);
143.1430 + TypeElement e = processingEnv.getElementUtils().getTypeElement(ret);
143.1431 + if (e == null) {
143.1432 + isModel[0] = true;
143.1433 + isEnum[0] = false;
143.1434 + isPrimitive[0] = false;
143.1435 + return ret;
143.1436 + }
143.1437 + tm = e.asType();
143.1438 + } catch (MirroredTypeException ex) {
143.1439 + tm = ex.getTypeMirror();
143.1440 + }
143.1441 + tm = processingEnv.getTypeUtils().erasure(tm);
143.1442 + if (isPrimitive[0] = tm.getKind().isPrimitive()) {
143.1443 + isEnum[0] = false;
143.1444 + isModel[0] = false;
143.1445 + return tm.toString();
143.1446 + }
143.1447 + final Element e = processingEnv.getTypeUtils().asElement(tm);
143.1448 + if (e.getKind() == ElementKind.CLASS && tm.getKind() == TypeKind.ERROR) {
143.1449 + isModel[0] = true;
143.1450 + isEnum[0] = false;
143.1451 + return e.getSimpleName().toString();
143.1452 + }
143.1453 +
143.1454 + final Model m = e == null ? null : e.getAnnotation(Model.class);
143.1455 + String ret;
143.1456 + if (m != null) {
143.1457 + ret = findPkgName(e) + '.' + m.className();
143.1458 + isModel[0] = true;
143.1459 + models.put(e, m.className());
143.1460 + } else if (findModelForMthd(e)) {
143.1461 + ret = ((TypeElement)e).getQualifiedName().toString();
143.1462 + isModel[0] = true;
143.1463 + } else {
143.1464 + ret = tm.toString();
143.1465 + }
143.1466 + TypeMirror enm = processingEnv.getElementUtils().getTypeElement("java.lang.Enum").asType();
143.1467 + enm = processingEnv.getTypeUtils().erasure(enm);
143.1468 + isEnum[0] = processingEnv.getTypeUtils().isSubtype(tm, enm);
143.1469 + return ret;
143.1470 + }
143.1471 +
143.1472 + private static boolean findModelForMthd(Element clazz) {
143.1473 + if (clazz == null) {
143.1474 + return false;
143.1475 + }
143.1476 + for (Element e : clazz.getEnclosedElements()) {
143.1477 + if (e.getKind() == ElementKind.METHOD) {
143.1478 + ExecutableElement ee = (ExecutableElement)e;
143.1479 + if (
143.1480 + ee.getSimpleName().contentEquals("modelFor") &&
143.1481 + ee.getParameters().isEmpty()
143.1482 + ) {
143.1483 + return true;
143.1484 + }
143.1485 + }
143.1486 + }
143.1487 + return false;
143.1488 + }
143.1489 +
143.1490 + private Iterable<String> findParamNames(
143.1491 + Element e, String url, String jsonParam, StringBuilder... both
143.1492 + ) {
143.1493 + List<String> params = new ArrayList<String>();
143.1494 + int wasJSON = 0;
143.1495 +
143.1496 + for (int pos = 0; ;) {
143.1497 + int next = url.indexOf('{', pos);
143.1498 + if (next == -1) {
143.1499 + both[wasJSON].append('"')
143.1500 + .append(url.substring(pos))
143.1501 + .append('"');
143.1502 + return params;
143.1503 + }
143.1504 + int close = url.indexOf('}', next);
143.1505 + if (close == -1) {
143.1506 + error("Unbalanced '{' and '}' in " + url, e);
143.1507 + return params;
143.1508 + }
143.1509 + final String paramName = url.substring(next + 1, close);
143.1510 + params.add(paramName);
143.1511 + if (paramName.equals(jsonParam) && !jsonParam.isEmpty()) {
143.1512 + both[wasJSON].append('"')
143.1513 + .append(url.substring(pos, next))
143.1514 + .append('"');
143.1515 + wasJSON = 1;
143.1516 + } else {
143.1517 + both[wasJSON].append('"')
143.1518 + .append(url.substring(pos, next))
143.1519 + .append("\" + ").append(paramName).append(" + ");
143.1520 + }
143.1521 + pos = close + 1;
143.1522 + }
143.1523 + }
143.1524 +
143.1525 + private static Prprt findPrprt(Prprt[] properties, String propName) {
143.1526 + for (Prprt p : properties) {
143.1527 + if (propName.equals(p.name())) {
143.1528 + return p;
143.1529 + }
143.1530 + }
143.1531 + return null;
143.1532 + }
143.1533 +
143.1534 + private boolean isPrimitive(String type) {
143.1535 + return
143.1536 + "int".equals(type) ||
143.1537 + "double".equals(type) ||
143.1538 + "long".equals(type) ||
143.1539 + "short".equals(type) ||
143.1540 + "byte".equals(type) ||
143.1541 + "char".equals(type) ||
143.1542 + "boolean".equals(type) ||
143.1543 + "float".equals(type);
143.1544 + }
143.1545 +
143.1546 + private static Collection<String> findDerivedFrom(Map<String, Collection<String>> propsDeps, String derivedProp) {
143.1547 + Set<String> names = new HashSet<String>();
143.1548 + for (Map.Entry<String, Collection<String>> e : propsDeps.entrySet()) {
143.1549 + if (e.getValue().contains(derivedProp)) {
143.1550 + names.add(e.getKey());
143.1551 + }
143.1552 + }
143.1553 + return names;
143.1554 + }
143.1555 +
143.1556 + private Prprt[] createProps(Element e, Property[] arr) {
143.1557 + Prprt[] ret = Prprt.wrap(processingEnv, e, arr);
143.1558 + Prprt[] prev = verify.put(e, ret);
143.1559 + if (prev != null) {
143.1560 + error("Two sets of properties for ", e);
143.1561 + }
143.1562 + return ret;
143.1563 + }
143.1564 +
143.1565 + private static String strip(String s) {
143.1566 + int indx = s.indexOf("__");
143.1567 + if (indx >= 0) {
143.1568 + return s.substring(0, indx);
143.1569 + } else {
143.1570 + return s;
143.1571 + }
143.1572 + }
143.1573 +
143.1574 + private String findDataSpecified(ExecutableElement e, OnReceive onR) {
143.1575 + try {
143.1576 + return onR.data().getName();
143.1577 + } catch (MirroredTypeException ex) {
143.1578 + final TypeMirror tm = ex.getTypeMirror();
143.1579 + String name;
143.1580 + final Element te = processingEnv.getTypeUtils().asElement(tm);
143.1581 + if (te.getKind() == ElementKind.CLASS && tm.getKind() == TypeKind.ERROR) {
143.1582 + name = te.getSimpleName().toString();
143.1583 + } else {
143.1584 + name = tm.toString();
143.1585 + }
143.1586 + return "java.lang.Object".equals(name) ? null : name;
143.1587 + } catch (Exception ex) {
143.1588 + // fallback
143.1589 + }
143.1590 +
143.1591 + AnnotationMirror found = null;
143.1592 + for (AnnotationMirror am : e.getAnnotationMirrors()) {
143.1593 + if (am.getAnnotationType().toString().equals(OnReceive.class.getName())) {
143.1594 + found = am;
143.1595 + }
143.1596 + }
143.1597 + if (found == null) {
143.1598 + return null;
143.1599 + }
143.1600 +
143.1601 + for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : found.getElementValues().entrySet()) {
143.1602 + ExecutableElement ee = entry.getKey();
143.1603 + AnnotationValue av = entry.getValue();
143.1604 + if (ee.getSimpleName().contentEquals("data")) {
143.1605 + List<? extends Object> values = getAnnoValues(processingEnv, e, found);
143.1606 + for (Object v : values) {
143.1607 + String sv = v.toString();
143.1608 + if (sv.startsWith("data = ") && sv.endsWith(".class")) {
143.1609 + return sv.substring(7, sv.length() - 6);
143.1610 + }
143.1611 + }
143.1612 + return "error";
143.1613 + }
143.1614 + }
143.1615 + return null;
143.1616 + }
143.1617 +
143.1618 + static List<? extends Object> getAnnoValues(ProcessingEnvironment pe, Element e, AnnotationMirror am) {
143.1619 + try {
143.1620 + Class<?> trees = Class.forName("com.sun.tools.javac.api.JavacTrees");
143.1621 + Method m = trees.getMethod("instance", ProcessingEnvironment.class);
143.1622 + Object instance = m.invoke(null, pe);
143.1623 + m = instance.getClass().getMethod("getPath", Element.class, AnnotationMirror.class);
143.1624 + Object path = m.invoke(instance, e, am);
143.1625 + m = path.getClass().getMethod("getLeaf");
143.1626 + Object leaf = m.invoke(path);
143.1627 + m = leaf.getClass().getMethod("getArguments");
143.1628 + return (List) m.invoke(leaf);
143.1629 + } catch (Exception ex) {
143.1630 + return Collections.emptyList();
143.1631 + }
143.1632 + }
143.1633 +
143.1634 + private static class Prprt {
143.1635 + private final Element e;
143.1636 + private final AnnotationMirror tm;
143.1637 + private final Property p;
143.1638 +
143.1639 + public Prprt(Element e, AnnotationMirror tm, Property p) {
143.1640 + this.e = e;
143.1641 + this.tm = tm;
143.1642 + this.p = p;
143.1643 + }
143.1644 +
143.1645 + String name() {
143.1646 + return p.name();
143.1647 + }
143.1648 +
143.1649 + boolean array() {
143.1650 + return p.array();
143.1651 + }
143.1652 +
143.1653 + String typeName(ProcessingEnvironment env) {
143.1654 + RuntimeException ex;
143.1655 + try {
143.1656 + return p.type().getName();
143.1657 + } catch (IncompleteAnnotationException e) {
143.1658 + ex = e;
143.1659 + } catch (AnnotationTypeMismatchException e) {
143.1660 + ex = e;
143.1661 + }
143.1662 + for (Object v : getAnnoValues(env, e, tm)) {
143.1663 + String s = v.toString().replace(" ", "");
143.1664 + if (s.startsWith("type=") && s.endsWith(".class")) {
143.1665 + return s.substring(5, s.length() - 6);
143.1666 + }
143.1667 + }
143.1668 + throw ex;
143.1669 + }
143.1670 +
143.1671 +
143.1672 + static Prprt[] wrap(ProcessingEnvironment pe, Element e, Property[] arr) {
143.1673 + if (arr.length == 0) {
143.1674 + return new Prprt[0];
143.1675 + }
143.1676 +
143.1677 + if (e.getKind() != ElementKind.CLASS) {
143.1678 + throw new IllegalStateException("" + e.getKind());
143.1679 + }
143.1680 + TypeElement te = (TypeElement)e;
143.1681 + List<? extends AnnotationValue> val = null;
143.1682 + for (AnnotationMirror an : te.getAnnotationMirrors()) {
143.1683 + for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : an.getElementValues().entrySet()) {
143.1684 + if (entry.getKey().getSimpleName().contentEquals("properties")) {
143.1685 + val = (List)entry.getValue().getValue();
143.1686 + break;
143.1687 + }
143.1688 + }
143.1689 + }
143.1690 + if (val == null || val.size() != arr.length) {
143.1691 + pe.getMessager().printMessage(Diagnostic.Kind.ERROR, "" + val, e);
143.1692 + return new Prprt[0];
143.1693 + }
143.1694 + Prprt[] ret = new Prprt[arr.length];
143.1695 + BIG: for (int i = 0; i < ret.length; i++) {
143.1696 + AnnotationMirror am = (AnnotationMirror)val.get(i).getValue();
143.1697 + ret[i] = new Prprt(e, am, arr[i]);
143.1698 +
143.1699 + }
143.1700 + return ret;
143.1701 + }
143.1702 + }
143.1703 +
143.1704 + @Override
143.1705 + public Iterable<? extends Completion> getCompletions(Element element, AnnotationMirror annotation, ExecutableElement member, String userText) {
143.1706 + final Level l = Level.FINE;
143.1707 + LOG.log(l, " element: {0}", element);
143.1708 + LOG.log(l, " annotation: {0}", annotation);
143.1709 + LOG.log(l, " member: {0}", member);
143.1710 + LOG.log(l, " userText: {0}", userText);
143.1711 + LOG.log(l, "str: {0}", annotation.getAnnotationType().toString());
143.1712 + if (annotation.getAnnotationType().toString().equals(OnReceive.class.getName())) {
143.1713 + if (member.getSimpleName().contentEquals("method")) {
143.1714 + return Arrays.asList(
143.1715 + methodOf("GET"),
143.1716 + methodOf("POST"),
143.1717 + methodOf("PUT"),
143.1718 + methodOf("DELETE"),
143.1719 + methodOf("HEAD"),
143.1720 + methodOf("WebSocket")
143.1721 + );
143.1722 + }
143.1723 + }
143.1724 +
143.1725 + return super.getCompletions(element, annotation, member, userText);
143.1726 + }
143.1727 +
143.1728 + private static final Completion methodOf(String method) {
143.1729 + ResourceBundle rb = ResourceBundle.getBundle("org.netbeans.html.json.impl.Bundle");
143.1730 + return Completions.of('"' + method + '"', rb.getString("MSG_Completion_" + method));
143.1731 + }
143.1732 +
143.1733 + private boolean findOnError(ExecutableElement errElem, TypeElement te, String name, String className) {
143.1734 + String err = null;
143.1735 + METHODS:
143.1736 + for (Element e : te.getEnclosedElements()) {
143.1737 + if (e.getKind() != ElementKind.METHOD) {
143.1738 + continue;
143.1739 + }
143.1740 + if (!e.getSimpleName().contentEquals(name)) {
143.1741 + continue;
143.1742 + }
143.1743 + if (!e.getModifiers().contains(Modifier.STATIC)) {
143.1744 + errElem = (ExecutableElement) e;
143.1745 + err = "Would have to be static";
143.1746 + continue;
143.1747 + }
143.1748 + ExecutableElement ee = (ExecutableElement) e;
143.1749 + TypeMirror excType = processingEnv.getElementUtils().getTypeElement(Exception.class.getName()).asType();
143.1750 + final List<? extends VariableElement> params = ee.getParameters();
143.1751 + boolean error = false;
143.1752 + if (params.size() != 2) {
143.1753 + error = true;
143.1754 + } else {
143.1755 + String firstType = params.get(0).asType().toString();
143.1756 + int lastDot = firstType.lastIndexOf('.');
143.1757 + if (lastDot != -1) {
143.1758 + firstType = firstType.substring(lastDot + 1);
143.1759 + }
143.1760 + if (!firstType.equals(className)) {
143.1761 + error = true;
143.1762 + }
143.1763 + if (!processingEnv.getTypeUtils().isAssignable(excType, params.get(1).asType())) {
143.1764 + error = true;
143.1765 + }
143.1766 + }
143.1767 + if (error) {
143.1768 + errElem = (ExecutableElement) e;
143.1769 + err = "Error method first argument needs to be " + className + " and second Exception";
143.1770 + continue;
143.1771 + }
143.1772 + return true;
143.1773 + }
143.1774 + if (err == null) {
143.1775 + err = "Cannot find " + name + "(" + className + ", Exception) method in this class";
143.1776 + }
143.1777 + error(err, errElem);
143.1778 + return false;
143.1779 + }
143.1780 +
143.1781 +}
144.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
144.2 +++ b/json/src/main/java/org/netbeans/html/json/impl/PropertyBindingAccessor.java Tue Jan 07 08:21:57 2014 +0100
144.3 @@ -0,0 +1,109 @@
144.4 +/**
144.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
144.6 + *
144.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
144.8 + *
144.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
144.10 + * Other names may be trademarks of their respective owners.
144.11 + *
144.12 + * The contents of this file are subject to the terms of either the GNU
144.13 + * General Public License Version 2 only ("GPL") or the Common
144.14 + * Development and Distribution License("CDDL") (collectively, the
144.15 + * "License"). You may not use this file except in compliance with the
144.16 + * License. You can obtain a copy of the License at
144.17 + * http://www.netbeans.org/cddl-gplv2.html
144.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
144.19 + * specific language governing permissions and limitations under the
144.20 + * License. When distributing the software, include this License Header
144.21 + * Notice in each file and include the License file at
144.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
144.23 + * particular file as subject to the "Classpath" exception as provided
144.24 + * by Oracle in the GPL Version 2 section of the License file that
144.25 + * accompanied this code. If applicable, add the following below the
144.26 + * License Header, with the fields enclosed by brackets [] replaced by
144.27 + * your own identifying information:
144.28 + * "Portions Copyrighted [year] [name of copyright owner]"
144.29 + *
144.30 + * Contributor(s):
144.31 + *
144.32 + * The Original Software is NetBeans. The Initial Developer of the Original
144.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
144.34 + *
144.35 + * If you wish your version of this file to be governed by only the CDDL
144.36 + * or only the GPL Version 2, indicate your decision by adding
144.37 + * "[Contributor] elects to include this software in this distribution
144.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
144.39 + * single choice of license, a recipient has the option to distribute
144.40 + * your version of this file under either the CDDL, the GPL Version 2 or
144.41 + * to extend the choice of license to its licensees as provided above.
144.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
144.43 + * Version 2 license, then the option applies only if the new code is
144.44 + * made subject to such option by the copyright holder.
144.45 + */
144.46 +package org.netbeans.html.json.impl;
144.47 +
144.48 +import net.java.html.BrwsrCtx;
144.49 +import org.apidesign.html.json.spi.FunctionBinding;
144.50 +import org.apidesign.html.json.spi.JSONCall;
144.51 +import org.apidesign.html.json.spi.PropertyBinding;
144.52 +import org.apidesign.html.json.spi.Proto;
144.53 +
144.54 +/**
144.55 + *
144.56 + * @author Jaroslav Tulach <jtulach@netbeans.org>
144.57 + */
144.58 +public abstract class PropertyBindingAccessor {
144.59 + private static PropertyBindingAccessor DEFAULT;
144.60 +
144.61 + protected PropertyBindingAccessor() {
144.62 + if (DEFAULT != null) throw new IllegalStateException();
144.63 + DEFAULT = this;
144.64 + }
144.65 +
144.66 + static {
144.67 + JSON.initClass(PropertyBinding.class);
144.68 + }
144.69 +
144.70 + protected abstract <M> PropertyBinding newBinding(
144.71 + Proto.Type<M> access, Bindings<?> bindings, String name, int index, M model, boolean readOnly
144.72 + );
144.73 + protected abstract JSONCall newCall(
144.74 + BrwsrCtx ctx, RcvrJSON callback, String urlBefore, String urlAfter,
144.75 + String method, Object data
144.76 + );
144.77 +
144.78 + protected abstract Bindings bindings(Proto proto, boolean initialize);
144.79 + protected abstract void notifyChange(Proto proto, int propIndex);
144.80 + protected abstract Proto findProto(Proto.Type<?> type, Object object);
144.81 + protected abstract <Model> Model cloneTo(Proto.Type<Model> type, Model model, BrwsrCtx c);
144.82 + protected abstract Object read(Proto.Type<?> from, BrwsrCtx c, Object data);
144.83 +
144.84 + static Bindings getBindings(Proto proto, boolean initialize) {
144.85 + return DEFAULT.bindings(proto, initialize);
144.86 + }
144.87 +
144.88 + static void notifyProtoChange(Proto proto, int propIndex) {
144.89 + DEFAULT.notifyChange(proto, propIndex);
144.90 + }
144.91 +
144.92 + static <M> PropertyBinding create(
144.93 + Proto.Type<M> access, Bindings<?> bindings, String name, int index, M model , boolean readOnly
144.94 + ) {
144.95 + return DEFAULT.newBinding(access, bindings, name, index, model, readOnly);
144.96 + }
144.97 + static JSONCall createCall(
144.98 + BrwsrCtx ctx, RcvrJSON callback, String urlBefore, String urlAfter,
144.99 + String method, Object data
144.100 + ) {
144.101 + return DEFAULT.newCall(ctx, callback, urlBefore, urlAfter, method, data);
144.102 + }
144.103 + static Proto protoFor(Proto.Type<?> type, Object object) {
144.104 + return DEFAULT.findProto(type, object);
144.105 + }
144.106 + static <Model> Model clone(Proto.Type<Model> type, Model model, BrwsrCtx c) {
144.107 + return DEFAULT.cloneTo(type, model, c);
144.108 + }
144.109 + static Object readFrom(Proto.Type<?> from, BrwsrCtx c, Object data) {
144.110 + return DEFAULT.read(from, c, data);
144.111 + }
144.112 +}
145.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
145.2 +++ b/json/src/main/java/org/netbeans/html/json/impl/RcvrJSON.java Tue Jan 07 08:21:57 2014 +0100
145.3 @@ -0,0 +1,128 @@
145.4 +/**
145.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
145.6 + *
145.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
145.8 + *
145.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
145.10 + * Other names may be trademarks of their respective owners.
145.11 + *
145.12 + * The contents of this file are subject to the terms of either the GNU
145.13 + * General Public License Version 2 only ("GPL") or the Common
145.14 + * Development and Distribution License("CDDL") (collectively, the
145.15 + * "License"). You may not use this file except in compliance with the
145.16 + * License. You can obtain a copy of the License at
145.17 + * http://www.netbeans.org/cddl-gplv2.html
145.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
145.19 + * specific language governing permissions and limitations under the
145.20 + * License. When distributing the software, include this License Header
145.21 + * Notice in each file and include the License file at
145.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
145.23 + * particular file as subject to the "Classpath" exception as provided
145.24 + * by Oracle in the GPL Version 2 section of the License file that
145.25 + * accompanied this code. If applicable, add the following below the
145.26 + * License Header, with the fields enclosed by brackets [] replaced by
145.27 + * your own identifying information:
145.28 + * "Portions Copyrighted [year] [name of copyright owner]"
145.29 + *
145.30 + * Contributor(s):
145.31 + *
145.32 + * The Original Software is NetBeans. The Initial Developer of the Original
145.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
145.34 + *
145.35 + * If you wish your version of this file to be governed by only the CDDL
145.36 + * or only the GPL Version 2, indicate your decision by adding
145.37 + * "[Contributor] elects to include this software in this distribution
145.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
145.39 + * single choice of license, a recipient has the option to distribute
145.40 + * your version of this file under either the CDDL, the GPL Version 2 or
145.41 + * to extend the choice of license to its licensees as provided above.
145.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
145.43 + * Version 2 license, then the option applies only if the new code is
145.44 + * made subject to such option by the copyright holder.
145.45 + */
145.46 +package org.netbeans.html.json.impl;
145.47 +
145.48 +import java.util.ArrayList;
145.49 +import net.java.html.BrwsrCtx;
145.50 +
145.51 +/** Super type for those who wish to receive JSON messages.
145.52 + *
145.53 + * @author Jaroslav Tulach <jtulach@netbeans.org>
145.54 + */
145.55 +public abstract class RcvrJSON {
145.56 + protected void onOpen(MsgEvnt msg) {}
145.57 + protected abstract void onMessage(MsgEvnt msg);
145.58 + protected void onClose(MsgEvnt msg) {}
145.59 + protected abstract void onError(MsgEvnt msg);
145.60 +
145.61 + public abstract static class MsgEvnt {
145.62 + MsgEvnt() {
145.63 + }
145.64 +
145.65 + public Throwable getError() {
145.66 + return null;
145.67 + }
145.68 +
145.69 + public final Exception getException() {
145.70 + Throwable t = getError();
145.71 + if (t instanceof Exception) {
145.72 + return (Exception)t;
145.73 + }
145.74 + if (t == null) {
145.75 + return null;
145.76 + }
145.77 + return new Exception(t);
145.78 + }
145.79 +
145.80 + public Object[] getValues() {
145.81 + return null;
145.82 + }
145.83 +
145.84 + public abstract void dispatch(RcvrJSON r);
145.85 +
145.86 + public static MsgEvnt createError(final Throwable t) {
145.87 + return new MsgEvnt() {
145.88 + @Override
145.89 + public Throwable getError() {
145.90 + return t;
145.91 + }
145.92 +
145.93 + @Override
145.94 + public void dispatch(RcvrJSON r) {
145.95 + r.onError(this);
145.96 + }
145.97 + };
145.98 + }
145.99 +
145.100 + public static MsgEvnt createMessage(final Object value) {
145.101 + return new MsgEvnt() {
145.102 + @Override
145.103 + public Object[] getValues() {
145.104 + return value instanceof Object[] ? (Object[])value : new Object[] { value };
145.105 + }
145.106 +
145.107 + @Override
145.108 + public void dispatch(RcvrJSON r) {
145.109 + r.onMessage(this);
145.110 + }
145.111 + };
145.112 + }
145.113 +
145.114 + public static MsgEvnt createOpen() {
145.115 + return new MsgEvnt() {
145.116 + @Override
145.117 + public void dispatch(RcvrJSON r) {
145.118 + r.onOpen(this);
145.119 + }
145.120 + };
145.121 + }
145.122 +
145.123 + public static MsgEvnt createClose() {
145.124 + return new MsgEvnt() {
145.125 + @Override
145.126 + public void dispatch(RcvrJSON r) {
145.127 + r.onClose(this);
145.128 + }
145.129 + };
145.130 + }
145.131 + } }
146.1 --- a/json/src/main/resources/org/apidesign/html/json/impl/Bundle.properties Thu Dec 19 17:11:01 2013 +0100
146.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
146.3 @@ -1,75 +0,0 @@
146.4 -#
146.5 -# HTML via Java(tm) Language Bindings
146.6 -# Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
146.7 -#
146.8 -# This program is free software: you can redistribute it and/or modify
146.9 -# it under the terms of the GNU General Public License as published by
146.10 -# the Free Software Foundation, version 2 of the License.
146.11 -#
146.12 -# This program is distributed in the hope that it will be useful,
146.13 -# but WITHOUT ANY WARRANTY; without even the implied warranty of
146.14 -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
146.15 -# GNU General Public License for more details. apidesign.org
146.16 -# designates this particular file as subject to the
146.17 -# "Classpath" exception as provided by apidesign.org
146.18 -# in the License file that accompanied this code.
146.19 -#
146.20 -# You should have received a copy of the GNU General Public License
146.21 -# along with this program. Look for COPYING file in the top folder.
146.22 -# If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
146.23 -#
146.24 -
146.25 -MSG_Completion_GET=The GET method means retrieve whatever information \
146.26 - (in the form of an entity) is identified by the Request-URI. \
146.27 - If the Request-URI refers to a data-producing process, \
146.28 - it is the produced data which shall be returned as the entity in \
146.29 - the response and not the source text of the process, \
146.30 - unless that text happens to be the output of the process.
146.31 -
146.32 -MSG_Completion_HEAD=The HEAD method is identical to GET except that the server \
146.33 - MUST NOT return a message-body in the response. The metainformation \
146.34 - contained in the HTTP headers in response to a HEAD request SHOULD be \
146.35 - identical to the information sent in response to a GET request. \
146.36 - This method can be used for obtaining metainformation about the entity implied \
146.37 - by the request without transferring the entity-body itself. \
146.38 - This method is often used for testing hypertext links for validity, \
146.39 - accessibility, and recent modification.
146.40 -
146.41 -MSG_Completion_POST=The POST method is used to request that the origin server \
146.42 - accept the entity enclosed in the request as a new subordinate of the resource \
146.43 - identified by the Request-URI in the Request-Line. POST is designed to allow \
146.44 - a uniform method to cover annotation of existing resources,\
146.45 - posting a message to a bulletin board, newsgroup, mailing list, or similar \
146.46 - group of articles, providing a block of data, such as the result of submitting a \
146.47 - form, to a data-handling process or extending a database through an append operation. \
146.48 - The actual function performed by the POST method is determined by the server \
146.49 - and is usually dependent on the Request-URI. The posted entity is subordinate \
146.50 - to that URI in the same way that a file is subordinate to a directory containing it, \
146.51 - a news article is subordinate to a newsgroup to which it is posted, \
146.52 - or a record is subordinate to a database.
146.53 -
146.54 -MSG_Completion_PUT=The PUT method requests that the enclosed entity be stored \
146.55 - under the supplied Request-URI. If the Request-URI refers to an already \
146.56 - existing resource, the enclosed entity SHOULD be considered as a modified \
146.57 - version of the one residing on the origin server. If the Request-URI does \
146.58 - not point to an existing resource, and that URI is capable of being defined \
146.59 - as a new resource by the requesting user agent, the origin server can \
146.60 - create the resource with that URI. If a new resource is created, the origin \
146.61 - server MUST inform the user agent via the 201 (Created) response. \
146.62 - If an existing resource is modified, either the 200 (OK) or 204 (No Content) \
146.63 - response codes SHOULD be sent to indicate successful completion of the request. \
146.64 - If the resource could not be created or modified with the Request-URI, an \
146.65 - appropriate error response SHOULD be given that reflects the nature of the problem. \
146.66 - The recipient of the entity MUST NOT ignore any Content-* (e.g. Content-Range) \
146.67 - headers that it does not understand or implement and MUST return \
146.68 - a 501 (Not Implemented) response in such cases.
146.69 -
146.70 -MSG_Completion_DELETE=The DELETE method requests that the origin server delete \
146.71 - the resource identified by the Request-URI. This method MAY be overridden \
146.72 - by human intervention (or other means) on the origin server. The client \
146.73 - cannot be guaranteed that the operation has been carried out, even if \
146.74 - the status code returned from the origin server indicates that the action \
146.75 - has been completed successfully. However, the server SHOULD NOT indicate \
146.76 - success unless, at the time the response is given, it intends to delete \
146.77 - the resource or move it to an inaccessible location.
146.78 -
147.1 --- a/json/src/main/resources/org/apidesign/html/json/spi/package.html Thu Dec 19 17:11:01 2013 +0100
147.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
147.3 @@ -1,37 +0,0 @@
147.4 -<!--
147.5 -
147.6 - HTML via Java(tm) Language Bindings
147.7 - Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
147.8 -
147.9 - This program is free software: you can redistribute it and/or modify
147.10 - it under the terms of the GNU General Public License as published by
147.11 - the Free Software Foundation, version 2 of the License.
147.12 -
147.13 - This program is distributed in the hope that it will be useful,
147.14 - but WITHOUT ANY WARRANTY; without even the implied warranty of
147.15 - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
147.16 - GNU General Public License for more details. apidesign.org
147.17 - designates this particular file as subject to the
147.18 - "Classpath" exception as provided by apidesign.org
147.19 - in the License file that accompanied this code.
147.20 -
147.21 - You should have received a copy of the GNU General Public License
147.22 - along with this program. Look for COPYING file in the top folder.
147.23 - If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
147.24 -
147.25 --->
147.26 -<!DOCTYPE html>
147.27 -<html>
147.28 - <head>
147.29 - <title></title>
147.30 - <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
147.31 - </head>
147.32 - <body>
147.33 - <div>Implement
147.34 - <a href="Technology.html">Technology</a> and
147.35 - <a href="Transfer.html">Transfer</a> and use
147.36 - <a href="ContextBuilder.html">ContextBuilder</a> to create an instance
147.37 - of <code>Context</code> representing your technology.
147.38 - </div>
147.39 - </body>
147.40 -</html>
148.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
148.2 +++ b/json/src/main/resources/org/netbeans/html/json/impl/Bundle.properties Tue Jan 07 08:21:57 2014 +0100
148.3 @@ -0,0 +1,97 @@
148.4 +#
148.5 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
148.6 +#
148.7 +# Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
148.8 +#
148.9 +# Oracle and Java are registered trademarks of Oracle and/or its affiliates.
148.10 +# Other names may be trademarks of their respective owners.
148.11 +#
148.12 +# The contents of this file are subject to the terms of either the GNU
148.13 +# General Public License Version 2 only ("GPL") or the Common
148.14 +# Development and Distribution License("CDDL") (collectively, the
148.15 +# "License"). You may not use this file except in compliance with the
148.16 +# License. You can obtain a copy of the License at
148.17 +# http://www.netbeans.org/cddl-gplv2.html
148.18 +# or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
148.19 +# specific language governing permissions and limitations under the
148.20 +# License. When distributing the software, include this License Header
148.21 +# Notice in each file and include the License file at
148.22 +# nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
148.23 +# particular file as subject to the "Classpath" exception as provided
148.24 +# by Oracle in the GPL Version 2 section of the License file that
148.25 +# accompanied this code. If applicable, add the following below the
148.26 +# License Header, with the fields enclosed by brackets [] replaced by
148.27 +# your own identifying information:
148.28 +# "Portions Copyrighted [year] [name of copyright owner]"
148.29 +#
148.30 +# Contributor(s):
148.31 +#
148.32 +# The Original Software is NetBeans. The Initial Developer of the Original
148.33 +# Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
148.34 +#
148.35 +# If you wish your version of this file to be governed by only the CDDL
148.36 +# or only the GPL Version 2, indicate your decision by adding
148.37 +# "[Contributor] elects to include this software in this distribution
148.38 +# under the [CDDL or GPL Version 2] license." If you do not indicate a
148.39 +# single choice of license, a recipient has the option to distribute
148.40 +# your version of this file under either the CDDL, the GPL Version 2 or
148.41 +# to extend the choice of license to its licensees as provided above.
148.42 +# However, if you add GPL Version 2 code and therefore, elected the GPL
148.43 +# Version 2 license, then the option applies only if the new code is
148.44 +# made subject to such option by the copyright holder.
148.45 +#
148.46 +
148.47 +MSG_Completion_GET=The GET method means retrieve whatever information \
148.48 + (in the form of an entity) is identified by the Request-URI. \
148.49 + If the Request-URI refers to a data-producing process, \
148.50 + it is the produced data which shall be returned as the entity in \
148.51 + the response and not the source text of the process, \
148.52 + unless that text happens to be the output of the process.
148.53 +
148.54 +MSG_Completion_HEAD=The HEAD method is identical to GET except that the server \
148.55 + MUST NOT return a message-body in the response. The metainformation \
148.56 + contained in the HTTP headers in response to a HEAD request SHOULD be \
148.57 + identical to the information sent in response to a GET request. \
148.58 + This method can be used for obtaining metainformation about the entity implied \
148.59 + by the request without transferring the entity-body itself. \
148.60 + This method is often used for testing hypertext links for validity, \
148.61 + accessibility, and recent modification.
148.62 +
148.63 +MSG_Completion_POST=The POST method is used to request that the origin server \
148.64 + accept the entity enclosed in the request as a new subordinate of the resource \
148.65 + identified by the Request-URI in the Request-Line. POST is designed to allow \
148.66 + a uniform method to cover annotation of existing resources,\
148.67 + posting a message to a bulletin board, newsgroup, mailing list, or similar \
148.68 + group of articles, providing a block of data, such as the result of submitting a \
148.69 + form, to a data-handling process or extending a database through an append operation. \
148.70 + The actual function performed by the POST method is determined by the server \
148.71 + and is usually dependent on the Request-URI. The posted entity is subordinate \
148.72 + to that URI in the same way that a file is subordinate to a directory containing it, \
148.73 + a news article is subordinate to a newsgroup to which it is posted, \
148.74 + or a record is subordinate to a database.
148.75 +
148.76 +MSG_Completion_PUT=The PUT method requests that the enclosed entity be stored \
148.77 + under the supplied Request-URI. If the Request-URI refers to an already \
148.78 + existing resource, the enclosed entity SHOULD be considered as a modified \
148.79 + version of the one residing on the origin server. If the Request-URI does \
148.80 + not point to an existing resource, and that URI is capable of being defined \
148.81 + as a new resource by the requesting user agent, the origin server can \
148.82 + create the resource with that URI. If a new resource is created, the origin \
148.83 + server MUST inform the user agent via the 201 (Created) response. \
148.84 + If an existing resource is modified, either the 200 (OK) or 204 (No Content) \
148.85 + response codes SHOULD be sent to indicate successful completion of the request. \
148.86 + If the resource could not be created or modified with the Request-URI, an \
148.87 + appropriate error response SHOULD be given that reflects the nature of the problem. \
148.88 + The recipient of the entity MUST NOT ignore any Content-* (e.g. Content-Range) \
148.89 + headers that it does not understand or implement and MUST return \
148.90 + a 501 (Not Implemented) response in such cases.
148.91 +
148.92 +MSG_Completion_DELETE=The DELETE method requests that the origin server delete \
148.93 + the resource identified by the Request-URI. This method MAY be overridden \
148.94 + by human intervention (or other means) on the origin server. The client \
148.95 + cannot be guaranteed that the operation has been carried out, even if \
148.96 + the status code returned from the origin server indicates that the action \
148.97 + has been completed successfully. However, the server SHOULD NOT indicate \
148.98 + success unless, at the time the response is given, it intends to delete \
148.99 + the resource or move it to an inaccessible location.
148.100 +
149.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
149.2 +++ b/json/src/main/resources/org/netbeans/html/json/spi/package.html Tue Jan 07 08:21:57 2014 +0100
149.3 @@ -0,0 +1,59 @@
149.4 +<!--
149.5 +
149.6 + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
149.7 +
149.8 + Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
149.9 +
149.10 + Oracle and Java are registered trademarks of Oracle and/or its affiliates.
149.11 + Other names may be trademarks of their respective owners.
149.12 +
149.13 + The contents of this file are subject to the terms of either the GNU
149.14 + General Public License Version 2 only ("GPL") or the Common
149.15 + Development and Distribution License("CDDL") (collectively, the
149.16 + "License"). You may not use this file except in compliance with the
149.17 + License. You can obtain a copy of the License at
149.18 + http://www.netbeans.org/cddl-gplv2.html
149.19 + or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
149.20 + specific language governing permissions and limitations under the
149.21 + License. When distributing the software, include this License Header
149.22 + Notice in each file and include the License file at
149.23 + nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
149.24 + particular file as subject to the "Classpath" exception as provided
149.25 + by Oracle in the GPL Version 2 section of the License file that
149.26 + accompanied this code. If applicable, add the following below the
149.27 + License Header, with the fields enclosed by brackets [] replaced by
149.28 + your own identifying information:
149.29 + "Portions Copyrighted [year] [name of copyright owner]"
149.30 +
149.31 + Contributor(s):
149.32 +
149.33 + The Original Software is NetBeans. The Initial Developer of the Original
149.34 + Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
149.35 +
149.36 + If you wish your version of this file to be governed by only the CDDL
149.37 + or only the GPL Version 2, indicate your decision by adding
149.38 + "[Contributor] elects to include this software in this distribution
149.39 + under the [CDDL or GPL Version 2] license." If you do not indicate a
149.40 + single choice of license, a recipient has the option to distribute
149.41 + your version of this file under either the CDDL, the GPL Version 2 or
149.42 + to extend the choice of license to its licensees as provided above.
149.43 + However, if you add GPL Version 2 code and therefore, elected the GPL
149.44 + Version 2 license, then the option applies only if the new code is
149.45 + made subject to such option by the copyright holder.
149.46 +
149.47 +-->
149.48 +<!DOCTYPE html>
149.49 +<html>
149.50 + <head>
149.51 + <title></title>
149.52 + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
149.53 + </head>
149.54 + <body>
149.55 + <div>Implement
149.56 + <a href="Technology.html">Technology</a> and
149.57 + <a href="Transfer.html">Transfer</a> and use
149.58 + <a href="ContextBuilder.html">ContextBuilder</a> to create an instance
149.59 + of <code>Context</code> representing your technology.
149.60 + </div>
149.61 + </body>
149.62 +</html>
150.1 --- a/json/src/test/java/net/java/html/json/BoardTest.java Thu Dec 19 17:11:01 2013 +0100
150.2 +++ b/json/src/test/java/net/java/html/json/BoardTest.java Tue Jan 07 08:21:57 2014 +0100
150.3 @@ -1,22 +1,44 @@
150.4 /**
150.5 - * HTML via Java(tm) Language Bindings
150.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
150.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
150.8 *
150.9 - * This program is free software: you can redistribute it and/or modify
150.10 - * it under the terms of the GNU General Public License as published by
150.11 - * the Free Software Foundation, version 2 of the License.
150.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
150.13 *
150.14 - * This program is distributed in the hope that it will be useful,
150.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
150.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
150.17 - * GNU General Public License for more details. apidesign.org
150.18 - * designates this particular file as subject to the
150.19 - * "Classpath" exception as provided by apidesign.org
150.20 - * in the License file that accompanied this code.
150.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
150.22 + * Other names may be trademarks of their respective owners.
150.23 *
150.24 - * You should have received a copy of the GNU General Public License
150.25 - * along with this program. Look for COPYING file in the top folder.
150.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
150.27 + * The contents of this file are subject to the terms of either the GNU
150.28 + * General Public License Version 2 only ("GPL") or the Common
150.29 + * Development and Distribution License("CDDL") (collectively, the
150.30 + * "License"). You may not use this file except in compliance with the
150.31 + * License. You can obtain a copy of the License at
150.32 + * http://www.netbeans.org/cddl-gplv2.html
150.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
150.34 + * specific language governing permissions and limitations under the
150.35 + * License. When distributing the software, include this License Header
150.36 + * Notice in each file and include the License file at
150.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
150.38 + * particular file as subject to the "Classpath" exception as provided
150.39 + * by Oracle in the GPL Version 2 section of the License file that
150.40 + * accompanied this code. If applicable, add the following below the
150.41 + * License Header, with the fields enclosed by brackets [] replaced by
150.42 + * your own identifying information:
150.43 + * "Portions Copyrighted [year] [name of copyright owner]"
150.44 + *
150.45 + * Contributor(s):
150.46 + *
150.47 + * The Original Software is NetBeans. The Initial Developer of the Original
150.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
150.49 + *
150.50 + * If you wish your version of this file to be governed by only the CDDL
150.51 + * or only the GPL Version 2, indicate your decision by adding
150.52 + * "[Contributor] elects to include this software in this distribution
150.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
150.54 + * single choice of license, a recipient has the option to distribute
150.55 + * your version of this file under either the CDDL, the GPL Version 2 or
150.56 + * to extend the choice of license to its licensees as provided above.
150.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
150.58 + * Version 2 license, then the option applies only if the new code is
150.59 + * made subject to such option by the copyright holder.
150.60 */
150.61 package net.java.html.json;
150.62
151.1 --- a/json/src/test/java/net/java/html/json/Compile.java Thu Dec 19 17:11:01 2013 +0100
151.2 +++ b/json/src/test/java/net/java/html/json/Compile.java Tue Jan 07 08:21:57 2014 +0100
151.3 @@ -1,22 +1,44 @@
151.4 /**
151.5 - * HTML via Java(tm) Language Bindings
151.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
151.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
151.8 *
151.9 - * This program is free software: you can redistribute it and/or modify
151.10 - * it under the terms of the GNU General Public License as published by
151.11 - * the Free Software Foundation, version 2 of the License.
151.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
151.13 *
151.14 - * This program is distributed in the hope that it will be useful,
151.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
151.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
151.17 - * GNU General Public License for more details. apidesign.org
151.18 - * designates this particular file as subject to the
151.19 - * "Classpath" exception as provided by apidesign.org
151.20 - * in the License file that accompanied this code.
151.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
151.22 + * Other names may be trademarks of their respective owners.
151.23 *
151.24 - * You should have received a copy of the GNU General Public License
151.25 - * along with this program. Look for COPYING file in the top folder.
151.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
151.27 + * The contents of this file are subject to the terms of either the GNU
151.28 + * General Public License Version 2 only ("GPL") or the Common
151.29 + * Development and Distribution License("CDDL") (collectively, the
151.30 + * "License"). You may not use this file except in compliance with the
151.31 + * License. You can obtain a copy of the License at
151.32 + * http://www.netbeans.org/cddl-gplv2.html
151.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
151.34 + * specific language governing permissions and limitations under the
151.35 + * License. When distributing the software, include this License Header
151.36 + * Notice in each file and include the License file at
151.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
151.38 + * particular file as subject to the "Classpath" exception as provided
151.39 + * by Oracle in the GPL Version 2 section of the License file that
151.40 + * accompanied this code. If applicable, add the following below the
151.41 + * License Header, with the fields enclosed by brackets [] replaced by
151.42 + * your own identifying information:
151.43 + * "Portions Copyrighted [year] [name of copyright owner]"
151.44 + *
151.45 + * Contributor(s):
151.46 + *
151.47 + * The Original Software is NetBeans. The Initial Developer of the Original
151.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
151.49 + *
151.50 + * If you wish your version of this file to be governed by only the CDDL
151.51 + * or only the GPL Version 2, indicate your decision by adding
151.52 + * "[Contributor] elects to include this software in this distribution
151.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
151.54 + * single choice of license, a recipient has the option to distribute
151.55 + * your version of this file under either the CDDL, the GPL Version 2 or
151.56 + * to extend the choice of license to its licensees as provided above.
151.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
151.58 + * Version 2 license, then the option applies only if the new code is
151.59 + * made subject to such option by the copyright holder.
151.60 */
151.61 package net.java.html.json;
151.62
152.1 --- a/json/src/test/java/net/java/html/json/MapModelTest.java Thu Dec 19 17:11:01 2013 +0100
152.2 +++ b/json/src/test/java/net/java/html/json/MapModelTest.java Tue Jan 07 08:21:57 2014 +0100
152.3 @@ -1,22 +1,44 @@
152.4 /**
152.5 - * HTML via Java(tm) Language Bindings
152.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
152.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
152.8 *
152.9 - * This program is free software: you can redistribute it and/or modify
152.10 - * it under the terms of the GNU General Public License as published by
152.11 - * the Free Software Foundation, version 2 of the License.
152.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
152.13 *
152.14 - * This program is distributed in the hope that it will be useful,
152.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
152.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
152.17 - * GNU General Public License for more details. apidesign.org
152.18 - * designates this particular file as subject to the
152.19 - * "Classpath" exception as provided by apidesign.org
152.20 - * in the License file that accompanied this code.
152.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
152.22 + * Other names may be trademarks of their respective owners.
152.23 *
152.24 - * You should have received a copy of the GNU General Public License
152.25 - * along with this program. Look for COPYING file in the top folder.
152.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
152.27 + * The contents of this file are subject to the terms of either the GNU
152.28 + * General Public License Version 2 only ("GPL") or the Common
152.29 + * Development and Distribution License("CDDL") (collectively, the
152.30 + * "License"). You may not use this file except in compliance with the
152.31 + * License. You can obtain a copy of the License at
152.32 + * http://www.netbeans.org/cddl-gplv2.html
152.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
152.34 + * specific language governing permissions and limitations under the
152.35 + * License. When distributing the software, include this License Header
152.36 + * Notice in each file and include the License file at
152.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
152.38 + * particular file as subject to the "Classpath" exception as provided
152.39 + * by Oracle in the GPL Version 2 section of the License file that
152.40 + * accompanied this code. If applicable, add the following below the
152.41 + * License Header, with the fields enclosed by brackets [] replaced by
152.42 + * your own identifying information:
152.43 + * "Portions Copyrighted [year] [name of copyright owner]"
152.44 + *
152.45 + * Contributor(s):
152.46 + *
152.47 + * The Original Software is NetBeans. The Initial Developer of the Original
152.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
152.49 + *
152.50 + * If you wish your version of this file to be governed by only the CDDL
152.51 + * or only the GPL Version 2, indicate your decision by adding
152.52 + * "[Contributor] elects to include this software in this distribution
152.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
152.54 + * single choice of license, a recipient has the option to distribute
152.55 + * your version of this file under either the CDDL, the GPL Version 2 or
152.56 + * to extend the choice of license to its licensees as provided above.
152.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
152.58 + * Version 2 license, then the option applies only if the new code is
152.59 + * made subject to such option by the copyright holder.
152.60 */
152.61 package net.java.html.json;
152.62
152.63 @@ -27,12 +49,12 @@
152.64 import java.util.HashMap;
152.65 import java.util.Map;
152.66 import org.apidesign.html.context.spi.Contexts;
152.67 -import org.apidesign.html.json.impl.WrapperObject;
152.68 import org.apidesign.html.json.spi.FunctionBinding;
152.69 import org.apidesign.html.json.spi.JSONCall;
152.70 import org.apidesign.html.json.spi.PropertyBinding;
152.71 import org.apidesign.html.json.spi.Technology;
152.72 import org.apidesign.html.json.spi.Transfer;
152.73 +import org.netbeans.html.json.impl.JSON;
152.74 import org.testng.annotations.BeforeMethod;
152.75 import org.testng.annotations.Test;
152.76 import static org.testng.Assert.*;
152.77 @@ -55,7 +77,7 @@
152.78 Person p = Models.bind(new Person(), c).applyBindings();
152.79 p.setFirstName("Jarda");
152.80
152.81 - Map m = (Map)WrapperObject.find(p);
152.82 + Map m = (Map)JSON.find(p);
152.83 Object v = m.get("firstName");
152.84 assertNotNull(v, "Value should be in the map");
152.85 assertEquals(v.getClass(), One.class, "It is instance of One");
152.86 @@ -76,7 +98,7 @@
152.87 Person p = Models.bind(new Person(), c);
152.88 p.setFirstName("Jirka");
152.89
152.90 - Map m = (Map)WrapperObject.find(p);
152.91 + Map m = (Map)JSON.find(p);
152.92 Object v = m.get("firstName");
152.93 assertNotNull(v, "Value should be in the map");
152.94 assertEquals(v.getClass(), One.class, "It is instance of One");
152.95 @@ -100,7 +122,7 @@
152.96 @Test public void derivedProperty() throws Exception {
152.97 Person p = Models.bind(new Person(), c);
152.98
152.99 - Map m = (Map)WrapperObject.find(p);
152.100 + Map m = (Map)JSON.find(p);
152.101 Object v = m.get("fullName");
152.102 assertNotNull(v, "Value should be in the map");
152.103 assertEquals(v.getClass(), One.class, "It is instance of One");
152.104 @@ -113,7 +135,7 @@
152.105 p.setFirstName("Trans");
152.106 p.setSex(Sex.MALE);
152.107
152.108 - Map m = (Map)WrapperObject.find(p);
152.109 + Map m = (Map)JSON.find(p);
152.110 Object o = m.get("changeSex");
152.111 assertNotNull(o, "Function registered in the model");
152.112 assertEquals(o.getClass(), One.class);
152.113 @@ -130,7 +152,7 @@
152.114 Person p = Models.bind(new Person(), c);
152.115 p.setFirstName("Trans");
152.116
152.117 - Map m = (Map)WrapperObject.find(p);
152.118 + Map m = (Map)JSON.find(p);
152.119 Object o = m.get("changeSex");
152.120 assertNotNull(o, "Function registered in the model");
152.121 assertEquals(o.getClass(), One.class);
153.1 --- a/json/src/test/java/net/java/html/json/ModelProcessorTest.java Thu Dec 19 17:11:01 2013 +0100
153.2 +++ b/json/src/test/java/net/java/html/json/ModelProcessorTest.java Tue Jan 07 08:21:57 2014 +0100
153.3 @@ -1,22 +1,44 @@
153.4 /**
153.5 - * HTML via Java(tm) Language Bindings
153.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
153.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
153.8 *
153.9 - * This program is free software: you can redistribute it and/or modify
153.10 - * it under the terms of the GNU General Public License as published by
153.11 - * the Free Software Foundation, version 2 of the License.
153.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
153.13 *
153.14 - * This program is distributed in the hope that it will be useful,
153.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
153.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
153.17 - * GNU General Public License for more details. apidesign.org
153.18 - * designates this particular file as subject to the
153.19 - * "Classpath" exception as provided by apidesign.org
153.20 - * in the License file that accompanied this code.
153.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
153.22 + * Other names may be trademarks of their respective owners.
153.23 *
153.24 - * You should have received a copy of the GNU General Public License
153.25 - * along with this program. Look for COPYING file in the top folder.
153.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
153.27 + * The contents of this file are subject to the terms of either the GNU
153.28 + * General Public License Version 2 only ("GPL") or the Common
153.29 + * Development and Distribution License("CDDL") (collectively, the
153.30 + * "License"). You may not use this file except in compliance with the
153.31 + * License. You can obtain a copy of the License at
153.32 + * http://www.netbeans.org/cddl-gplv2.html
153.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
153.34 + * specific language governing permissions and limitations under the
153.35 + * License. When distributing the software, include this License Header
153.36 + * Notice in each file and include the License file at
153.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
153.38 + * particular file as subject to the "Classpath" exception as provided
153.39 + * by Oracle in the GPL Version 2 section of the License file that
153.40 + * accompanied this code. If applicable, add the following below the
153.41 + * License Header, with the fields enclosed by brackets [] replaced by
153.42 + * your own identifying information:
153.43 + * "Portions Copyrighted [year] [name of copyright owner]"
153.44 + *
153.45 + * Contributor(s):
153.46 + *
153.47 + * The Original Software is NetBeans. The Initial Developer of the Original
153.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
153.49 + *
153.50 + * If you wish your version of this file to be governed by only the CDDL
153.51 + * or only the GPL Version 2, indicate your decision by adding
153.52 + * "[Contributor] elects to include this software in this distribution
153.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
153.54 + * single choice of license, a recipient has the option to distribute
153.55 + * your version of this file under either the CDDL, the GPL Version 2 or
153.56 + * to extend the choice of license to its licensees as provided above.
153.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
153.58 + * Version 2 license, then the option applies only if the new code is
153.59 + * made subject to such option by the copyright holder.
153.60 */
153.61 package net.java.html.json;
153.62
154.1 --- a/json/src/test/java/net/java/html/json/ModelTest.java Thu Dec 19 17:11:01 2013 +0100
154.2 +++ b/json/src/test/java/net/java/html/json/ModelTest.java Tue Jan 07 08:21:57 2014 +0100
154.3 @@ -1,22 +1,44 @@
154.4 /**
154.5 - * HTML via Java(tm) Language Bindings
154.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
154.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
154.8 *
154.9 - * This program is free software: you can redistribute it and/or modify
154.10 - * it under the terms of the GNU General Public License as published by
154.11 - * the Free Software Foundation, version 2 of the License.
154.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
154.13 *
154.14 - * This program is distributed in the hope that it will be useful,
154.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
154.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
154.17 - * GNU General Public License for more details. apidesign.org
154.18 - * designates this particular file as subject to the
154.19 - * "Classpath" exception as provided by apidesign.org
154.20 - * in the License file that accompanied this code.
154.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
154.22 + * Other names may be trademarks of their respective owners.
154.23 *
154.24 - * You should have received a copy of the GNU General Public License
154.25 - * along with this program. Look for COPYING file in the top folder.
154.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
154.27 + * The contents of this file are subject to the terms of either the GNU
154.28 + * General Public License Version 2 only ("GPL") or the Common
154.29 + * Development and Distribution License("CDDL") (collectively, the
154.30 + * "License"). You may not use this file except in compliance with the
154.31 + * License. You can obtain a copy of the License at
154.32 + * http://www.netbeans.org/cddl-gplv2.html
154.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
154.34 + * specific language governing permissions and limitations under the
154.35 + * License. When distributing the software, include this License Header
154.36 + * Notice in each file and include the License file at
154.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
154.38 + * particular file as subject to the "Classpath" exception as provided
154.39 + * by Oracle in the GPL Version 2 section of the License file that
154.40 + * accompanied this code. If applicable, add the following below the
154.41 + * License Header, with the fields enclosed by brackets [] replaced by
154.42 + * your own identifying information:
154.43 + * "Portions Copyrighted [year] [name of copyright owner]"
154.44 + *
154.45 + * Contributor(s):
154.46 + *
154.47 + * The Original Software is NetBeans. The Initial Developer of the Original
154.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
154.49 + *
154.50 + * If you wish your version of this file to be governed by only the CDDL
154.51 + * or only the GPL Version 2, indicate your decision by adding
154.52 + * "[Contributor] elects to include this software in this distribution
154.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
154.54 + * single choice of license, a recipient has the option to distribute
154.55 + * your version of this file under either the CDDL, the GPL Version 2 or
154.56 + * to extend the choice of license to its licensees as provided above.
154.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
154.58 + * Version 2 license, then the option applies only if the new code is
154.59 + * made subject to such option by the copyright holder.
154.60 */
154.61 package net.java.html.json;
154.62
155.1 --- a/json/src/test/java/net/java/html/json/ModelsTest.java Thu Dec 19 17:11:01 2013 +0100
155.2 +++ b/json/src/test/java/net/java/html/json/ModelsTest.java Tue Jan 07 08:21:57 2014 +0100
155.3 @@ -1,22 +1,44 @@
155.4 /**
155.5 - * HTML via Java(tm) Language Bindings
155.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
155.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
155.8 *
155.9 - * This program is free software: you can redistribute it and/or modify
155.10 - * it under the terms of the GNU General Public License as published by
155.11 - * the Free Software Foundation, version 2 of the License.
155.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
155.13 *
155.14 - * This program is distributed in the hope that it will be useful,
155.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
155.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
155.17 - * GNU General Public License for more details. apidesign.org
155.18 - * designates this particular file as subject to the
155.19 - * "Classpath" exception as provided by apidesign.org
155.20 - * in the License file that accompanied this code.
155.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
155.22 + * Other names may be trademarks of their respective owners.
155.23 *
155.24 - * You should have received a copy of the GNU General Public License
155.25 - * along with this program. Look for COPYING file in the top folder.
155.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
155.27 + * The contents of this file are subject to the terms of either the GNU
155.28 + * General Public License Version 2 only ("GPL") or the Common
155.29 + * Development and Distribution License("CDDL") (collectively, the
155.30 + * "License"). You may not use this file except in compliance with the
155.31 + * License. You can obtain a copy of the License at
155.32 + * http://www.netbeans.org/cddl-gplv2.html
155.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
155.34 + * specific language governing permissions and limitations under the
155.35 + * License. When distributing the software, include this License Header
155.36 + * Notice in each file and include the License file at
155.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
155.38 + * particular file as subject to the "Classpath" exception as provided
155.39 + * by Oracle in the GPL Version 2 section of the License file that
155.40 + * accompanied this code. If applicable, add the following below the
155.41 + * License Header, with the fields enclosed by brackets [] replaced by
155.42 + * your own identifying information:
155.43 + * "Portions Copyrighted [year] [name of copyright owner]"
155.44 + *
155.45 + * Contributor(s):
155.46 + *
155.47 + * The Original Software is NetBeans. The Initial Developer of the Original
155.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
155.49 + *
155.50 + * If you wish your version of this file to be governed by only the CDDL
155.51 + * or only the GPL Version 2, indicate your decision by adding
155.52 + * "[Contributor] elects to include this software in this distribution
155.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
155.54 + * single choice of license, a recipient has the option to distribute
155.55 + * your version of this file under either the CDDL, the GPL Version 2 or
155.56 + * to extend the choice of license to its licensees as provided above.
155.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
155.58 + * Version 2 license, then the option applies only if the new code is
155.59 + * made subject to such option by the copyright holder.
155.60 */
155.61 package net.java.html.json;
155.62
156.1 --- a/json/src/test/java/net/java/html/json/OperationTest.java Thu Dec 19 17:11:01 2013 +0100
156.2 +++ b/json/src/test/java/net/java/html/json/OperationTest.java Tue Jan 07 08:21:57 2014 +0100
156.3 @@ -1,22 +1,44 @@
156.4 /**
156.5 - * HTML via Java(tm) Language Bindings
156.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
156.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
156.8 *
156.9 - * This program is free software: you can redistribute it and/or modify
156.10 - * it under the terms of the GNU General Public License as published by
156.11 - * the Free Software Foundation, version 2 of the License.
156.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
156.13 *
156.14 - * This program is distributed in the hope that it will be useful,
156.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
156.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
156.17 - * GNU General Public License for more details. apidesign.org
156.18 - * designates this particular file as subject to the
156.19 - * "Classpath" exception as provided by apidesign.org
156.20 - * in the License file that accompanied this code.
156.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
156.22 + * Other names may be trademarks of their respective owners.
156.23 *
156.24 - * You should have received a copy of the GNU General Public License
156.25 - * along with this program. Look for COPYING file in the top folder.
156.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
156.27 + * The contents of this file are subject to the terms of either the GNU
156.28 + * General Public License Version 2 only ("GPL") or the Common
156.29 + * Development and Distribution License("CDDL") (collectively, the
156.30 + * "License"). You may not use this file except in compliance with the
156.31 + * License. You can obtain a copy of the License at
156.32 + * http://www.netbeans.org/cddl-gplv2.html
156.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
156.34 + * specific language governing permissions and limitations under the
156.35 + * License. When distributing the software, include this License Header
156.36 + * Notice in each file and include the License file at
156.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
156.38 + * particular file as subject to the "Classpath" exception as provided
156.39 + * by Oracle in the GPL Version 2 section of the License file that
156.40 + * accompanied this code. If applicable, add the following below the
156.41 + * License Header, with the fields enclosed by brackets [] replaced by
156.42 + * your own identifying information:
156.43 + * "Portions Copyrighted [year] [name of copyright owner]"
156.44 + *
156.45 + * Contributor(s):
156.46 + *
156.47 + * The Original Software is NetBeans. The Initial Developer of the Original
156.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
156.49 + *
156.50 + * If you wish your version of this file to be governed by only the CDDL
156.51 + * or only the GPL Version 2, indicate your decision by adding
156.52 + * "[Contributor] elects to include this software in this distribution
156.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
156.54 + * single choice of license, a recipient has the option to distribute
156.55 + * your version of this file under either the CDDL, the GPL Version 2 or
156.56 + * to extend the choice of license to its licensees as provided above.
156.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
156.58 + * Version 2 license, then the option applies only if the new code is
156.59 + * made subject to such option by the copyright holder.
156.60 */
156.61 package net.java.html.json;
156.62
157.1 --- a/json/src/test/java/net/java/html/json/PersonImpl.java Thu Dec 19 17:11:01 2013 +0100
157.2 +++ b/json/src/test/java/net/java/html/json/PersonImpl.java Tue Jan 07 08:21:57 2014 +0100
157.3 @@ -1,22 +1,44 @@
157.4 /**
157.5 - * HTML via Java(tm) Language Bindings
157.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
157.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
157.8 *
157.9 - * This program is free software: you can redistribute it and/or modify
157.10 - * it under the terms of the GNU General Public License as published by
157.11 - * the Free Software Foundation, version 2 of the License.
157.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
157.13 *
157.14 - * This program is distributed in the hope that it will be useful,
157.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
157.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
157.17 - * GNU General Public License for more details. apidesign.org
157.18 - * designates this particular file as subject to the
157.19 - * "Classpath" exception as provided by apidesign.org
157.20 - * in the License file that accompanied this code.
157.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
157.22 + * Other names may be trademarks of their respective owners.
157.23 *
157.24 - * You should have received a copy of the GNU General Public License
157.25 - * along with this program. Look for COPYING file in the top folder.
157.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
157.27 + * The contents of this file are subject to the terms of either the GNU
157.28 + * General Public License Version 2 only ("GPL") or the Common
157.29 + * Development and Distribution License("CDDL") (collectively, the
157.30 + * "License"). You may not use this file except in compliance with the
157.31 + * License. You can obtain a copy of the License at
157.32 + * http://www.netbeans.org/cddl-gplv2.html
157.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
157.34 + * specific language governing permissions and limitations under the
157.35 + * License. When distributing the software, include this License Header
157.36 + * Notice in each file and include the License file at
157.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
157.38 + * particular file as subject to the "Classpath" exception as provided
157.39 + * by Oracle in the GPL Version 2 section of the License file that
157.40 + * accompanied this code. If applicable, add the following below the
157.41 + * License Header, with the fields enclosed by brackets [] replaced by
157.42 + * your own identifying information:
157.43 + * "Portions Copyrighted [year] [name of copyright owner]"
157.44 + *
157.45 + * Contributor(s):
157.46 + *
157.47 + * The Original Software is NetBeans. The Initial Developer of the Original
157.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
157.49 + *
157.50 + * If you wish your version of this file to be governed by only the CDDL
157.51 + * or only the GPL Version 2, indicate your decision by adding
157.52 + * "[Contributor] elects to include this software in this distribution
157.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
157.54 + * single choice of license, a recipient has the option to distribute
157.55 + * your version of this file under either the CDDL, the GPL Version 2 or
157.56 + * to extend the choice of license to its licensees as provided above.
157.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
157.58 + * Version 2 license, then the option applies only if the new code is
157.59 + * made subject to such option by the copyright holder.
157.60 */
157.61 package net.java.html.json;
157.62
158.1 --- a/json/src/test/java/net/java/html/json/PrimitiveArrayTest.java Thu Dec 19 17:11:01 2013 +0100
158.2 +++ b/json/src/test/java/net/java/html/json/PrimitiveArrayTest.java Tue Jan 07 08:21:57 2014 +0100
158.3 @@ -1,25 +1,48 @@
158.4 /**
158.5 - * HTML via Java(tm) Language Bindings
158.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
158.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
158.8 *
158.9 - * This program is free software: you can redistribute it and/or modify
158.10 - * it under the terms of the GNU General Public License as published by
158.11 - * the Free Software Foundation, version 2 of the License.
158.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
158.13 *
158.14 - * This program is distributed in the hope that it will be useful,
158.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
158.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
158.17 - * GNU General Public License for more details. apidesign.org
158.18 - * designates this particular file as subject to the
158.19 - * "Classpath" exception as provided by apidesign.org
158.20 - * in the License file that accompanied this code.
158.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
158.22 + * Other names may be trademarks of their respective owners.
158.23 *
158.24 - * You should have received a copy of the GNU General Public License
158.25 - * along with this program. Look for COPYING file in the top folder.
158.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
158.27 + * The contents of this file are subject to the terms of either the GNU
158.28 + * General Public License Version 2 only ("GPL") or the Common
158.29 + * Development and Distribution License("CDDL") (collectively, the
158.30 + * "License"). You may not use this file except in compliance with the
158.31 + * License. You can obtain a copy of the License at
158.32 + * http://www.netbeans.org/cddl-gplv2.html
158.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
158.34 + * specific language governing permissions and limitations under the
158.35 + * License. When distributing the software, include this License Header
158.36 + * Notice in each file and include the License file at
158.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
158.38 + * particular file as subject to the "Classpath" exception as provided
158.39 + * by Oracle in the GPL Version 2 section of the License file that
158.40 + * accompanied this code. If applicable, add the following below the
158.41 + * License Header, with the fields enclosed by brackets [] replaced by
158.42 + * your own identifying information:
158.43 + * "Portions Copyrighted [year] [name of copyright owner]"
158.44 + *
158.45 + * Contributor(s):
158.46 + *
158.47 + * The Original Software is NetBeans. The Initial Developer of the Original
158.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
158.49 + *
158.50 + * If you wish your version of this file to be governed by only the CDDL
158.51 + * or only the GPL Version 2, indicate your decision by adding
158.52 + * "[Contributor] elects to include this software in this distribution
158.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
158.54 + * single choice of license, a recipient has the option to distribute
158.55 + * your version of this file under either the CDDL, the GPL Version 2 or
158.56 + * to extend the choice of license to its licensees as provided above.
158.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
158.58 + * Version 2 license, then the option applies only if the new code is
158.59 + * made subject to such option by the copyright holder.
158.60 */
158.61 package net.java.html.json;
158.62
158.63 +import java.util.List;
158.64 import org.testng.Assert;
158.65 import org.testng.annotations.Test;
158.66
158.67 @@ -31,11 +54,16 @@
158.68 @Property(name = "array", type = byte.class, array = true)
158.69 })
158.70 public class PrimitiveArrayTest {
158.71 + @ComputedProperty static int length(List<Byte> array) {
158.72 + return array.size();
158.73 + }
158.74 +
158.75 @Test public void generatedConstructorWithPrimitiveType() {
158.76 byte[] arr = new byte[10];
158.77 arr[3] = 10;
158.78 ByteArray a = new ByteArray(arr);
158.79 Assert.assertEquals(a.getArray().size(), 10, "Ten elements");
158.80 Assert.assertEquals(a.getArray().get(3).byteValue(), 10, "Value ten");
158.81 + Assert.assertEquals(a.getLength(), 10, "Derived property is OK too");
158.82 }
158.83 }
159.1 --- a/json/src/test/java/net/java/html/json/Sex.java Thu Dec 19 17:11:01 2013 +0100
159.2 +++ b/json/src/test/java/net/java/html/json/Sex.java Tue Jan 07 08:21:57 2014 +0100
159.3 @@ -1,22 +1,44 @@
159.4 /**
159.5 - * HTML via Java(tm) Language Bindings
159.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
159.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
159.8 *
159.9 - * This program is free software: you can redistribute it and/or modify
159.10 - * it under the terms of the GNU General Public License as published by
159.11 - * the Free Software Foundation, version 2 of the License.
159.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
159.13 *
159.14 - * This program is distributed in the hope that it will be useful,
159.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
159.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
159.17 - * GNU General Public License for more details. apidesign.org
159.18 - * designates this particular file as subject to the
159.19 - * "Classpath" exception as provided by apidesign.org
159.20 - * in the License file that accompanied this code.
159.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
159.22 + * Other names may be trademarks of their respective owners.
159.23 *
159.24 - * You should have received a copy of the GNU General Public License
159.25 - * along with this program. Look for COPYING file in the top folder.
159.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
159.27 + * The contents of this file are subject to the terms of either the GNU
159.28 + * General Public License Version 2 only ("GPL") or the Common
159.29 + * Development and Distribution License("CDDL") (collectively, the
159.30 + * "License"). You may not use this file except in compliance with the
159.31 + * License. You can obtain a copy of the License at
159.32 + * http://www.netbeans.org/cddl-gplv2.html
159.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
159.34 + * specific language governing permissions and limitations under the
159.35 + * License. When distributing the software, include this License Header
159.36 + * Notice in each file and include the License file at
159.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
159.38 + * particular file as subject to the "Classpath" exception as provided
159.39 + * by Oracle in the GPL Version 2 section of the License file that
159.40 + * accompanied this code. If applicable, add the following below the
159.41 + * License Header, with the fields enclosed by brackets [] replaced by
159.42 + * your own identifying information:
159.43 + * "Portions Copyrighted [year] [name of copyright owner]"
159.44 + *
159.45 + * Contributor(s):
159.46 + *
159.47 + * The Original Software is NetBeans. The Initial Developer of the Original
159.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
159.49 + *
159.50 + * If you wish your version of this file to be governed by only the CDDL
159.51 + * or only the GPL Version 2, indicate your decision by adding
159.52 + * "[Contributor] elects to include this software in this distribution
159.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
159.54 + * single choice of license, a recipient has the option to distribute
159.55 + * your version of this file under either the CDDL, the GPL Version 2 or
159.56 + * to extend the choice of license to its licensees as provided above.
159.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
159.58 + * Version 2 license, then the option applies only if the new code is
159.59 + * made subject to such option by the copyright holder.
159.60 */
159.61 package net.java.html.json;
159.62
160.1 --- a/json/src/test/java/net/java/html/json/TypesTest.java Thu Dec 19 17:11:01 2013 +0100
160.2 +++ b/json/src/test/java/net/java/html/json/TypesTest.java Tue Jan 07 08:21:57 2014 +0100
160.3 @@ -1,22 +1,44 @@
160.4 /**
160.5 - * HTML via Java(tm) Language Bindings
160.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
160.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
160.8 *
160.9 - * This program is free software: you can redistribute it and/or modify
160.10 - * it under the terms of the GNU General Public License as published by
160.11 - * the Free Software Foundation, version 2 of the License.
160.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
160.13 *
160.14 - * This program is distributed in the hope that it will be useful,
160.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
160.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
160.17 - * GNU General Public License for more details. apidesign.org
160.18 - * designates this particular file as subject to the
160.19 - * "Classpath" exception as provided by apidesign.org
160.20 - * in the License file that accompanied this code.
160.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
160.22 + * Other names may be trademarks of their respective owners.
160.23 *
160.24 - * You should have received a copy of the GNU General Public License
160.25 - * along with this program. Look for COPYING file in the top folder.
160.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
160.27 + * The contents of this file are subject to the terms of either the GNU
160.28 + * General Public License Version 2 only ("GPL") or the Common
160.29 + * Development and Distribution License("CDDL") (collectively, the
160.30 + * "License"). You may not use this file except in compliance with the
160.31 + * License. You can obtain a copy of the License at
160.32 + * http://www.netbeans.org/cddl-gplv2.html
160.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
160.34 + * specific language governing permissions and limitations under the
160.35 + * License. When distributing the software, include this License Header
160.36 + * Notice in each file and include the License file at
160.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
160.38 + * particular file as subject to the "Classpath" exception as provided
160.39 + * by Oracle in the GPL Version 2 section of the License file that
160.40 + * accompanied this code. If applicable, add the following below the
160.41 + * License Header, with the fields enclosed by brackets [] replaced by
160.42 + * your own identifying information:
160.43 + * "Portions Copyrighted [year] [name of copyright owner]"
160.44 + *
160.45 + * Contributor(s):
160.46 + *
160.47 + * The Original Software is NetBeans. The Initial Developer of the Original
160.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
160.49 + *
160.50 + * If you wish your version of this file to be governed by only the CDDL
160.51 + * or only the GPL Version 2, indicate your decision by adding
160.52 + * "[Contributor] elects to include this software in this distribution
160.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
160.54 + * single choice of license, a recipient has the option to distribute
160.55 + * your version of this file under either the CDDL, the GPL Version 2 or
160.56 + * to extend the choice of license to its licensees as provided above.
160.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
160.58 + * Version 2 license, then the option applies only if the new code is
160.59 + * made subject to such option by the copyright holder.
160.60 */
160.61 package net.java.html.json;
160.62
160.63 @@ -24,9 +46,9 @@
160.64 import java.util.Map;
160.65 import net.java.html.json.MapModelTest.One;
160.66 import org.apidesign.html.context.spi.Contexts;
160.67 -import org.apidesign.html.json.impl.WrapperObject;
160.68 import org.apidesign.html.json.spi.Technology;
160.69 import org.apidesign.html.json.spi.Transfer;
160.70 +import org.netbeans.html.json.impl.JSON;
160.71 import org.testng.annotations.BeforeMethod;
160.72 import org.testng.annotations.Test;
160.73 import static org.testng.Assert.*;
160.74 @@ -89,10 +111,10 @@
160.75 t.setFloatX(99f);
160.76 */
160.77
160.78 - Object json = WrapperObject.find(t);
160.79 + Object json = JSON.find(t);
160.80
160.81 Types copy = Models.bind(new Types(), c);
160.82 - Map copyMap = (Map) WrapperObject.find(copy);
160.83 + Map copyMap = (Map) JSON.find(copy);
160.84 One o = (One) copyMap.get("readFromEvent");
160.85 o.fb.call(null, json);
160.86
161.1 --- a/json/src/test/java/net/java/html/json/WebSocketCallTest.java Thu Dec 19 17:11:01 2013 +0100
161.2 +++ b/json/src/test/java/net/java/html/json/WebSocketCallTest.java Tue Jan 07 08:21:57 2014 +0100
161.3 @@ -1,22 +1,44 @@
161.4 /**
161.5 - * HTML via Java(tm) Language Bindings
161.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
161.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
161.8 *
161.9 - * This program is free software: you can redistribute it and/or modify
161.10 - * it under the terms of the GNU General Public License as published by
161.11 - * the Free Software Foundation, version 2 of the License.
161.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
161.13 *
161.14 - * This program is distributed in the hope that it will be useful,
161.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
161.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
161.17 - * GNU General Public License for more details. apidesign.org
161.18 - * designates this particular file as subject to the
161.19 - * "Classpath" exception as provided by apidesign.org
161.20 - * in the License file that accompanied this code.
161.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
161.22 + * Other names may be trademarks of their respective owners.
161.23 *
161.24 - * You should have received a copy of the GNU General Public License
161.25 - * along with this program. Look for COPYING file in the top folder.
161.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
161.27 + * The contents of this file are subject to the terms of either the GNU
161.28 + * General Public License Version 2 only ("GPL") or the Common
161.29 + * Development and Distribution License("CDDL") (collectively, the
161.30 + * "License"). You may not use this file except in compliance with the
161.31 + * License. You can obtain a copy of the License at
161.32 + * http://www.netbeans.org/cddl-gplv2.html
161.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
161.34 + * specific language governing permissions and limitations under the
161.35 + * License. When distributing the software, include this License Header
161.36 + * Notice in each file and include the License file at
161.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
161.38 + * particular file as subject to the "Classpath" exception as provided
161.39 + * by Oracle in the GPL Version 2 section of the License file that
161.40 + * accompanied this code. If applicable, add the following below the
161.41 + * License Header, with the fields enclosed by brackets [] replaced by
161.42 + * your own identifying information:
161.43 + * "Portions Copyrighted [year] [name of copyright owner]"
161.44 + *
161.45 + * Contributor(s):
161.46 + *
161.47 + * The Original Software is NetBeans. The Initial Developer of the Original
161.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
161.49 + *
161.50 + * If you wish your version of this file to be governed by only the CDDL
161.51 + * or only the GPL Version 2, indicate your decision by adding
161.52 + * "[Contributor] elects to include this software in this distribution
161.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
161.54 + * single choice of license, a recipient has the option to distribute
161.55 + * your version of this file under either the CDDL, the GPL Version 2 or
161.56 + * to extend the choice of license to its licensees as provided above.
161.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
161.58 + * Version 2 license, then the option applies only if the new code is
161.59 + * made subject to such option by the copyright holder.
161.60 */
161.61 package net.java.html.json;
161.62
162.1 --- a/json/src/test/java/org/apidesign/html/json/impl/ConstructorTest.java Thu Dec 19 17:11:01 2013 +0100
162.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
162.3 @@ -1,58 +0,0 @@
162.4 -/**
162.5 - * HTML via Java(tm) Language Bindings
162.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
162.7 - *
162.8 - * This program is free software: you can redistribute it and/or modify
162.9 - * it under the terms of the GNU General Public License as published by
162.10 - * the Free Software Foundation, version 2 of the License.
162.11 - *
162.12 - * This program is distributed in the hope that it will be useful,
162.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
162.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
162.15 - * GNU General Public License for more details. apidesign.org
162.16 - * designates this particular file as subject to the
162.17 - * "Classpath" exception as provided by apidesign.org
162.18 - * in the License file that accompanied this code.
162.19 - *
162.20 - * You should have received a copy of the GNU General Public License
162.21 - * along with this program. Look for COPYING file in the top folder.
162.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
162.23 - */
162.24 -package org.apidesign.html.json.impl;
162.25 -
162.26 -import net.java.html.json.Model;
162.27 -import net.java.html.json.Property;
162.28 -import static org.testng.Assert.assertNotNull;
162.29 -import static org.testng.Assert.assertEquals;
162.30 -import org.testng.annotations.Test;
162.31 -
162.32 -/**
162.33 - *
162.34 - * @author Jaroslav Tulach <jtulach@netbeans.org>
162.35 - */
162.36 -@Model(className="Man", properties={
162.37 - @Property(name = "name", type = String.class),
162.38 - @Property(name = "other", type = Address.class, array = true),
162.39 - @Property(name = "primary", type = Address.class),
162.40 - @Property(name = "childrenNames", type = String.class, array = true)
162.41 -})
162.42 -public class ConstructorTest {
162.43 - @Model(className = "Address", properties = {
162.44 - @Property(name = "place", type = String.class)
162.45 - })
162.46 - static final class AddressModel {
162.47 - }
162.48 -
162.49 - @Test public void initializedByDefault() {
162.50 - Man m = new Man();
162.51 - assertNotNull(m.getPrimary(), "Single subobjects are initialized");
162.52 - }
162.53 -
162.54 - @Test public void hasRichConstructor() {
162.55 - Man m = new Man("Jarda", new Address("home"), new Address("work"), new Address("hotel"));
162.56 - assertEquals(m.getName(), "Jarda");
162.57 - assertNotNull(m.getPrimary(), "Primary address specified");
162.58 - assertNotNull(m.getPrimary().getPlace(), "home");
162.59 - assertEquals(m.getOther().size(), 2, "Two other addresses");
162.60 - }
162.61 -}
163.1 --- a/json/src/test/java/org/apidesign/html/json/impl/EmployeeImpl.java Thu Dec 19 17:11:01 2013 +0100
163.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
163.3 @@ -1,42 +0,0 @@
163.4 -/**
163.5 - * HTML via Java(tm) Language Bindings
163.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
163.7 - *
163.8 - * This program is free software: you can redistribute it and/or modify
163.9 - * it under the terms of the GNU General Public License as published by
163.10 - * the Free Software Foundation, version 2 of the License.
163.11 - *
163.12 - * This program is distributed in the hope that it will be useful,
163.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
163.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
163.15 - * GNU General Public License for more details. apidesign.org
163.16 - * designates this particular file as subject to the
163.17 - * "Classpath" exception as provided by apidesign.org
163.18 - * in the License file that accompanied this code.
163.19 - *
163.20 - * You should have received a copy of the GNU General Public License
163.21 - * along with this program. Look for COPYING file in the top folder.
163.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
163.23 - */
163.24 -
163.25 -package org.apidesign.html.json.impl;
163.26 -
163.27 -import net.java.html.json.Model;
163.28 -import net.java.html.json.OnReceive;
163.29 -import net.java.html.json.Person;
163.30 -import net.java.html.json.Property;
163.31 -
163.32 -/**
163.33 - *
163.34 - * @author Jaroslav Tulach <jtulach@netbeans.org>
163.35 - */
163.36 -@Model(className = "Employee", properties = {
163.37 - @Property(name = "person", type = Person.class),
163.38 - @Property(name = "employer", type = Employer.class)
163.39 -})
163.40 -public class EmployeeImpl {
163.41 - @OnReceive(url = "some/url")
163.42 - static void changePersonality(Employee e, Person p) {
163.43 - e.setPerson(p);
163.44 - }
163.45 -}
164.1 --- a/json/src/test/java/org/apidesign/html/json/impl/EmployerTest.java Thu Dec 19 17:11:01 2013 +0100
164.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
164.3 @@ -1,43 +0,0 @@
164.4 -/**
164.5 - * HTML via Java(tm) Language Bindings
164.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
164.7 - *
164.8 - * This program is free software: you can redistribute it and/or modify
164.9 - * it under the terms of the GNU General Public License as published by
164.10 - * the Free Software Foundation, version 2 of the License.
164.11 - *
164.12 - * This program is distributed in the hope that it will be useful,
164.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
164.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
164.15 - * GNU General Public License for more details. apidesign.org
164.16 - * designates this particular file as subject to the
164.17 - * "Classpath" exception as provided by apidesign.org
164.18 - * in the License file that accompanied this code.
164.19 - *
164.20 - * You should have received a copy of the GNU General Public License
164.21 - * along with this program. Look for COPYING file in the top folder.
164.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
164.23 - */
164.24 -package org.apidesign.html.json.impl;
164.25 -
164.26 -import net.java.html.BrwsrCtx;
164.27 -import net.java.html.json.Model;
164.28 -import net.java.html.json.Models;
164.29 -import net.java.html.json.Property;
164.30 -import org.testng.Assert;
164.31 -import org.testng.annotations.Test;
164.32 -
164.33 -/**
164.34 - *
164.35 - * @author Jaroslav Tulach <jtulach@netbeans.org>
164.36 - */
164.37 -@Model(className = "Employer", properties = {
164.38 - @Property(name = "name", type = String.class)
164.39 -})
164.40 -public class EmployerTest {
164.41 - @Test public void preLoadsTheClass() {
164.42 - Employer em = Models.fromRaw(BrwsrCtx.EMPTY, Employer.class, this);
164.43 - Assert.assertNotNull(em, "Class loaded");
164.44 - em.applyBindings();
164.45 - }
164.46 -}
165.1 --- a/json/src/test/java/org/apidesign/html/json/impl/JSONListTest.java Thu Dec 19 17:11:01 2013 +0100
165.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
165.3 @@ -1,170 +0,0 @@
165.4 -/**
165.5 - * HTML via Java(tm) Language Bindings
165.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
165.7 - *
165.8 - * This program is free software: you can redistribute it and/or modify
165.9 - * it under the terms of the GNU General Public License as published by
165.10 - * the Free Software Foundation, version 2 of the License.
165.11 - *
165.12 - * This program is distributed in the hope that it will be useful,
165.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
165.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
165.15 - * GNU General Public License for more details. apidesign.org
165.16 - * designates this particular file as subject to the
165.17 - * "Classpath" exception as provided by apidesign.org
165.18 - * in the License file that accompanied this code.
165.19 - *
165.20 - * You should have received a copy of the GNU General Public License
165.21 - * along with this program. Look for COPYING file in the top folder.
165.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
165.23 - */
165.24 -package org.apidesign.html.json.impl;
165.25 -
165.26 -import java.util.HashMap;
165.27 -import java.util.Map;
165.28 -import net.java.html.BrwsrCtx;
165.29 -import net.java.html.json.Models;
165.30 -import net.java.html.json.People;
165.31 -import net.java.html.json.Person;
165.32 -import net.java.html.json.Sex;
165.33 -import org.apidesign.html.context.spi.Contexts;
165.34 -import org.apidesign.html.json.spi.FunctionBinding;
165.35 -import org.apidesign.html.json.spi.PropertyBinding;
165.36 -import org.apidesign.html.json.spi.Technology;
165.37 -import static org.testng.Assert.*;
165.38 -import org.testng.annotations.BeforeMethod;
165.39 -import org.testng.annotations.Test;
165.40 -
165.41 -/**
165.42 - *
165.43 - * @author Jaroslav Tulach <jtulach@netbeans.org>
165.44 - */
165.45 -public class JSONListTest implements Technology<Object> {
165.46 - private boolean replaceArray;
165.47 - private final Map<String,PropertyBinding> bindings = new HashMap<String,PropertyBinding>();
165.48 -
165.49 - public JSONListTest() {
165.50 - }
165.51 -
165.52 - @BeforeMethod public void clear() {
165.53 - replaceArray = false;
165.54 - }
165.55 -
165.56 - @Test public void testConvertorOnAnObject() {
165.57 - BrwsrCtx c = Contexts.newBuilder().register(Technology.class, this, 1).build();
165.58 -
165.59 - Person p = Models.bind(new Person(), c);
165.60 - p.setFirstName("1");
165.61 - p.setLastName("2");
165.62 - p.setSex(Sex.MALE);
165.63 -
165.64 - Object real = WrapperObject.find(p);
165.65 - assertEquals(this, real, "I am the right model");
165.66 - }
165.67 -
165.68 - @Test public void testConvertorOnAnArray() {
165.69 - BrwsrCtx c = Contexts.newBuilder().register(Technology.class, this, 1).build();
165.70 -
165.71 - Person p = Models.bind(new Person(), c);
165.72 - p.setFirstName("1");
165.73 - p.setLastName("2");
165.74 - p.setSex(Sex.MALE);
165.75 -
165.76 - People people = Models.bind(new People(p), c).applyBindings();
165.77 - assertEquals(people.getInfo().toString(), "[{\"firstName\":\"1\",\"lastName\":\"2\",\"sex\":\"MALE\"}]", "Converted to real JSON");
165.78 -
165.79 - PropertyBinding pb = bindings.get("info");
165.80 - assertNotNull(pb, "Binding for info found");
165.81 -
165.82 - Object real = pb.getValue();
165.83 - assertTrue(real instanceof Object[], "It is an array: " + real);
165.84 - Object[] arr = (Object[])real;
165.85 - assertEquals(arr.length, 1, "Size is one");
165.86 - assertEquals(this, arr[0], "I am the right model");
165.87 - }
165.88 -
165.89 - @Test public void testNicknames() {
165.90 - BrwsrCtx c = Contexts.newBuilder().register(Technology.class, this, 1).build();
165.91 -
165.92 - People people = Models.bind(new People(), c).applyBindings();
165.93 - people.getNicknames().add("One");
165.94 - people.getNicknames().add("Two");
165.95 -
165.96 - PropertyBinding pb = bindings.get("nicknames");
165.97 - assertNotNull(pb, "Binding for info found");
165.98 -
165.99 - Object real = pb.getValue();
165.100 - assertTrue(real instanceof Object[], "It is an array: " + real);
165.101 - Object[] arr = (Object[])real;
165.102 - assertEquals(arr.length, 2, "Length two");
165.103 - assertEquals(arr[0], "One", "Text should be in the model");
165.104 - assertEquals(arr[1], "Two", "2nd text in the model");
165.105 - }
165.106 -
165.107 - @Test public void testConvertorOnAnArrayWithWrapper() {
165.108 - this.replaceArray = true;
165.109 - BrwsrCtx c = Contexts.newBuilder().register(Technology.class, this, 1).build();
165.110 -
165.111 - Person p = Models.bind(new Person(), c);
165.112 - p.setFirstName("1");
165.113 - p.setLastName("2");
165.114 - p.setSex(Sex.MALE);
165.115 -
165.116 - People people = Models.bind(new People(), c).applyBindings();
165.117 - people.getInfo().add(p);
165.118 -
165.119 - Object real = WrapperObject.find(people.getInfo());
165.120 - assertEquals(real, this, "I am the model of the array");
165.121 - }
165.122 -
165.123 - @Test public void bindingsOnArray() {
165.124 - this.replaceArray = true;
165.125 - BrwsrCtx c = Contexts.newBuilder().register(Technology.class, this, 1).build();
165.126 -
165.127 - People p = Models.bind(new People(), c).applyBindings();
165.128 - p.getAge().add(30);
165.129 -
165.130 - PropertyBinding pb = bindings.get("age");
165.131 - assertNotNull(pb, "There is a binding for age list");
165.132 -
165.133 - assertEquals(pb.getValue(), this, "I am the model of the array");
165.134 - }
165.135 -
165.136 - @Override
165.137 - public Object wrapModel(Object model) {
165.138 - return this;
165.139 - }
165.140 -
165.141 - @Override
165.142 - public void bind(PropertyBinding b, Object model, Object data) {
165.143 - bindings.put(b.getPropertyName(), b);
165.144 - }
165.145 -
165.146 - @Override
165.147 - public void valueHasMutated(Object data, String propertyName) {
165.148 - }
165.149 -
165.150 - @Override
165.151 - public void expose(FunctionBinding fb, Object model, Object d) {
165.152 - }
165.153 -
165.154 - @Override
165.155 - public void applyBindings(Object data) {
165.156 - }
165.157 -
165.158 - @Override
165.159 - public Object wrapArray(Object[] arr) {
165.160 - return replaceArray ? this : arr;
165.161 - }
165.162 -
165.163 - @Override
165.164 - public <M> M toModel(Class<M> modelClass, Object data) {
165.165 - return modelClass.cast(data);
165.166 - }
165.167 -
165.168 - @Override
165.169 - public void runSafe(Runnable r) {
165.170 - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
165.171 - }
165.172 -
165.173 -}
166.1 --- a/json/src/test/java/org/apidesign/html/json/impl/JSONTest.java Thu Dec 19 17:11:01 2013 +0100
166.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
166.3 @@ -1,62 +0,0 @@
166.4 -/**
166.5 - * HTML via Java(tm) Language Bindings
166.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
166.7 - *
166.8 - * This program is free software: you can redistribute it and/or modify
166.9 - * it under the terms of the GNU General Public License as published by
166.10 - * the Free Software Foundation, version 2 of the License.
166.11 - *
166.12 - * This program is distributed in the hope that it will be useful,
166.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
166.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
166.15 - * GNU General Public License for more details. apidesign.org
166.16 - * designates this particular file as subject to the
166.17 - * "Classpath" exception as provided by apidesign.org
166.18 - * in the License file that accompanied this code.
166.19 - *
166.20 - * You should have received a copy of the GNU General Public License
166.21 - * along with this program. Look for COPYING file in the top folder.
166.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
166.23 - */
166.24 -package org.apidesign.html.json.impl;
166.25 -
166.26 -import static org.testng.Assert.*;
166.27 -import org.testng.annotations.Test;
166.28 -
166.29 -/**
166.30 - *
166.31 - * @author Jaroslav Tulach <jtulach@netbeans.org>
166.32 - */
166.33 -public class JSONTest {
166.34 -
166.35 - public JSONTest() {
166.36 - }
166.37 -
166.38 - @Test public void longToStringValue() {
166.39 - assertEquals(JSON.stringValue(Long.valueOf(1)), "1");
166.40 - }
166.41 -
166.42 - @Test public void booleanIsSortOfNumber() {
166.43 - assertEquals(JSON.numberValue(Boolean.TRUE), Integer.valueOf(1));
166.44 - assertEquals(JSON.numberValue(Boolean.FALSE), Integer.valueOf(0));
166.45 - }
166.46 -
166.47 - @Test public void numberToChar() {
166.48 - assertEquals(JSON.charValue(65), Character.valueOf('A'));
166.49 - }
166.50 - @Test public void booleanToChar() {
166.51 - assertEquals(JSON.charValue(false), Character.valueOf((char)0));
166.52 - assertEquals(JSON.charValue(true), Character.valueOf((char)1));
166.53 - }
166.54 - @Test public void stringToChar() {
166.55 - assertEquals(JSON.charValue("Ahoj"), Character.valueOf('A'));
166.56 - }
166.57 - @Test public void stringToBoolean() {
166.58 - assertEquals(JSON.boolValue("false"), Boolean.FALSE);
166.59 - assertEquals(JSON.boolValue("True"), Boolean.TRUE);
166.60 - }
166.61 - @Test public void numberToBoolean() {
166.62 - assertEquals(JSON.boolValue(0), Boolean.FALSE);
166.63 - assertEquals(JSON.boolValue(1), Boolean.TRUE);
166.64 - }
166.65 -}
167.1 --- a/json/src/test/java/org/apidesign/html/json/impl/NoPropertiesTest.java Thu Dec 19 17:11:01 2013 +0100
167.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
167.3 @@ -1,33 +0,0 @@
167.4 -/**
167.5 - * HTML via Java(tm) Language Bindings
167.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
167.7 - *
167.8 - * This program is free software: you can redistribute it and/or modify
167.9 - * it under the terms of the GNU General Public License as published by
167.10 - * the Free Software Foundation, version 2 of the License.
167.11 - *
167.12 - * This program is distributed in the hope that it will be useful,
167.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
167.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
167.15 - * GNU General Public License for more details. apidesign.org
167.16 - * designates this particular file as subject to the
167.17 - * "Classpath" exception as provided by apidesign.org
167.18 - * in the License file that accompanied this code.
167.19 - *
167.20 - * You should have received a copy of the GNU General Public License
167.21 - * along with this program. Look for COPYING file in the top folder.
167.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
167.23 - */
167.24 -package org.apidesign.html.json.impl;
167.25 -
167.26 -import net.java.html.json.Model;
167.27 -
167.28 -/** Originally could not compile.
167.29 - *
167.30 - * @author Jaroslav Tulach <jtulach@netbeans.org>
167.31 - */
167.32 -@Model(className="NoProperties", properties = {
167.33 -})
167.34 -public class NoPropertiesTest {
167.35 -
167.36 -}
168.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
168.2 +++ b/json/src/test/java/org/netbeans/html/json/impl/ConstructorTest.java Tue Jan 07 08:21:57 2014 +0100
168.3 @@ -0,0 +1,80 @@
168.4 +/**
168.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
168.6 + *
168.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
168.8 + *
168.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
168.10 + * Other names may be trademarks of their respective owners.
168.11 + *
168.12 + * The contents of this file are subject to the terms of either the GNU
168.13 + * General Public License Version 2 only ("GPL") or the Common
168.14 + * Development and Distribution License("CDDL") (collectively, the
168.15 + * "License"). You may not use this file except in compliance with the
168.16 + * License. You can obtain a copy of the License at
168.17 + * http://www.netbeans.org/cddl-gplv2.html
168.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
168.19 + * specific language governing permissions and limitations under the
168.20 + * License. When distributing the software, include this License Header
168.21 + * Notice in each file and include the License file at
168.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
168.23 + * particular file as subject to the "Classpath" exception as provided
168.24 + * by Oracle in the GPL Version 2 section of the License file that
168.25 + * accompanied this code. If applicable, add the following below the
168.26 + * License Header, with the fields enclosed by brackets [] replaced by
168.27 + * your own identifying information:
168.28 + * "Portions Copyrighted [year] [name of copyright owner]"
168.29 + *
168.30 + * Contributor(s):
168.31 + *
168.32 + * The Original Software is NetBeans. The Initial Developer of the Original
168.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
168.34 + *
168.35 + * If you wish your version of this file to be governed by only the CDDL
168.36 + * or only the GPL Version 2, indicate your decision by adding
168.37 + * "[Contributor] elects to include this software in this distribution
168.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
168.39 + * single choice of license, a recipient has the option to distribute
168.40 + * your version of this file under either the CDDL, the GPL Version 2 or
168.41 + * to extend the choice of license to its licensees as provided above.
168.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
168.43 + * Version 2 license, then the option applies only if the new code is
168.44 + * made subject to such option by the copyright holder.
168.45 + */
168.46 +package org.netbeans.html.json.impl;
168.47 +
168.48 +import net.java.html.json.Model;
168.49 +import net.java.html.json.Property;
168.50 +import static org.testng.Assert.assertNotNull;
168.51 +import static org.testng.Assert.assertEquals;
168.52 +import org.testng.annotations.Test;
168.53 +
168.54 +/**
168.55 + *
168.56 + * @author Jaroslav Tulach <jtulach@netbeans.org>
168.57 + */
168.58 +@Model(className="Man", properties={
168.59 + @Property(name = "name", type = String.class),
168.60 + @Property(name = "other", type = Address.class, array = true),
168.61 + @Property(name = "primary", type = Address.class),
168.62 + @Property(name = "childrenNames", type = String.class, array = true)
168.63 +})
168.64 +public class ConstructorTest {
168.65 + @Model(className = "Address", properties = {
168.66 + @Property(name = "place", type = String.class)
168.67 + })
168.68 + static final class AddressModel {
168.69 + }
168.70 +
168.71 + @Test public void initializedByDefault() {
168.72 + Man m = new Man();
168.73 + assertNotNull(m.getPrimary(), "Single subobjects are initialized");
168.74 + }
168.75 +
168.76 + @Test public void hasRichConstructor() {
168.77 + Man m = new Man("Jarda", new Address("home"), new Address("work"), new Address("hotel"));
168.78 + assertEquals(m.getName(), "Jarda");
168.79 + assertNotNull(m.getPrimary(), "Primary address specified");
168.80 + assertNotNull(m.getPrimary().getPlace(), "home");
168.81 + assertEquals(m.getOther().size(), 2, "Two other addresses");
168.82 + }
168.83 +}
169.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
169.2 +++ b/json/src/test/java/org/netbeans/html/json/impl/EmployeeImpl.java Tue Jan 07 08:21:57 2014 +0100
169.3 @@ -0,0 +1,63 @@
169.4 +/**
169.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
169.6 + *
169.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
169.8 + *
169.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
169.10 + * Other names may be trademarks of their respective owners.
169.11 + *
169.12 + * The contents of this file are subject to the terms of either the GNU
169.13 + * General Public License Version 2 only ("GPL") or the Common
169.14 + * Development and Distribution License("CDDL") (collectively, the
169.15 + * "License"). You may not use this file except in compliance with the
169.16 + * License. You can obtain a copy of the License at
169.17 + * http://www.netbeans.org/cddl-gplv2.html
169.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
169.19 + * specific language governing permissions and limitations under the
169.20 + * License. When distributing the software, include this License Header
169.21 + * Notice in each file and include the License file at
169.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
169.23 + * particular file as subject to the "Classpath" exception as provided
169.24 + * by Oracle in the GPL Version 2 section of the License file that
169.25 + * accompanied this code. If applicable, add the following below the
169.26 + * License Header, with the fields enclosed by brackets [] replaced by
169.27 + * your own identifying information:
169.28 + * "Portions Copyrighted [year] [name of copyright owner]"
169.29 + *
169.30 + * Contributor(s):
169.31 + *
169.32 + * The Original Software is NetBeans. The Initial Developer of the Original
169.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
169.34 + *
169.35 + * If you wish your version of this file to be governed by only the CDDL
169.36 + * or only the GPL Version 2, indicate your decision by adding
169.37 + * "[Contributor] elects to include this software in this distribution
169.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
169.39 + * single choice of license, a recipient has the option to distribute
169.40 + * your version of this file under either the CDDL, the GPL Version 2 or
169.41 + * to extend the choice of license to its licensees as provided above.
169.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
169.43 + * Version 2 license, then the option applies only if the new code is
169.44 + * made subject to such option by the copyright holder.
169.45 + */
169.46 +package org.netbeans.html.json.impl;
169.47 +
169.48 +import net.java.html.json.Model;
169.49 +import net.java.html.json.OnReceive;
169.50 +import net.java.html.json.Person;
169.51 +import net.java.html.json.Property;
169.52 +
169.53 +/**
169.54 + *
169.55 + * @author Jaroslav Tulach <jtulach@netbeans.org>
169.56 + */
169.57 +@Model(className = "Employee", properties = {
169.58 + @Property(name = "person", type = Person.class),
169.59 + @Property(name = "employer", type = Employer.class)
169.60 +})
169.61 +public class EmployeeImpl {
169.62 + @OnReceive(url = "some/url")
169.63 + static void changePersonality(Employee e, Person p) {
169.64 + e.setPerson(p);
169.65 + }
169.66 +}
170.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
170.2 +++ b/json/src/test/java/org/netbeans/html/json/impl/EmployerTest.java Tue Jan 07 08:21:57 2014 +0100
170.3 @@ -0,0 +1,65 @@
170.4 +/**
170.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
170.6 + *
170.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
170.8 + *
170.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
170.10 + * Other names may be trademarks of their respective owners.
170.11 + *
170.12 + * The contents of this file are subject to the terms of either the GNU
170.13 + * General Public License Version 2 only ("GPL") or the Common
170.14 + * Development and Distribution License("CDDL") (collectively, the
170.15 + * "License"). You may not use this file except in compliance with the
170.16 + * License. You can obtain a copy of the License at
170.17 + * http://www.netbeans.org/cddl-gplv2.html
170.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
170.19 + * specific language governing permissions and limitations under the
170.20 + * License. When distributing the software, include this License Header
170.21 + * Notice in each file and include the License file at
170.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
170.23 + * particular file as subject to the "Classpath" exception as provided
170.24 + * by Oracle in the GPL Version 2 section of the License file that
170.25 + * accompanied this code. If applicable, add the following below the
170.26 + * License Header, with the fields enclosed by brackets [] replaced by
170.27 + * your own identifying information:
170.28 + * "Portions Copyrighted [year] [name of copyright owner]"
170.29 + *
170.30 + * Contributor(s):
170.31 + *
170.32 + * The Original Software is NetBeans. The Initial Developer of the Original
170.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
170.34 + *
170.35 + * If you wish your version of this file to be governed by only the CDDL
170.36 + * or only the GPL Version 2, indicate your decision by adding
170.37 + * "[Contributor] elects to include this software in this distribution
170.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
170.39 + * single choice of license, a recipient has the option to distribute
170.40 + * your version of this file under either the CDDL, the GPL Version 2 or
170.41 + * to extend the choice of license to its licensees as provided above.
170.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
170.43 + * Version 2 license, then the option applies only if the new code is
170.44 + * made subject to such option by the copyright holder.
170.45 + */
170.46 +package org.netbeans.html.json.impl;
170.47 +
170.48 +import net.java.html.BrwsrCtx;
170.49 +import net.java.html.json.Model;
170.50 +import net.java.html.json.Models;
170.51 +import net.java.html.json.Property;
170.52 +import org.testng.Assert;
170.53 +import org.testng.annotations.Test;
170.54 +
170.55 +/**
170.56 + *
170.57 + * @author Jaroslav Tulach <jtulach@netbeans.org>
170.58 + */
170.59 +@Model(className = "Employer", properties = {
170.60 + @Property(name = "name", type = String.class)
170.61 +})
170.62 +public class EmployerTest {
170.63 + @Test public void preLoadsTheClass() {
170.64 + Employer em = Models.fromRaw(BrwsrCtx.EMPTY, Employer.class, this);
170.65 + Assert.assertNotNull(em, "Class loaded");
170.66 + em.applyBindings();
170.67 + }
170.68 +}
171.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
171.2 +++ b/json/src/test/java/org/netbeans/html/json/impl/JSONListTest.java Tue Jan 07 08:21:57 2014 +0100
171.3 @@ -0,0 +1,192 @@
171.4 +/**
171.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
171.6 + *
171.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
171.8 + *
171.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
171.10 + * Other names may be trademarks of their respective owners.
171.11 + *
171.12 + * The contents of this file are subject to the terms of either the GNU
171.13 + * General Public License Version 2 only ("GPL") or the Common
171.14 + * Development and Distribution License("CDDL") (collectively, the
171.15 + * "License"). You may not use this file except in compliance with the
171.16 + * License. You can obtain a copy of the License at
171.17 + * http://www.netbeans.org/cddl-gplv2.html
171.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
171.19 + * specific language governing permissions and limitations under the
171.20 + * License. When distributing the software, include this License Header
171.21 + * Notice in each file and include the License file at
171.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
171.23 + * particular file as subject to the "Classpath" exception as provided
171.24 + * by Oracle in the GPL Version 2 section of the License file that
171.25 + * accompanied this code. If applicable, add the following below the
171.26 + * License Header, with the fields enclosed by brackets [] replaced by
171.27 + * your own identifying information:
171.28 + * "Portions Copyrighted [year] [name of copyright owner]"
171.29 + *
171.30 + * Contributor(s):
171.31 + *
171.32 + * The Original Software is NetBeans. The Initial Developer of the Original
171.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
171.34 + *
171.35 + * If you wish your version of this file to be governed by only the CDDL
171.36 + * or only the GPL Version 2, indicate your decision by adding
171.37 + * "[Contributor] elects to include this software in this distribution
171.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
171.39 + * single choice of license, a recipient has the option to distribute
171.40 + * your version of this file under either the CDDL, the GPL Version 2 or
171.41 + * to extend the choice of license to its licensees as provided above.
171.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
171.43 + * Version 2 license, then the option applies only if the new code is
171.44 + * made subject to such option by the copyright holder.
171.45 + */
171.46 +package org.netbeans.html.json.impl;
171.47 +
171.48 +import java.util.HashMap;
171.49 +import java.util.Map;
171.50 +import net.java.html.BrwsrCtx;
171.51 +import net.java.html.json.Models;
171.52 +import net.java.html.json.People;
171.53 +import net.java.html.json.Person;
171.54 +import net.java.html.json.Sex;
171.55 +import org.apidesign.html.context.spi.Contexts;
171.56 +import org.apidesign.html.json.spi.FunctionBinding;
171.57 +import org.apidesign.html.json.spi.PropertyBinding;
171.58 +import org.apidesign.html.json.spi.Technology;
171.59 +import static org.testng.Assert.*;
171.60 +import org.testng.annotations.BeforeMethod;
171.61 +import org.testng.annotations.Test;
171.62 +
171.63 +/**
171.64 + *
171.65 + * @author Jaroslav Tulach <jtulach@netbeans.org>
171.66 + */
171.67 +public class JSONListTest implements Technology<Object> {
171.68 + private boolean replaceArray;
171.69 + private final Map<String,PropertyBinding> bindings = new HashMap<String,PropertyBinding>();
171.70 +
171.71 + public JSONListTest() {
171.72 + }
171.73 +
171.74 + @BeforeMethod public void clear() {
171.75 + replaceArray = false;
171.76 + }
171.77 +
171.78 + @Test public void testConvertorOnAnObject() {
171.79 + BrwsrCtx c = Contexts.newBuilder().register(Technology.class, this, 1).build();
171.80 +
171.81 + Person p = Models.bind(new Person(), c);
171.82 + p.setFirstName("1");
171.83 + p.setLastName("2");
171.84 + p.setSex(Sex.MALE);
171.85 +
171.86 + Object real = JSON.find(p);
171.87 + assertEquals(this, real, "I am the right model");
171.88 + }
171.89 +
171.90 + @Test public void testConvertorOnAnArray() {
171.91 + BrwsrCtx c = Contexts.newBuilder().register(Technology.class, this, 1).build();
171.92 +
171.93 + Person p = Models.bind(new Person(), c);
171.94 + p.setFirstName("1");
171.95 + p.setLastName("2");
171.96 + p.setSex(Sex.MALE);
171.97 +
171.98 + People people = Models.bind(new People(p), c).applyBindings();
171.99 + assertEquals(people.getInfo().toString(), "[{\"firstName\":\"1\",\"lastName\":\"2\",\"sex\":\"MALE\"}]", "Converted to real JSON");
171.100 +
171.101 + PropertyBinding pb = bindings.get("info");
171.102 + assertNotNull(pb, "Binding for info found");
171.103 +
171.104 + Object real = pb.getValue();
171.105 + assertTrue(real instanceof Object[], "It is an array: " + real);
171.106 + Object[] arr = (Object[])real;
171.107 + assertEquals(arr.length, 1, "Size is one");
171.108 + assertEquals(this, arr[0], "I am the right model");
171.109 + }
171.110 +
171.111 + @Test public void testNicknames() {
171.112 + BrwsrCtx c = Contexts.newBuilder().register(Technology.class, this, 1).build();
171.113 +
171.114 + People people = Models.bind(new People(), c).applyBindings();
171.115 + people.getNicknames().add("One");
171.116 + people.getNicknames().add("Two");
171.117 +
171.118 + PropertyBinding pb = bindings.get("nicknames");
171.119 + assertNotNull(pb, "Binding for info found");
171.120 +
171.121 + Object real = pb.getValue();
171.122 + assertTrue(real instanceof Object[], "It is an array: " + real);
171.123 + Object[] arr = (Object[])real;
171.124 + assertEquals(arr.length, 2, "Length two");
171.125 + assertEquals(arr[0], "One", "Text should be in the model");
171.126 + assertEquals(arr[1], "Two", "2nd text in the model");
171.127 + }
171.128 +
171.129 + @Test public void testConvertorOnAnArrayWithWrapper() {
171.130 + this.replaceArray = true;
171.131 + BrwsrCtx c = Contexts.newBuilder().register(Technology.class, this, 1).build();
171.132 +
171.133 + Person p = Models.bind(new Person(), c);
171.134 + p.setFirstName("1");
171.135 + p.setLastName("2");
171.136 + p.setSex(Sex.MALE);
171.137 +
171.138 + People people = Models.bind(new People(), c).applyBindings();
171.139 + people.getInfo().add(p);
171.140 +
171.141 + Object real = JSON.find(people.getInfo());
171.142 + assertEquals(real, this, "I am the model of the array");
171.143 + }
171.144 +
171.145 + @Test public void bindingsOnArray() {
171.146 + this.replaceArray = true;
171.147 + BrwsrCtx c = Contexts.newBuilder().register(Technology.class, this, 1).build();
171.148 +
171.149 + People p = Models.bind(new People(), c).applyBindings();
171.150 + p.getAge().add(30);
171.151 +
171.152 + PropertyBinding pb = bindings.get("age");
171.153 + assertNotNull(pb, "There is a binding for age list");
171.154 +
171.155 + assertEquals(pb.getValue(), this, "I am the model of the array");
171.156 + }
171.157 +
171.158 + @Override
171.159 + public Object wrapModel(Object model) {
171.160 + return this;
171.161 + }
171.162 +
171.163 + @Override
171.164 + public void bind(PropertyBinding b, Object model, Object data) {
171.165 + bindings.put(b.getPropertyName(), b);
171.166 + }
171.167 +
171.168 + @Override
171.169 + public void valueHasMutated(Object data, String propertyName) {
171.170 + }
171.171 +
171.172 + @Override
171.173 + public void expose(FunctionBinding fb, Object model, Object d) {
171.174 + }
171.175 +
171.176 + @Override
171.177 + public void applyBindings(Object data) {
171.178 + }
171.179 +
171.180 + @Override
171.181 + public Object wrapArray(Object[] arr) {
171.182 + return replaceArray ? this : arr;
171.183 + }
171.184 +
171.185 + @Override
171.186 + public <M> M toModel(Class<M> modelClass, Object data) {
171.187 + return modelClass.cast(data);
171.188 + }
171.189 +
171.190 + @Override
171.191 + public void runSafe(Runnable r) {
171.192 + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
171.193 + }
171.194 +
171.195 +}
172.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
172.2 +++ b/json/src/test/java/org/netbeans/html/json/impl/JSONTest.java Tue Jan 07 08:21:57 2014 +0100
172.3 @@ -0,0 +1,84 @@
172.4 +/**
172.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
172.6 + *
172.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
172.8 + *
172.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
172.10 + * Other names may be trademarks of their respective owners.
172.11 + *
172.12 + * The contents of this file are subject to the terms of either the GNU
172.13 + * General Public License Version 2 only ("GPL") or the Common
172.14 + * Development and Distribution License("CDDL") (collectively, the
172.15 + * "License"). You may not use this file except in compliance with the
172.16 + * License. You can obtain a copy of the License at
172.17 + * http://www.netbeans.org/cddl-gplv2.html
172.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
172.19 + * specific language governing permissions and limitations under the
172.20 + * License. When distributing the software, include this License Header
172.21 + * Notice in each file and include the License file at
172.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
172.23 + * particular file as subject to the "Classpath" exception as provided
172.24 + * by Oracle in the GPL Version 2 section of the License file that
172.25 + * accompanied this code. If applicable, add the following below the
172.26 + * License Header, with the fields enclosed by brackets [] replaced by
172.27 + * your own identifying information:
172.28 + * "Portions Copyrighted [year] [name of copyright owner]"
172.29 + *
172.30 + * Contributor(s):
172.31 + *
172.32 + * The Original Software is NetBeans. The Initial Developer of the Original
172.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
172.34 + *
172.35 + * If you wish your version of this file to be governed by only the CDDL
172.36 + * or only the GPL Version 2, indicate your decision by adding
172.37 + * "[Contributor] elects to include this software in this distribution
172.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
172.39 + * single choice of license, a recipient has the option to distribute
172.40 + * your version of this file under either the CDDL, the GPL Version 2 or
172.41 + * to extend the choice of license to its licensees as provided above.
172.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
172.43 + * Version 2 license, then the option applies only if the new code is
172.44 + * made subject to such option by the copyright holder.
172.45 + */
172.46 +package org.netbeans.html.json.impl;
172.47 +
172.48 +import static org.testng.Assert.*;
172.49 +import org.testng.annotations.Test;
172.50 +
172.51 +/**
172.52 + *
172.53 + * @author Jaroslav Tulach <jtulach@netbeans.org>
172.54 + */
172.55 +public class JSONTest {
172.56 +
172.57 + public JSONTest() {
172.58 + }
172.59 +
172.60 + @Test public void longToStringValue() {
172.61 + assertEquals(JSON.stringValue(Long.valueOf(1)), "1");
172.62 + }
172.63 +
172.64 + @Test public void booleanIsSortOfNumber() {
172.65 + assertEquals(JSON.numberValue(Boolean.TRUE), Integer.valueOf(1));
172.66 + assertEquals(JSON.numberValue(Boolean.FALSE), Integer.valueOf(0));
172.67 + }
172.68 +
172.69 + @Test public void numberToChar() {
172.70 + assertEquals(JSON.charValue(65), Character.valueOf('A'));
172.71 + }
172.72 + @Test public void booleanToChar() {
172.73 + assertEquals(JSON.charValue(false), Character.valueOf((char)0));
172.74 + assertEquals(JSON.charValue(true), Character.valueOf((char)1));
172.75 + }
172.76 + @Test public void stringToChar() {
172.77 + assertEquals(JSON.charValue("Ahoj"), Character.valueOf('A'));
172.78 + }
172.79 + @Test public void stringToBoolean() {
172.80 + assertEquals(JSON.boolValue("false"), Boolean.FALSE);
172.81 + assertEquals(JSON.boolValue("True"), Boolean.TRUE);
172.82 + }
172.83 + @Test public void numberToBoolean() {
172.84 + assertEquals(JSON.boolValue(0), Boolean.FALSE);
172.85 + assertEquals(JSON.boolValue(1), Boolean.TRUE);
172.86 + }
172.87 +}
173.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
173.2 +++ b/json/src/test/java/org/netbeans/html/json/impl/NoPropertiesTest.java Tue Jan 07 08:21:57 2014 +0100
173.3 @@ -0,0 +1,55 @@
173.4 +/**
173.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
173.6 + *
173.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
173.8 + *
173.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
173.10 + * Other names may be trademarks of their respective owners.
173.11 + *
173.12 + * The contents of this file are subject to the terms of either the GNU
173.13 + * General Public License Version 2 only ("GPL") or the Common
173.14 + * Development and Distribution License("CDDL") (collectively, the
173.15 + * "License"). You may not use this file except in compliance with the
173.16 + * License. You can obtain a copy of the License at
173.17 + * http://www.netbeans.org/cddl-gplv2.html
173.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
173.19 + * specific language governing permissions and limitations under the
173.20 + * License. When distributing the software, include this License Header
173.21 + * Notice in each file and include the License file at
173.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
173.23 + * particular file as subject to the "Classpath" exception as provided
173.24 + * by Oracle in the GPL Version 2 section of the License file that
173.25 + * accompanied this code. If applicable, add the following below the
173.26 + * License Header, with the fields enclosed by brackets [] replaced by
173.27 + * your own identifying information:
173.28 + * "Portions Copyrighted [year] [name of copyright owner]"
173.29 + *
173.30 + * Contributor(s):
173.31 + *
173.32 + * The Original Software is NetBeans. The Initial Developer of the Original
173.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
173.34 + *
173.35 + * If you wish your version of this file to be governed by only the CDDL
173.36 + * or only the GPL Version 2, indicate your decision by adding
173.37 + * "[Contributor] elects to include this software in this distribution
173.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
173.39 + * single choice of license, a recipient has the option to distribute
173.40 + * your version of this file under either the CDDL, the GPL Version 2 or
173.41 + * to extend the choice of license to its licensees as provided above.
173.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
173.43 + * Version 2 license, then the option applies only if the new code is
173.44 + * made subject to such option by the copyright holder.
173.45 + */
173.46 +package org.netbeans.html.json.impl;
173.47 +
173.48 +import net.java.html.json.Model;
173.49 +
173.50 +/** Originally could not compile.
173.51 + *
173.52 + * @author Jaroslav Tulach <jtulach@netbeans.org>
173.53 + */
173.54 +@Model(className="NoProperties", properties = {
173.55 +})
173.56 +public class NoPropertiesTest {
173.57 +
173.58 +}
174.1 --- a/ko-archetype-test/pom.xml Thu Dec 19 17:11:01 2013 +0100
174.2 +++ b/ko-archetype-test/pom.xml Tue Jan 07 08:21:57 2014 +0100
174.3 @@ -2,11 +2,11 @@
174.4 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
174.5 <modelVersion>4.0.0</modelVersion>
174.6 <parent>
174.7 - <groupId>org.apidesign</groupId>
174.8 - <artifactId>html</artifactId>
174.9 + <groupId>org.netbeans.html</groupId>
174.10 + <artifactId>pom</artifactId>
174.11 <version>0.7-SNAPSHOT</version>
174.12 </parent>
174.13 - <groupId>org.apidesign.html</groupId>
174.14 + <groupId>org.netbeans.html</groupId>
174.15 <artifactId>ko-archetype-test</artifactId>
174.16 <version>0.7-SNAPSHOT</version>
174.17 <name>Knockout 4 Java Archetype Test</name>
175.1 --- a/ko-archetype-test/src/test/java/org/apidesign/html/archetype/test/ArchetypeVersionTest.java Thu Dec 19 17:11:01 2013 +0100
175.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
175.3 @@ -1,106 +0,0 @@
175.4 -/**
175.5 - * HTML via Java(tm) Language Bindings
175.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
175.7 - *
175.8 - * This program is free software: you can redistribute it and/or modify
175.9 - * it under the terms of the GNU General Public License as published by
175.10 - * the Free Software Foundation, version 2 of the License.
175.11 - *
175.12 - * This program is distributed in the hope that it will be useful,
175.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
175.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
175.15 - * GNU General Public License for more details. apidesign.org
175.16 - * designates this particular file as subject to the
175.17 - * "Classpath" exception as provided by apidesign.org
175.18 - * in the License file that accompanied this code.
175.19 - *
175.20 - * You should have received a copy of the GNU General Public License
175.21 - * along with this program. Look for COPYING file in the top folder.
175.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
175.23 - */
175.24 -package org.apidesign.html.archetype.test;
175.25 -
175.26 -import java.io.IOException;
175.27 -import java.net.URL;
175.28 -import javax.xml.XMLConstants;
175.29 -import javax.xml.parsers.DocumentBuilderFactory;
175.30 -import javax.xml.parsers.ParserConfigurationException;
175.31 -import javax.xml.xpath.XPathConstants;
175.32 -import javax.xml.xpath.XPathExpression;
175.33 -import javax.xml.xpath.XPathExpressionException;
175.34 -import javax.xml.xpath.XPathFactory;
175.35 -import javax.xml.xpath.XPathFactoryConfigurationException;
175.36 -import org.testng.annotations.Test;
175.37 -import static org.testng.Assert.*;
175.38 -import org.testng.annotations.BeforeClass;
175.39 -import org.w3c.dom.Document;
175.40 -import org.w3c.dom.NodeList;
175.41 -import org.xml.sax.SAXException;
175.42 -
175.43 -/**
175.44 - *
175.45 - * @author Jaroslav Tulach <jtulach@netbeans.org>
175.46 - */
175.47 -public class ArchetypeVersionTest {
175.48 - private String version;
175.49 -
175.50 - public ArchetypeVersionTest() {
175.51 - }
175.52 -
175.53 - @BeforeClass public void readCurrentVersion() throws Exception {
175.54 - version = findCurrentVersion();
175.55 - assertFalse(version.isEmpty(), "There should be some version string");
175.56 - }
175.57 -
175.58 -
175.59 - @Test public void testComparePomDepsVersions() throws Exception {
175.60 - final ClassLoader l = ArchetypeVersionTest.class.getClassLoader();
175.61 - URL r = l.getResource("archetype-resources/pom.xml");
175.62 - assertNotNull(r, "Archetype pom found");
175.63 -
175.64 - final XPathFactory fact = XPathFactory.newInstance();
175.65 - XPathExpression xp2 = fact.newXPath().compile(
175.66 - "//properties/net.java.html.version/text()"
175.67 - );
175.68 -
175.69 - Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(r.openStream());
175.70 - String arch = (String) xp2.evaluate(dom, XPathConstants.STRING);
175.71 -
175.72 - assertEquals(arch, version, "net.java.html.json dependency needs to be on latest version");
175.73 - }
175.74 -
175.75 - @Test public void testNbActions() throws Exception {
175.76 - final ClassLoader l = ArchetypeVersionTest.class.getClassLoader();
175.77 - URL r = l.getResource("archetype-resources/nbactions.xml");
175.78 - assertNotNull(r, "Archetype nb file found");
175.79 -
175.80 - final XPathFactory fact = XPathFactory.newInstance();
175.81 - XPathExpression xp2 = fact.newXPath().compile(
175.82 - "//goal/text()"
175.83 - );
175.84 -
175.85 - Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(r.openStream());
175.86 - NodeList goals = (NodeList) xp2.evaluate(dom, XPathConstants.NODESET);
175.87 -
175.88 - for (int i = 0; i < goals.getLength(); i++) {
175.89 - String s = goals.item(i).getTextContent();
175.90 - if (s.contains("apidesign")) {
175.91 - assertFalse(s.matches(".*apidesign.*[0-9].*"), "No numbers: " + s);
175.92 - }
175.93 - }
175.94 - }
175.95 -
175.96 - static String findCurrentVersion() throws XPathExpressionException, IOException, ParserConfigurationException, SAXException, XPathFactoryConfigurationException {
175.97 - final ClassLoader l = ArchetypeVersionTest.class.getClassLoader();
175.98 - URL u = l.getResource("META-INF/maven/org.apidesign.html/knockout4j-archetype/pom.xml");
175.99 - assertNotNull(u, "Own pom found: " + System.getProperty("java.class.path"));
175.100 -
175.101 - final XPathFactory fact = XPathFactory.newInstance();
175.102 - fact.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
175.103 -
175.104 - XPathExpression xp = fact.newXPath().compile("project/version/text()");
175.105 -
175.106 - Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(u.openStream());
175.107 - return xp.evaluate(dom);
175.108 - }
175.109 -}
176.1 --- a/ko-archetype-test/src/test/java/org/apidesign/html/archetype/test/VerifyArchetypeTest.java Thu Dec 19 17:11:01 2013 +0100
176.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
176.3 @@ -1,77 +0,0 @@
176.4 -/**
176.5 - * HTML via Java(tm) Language Bindings
176.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
176.7 - *
176.8 - * This program is free software: you can redistribute it and/or modify
176.9 - * it under the terms of the GNU General Public License as published by
176.10 - * the Free Software Foundation, version 2 of the License.
176.11 - *
176.12 - * This program is distributed in the hope that it will be useful,
176.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
176.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
176.15 - * GNU General Public License for more details. apidesign.org
176.16 - * designates this particular file as subject to the
176.17 - * "Classpath" exception as provided by apidesign.org
176.18 - * in the License file that accompanied this code.
176.19 - *
176.20 - * You should have received a copy of the GNU General Public License
176.21 - * along with this program. Look for COPYING file in the top folder.
176.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
176.23 - */
176.24 -package org.apidesign.html.archetype.test;
176.25 -
176.26 -import java.io.File;
176.27 -import java.util.Properties;
176.28 -import org.apache.maven.it.Verifier;
176.29 -import org.testng.annotations.Test;
176.30 -import static org.testng.Assert.*;
176.31 -
176.32 -/**
176.33 - *
176.34 - * @author Jaroslav Tulach <jtulach@netbeans.org>
176.35 - */
176.36 -public class VerifyArchetypeTest {
176.37 - @Test public void projectCompiles() throws Exception {
176.38 - final File dir = new File("target/tests/fxcompile/").getAbsoluteFile();
176.39 - generateFromArchetype(dir);
176.40 -
176.41 - File created = new File(dir, "o-a-test");
176.42 - assertTrue(created.isDirectory(), "Project created");
176.43 - assertTrue(new File(created, "pom.xml").isFile(), "Pom file is in there");
176.44 -
176.45 - Verifier v = new Verifier(created.getAbsolutePath());
176.46 - v.executeGoal("verify");
176.47 -
176.48 - v.verifyErrorFreeLog();
176.49 -
176.50 - for (String l : v.loadFile(v.getBasedir(), v.getLogFileName(), false)) {
176.51 - if (l.contains("j2js")) {
176.52 - fail("No pre-compilaton:\n" + l);
176.53 - }
176.54 - }
176.55 -
176.56 - v.verifyTextInLog("fxcompile/o-a-test/target/o-a-test-1.0-SNAPSHOT-html.java.net.zip");
176.57 - }
176.58 -
176.59 - private Verifier generateFromArchetype(final File dir, String... params) throws Exception {
176.60 - Verifier v = new Verifier(dir.getAbsolutePath());
176.61 - v.setAutoclean(false);
176.62 - v.setLogFileName("generate.log");
176.63 - v.deleteDirectory("");
176.64 - dir.mkdirs();
176.65 - Properties sysProp = v.getSystemProperties();
176.66 - sysProp.put("groupId", "org.apidesign.test");
176.67 - sysProp.put("artifactId", "o-a-test");
176.68 - sysProp.put("package", "org.apidesign.test.oat");
176.69 - sysProp.put("archetypeGroupId", "org.apidesign.html");
176.70 - sysProp.put("archetypeArtifactId", "knockout4j-archetype");
176.71 - sysProp.put("archetypeVersion", ArchetypeVersionTest.findCurrentVersion());
176.72 -
176.73 - for (String p : params) {
176.74 - v.addCliOption(p);
176.75 - }
176.76 - v.executeGoal("archetype:generate");
176.77 - v.verifyErrorFreeLog();
176.78 - return v;
176.79 - }
176.80 -}
177.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
177.2 +++ b/ko-archetype-test/src/test/java/org/netbeans/html/archetype/test/ArchetypeVersionTest.java Tue Jan 07 08:21:57 2014 +0100
177.3 @@ -0,0 +1,128 @@
177.4 +/**
177.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
177.6 + *
177.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
177.8 + *
177.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
177.10 + * Other names may be trademarks of their respective owners.
177.11 + *
177.12 + * The contents of this file are subject to the terms of either the GNU
177.13 + * General Public License Version 2 only ("GPL") or the Common
177.14 + * Development and Distribution License("CDDL") (collectively, the
177.15 + * "License"). You may not use this file except in compliance with the
177.16 + * License. You can obtain a copy of the License at
177.17 + * http://www.netbeans.org/cddl-gplv2.html
177.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
177.19 + * specific language governing permissions and limitations under the
177.20 + * License. When distributing the software, include this License Header
177.21 + * Notice in each file and include the License file at
177.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
177.23 + * particular file as subject to the "Classpath" exception as provided
177.24 + * by Oracle in the GPL Version 2 section of the License file that
177.25 + * accompanied this code. If applicable, add the following below the
177.26 + * License Header, with the fields enclosed by brackets [] replaced by
177.27 + * your own identifying information:
177.28 + * "Portions Copyrighted [year] [name of copyright owner]"
177.29 + *
177.30 + * Contributor(s):
177.31 + *
177.32 + * The Original Software is NetBeans. The Initial Developer of the Original
177.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
177.34 + *
177.35 + * If you wish your version of this file to be governed by only the CDDL
177.36 + * or only the GPL Version 2, indicate your decision by adding
177.37 + * "[Contributor] elects to include this software in this distribution
177.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
177.39 + * single choice of license, a recipient has the option to distribute
177.40 + * your version of this file under either the CDDL, the GPL Version 2 or
177.41 + * to extend the choice of license to its licensees as provided above.
177.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
177.43 + * Version 2 license, then the option applies only if the new code is
177.44 + * made subject to such option by the copyright holder.
177.45 + */
177.46 +package org.netbeans.html.archetype.test;
177.47 +
177.48 +import java.io.IOException;
177.49 +import java.net.URL;
177.50 +import javax.xml.XMLConstants;
177.51 +import javax.xml.parsers.DocumentBuilderFactory;
177.52 +import javax.xml.parsers.ParserConfigurationException;
177.53 +import javax.xml.xpath.XPathConstants;
177.54 +import javax.xml.xpath.XPathExpression;
177.55 +import javax.xml.xpath.XPathExpressionException;
177.56 +import javax.xml.xpath.XPathFactory;
177.57 +import javax.xml.xpath.XPathFactoryConfigurationException;
177.58 +import org.testng.annotations.Test;
177.59 +import static org.testng.Assert.*;
177.60 +import org.testng.annotations.BeforeClass;
177.61 +import org.w3c.dom.Document;
177.62 +import org.w3c.dom.NodeList;
177.63 +import org.xml.sax.SAXException;
177.64 +
177.65 +/**
177.66 + *
177.67 + * @author Jaroslav Tulach <jtulach@netbeans.org>
177.68 + */
177.69 +public class ArchetypeVersionTest {
177.70 + private String version;
177.71 +
177.72 + public ArchetypeVersionTest() {
177.73 + }
177.74 +
177.75 + @BeforeClass public void readCurrentVersion() throws Exception {
177.76 + version = findCurrentVersion();
177.77 + assertFalse(version.isEmpty(), "There should be some version string");
177.78 + }
177.79 +
177.80 +
177.81 + @Test public void testComparePomDepsVersions() throws Exception {
177.82 + final ClassLoader l = ArchetypeVersionTest.class.getClassLoader();
177.83 + URL r = l.getResource("archetype-resources/pom.xml");
177.84 + assertNotNull(r, "Archetype pom found");
177.85 +
177.86 + final XPathFactory fact = XPathFactory.newInstance();
177.87 + XPathExpression xp2 = fact.newXPath().compile(
177.88 + "//properties/net.java.html.version/text()"
177.89 + );
177.90 +
177.91 + Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(r.openStream());
177.92 + String arch = (String) xp2.evaluate(dom, XPathConstants.STRING);
177.93 +
177.94 + assertEquals(arch, version, "net.java.html.json dependency needs to be on latest version");
177.95 + }
177.96 +
177.97 + @Test public void testNbActions() throws Exception {
177.98 + final ClassLoader l = ArchetypeVersionTest.class.getClassLoader();
177.99 + URL r = l.getResource("archetype-resources/nbactions.xml");
177.100 + assertNotNull(r, "Archetype nb file found");
177.101 +
177.102 + final XPathFactory fact = XPathFactory.newInstance();
177.103 + XPathExpression xp2 = fact.newXPath().compile(
177.104 + "//goal/text()"
177.105 + );
177.106 +
177.107 + Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(r.openStream());
177.108 + NodeList goals = (NodeList) xp2.evaluate(dom, XPathConstants.NODESET);
177.109 +
177.110 + for (int i = 0; i < goals.getLength(); i++) {
177.111 + String s = goals.item(i).getTextContent();
177.112 + if (s.contains("netbeans")) {
177.113 + assertFalse(s.matches(".*netbeans.*[0-9].*"), "No numbers: " + s);
177.114 + }
177.115 + }
177.116 + }
177.117 +
177.118 + static String findCurrentVersion() throws XPathExpressionException, IOException, ParserConfigurationException, SAXException, XPathFactoryConfigurationException {
177.119 + final ClassLoader l = ArchetypeVersionTest.class.getClassLoader();
177.120 + URL u = l.getResource("META-INF/maven/org.netbeans.html/knockout4j-archetype/pom.xml");
177.121 + assertNotNull(u, "Own pom found: " + System.getProperty("java.class.path"));
177.122 +
177.123 + final XPathFactory fact = XPathFactory.newInstance();
177.124 + fact.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
177.125 +
177.126 + XPathExpression xp = fact.newXPath().compile("project/version/text()");
177.127 +
177.128 + Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(u.openStream());
177.129 + return xp.evaluate(dom);
177.130 + }
177.131 +}
178.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
178.2 +++ b/ko-archetype-test/src/test/java/org/netbeans/html/archetype/test/VerifyArchetypeTest.java Tue Jan 07 08:21:57 2014 +0100
178.3 @@ -0,0 +1,99 @@
178.4 +/**
178.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
178.6 + *
178.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
178.8 + *
178.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
178.10 + * Other names may be trademarks of their respective owners.
178.11 + *
178.12 + * The contents of this file are subject to the terms of either the GNU
178.13 + * General Public License Version 2 only ("GPL") or the Common
178.14 + * Development and Distribution License("CDDL") (collectively, the
178.15 + * "License"). You may not use this file except in compliance with the
178.16 + * License. You can obtain a copy of the License at
178.17 + * http://www.netbeans.org/cddl-gplv2.html
178.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
178.19 + * specific language governing permissions and limitations under the
178.20 + * License. When distributing the software, include this License Header
178.21 + * Notice in each file and include the License file at
178.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
178.23 + * particular file as subject to the "Classpath" exception as provided
178.24 + * by Oracle in the GPL Version 2 section of the License file that
178.25 + * accompanied this code. If applicable, add the following below the
178.26 + * License Header, with the fields enclosed by brackets [] replaced by
178.27 + * your own identifying information:
178.28 + * "Portions Copyrighted [year] [name of copyright owner]"
178.29 + *
178.30 + * Contributor(s):
178.31 + *
178.32 + * The Original Software is NetBeans. The Initial Developer of the Original
178.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
178.34 + *
178.35 + * If you wish your version of this file to be governed by only the CDDL
178.36 + * or only the GPL Version 2, indicate your decision by adding
178.37 + * "[Contributor] elects to include this software in this distribution
178.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
178.39 + * single choice of license, a recipient has the option to distribute
178.40 + * your version of this file under either the CDDL, the GPL Version 2 or
178.41 + * to extend the choice of license to its licensees as provided above.
178.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
178.43 + * Version 2 license, then the option applies only if the new code is
178.44 + * made subject to such option by the copyright holder.
178.45 + */
178.46 +package org.netbeans.html.archetype.test;
178.47 +
178.48 +import java.io.File;
178.49 +import java.util.Properties;
178.50 +import org.apache.maven.it.Verifier;
178.51 +import org.testng.annotations.Test;
178.52 +import static org.testng.Assert.*;
178.53 +
178.54 +/**
178.55 + *
178.56 + * @author Jaroslav Tulach <jtulach@netbeans.org>
178.57 + */
178.58 +public class VerifyArchetypeTest {
178.59 + @Test public void projectCompiles() throws Exception {
178.60 + final File dir = new File("target/tests/fxcompile/").getAbsoluteFile();
178.61 + generateFromArchetype(dir);
178.62 +
178.63 + File created = new File(dir, "o-a-test");
178.64 + assertTrue(created.isDirectory(), "Project created");
178.65 + assertTrue(new File(created, "pom.xml").isFile(), "Pom file is in there");
178.66 +
178.67 + Verifier v = new Verifier(created.getAbsolutePath());
178.68 + v.executeGoal("verify");
178.69 +
178.70 + v.verifyErrorFreeLog();
178.71 +
178.72 + for (String l : v.loadFile(v.getBasedir(), v.getLogFileName(), false)) {
178.73 + if (l.contains("j2js")) {
178.74 + fail("No pre-compilaton:\n" + l);
178.75 + }
178.76 + }
178.77 +
178.78 + v.verifyTextInLog("fxcompile/o-a-test/target/o-a-test-1.0-SNAPSHOT-html.java.net.zip");
178.79 + }
178.80 +
178.81 + private Verifier generateFromArchetype(final File dir, String... params) throws Exception {
178.82 + Verifier v = new Verifier(dir.getAbsolutePath());
178.83 + v.setAutoclean(false);
178.84 + v.setLogFileName("generate.log");
178.85 + v.deleteDirectory("");
178.86 + dir.mkdirs();
178.87 + Properties sysProp = v.getSystemProperties();
178.88 + sysProp.put("groupId", "org.someuser.test");
178.89 + sysProp.put("artifactId", "o-a-test");
178.90 + sysProp.put("package", "org.someuser.test.oat");
178.91 + sysProp.put("archetypeGroupId", "org.netbeans.html");
178.92 + sysProp.put("archetypeArtifactId", "knockout4j-archetype");
178.93 + sysProp.put("archetypeVersion", ArchetypeVersionTest.findCurrentVersion());
178.94 +
178.95 + for (String p : params) {
178.96 + v.addCliOption(p);
178.97 + }
178.98 + v.executeGoal("archetype:generate");
178.99 + v.verifyErrorFreeLog();
178.100 + return v;
178.101 + }
178.102 +}
179.1 --- a/ko-archetype/pom.xml Thu Dec 19 17:11:01 2013 +0100
179.2 +++ b/ko-archetype/pom.xml Tue Jan 07 08:21:57 2014 +0100
179.3 @@ -2,11 +2,11 @@
179.4 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
179.5 <modelVersion>4.0.0</modelVersion>
179.6 <parent>
179.7 - <artifactId>html</artifactId>
179.8 - <groupId>org.apidesign</groupId>
179.9 + <groupId>org.netbeans.html</groupId>
179.10 + <artifactId>pom</artifactId>
179.11 <version>0.7-SNAPSHOT</version>
179.12 </parent>
179.13 - <groupId>org.apidesign.html</groupId>
179.14 + <groupId>org.netbeans.html</groupId>
179.15 <artifactId>knockout4j-archetype</artifactId>
179.16 <version>0.7-SNAPSHOT</version>
179.17 <packaging>jar</packaging>
180.1 --- a/ko-archetype/src/main/java/org/apidesign/html/archetype/package-info.java Thu Dec 19 17:11:01 2013 +0100
180.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
180.3 @@ -1,21 +0,0 @@
180.4 -/**
180.5 - * HTML via Java(tm) Language Bindings
180.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
180.7 - *
180.8 - * This program is free software: you can redistribute it and/or modify
180.9 - * it under the terms of the GNU General Public License as published by
180.10 - * the Free Software Foundation, version 2 of the License.
180.11 - *
180.12 - * This program is distributed in the hope that it will be useful,
180.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
180.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
180.15 - * GNU General Public License for more details. apidesign.org
180.16 - * designates this particular file as subject to the
180.17 - * "Classpath" exception as provided by apidesign.org
180.18 - * in the License file that accompanied this code.
180.19 - *
180.20 - * You should have received a copy of the GNU General Public License
180.21 - * along with this program. Look for COPYING file in the top folder.
180.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
180.23 - */
180.24 -package org.apidesign.html.archetype;
181.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
181.2 +++ b/ko-archetype/src/main/java/org/netbeans/html/archetype/package-info.java Tue Jan 07 08:21:57 2014 +0100
181.3 @@ -0,0 +1,43 @@
181.4 +/**
181.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
181.6 + *
181.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
181.8 + *
181.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
181.10 + * Other names may be trademarks of their respective owners.
181.11 + *
181.12 + * The contents of this file are subject to the terms of either the GNU
181.13 + * General Public License Version 2 only ("GPL") or the Common
181.14 + * Development and Distribution License("CDDL") (collectively, the
181.15 + * "License"). You may not use this file except in compliance with the
181.16 + * License. You can obtain a copy of the License at
181.17 + * http://www.netbeans.org/cddl-gplv2.html
181.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
181.19 + * specific language governing permissions and limitations under the
181.20 + * License. When distributing the software, include this License Header
181.21 + * Notice in each file and include the License file at
181.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
181.23 + * particular file as subject to the "Classpath" exception as provided
181.24 + * by Oracle in the GPL Version 2 section of the License file that
181.25 + * accompanied this code. If applicable, add the following below the
181.26 + * License Header, with the fields enclosed by brackets [] replaced by
181.27 + * your own identifying information:
181.28 + * "Portions Copyrighted [year] [name of copyright owner]"
181.29 + *
181.30 + * Contributor(s):
181.31 + *
181.32 + * The Original Software is NetBeans. The Initial Developer of the Original
181.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
181.34 + *
181.35 + * If you wish your version of this file to be governed by only the CDDL
181.36 + * or only the GPL Version 2, indicate your decision by adding
181.37 + * "[Contributor] elects to include this software in this distribution
181.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
181.39 + * single choice of license, a recipient has the option to distribute
181.40 + * your version of this file under either the CDDL, the GPL Version 2 or
181.41 + * to extend the choice of license to its licensees as provided above.
181.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
181.43 + * Version 2 license, then the option applies only if the new code is
181.44 + * made subject to such option by the copyright holder.
181.45 + */
181.46 +package org.netbeans.html.archetype;
182.1 --- a/ko-archetype/src/main/resources/archetype-resources/pom.xml Thu Dec 19 17:11:01 2013 +0100
182.2 +++ b/ko-archetype/src/main/resources/archetype-resources/pom.xml Tue Jan 07 08:21:57 2014 +0100
182.3 @@ -101,24 +101,24 @@
182.4 </build>
182.5 <dependencies>
182.6 <dependency>
182.7 - <groupId>org.apidesign.html</groupId>
182.8 + <groupId>org.netbeans.html</groupId>
182.9 <artifactId>net.java.html.json</artifactId>
182.10 <version>\${net.java.html.version}</version>
182.11 </dependency>
182.12 <dependency>
182.13 - <groupId>org.apidesign.html</groupId>
182.14 + <groupId>org.netbeans.html</groupId>
182.15 <artifactId>net.java.html.boot</artifactId>
182.16 <version>\${net.java.html.version}</version>
182.17 </dependency>
182.18 <dependency>
182.19 - <groupId>org.apidesign.html</groupId>
182.20 + <groupId>org.netbeans.html</groupId>
182.21 <artifactId>ko-fx</artifactId>
182.22 <version>\${net.java.html.version}</version>
182.23 <scope>runtime</scope>
182.24 </dependency>
182.25 <dependency>
182.26 - <groupId>org.apidesign.html</groupId>
182.27 - <artifactId>boot-fx</artifactId>
182.28 + <groupId>org.netbeans.html</groupId>
182.29 + <artifactId>net.java.html.boot.fx</artifactId>
182.30 <version>\${net.java.html.version}</version>
182.31 <scope>runtime</scope>
182.32 </dependency>
183.1 --- a/ko-fx/pom.xml Thu Dec 19 17:11:01 2013 +0100
183.2 +++ b/ko-fx/pom.xml Tue Jan 07 08:21:57 2014 +0100
183.3 @@ -2,11 +2,11 @@
183.4 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
183.5 <modelVersion>4.0.0</modelVersion>
183.6 <parent>
183.7 - <groupId>org.apidesign</groupId>
183.8 - <artifactId>html</artifactId>
183.9 + <groupId>org.netbeans.html</groupId>
183.10 + <artifactId>pom</artifactId>
183.11 <version>0.7-SNAPSHOT</version>
183.12 </parent>
183.13 - <groupId>org.apidesign.html</groupId>
183.14 + <groupId>org.netbeans.html</groupId>
183.15 <artifactId>ko-fx</artifactId>
183.16 <version>0.7-SNAPSHOT</version>
183.17 <packaging>bundle</packaging>
183.18 @@ -14,6 +14,7 @@
183.19 <url>http://maven.apache.org</url>
183.20 <properties>
183.21 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
183.22 + <bundleSymbolicName>org.netbeans.html.ko-fx</bundleSymbolicName>
183.23 </properties>
183.24 <build>
183.25 <plugins>
183.26 @@ -52,7 +53,7 @@
183.27 <artifactId>org.json-osgi</artifactId>
183.28 </dependency>
183.29 <dependency>
183.30 - <groupId>org.apidesign.html</groupId>
183.31 + <groupId>org.netbeans.html</groupId>
183.32 <artifactId>net.java.html.json</artifactId>
183.33 <version>${project.version}</version>
183.34 </dependency>
183.35 @@ -73,14 +74,14 @@
183.36 <scope>provided</scope>
183.37 </dependency>
183.38 <dependency>
183.39 - <groupId>org.apidesign.html</groupId>
183.40 + <groupId>org.netbeans.html</groupId>
183.41 <artifactId>net.java.html.boot</artifactId>
183.42 <version>${project.version}</version>
183.43 <type>jar</type>
183.44 </dependency>
183.45 <dependency>
183.46 <groupId>${project.groupId}</groupId>
183.47 - <artifactId>boot-fx</artifactId>
183.48 + <artifactId>net.java.html.boot.fx</artifactId>
183.49 <version>${project.version}</version>
183.50 <scope>test</scope>
183.51 </dependency>
184.1 --- a/ko-fx/src/main/java/org/apidesign/html/kofx/Console.java Thu Dec 19 17:11:01 2013 +0100
184.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
184.3 @@ -1,59 +0,0 @@
184.4 -/**
184.5 - * HTML via Java(tm) Language Bindings
184.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
184.7 - *
184.8 - * This program is free software: you can redistribute it and/or modify
184.9 - * it under the terms of the GNU General Public License as published by
184.10 - * the Free Software Foundation, version 2 of the License.
184.11 - *
184.12 - * This program is distributed in the hope that it will be useful,
184.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
184.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
184.15 - * GNU General Public License for more details. apidesign.org
184.16 - * designates this particular file as subject to the
184.17 - * "Classpath" exception as provided by apidesign.org
184.18 - * in the License file that accompanied this code.
184.19 - *
184.20 - * You should have received a copy of the GNU General Public License
184.21 - * along with this program. Look for COPYING file in the top folder.
184.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
184.23 - */
184.24 -package org.apidesign.html.kofx;
184.25 -
184.26 -import java.util.logging.Level;
184.27 -import java.util.logging.Logger;
184.28 -import net.java.html.js.JavaScriptBody;
184.29 -
184.30 -/** This is an implementation package - just
184.31 - * include its JAR on classpath and use official {@link Context} API
184.32 - * to access the functionality.
184.33 - * <p>
184.34 - * Redirects JavaScript's messages to Java's {@link Logger}.
184.35 - *
184.36 - * @author Jaroslav Tulach <jtulach@netbeans.org>
184.37 - */
184.38 -final class Console {
184.39 - private static final Logger LOG = Logger.getLogger(Console.class.getName());
184.40 -
184.41 - private Console() {
184.42 - }
184.43 -
184.44 - static void register() {
184.45 - registerImpl("log", Level.INFO);
184.46 - registerImpl("info", Level.INFO);
184.47 - registerImpl("warn", Level.WARNING);
184.48 - registerImpl("error", Level.SEVERE);
184.49 - }
184.50 -
184.51 - @JavaScriptBody(args = { "attr", "l" },
184.52 - javacall = true, body =
184.53 - " window.console[attr] = function(m) {\n"
184.54 - + " @org.apidesign.html.kofx.Console::log(Ljava/util/logging/Level;Ljava/lang/String;)(l, m);\n"
184.55 - + " };\n"
184.56 - )
184.57 - private static native void registerImpl(String attr, Level l);
184.58 -
184.59 - static void log(Level l, String msg) {
184.60 - LOG.log(l, msg);
184.61 - }
184.62 -}
185.1 --- a/ko-fx/src/main/java/org/apidesign/html/kofx/FXContext.java Thu Dec 19 17:11:01 2013 +0100
185.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
185.3 @@ -1,200 +0,0 @@
185.4 -/**
185.5 - * HTML via Java(tm) Language Bindings
185.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
185.7 - *
185.8 - * This program is free software: you can redistribute it and/or modify
185.9 - * it under the terms of the GNU General Public License as published by
185.10 - * the Free Software Foundation, version 2 of the License.
185.11 - *
185.12 - * This program is distributed in the hope that it will be useful,
185.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
185.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
185.15 - * GNU General Public License for more details. apidesign.org
185.16 - * designates this particular file as subject to the
185.17 - * "Classpath" exception as provided by apidesign.org
185.18 - * in the License file that accompanied this code.
185.19 - *
185.20 - * You should have received a copy of the GNU General Public License
185.21 - * along with this program. Look for COPYING file in the top folder.
185.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
185.23 - */
185.24 -package org.apidesign.html.kofx;
185.25 -
185.26 -import java.io.Closeable;
185.27 -import java.io.IOException;
185.28 -import java.io.InputStream;
185.29 -import java.util.ServiceLoader;
185.30 -import java.util.logging.Logger;
185.31 -import javafx.application.Platform;
185.32 -import net.java.html.js.JavaScriptBody;
185.33 -import netscape.javascript.JSObject;
185.34 -import org.apidesign.html.boot.spi.Fn;
185.35 -import org.apidesign.html.context.spi.Contexts;
185.36 -import org.apidesign.html.json.spi.FunctionBinding;
185.37 -import org.apidesign.html.json.spi.JSONCall;
185.38 -import org.apidesign.html.json.spi.PropertyBinding;
185.39 -import org.apidesign.html.json.spi.Technology;
185.40 -import org.apidesign.html.json.spi.Transfer;
185.41 -import org.apidesign.html.json.spi.WSTransfer;
185.42 -import org.openide.util.lookup.ServiceProvider;
185.43 -
185.44 -/** This is an implementation package - just
185.45 - * include its JAR on classpath and use official {@link Context} API
185.46 - * to access the functionality.
185.47 - * <p>
185.48 - * Registers {@link ContextProvider}, so {@link ServiceLoader} can find it.
185.49 - *
185.50 - * @author Jaroslav Tulach <jtulach@netbeans.org>
185.51 - */
185.52 -public final class FXContext
185.53 -implements Technology.BatchInit<JSObject>, Transfer, WSTransfer<LoadWS> {
185.54 - static final Logger LOG = Logger.getLogger(FXContext.class.getName());
185.55 - private static Boolean javaScriptEnabled;
185.56 - private final Fn.Presenter browserContext;
185.57 -
185.58 - public FXContext(Fn.Presenter browserContext) {
185.59 - this.browserContext = browserContext;
185.60 - }
185.61 -
185.62 - @JavaScriptBody(args = {}, body = "return true;")
185.63 - private static boolean isJavaScriptEnabledJs() {
185.64 - return false;
185.65 - }
185.66 -
185.67 - static boolean isJavaScriptEnabled() {
185.68 - if (javaScriptEnabled != null) {
185.69 - return javaScriptEnabled;
185.70 - }
185.71 - return javaScriptEnabled = isJavaScriptEnabledJs();
185.72 - }
185.73 -
185.74 - final boolean areWebSocketsSupported() {
185.75 - return LoadWS.isSupported();
185.76 - }
185.77 -
185.78 -
185.79 - @Override
185.80 - public JSObject wrapModel(Object model, PropertyBinding[] propArr, FunctionBinding[] funcArr) {
185.81 - String[] propNames = new String[propArr.length];
185.82 - boolean[] propReadOnly = new boolean[propArr.length];
185.83 - Object[] propValues = new Object[propArr.length];
185.84 - for (int i = 0; i < propNames.length; i++) {
185.85 - propNames[i] = propArr[i].getPropertyName();
185.86 - propReadOnly[i] = propArr[i].isReadOnly();
185.87 - propValues[i] = propArr[i].getValue();
185.88 - }
185.89 - String[] funcNames = new String[funcArr.length];
185.90 - for (int i = 0; i < funcNames.length; i++) {
185.91 - funcNames[i] = funcArr[i].getFunctionName();
185.92 - }
185.93 -
185.94 - return Knockout.wrapModel(model,
185.95 - propNames, propReadOnly, Knockout.toArray(propValues), propArr,
185.96 - funcNames, funcArr
185.97 - );
185.98 - }
185.99 -
185.100 - @Override
185.101 - public JSObject wrapModel(Object model) {
185.102 - throw new UnsupportedOperationException();
185.103 - }
185.104 -
185.105 - @Override
185.106 - public void bind(PropertyBinding b, Object model, JSObject data) {
185.107 - throw new UnsupportedOperationException();
185.108 - }
185.109 -
185.110 - @Override
185.111 - public void valueHasMutated(JSObject data, String propertyName) {
185.112 - Knockout.valueHasMutated(data, propertyName);
185.113 - }
185.114 -
185.115 - @Override
185.116 - public void expose(FunctionBinding fb, Object model, JSObject d) {
185.117 - throw new UnsupportedOperationException();
185.118 - }
185.119 -
185.120 - @Override
185.121 - public void applyBindings(JSObject data) {
185.122 - Knockout.applyBindings(data);
185.123 - }
185.124 -
185.125 - @Override
185.126 - public Object wrapArray(Object[] arr) {
185.127 - return Knockout.toArray(arr);
185.128 - }
185.129 -
185.130 - @Override
185.131 - public void extract(Object obj, String[] props, Object[] values) {
185.132 - LoadJSON.extractJSON(obj, props, values);
185.133 - }
185.134 -
185.135 - @Override
185.136 - public void loadJSON(final JSONCall call) {
185.137 - LoadJSON.loadJSON(call);
185.138 - }
185.139 -
185.140 - @Override
185.141 - public <M> M toModel(Class<M> modelClass, Object data) {
185.142 - if (data instanceof JSObject) {
185.143 - data = ((JSObject)data).getMember("ko-fx.model"); // NOI18N
185.144 - }
185.145 - return modelClass.cast(data);
185.146 - }
185.147 -
185.148 - @Override
185.149 - public Object toJSON(InputStream is) throws IOException {
185.150 - return LoadJSON.parse(is);
185.151 - }
185.152 -
185.153 - @Override
185.154 - public void runSafe(final Runnable r) {
185.155 - class Wrap implements Runnable {
185.156 - @Override public void run() {
185.157 - try (Closeable c = Fn.activate(browserContext)) {
185.158 - r.run();
185.159 - } catch (IOException ex) {
185.160 - // cannot be thrown
185.161 - }
185.162 - }
185.163 - }
185.164 - Wrap w = new Wrap();
185.165 -
185.166 - if (Platform.isFxApplicationThread()) {
185.167 - w.run();
185.168 - } else {
185.169 - Platform.runLater(w);
185.170 - }
185.171 - }
185.172 -
185.173 - @Override
185.174 - public LoadWS open(String url, JSONCall onReply) {
185.175 - return new LoadWS(onReply, url);
185.176 - }
185.177 -
185.178 - @Override
185.179 - public void send(LoadWS socket, JSONCall data) {
185.180 - socket.send(data);
185.181 - }
185.182 -
185.183 - @Override
185.184 - public void close(LoadWS socket) {
185.185 - socket.close();
185.186 - }
185.187 -
185.188 - @ServiceProvider(service = Contexts.Provider.class)
185.189 - public static final class Prvdr implements Contexts.Provider {
185.190 - @Override
185.191 - public void fillContext(Contexts.Builder context, Class<?> requestor) {
185.192 - if (isJavaScriptEnabled()) {
185.193 - FXContext c = new FXContext(Fn.activePresenter());
185.194 -
185.195 - context.register(Technology.class, c, 100);
185.196 - context.register(Transfer.class, c, 100);
185.197 - if (c.areWebSocketsSupported()) {
185.198 - context.register(WSTransfer.class, c, 100);
185.199 - }
185.200 - }
185.201 - }
185.202 - }
185.203 -}
186.1 --- a/ko-fx/src/main/java/org/apidesign/html/kofx/Knockout.java Thu Dec 19 17:11:01 2013 +0100
186.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
186.3 @@ -1,123 +0,0 @@
186.4 -/**
186.5 - * HTML via Java(tm) Language Bindings
186.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
186.7 - *
186.8 - * This program is free software: you can redistribute it and/or modify
186.9 - * it under the terms of the GNU General Public License as published by
186.10 - * the Free Software Foundation, version 2 of the License.
186.11 - *
186.12 - * This program is distributed in the hope that it will be useful,
186.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
186.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
186.15 - * GNU General Public License for more details. apidesign.org
186.16 - * designates this particular file as subject to the
186.17 - * "Classpath" exception as provided by apidesign.org
186.18 - * in the License file that accompanied this code.
186.19 - *
186.20 - * You should have received a copy of the GNU General Public License
186.21 - * along with this program. Look for COPYING file in the top folder.
186.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
186.23 - */
186.24 -package org.apidesign.html.kofx;
186.25 -
186.26 -import net.java.html.js.JavaScriptBody;
186.27 -import net.java.html.js.JavaScriptResource;
186.28 -import net.java.html.json.Model;
186.29 -import netscape.javascript.JSObject;
186.30 -import org.apidesign.html.json.spi.FunctionBinding;
186.31 -import org.apidesign.html.json.spi.PropertyBinding;
186.32 -
186.33 -/** This is an implementation package - just
186.34 - * include its JAR on classpath and use official {@link Context} API
186.35 - * to access the functionality.
186.36 - * <p>
186.37 - * Provides binding between {@link Model models} and knockout.js running
186.38 - * inside a JavaFX WebView.
186.39 - *
186.40 - * @author Jaroslav Tulach <jtulach@netbeans.org>
186.41 - */
186.42 -@JavaScriptResource("knockout-2.2.1.js")
186.43 -final class Knockout {
186.44 - static final JSObject KObject;
186.45 - static {
186.46 - Console.register();
186.47 - KObject = (JSObject) kObj();
186.48 - }
186.49 -
186.50 - static Object toArray(Object[] arr) {
186.51 - return KObject.call("array", arr);
186.52 - }
186.53 -
186.54 - @JavaScriptBody(args = { "model", "prop" }, body =
186.55 - "if (model) {\n"
186.56 - + " var koProp = model[prop];\n"
186.57 - + " if (koProp && koProp['valueHasMutated']) {\n"
186.58 - + " koProp['valueHasMutated']();\n"
186.59 - + " }\n"
186.60 - + "}\n"
186.61 - )
186.62 - public native static void valueHasMutated(JSObject model, String prop);
186.63 -
186.64 - @JavaScriptBody(args = { "bindings" }, body = "ko.applyBindings(bindings);")
186.65 - native static void applyBindings(Object bindings);
186.66 -
186.67 - @JavaScriptBody(args = {}, body =
186.68 - " var k = {};"
186.69 - + " k.array= function() {"
186.70 - + " return Array.prototype.slice.call(arguments);"
186.71 - + " };"
186.72 - + " return k;"
186.73 - )
186.74 - private static native Object kObj();
186.75 -
186.76 -
186.77 - @JavaScriptBody(
186.78 - javacall = true,
186.79 - args = {"model", "propNames", "propReadOnly", "propValues", "propArr", "funcNames", "funcArr"},
186.80 - body
186.81 - = "var ret = {};\n"
186.82 - + "ret['ko-fx.model'] = model;\n"
186.83 - + "function koComputed(name, readOnly, value, prop) {\n"
186.84 - + " function realGetter() {\n"
186.85 - + " try {"
186.86 - + " var v = prop.@org.apidesign.html.json.spi.PropertyBinding::getValue()();"
186.87 - + " return v;"
186.88 - + " } catch (e) {"
186.89 - + " alert(\"Cannot call getValue on \" + model + \" prop: \" + name + \" error: \" + e);"
186.90 - + " }"
186.91 - + " }\n"
186.92 - + " var activeGetter = function() { return value; };\n"
186.93 - + " var bnd = {"
186.94 - + " read: function() {"
186.95 - + " var r = activeGetter();"
186.96 - + " activeGetter = realGetter;"
186.97 - + " return r;"
186.98 - + " },"
186.99 - + " owner: ret\n"
186.100 - + " };\n"
186.101 - + " if (!readOnly) {\n"
186.102 - + " bnd.write = function(val) {\n"
186.103 - + " prop.@org.apidesign.html.json.spi.PropertyBinding::setValue(Ljava/lang/Object;)(val);\n"
186.104 - + " };"
186.105 - + " };"
186.106 - + " ret[name] = ko.computed(bnd);"
186.107 - + "}\n"
186.108 - + "for (var i = 0; i < propNames.length; i++) {\n"
186.109 - + " koComputed(propNames[i], propReadOnly[i], propValues[i], propArr[i]);\n"
186.110 - + "}\n"
186.111 - + "function koExpose(name, func) {\n"
186.112 - + " ret[name] = function(data, ev) {\n"
186.113 - + " func.@org.apidesign.html.json.spi.FunctionBinding::call(Ljava/lang/Object;Ljava/lang/Object;)(data, ev);\n"
186.114 - + " };\n"
186.115 - + "}\n"
186.116 - + "for (var i = 0; i < funcNames.length; i++) {\n"
186.117 - + " koExpose(funcNames[i], funcArr[i]);\n"
186.118 - + "}\n"
186.119 - + "return ret;\n"
186.120 - )
186.121 - static native JSObject wrapModel(
186.122 - Object model,
186.123 - String[] propNames, boolean[] propReadOnly, Object propValues, PropertyBinding[] propArr,
186.124 - String[] funcNames, FunctionBinding[] funcArr
186.125 - );
186.126 -}
187.1 --- a/ko-fx/src/main/java/org/apidesign/html/kofx/LoadJSON.java Thu Dec 19 17:11:01 2013 +0100
187.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
187.3 @@ -1,245 +0,0 @@
187.4 -/**
187.5 - * HTML via Java(tm) Language Bindings
187.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
187.7 - *
187.8 - * This program is free software: you can redistribute it and/or modify
187.9 - * it under the terms of the GNU General Public License as published by
187.10 - * the Free Software Foundation, version 2 of the License.
187.11 - *
187.12 - * This program is distributed in the hope that it will be useful,
187.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
187.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
187.15 - * GNU General Public License for more details. apidesign.org
187.16 - * designates this particular file as subject to the
187.17 - * "Classpath" exception as provided by apidesign.org
187.18 - * in the License file that accompanied this code.
187.19 - *
187.20 - * You should have received a copy of the GNU General Public License
187.21 - * along with this program. Look for COPYING file in the top folder.
187.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
187.23 - */
187.24 -package org.apidesign.html.kofx;
187.25 -
187.26 -import java.io.IOException;
187.27 -import java.io.InputStream;
187.28 -import java.io.InputStreamReader;
187.29 -import java.io.OutputStream;
187.30 -import java.io.PushbackInputStream;
187.31 -import java.io.Reader;
187.32 -import java.net.HttpURLConnection;
187.33 -import java.net.MalformedURLException;
187.34 -import java.net.URL;
187.35 -import java.net.URLConnection;
187.36 -import java.util.Iterator;
187.37 -import java.util.concurrent.Executor;
187.38 -import java.util.concurrent.Executors;
187.39 -import java.util.concurrent.ThreadFactory;
187.40 -import java.util.logging.Level;
187.41 -import java.util.logging.Logger;
187.42 -import javafx.application.Platform;
187.43 -import net.java.html.js.JavaScriptBody;
187.44 -import netscape.javascript.JSObject;
187.45 -import org.apidesign.html.json.spi.JSONCall;
187.46 -import org.json.JSONArray;
187.47 -import org.json.JSONException;
187.48 -import org.json.JSONObject;
187.49 -import org.json.JSONTokener;
187.50 -
187.51 -/** This is an implementation package - just
187.52 - * include its JAR on classpath and use official {@link Context} API
187.53 - * to access the functionality.
187.54 - *
187.55 - * @author Jaroslav Tulach <jtulach@netbeans.org>
187.56 - */
187.57 -final class LoadJSON implements Runnable {
187.58 - private static final Logger LOG = FXContext.LOG;
187.59 - private static final Executor REQ = Executors.newCachedThreadPool(new ThreadFactory() {
187.60 - @Override
187.61 - public Thread newThread(Runnable runnable) {
187.62 - Thread thread = Executors.defaultThreadFactory().newThread(runnable);
187.63 - thread.setDaemon(true);
187.64 - return thread;
187.65 - }
187.66 - });
187.67 -
187.68 - private final JSONCall call;
187.69 - private final URL base;
187.70 - private Throwable error;
187.71 - private Object json;
187.72 -
187.73 -
187.74 - private LoadJSON(JSONCall call) {
187.75 - this.call = call;
187.76 - URL b;
187.77 - try {
187.78 - b = new URL(findBaseURL());
187.79 - } catch (MalformedURLException ex) {
187.80 - LOG.log(Level.SEVERE, "Can't find base url for " + call.composeURL("dummy"), ex);
187.81 - b = null;
187.82 - }
187.83 - this.base = b;
187.84 - }
187.85 -
187.86 - public static void loadJSON(JSONCall call) {
187.87 - assert !"WebSocket".equals(call.getMethod());
187.88 - REQ.execute(new LoadJSON((call)));
187.89 - }
187.90 -
187.91 - @Override
187.92 - public void run() {
187.93 - if (Platform.isFxApplicationThread()) {
187.94 - if (error != null) {
187.95 - call.notifyError(error);
187.96 - } else {
187.97 - call.notifySuccess(json);
187.98 - }
187.99 - return;
187.100 - }
187.101 - final String url;
187.102 - if (call.isJSONP()) {
187.103 - url = call.composeURL("dummy");
187.104 - } else {
187.105 - url = call.composeURL(null);
187.106 - }
187.107 - try {
187.108 - final URL u = new URL(base, url.replace(" ", "%20"));
187.109 - URLConnection conn = u.openConnection();
187.110 - if (conn instanceof HttpURLConnection) {
187.111 - HttpURLConnection huc = (HttpURLConnection) conn;
187.112 - if (call.getMethod() != null) {
187.113 - huc.setRequestMethod(call.getMethod());
187.114 - }
187.115 - if (call.isDoOutput()) {
187.116 - huc.setDoOutput(true);
187.117 - final OutputStream os = huc.getOutputStream();
187.118 - call.writeData(os);
187.119 - os.flush();
187.120 - }
187.121 - }
187.122 - final PushbackInputStream is = new PushbackInputStream(
187.123 - conn.getInputStream(), 1
187.124 - );
187.125 - boolean array = false;
187.126 - boolean string = false;
187.127 - if (call.isJSONP()) {
187.128 - for (;;) {
187.129 - int ch = is.read();
187.130 - if (ch == -1) {
187.131 - break;
187.132 - }
187.133 - if (ch == '[') {
187.134 - is.unread(ch);
187.135 - array = true;
187.136 - break;
187.137 - }
187.138 - if (ch == '{') {
187.139 - is.unread(ch);
187.140 - break;
187.141 - }
187.142 - }
187.143 - } else {
187.144 - int ch = is.read();
187.145 - if (ch == -1) {
187.146 - string = true;
187.147 - } else {
187.148 - array = ch == '[';
187.149 - is.unread(ch);
187.150 - if (!array && ch != '{') {
187.151 - string = true;
187.152 - }
187.153 - }
187.154 - }
187.155 - try {
187.156 - if (string) {
187.157 - throw new JSONException("");
187.158 - }
187.159 - Reader r = new InputStreamReader(is, "UTF-8");
187.160 -
187.161 - JSONTokener tok = new JSONTokener(r);
187.162 - Object obj;
187.163 - obj = array ? new JSONArray(tok) : new JSONObject(tok);
187.164 - json = convertToArray(obj);
187.165 - } catch (JSONException ex) {
187.166 - Reader r = new InputStreamReader(is, "UTF-8");
187.167 - StringBuilder sb = new StringBuilder();
187.168 - for (;;) {
187.169 - int ch = r.read();
187.170 - if (ch == -1) {
187.171 - break;
187.172 - }
187.173 - sb.append((char)ch);
187.174 - }
187.175 - json = sb.toString();
187.176 - }
187.177 - } catch (IOException ex) {
187.178 - error = ex;
187.179 - } finally {
187.180 - Platform.runLater(this);
187.181 - }
187.182 - }
187.183 -
187.184 - static Object convertToArray(Object o) throws JSONException {
187.185 - if (o instanceof JSONArray) {
187.186 - JSONArray ja = (JSONArray)o;
187.187 - Object[] arr = new Object[ja.length()];
187.188 - for (int i = 0; i < arr.length; i++) {
187.189 - arr[i] = convertToArray(ja.get(i));
187.190 - }
187.191 - return arr;
187.192 - } else if (o instanceof JSONObject) {
187.193 - JSONObject obj = (JSONObject)o;
187.194 - Iterator it = obj.keys();
187.195 - while (it.hasNext()) {
187.196 - String key = (String)it.next();
187.197 - obj.put(key, convertToArray(obj.get(key)));
187.198 - }
187.199 - return obj;
187.200 - } else {
187.201 - return o;
187.202 - }
187.203 - }
187.204 -
187.205 - public static void extractJSON(Object jsonObject, String[] props, Object[] values) {
187.206 - if (jsonObject instanceof JSONObject) {
187.207 - JSONObject obj = (JSONObject)jsonObject;
187.208 - for (int i = 0; i < props.length; i++) {
187.209 - try {
187.210 - values[i] = obj.has(props[i]) ? obj.get(props[i]) : null;
187.211 - } catch (JSONException ex) {
187.212 - LoadJSON.LOG.log(Level.SEVERE, "Can't read " + props[i] + " from " + jsonObject, ex);
187.213 - }
187.214 - }
187.215 - }
187.216 - if (jsonObject instanceof JSObject) {
187.217 - JSObject obj = (JSObject)jsonObject;
187.218 - for (int i = 0; i < props.length; i++) {
187.219 - Object val = obj.getMember(props[i]);
187.220 - values[i] = isDefined(val) ? val : null;
187.221 - }
187.222 - }
187.223 - }
187.224 -
187.225 - public static Object parse(InputStream is) throws IOException {
187.226 - try {
187.227 - InputStreamReader r = new InputStreamReader(is, "UTF-8");
187.228 - JSONTokener t = new JSONTokener(r);
187.229 - return new JSONObject(t);
187.230 - } catch (JSONException ex) {
187.231 - throw new IOException(ex);
187.232 - }
187.233 - }
187.234 -
187.235 - @JavaScriptBody(args = { }, body =
187.236 - "var h;"
187.237 - + "if (!!window && !!window.location && !!window.location.href)\n"
187.238 - + " h = window.location.href;\n"
187.239 - + "else "
187.240 - + " h = null;"
187.241 - + "return h;\n"
187.242 - )
187.243 - private static native String findBaseURL();
187.244 -
187.245 - private static boolean isDefined(Object val) {
187.246 - return !"undefined".equals(val);
187.247 - }
187.248 -}
188.1 --- a/ko-fx/src/main/java/org/apidesign/html/kofx/LoadWS.java Thu Dec 19 17:11:01 2013 +0100
188.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
188.3 @@ -1,127 +0,0 @@
188.4 -/**
188.5 - * HTML via Java(tm) Language Bindings
188.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
188.7 - *
188.8 - * This program is free software: you can redistribute it and/or modify
188.9 - * it under the terms of the GNU General Public License as published by
188.10 - * the Free Software Foundation, version 2 of the License.
188.11 - *
188.12 - * This program is distributed in the hope that it will be useful,
188.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
188.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
188.15 - * GNU General Public License for more details. apidesign.org
188.16 - * designates this particular file as subject to the
188.17 - * "Classpath" exception as provided by apidesign.org
188.18 - * in the License file that accompanied this code.
188.19 - *
188.20 - * You should have received a copy of the GNU General Public License
188.21 - * along with this program. Look for COPYING file in the top folder.
188.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
188.23 - */
188.24 -package org.apidesign.html.kofx;
188.25 -
188.26 -import net.java.html.js.JavaScriptBody;
188.27 -import org.apidesign.html.json.spi.JSONCall;
188.28 -import org.json.JSONArray;
188.29 -import org.json.JSONException;
188.30 -import org.json.JSONObject;
188.31 -import org.json.JSONTokener;
188.32 -
188.33 -/** Communication with WebSockets for WebView 1.8.
188.34 - *
188.35 - * @author Jaroslav Tulach <jtulach@netbeans.org>
188.36 - */
188.37 -final class LoadWS {
188.38 - private static final boolean SUPPORTED = isWebSocket();
188.39 - private final Object ws;
188.40 - private final JSONCall call;
188.41 -
188.42 - LoadWS(JSONCall first, String url) {
188.43 - call = first;
188.44 - ws = initWebSocket(this, url);
188.45 - if (ws == null) {
188.46 - first.notifyError(new IllegalArgumentException("Wrong URL: " + url));
188.47 - }
188.48 - }
188.49 -
188.50 - static boolean isSupported() {
188.51 - return SUPPORTED;
188.52 - }
188.53 -
188.54 - void send(JSONCall call) {
188.55 - push(call);
188.56 - }
188.57 -
188.58 - private synchronized void push(JSONCall call) {
188.59 - send(ws, call.getMessage());
188.60 - }
188.61 -
188.62 - void onOpen(Object ev) {
188.63 - if (!call.isDoOutput()) {
188.64 - call.notifySuccess(null);
188.65 - }
188.66 - }
188.67 -
188.68 - void onMessage(Object ev, String data) {
188.69 - Object json;
188.70 - try {
188.71 - data = data.trim();
188.72 -
188.73 - JSONTokener tok = new JSONTokener(data);
188.74 - Object obj;
188.75 - obj = data.startsWith("[") ? new JSONArray(tok) : new JSONObject(tok);
188.76 - json = LoadJSON.convertToArray(obj);
188.77 - } catch (JSONException ex) {
188.78 - json = data;
188.79 - }
188.80 - call.notifySuccess(json);
188.81 - }
188.82 -
188.83 - void onError(Object ev) {
188.84 - call.notifyError(new Exception(ev.toString()));
188.85 - }
188.86 -
188.87 - void onClose(boolean wasClean, int code, String reason) {
188.88 - call.notifyError(null);
188.89 - }
188.90 -
188.91 - @JavaScriptBody(args = {}, body = "if (window.WebSocket) return true; else return false;")
188.92 - private static boolean isWebSocket() {
188.93 - return false;
188.94 - }
188.95 -
188.96 - @JavaScriptBody(args = { "back", "url" }, javacall = true, body = ""
188.97 - + "if (window.WebSocket) {"
188.98 - + " try {"
188.99 - + " var ws = new window.WebSocket(url);"
188.100 - + " ws.onopen = function(ev) { back.@org.apidesign.html.kofx.LoadWS::onOpen(Ljava/lang/Object;)(ev); };"
188.101 - + " ws.onmessage = function(ev) { back.@org.apidesign.html.kofx.LoadWS::onMessage(Ljava/lang/Object;Ljava/lang/String;)(ev, ev.data); };"
188.102 - + " ws.onerror = function(ev) { back.@org.apidesign.html.kofx.LoadWS::onError(Ljava/lang/Object;)(ev); };"
188.103 - + " ws.onclose = function(ev) { back.@org.apidesign.html.kofx.LoadWS::onClose(ZILjava/lang/String;)(ev.wasClean, ev.code, ev.reason); };"
188.104 - + " return ws;"
188.105 - + " } catch (ex) {"
188.106 - + " return null;"
188.107 - + " }"
188.108 - + "} else {"
188.109 - + " return null;"
188.110 - + "}"
188.111 - )
188.112 - private static Object initWebSocket(Object back, String url) {
188.113 - return null;
188.114 - }
188.115 -
188.116 -
188.117 - @JavaScriptBody(args = { "ws", "msg" }, body = ""
188.118 - + "ws.send(msg);"
188.119 - )
188.120 - private void send(Object ws, String msg) {
188.121 - }
188.122 -
188.123 - @JavaScriptBody(args = { "ws" }, body = "ws.close();")
188.124 - private static void close(Object ws) {
188.125 - }
188.126 -
188.127 - void close() {
188.128 - close(ws);
188.129 - }
188.130 -}
189.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
189.2 +++ b/ko-fx/src/main/java/org/netbeans/html/kofx/Console.java Tue Jan 07 08:21:57 2014 +0100
189.3 @@ -0,0 +1,81 @@
189.4 +/**
189.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
189.6 + *
189.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
189.8 + *
189.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
189.10 + * Other names may be trademarks of their respective owners.
189.11 + *
189.12 + * The contents of this file are subject to the terms of either the GNU
189.13 + * General Public License Version 2 only ("GPL") or the Common
189.14 + * Development and Distribution License("CDDL") (collectively, the
189.15 + * "License"). You may not use this file except in compliance with the
189.16 + * License. You can obtain a copy of the License at
189.17 + * http://www.netbeans.org/cddl-gplv2.html
189.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
189.19 + * specific language governing permissions and limitations under the
189.20 + * License. When distributing the software, include this License Header
189.21 + * Notice in each file and include the License file at
189.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
189.23 + * particular file as subject to the "Classpath" exception as provided
189.24 + * by Oracle in the GPL Version 2 section of the License file that
189.25 + * accompanied this code. If applicable, add the following below the
189.26 + * License Header, with the fields enclosed by brackets [] replaced by
189.27 + * your own identifying information:
189.28 + * "Portions Copyrighted [year] [name of copyright owner]"
189.29 + *
189.30 + * Contributor(s):
189.31 + *
189.32 + * The Original Software is NetBeans. The Initial Developer of the Original
189.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
189.34 + *
189.35 + * If you wish your version of this file to be governed by only the CDDL
189.36 + * or only the GPL Version 2, indicate your decision by adding
189.37 + * "[Contributor] elects to include this software in this distribution
189.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
189.39 + * single choice of license, a recipient has the option to distribute
189.40 + * your version of this file under either the CDDL, the GPL Version 2 or
189.41 + * to extend the choice of license to its licensees as provided above.
189.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
189.43 + * Version 2 license, then the option applies only if the new code is
189.44 + * made subject to such option by the copyright holder.
189.45 + */
189.46 +package org.netbeans.html.kofx;
189.47 +
189.48 +import java.util.logging.Level;
189.49 +import java.util.logging.Logger;
189.50 +import net.java.html.js.JavaScriptBody;
189.51 +
189.52 +/** This is an implementation package - just
189.53 + * include its JAR on classpath and use official {@link Context} API
189.54 + * to access the functionality.
189.55 + * <p>
189.56 + * Redirects JavaScript's messages to Java's {@link Logger}.
189.57 + *
189.58 + * @author Jaroslav Tulach <jtulach@netbeans.org>
189.59 + */
189.60 +final class Console {
189.61 + private static final Logger LOG = Logger.getLogger(Console.class.getName());
189.62 +
189.63 + private Console() {
189.64 + }
189.65 +
189.66 + static void register() {
189.67 + registerImpl("log", Level.INFO);
189.68 + registerImpl("info", Level.INFO);
189.69 + registerImpl("warn", Level.WARNING);
189.70 + registerImpl("error", Level.SEVERE);
189.71 + }
189.72 +
189.73 + @JavaScriptBody(args = { "attr", "l" },
189.74 + javacall = true, body =
189.75 + " window.console[attr] = function(m) {\n"
189.76 + + " @org.netbeans.html.kofx.Console::log(Ljava/util/logging/Level;Ljava/lang/String;)(l, m);\n"
189.77 + + " };\n"
189.78 + )
189.79 + private static native void registerImpl(String attr, Level l);
189.80 +
189.81 + static void log(Level l, String msg) {
189.82 + LOG.log(l, msg);
189.83 + }
189.84 +}
190.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
190.2 +++ b/ko-fx/src/main/java/org/netbeans/html/kofx/FXContext.java Tue Jan 07 08:21:57 2014 +0100
190.3 @@ -0,0 +1,222 @@
190.4 +/**
190.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
190.6 + *
190.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
190.8 + *
190.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
190.10 + * Other names may be trademarks of their respective owners.
190.11 + *
190.12 + * The contents of this file are subject to the terms of either the GNU
190.13 + * General Public License Version 2 only ("GPL") or the Common
190.14 + * Development and Distribution License("CDDL") (collectively, the
190.15 + * "License"). You may not use this file except in compliance with the
190.16 + * License. You can obtain a copy of the License at
190.17 + * http://www.netbeans.org/cddl-gplv2.html
190.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
190.19 + * specific language governing permissions and limitations under the
190.20 + * License. When distributing the software, include this License Header
190.21 + * Notice in each file and include the License file at
190.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
190.23 + * particular file as subject to the "Classpath" exception as provided
190.24 + * by Oracle in the GPL Version 2 section of the License file that
190.25 + * accompanied this code. If applicable, add the following below the
190.26 + * License Header, with the fields enclosed by brackets [] replaced by
190.27 + * your own identifying information:
190.28 + * "Portions Copyrighted [year] [name of copyright owner]"
190.29 + *
190.30 + * Contributor(s):
190.31 + *
190.32 + * The Original Software is NetBeans. The Initial Developer of the Original
190.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
190.34 + *
190.35 + * If you wish your version of this file to be governed by only the CDDL
190.36 + * or only the GPL Version 2, indicate your decision by adding
190.37 + * "[Contributor] elects to include this software in this distribution
190.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
190.39 + * single choice of license, a recipient has the option to distribute
190.40 + * your version of this file under either the CDDL, the GPL Version 2 or
190.41 + * to extend the choice of license to its licensees as provided above.
190.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
190.43 + * Version 2 license, then the option applies only if the new code is
190.44 + * made subject to such option by the copyright holder.
190.45 + */
190.46 +package org.netbeans.html.kofx;
190.47 +
190.48 +import java.io.Closeable;
190.49 +import java.io.IOException;
190.50 +import java.io.InputStream;
190.51 +import java.util.ServiceLoader;
190.52 +import java.util.logging.Logger;
190.53 +import javafx.application.Platform;
190.54 +import net.java.html.js.JavaScriptBody;
190.55 +import netscape.javascript.JSObject;
190.56 +import org.apidesign.html.boot.spi.Fn;
190.57 +import org.apidesign.html.context.spi.Contexts;
190.58 +import org.apidesign.html.json.spi.FunctionBinding;
190.59 +import org.apidesign.html.json.spi.JSONCall;
190.60 +import org.apidesign.html.json.spi.PropertyBinding;
190.61 +import org.apidesign.html.json.spi.Technology;
190.62 +import org.apidesign.html.json.spi.Transfer;
190.63 +import org.apidesign.html.json.spi.WSTransfer;
190.64 +import org.openide.util.lookup.ServiceProvider;
190.65 +
190.66 +/** This is an implementation package - just
190.67 + * include its JAR on classpath and use official {@link Context} API
190.68 + * to access the functionality.
190.69 + * <p>
190.70 + * Registers {@link ContextProvider}, so {@link ServiceLoader} can find it.
190.71 + *
190.72 + * @author Jaroslav Tulach <jtulach@netbeans.org>
190.73 + */
190.74 +public final class FXContext
190.75 +implements Technology.BatchInit<JSObject>, Transfer, WSTransfer<LoadWS> {
190.76 + static final Logger LOG = Logger.getLogger(FXContext.class.getName());
190.77 + private static Boolean javaScriptEnabled;
190.78 + private final Fn.Presenter browserContext;
190.79 +
190.80 + public FXContext(Fn.Presenter browserContext) {
190.81 + this.browserContext = browserContext;
190.82 + }
190.83 +
190.84 + @JavaScriptBody(args = {}, body = "return true;")
190.85 + private static boolean isJavaScriptEnabledJs() {
190.86 + return false;
190.87 + }
190.88 +
190.89 + static boolean isJavaScriptEnabled() {
190.90 + if (javaScriptEnabled != null) {
190.91 + return javaScriptEnabled;
190.92 + }
190.93 + return javaScriptEnabled = isJavaScriptEnabledJs();
190.94 + }
190.95 +
190.96 + final boolean areWebSocketsSupported() {
190.97 + return LoadWS.isSupported();
190.98 + }
190.99 +
190.100 +
190.101 + @Override
190.102 + public JSObject wrapModel(Object model, PropertyBinding[] propArr, FunctionBinding[] funcArr) {
190.103 + String[] propNames = new String[propArr.length];
190.104 + boolean[] propReadOnly = new boolean[propArr.length];
190.105 + Object[] propValues = new Object[propArr.length];
190.106 + for (int i = 0; i < propNames.length; i++) {
190.107 + propNames[i] = propArr[i].getPropertyName();
190.108 + propReadOnly[i] = propArr[i].isReadOnly();
190.109 + propValues[i] = propArr[i].getValue();
190.110 + }
190.111 + String[] funcNames = new String[funcArr.length];
190.112 + for (int i = 0; i < funcNames.length; i++) {
190.113 + funcNames[i] = funcArr[i].getFunctionName();
190.114 + }
190.115 +
190.116 + return Knockout.wrapModel(model,
190.117 + propNames, propReadOnly, Knockout.toArray(propValues), propArr,
190.118 + funcNames, funcArr
190.119 + );
190.120 + }
190.121 +
190.122 + @Override
190.123 + public JSObject wrapModel(Object model) {
190.124 + throw new UnsupportedOperationException();
190.125 + }
190.126 +
190.127 + @Override
190.128 + public void bind(PropertyBinding b, Object model, JSObject data) {
190.129 + throw new UnsupportedOperationException();
190.130 + }
190.131 +
190.132 + @Override
190.133 + public void valueHasMutated(JSObject data, String propertyName) {
190.134 + Knockout.valueHasMutated(data, propertyName);
190.135 + }
190.136 +
190.137 + @Override
190.138 + public void expose(FunctionBinding fb, Object model, JSObject d) {
190.139 + throw new UnsupportedOperationException();
190.140 + }
190.141 +
190.142 + @Override
190.143 + public void applyBindings(JSObject data) {
190.144 + Knockout.applyBindings(data);
190.145 + }
190.146 +
190.147 + @Override
190.148 + public Object wrapArray(Object[] arr) {
190.149 + return Knockout.toArray(arr);
190.150 + }
190.151 +
190.152 + @Override
190.153 + public void extract(Object obj, String[] props, Object[] values) {
190.154 + LoadJSON.extractJSON(obj, props, values);
190.155 + }
190.156 +
190.157 + @Override
190.158 + public void loadJSON(final JSONCall call) {
190.159 + LoadJSON.loadJSON(call);
190.160 + }
190.161 +
190.162 + @Override
190.163 + public <M> M toModel(Class<M> modelClass, Object data) {
190.164 + if (data instanceof JSObject) {
190.165 + data = ((JSObject)data).getMember("ko-fx.model"); // NOI18N
190.166 + }
190.167 + return modelClass.cast(data);
190.168 + }
190.169 +
190.170 + @Override
190.171 + public Object toJSON(InputStream is) throws IOException {
190.172 + return LoadJSON.parse(is);
190.173 + }
190.174 +
190.175 + @Override
190.176 + public void runSafe(final Runnable r) {
190.177 + class Wrap implements Runnable {
190.178 + @Override public void run() {
190.179 + try (Closeable c = Fn.activate(browserContext)) {
190.180 + r.run();
190.181 + } catch (IOException ex) {
190.182 + // cannot be thrown
190.183 + }
190.184 + }
190.185 + }
190.186 + Wrap w = new Wrap();
190.187 +
190.188 + if (Platform.isFxApplicationThread()) {
190.189 + w.run();
190.190 + } else {
190.191 + Platform.runLater(w);
190.192 + }
190.193 + }
190.194 +
190.195 + @Override
190.196 + public LoadWS open(String url, JSONCall onReply) {
190.197 + return new LoadWS(onReply, url);
190.198 + }
190.199 +
190.200 + @Override
190.201 + public void send(LoadWS socket, JSONCall data) {
190.202 + socket.send(data);
190.203 + }
190.204 +
190.205 + @Override
190.206 + public void close(LoadWS socket) {
190.207 + socket.close();
190.208 + }
190.209 +
190.210 + @ServiceProvider(service = Contexts.Provider.class)
190.211 + public static final class Prvdr implements Contexts.Provider {
190.212 + @Override
190.213 + public void fillContext(Contexts.Builder context, Class<?> requestor) {
190.214 + if (isJavaScriptEnabled()) {
190.215 + FXContext c = new FXContext(Fn.activePresenter());
190.216 +
190.217 + context.register(Technology.class, c, 100);
190.218 + context.register(Transfer.class, c, 100);
190.219 + if (c.areWebSocketsSupported()) {
190.220 + context.register(WSTransfer.class, c, 100);
190.221 + }
190.222 + }
190.223 + }
190.224 + }
190.225 +}
191.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
191.2 +++ b/ko-fx/src/main/java/org/netbeans/html/kofx/Knockout.java Tue Jan 07 08:21:57 2014 +0100
191.3 @@ -0,0 +1,145 @@
191.4 +/**
191.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
191.6 + *
191.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
191.8 + *
191.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
191.10 + * Other names may be trademarks of their respective owners.
191.11 + *
191.12 + * The contents of this file are subject to the terms of either the GNU
191.13 + * General Public License Version 2 only ("GPL") or the Common
191.14 + * Development and Distribution License("CDDL") (collectively, the
191.15 + * "License"). You may not use this file except in compliance with the
191.16 + * License. You can obtain a copy of the License at
191.17 + * http://www.netbeans.org/cddl-gplv2.html
191.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
191.19 + * specific language governing permissions and limitations under the
191.20 + * License. When distributing the software, include this License Header
191.21 + * Notice in each file and include the License file at
191.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
191.23 + * particular file as subject to the "Classpath" exception as provided
191.24 + * by Oracle in the GPL Version 2 section of the License file that
191.25 + * accompanied this code. If applicable, add the following below the
191.26 + * License Header, with the fields enclosed by brackets [] replaced by
191.27 + * your own identifying information:
191.28 + * "Portions Copyrighted [year] [name of copyright owner]"
191.29 + *
191.30 + * Contributor(s):
191.31 + *
191.32 + * The Original Software is NetBeans. The Initial Developer of the Original
191.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
191.34 + *
191.35 + * If you wish your version of this file to be governed by only the CDDL
191.36 + * or only the GPL Version 2, indicate your decision by adding
191.37 + * "[Contributor] elects to include this software in this distribution
191.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
191.39 + * single choice of license, a recipient has the option to distribute
191.40 + * your version of this file under either the CDDL, the GPL Version 2 or
191.41 + * to extend the choice of license to its licensees as provided above.
191.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
191.43 + * Version 2 license, then the option applies only if the new code is
191.44 + * made subject to such option by the copyright holder.
191.45 + */
191.46 +package org.netbeans.html.kofx;
191.47 +
191.48 +import net.java.html.js.JavaScriptBody;
191.49 +import net.java.html.js.JavaScriptResource;
191.50 +import net.java.html.json.Model;
191.51 +import netscape.javascript.JSObject;
191.52 +import org.apidesign.html.json.spi.FunctionBinding;
191.53 +import org.apidesign.html.json.spi.PropertyBinding;
191.54 +
191.55 +/** This is an implementation package - just
191.56 + * include its JAR on classpath and use official {@link Context} API
191.57 + * to access the functionality.
191.58 + * <p>
191.59 + * Provides binding between {@link Model models} and knockout.js running
191.60 + * inside a JavaFX WebView.
191.61 + *
191.62 + * @author Jaroslav Tulach <jtulach@netbeans.org>
191.63 + */
191.64 +@JavaScriptResource("knockout-2.2.1.js")
191.65 +final class Knockout {
191.66 + static final JSObject KObject;
191.67 + static {
191.68 + Console.register();
191.69 + KObject = (JSObject) kObj();
191.70 + }
191.71 +
191.72 + static Object toArray(Object[] arr) {
191.73 + return KObject.call("array", arr);
191.74 + }
191.75 +
191.76 + @JavaScriptBody(args = { "model", "prop" }, body =
191.77 + "if (model) {\n"
191.78 + + " var koProp = model[prop];\n"
191.79 + + " if (koProp && koProp['valueHasMutated']) {\n"
191.80 + + " koProp['valueHasMutated']();\n"
191.81 + + " }\n"
191.82 + + "}\n"
191.83 + )
191.84 + public native static void valueHasMutated(JSObject model, String prop);
191.85 +
191.86 + @JavaScriptBody(args = { "bindings" }, body = "ko.applyBindings(bindings);")
191.87 + native static void applyBindings(Object bindings);
191.88 +
191.89 + @JavaScriptBody(args = {}, body =
191.90 + " var k = {};"
191.91 + + " k.array= function() {"
191.92 + + " return Array.prototype.slice.call(arguments);"
191.93 + + " };"
191.94 + + " return k;"
191.95 + )
191.96 + private static native Object kObj();
191.97 +
191.98 +
191.99 + @JavaScriptBody(
191.100 + javacall = true,
191.101 + args = {"model", "propNames", "propReadOnly", "propValues", "propArr", "funcNames", "funcArr"},
191.102 + body
191.103 + = "var ret = {};\n"
191.104 + + "ret['ko-fx.model'] = model;\n"
191.105 + + "function koComputed(name, readOnly, value, prop) {\n"
191.106 + + " function realGetter() {\n"
191.107 + + " try {"
191.108 + + " var v = prop.@org.apidesign.html.json.spi.PropertyBinding::getValue()();"
191.109 + + " return v;"
191.110 + + " } catch (e) {"
191.111 + + " alert(\"Cannot call getValue on \" + model + \" prop: \" + name + \" error: \" + e);"
191.112 + + " }"
191.113 + + " }\n"
191.114 + + " var activeGetter = function() { return value; };\n"
191.115 + + " var bnd = {"
191.116 + + " read: function() {"
191.117 + + " var r = activeGetter();"
191.118 + + " activeGetter = realGetter;"
191.119 + + " return r;"
191.120 + + " },"
191.121 + + " owner: ret\n"
191.122 + + " };\n"
191.123 + + " if (!readOnly) {\n"
191.124 + + " bnd.write = function(val) {\n"
191.125 + + " prop.@org.apidesign.html.json.spi.PropertyBinding::setValue(Ljava/lang/Object;)(val);\n"
191.126 + + " };"
191.127 + + " };"
191.128 + + " ret[name] = ko.computed(bnd);"
191.129 + + "}\n"
191.130 + + "for (var i = 0; i < propNames.length; i++) {\n"
191.131 + + " koComputed(propNames[i], propReadOnly[i], propValues[i], propArr[i]);\n"
191.132 + + "}\n"
191.133 + + "function koExpose(name, func) {\n"
191.134 + + " ret[name] = function(data, ev) {\n"
191.135 + + " func.@org.apidesign.html.json.spi.FunctionBinding::call(Ljava/lang/Object;Ljava/lang/Object;)(data, ev);\n"
191.136 + + " };\n"
191.137 + + "}\n"
191.138 + + "for (var i = 0; i < funcNames.length; i++) {\n"
191.139 + + " koExpose(funcNames[i], funcArr[i]);\n"
191.140 + + "}\n"
191.141 + + "return ret;\n"
191.142 + )
191.143 + static native JSObject wrapModel(
191.144 + Object model,
191.145 + String[] propNames, boolean[] propReadOnly, Object propValues, PropertyBinding[] propArr,
191.146 + String[] funcNames, FunctionBinding[] funcArr
191.147 + );
191.148 +}
192.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
192.2 +++ b/ko-fx/src/main/java/org/netbeans/html/kofx/LoadJSON.java Tue Jan 07 08:21:57 2014 +0100
192.3 @@ -0,0 +1,267 @@
192.4 +/**
192.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
192.6 + *
192.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
192.8 + *
192.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
192.10 + * Other names may be trademarks of their respective owners.
192.11 + *
192.12 + * The contents of this file are subject to the terms of either the GNU
192.13 + * General Public License Version 2 only ("GPL") or the Common
192.14 + * Development and Distribution License("CDDL") (collectively, the
192.15 + * "License"). You may not use this file except in compliance with the
192.16 + * License. You can obtain a copy of the License at
192.17 + * http://www.netbeans.org/cddl-gplv2.html
192.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
192.19 + * specific language governing permissions and limitations under the
192.20 + * License. When distributing the software, include this License Header
192.21 + * Notice in each file and include the License file at
192.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
192.23 + * particular file as subject to the "Classpath" exception as provided
192.24 + * by Oracle in the GPL Version 2 section of the License file that
192.25 + * accompanied this code. If applicable, add the following below the
192.26 + * License Header, with the fields enclosed by brackets [] replaced by
192.27 + * your own identifying information:
192.28 + * "Portions Copyrighted [year] [name of copyright owner]"
192.29 + *
192.30 + * Contributor(s):
192.31 + *
192.32 + * The Original Software is NetBeans. The Initial Developer of the Original
192.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
192.34 + *
192.35 + * If you wish your version of this file to be governed by only the CDDL
192.36 + * or only the GPL Version 2, indicate your decision by adding
192.37 + * "[Contributor] elects to include this software in this distribution
192.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
192.39 + * single choice of license, a recipient has the option to distribute
192.40 + * your version of this file under either the CDDL, the GPL Version 2 or
192.41 + * to extend the choice of license to its licensees as provided above.
192.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
192.43 + * Version 2 license, then the option applies only if the new code is
192.44 + * made subject to such option by the copyright holder.
192.45 + */
192.46 +package org.netbeans.html.kofx;
192.47 +
192.48 +import java.io.IOException;
192.49 +import java.io.InputStream;
192.50 +import java.io.InputStreamReader;
192.51 +import java.io.OutputStream;
192.52 +import java.io.PushbackInputStream;
192.53 +import java.io.Reader;
192.54 +import java.net.HttpURLConnection;
192.55 +import java.net.MalformedURLException;
192.56 +import java.net.URL;
192.57 +import java.net.URLConnection;
192.58 +import java.util.Iterator;
192.59 +import java.util.concurrent.Executor;
192.60 +import java.util.concurrent.Executors;
192.61 +import java.util.concurrent.ThreadFactory;
192.62 +import java.util.logging.Level;
192.63 +import java.util.logging.Logger;
192.64 +import javafx.application.Platform;
192.65 +import net.java.html.js.JavaScriptBody;
192.66 +import netscape.javascript.JSObject;
192.67 +import org.apidesign.html.json.spi.JSONCall;
192.68 +import org.json.JSONArray;
192.69 +import org.json.JSONException;
192.70 +import org.json.JSONObject;
192.71 +import org.json.JSONTokener;
192.72 +
192.73 +/** This is an implementation package - just
192.74 + * include its JAR on classpath and use official {@link Context} API
192.75 + * to access the functionality.
192.76 + *
192.77 + * @author Jaroslav Tulach <jtulach@netbeans.org>
192.78 + */
192.79 +final class LoadJSON implements Runnable {
192.80 + private static final Logger LOG = FXContext.LOG;
192.81 + private static final Executor REQ = Executors.newCachedThreadPool(new ThreadFactory() {
192.82 + @Override
192.83 + public Thread newThread(Runnable runnable) {
192.84 + Thread thread = Executors.defaultThreadFactory().newThread(runnable);
192.85 + thread.setDaemon(true);
192.86 + return thread;
192.87 + }
192.88 + });
192.89 +
192.90 + private final JSONCall call;
192.91 + private final URL base;
192.92 + private Throwable error;
192.93 + private Object json;
192.94 +
192.95 +
192.96 + private LoadJSON(JSONCall call) {
192.97 + this.call = call;
192.98 + URL b;
192.99 + try {
192.100 + b = new URL(findBaseURL());
192.101 + } catch (MalformedURLException ex) {
192.102 + LOG.log(Level.SEVERE, "Can't find base url for " + call.composeURL("dummy"), ex);
192.103 + b = null;
192.104 + }
192.105 + this.base = b;
192.106 + }
192.107 +
192.108 + public static void loadJSON(JSONCall call) {
192.109 + assert !"WebSocket".equals(call.getMethod());
192.110 + REQ.execute(new LoadJSON((call)));
192.111 + }
192.112 +
192.113 + @Override
192.114 + public void run() {
192.115 + if (Platform.isFxApplicationThread()) {
192.116 + if (error != null) {
192.117 + call.notifyError(error);
192.118 + } else {
192.119 + call.notifySuccess(json);
192.120 + }
192.121 + return;
192.122 + }
192.123 + final String url;
192.124 + if (call.isJSONP()) {
192.125 + url = call.composeURL("dummy");
192.126 + } else {
192.127 + url = call.composeURL(null);
192.128 + }
192.129 + try {
192.130 + final URL u = new URL(base, url.replace(" ", "%20"));
192.131 + URLConnection conn = u.openConnection();
192.132 + if (conn instanceof HttpURLConnection) {
192.133 + HttpURLConnection huc = (HttpURLConnection) conn;
192.134 + if (call.getMethod() != null) {
192.135 + huc.setRequestMethod(call.getMethod());
192.136 + }
192.137 + if (call.isDoOutput()) {
192.138 + huc.setDoOutput(true);
192.139 + final OutputStream os = huc.getOutputStream();
192.140 + call.writeData(os);
192.141 + os.flush();
192.142 + }
192.143 + }
192.144 + final PushbackInputStream is = new PushbackInputStream(
192.145 + conn.getInputStream(), 1
192.146 + );
192.147 + boolean array = false;
192.148 + boolean string = false;
192.149 + if (call.isJSONP()) {
192.150 + for (;;) {
192.151 + int ch = is.read();
192.152 + if (ch == -1) {
192.153 + break;
192.154 + }
192.155 + if (ch == '[') {
192.156 + is.unread(ch);
192.157 + array = true;
192.158 + break;
192.159 + }
192.160 + if (ch == '{') {
192.161 + is.unread(ch);
192.162 + break;
192.163 + }
192.164 + }
192.165 + } else {
192.166 + int ch = is.read();
192.167 + if (ch == -1) {
192.168 + string = true;
192.169 + } else {
192.170 + array = ch == '[';
192.171 + is.unread(ch);
192.172 + if (!array && ch != '{') {
192.173 + string = true;
192.174 + }
192.175 + }
192.176 + }
192.177 + try {
192.178 + if (string) {
192.179 + throw new JSONException("");
192.180 + }
192.181 + Reader r = new InputStreamReader(is, "UTF-8");
192.182 +
192.183 + JSONTokener tok = new JSONTokener(r);
192.184 + Object obj;
192.185 + obj = array ? new JSONArray(tok) : new JSONObject(tok);
192.186 + json = convertToArray(obj);
192.187 + } catch (JSONException ex) {
192.188 + Reader r = new InputStreamReader(is, "UTF-8");
192.189 + StringBuilder sb = new StringBuilder();
192.190 + for (;;) {
192.191 + int ch = r.read();
192.192 + if (ch == -1) {
192.193 + break;
192.194 + }
192.195 + sb.append((char)ch);
192.196 + }
192.197 + json = sb.toString();
192.198 + }
192.199 + } catch (IOException ex) {
192.200 + error = ex;
192.201 + } finally {
192.202 + Platform.runLater(this);
192.203 + }
192.204 + }
192.205 +
192.206 + static Object convertToArray(Object o) throws JSONException {
192.207 + if (o instanceof JSONArray) {
192.208 + JSONArray ja = (JSONArray)o;
192.209 + Object[] arr = new Object[ja.length()];
192.210 + for (int i = 0; i < arr.length; i++) {
192.211 + arr[i] = convertToArray(ja.get(i));
192.212 + }
192.213 + return arr;
192.214 + } else if (o instanceof JSONObject) {
192.215 + JSONObject obj = (JSONObject)o;
192.216 + Iterator it = obj.keys();
192.217 + while (it.hasNext()) {
192.218 + String key = (String)it.next();
192.219 + obj.put(key, convertToArray(obj.get(key)));
192.220 + }
192.221 + return obj;
192.222 + } else {
192.223 + return o;
192.224 + }
192.225 + }
192.226 +
192.227 + public static void extractJSON(Object jsonObject, String[] props, Object[] values) {
192.228 + if (jsonObject instanceof JSONObject) {
192.229 + JSONObject obj = (JSONObject)jsonObject;
192.230 + for (int i = 0; i < props.length; i++) {
192.231 + try {
192.232 + values[i] = obj.has(props[i]) ? obj.get(props[i]) : null;
192.233 + } catch (JSONException ex) {
192.234 + LoadJSON.LOG.log(Level.SEVERE, "Can't read " + props[i] + " from " + jsonObject, ex);
192.235 + }
192.236 + }
192.237 + }
192.238 + if (jsonObject instanceof JSObject) {
192.239 + JSObject obj = (JSObject)jsonObject;
192.240 + for (int i = 0; i < props.length; i++) {
192.241 + Object val = obj.getMember(props[i]);
192.242 + values[i] = isDefined(val) ? val : null;
192.243 + }
192.244 + }
192.245 + }
192.246 +
192.247 + public static Object parse(InputStream is) throws IOException {
192.248 + try {
192.249 + InputStreamReader r = new InputStreamReader(is, "UTF-8");
192.250 + JSONTokener t = new JSONTokener(r);
192.251 + return new JSONObject(t);
192.252 + } catch (JSONException ex) {
192.253 + throw new IOException(ex);
192.254 + }
192.255 + }
192.256 +
192.257 + @JavaScriptBody(args = { }, body =
192.258 + "var h;"
192.259 + + "if (!!window && !!window.location && !!window.location.href)\n"
192.260 + + " h = window.location.href;\n"
192.261 + + "else "
192.262 + + " h = null;"
192.263 + + "return h;\n"
192.264 + )
192.265 + private static native String findBaseURL();
192.266 +
192.267 + private static boolean isDefined(Object val) {
192.268 + return !"undefined".equals(val);
192.269 + }
192.270 +}
193.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
193.2 +++ b/ko-fx/src/main/java/org/netbeans/html/kofx/LoadWS.java Tue Jan 07 08:21:57 2014 +0100
193.3 @@ -0,0 +1,149 @@
193.4 +/**
193.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
193.6 + *
193.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
193.8 + *
193.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
193.10 + * Other names may be trademarks of their respective owners.
193.11 + *
193.12 + * The contents of this file are subject to the terms of either the GNU
193.13 + * General Public License Version 2 only ("GPL") or the Common
193.14 + * Development and Distribution License("CDDL") (collectively, the
193.15 + * "License"). You may not use this file except in compliance with the
193.16 + * License. You can obtain a copy of the License at
193.17 + * http://www.netbeans.org/cddl-gplv2.html
193.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
193.19 + * specific language governing permissions and limitations under the
193.20 + * License. When distributing the software, include this License Header
193.21 + * Notice in each file and include the License file at
193.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
193.23 + * particular file as subject to the "Classpath" exception as provided
193.24 + * by Oracle in the GPL Version 2 section of the License file that
193.25 + * accompanied this code. If applicable, add the following below the
193.26 + * License Header, with the fields enclosed by brackets [] replaced by
193.27 + * your own identifying information:
193.28 + * "Portions Copyrighted [year] [name of copyright owner]"
193.29 + *
193.30 + * Contributor(s):
193.31 + *
193.32 + * The Original Software is NetBeans. The Initial Developer of the Original
193.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
193.34 + *
193.35 + * If you wish your version of this file to be governed by only the CDDL
193.36 + * or only the GPL Version 2, indicate your decision by adding
193.37 + * "[Contributor] elects to include this software in this distribution
193.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
193.39 + * single choice of license, a recipient has the option to distribute
193.40 + * your version of this file under either the CDDL, the GPL Version 2 or
193.41 + * to extend the choice of license to its licensees as provided above.
193.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
193.43 + * Version 2 license, then the option applies only if the new code is
193.44 + * made subject to such option by the copyright holder.
193.45 + */
193.46 +package org.netbeans.html.kofx;
193.47 +
193.48 +import net.java.html.js.JavaScriptBody;
193.49 +import org.apidesign.html.json.spi.JSONCall;
193.50 +import org.json.JSONArray;
193.51 +import org.json.JSONException;
193.52 +import org.json.JSONObject;
193.53 +import org.json.JSONTokener;
193.54 +
193.55 +/** Communication with WebSockets for WebView 1.8.
193.56 + *
193.57 + * @author Jaroslav Tulach <jtulach@netbeans.org>
193.58 + */
193.59 +final class LoadWS {
193.60 + private static final boolean SUPPORTED = isWebSocket();
193.61 + private final Object ws;
193.62 + private final JSONCall call;
193.63 +
193.64 + LoadWS(JSONCall first, String url) {
193.65 + call = first;
193.66 + ws = initWebSocket(this, url);
193.67 + if (ws == null) {
193.68 + first.notifyError(new IllegalArgumentException("Wrong URL: " + url));
193.69 + }
193.70 + }
193.71 +
193.72 + static boolean isSupported() {
193.73 + return SUPPORTED;
193.74 + }
193.75 +
193.76 + void send(JSONCall call) {
193.77 + push(call);
193.78 + }
193.79 +
193.80 + private synchronized void push(JSONCall call) {
193.81 + send(ws, call.getMessage());
193.82 + }
193.83 +
193.84 + void onOpen(Object ev) {
193.85 + if (!call.isDoOutput()) {
193.86 + call.notifySuccess(null);
193.87 + }
193.88 + }
193.89 +
193.90 + void onMessage(Object ev, String data) {
193.91 + Object json;
193.92 + try {
193.93 + data = data.trim();
193.94 +
193.95 + JSONTokener tok = new JSONTokener(data);
193.96 + Object obj;
193.97 + obj = data.startsWith("[") ? new JSONArray(tok) : new JSONObject(tok);
193.98 + json = LoadJSON.convertToArray(obj);
193.99 + } catch (JSONException ex) {
193.100 + json = data;
193.101 + }
193.102 + call.notifySuccess(json);
193.103 + }
193.104 +
193.105 + void onError(Object ev) {
193.106 + call.notifyError(new Exception(ev.toString()));
193.107 + }
193.108 +
193.109 + void onClose(boolean wasClean, int code, String reason) {
193.110 + call.notifyError(null);
193.111 + }
193.112 +
193.113 + @JavaScriptBody(args = {}, body = "if (window.WebSocket) return true; else return false;")
193.114 + private static boolean isWebSocket() {
193.115 + return false;
193.116 + }
193.117 +
193.118 + @JavaScriptBody(args = { "back", "url" }, javacall = true, body = ""
193.119 + + "if (window.WebSocket) {"
193.120 + + " try {"
193.121 + + " var ws = new window.WebSocket(url);"
193.122 + + " ws.onopen = function(ev) { back.@org.netbeans.html.kofx.LoadWS::onOpen(Ljava/lang/Object;)(ev); };"
193.123 + + " ws.onmessage = function(ev) { back.@org.netbeans.html.kofx.LoadWS::onMessage(Ljava/lang/Object;Ljava/lang/String;)(ev, ev.data); };"
193.124 + + " ws.onerror = function(ev) { back.@org.netbeans.html.kofx.LoadWS::onError(Ljava/lang/Object;)(ev); };"
193.125 + + " ws.onclose = function(ev) { back.@org.netbeans.html.kofx.LoadWS::onClose(ZILjava/lang/String;)(ev.wasClean, ev.code, ev.reason); };"
193.126 + + " return ws;"
193.127 + + " } catch (ex) {"
193.128 + + " return null;"
193.129 + + " }"
193.130 + + "} else {"
193.131 + + " return null;"
193.132 + + "}"
193.133 + )
193.134 + private static Object initWebSocket(Object back, String url) {
193.135 + return null;
193.136 + }
193.137 +
193.138 +
193.139 + @JavaScriptBody(args = { "ws", "msg" }, body = ""
193.140 + + "ws.send(msg);"
193.141 + )
193.142 + private void send(Object ws, String msg) {
193.143 + }
193.144 +
193.145 + @JavaScriptBody(args = { "ws" }, body = "ws.close();")
193.146 + private static void close(Object ws) {
193.147 + }
193.148 +
193.149 + void close() {
193.150 + close(ws);
193.151 + }
193.152 +}
194.1 --- a/ko-fx/src/main/resources/org/apidesign/html/kofx/knockout-2.2.1.js Thu Dec 19 17:11:01 2013 +0100
194.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
194.3 @@ -1,3594 +0,0 @@
194.4 -// Knockout JavaScript library v2.2.1
194.5 -// (c) Steven Sanderson - http://knockoutjs.com/
194.6 -// License: MIT (http://www.opensource.org/licenses/mit-license.php)
194.7 -
194.8 -(function(){
194.9 -var DEBUG=true;
194.10 -(function(window,document,navigator,jQuery,undefined){
194.11 -!function(factory) {
194.12 - // Support three module loading scenarios
194.13 - if (typeof require === 'function' && typeof exports === 'object' && typeof module === 'object') {
194.14 - // [1] CommonJS/Node.js
194.15 - var target = module['exports'] || exports; // module.exports is for Node.js
194.16 - factory(target);
194.17 - } else if (typeof define === 'function' && define['amd']) {
194.18 - // [2] AMD anonymous module
194.19 - define(['exports'], factory);
194.20 - } else {
194.21 - // [3] No module loader (plain <script> tag) - put directly in global namespace
194.22 - factory(window['ko'] = {});
194.23 - }
194.24 -}(function(koExports){
194.25 -// Internally, all KO objects are attached to koExports (even the non-exported ones whose names will be minified by the closure compiler).
194.26 -// In the future, the following "ko" variable may be made distinct from "koExports" so that private objects are not externally reachable.
194.27 -var ko = typeof koExports !== 'undefined' ? koExports : {};
194.28 -// Google Closure Compiler helpers (used only to make the minified file smaller)
194.29 -ko.exportSymbol = function(koPath, object) {
194.30 - var tokens = koPath.split(".");
194.31 -
194.32 - // In the future, "ko" may become distinct from "koExports" (so that non-exported objects are not reachable)
194.33 - // At that point, "target" would be set to: (typeof koExports !== "undefined" ? koExports : ko)
194.34 - var target = ko;
194.35 -
194.36 - for (var i = 0; i < tokens.length - 1; i++)
194.37 - target = target[tokens[i]];
194.38 - target[tokens[tokens.length - 1]] = object;
194.39 -};
194.40 -ko.exportProperty = function(owner, publicName, object) {
194.41 - owner[publicName] = object;
194.42 -};
194.43 -ko.version = "2.2.1";
194.44 -
194.45 -ko.exportSymbol('version', ko.version);
194.46 -ko.utils = new (function () {
194.47 - var stringTrimRegex = /^(\s|\u00A0)+|(\s|\u00A0)+$/g;
194.48 -
194.49 - // Represent the known event types in a compact way, then at runtime transform it into a hash with event name as key (for fast lookup)
194.50 - var knownEvents = {}, knownEventTypesByEventName = {};
194.51 - var keyEventTypeName = /Firefox\/2/i.test(navigator.userAgent) ? 'KeyboardEvent' : 'UIEvents';
194.52 - knownEvents[keyEventTypeName] = ['keyup', 'keydown', 'keypress'];
194.53 - knownEvents['MouseEvents'] = ['click', 'dblclick', 'mousedown', 'mouseup', 'mousemove', 'mouseover', 'mouseout', 'mouseenter', 'mouseleave'];
194.54 - for (var eventType in knownEvents) {
194.55 - var knownEventsForType = knownEvents[eventType];
194.56 - if (knownEventsForType.length) {
194.57 - for (var i = 0, j = knownEventsForType.length; i < j; i++)
194.58 - knownEventTypesByEventName[knownEventsForType[i]] = eventType;
194.59 - }
194.60 - }
194.61 - var eventsThatMustBeRegisteredUsingAttachEvent = { 'propertychange': true }; // Workaround for an IE9 issue - https://github.com/SteveSanderson/knockout/issues/406
194.62 -
194.63 - // Detect IE versions for bug workarounds (uses IE conditionals, not UA string, for robustness)
194.64 - // Note that, since IE 10 does not support conditional comments, the following logic only detects IE < 10.
194.65 - // Currently this is by design, since IE 10+ behaves correctly when treated as a standard browser.
194.66 - // If there is a future need to detect specific versions of IE10+, we will amend this.
194.67 - var ieVersion = (function() {
194.68 - var version = 3, div = document.createElement('div'), iElems = div.getElementsByTagName('i');
194.69 -
194.70 - // Keep constructing conditional HTML blocks until we hit one that resolves to an empty fragment
194.71 - while (
194.72 - div.innerHTML = '<!--[if gt IE ' + (++version) + ']><i></i><![endif]-->',
194.73 - iElems[0]
194.74 - );
194.75 - return version > 4 ? version : undefined;
194.76 - }());
194.77 - var isIe6 = ieVersion === 6,
194.78 - isIe7 = ieVersion === 7;
194.79 -
194.80 - function isClickOnCheckableElement(element, eventType) {
194.81 - if ((ko.utils.tagNameLower(element) !== "input") || !element.type) return false;
194.82 - if (eventType.toLowerCase() != "click") return false;
194.83 - var inputType = element.type;
194.84 - return (inputType == "checkbox") || (inputType == "radio");
194.85 - }
194.86 -
194.87 - return {
194.88 - fieldsIncludedWithJsonPost: ['authenticity_token', /^__RequestVerificationToken(_.*)?$/],
194.89 -
194.90 - arrayForEach: function (array, action) {
194.91 - for (var i = 0, j = array.length; i < j; i++)
194.92 - action(array[i]);
194.93 - },
194.94 -
194.95 - arrayIndexOf: function (array, item) {
194.96 - if (typeof Array.prototype.indexOf == "function")
194.97 - return Array.prototype.indexOf.call(array, item);
194.98 - for (var i = 0, j = array.length; i < j; i++)
194.99 - if (array[i] === item)
194.100 - return i;
194.101 - return -1;
194.102 - },
194.103 -
194.104 - arrayFirst: function (array, predicate, predicateOwner) {
194.105 - for (var i = 0, j = array.length; i < j; i++)
194.106 - if (predicate.call(predicateOwner, array[i]))
194.107 - return array[i];
194.108 - return null;
194.109 - },
194.110 -
194.111 - arrayRemoveItem: function (array, itemToRemove) {
194.112 - var index = ko.utils.arrayIndexOf(array, itemToRemove);
194.113 - if (index >= 0)
194.114 - array.splice(index, 1);
194.115 - },
194.116 -
194.117 - arrayGetDistinctValues: function (array) {
194.118 - array = array || [];
194.119 - var result = [];
194.120 - for (var i = 0, j = array.length; i < j; i++) {
194.121 - if (ko.utils.arrayIndexOf(result, array[i]) < 0)
194.122 - result.push(array[i]);
194.123 - }
194.124 - return result;
194.125 - },
194.126 -
194.127 - arrayMap: function (array, mapping) {
194.128 - array = array || [];
194.129 - var result = [];
194.130 - for (var i = 0, j = array.length; i < j; i++)
194.131 - result.push(mapping(array[i]));
194.132 - return result;
194.133 - },
194.134 -
194.135 - arrayFilter: function (array, predicate) {
194.136 - array = array || [];
194.137 - var result = [];
194.138 - for (var i = 0, j = array.length; i < j; i++)
194.139 - if (predicate(array[i]))
194.140 - result.push(array[i]);
194.141 - return result;
194.142 - },
194.143 -
194.144 - arrayPushAll: function (array, valuesToPush) {
194.145 - if (valuesToPush instanceof Array)
194.146 - array.push.apply(array, valuesToPush);
194.147 - else
194.148 - for (var i = 0, j = valuesToPush.length; i < j; i++)
194.149 - array.push(valuesToPush[i]);
194.150 - return array;
194.151 - },
194.152 -
194.153 - extend: function (target, source) {
194.154 - if (source) {
194.155 - for(var prop in source) {
194.156 - if(source.hasOwnProperty(prop)) {
194.157 - target[prop] = source[prop];
194.158 - }
194.159 - }
194.160 - }
194.161 - return target;
194.162 - },
194.163 -
194.164 - emptyDomNode: function (domNode) {
194.165 - while (domNode.firstChild) {
194.166 - ko.removeNode(domNode.firstChild);
194.167 - }
194.168 - },
194.169 -
194.170 - moveCleanedNodesToContainerElement: function(nodes) {
194.171 - // Ensure it's a real array, as we're about to reparent the nodes and
194.172 - // we don't want the underlying collection to change while we're doing that.
194.173 - var nodesArray = ko.utils.makeArray(nodes);
194.174 -
194.175 - var container = document.createElement('div');
194.176 - for (var i = 0, j = nodesArray.length; i < j; i++) {
194.177 - container.appendChild(ko.cleanNode(nodesArray[i]));
194.178 - }
194.179 - return container;
194.180 - },
194.181 -
194.182 - cloneNodes: function (nodesArray, shouldCleanNodes) {
194.183 - for (var i = 0, j = nodesArray.length, newNodesArray = []; i < j; i++) {
194.184 - var clonedNode = nodesArray[i].cloneNode(true);
194.185 - newNodesArray.push(shouldCleanNodes ? ko.cleanNode(clonedNode) : clonedNode);
194.186 - }
194.187 - return newNodesArray;
194.188 - },
194.189 -
194.190 - setDomNodeChildren: function (domNode, childNodes) {
194.191 - ko.utils.emptyDomNode(domNode);
194.192 - if (childNodes) {
194.193 - for (var i = 0, j = childNodes.length; i < j; i++)
194.194 - domNode.appendChild(childNodes[i]);
194.195 - }
194.196 - },
194.197 -
194.198 - replaceDomNodes: function (nodeToReplaceOrNodeArray, newNodesArray) {
194.199 - var nodesToReplaceArray = nodeToReplaceOrNodeArray.nodeType ? [nodeToReplaceOrNodeArray] : nodeToReplaceOrNodeArray;
194.200 - if (nodesToReplaceArray.length > 0) {
194.201 - var insertionPoint = nodesToReplaceArray[0];
194.202 - var parent = insertionPoint.parentNode;
194.203 - for (var i = 0, j = newNodesArray.length; i < j; i++)
194.204 - parent.insertBefore(newNodesArray[i], insertionPoint);
194.205 - for (var i = 0, j = nodesToReplaceArray.length; i < j; i++) {
194.206 - ko.removeNode(nodesToReplaceArray[i]);
194.207 - }
194.208 - }
194.209 - },
194.210 -
194.211 - setOptionNodeSelectionState: function (optionNode, isSelected) {
194.212 - // IE6 sometimes throws "unknown error" if you try to write to .selected directly, whereas Firefox struggles with setAttribute. Pick one based on browser.
194.213 - if (ieVersion < 7)
194.214 - optionNode.setAttribute("selected", isSelected);
194.215 - else
194.216 - optionNode.selected = isSelected;
194.217 - },
194.218 -
194.219 - stringTrim: function (string) {
194.220 - return (string || "").replace(stringTrimRegex, "");
194.221 - },
194.222 -
194.223 - stringTokenize: function (string, delimiter) {
194.224 - var result = [];
194.225 - var tokens = (string || "").split(delimiter);
194.226 - for (var i = 0, j = tokens.length; i < j; i++) {
194.227 - var trimmed = ko.utils.stringTrim(tokens[i]);
194.228 - if (trimmed !== "")
194.229 - result.push(trimmed);
194.230 - }
194.231 - return result;
194.232 - },
194.233 -
194.234 - stringStartsWith: function (string, startsWith) {
194.235 - string = string || "";
194.236 - if (startsWith.length > string.length)
194.237 - return false;
194.238 - return string.substring(0, startsWith.length) === startsWith;
194.239 - },
194.240 -
194.241 - domNodeIsContainedBy: function (node, containedByNode) {
194.242 - if (containedByNode.compareDocumentPosition)
194.243 - return (containedByNode.compareDocumentPosition(node) & 16) == 16;
194.244 - while (node != null) {
194.245 - if (node == containedByNode)
194.246 - return true;
194.247 - node = node.parentNode;
194.248 - }
194.249 - return false;
194.250 - },
194.251 -
194.252 - domNodeIsAttachedToDocument: function (node) {
194.253 - return ko.utils.domNodeIsContainedBy(node, node.ownerDocument);
194.254 - },
194.255 -
194.256 - tagNameLower: function(element) {
194.257 - // For HTML elements, tagName will always be upper case; for XHTML elements, it'll be lower case.
194.258 - // Possible future optimization: If we know it's an element from an XHTML document (not HTML),
194.259 - // we don't need to do the .toLowerCase() as it will always be lower case anyway.
194.260 - return element && element.tagName && element.tagName.toLowerCase();
194.261 - },
194.262 -
194.263 - registerEventHandler: function (element, eventType, handler) {
194.264 - var mustUseAttachEvent = ieVersion && eventsThatMustBeRegisteredUsingAttachEvent[eventType];
194.265 - if (!mustUseAttachEvent && typeof jQuery != "undefined") {
194.266 - if (isClickOnCheckableElement(element, eventType)) {
194.267 - // For click events on checkboxes, jQuery interferes with the event handling in an awkward way:
194.268 - // it toggles the element checked state *after* the click event handlers run, whereas native
194.269 - // click events toggle the checked state *before* the event handler.
194.270 - // Fix this by intecepting the handler and applying the correct checkedness before it runs.
194.271 - var originalHandler = handler;
194.272 - handler = function(event, eventData) {
194.273 - var jQuerySuppliedCheckedState = this.checked;
194.274 - if (eventData)
194.275 - this.checked = eventData.checkedStateBeforeEvent !== true;
194.276 - originalHandler.call(this, event);
194.277 - this.checked = jQuerySuppliedCheckedState; // Restore the state jQuery applied
194.278 - };
194.279 - }
194.280 - jQuery(element)['bind'](eventType, handler);
194.281 - } else if (!mustUseAttachEvent && typeof element.addEventListener == "function")
194.282 - element.addEventListener(eventType, handler, false);
194.283 - else if (typeof element.attachEvent != "undefined")
194.284 - element.attachEvent("on" + eventType, function (event) {
194.285 - handler.call(element, event);
194.286 - });
194.287 - else
194.288 - throw new Error("Browser doesn't support addEventListener or attachEvent");
194.289 - },
194.290 -
194.291 - triggerEvent: function (element, eventType) {
194.292 - if (!(element && element.nodeType))
194.293 - throw new Error("element must be a DOM node when calling triggerEvent");
194.294 -
194.295 - if (typeof jQuery != "undefined") {
194.296 - var eventData = [];
194.297 - if (isClickOnCheckableElement(element, eventType)) {
194.298 - // Work around the jQuery "click events on checkboxes" issue described above by storing the original checked state before triggering the handler
194.299 - eventData.push({ checkedStateBeforeEvent: element.checked });
194.300 - }
194.301 - jQuery(element)['trigger'](eventType, eventData);
194.302 - } else if (typeof document.createEvent == "function") {
194.303 - if (typeof element.dispatchEvent == "function") {
194.304 - var eventCategory = knownEventTypesByEventName[eventType] || "HTMLEvents";
194.305 - var event = document.createEvent(eventCategory);
194.306 - event.initEvent(eventType, true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, element);
194.307 - element.dispatchEvent(event);
194.308 - }
194.309 - else
194.310 - throw new Error("The supplied element doesn't support dispatchEvent");
194.311 - } else if (typeof element.fireEvent != "undefined") {
194.312 - // Unlike other browsers, IE doesn't change the checked state of checkboxes/radiobuttons when you trigger their "click" event
194.313 - // so to make it consistent, we'll do it manually here
194.314 - if (isClickOnCheckableElement(element, eventType))
194.315 - element.checked = element.checked !== true;
194.316 - element.fireEvent("on" + eventType);
194.317 - }
194.318 - else
194.319 - throw new Error("Browser doesn't support triggering events");
194.320 - },
194.321 -
194.322 - unwrapObservable: function (value) {
194.323 - return ko.isObservable(value) ? value() : value;
194.324 - },
194.325 -
194.326 - peekObservable: function (value) {
194.327 - return ko.isObservable(value) ? value.peek() : value;
194.328 - },
194.329 -
194.330 - toggleDomNodeCssClass: function (node, classNames, shouldHaveClass) {
194.331 - if (classNames) {
194.332 - var cssClassNameRegex = /[\w-]+/g,
194.333 - currentClassNames = node.className.match(cssClassNameRegex) || [];
194.334 - ko.utils.arrayForEach(classNames.match(cssClassNameRegex), function(className) {
194.335 - var indexOfClass = ko.utils.arrayIndexOf(currentClassNames, className);
194.336 - if (indexOfClass >= 0) {
194.337 - if (!shouldHaveClass)
194.338 - currentClassNames.splice(indexOfClass, 1);
194.339 - } else {
194.340 - if (shouldHaveClass)
194.341 - currentClassNames.push(className);
194.342 - }
194.343 - });
194.344 - node.className = currentClassNames.join(" ");
194.345 - }
194.346 - },
194.347 -
194.348 - setTextContent: function(element, textContent) {
194.349 - var value = ko.utils.unwrapObservable(textContent);
194.350 - if ((value === null) || (value === undefined))
194.351 - value = "";
194.352 -
194.353 - if (element.nodeType === 3) {
194.354 - element.data = value;
194.355 - } else {
194.356 - // We need there to be exactly one child: a text node.
194.357 - // If there are no children, more than one, or if it's not a text node,
194.358 - // we'll clear everything and create a single text node.
194.359 - var innerTextNode = ko.virtualElements.firstChild(element);
194.360 - if (!innerTextNode || innerTextNode.nodeType != 3 || ko.virtualElements.nextSibling(innerTextNode)) {
194.361 - ko.virtualElements.setDomNodeChildren(element, [document.createTextNode(value)]);
194.362 - } else {
194.363 - innerTextNode.data = value;
194.364 - }
194.365 -
194.366 - ko.utils.forceRefresh(element);
194.367 - }
194.368 - },
194.369 -
194.370 - setElementName: function(element, name) {
194.371 - element.name = name;
194.372 -
194.373 - // Workaround IE 6/7 issue
194.374 - // - https://github.com/SteveSanderson/knockout/issues/197
194.375 - // - http://www.matts411.com/post/setting_the_name_attribute_in_ie_dom/
194.376 - if (ieVersion <= 7) {
194.377 - try {
194.378 - element.mergeAttributes(document.createElement("<input name='" + element.name + "'/>"), false);
194.379 - }
194.380 - catch(e) {} // For IE9 with doc mode "IE9 Standards" and browser mode "IE9 Compatibility View"
194.381 - }
194.382 - },
194.383 -
194.384 - forceRefresh: function(node) {
194.385 - // Workaround for an IE9 rendering bug - https://github.com/SteveSanderson/knockout/issues/209
194.386 - if (ieVersion >= 9) {
194.387 - // For text nodes and comment nodes (most likely virtual elements), we will have to refresh the container
194.388 - var elem = node.nodeType == 1 ? node : node.parentNode;
194.389 - if (elem.style)
194.390 - elem.style.zoom = elem.style.zoom;
194.391 - }
194.392 - },
194.393 -
194.394 - ensureSelectElementIsRenderedCorrectly: function(selectElement) {
194.395 - // Workaround for IE9 rendering bug - it doesn't reliably display all the text in dynamically-added select boxes unless you force it to re-render by updating the width.
194.396 - // (See https://github.com/SteveSanderson/knockout/issues/312, http://stackoverflow.com/questions/5908494/select-only-shows-first-char-of-selected-option)
194.397 - if (ieVersion >= 9) {
194.398 - var originalWidth = selectElement.style.width;
194.399 - selectElement.style.width = 0;
194.400 - selectElement.style.width = originalWidth;
194.401 - }
194.402 - },
194.403 -
194.404 - range: function (min, max) {
194.405 - min = ko.utils.unwrapObservable(min);
194.406 - max = ko.utils.unwrapObservable(max);
194.407 - var result = [];
194.408 - for (var i = min; i <= max; i++)
194.409 - result.push(i);
194.410 - return result;
194.411 - },
194.412 -
194.413 - makeArray: function(arrayLikeObject) {
194.414 - var result = [];
194.415 - for (var i = 0, j = arrayLikeObject.length; i < j; i++) {
194.416 - result.push(arrayLikeObject[i]);
194.417 - };
194.418 - return result;
194.419 - },
194.420 -
194.421 - isIe6 : isIe6,
194.422 - isIe7 : isIe7,
194.423 - ieVersion : ieVersion,
194.424 -
194.425 - getFormFields: function(form, fieldName) {
194.426 - var fields = ko.utils.makeArray(form.getElementsByTagName("input")).concat(ko.utils.makeArray(form.getElementsByTagName("textarea")));
194.427 - var isMatchingField = (typeof fieldName == 'string')
194.428 - ? function(field) { return field.name === fieldName }
194.429 - : function(field) { return fieldName.test(field.name) }; // Treat fieldName as regex or object containing predicate
194.430 - var matches = [];
194.431 - for (var i = fields.length - 1; i >= 0; i--) {
194.432 - if (isMatchingField(fields[i]))
194.433 - matches.push(fields[i]);
194.434 - };
194.435 - return matches;
194.436 - },
194.437 -
194.438 - parseJson: function (jsonString) {
194.439 - if (typeof jsonString == "string") {
194.440 - jsonString = ko.utils.stringTrim(jsonString);
194.441 - if (jsonString) {
194.442 - if (window.JSON && window.JSON.parse) // Use native parsing where available
194.443 - return window.JSON.parse(jsonString);
194.444 - return (new Function("return " + jsonString))(); // Fallback on less safe parsing for older browsers
194.445 - }
194.446 - }
194.447 - return null;
194.448 - },
194.449 -
194.450 - stringifyJson: function (data, replacer, space) { // replacer and space are optional
194.451 - if ((typeof JSON == "undefined") || (typeof JSON.stringify == "undefined"))
194.452 - throw new Error("Cannot find JSON.stringify(). Some browsers (e.g., IE < 8) don't support it natively, but you can overcome this by adding a script reference to json2.js, downloadable from http://www.json.org/json2.js");
194.453 - return JSON.stringify(ko.utils.unwrapObservable(data), replacer, space);
194.454 - },
194.455 -
194.456 - postJson: function (urlOrForm, data, options) {
194.457 - options = options || {};
194.458 - var params = options['params'] || {};
194.459 - var includeFields = options['includeFields'] || this.fieldsIncludedWithJsonPost;
194.460 - var url = urlOrForm;
194.461 -
194.462 - // If we were given a form, use its 'action' URL and pick out any requested field values
194.463 - if((typeof urlOrForm == 'object') && (ko.utils.tagNameLower(urlOrForm) === "form")) {
194.464 - var originalForm = urlOrForm;
194.465 - url = originalForm.action;
194.466 - for (var i = includeFields.length - 1; i >= 0; i--) {
194.467 - var fields = ko.utils.getFormFields(originalForm, includeFields[i]);
194.468 - for (var j = fields.length - 1; j >= 0; j--)
194.469 - params[fields[j].name] = fields[j].value;
194.470 - }
194.471 - }
194.472 -
194.473 - data = ko.utils.unwrapObservable(data);
194.474 - var form = document.createElement("form");
194.475 - form.style.display = "none";
194.476 - form.action = url;
194.477 - form.method = "post";
194.478 - for (var key in data) {
194.479 - var input = document.createElement("input");
194.480 - input.name = key;
194.481 - input.value = ko.utils.stringifyJson(ko.utils.unwrapObservable(data[key]));
194.482 - form.appendChild(input);
194.483 - }
194.484 - for (var key in params) {
194.485 - var input = document.createElement("input");
194.486 - input.name = key;
194.487 - input.value = params[key];
194.488 - form.appendChild(input);
194.489 - }
194.490 - document.body.appendChild(form);
194.491 - options['submitter'] ? options['submitter'](form) : form.submit();
194.492 - setTimeout(function () { form.parentNode.removeChild(form); }, 0);
194.493 - }
194.494 - }
194.495 -})();
194.496 -
194.497 -ko.exportSymbol('utils', ko.utils);
194.498 -ko.exportSymbol('utils.arrayForEach', ko.utils.arrayForEach);
194.499 -ko.exportSymbol('utils.arrayFirst', ko.utils.arrayFirst);
194.500 -ko.exportSymbol('utils.arrayFilter', ko.utils.arrayFilter);
194.501 -ko.exportSymbol('utils.arrayGetDistinctValues', ko.utils.arrayGetDistinctValues);
194.502 -ko.exportSymbol('utils.arrayIndexOf', ko.utils.arrayIndexOf);
194.503 -ko.exportSymbol('utils.arrayMap', ko.utils.arrayMap);
194.504 -ko.exportSymbol('utils.arrayPushAll', ko.utils.arrayPushAll);
194.505 -ko.exportSymbol('utils.arrayRemoveItem', ko.utils.arrayRemoveItem);
194.506 -ko.exportSymbol('utils.extend', ko.utils.extend);
194.507 -ko.exportSymbol('utils.fieldsIncludedWithJsonPost', ko.utils.fieldsIncludedWithJsonPost);
194.508 -ko.exportSymbol('utils.getFormFields', ko.utils.getFormFields);
194.509 -ko.exportSymbol('utils.peekObservable', ko.utils.peekObservable);
194.510 -ko.exportSymbol('utils.postJson', ko.utils.postJson);
194.511 -ko.exportSymbol('utils.parseJson', ko.utils.parseJson);
194.512 -ko.exportSymbol('utils.registerEventHandler', ko.utils.registerEventHandler);
194.513 -ko.exportSymbol('utils.stringifyJson', ko.utils.stringifyJson);
194.514 -ko.exportSymbol('utils.range', ko.utils.range);
194.515 -ko.exportSymbol('utils.toggleDomNodeCssClass', ko.utils.toggleDomNodeCssClass);
194.516 -ko.exportSymbol('utils.triggerEvent', ko.utils.triggerEvent);
194.517 -ko.exportSymbol('utils.unwrapObservable', ko.utils.unwrapObservable);
194.518 -
194.519 -if (!Function.prototype['bind']) {
194.520 - // Function.prototype.bind is a standard part of ECMAScript 5th Edition (December 2009, http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf)
194.521 - // In case the browser doesn't implement it natively, provide a JavaScript implementation. This implementation is based on the one in prototype.js
194.522 - Function.prototype['bind'] = function (object) {
194.523 - var originalFunction = this, args = Array.prototype.slice.call(arguments), object = args.shift();
194.524 - return function () {
194.525 - return originalFunction.apply(object, args.concat(Array.prototype.slice.call(arguments)));
194.526 - };
194.527 - };
194.528 -}
194.529 -
194.530 -ko.utils.domData = new (function () {
194.531 - var uniqueId = 0;
194.532 - var dataStoreKeyExpandoPropertyName = "__ko__" + (new Date).getTime();
194.533 - var dataStore = {};
194.534 - return {
194.535 - get: function (node, key) {
194.536 - var allDataForNode = ko.utils.domData.getAll(node, false);
194.537 - return allDataForNode === undefined ? undefined : allDataForNode[key];
194.538 - },
194.539 - set: function (node, key, value) {
194.540 - if (value === undefined) {
194.541 - // Make sure we don't actually create a new domData key if we are actually deleting a value
194.542 - if (ko.utils.domData.getAll(node, false) === undefined)
194.543 - return;
194.544 - }
194.545 - var allDataForNode = ko.utils.domData.getAll(node, true);
194.546 - allDataForNode[key] = value;
194.547 - },
194.548 - getAll: function (node, createIfNotFound) {
194.549 - var dataStoreKey = node[dataStoreKeyExpandoPropertyName];
194.550 - var hasExistingDataStore = dataStoreKey && (dataStoreKey !== "null") && dataStore[dataStoreKey];
194.551 - if (!hasExistingDataStore) {
194.552 - if (!createIfNotFound)
194.553 - return undefined;
194.554 - dataStoreKey = node[dataStoreKeyExpandoPropertyName] = "ko" + uniqueId++;
194.555 - dataStore[dataStoreKey] = {};
194.556 - }
194.557 - return dataStore[dataStoreKey];
194.558 - },
194.559 - clear: function (node) {
194.560 - var dataStoreKey = node[dataStoreKeyExpandoPropertyName];
194.561 - if (dataStoreKey) {
194.562 - delete dataStore[dataStoreKey];
194.563 - node[dataStoreKeyExpandoPropertyName] = null;
194.564 - return true; // Exposing "did clean" flag purely so specs can infer whether things have been cleaned up as intended
194.565 - }
194.566 - return false;
194.567 - }
194.568 - }
194.569 -})();
194.570 -
194.571 -ko.exportSymbol('utils.domData', ko.utils.domData);
194.572 -ko.exportSymbol('utils.domData.clear', ko.utils.domData.clear); // Exporting only so specs can clear up after themselves fully
194.573 -
194.574 -ko.utils.domNodeDisposal = new (function () {
194.575 - var domDataKey = "__ko_domNodeDisposal__" + (new Date).getTime();
194.576 - var cleanableNodeTypes = { 1: true, 8: true, 9: true }; // Element, Comment, Document
194.577 - var cleanableNodeTypesWithDescendants = { 1: true, 9: true }; // Element, Document
194.578 -
194.579 - function getDisposeCallbacksCollection(node, createIfNotFound) {
194.580 - var allDisposeCallbacks = ko.utils.domData.get(node, domDataKey);
194.581 - if ((allDisposeCallbacks === undefined) && createIfNotFound) {
194.582 - allDisposeCallbacks = [];
194.583 - ko.utils.domData.set(node, domDataKey, allDisposeCallbacks);
194.584 - }
194.585 - return allDisposeCallbacks;
194.586 - }
194.587 - function destroyCallbacksCollection(node) {
194.588 - ko.utils.domData.set(node, domDataKey, undefined);
194.589 - }
194.590 -
194.591 - function cleanSingleNode(node) {
194.592 - // Run all the dispose callbacks
194.593 - var callbacks = getDisposeCallbacksCollection(node, false);
194.594 - if (callbacks) {
194.595 - callbacks = callbacks.slice(0); // Clone, as the array may be modified during iteration (typically, callbacks will remove themselves)
194.596 - for (var i = 0; i < callbacks.length; i++)
194.597 - callbacks[i](node);
194.598 - }
194.599 -
194.600 - // Also erase the DOM data
194.601 - ko.utils.domData.clear(node);
194.602 -
194.603 - // Special support for jQuery here because it's so commonly used.
194.604 - // Many jQuery plugins (including jquery.tmpl) store data using jQuery's equivalent of domData
194.605 - // so notify it to tear down any resources associated with the node & descendants here.
194.606 - if ((typeof jQuery == "function") && (typeof jQuery['cleanData'] == "function"))
194.607 - jQuery['cleanData']([node]);
194.608 -
194.609 - // Also clear any immediate-child comment nodes, as these wouldn't have been found by
194.610 - // node.getElementsByTagName("*") in cleanNode() (comment nodes aren't elements)
194.611 - if (cleanableNodeTypesWithDescendants[node.nodeType])
194.612 - cleanImmediateCommentTypeChildren(node);
194.613 - }
194.614 -
194.615 - function cleanImmediateCommentTypeChildren(nodeWithChildren) {
194.616 - var child, nextChild = nodeWithChildren.firstChild;
194.617 - while (child = nextChild) {
194.618 - nextChild = child.nextSibling;
194.619 - if (child.nodeType === 8)
194.620 - cleanSingleNode(child);
194.621 - }
194.622 - }
194.623 -
194.624 - return {
194.625 - addDisposeCallback : function(node, callback) {
194.626 - if (typeof callback != "function")
194.627 - throw new Error("Callback must be a function");
194.628 - getDisposeCallbacksCollection(node, true).push(callback);
194.629 - },
194.630 -
194.631 - removeDisposeCallback : function(node, callback) {
194.632 - var callbacksCollection = getDisposeCallbacksCollection(node, false);
194.633 - if (callbacksCollection) {
194.634 - ko.utils.arrayRemoveItem(callbacksCollection, callback);
194.635 - if (callbacksCollection.length == 0)
194.636 - destroyCallbacksCollection(node);
194.637 - }
194.638 - },
194.639 -
194.640 - cleanNode : function(node) {
194.641 - // First clean this node, where applicable
194.642 - if (cleanableNodeTypes[node.nodeType]) {
194.643 - cleanSingleNode(node);
194.644 -
194.645 - // ... then its descendants, where applicable
194.646 - if (cleanableNodeTypesWithDescendants[node.nodeType]) {
194.647 - // Clone the descendants list in case it changes during iteration
194.648 - var descendants = [];
194.649 - ko.utils.arrayPushAll(descendants, node.getElementsByTagName("*"));
194.650 - for (var i = 0, j = descendants.length; i < j; i++)
194.651 - cleanSingleNode(descendants[i]);
194.652 - }
194.653 - }
194.654 - return node;
194.655 - },
194.656 -
194.657 - removeNode : function(node) {
194.658 - ko.cleanNode(node);
194.659 - if (node.parentNode)
194.660 - node.parentNode.removeChild(node);
194.661 - }
194.662 - }
194.663 -})();
194.664 -ko.cleanNode = ko.utils.domNodeDisposal.cleanNode; // Shorthand name for convenience
194.665 -ko.removeNode = ko.utils.domNodeDisposal.removeNode; // Shorthand name for convenience
194.666 -ko.exportSymbol('cleanNode', ko.cleanNode);
194.667 -ko.exportSymbol('removeNode', ko.removeNode);
194.668 -ko.exportSymbol('utils.domNodeDisposal', ko.utils.domNodeDisposal);
194.669 -ko.exportSymbol('utils.domNodeDisposal.addDisposeCallback', ko.utils.domNodeDisposal.addDisposeCallback);
194.670 -ko.exportSymbol('utils.domNodeDisposal.removeDisposeCallback', ko.utils.domNodeDisposal.removeDisposeCallback);
194.671 -(function () {
194.672 - var leadingCommentRegex = /^(\s*)<!--(.*?)-->/;
194.673 -
194.674 - function simpleHtmlParse(html) {
194.675 - // Based on jQuery's "clean" function, but only accounting for table-related elements.
194.676 - // If you have referenced jQuery, this won't be used anyway - KO will use jQuery's "clean" function directly
194.677 -
194.678 - // Note that there's still an issue in IE < 9 whereby it will discard comment nodes that are the first child of
194.679 - // a descendant node. For example: "<div><!-- mycomment -->abc</div>" will get parsed as "<div>abc</div>"
194.680 - // This won't affect anyone who has referenced jQuery, and there's always the workaround of inserting a dummy node
194.681 - // (possibly a text node) in front of the comment. So, KO does not attempt to workaround this IE issue automatically at present.
194.682 -
194.683 - // Trim whitespace, otherwise indexOf won't work as expected
194.684 - var tags = ko.utils.stringTrim(html).toLowerCase(), div = document.createElement("div");
194.685 -
194.686 - // Finds the first match from the left column, and returns the corresponding "wrap" data from the right column
194.687 - var wrap = tags.match(/^<(thead|tbody|tfoot)/) && [1, "<table>", "</table>"] ||
194.688 - !tags.indexOf("<tr") && [2, "<table><tbody>", "</tbody></table>"] ||
194.689 - (!tags.indexOf("<td") || !tags.indexOf("<th")) && [3, "<table><tbody><tr>", "</tr></tbody></table>"] ||
194.690 - /* anything else */ [0, "", ""];
194.691 -
194.692 - // Go to html and back, then peel off extra wrappers
194.693 - // Note that we always prefix with some dummy text, because otherwise, IE<9 will strip out leading comment nodes in descendants. Total madness.
194.694 - var markup = "ignored<div>" + wrap[1] + html + wrap[2] + "</div>";
194.695 - if (typeof window['innerShiv'] == "function") {
194.696 - div.appendChild(window['innerShiv'](markup));
194.697 - } else {
194.698 - div.innerHTML = markup;
194.699 - }
194.700 -
194.701 - // Move to the right depth
194.702 - while (wrap[0]--)
194.703 - div = div.lastChild;
194.704 -
194.705 - return ko.utils.makeArray(div.lastChild.childNodes);
194.706 - }
194.707 -
194.708 - function jQueryHtmlParse(html) {
194.709 - // jQuery's "parseHTML" function was introduced in jQuery 1.8.0 and is a documented public API.
194.710 - if (jQuery['parseHTML']) {
194.711 - return jQuery['parseHTML'](html);
194.712 - } else {
194.713 - // For jQuery < 1.8.0, we fall back on the undocumented internal "clean" function.
194.714 - var elems = jQuery['clean']([html]);
194.715 -
194.716 - // As of jQuery 1.7.1, jQuery parses the HTML by appending it to some dummy parent nodes held in an in-memory document fragment.
194.717 - // Unfortunately, it never clears the dummy parent nodes from the document fragment, so it leaks memory over time.
194.718 - // Fix this by finding the top-most dummy parent element, and detaching it from its owner fragment.
194.719 - if (elems && elems[0]) {
194.720 - // Find the top-most parent element that's a direct child of a document fragment
194.721 - var elem = elems[0];
194.722 - while (elem.parentNode && elem.parentNode.nodeType !== 11 /* i.e., DocumentFragment */)
194.723 - elem = elem.parentNode;
194.724 - // ... then detach it
194.725 - if (elem.parentNode)
194.726 - elem.parentNode.removeChild(elem);
194.727 - }
194.728 -
194.729 - return elems;
194.730 - }
194.731 - }
194.732 -
194.733 - ko.utils.parseHtmlFragment = function(html) {
194.734 - return typeof jQuery != 'undefined' ? jQueryHtmlParse(html) // As below, benefit from jQuery's optimisations where possible
194.735 - : simpleHtmlParse(html); // ... otherwise, this simple logic will do in most common cases.
194.736 - };
194.737 -
194.738 - ko.utils.setHtml = function(node, html) {
194.739 - ko.utils.emptyDomNode(node);
194.740 -
194.741 - // There's no legitimate reason to display a stringified observable without unwrapping it, so we'll unwrap it
194.742 - html = ko.utils.unwrapObservable(html);
194.743 -
194.744 - if ((html !== null) && (html !== undefined)) {
194.745 - if (typeof html != 'string')
194.746 - html = html.toString();
194.747 -
194.748 - // jQuery contains a lot of sophisticated code to parse arbitrary HTML fragments,
194.749 - // for example <tr> elements which are not normally allowed to exist on their own.
194.750 - // If you've referenced jQuery we'll use that rather than duplicating its code.
194.751 - if (typeof jQuery != 'undefined') {
194.752 - jQuery(node)['html'](html);
194.753 - } else {
194.754 - // ... otherwise, use KO's own parsing logic.
194.755 - var parsedNodes = ko.utils.parseHtmlFragment(html);
194.756 - for (var i = 0; i < parsedNodes.length; i++)
194.757 - node.appendChild(parsedNodes[i]);
194.758 - }
194.759 - }
194.760 - };
194.761 -})();
194.762 -
194.763 -ko.exportSymbol('utils.parseHtmlFragment', ko.utils.parseHtmlFragment);
194.764 -ko.exportSymbol('utils.setHtml', ko.utils.setHtml);
194.765 -
194.766 -ko.memoization = (function () {
194.767 - var memos = {};
194.768 -
194.769 - function randomMax8HexChars() {
194.770 - return (((1 + Math.random()) * 0x100000000) | 0).toString(16).substring(1);
194.771 - }
194.772 - function generateRandomId() {
194.773 - return randomMax8HexChars() + randomMax8HexChars();
194.774 - }
194.775 - function findMemoNodes(rootNode, appendToArray) {
194.776 - if (!rootNode)
194.777 - return;
194.778 - if (rootNode.nodeType == 8) {
194.779 - var memoId = ko.memoization.parseMemoText(rootNode.nodeValue);
194.780 - if (memoId != null)
194.781 - appendToArray.push({ domNode: rootNode, memoId: memoId });
194.782 - } else if (rootNode.nodeType == 1) {
194.783 - for (var i = 0, childNodes = rootNode.childNodes, j = childNodes.length; i < j; i++)
194.784 - findMemoNodes(childNodes[i], appendToArray);
194.785 - }
194.786 - }
194.787 -
194.788 - return {
194.789 - memoize: function (callback) {
194.790 - if (typeof callback != "function")
194.791 - throw new Error("You can only pass a function to ko.memoization.memoize()");
194.792 - var memoId = generateRandomId();
194.793 - memos[memoId] = callback;
194.794 - return "<!--[ko_memo:" + memoId + "]-->";
194.795 - },
194.796 -
194.797 - unmemoize: function (memoId, callbackParams) {
194.798 - var callback = memos[memoId];
194.799 - if (callback === undefined)
194.800 - throw new Error("Couldn't find any memo with ID " + memoId + ". Perhaps it's already been unmemoized.");
194.801 - try {
194.802 - callback.apply(null, callbackParams || []);
194.803 - return true;
194.804 - }
194.805 - finally { delete memos[memoId]; }
194.806 - },
194.807 -
194.808 - unmemoizeDomNodeAndDescendants: function (domNode, extraCallbackParamsArray) {
194.809 - var memos = [];
194.810 - findMemoNodes(domNode, memos);
194.811 - for (var i = 0, j = memos.length; i < j; i++) {
194.812 - var node = memos[i].domNode;
194.813 - var combinedParams = [node];
194.814 - if (extraCallbackParamsArray)
194.815 - ko.utils.arrayPushAll(combinedParams, extraCallbackParamsArray);
194.816 - ko.memoization.unmemoize(memos[i].memoId, combinedParams);
194.817 - node.nodeValue = ""; // Neuter this node so we don't try to unmemoize it again
194.818 - if (node.parentNode)
194.819 - node.parentNode.removeChild(node); // If possible, erase it totally (not always possible - someone else might just hold a reference to it then call unmemoizeDomNodeAndDescendants again)
194.820 - }
194.821 - },
194.822 -
194.823 - parseMemoText: function (memoText) {
194.824 - var match = memoText.match(/^\[ko_memo\:(.*?)\]$/);
194.825 - return match ? match[1] : null;
194.826 - }
194.827 - };
194.828 -})();
194.829 -
194.830 -ko.exportSymbol('memoization', ko.memoization);
194.831 -ko.exportSymbol('memoization.memoize', ko.memoization.memoize);
194.832 -ko.exportSymbol('memoization.unmemoize', ko.memoization.unmemoize);
194.833 -ko.exportSymbol('memoization.parseMemoText', ko.memoization.parseMemoText);
194.834 -ko.exportSymbol('memoization.unmemoizeDomNodeAndDescendants', ko.memoization.unmemoizeDomNodeAndDescendants);
194.835 -ko.extenders = {
194.836 - 'throttle': function(target, timeout) {
194.837 - // Throttling means two things:
194.838 -
194.839 - // (1) For dependent observables, we throttle *evaluations* so that, no matter how fast its dependencies
194.840 - // notify updates, the target doesn't re-evaluate (and hence doesn't notify) faster than a certain rate
194.841 - target['throttleEvaluation'] = timeout;
194.842 -
194.843 - // (2) For writable targets (observables, or writable dependent observables), we throttle *writes*
194.844 - // so the target cannot change value synchronously or faster than a certain rate
194.845 - var writeTimeoutInstance = null;
194.846 - return ko.dependentObservable({
194.847 - 'read': target,
194.848 - 'write': function(value) {
194.849 - clearTimeout(writeTimeoutInstance);
194.850 - writeTimeoutInstance = setTimeout(function() {
194.851 - target(value);
194.852 - }, timeout);
194.853 - }
194.854 - });
194.855 - },
194.856 -
194.857 - 'notify': function(target, notifyWhen) {
194.858 - target["equalityComparer"] = notifyWhen == "always"
194.859 - ? function() { return false } // Treat all values as not equal
194.860 - : ko.observable["fn"]["equalityComparer"];
194.861 - return target;
194.862 - }
194.863 -};
194.864 -
194.865 -function applyExtenders(requestedExtenders) {
194.866 - var target = this;
194.867 - if (requestedExtenders) {
194.868 - for (var key in requestedExtenders) {
194.869 - var extenderHandler = ko.extenders[key];
194.870 - if (typeof extenderHandler == 'function') {
194.871 - target = extenderHandler(target, requestedExtenders[key]);
194.872 - }
194.873 - }
194.874 - }
194.875 - return target;
194.876 -}
194.877 -
194.878 -ko.exportSymbol('extenders', ko.extenders);
194.879 -
194.880 -ko.subscription = function (target, callback, disposeCallback) {
194.881 - this.target = target;
194.882 - this.callback = callback;
194.883 - this.disposeCallback = disposeCallback;
194.884 - ko.exportProperty(this, 'dispose', this.dispose);
194.885 -};
194.886 -ko.subscription.prototype.dispose = function () {
194.887 - this.isDisposed = true;
194.888 - this.disposeCallback();
194.889 -};
194.890 -
194.891 -ko.subscribable = function () {
194.892 - this._subscriptions = {};
194.893 -
194.894 - ko.utils.extend(this, ko.subscribable['fn']);
194.895 - ko.exportProperty(this, 'subscribe', this.subscribe);
194.896 - ko.exportProperty(this, 'extend', this.extend);
194.897 - ko.exportProperty(this, 'getSubscriptionsCount', this.getSubscriptionsCount);
194.898 -}
194.899 -
194.900 -var defaultEvent = "change";
194.901 -
194.902 -ko.subscribable['fn'] = {
194.903 - subscribe: function (callback, callbackTarget, event) {
194.904 - event = event || defaultEvent;
194.905 - var boundCallback = callbackTarget ? callback.bind(callbackTarget) : callback;
194.906 -
194.907 - var subscription = new ko.subscription(this, boundCallback, function () {
194.908 - ko.utils.arrayRemoveItem(this._subscriptions[event], subscription);
194.909 - }.bind(this));
194.910 -
194.911 - if (!this._subscriptions[event])
194.912 - this._subscriptions[event] = [];
194.913 - this._subscriptions[event].push(subscription);
194.914 - return subscription;
194.915 - },
194.916 -
194.917 - "notifySubscribers": function (valueToNotify, event) {
194.918 - event = event || defaultEvent;
194.919 - if (this._subscriptions[event]) {
194.920 - ko.dependencyDetection.ignore(function() {
194.921 - ko.utils.arrayForEach(this._subscriptions[event].slice(0), function (subscription) {
194.922 - // In case a subscription was disposed during the arrayForEach cycle, check
194.923 - // for isDisposed on each subscription before invoking its callback
194.924 - if (subscription && (subscription.isDisposed !== true))
194.925 - subscription.callback(valueToNotify);
194.926 - });
194.927 - }, this);
194.928 - }
194.929 - },
194.930 -
194.931 - getSubscriptionsCount: function () {
194.932 - var total = 0;
194.933 - for (var eventName in this._subscriptions) {
194.934 - if (this._subscriptions.hasOwnProperty(eventName))
194.935 - total += this._subscriptions[eventName].length;
194.936 - }
194.937 - return total;
194.938 - },
194.939 -
194.940 - extend: applyExtenders
194.941 -};
194.942 -
194.943 -
194.944 -ko.isSubscribable = function (instance) {
194.945 - return typeof instance.subscribe == "function" && typeof instance["notifySubscribers"] == "function";
194.946 -};
194.947 -
194.948 -ko.exportSymbol('subscribable', ko.subscribable);
194.949 -ko.exportSymbol('isSubscribable', ko.isSubscribable);
194.950 -
194.951 -ko.dependencyDetection = (function () {
194.952 - var _frames = [];
194.953 -
194.954 - return {
194.955 - begin: function (callback) {
194.956 - _frames.push({ callback: callback, distinctDependencies:[] });
194.957 - },
194.958 -
194.959 - end: function () {
194.960 - _frames.pop();
194.961 - },
194.962 -
194.963 - registerDependency: function (subscribable) {
194.964 - if (!ko.isSubscribable(subscribable))
194.965 - throw new Error("Only subscribable things can act as dependencies");
194.966 - if (_frames.length > 0) {
194.967 - var topFrame = _frames[_frames.length - 1];
194.968 - if (!topFrame || ko.utils.arrayIndexOf(topFrame.distinctDependencies, subscribable) >= 0)
194.969 - return;
194.970 - topFrame.distinctDependencies.push(subscribable);
194.971 - topFrame.callback(subscribable);
194.972 - }
194.973 - },
194.974 -
194.975 - ignore: function(callback, callbackTarget, callbackArgs) {
194.976 - try {
194.977 - _frames.push(null);
194.978 - return callback.apply(callbackTarget, callbackArgs || []);
194.979 - } finally {
194.980 - _frames.pop();
194.981 - }
194.982 - }
194.983 - };
194.984 -})();
194.985 -var primitiveTypes = { 'undefined':true, 'boolean':true, 'number':true, 'string':true };
194.986 -
194.987 -ko.observable = function (initialValue) {
194.988 - var _latestValue = initialValue;
194.989 -
194.990 - function observable() {
194.991 - if (arguments.length > 0) {
194.992 - // Write
194.993 -
194.994 - // Ignore writes if the value hasn't changed
194.995 - if ((!observable['equalityComparer']) || !observable['equalityComparer'](_latestValue, arguments[0])) {
194.996 - observable.valueWillMutate();
194.997 - _latestValue = arguments[0];
194.998 - if (DEBUG) observable._latestValue = _latestValue;
194.999 - observable.valueHasMutated();
194.1000 - }
194.1001 - return this; // Permits chained assignments
194.1002 - }
194.1003 - else {
194.1004 - // Read
194.1005 - ko.dependencyDetection.registerDependency(observable); // The caller only needs to be notified of changes if they did a "read" operation
194.1006 - return _latestValue;
194.1007 - }
194.1008 - }
194.1009 - if (DEBUG) observable._latestValue = _latestValue;
194.1010 - ko.subscribable.call(observable);
194.1011 - observable.peek = function() { return _latestValue };
194.1012 - observable.valueHasMutated = function () { observable["notifySubscribers"](_latestValue); }
194.1013 - observable.valueWillMutate = function () { observable["notifySubscribers"](_latestValue, "beforeChange"); }
194.1014 - ko.utils.extend(observable, ko.observable['fn']);
194.1015 -
194.1016 - ko.exportProperty(observable, 'peek', observable.peek);
194.1017 - ko.exportProperty(observable, "valueHasMutated", observable.valueHasMutated);
194.1018 - ko.exportProperty(observable, "valueWillMutate", observable.valueWillMutate);
194.1019 -
194.1020 - return observable;
194.1021 -}
194.1022 -
194.1023 -ko.observable['fn'] = {
194.1024 - "equalityComparer": function valuesArePrimitiveAndEqual(a, b) {
194.1025 - var oldValueIsPrimitive = (a === null) || (typeof(a) in primitiveTypes);
194.1026 - return oldValueIsPrimitive ? (a === b) : false;
194.1027 - }
194.1028 -};
194.1029 -
194.1030 -var protoProperty = ko.observable.protoProperty = "__ko_proto__";
194.1031 -ko.observable['fn'][protoProperty] = ko.observable;
194.1032 -
194.1033 -ko.hasPrototype = function(instance, prototype) {
194.1034 - if ((instance === null) || (instance === undefined) || (instance[protoProperty] === undefined)) return false;
194.1035 - if (instance[protoProperty] === prototype) return true;
194.1036 - return ko.hasPrototype(instance[protoProperty], prototype); // Walk the prototype chain
194.1037 -};
194.1038 -
194.1039 -ko.isObservable = function (instance) {
194.1040 - return ko.hasPrototype(instance, ko.observable);
194.1041 -}
194.1042 -ko.isWriteableObservable = function (instance) {
194.1043 - // Observable
194.1044 - if ((typeof instance == "function") && instance[protoProperty] === ko.observable)
194.1045 - return true;
194.1046 - // Writeable dependent observable
194.1047 - if ((typeof instance == "function") && (instance[protoProperty] === ko.dependentObservable) && (instance.hasWriteFunction))
194.1048 - return true;
194.1049 - // Anything else
194.1050 - return false;
194.1051 -}
194.1052 -
194.1053 -
194.1054 -ko.exportSymbol('observable', ko.observable);
194.1055 -ko.exportSymbol('isObservable', ko.isObservable);
194.1056 -ko.exportSymbol('isWriteableObservable', ko.isWriteableObservable);
194.1057 -ko.observableArray = function (initialValues) {
194.1058 - if (arguments.length == 0) {
194.1059 - // Zero-parameter constructor initializes to empty array
194.1060 - initialValues = [];
194.1061 - }
194.1062 - if ((initialValues !== null) && (initialValues !== undefined) && !('length' in initialValues))
194.1063 - throw new Error("The argument passed when initializing an observable array must be an array, or null, or undefined.");
194.1064 -
194.1065 - var result = ko.observable(initialValues);
194.1066 - ko.utils.extend(result, ko.observableArray['fn']);
194.1067 - return result;
194.1068 -}
194.1069 -
194.1070 -ko.observableArray['fn'] = {
194.1071 - 'remove': function (valueOrPredicate) {
194.1072 - var underlyingArray = this.peek();
194.1073 - var removedValues = [];
194.1074 - var predicate = typeof valueOrPredicate == "function" ? valueOrPredicate : function (value) { return value === valueOrPredicate; };
194.1075 - for (var i = 0; i < underlyingArray.length; i++) {
194.1076 - var value = underlyingArray[i];
194.1077 - if (predicate(value)) {
194.1078 - if (removedValues.length === 0) {
194.1079 - this.valueWillMutate();
194.1080 - }
194.1081 - removedValues.push(value);
194.1082 - underlyingArray.splice(i, 1);
194.1083 - i--;
194.1084 - }
194.1085 - }
194.1086 - if (removedValues.length) {
194.1087 - this.valueHasMutated();
194.1088 - }
194.1089 - return removedValues;
194.1090 - },
194.1091 -
194.1092 - 'removeAll': function (arrayOfValues) {
194.1093 - // If you passed zero args, we remove everything
194.1094 - if (arrayOfValues === undefined) {
194.1095 - var underlyingArray = this.peek();
194.1096 - var allValues = underlyingArray.slice(0);
194.1097 - this.valueWillMutate();
194.1098 - underlyingArray.splice(0, underlyingArray.length);
194.1099 - this.valueHasMutated();
194.1100 - return allValues;
194.1101 - }
194.1102 - // If you passed an arg, we interpret it as an array of entries to remove
194.1103 - if (!arrayOfValues)
194.1104 - return [];
194.1105 - return this['remove'](function (value) {
194.1106 - return ko.utils.arrayIndexOf(arrayOfValues, value) >= 0;
194.1107 - });
194.1108 - },
194.1109 -
194.1110 - 'destroy': function (valueOrPredicate) {
194.1111 - var underlyingArray = this.peek();
194.1112 - var predicate = typeof valueOrPredicate == "function" ? valueOrPredicate : function (value) { return value === valueOrPredicate; };
194.1113 - this.valueWillMutate();
194.1114 - for (var i = underlyingArray.length - 1; i >= 0; i--) {
194.1115 - var value = underlyingArray[i];
194.1116 - if (predicate(value))
194.1117 - underlyingArray[i]["_destroy"] = true;
194.1118 - }
194.1119 - this.valueHasMutated();
194.1120 - },
194.1121 -
194.1122 - 'destroyAll': function (arrayOfValues) {
194.1123 - // If you passed zero args, we destroy everything
194.1124 - if (arrayOfValues === undefined)
194.1125 - return this['destroy'](function() { return true });
194.1126 -
194.1127 - // If you passed an arg, we interpret it as an array of entries to destroy
194.1128 - if (!arrayOfValues)
194.1129 - return [];
194.1130 - return this['destroy'](function (value) {
194.1131 - return ko.utils.arrayIndexOf(arrayOfValues, value) >= 0;
194.1132 - });
194.1133 - },
194.1134 -
194.1135 - 'indexOf': function (item) {
194.1136 - var underlyingArray = this();
194.1137 - return ko.utils.arrayIndexOf(underlyingArray, item);
194.1138 - },
194.1139 -
194.1140 - 'replace': function(oldItem, newItem) {
194.1141 - var index = this['indexOf'](oldItem);
194.1142 - if (index >= 0) {
194.1143 - this.valueWillMutate();
194.1144 - this.peek()[index] = newItem;
194.1145 - this.valueHasMutated();
194.1146 - }
194.1147 - }
194.1148 -}
194.1149 -
194.1150 -// Populate ko.observableArray.fn with read/write functions from native arrays
194.1151 -// Important: Do not add any additional functions here that may reasonably be used to *read* data from the array
194.1152 -// because we'll eval them without causing subscriptions, so ko.computed output could end up getting stale
194.1153 -ko.utils.arrayForEach(["pop", "push", "reverse", "shift", "sort", "splice", "unshift"], function (methodName) {
194.1154 - ko.observableArray['fn'][methodName] = function () {
194.1155 - // Use "peek" to avoid creating a subscription in any computed that we're executing in the context of
194.1156 - // (for consistency with mutating regular observables)
194.1157 - var underlyingArray = this.peek();
194.1158 - this.valueWillMutate();
194.1159 - var methodCallResult = underlyingArray[methodName].apply(underlyingArray, arguments);
194.1160 - this.valueHasMutated();
194.1161 - return methodCallResult;
194.1162 - };
194.1163 -});
194.1164 -
194.1165 -// Populate ko.observableArray.fn with read-only functions from native arrays
194.1166 -ko.utils.arrayForEach(["slice"], function (methodName) {
194.1167 - ko.observableArray['fn'][methodName] = function () {
194.1168 - var underlyingArray = this();
194.1169 - return underlyingArray[methodName].apply(underlyingArray, arguments);
194.1170 - };
194.1171 -});
194.1172 -
194.1173 -ko.exportSymbol('observableArray', ko.observableArray);
194.1174 -ko.dependentObservable = function (evaluatorFunctionOrOptions, evaluatorFunctionTarget, options) {
194.1175 - var _latestValue,
194.1176 - _hasBeenEvaluated = false,
194.1177 - _isBeingEvaluated = false,
194.1178 - readFunction = evaluatorFunctionOrOptions;
194.1179 -
194.1180 - if (readFunction && typeof readFunction == "object") {
194.1181 - // Single-parameter syntax - everything is on this "options" param
194.1182 - options = readFunction;
194.1183 - readFunction = options["read"];
194.1184 - } else {
194.1185 - // Multi-parameter syntax - construct the options according to the params passed
194.1186 - options = options || {};
194.1187 - if (!readFunction)
194.1188 - readFunction = options["read"];
194.1189 - }
194.1190 - if (typeof readFunction != "function")
194.1191 - throw new Error("Pass a function that returns the value of the ko.computed");
194.1192 -
194.1193 - function addSubscriptionToDependency(subscribable) {
194.1194 - _subscriptionsToDependencies.push(subscribable.subscribe(evaluatePossiblyAsync));
194.1195 - }
194.1196 -
194.1197 - function disposeAllSubscriptionsToDependencies() {
194.1198 - ko.utils.arrayForEach(_subscriptionsToDependencies, function (subscription) {
194.1199 - subscription.dispose();
194.1200 - });
194.1201 - _subscriptionsToDependencies = [];
194.1202 - }
194.1203 -
194.1204 - function evaluatePossiblyAsync() {
194.1205 - var throttleEvaluationTimeout = dependentObservable['throttleEvaluation'];
194.1206 - if (throttleEvaluationTimeout && throttleEvaluationTimeout >= 0) {
194.1207 - clearTimeout(evaluationTimeoutInstance);
194.1208 - evaluationTimeoutInstance = setTimeout(evaluateImmediate, throttleEvaluationTimeout);
194.1209 - } else
194.1210 - evaluateImmediate();
194.1211 - }
194.1212 -
194.1213 - function evaluateImmediate() {
194.1214 - if (_isBeingEvaluated) {
194.1215 - // If the evaluation of a ko.computed causes side effects, it's possible that it will trigger its own re-evaluation.
194.1216 - // This is not desirable (it's hard for a developer to realise a chain of dependencies might cause this, and they almost
194.1217 - // certainly didn't intend infinite re-evaluations). So, for predictability, we simply prevent ko.computeds from causing
194.1218 - // their own re-evaluation. Further discussion at https://github.com/SteveSanderson/knockout/pull/387
194.1219 - return;
194.1220 - }
194.1221 -
194.1222 - // Don't dispose on first evaluation, because the "disposeWhen" callback might
194.1223 - // e.g., dispose when the associated DOM element isn't in the doc, and it's not
194.1224 - // going to be in the doc until *after* the first evaluation
194.1225 - if (_hasBeenEvaluated && disposeWhen()) {
194.1226 - dispose();
194.1227 - return;
194.1228 - }
194.1229 -
194.1230 - _isBeingEvaluated = true;
194.1231 - try {
194.1232 - // Initially, we assume that none of the subscriptions are still being used (i.e., all are candidates for disposal).
194.1233 - // Then, during evaluation, we cross off any that are in fact still being used.
194.1234 - var disposalCandidates = ko.utils.arrayMap(_subscriptionsToDependencies, function(item) {return item.target;});
194.1235 -
194.1236 - ko.dependencyDetection.begin(function(subscribable) {
194.1237 - var inOld;
194.1238 - if ((inOld = ko.utils.arrayIndexOf(disposalCandidates, subscribable)) >= 0)
194.1239 - disposalCandidates[inOld] = undefined; // Don't want to dispose this subscription, as it's still being used
194.1240 - else
194.1241 - addSubscriptionToDependency(subscribable); // Brand new subscription - add it
194.1242 - });
194.1243 -
194.1244 - var newValue = readFunction.call(evaluatorFunctionTarget);
194.1245 -
194.1246 - // For each subscription no longer being used, remove it from the active subscriptions list and dispose it
194.1247 - for (var i = disposalCandidates.length - 1; i >= 0; i--) {
194.1248 - if (disposalCandidates[i])
194.1249 - _subscriptionsToDependencies.splice(i, 1)[0].dispose();
194.1250 - }
194.1251 - _hasBeenEvaluated = true;
194.1252 -
194.1253 - dependentObservable["notifySubscribers"](_latestValue, "beforeChange");
194.1254 - _latestValue = newValue;
194.1255 - if (DEBUG) dependentObservable._latestValue = _latestValue;
194.1256 - } finally {
194.1257 - ko.dependencyDetection.end();
194.1258 - }
194.1259 -
194.1260 - dependentObservable["notifySubscribers"](_latestValue);
194.1261 - _isBeingEvaluated = false;
194.1262 - if (!_subscriptionsToDependencies.length)
194.1263 - dispose();
194.1264 - }
194.1265 -
194.1266 - function dependentObservable() {
194.1267 - if (arguments.length > 0) {
194.1268 - if (typeof writeFunction === "function") {
194.1269 - // Writing a value
194.1270 - writeFunction.apply(evaluatorFunctionTarget, arguments);
194.1271 - } else {
194.1272 - throw new Error("Cannot write a value to a ko.computed unless you specify a 'write' option. If you wish to read the current value, don't pass any parameters.");
194.1273 - }
194.1274 - return this; // Permits chained assignments
194.1275 - } else {
194.1276 - // Reading the value
194.1277 - if (!_hasBeenEvaluated)
194.1278 - evaluateImmediate();
194.1279 - ko.dependencyDetection.registerDependency(dependentObservable);
194.1280 - return _latestValue;
194.1281 - }
194.1282 - }
194.1283 -
194.1284 - function peek() {
194.1285 - if (!_hasBeenEvaluated)
194.1286 - evaluateImmediate();
194.1287 - return _latestValue;
194.1288 - }
194.1289 -
194.1290 - function isActive() {
194.1291 - return !_hasBeenEvaluated || _subscriptionsToDependencies.length > 0;
194.1292 - }
194.1293 -
194.1294 - // By here, "options" is always non-null
194.1295 - var writeFunction = options["write"],
194.1296 - disposeWhenNodeIsRemoved = options["disposeWhenNodeIsRemoved"] || options.disposeWhenNodeIsRemoved || null,
194.1297 - disposeWhen = options["disposeWhen"] || options.disposeWhen || function() { return false; },
194.1298 - dispose = disposeAllSubscriptionsToDependencies,
194.1299 - _subscriptionsToDependencies = [],
194.1300 - evaluationTimeoutInstance = null;
194.1301 -
194.1302 - if (!evaluatorFunctionTarget)
194.1303 - evaluatorFunctionTarget = options["owner"];
194.1304 -
194.1305 - dependentObservable.peek = peek;
194.1306 - dependentObservable.getDependenciesCount = function () { return _subscriptionsToDependencies.length; };
194.1307 - dependentObservable.hasWriteFunction = typeof options["write"] === "function";
194.1308 - dependentObservable.dispose = function () { dispose(); };
194.1309 - dependentObservable.isActive = isActive;
194.1310 - dependentObservable.valueHasMutated = function() {
194.1311 - _hasBeenEvaluated = false;
194.1312 - evaluateImmediate();
194.1313 - };
194.1314 -
194.1315 - ko.subscribable.call(dependentObservable);
194.1316 - ko.utils.extend(dependentObservable, ko.dependentObservable['fn']);
194.1317 -
194.1318 - ko.exportProperty(dependentObservable, 'peek', dependentObservable.peek);
194.1319 - ko.exportProperty(dependentObservable, 'dispose', dependentObservable.dispose);
194.1320 - ko.exportProperty(dependentObservable, 'isActive', dependentObservable.isActive);
194.1321 - ko.exportProperty(dependentObservable, 'getDependenciesCount', dependentObservable.getDependenciesCount);
194.1322 -
194.1323 - // Evaluate, unless deferEvaluation is true
194.1324 - if (options['deferEvaluation'] !== true)
194.1325 - evaluateImmediate();
194.1326 -
194.1327 - // Build "disposeWhenNodeIsRemoved" and "disposeWhenNodeIsRemovedCallback" option values.
194.1328 - // But skip if isActive is false (there will never be any dependencies to dispose).
194.1329 - // (Note: "disposeWhenNodeIsRemoved" option both proactively disposes as soon as the node is removed using ko.removeNode(),
194.1330 - // plus adds a "disposeWhen" callback that, on each evaluation, disposes if the node was removed by some other means.)
194.1331 - if (disposeWhenNodeIsRemoved && isActive()) {
194.1332 - dispose = function() {
194.1333 - ko.utils.domNodeDisposal.removeDisposeCallback(disposeWhenNodeIsRemoved, arguments.callee);
194.1334 - disposeAllSubscriptionsToDependencies();
194.1335 - };
194.1336 - ko.utils.domNodeDisposal.addDisposeCallback(disposeWhenNodeIsRemoved, dispose);
194.1337 - var existingDisposeWhenFunction = disposeWhen;
194.1338 - disposeWhen = function () {
194.1339 - return !ko.utils.domNodeIsAttachedToDocument(disposeWhenNodeIsRemoved) || existingDisposeWhenFunction();
194.1340 - }
194.1341 - }
194.1342 -
194.1343 - return dependentObservable;
194.1344 -};
194.1345 -
194.1346 -ko.isComputed = function(instance) {
194.1347 - return ko.hasPrototype(instance, ko.dependentObservable);
194.1348 -};
194.1349 -
194.1350 -var protoProp = ko.observable.protoProperty; // == "__ko_proto__"
194.1351 -ko.dependentObservable[protoProp] = ko.observable;
194.1352 -
194.1353 -ko.dependentObservable['fn'] = {};
194.1354 -ko.dependentObservable['fn'][protoProp] = ko.dependentObservable;
194.1355 -
194.1356 -ko.exportSymbol('dependentObservable', ko.dependentObservable);
194.1357 -ko.exportSymbol('computed', ko.dependentObservable); // Make "ko.computed" an alias for "ko.dependentObservable"
194.1358 -ko.exportSymbol('isComputed', ko.isComputed);
194.1359 -
194.1360 -(function() {
194.1361 - var maxNestedObservableDepth = 10; // Escape the (unlikely) pathalogical case where an observable's current value is itself (or similar reference cycle)
194.1362 -
194.1363 - ko.toJS = function(rootObject) {
194.1364 - if (arguments.length == 0)
194.1365 - throw new Error("When calling ko.toJS, pass the object you want to convert.");
194.1366 -
194.1367 - // We just unwrap everything at every level in the object graph
194.1368 - return mapJsObjectGraph(rootObject, function(valueToMap) {
194.1369 - // Loop because an observable's value might in turn be another observable wrapper
194.1370 - for (var i = 0; ko.isObservable(valueToMap) && (i < maxNestedObservableDepth); i++)
194.1371 - valueToMap = valueToMap();
194.1372 - return valueToMap;
194.1373 - });
194.1374 - };
194.1375 -
194.1376 - ko.toJSON = function(rootObject, replacer, space) { // replacer and space are optional
194.1377 - var plainJavaScriptObject = ko.toJS(rootObject);
194.1378 - return ko.utils.stringifyJson(plainJavaScriptObject, replacer, space);
194.1379 - };
194.1380 -
194.1381 - function mapJsObjectGraph(rootObject, mapInputCallback, visitedObjects) {
194.1382 - visitedObjects = visitedObjects || new objectLookup();
194.1383 -
194.1384 - rootObject = mapInputCallback(rootObject);
194.1385 - var canHaveProperties = (typeof rootObject == "object") && (rootObject !== null) && (rootObject !== undefined) && (!(rootObject instanceof Date));
194.1386 - if (!canHaveProperties)
194.1387 - return rootObject;
194.1388 -
194.1389 - var outputProperties = rootObject instanceof Array ? [] : {};
194.1390 - visitedObjects.save(rootObject, outputProperties);
194.1391 -
194.1392 - visitPropertiesOrArrayEntries(rootObject, function(indexer) {
194.1393 - var propertyValue = mapInputCallback(rootObject[indexer]);
194.1394 -
194.1395 - switch (typeof propertyValue) {
194.1396 - case "boolean":
194.1397 - case "number":
194.1398 - case "string":
194.1399 - case "function":
194.1400 - outputProperties[indexer] = propertyValue;
194.1401 - break;
194.1402 - case "object":
194.1403 - case "undefined":
194.1404 - var previouslyMappedValue = visitedObjects.get(propertyValue);
194.1405 - outputProperties[indexer] = (previouslyMappedValue !== undefined)
194.1406 - ? previouslyMappedValue
194.1407 - : mapJsObjectGraph(propertyValue, mapInputCallback, visitedObjects);
194.1408 - break;
194.1409 - }
194.1410 - });
194.1411 -
194.1412 - return outputProperties;
194.1413 - }
194.1414 -
194.1415 - function visitPropertiesOrArrayEntries(rootObject, visitorCallback) {
194.1416 - if (rootObject instanceof Array) {
194.1417 - for (var i = 0; i < rootObject.length; i++)
194.1418 - visitorCallback(i);
194.1419 -
194.1420 - // For arrays, also respect toJSON property for custom mappings (fixes #278)
194.1421 - if (typeof rootObject['toJSON'] == 'function')
194.1422 - visitorCallback('toJSON');
194.1423 - } else {
194.1424 - for (var propertyName in rootObject)
194.1425 - visitorCallback(propertyName);
194.1426 - }
194.1427 - };
194.1428 -
194.1429 - function objectLookup() {
194.1430 - var keys = [];
194.1431 - var values = [];
194.1432 - this.save = function(key, value) {
194.1433 - var existingIndex = ko.utils.arrayIndexOf(keys, key);
194.1434 - if (existingIndex >= 0)
194.1435 - values[existingIndex] = value;
194.1436 - else {
194.1437 - keys.push(key);
194.1438 - values.push(value);
194.1439 - }
194.1440 - };
194.1441 - this.get = function(key) {
194.1442 - var existingIndex = ko.utils.arrayIndexOf(keys, key);
194.1443 - return (existingIndex >= 0) ? values[existingIndex] : undefined;
194.1444 - };
194.1445 - };
194.1446 -})();
194.1447 -
194.1448 -ko.exportSymbol('toJS', ko.toJS);
194.1449 -ko.exportSymbol('toJSON', ko.toJSON);
194.1450 -(function () {
194.1451 - var hasDomDataExpandoProperty = '__ko__hasDomDataOptionValue__';
194.1452 -
194.1453 - // Normally, SELECT elements and their OPTIONs can only take value of type 'string' (because the values
194.1454 - // are stored on DOM attributes). ko.selectExtensions provides a way for SELECTs/OPTIONs to have values
194.1455 - // that are arbitrary objects. This is very convenient when implementing things like cascading dropdowns.
194.1456 - ko.selectExtensions = {
194.1457 - readValue : function(element) {
194.1458 - switch (ko.utils.tagNameLower(element)) {
194.1459 - case 'option':
194.1460 - if (element[hasDomDataExpandoProperty] === true)
194.1461 - return ko.utils.domData.get(element, ko.bindingHandlers.options.optionValueDomDataKey);
194.1462 - return ko.utils.ieVersion <= 7
194.1463 - ? (element.getAttributeNode('value').specified ? element.value : element.text)
194.1464 - : element.value;
194.1465 - case 'select':
194.1466 - return element.selectedIndex >= 0 ? ko.selectExtensions.readValue(element.options[element.selectedIndex]) : undefined;
194.1467 - default:
194.1468 - return element.value;
194.1469 - }
194.1470 - },
194.1471 -
194.1472 - writeValue: function(element, value) {
194.1473 - switch (ko.utils.tagNameLower(element)) {
194.1474 - case 'option':
194.1475 - switch(typeof value) {
194.1476 - case "string":
194.1477 - ko.utils.domData.set(element, ko.bindingHandlers.options.optionValueDomDataKey, undefined);
194.1478 - if (hasDomDataExpandoProperty in element) { // IE <= 8 throws errors if you delete non-existent properties from a DOM node
194.1479 - delete element[hasDomDataExpandoProperty];
194.1480 - }
194.1481 - element.value = value;
194.1482 - break;
194.1483 - default:
194.1484 - // Store arbitrary object using DomData
194.1485 - ko.utils.domData.set(element, ko.bindingHandlers.options.optionValueDomDataKey, value);
194.1486 - element[hasDomDataExpandoProperty] = true;
194.1487 -
194.1488 - // Special treatment of numbers is just for backward compatibility. KO 1.2.1 wrote numerical values to element.value.
194.1489 - element.value = typeof value === "number" ? value : "";
194.1490 - break;
194.1491 - }
194.1492 - break;
194.1493 - case 'select':
194.1494 - for (var i = element.options.length - 1; i >= 0; i--) {
194.1495 - if (ko.selectExtensions.readValue(element.options[i]) == value) {
194.1496 - element.selectedIndex = i;
194.1497 - break;
194.1498 - }
194.1499 - }
194.1500 - break;
194.1501 - default:
194.1502 - if ((value === null) || (value === undefined))
194.1503 - value = "";
194.1504 - element.value = value;
194.1505 - break;
194.1506 - }
194.1507 - }
194.1508 - };
194.1509 -})();
194.1510 -
194.1511 -ko.exportSymbol('selectExtensions', ko.selectExtensions);
194.1512 -ko.exportSymbol('selectExtensions.readValue', ko.selectExtensions.readValue);
194.1513 -ko.exportSymbol('selectExtensions.writeValue', ko.selectExtensions.writeValue);
194.1514 -ko.expressionRewriting = (function () {
194.1515 - var restoreCapturedTokensRegex = /\@ko_token_(\d+)\@/g;
194.1516 - var javaScriptReservedWords = ["true", "false"];
194.1517 -
194.1518 - // Matches something that can be assigned to--either an isolated identifier or something ending with a property accessor
194.1519 - // This is designed to be simple and avoid false negatives, but could produce false positives (e.g., a+b.c).
194.1520 - var javaScriptAssignmentTarget = /^(?:[$_a-z][$\w]*|(.+)(\.\s*[$_a-z][$\w]*|\[.+\]))$/i;
194.1521 -
194.1522 - function restoreTokens(string, tokens) {
194.1523 - var prevValue = null;
194.1524 - while (string != prevValue) { // Keep restoring tokens until it no longer makes a difference (they may be nested)
194.1525 - prevValue = string;
194.1526 - string = string.replace(restoreCapturedTokensRegex, function (match, tokenIndex) {
194.1527 - return tokens[tokenIndex];
194.1528 - });
194.1529 - }
194.1530 - return string;
194.1531 - }
194.1532 -
194.1533 - function getWriteableValue(expression) {
194.1534 - if (ko.utils.arrayIndexOf(javaScriptReservedWords, ko.utils.stringTrim(expression).toLowerCase()) >= 0)
194.1535 - return false;
194.1536 - var match = expression.match(javaScriptAssignmentTarget);
194.1537 - return match === null ? false : match[1] ? ('Object(' + match[1] + ')' + match[2]) : expression;
194.1538 - }
194.1539 -
194.1540 - function ensureQuoted(key) {
194.1541 - var trimmedKey = ko.utils.stringTrim(key);
194.1542 - switch (trimmedKey.length && trimmedKey.charAt(0)) {
194.1543 - case "'":
194.1544 - case '"':
194.1545 - return key;
194.1546 - default:
194.1547 - return "'" + trimmedKey + "'";
194.1548 - }
194.1549 - }
194.1550 -
194.1551 - return {
194.1552 - bindingRewriteValidators: [],
194.1553 -
194.1554 - parseObjectLiteral: function(objectLiteralString) {
194.1555 - // A full tokeniser+lexer would add too much weight to this library, so here's a simple parser
194.1556 - // that is sufficient just to split an object literal string into a set of top-level key-value pairs
194.1557 -
194.1558 - var str = ko.utils.stringTrim(objectLiteralString);
194.1559 - if (str.length < 3)
194.1560 - return [];
194.1561 - if (str.charAt(0) === "{")// Ignore any braces surrounding the whole object literal
194.1562 - str = str.substring(1, str.length - 1);
194.1563 -
194.1564 - // Pull out any string literals and regex literals
194.1565 - var tokens = [];
194.1566 - var tokenStart = null, tokenEndChar;
194.1567 - for (var position = 0; position < str.length; position++) {
194.1568 - var c = str.charAt(position);
194.1569 - if (tokenStart === null) {
194.1570 - switch (c) {
194.1571 - case '"':
194.1572 - case "'":
194.1573 - case "/":
194.1574 - tokenStart = position;
194.1575 - tokenEndChar = c;
194.1576 - break;
194.1577 - }
194.1578 - } else if ((c == tokenEndChar) && (str.charAt(position - 1) !== "\\")) {
194.1579 - var token = str.substring(tokenStart, position + 1);
194.1580 - tokens.push(token);
194.1581 - var replacement = "@ko_token_" + (tokens.length - 1) + "@";
194.1582 - str = str.substring(0, tokenStart) + replacement + str.substring(position + 1);
194.1583 - position -= (token.length - replacement.length);
194.1584 - tokenStart = null;
194.1585 - }
194.1586 - }
194.1587 -
194.1588 - // Next pull out balanced paren, brace, and bracket blocks
194.1589 - tokenStart = null;
194.1590 - tokenEndChar = null;
194.1591 - var tokenDepth = 0, tokenStartChar = null;
194.1592 - for (var position = 0; position < str.length; position++) {
194.1593 - var c = str.charAt(position);
194.1594 - if (tokenStart === null) {
194.1595 - switch (c) {
194.1596 - case "{": tokenStart = position; tokenStartChar = c;
194.1597 - tokenEndChar = "}";
194.1598 - break;
194.1599 - case "(": tokenStart = position; tokenStartChar = c;
194.1600 - tokenEndChar = ")";
194.1601 - break;
194.1602 - case "[": tokenStart = position; tokenStartChar = c;
194.1603 - tokenEndChar = "]";
194.1604 - break;
194.1605 - }
194.1606 - }
194.1607 -
194.1608 - if (c === tokenStartChar)
194.1609 - tokenDepth++;
194.1610 - else if (c === tokenEndChar) {
194.1611 - tokenDepth--;
194.1612 - if (tokenDepth === 0) {
194.1613 - var token = str.substring(tokenStart, position + 1);
194.1614 - tokens.push(token);
194.1615 - var replacement = "@ko_token_" + (tokens.length - 1) + "@";
194.1616 - str = str.substring(0, tokenStart) + replacement + str.substring(position + 1);
194.1617 - position -= (token.length - replacement.length);
194.1618 - tokenStart = null;
194.1619 - }
194.1620 - }
194.1621 - }
194.1622 -
194.1623 - // Now we can safely split on commas to get the key/value pairs
194.1624 - var result = [];
194.1625 - var keyValuePairs = str.split(",");
194.1626 - for (var i = 0, j = keyValuePairs.length; i < j; i++) {
194.1627 - var pair = keyValuePairs[i];
194.1628 - var colonPos = pair.indexOf(":");
194.1629 - if ((colonPos > 0) && (colonPos < pair.length - 1)) {
194.1630 - var key = pair.substring(0, colonPos);
194.1631 - var value = pair.substring(colonPos + 1);
194.1632 - result.push({ 'key': restoreTokens(key, tokens), 'value': restoreTokens(value, tokens) });
194.1633 - } else {
194.1634 - result.push({ 'unknown': restoreTokens(pair, tokens) });
194.1635 - }
194.1636 - }
194.1637 - return result;
194.1638 - },
194.1639 -
194.1640 - preProcessBindings: function (objectLiteralStringOrKeyValueArray) {
194.1641 - var keyValueArray = typeof objectLiteralStringOrKeyValueArray === "string"
194.1642 - ? ko.expressionRewriting.parseObjectLiteral(objectLiteralStringOrKeyValueArray)
194.1643 - : objectLiteralStringOrKeyValueArray;
194.1644 - var resultStrings = [], propertyAccessorResultStrings = [];
194.1645 -
194.1646 - var keyValueEntry;
194.1647 - for (var i = 0; keyValueEntry = keyValueArray[i]; i++) {
194.1648 - if (resultStrings.length > 0)
194.1649 - resultStrings.push(",");
194.1650 -
194.1651 - if (keyValueEntry['key']) {
194.1652 - var quotedKey = ensureQuoted(keyValueEntry['key']), val = keyValueEntry['value'];
194.1653 - resultStrings.push(quotedKey);
194.1654 - resultStrings.push(":");
194.1655 - resultStrings.push(val);
194.1656 -
194.1657 - if (val = getWriteableValue(ko.utils.stringTrim(val))) {
194.1658 - if (propertyAccessorResultStrings.length > 0)
194.1659 - propertyAccessorResultStrings.push(", ");
194.1660 - propertyAccessorResultStrings.push(quotedKey + " : function(__ko_value) { " + val + " = __ko_value; }");
194.1661 - }
194.1662 - } else if (keyValueEntry['unknown']) {
194.1663 - resultStrings.push(keyValueEntry['unknown']);
194.1664 - }
194.1665 - }
194.1666 -
194.1667 - var combinedResult = resultStrings.join("");
194.1668 - if (propertyAccessorResultStrings.length > 0) {
194.1669 - var allPropertyAccessors = propertyAccessorResultStrings.join("");
194.1670 - combinedResult = combinedResult + ", '_ko_property_writers' : { " + allPropertyAccessors + " } ";
194.1671 - }
194.1672 -
194.1673 - return combinedResult;
194.1674 - },
194.1675 -
194.1676 - keyValueArrayContainsKey: function(keyValueArray, key) {
194.1677 - for (var i = 0; i < keyValueArray.length; i++)
194.1678 - if (ko.utils.stringTrim(keyValueArray[i]['key']) == key)
194.1679 - return true;
194.1680 - return false;
194.1681 - },
194.1682 -
194.1683 - // Internal, private KO utility for updating model properties from within bindings
194.1684 - // property: If the property being updated is (or might be) an observable, pass it here
194.1685 - // If it turns out to be a writable observable, it will be written to directly
194.1686 - // allBindingsAccessor: All bindings in the current execution context.
194.1687 - // This will be searched for a '_ko_property_writers' property in case you're writing to a non-observable
194.1688 - // key: The key identifying the property to be written. Example: for { hasFocus: myValue }, write to 'myValue' by specifying the key 'hasFocus'
194.1689 - // value: The value to be written
194.1690 - // checkIfDifferent: If true, and if the property being written is a writable observable, the value will only be written if
194.1691 - // it is !== existing value on that writable observable
194.1692 - writeValueToProperty: function(property, allBindingsAccessor, key, value, checkIfDifferent) {
194.1693 - if (!property || !ko.isWriteableObservable(property)) {
194.1694 - var propWriters = allBindingsAccessor()['_ko_property_writers'];
194.1695 - if (propWriters && propWriters[key])
194.1696 - propWriters[key](value);
194.1697 - } else if (!checkIfDifferent || property.peek() !== value) {
194.1698 - property(value);
194.1699 - }
194.1700 - }
194.1701 - };
194.1702 -})();
194.1703 -
194.1704 -ko.exportSymbol('expressionRewriting', ko.expressionRewriting);
194.1705 -ko.exportSymbol('expressionRewriting.bindingRewriteValidators', ko.expressionRewriting.bindingRewriteValidators);
194.1706 -ko.exportSymbol('expressionRewriting.parseObjectLiteral', ko.expressionRewriting.parseObjectLiteral);
194.1707 -ko.exportSymbol('expressionRewriting.preProcessBindings', ko.expressionRewriting.preProcessBindings);
194.1708 -
194.1709 -// For backward compatibility, define the following aliases. (Previously, these function names were misleading because
194.1710 -// they referred to JSON specifically, even though they actually work with arbitrary JavaScript object literal expressions.)
194.1711 -ko.exportSymbol('jsonExpressionRewriting', ko.expressionRewriting);
194.1712 -ko.exportSymbol('jsonExpressionRewriting.insertPropertyAccessorsIntoJson', ko.expressionRewriting.preProcessBindings);(function() {
194.1713 - // "Virtual elements" is an abstraction on top of the usual DOM API which understands the notion that comment nodes
194.1714 - // may be used to represent hierarchy (in addition to the DOM's natural hierarchy).
194.1715 - // If you call the DOM-manipulating functions on ko.virtualElements, you will be able to read and write the state
194.1716 - // of that virtual hierarchy
194.1717 - //
194.1718 - // The point of all this is to support containerless templates (e.g., <!-- ko foreach:someCollection -->blah<!-- /ko -->)
194.1719 - // without having to scatter special cases all over the binding and templating code.
194.1720 -
194.1721 - // IE 9 cannot reliably read the "nodeValue" property of a comment node (see https://github.com/SteveSanderson/knockout/issues/186)
194.1722 - // but it does give them a nonstandard alternative property called "text" that it can read reliably. Other browsers don't have that property.
194.1723 - // So, use node.text where available, and node.nodeValue elsewhere
194.1724 - var commentNodesHaveTextProperty = document.createComment("test").text === "<!--test-->";
194.1725 -
194.1726 - var startCommentRegex = commentNodesHaveTextProperty ? /^<!--\s*ko(?:\s+(.+\s*\:[\s\S]*))?\s*-->$/ : /^\s*ko(?:\s+(.+\s*\:[\s\S]*))?\s*$/;
194.1727 - var endCommentRegex = commentNodesHaveTextProperty ? /^<!--\s*\/ko\s*-->$/ : /^\s*\/ko\s*$/;
194.1728 - var htmlTagsWithOptionallyClosingChildren = { 'ul': true, 'ol': true };
194.1729 -
194.1730 - function isStartComment(node) {
194.1731 - return (node.nodeType == 8) && (commentNodesHaveTextProperty ? node.text : node.nodeValue).match(startCommentRegex);
194.1732 - }
194.1733 -
194.1734 - function isEndComment(node) {
194.1735 - return (node.nodeType == 8) && (commentNodesHaveTextProperty ? node.text : node.nodeValue).match(endCommentRegex);
194.1736 - }
194.1737 -
194.1738 - function getVirtualChildren(startComment, allowUnbalanced) {
194.1739 - var currentNode = startComment;
194.1740 - var depth = 1;
194.1741 - var children = [];
194.1742 - while (currentNode = currentNode.nextSibling) {
194.1743 - if (isEndComment(currentNode)) {
194.1744 - depth--;
194.1745 - if (depth === 0)
194.1746 - return children;
194.1747 - }
194.1748 -
194.1749 - children.push(currentNode);
194.1750 -
194.1751 - if (isStartComment(currentNode))
194.1752 - depth++;
194.1753 - }
194.1754 - if (!allowUnbalanced)
194.1755 - throw new Error("Cannot find closing comment tag to match: " + startComment.nodeValue);
194.1756 - return null;
194.1757 - }
194.1758 -
194.1759 - function getMatchingEndComment(startComment, allowUnbalanced) {
194.1760 - var allVirtualChildren = getVirtualChildren(startComment, allowUnbalanced);
194.1761 - if (allVirtualChildren) {
194.1762 - if (allVirtualChildren.length > 0)
194.1763 - return allVirtualChildren[allVirtualChildren.length - 1].nextSibling;
194.1764 - return startComment.nextSibling;
194.1765 - } else
194.1766 - return null; // Must have no matching end comment, and allowUnbalanced is true
194.1767 - }
194.1768 -
194.1769 - function getUnbalancedChildTags(node) {
194.1770 - // e.g., from <div>OK</div><!-- ko blah --><span>Another</span>, returns: <!-- ko blah --><span>Another</span>
194.1771 - // from <div>OK</div><!-- /ko --><!-- /ko -->, returns: <!-- /ko --><!-- /ko -->
194.1772 - var childNode = node.firstChild, captureRemaining = null;
194.1773 - if (childNode) {
194.1774 - do {
194.1775 - if (captureRemaining) // We already hit an unbalanced node and are now just scooping up all subsequent nodes
194.1776 - captureRemaining.push(childNode);
194.1777 - else if (isStartComment(childNode)) {
194.1778 - var matchingEndComment = getMatchingEndComment(childNode, /* allowUnbalanced: */ true);
194.1779 - if (matchingEndComment) // It's a balanced tag, so skip immediately to the end of this virtual set
194.1780 - childNode = matchingEndComment;
194.1781 - else
194.1782 - captureRemaining = [childNode]; // It's unbalanced, so start capturing from this point
194.1783 - } else if (isEndComment(childNode)) {
194.1784 - captureRemaining = [childNode]; // It's unbalanced (if it wasn't, we'd have skipped over it already), so start capturing
194.1785 - }
194.1786 - } while (childNode = childNode.nextSibling);
194.1787 - }
194.1788 - return captureRemaining;
194.1789 - }
194.1790 -
194.1791 - ko.virtualElements = {
194.1792 - allowedBindings: {},
194.1793 -
194.1794 - childNodes: function(node) {
194.1795 - return isStartComment(node) ? getVirtualChildren(node) : node.childNodes;
194.1796 - },
194.1797 -
194.1798 - emptyNode: function(node) {
194.1799 - if (!isStartComment(node))
194.1800 - ko.utils.emptyDomNode(node);
194.1801 - else {
194.1802 - var virtualChildren = ko.virtualElements.childNodes(node);
194.1803 - for (var i = 0, j = virtualChildren.length; i < j; i++)
194.1804 - ko.removeNode(virtualChildren[i]);
194.1805 - }
194.1806 - },
194.1807 -
194.1808 - setDomNodeChildren: function(node, childNodes) {
194.1809 - if (!isStartComment(node))
194.1810 - ko.utils.setDomNodeChildren(node, childNodes);
194.1811 - else {
194.1812 - ko.virtualElements.emptyNode(node);
194.1813 - var endCommentNode = node.nextSibling; // Must be the next sibling, as we just emptied the children
194.1814 - for (var i = 0, j = childNodes.length; i < j; i++)
194.1815 - endCommentNode.parentNode.insertBefore(childNodes[i], endCommentNode);
194.1816 - }
194.1817 - },
194.1818 -
194.1819 - prepend: function(containerNode, nodeToPrepend) {
194.1820 - if (!isStartComment(containerNode)) {
194.1821 - if (containerNode.firstChild)
194.1822 - containerNode.insertBefore(nodeToPrepend, containerNode.firstChild);
194.1823 - else
194.1824 - containerNode.appendChild(nodeToPrepend);
194.1825 - } else {
194.1826 - // Start comments must always have a parent and at least one following sibling (the end comment)
194.1827 - containerNode.parentNode.insertBefore(nodeToPrepend, containerNode.nextSibling);
194.1828 - }
194.1829 - },
194.1830 -
194.1831 - insertAfter: function(containerNode, nodeToInsert, insertAfterNode) {
194.1832 - if (!insertAfterNode) {
194.1833 - ko.virtualElements.prepend(containerNode, nodeToInsert);
194.1834 - } else if (!isStartComment(containerNode)) {
194.1835 - // Insert after insertion point
194.1836 - if (insertAfterNode.nextSibling)
194.1837 - containerNode.insertBefore(nodeToInsert, insertAfterNode.nextSibling);
194.1838 - else
194.1839 - containerNode.appendChild(nodeToInsert);
194.1840 - } else {
194.1841 - // Children of start comments must always have a parent and at least one following sibling (the end comment)
194.1842 - containerNode.parentNode.insertBefore(nodeToInsert, insertAfterNode.nextSibling);
194.1843 - }
194.1844 - },
194.1845 -
194.1846 - firstChild: function(node) {
194.1847 - if (!isStartComment(node))
194.1848 - return node.firstChild;
194.1849 - if (!node.nextSibling || isEndComment(node.nextSibling))
194.1850 - return null;
194.1851 - return node.nextSibling;
194.1852 - },
194.1853 -
194.1854 - nextSibling: function(node) {
194.1855 - if (isStartComment(node))
194.1856 - node = getMatchingEndComment(node);
194.1857 - if (node.nextSibling && isEndComment(node.nextSibling))
194.1858 - return null;
194.1859 - return node.nextSibling;
194.1860 - },
194.1861 -
194.1862 - virtualNodeBindingValue: function(node) {
194.1863 - var regexMatch = isStartComment(node);
194.1864 - return regexMatch ? regexMatch[1] : null;
194.1865 - },
194.1866 -
194.1867 - normaliseVirtualElementDomStructure: function(elementVerified) {
194.1868 - // Workaround for https://github.com/SteveSanderson/knockout/issues/155
194.1869 - // (IE <= 8 or IE 9 quirks mode parses your HTML weirdly, treating closing </li> tags as if they don't exist, thereby moving comment nodes
194.1870 - // that are direct descendants of <ul> into the preceding <li>)
194.1871 - if (!htmlTagsWithOptionallyClosingChildren[ko.utils.tagNameLower(elementVerified)])
194.1872 - return;
194.1873 -
194.1874 - // Scan immediate children to see if they contain unbalanced comment tags. If they do, those comment tags
194.1875 - // must be intended to appear *after* that child, so move them there.
194.1876 - var childNode = elementVerified.firstChild;
194.1877 - if (childNode) {
194.1878 - do {
194.1879 - if (childNode.nodeType === 1) {
194.1880 - var unbalancedTags = getUnbalancedChildTags(childNode);
194.1881 - if (unbalancedTags) {
194.1882 - // Fix up the DOM by moving the unbalanced tags to where they most likely were intended to be placed - *after* the child
194.1883 - var nodeToInsertBefore = childNode.nextSibling;
194.1884 - for (var i = 0; i < unbalancedTags.length; i++) {
194.1885 - if (nodeToInsertBefore)
194.1886 - elementVerified.insertBefore(unbalancedTags[i], nodeToInsertBefore);
194.1887 - else
194.1888 - elementVerified.appendChild(unbalancedTags[i]);
194.1889 - }
194.1890 - }
194.1891 - }
194.1892 - } while (childNode = childNode.nextSibling);
194.1893 - }
194.1894 - }
194.1895 - };
194.1896 -})();
194.1897 -ko.exportSymbol('virtualElements', ko.virtualElements);
194.1898 -ko.exportSymbol('virtualElements.allowedBindings', ko.virtualElements.allowedBindings);
194.1899 -ko.exportSymbol('virtualElements.emptyNode', ko.virtualElements.emptyNode);
194.1900 -//ko.exportSymbol('virtualElements.firstChild', ko.virtualElements.firstChild); // firstChild is not minified
194.1901 -ko.exportSymbol('virtualElements.insertAfter', ko.virtualElements.insertAfter);
194.1902 -//ko.exportSymbol('virtualElements.nextSibling', ko.virtualElements.nextSibling); // nextSibling is not minified
194.1903 -ko.exportSymbol('virtualElements.prepend', ko.virtualElements.prepend);
194.1904 -ko.exportSymbol('virtualElements.setDomNodeChildren', ko.virtualElements.setDomNodeChildren);
194.1905 -(function() {
194.1906 - var defaultBindingAttributeName = "data-bind";
194.1907 -
194.1908 - ko.bindingProvider = function() {
194.1909 - this.bindingCache = {};
194.1910 - };
194.1911 -
194.1912 - ko.utils.extend(ko.bindingProvider.prototype, {
194.1913 - 'nodeHasBindings': function(node) {
194.1914 - switch (node.nodeType) {
194.1915 - case 1: return node.getAttribute(defaultBindingAttributeName) != null; // Element
194.1916 - case 8: return ko.virtualElements.virtualNodeBindingValue(node) != null; // Comment node
194.1917 - default: return false;
194.1918 - }
194.1919 - },
194.1920 -
194.1921 - 'getBindings': function(node, bindingContext) {
194.1922 - var bindingsString = this['getBindingsString'](node, bindingContext);
194.1923 - return bindingsString ? this['parseBindingsString'](bindingsString, bindingContext, node) : null;
194.1924 - },
194.1925 -
194.1926 - // The following function is only used internally by this default provider.
194.1927 - // It's not part of the interface definition for a general binding provider.
194.1928 - 'getBindingsString': function(node, bindingContext) {
194.1929 - switch (node.nodeType) {
194.1930 - case 1: return node.getAttribute(defaultBindingAttributeName); // Element
194.1931 - case 8: return ko.virtualElements.virtualNodeBindingValue(node); // Comment node
194.1932 - default: return null;
194.1933 - }
194.1934 - },
194.1935 -
194.1936 - // The following function is only used internally by this default provider.
194.1937 - // It's not part of the interface definition for a general binding provider.
194.1938 - 'parseBindingsString': function(bindingsString, bindingContext, node) {
194.1939 - try {
194.1940 - var bindingFunction = createBindingsStringEvaluatorViaCache(bindingsString, this.bindingCache);
194.1941 - return bindingFunction(bindingContext, node);
194.1942 - } catch (ex) {
194.1943 - throw new Error("Unable to parse bindings.\nMessage: " + ex + ";\nBindings value: " + bindingsString);
194.1944 - }
194.1945 - }
194.1946 - });
194.1947 -
194.1948 - ko.bindingProvider['instance'] = new ko.bindingProvider();
194.1949 -
194.1950 - function createBindingsStringEvaluatorViaCache(bindingsString, cache) {
194.1951 - var cacheKey = bindingsString;
194.1952 - return cache[cacheKey]
194.1953 - || (cache[cacheKey] = createBindingsStringEvaluator(bindingsString));
194.1954 - }
194.1955 -
194.1956 - function createBindingsStringEvaluator(bindingsString) {
194.1957 - // Build the source for a function that evaluates "expression"
194.1958 - // For each scope variable, add an extra level of "with" nesting
194.1959 - // Example result: with(sc1) { with(sc0) { return (expression) } }
194.1960 - var rewrittenBindings = ko.expressionRewriting.preProcessBindings(bindingsString),
194.1961 - functionBody = "with($context){with($data||{}){return{" + rewrittenBindings + "}}}";
194.1962 - return new Function("$context", "$element", functionBody);
194.1963 - }
194.1964 -})();
194.1965 -
194.1966 -ko.exportSymbol('bindingProvider', ko.bindingProvider);
194.1967 -(function () {
194.1968 - ko.bindingHandlers = {};
194.1969 -
194.1970 - ko.bindingContext = function(dataItem, parentBindingContext, dataItemAlias) {
194.1971 - if (parentBindingContext) {
194.1972 - ko.utils.extend(this, parentBindingContext); // Inherit $root and any custom properties
194.1973 - this['$parentContext'] = parentBindingContext;
194.1974 - this['$parent'] = parentBindingContext['$data'];
194.1975 - this['$parents'] = (parentBindingContext['$parents'] || []).slice(0);
194.1976 - this['$parents'].unshift(this['$parent']);
194.1977 - } else {
194.1978 - this['$parents'] = [];
194.1979 - this['$root'] = dataItem;
194.1980 - // Export 'ko' in the binding context so it will be available in bindings and templates
194.1981 - // even if 'ko' isn't exported as a global, such as when using an AMD loader.
194.1982 - // See https://github.com/SteveSanderson/knockout/issues/490
194.1983 - this['ko'] = ko;
194.1984 - }
194.1985 - this['$data'] = dataItem;
194.1986 - if (dataItemAlias)
194.1987 - this[dataItemAlias] = dataItem;
194.1988 - }
194.1989 - ko.bindingContext.prototype['createChildContext'] = function (dataItem, dataItemAlias) {
194.1990 - return new ko.bindingContext(dataItem, this, dataItemAlias);
194.1991 - };
194.1992 - ko.bindingContext.prototype['extend'] = function(properties) {
194.1993 - var clone = ko.utils.extend(new ko.bindingContext(), this);
194.1994 - return ko.utils.extend(clone, properties);
194.1995 - };
194.1996 -
194.1997 - function validateThatBindingIsAllowedForVirtualElements(bindingName) {
194.1998 - var validator = ko.virtualElements.allowedBindings[bindingName];
194.1999 - if (!validator)
194.2000 - throw new Error("The binding '" + bindingName + "' cannot be used with virtual elements")
194.2001 - }
194.2002 -
194.2003 - function applyBindingsToDescendantsInternal (viewModel, elementOrVirtualElement, bindingContextsMayDifferFromDomParentElement) {
194.2004 - var currentChild, nextInQueue = ko.virtualElements.firstChild(elementOrVirtualElement);
194.2005 - while (currentChild = nextInQueue) {
194.2006 - // Keep a record of the next child *before* applying bindings, in case the binding removes the current child from its position
194.2007 - nextInQueue = ko.virtualElements.nextSibling(currentChild);
194.2008 - applyBindingsToNodeAndDescendantsInternal(viewModel, currentChild, bindingContextsMayDifferFromDomParentElement);
194.2009 - }
194.2010 - }
194.2011 -
194.2012 - function applyBindingsToNodeAndDescendantsInternal (viewModel, nodeVerified, bindingContextMayDifferFromDomParentElement) {
194.2013 - var shouldBindDescendants = true;
194.2014 -
194.2015 - // Perf optimisation: Apply bindings only if...
194.2016 - // (1) We need to store the binding context on this node (because it may differ from the DOM parent node's binding context)
194.2017 - // Note that we can't store binding contexts on non-elements (e.g., text nodes), as IE doesn't allow expando properties for those
194.2018 - // (2) It might have bindings (e.g., it has a data-bind attribute, or it's a marker for a containerless template)
194.2019 - var isElement = (nodeVerified.nodeType === 1);
194.2020 - if (isElement) // Workaround IE <= 8 HTML parsing weirdness
194.2021 - ko.virtualElements.normaliseVirtualElementDomStructure(nodeVerified);
194.2022 -
194.2023 - var shouldApplyBindings = (isElement && bindingContextMayDifferFromDomParentElement) // Case (1)
194.2024 - || ko.bindingProvider['instance']['nodeHasBindings'](nodeVerified); // Case (2)
194.2025 - if (shouldApplyBindings)
194.2026 - shouldBindDescendants = applyBindingsToNodeInternal(nodeVerified, null, viewModel, bindingContextMayDifferFromDomParentElement).shouldBindDescendants;
194.2027 -
194.2028 - if (shouldBindDescendants) {
194.2029 - // We're recursing automatically into (real or virtual) child nodes without changing binding contexts. So,
194.2030 - // * For children of a *real* element, the binding context is certainly the same as on their DOM .parentNode,
194.2031 - // hence bindingContextsMayDifferFromDomParentElement is false
194.2032 - // * For children of a *virtual* element, we can't be sure. Evaluating .parentNode on those children may
194.2033 - // skip over any number of intermediate virtual elements, any of which might define a custom binding context,
194.2034 - // hence bindingContextsMayDifferFromDomParentElement is true
194.2035 - applyBindingsToDescendantsInternal(viewModel, nodeVerified, /* bindingContextsMayDifferFromDomParentElement: */ !isElement);
194.2036 - }
194.2037 - }
194.2038 -
194.2039 - function applyBindingsToNodeInternal (node, bindings, viewModelOrBindingContext, bindingContextMayDifferFromDomParentElement) {
194.2040 - // Need to be sure that inits are only run once, and updates never run until all the inits have been run
194.2041 - var initPhase = 0; // 0 = before all inits, 1 = during inits, 2 = after all inits
194.2042 -
194.2043 - // Each time the dependentObservable is evaluated (after data changes),
194.2044 - // the binding attribute is reparsed so that it can pick out the correct
194.2045 - // model properties in the context of the changed data.
194.2046 - // DOM event callbacks need to be able to access this changed data,
194.2047 - // so we need a single parsedBindings variable (shared by all callbacks
194.2048 - // associated with this node's bindings) that all the closures can access.
194.2049 - var parsedBindings;
194.2050 - function makeValueAccessor(bindingKey) {
194.2051 - return function () { return parsedBindings[bindingKey] }
194.2052 - }
194.2053 - function parsedBindingsAccessor() {
194.2054 - return parsedBindings;
194.2055 - }
194.2056 -
194.2057 - var bindingHandlerThatControlsDescendantBindings;
194.2058 - ko.dependentObservable(
194.2059 - function () {
194.2060 - // Ensure we have a nonnull binding context to work with
194.2061 - var bindingContextInstance = viewModelOrBindingContext && (viewModelOrBindingContext instanceof ko.bindingContext)
194.2062 - ? viewModelOrBindingContext
194.2063 - : new ko.bindingContext(ko.utils.unwrapObservable(viewModelOrBindingContext));
194.2064 - var viewModel = bindingContextInstance['$data'];
194.2065 -
194.2066 - // Optimization: Don't store the binding context on this node if it's definitely the same as on node.parentNode, because
194.2067 - // we can easily recover it just by scanning up the node's ancestors in the DOM
194.2068 - // (note: here, parent node means "real DOM parent" not "virtual parent", as there's no O(1) way to find the virtual parent)
194.2069 - if (bindingContextMayDifferFromDomParentElement)
194.2070 - ko.storedBindingContextForNode(node, bindingContextInstance);
194.2071 -
194.2072 - // Use evaluatedBindings if given, otherwise fall back on asking the bindings provider to give us some bindings
194.2073 - var evaluatedBindings = (typeof bindings == "function") ? bindings(bindingContextInstance, node) : bindings;
194.2074 - parsedBindings = evaluatedBindings || ko.bindingProvider['instance']['getBindings'](node, bindingContextInstance);
194.2075 -
194.2076 - if (parsedBindings) {
194.2077 - // First run all the inits, so bindings can register for notification on changes
194.2078 - if (initPhase === 0) {
194.2079 - initPhase = 1;
194.2080 - for (var bindingKey in parsedBindings) {
194.2081 - var binding = ko.bindingHandlers[bindingKey];
194.2082 - if (binding && node.nodeType === 8)
194.2083 - validateThatBindingIsAllowedForVirtualElements(bindingKey);
194.2084 -
194.2085 - if (binding && typeof binding["init"] == "function") {
194.2086 - var handlerInitFn = binding["init"];
194.2087 - var initResult = handlerInitFn(node, makeValueAccessor(bindingKey), parsedBindingsAccessor, viewModel, bindingContextInstance);
194.2088 -
194.2089 - // If this binding handler claims to control descendant bindings, make a note of this
194.2090 - if (initResult && initResult['controlsDescendantBindings']) {
194.2091 - if (bindingHandlerThatControlsDescendantBindings !== undefined)
194.2092 - throw new Error("Multiple bindings (" + bindingHandlerThatControlsDescendantBindings + " and " + bindingKey + ") are trying to control descendant bindings of the same element. You cannot use these bindings together on the same element.");
194.2093 - bindingHandlerThatControlsDescendantBindings = bindingKey;
194.2094 - }
194.2095 - }
194.2096 - }
194.2097 - initPhase = 2;
194.2098 - }
194.2099 -
194.2100 - // ... then run all the updates, which might trigger changes even on the first evaluation
194.2101 - if (initPhase === 2) {
194.2102 - for (var bindingKey in parsedBindings) {
194.2103 - var binding = ko.bindingHandlers[bindingKey];
194.2104 - if (binding && typeof binding["update"] == "function") {
194.2105 - var handlerUpdateFn = binding["update"];
194.2106 - handlerUpdateFn(node, makeValueAccessor(bindingKey), parsedBindingsAccessor, viewModel, bindingContextInstance);
194.2107 - }
194.2108 - }
194.2109 - }
194.2110 - }
194.2111 - },
194.2112 - null,
194.2113 - { disposeWhenNodeIsRemoved : node }
194.2114 - );
194.2115 -
194.2116 - return {
194.2117 - shouldBindDescendants: bindingHandlerThatControlsDescendantBindings === undefined
194.2118 - };
194.2119 - };
194.2120 -
194.2121 - var storedBindingContextDomDataKey = "__ko_bindingContext__";
194.2122 - ko.storedBindingContextForNode = function (node, bindingContext) {
194.2123 - if (arguments.length == 2)
194.2124 - ko.utils.domData.set(node, storedBindingContextDomDataKey, bindingContext);
194.2125 - else
194.2126 - return ko.utils.domData.get(node, storedBindingContextDomDataKey);
194.2127 - }
194.2128 -
194.2129 - ko.applyBindingsToNode = function (node, bindings, viewModel) {
194.2130 - if (node.nodeType === 1) // If it's an element, workaround IE <= 8 HTML parsing weirdness
194.2131 - ko.virtualElements.normaliseVirtualElementDomStructure(node);
194.2132 - return applyBindingsToNodeInternal(node, bindings, viewModel, true);
194.2133 - };
194.2134 -
194.2135 - ko.applyBindingsToDescendants = function(viewModel, rootNode) {
194.2136 - if (rootNode.nodeType === 1 || rootNode.nodeType === 8)
194.2137 - applyBindingsToDescendantsInternal(viewModel, rootNode, true);
194.2138 - };
194.2139 -
194.2140 - ko.applyBindings = function (viewModel, rootNode) {
194.2141 - if (rootNode && (rootNode.nodeType !== 1) && (rootNode.nodeType !== 8))
194.2142 - throw new Error("ko.applyBindings: first parameter should be your view model; second parameter should be a DOM node");
194.2143 - rootNode = rootNode || window.document.body; // Make "rootNode" parameter optional
194.2144 -
194.2145 - applyBindingsToNodeAndDescendantsInternal(viewModel, rootNode, true);
194.2146 - };
194.2147 -
194.2148 - // Retrieving binding context from arbitrary nodes
194.2149 - ko.contextFor = function(node) {
194.2150 - // We can only do something meaningful for elements and comment nodes (in particular, not text nodes, as IE can't store domdata for them)
194.2151 - switch (node.nodeType) {
194.2152 - case 1:
194.2153 - case 8:
194.2154 - var context = ko.storedBindingContextForNode(node);
194.2155 - if (context) return context;
194.2156 - if (node.parentNode) return ko.contextFor(node.parentNode);
194.2157 - break;
194.2158 - }
194.2159 - return undefined;
194.2160 - };
194.2161 - ko.dataFor = function(node) {
194.2162 - var context = ko.contextFor(node);
194.2163 - return context ? context['$data'] : undefined;
194.2164 - };
194.2165 -
194.2166 - ko.exportSymbol('bindingHandlers', ko.bindingHandlers);
194.2167 - ko.exportSymbol('applyBindings', ko.applyBindings);
194.2168 - ko.exportSymbol('applyBindingsToDescendants', ko.applyBindingsToDescendants);
194.2169 - ko.exportSymbol('applyBindingsToNode', ko.applyBindingsToNode);
194.2170 - ko.exportSymbol('contextFor', ko.contextFor);
194.2171 - ko.exportSymbol('dataFor', ko.dataFor);
194.2172 -})();
194.2173 -var attrHtmlToJavascriptMap = { 'class': 'className', 'for': 'htmlFor' };
194.2174 -ko.bindingHandlers['attr'] = {
194.2175 - 'update': function(element, valueAccessor, allBindingsAccessor) {
194.2176 - var value = ko.utils.unwrapObservable(valueAccessor()) || {};
194.2177 - for (var attrName in value) {
194.2178 - if (typeof attrName == "string") {
194.2179 - var attrValue = ko.utils.unwrapObservable(value[attrName]);
194.2180 -
194.2181 - // To cover cases like "attr: { checked:someProp }", we want to remove the attribute entirely
194.2182 - // when someProp is a "no value"-like value (strictly null, false, or undefined)
194.2183 - // (because the absence of the "checked" attr is how to mark an element as not checked, etc.)
194.2184 - var toRemove = (attrValue === false) || (attrValue === null) || (attrValue === undefined);
194.2185 - if (toRemove)
194.2186 - element.removeAttribute(attrName);
194.2187 -
194.2188 - // In IE <= 7 and IE8 Quirks Mode, you have to use the Javascript property name instead of the
194.2189 - // HTML attribute name for certain attributes. IE8 Standards Mode supports the correct behavior,
194.2190 - // but instead of figuring out the mode, we'll just set the attribute through the Javascript
194.2191 - // property for IE <= 8.
194.2192 - if (ko.utils.ieVersion <= 8 && attrName in attrHtmlToJavascriptMap) {
194.2193 - attrName = attrHtmlToJavascriptMap[attrName];
194.2194 - if (toRemove)
194.2195 - element.removeAttribute(attrName);
194.2196 - else
194.2197 - element[attrName] = attrValue;
194.2198 - } else if (!toRemove) {
194.2199 - try {
194.2200 - element.setAttribute(attrName, attrValue.toString());
194.2201 - } catch (err) {
194.2202 - // ignore for now
194.2203 - if (console) {
194.2204 - console.log("Can't set attribute " + attrName + " to " + attrValue + " error: " + err);
194.2205 - }
194.2206 - }
194.2207 - }
194.2208 -
194.2209 - // Treat "name" specially - although you can think of it as an attribute, it also needs
194.2210 - // special handling on older versions of IE (https://github.com/SteveSanderson/knockout/pull/333)
194.2211 - // Deliberately being case-sensitive here because XHTML would regard "Name" as a different thing
194.2212 - // entirely, and there's no strong reason to allow for such casing in HTML.
194.2213 - if (attrName === "name") {
194.2214 - ko.utils.setElementName(element, toRemove ? "" : attrValue.toString());
194.2215 - }
194.2216 - }
194.2217 - }
194.2218 - }
194.2219 -};
194.2220 -ko.bindingHandlers['checked'] = {
194.2221 - 'init': function (element, valueAccessor, allBindingsAccessor) {
194.2222 - var updateHandler = function() {
194.2223 - var valueToWrite;
194.2224 - if (element.type == "checkbox") {
194.2225 - valueToWrite = element.checked;
194.2226 - } else if ((element.type == "radio") && (element.checked)) {
194.2227 - valueToWrite = element.value;
194.2228 - } else {
194.2229 - return; // "checked" binding only responds to checkboxes and selected radio buttons
194.2230 - }
194.2231 -
194.2232 - var modelValue = valueAccessor(), unwrappedValue = ko.utils.unwrapObservable(modelValue);
194.2233 - if ((element.type == "checkbox") && (unwrappedValue instanceof Array)) {
194.2234 - // For checkboxes bound to an array, we add/remove the checkbox value to that array
194.2235 - // This works for both observable and non-observable arrays
194.2236 - var existingEntryIndex = ko.utils.arrayIndexOf(unwrappedValue, element.value);
194.2237 - if (element.checked && (existingEntryIndex < 0))
194.2238 - modelValue.push(element.value);
194.2239 - else if ((!element.checked) && (existingEntryIndex >= 0))
194.2240 - modelValue.splice(existingEntryIndex, 1);
194.2241 - } else {
194.2242 - ko.expressionRewriting.writeValueToProperty(modelValue, allBindingsAccessor, 'checked', valueToWrite, true);
194.2243 - }
194.2244 - };
194.2245 - ko.utils.registerEventHandler(element, "click", updateHandler);
194.2246 -
194.2247 - // IE 6 won't allow radio buttons to be selected unless they have a name
194.2248 - if ((element.type == "radio") && !element.name)
194.2249 - ko.bindingHandlers['uniqueName']['init'](element, function() { return true });
194.2250 - },
194.2251 - 'update': function (element, valueAccessor) {
194.2252 - var value = ko.utils.unwrapObservable(valueAccessor());
194.2253 -
194.2254 - if (element.type == "checkbox") {
194.2255 - if (value instanceof Array) {
194.2256 - // When bound to an array, the checkbox being checked represents its value being present in that array
194.2257 - element.checked = ko.utils.arrayIndexOf(value, element.value) >= 0;
194.2258 - } else {
194.2259 - // When bound to anything other value (not an array), the checkbox being checked represents the value being trueish
194.2260 - element.checked = value;
194.2261 - }
194.2262 - } else if (element.type == "radio") {
194.2263 - element.checked = (element.value == value);
194.2264 - }
194.2265 - }
194.2266 -};
194.2267 -var classesWrittenByBindingKey = '__ko__cssValue';
194.2268 -ko.bindingHandlers['css'] = {
194.2269 - 'update': function (element, valueAccessor) {
194.2270 - var value = ko.utils.unwrapObservable(valueAccessor());
194.2271 - if (typeof value == "object") {
194.2272 - for (var className in value) {
194.2273 - var shouldHaveClass = ko.utils.unwrapObservable(value[className]);
194.2274 - ko.utils.toggleDomNodeCssClass(element, className, shouldHaveClass);
194.2275 - }
194.2276 - } else {
194.2277 - value = String(value || ''); // Make sure we don't try to store or set a non-string value
194.2278 - ko.utils.toggleDomNodeCssClass(element, element[classesWrittenByBindingKey], false);
194.2279 - element[classesWrittenByBindingKey] = value;
194.2280 - ko.utils.toggleDomNodeCssClass(element, value, true);
194.2281 - }
194.2282 - }
194.2283 -};
194.2284 -ko.bindingHandlers['enable'] = {
194.2285 - 'update': function (element, valueAccessor) {
194.2286 - var value = ko.utils.unwrapObservable(valueAccessor());
194.2287 - if (value && element.disabled)
194.2288 - element.removeAttribute("disabled");
194.2289 - else if ((!value) && (!element.disabled))
194.2290 - element.disabled = true;
194.2291 - }
194.2292 -};
194.2293 -
194.2294 -ko.bindingHandlers['disable'] = {
194.2295 - 'update': function (element, valueAccessor) {
194.2296 - ko.bindingHandlers['enable']['update'](element, function() { return !ko.utils.unwrapObservable(valueAccessor()) });
194.2297 - }
194.2298 -};
194.2299 -// For certain common events (currently just 'click'), allow a simplified data-binding syntax
194.2300 -// e.g. click:handler instead of the usual full-length event:{click:handler}
194.2301 -function makeEventHandlerShortcut(eventName) {
194.2302 - ko.bindingHandlers[eventName] = {
194.2303 - 'init': function(element, valueAccessor, allBindingsAccessor, viewModel) {
194.2304 - var newValueAccessor = function () {
194.2305 - var result = {};
194.2306 - result[eventName] = valueAccessor();
194.2307 - return result;
194.2308 - };
194.2309 - return ko.bindingHandlers['event']['init'].call(this, element, newValueAccessor, allBindingsAccessor, viewModel);
194.2310 - }
194.2311 - }
194.2312 -}
194.2313 -
194.2314 -ko.bindingHandlers['event'] = {
194.2315 - 'init' : function (element, valueAccessor, allBindingsAccessor, viewModel) {
194.2316 - var eventsToHandle = valueAccessor() || {};
194.2317 - for(var eventNameOutsideClosure in eventsToHandle) {
194.2318 - (function() {
194.2319 - var eventName = eventNameOutsideClosure; // Separate variable to be captured by event handler closure
194.2320 - if (typeof eventName == "string") {
194.2321 - ko.utils.registerEventHandler(element, eventName, function (event) {
194.2322 - var handlerReturnValue;
194.2323 - var handlerFunction = valueAccessor()[eventName];
194.2324 - if (!handlerFunction)
194.2325 - return;
194.2326 - var allBindings = allBindingsAccessor();
194.2327 -
194.2328 - try {
194.2329 - // Take all the event args, and prefix with the viewmodel
194.2330 - var argsForHandler = ko.utils.makeArray(arguments);
194.2331 - argsForHandler.unshift(viewModel);
194.2332 - handlerReturnValue = handlerFunction.apply(viewModel, argsForHandler);
194.2333 - } finally {
194.2334 - if (handlerReturnValue !== true) { // Normally we want to prevent default action. Developer can override this be explicitly returning true.
194.2335 - if (event.preventDefault)
194.2336 - event.preventDefault();
194.2337 - else
194.2338 - event.returnValue = false;
194.2339 - }
194.2340 - }
194.2341 -
194.2342 - var bubble = allBindings[eventName + 'Bubble'] !== false;
194.2343 - if (!bubble) {
194.2344 - event.cancelBubble = true;
194.2345 - if (event.stopPropagation)
194.2346 - event.stopPropagation();
194.2347 - }
194.2348 - });
194.2349 - }
194.2350 - })();
194.2351 - }
194.2352 - }
194.2353 -};
194.2354 -// "foreach: someExpression" is equivalent to "template: { foreach: someExpression }"
194.2355 -// "foreach: { data: someExpression, afterAdd: myfn }" is equivalent to "template: { foreach: someExpression, afterAdd: myfn }"
194.2356 -ko.bindingHandlers['foreach'] = {
194.2357 - makeTemplateValueAccessor: function(valueAccessor) {
194.2358 - return function() {
194.2359 - var modelValue = valueAccessor(),
194.2360 - unwrappedValue = ko.utils.peekObservable(modelValue); // Unwrap without setting a dependency here
194.2361 -
194.2362 - // If unwrappedValue is the array, pass in the wrapped value on its own
194.2363 - // The value will be unwrapped and tracked within the template binding
194.2364 - // (See https://github.com/SteveSanderson/knockout/issues/523)
194.2365 - if ((!unwrappedValue) || typeof unwrappedValue.length == "number")
194.2366 - return { 'foreach': modelValue, 'templateEngine': ko.nativeTemplateEngine.instance };
194.2367 -
194.2368 - // If unwrappedValue.data is the array, preserve all relevant options and unwrap again value so we get updates
194.2369 - ko.utils.unwrapObservable(modelValue);
194.2370 - return {
194.2371 - 'foreach': unwrappedValue['data'],
194.2372 - 'as': unwrappedValue['as'],
194.2373 - 'includeDestroyed': unwrappedValue['includeDestroyed'],
194.2374 - 'afterAdd': unwrappedValue['afterAdd'],
194.2375 - 'beforeRemove': unwrappedValue['beforeRemove'],
194.2376 - 'afterRender': unwrappedValue['afterRender'],
194.2377 - 'beforeMove': unwrappedValue['beforeMove'],
194.2378 - 'afterMove': unwrappedValue['afterMove'],
194.2379 - 'templateEngine': ko.nativeTemplateEngine.instance
194.2380 - };
194.2381 - };
194.2382 - },
194.2383 - 'init': function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
194.2384 - return ko.bindingHandlers['template']['init'](element, ko.bindingHandlers['foreach'].makeTemplateValueAccessor(valueAccessor));
194.2385 - },
194.2386 - 'update': function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
194.2387 - return ko.bindingHandlers['template']['update'](element, ko.bindingHandlers['foreach'].makeTemplateValueAccessor(valueAccessor), allBindingsAccessor, viewModel, bindingContext);
194.2388 - }
194.2389 -};
194.2390 -ko.expressionRewriting.bindingRewriteValidators['foreach'] = false; // Can't rewrite control flow bindings
194.2391 -ko.virtualElements.allowedBindings['foreach'] = true;
194.2392 -var hasfocusUpdatingProperty = '__ko_hasfocusUpdating';
194.2393 -ko.bindingHandlers['hasfocus'] = {
194.2394 - 'init': function(element, valueAccessor, allBindingsAccessor) {
194.2395 - var handleElementFocusChange = function(isFocused) {
194.2396 - // Where possible, ignore which event was raised and determine focus state using activeElement,
194.2397 - // as this avoids phantom focus/blur events raised when changing tabs in modern browsers.
194.2398 - // However, not all KO-targeted browsers (Firefox 2) support activeElement. For those browsers,
194.2399 - // prevent a loss of focus when changing tabs/windows by setting a flag that prevents hasfocus
194.2400 - // from calling 'blur()' on the element when it loses focus.
194.2401 - // Discussion at https://github.com/SteveSanderson/knockout/pull/352
194.2402 - element[hasfocusUpdatingProperty] = true;
194.2403 - var ownerDoc = element.ownerDocument;
194.2404 - if ("activeElement" in ownerDoc) {
194.2405 - isFocused = (ownerDoc.activeElement === element);
194.2406 - }
194.2407 - var modelValue = valueAccessor();
194.2408 - ko.expressionRewriting.writeValueToProperty(modelValue, allBindingsAccessor, 'hasfocus', isFocused, true);
194.2409 - element[hasfocusUpdatingProperty] = false;
194.2410 - };
194.2411 - var handleElementFocusIn = handleElementFocusChange.bind(null, true);
194.2412 - var handleElementFocusOut = handleElementFocusChange.bind(null, false);
194.2413 -
194.2414 - ko.utils.registerEventHandler(element, "focus", handleElementFocusIn);
194.2415 - ko.utils.registerEventHandler(element, "focusin", handleElementFocusIn); // For IE
194.2416 - ko.utils.registerEventHandler(element, "blur", handleElementFocusOut);
194.2417 - ko.utils.registerEventHandler(element, "focusout", handleElementFocusOut); // For IE
194.2418 - },
194.2419 - 'update': function(element, valueAccessor) {
194.2420 - var value = ko.utils.unwrapObservable(valueAccessor());
194.2421 - if (!element[hasfocusUpdatingProperty]) {
194.2422 - value ? element.focus() : element.blur();
194.2423 - ko.dependencyDetection.ignore(ko.utils.triggerEvent, null, [element, value ? "focusin" : "focusout"]); // For IE, which doesn't reliably fire "focus" or "blur" events synchronously
194.2424 - }
194.2425 - }
194.2426 -};
194.2427 -ko.bindingHandlers['html'] = {
194.2428 - 'init': function() {
194.2429 - // Prevent binding on the dynamically-injected HTML (as developers are unlikely to expect that, and it has security implications)
194.2430 - return { 'controlsDescendantBindings': true };
194.2431 - },
194.2432 - 'update': function (element, valueAccessor) {
194.2433 - // setHtml will unwrap the value if needed
194.2434 - ko.utils.setHtml(element, valueAccessor());
194.2435 - }
194.2436 -};
194.2437 -var withIfDomDataKey = '__ko_withIfBindingData';
194.2438 -// Makes a binding like with or if
194.2439 -function makeWithIfBinding(bindingKey, isWith, isNot, makeContextCallback) {
194.2440 - ko.bindingHandlers[bindingKey] = {
194.2441 - 'init': function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
194.2442 - ko.utils.domData.set(element, withIfDomDataKey, {});
194.2443 - return { 'controlsDescendantBindings': true };
194.2444 - },
194.2445 - 'update': function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
194.2446 - var withIfData = ko.utils.domData.get(element, withIfDomDataKey),
194.2447 - dataValue = ko.utils.unwrapObservable(valueAccessor()),
194.2448 - shouldDisplay = !isNot !== !dataValue, // equivalent to isNot ? !dataValue : !!dataValue
194.2449 - isFirstRender = !withIfData.savedNodes,
194.2450 - needsRefresh = isFirstRender || isWith || (shouldDisplay !== withIfData.didDisplayOnLastUpdate);
194.2451 -
194.2452 - if (needsRefresh) {
194.2453 - if (isFirstRender) {
194.2454 - withIfData.savedNodes = ko.utils.cloneNodes(ko.virtualElements.childNodes(element), true /* shouldCleanNodes */);
194.2455 - }
194.2456 -
194.2457 - if (shouldDisplay) {
194.2458 - if (!isFirstRender) {
194.2459 - ko.virtualElements.setDomNodeChildren(element, ko.utils.cloneNodes(withIfData.savedNodes));
194.2460 - }
194.2461 - ko.applyBindingsToDescendants(makeContextCallback ? makeContextCallback(bindingContext, dataValue) : bindingContext, element);
194.2462 - } else {
194.2463 - ko.virtualElements.emptyNode(element);
194.2464 - }
194.2465 -
194.2466 - withIfData.didDisplayOnLastUpdate = shouldDisplay;
194.2467 - }
194.2468 - }
194.2469 - };
194.2470 - ko.expressionRewriting.bindingRewriteValidators[bindingKey] = false; // Can't rewrite control flow bindings
194.2471 - ko.virtualElements.allowedBindings[bindingKey] = true;
194.2472 -}
194.2473 -
194.2474 -// Construct the actual binding handlers
194.2475 -makeWithIfBinding('if');
194.2476 -makeWithIfBinding('ifnot', false /* isWith */, true /* isNot */);
194.2477 -makeWithIfBinding('with', true /* isWith */, false /* isNot */,
194.2478 - function(bindingContext, dataValue) {
194.2479 - return bindingContext['createChildContext'](dataValue);
194.2480 - }
194.2481 -);
194.2482 -function ensureDropdownSelectionIsConsistentWithModelValue(element, modelValue, preferModelValue) {
194.2483 - if (preferModelValue) {
194.2484 - if (modelValue !== ko.selectExtensions.readValue(element))
194.2485 - ko.selectExtensions.writeValue(element, modelValue);
194.2486 - }
194.2487 -
194.2488 - // No matter which direction we're syncing in, we want the end result to be equality between dropdown value and model value.
194.2489 - // If they aren't equal, either we prefer the dropdown value, or the model value couldn't be represented, so either way,
194.2490 - // change the model value to match the dropdown.
194.2491 - if (modelValue !== ko.selectExtensions.readValue(element))
194.2492 - ko.dependencyDetection.ignore(ko.utils.triggerEvent, null, [element, "change"]);
194.2493 -};
194.2494 -
194.2495 -ko.bindingHandlers['options'] = {
194.2496 - 'update': function (element, valueAccessor, allBindingsAccessor) {
194.2497 - if (ko.utils.tagNameLower(element) !== "select")
194.2498 - throw new Error("options binding applies only to SELECT elements");
194.2499 -
194.2500 - var selectWasPreviouslyEmpty = element.length == 0;
194.2501 - var previousSelectedValues = ko.utils.arrayMap(ko.utils.arrayFilter(element.childNodes, function (node) {
194.2502 - return node.tagName && (ko.utils.tagNameLower(node) === "option") && node.selected;
194.2503 - }), function (node) {
194.2504 - return ko.selectExtensions.readValue(node) || node.innerText || node.textContent;
194.2505 - });
194.2506 - var previousScrollTop = element.scrollTop;
194.2507 -
194.2508 - var value = ko.utils.unwrapObservable(valueAccessor());
194.2509 - var selectedValue = element.value;
194.2510 -
194.2511 - // Remove all existing <option>s.
194.2512 - // Need to use .remove() rather than .removeChild() for <option>s otherwise IE behaves oddly (https://github.com/SteveSanderson/knockout/issues/134)
194.2513 - while (element.length > 0) {
194.2514 - ko.cleanNode(element.options[0]);
194.2515 - element.remove(0);
194.2516 - }
194.2517 -
194.2518 - if (value) {
194.2519 - var allBindings = allBindingsAccessor(),
194.2520 - includeDestroyed = allBindings['optionsIncludeDestroyed'];
194.2521 -
194.2522 - if (typeof value.length != "number")
194.2523 - value = [value];
194.2524 - if (allBindings['optionsCaption']) {
194.2525 - var option = document.createElement("option");
194.2526 - ko.utils.setHtml(option, allBindings['optionsCaption']);
194.2527 - ko.selectExtensions.writeValue(option, undefined);
194.2528 - element.appendChild(option);
194.2529 - }
194.2530 -
194.2531 - for (var i = 0, j = value.length; i < j; i++) {
194.2532 - // Skip destroyed items
194.2533 - var arrayEntry = value[i];
194.2534 - if (arrayEntry && arrayEntry['_destroy'] && !includeDestroyed)
194.2535 - continue;
194.2536 -
194.2537 - var option = document.createElement("option");
194.2538 -
194.2539 - function applyToObject(object, predicate, defaultValue) {
194.2540 - var predicateType = typeof predicate;
194.2541 - if (predicateType == "function") // Given a function; run it against the data value
194.2542 - return predicate(object);
194.2543 - else if (predicateType == "string") // Given a string; treat it as a property name on the data value
194.2544 - return object[predicate];
194.2545 - else // Given no optionsText arg; use the data value itself
194.2546 - return defaultValue;
194.2547 - }
194.2548 -
194.2549 - // Apply a value to the option element
194.2550 - var optionValue = applyToObject(arrayEntry, allBindings['optionsValue'], arrayEntry);
194.2551 - ko.selectExtensions.writeValue(option, ko.utils.unwrapObservable(optionValue));
194.2552 -
194.2553 - // Apply some text to the option element
194.2554 - var optionText = applyToObject(arrayEntry, allBindings['optionsText'], optionValue);
194.2555 - ko.utils.setTextContent(option, optionText);
194.2556 -
194.2557 - element.appendChild(option);
194.2558 - }
194.2559 -
194.2560 - // IE6 doesn't like us to assign selection to OPTION nodes before they're added to the document.
194.2561 - // That's why we first added them without selection. Now it's time to set the selection.
194.2562 - var newOptions = element.getElementsByTagName("option");
194.2563 - var countSelectionsRetained = 0;
194.2564 - for (var i = 0, j = newOptions.length; i < j; i++) {
194.2565 - if (ko.utils.arrayIndexOf(previousSelectedValues, ko.selectExtensions.readValue(newOptions[i])) >= 0) {
194.2566 - ko.utils.setOptionNodeSelectionState(newOptions[i], true);
194.2567 - countSelectionsRetained++;
194.2568 - }
194.2569 - }
194.2570 -
194.2571 - element.scrollTop = previousScrollTop;
194.2572 -
194.2573 - if (selectWasPreviouslyEmpty && ('value' in allBindings)) {
194.2574 - // Ensure consistency between model value and selected option.
194.2575 - // If the dropdown is being populated for the first time here (or was otherwise previously empty),
194.2576 - // the dropdown selection state is meaningless, so we preserve the model value.
194.2577 - ensureDropdownSelectionIsConsistentWithModelValue(element, ko.utils.peekObservable(allBindings['value']), /* preferModelValue */ true);
194.2578 - }
194.2579 -
194.2580 - // Workaround for IE9 bug
194.2581 - ko.utils.ensureSelectElementIsRenderedCorrectly(element);
194.2582 - }
194.2583 - }
194.2584 -};
194.2585 -ko.bindingHandlers['options'].optionValueDomDataKey = '__ko.optionValueDomData__';
194.2586 -ko.bindingHandlers['selectedOptions'] = {
194.2587 - 'init': function (element, valueAccessor, allBindingsAccessor) {
194.2588 - ko.utils.registerEventHandler(element, "change", function () {
194.2589 - var value = valueAccessor(), valueToWrite = [];
194.2590 - ko.utils.arrayForEach(element.getElementsByTagName("option"), function(node) {
194.2591 - if (node.selected)
194.2592 - valueToWrite.push(ko.selectExtensions.readValue(node));
194.2593 - });
194.2594 - ko.expressionRewriting.writeValueToProperty(value, allBindingsAccessor, 'value', valueToWrite);
194.2595 - });
194.2596 - },
194.2597 - 'update': function (element, valueAccessor) {
194.2598 - if (ko.utils.tagNameLower(element) != "select")
194.2599 - throw new Error("values binding applies only to SELECT elements");
194.2600 -
194.2601 - var newValue = ko.utils.unwrapObservable(valueAccessor());
194.2602 - if (newValue && typeof newValue.length == "number") {
194.2603 - ko.utils.arrayForEach(element.getElementsByTagName("option"), function(node) {
194.2604 - var isSelected = ko.utils.arrayIndexOf(newValue, ko.selectExtensions.readValue(node)) >= 0;
194.2605 - ko.utils.setOptionNodeSelectionState(node, isSelected);
194.2606 - });
194.2607 - }
194.2608 - }
194.2609 -};
194.2610 -ko.bindingHandlers['style'] = {
194.2611 - 'update': function (element, valueAccessor) {
194.2612 - var value = ko.utils.unwrapObservable(valueAccessor() || {});
194.2613 - for (var styleName in value) {
194.2614 - if (typeof styleName == "string") {
194.2615 - var styleValue = ko.utils.unwrapObservable(value[styleName]);
194.2616 - element.style[styleName] = styleValue || ""; // Empty string removes the value, whereas null/undefined have no effect
194.2617 - }
194.2618 - }
194.2619 - }
194.2620 -};
194.2621 -ko.bindingHandlers['submit'] = {
194.2622 - 'init': function (element, valueAccessor, allBindingsAccessor, viewModel) {
194.2623 - if (typeof valueAccessor() != "function")
194.2624 - throw new Error("The value for a submit binding must be a function");
194.2625 - ko.utils.registerEventHandler(element, "submit", function (event) {
194.2626 - var handlerReturnValue;
194.2627 - var value = valueAccessor();
194.2628 - try { handlerReturnValue = value.call(viewModel, element); }
194.2629 - finally {
194.2630 - if (handlerReturnValue !== true) { // Normally we want to prevent default action. Developer can override this be explicitly returning true.
194.2631 - if (event.preventDefault)
194.2632 - event.preventDefault();
194.2633 - else
194.2634 - event.returnValue = false;
194.2635 - }
194.2636 - }
194.2637 - });
194.2638 - }
194.2639 -};
194.2640 -ko.bindingHandlers['text'] = {
194.2641 - 'update': function (element, valueAccessor) {
194.2642 - ko.utils.setTextContent(element, valueAccessor());
194.2643 - }
194.2644 -};
194.2645 -ko.virtualElements.allowedBindings['text'] = true;
194.2646 -ko.bindingHandlers['uniqueName'] = {
194.2647 - 'init': function (element, valueAccessor) {
194.2648 - if (valueAccessor()) {
194.2649 - var name = "ko_unique_" + (++ko.bindingHandlers['uniqueName'].currentIndex);
194.2650 - ko.utils.setElementName(element, name);
194.2651 - }
194.2652 - }
194.2653 -};
194.2654 -ko.bindingHandlers['uniqueName'].currentIndex = 0;
194.2655 -ko.bindingHandlers['value'] = {
194.2656 - 'init': function (element, valueAccessor, allBindingsAccessor) {
194.2657 - // Always catch "change" event; possibly other events too if asked
194.2658 - var eventsToCatch = ["change"];
194.2659 - var requestedEventsToCatch = allBindingsAccessor()["valueUpdate"];
194.2660 - var propertyChangedFired = false;
194.2661 - if (requestedEventsToCatch) {
194.2662 - if (typeof requestedEventsToCatch == "string") // Allow both individual event names, and arrays of event names
194.2663 - requestedEventsToCatch = [requestedEventsToCatch];
194.2664 - ko.utils.arrayPushAll(eventsToCatch, requestedEventsToCatch);
194.2665 - eventsToCatch = ko.utils.arrayGetDistinctValues(eventsToCatch);
194.2666 - }
194.2667 -
194.2668 - var valueUpdateHandler = function() {
194.2669 - propertyChangedFired = false;
194.2670 - var modelValue = valueAccessor();
194.2671 - var elementValue = ko.selectExtensions.readValue(element);
194.2672 - ko.expressionRewriting.writeValueToProperty(modelValue, allBindingsAccessor, 'value', elementValue);
194.2673 - }
194.2674 -
194.2675 - // Workaround for https://github.com/SteveSanderson/knockout/issues/122
194.2676 - // IE doesn't fire "change" events on textboxes if the user selects a value from its autocomplete list
194.2677 - var ieAutoCompleteHackNeeded = ko.utils.ieVersion && element.tagName.toLowerCase() == "input" && element.type == "text"
194.2678 - && element.autocomplete != "off" && (!element.form || element.form.autocomplete != "off");
194.2679 - if (ieAutoCompleteHackNeeded && ko.utils.arrayIndexOf(eventsToCatch, "propertychange") == -1) {
194.2680 - ko.utils.registerEventHandler(element, "propertychange", function () { propertyChangedFired = true });
194.2681 - ko.utils.registerEventHandler(element, "blur", function() {
194.2682 - if (propertyChangedFired) {
194.2683 - valueUpdateHandler();
194.2684 - }
194.2685 - });
194.2686 - }
194.2687 -
194.2688 - ko.utils.arrayForEach(eventsToCatch, function(eventName) {
194.2689 - // The syntax "after<eventname>" means "run the handler asynchronously after the event"
194.2690 - // This is useful, for example, to catch "keydown" events after the browser has updated the control
194.2691 - // (otherwise, ko.selectExtensions.readValue(this) will receive the control's value *before* the key event)
194.2692 - var handler = valueUpdateHandler;
194.2693 - if (ko.utils.stringStartsWith(eventName, "after")) {
194.2694 - handler = function() { setTimeout(valueUpdateHandler, 0) };
194.2695 - eventName = eventName.substring("after".length);
194.2696 - }
194.2697 - ko.utils.registerEventHandler(element, eventName, handler);
194.2698 - });
194.2699 - },
194.2700 - 'update': function (element, valueAccessor) {
194.2701 - var valueIsSelectOption = ko.utils.tagNameLower(element) === "select";
194.2702 - var newValue = ko.utils.unwrapObservable(valueAccessor());
194.2703 - var elementValue = ko.selectExtensions.readValue(element);
194.2704 - var valueHasChanged = (newValue != elementValue);
194.2705 -
194.2706 - // JavaScript's 0 == "" behavious is unfortunate here as it prevents writing 0 to an empty text box (loose equality suggests the values are the same).
194.2707 - // We don't want to do a strict equality comparison as that is more confusing for developers in certain cases, so we specifically special case 0 != "" here.
194.2708 - if ((newValue === 0) && (elementValue !== 0) && (elementValue !== "0"))
194.2709 - valueHasChanged = true;
194.2710 -
194.2711 - if (valueHasChanged) {
194.2712 - var applyValueAction = function () { ko.selectExtensions.writeValue(element, newValue); };
194.2713 - applyValueAction();
194.2714 -
194.2715 - // Workaround for IE6 bug: It won't reliably apply values to SELECT nodes during the same execution thread
194.2716 - // right after you've changed the set of OPTION nodes on it. So for that node type, we'll schedule a second thread
194.2717 - // to apply the value as well.
194.2718 - var alsoApplyAsynchronously = valueIsSelectOption;
194.2719 - if (alsoApplyAsynchronously)
194.2720 - setTimeout(applyValueAction, 0);
194.2721 - }
194.2722 -
194.2723 - // If you try to set a model value that can't be represented in an already-populated dropdown, reject that change,
194.2724 - // because you're not allowed to have a model value that disagrees with a visible UI selection.
194.2725 - if (valueIsSelectOption && (element.length > 0))
194.2726 - ensureDropdownSelectionIsConsistentWithModelValue(element, newValue, /* preferModelValue */ false);
194.2727 - }
194.2728 -};
194.2729 -ko.bindingHandlers['visible'] = {
194.2730 - 'update': function (element, valueAccessor) {
194.2731 - var value = ko.utils.unwrapObservable(valueAccessor());
194.2732 - var isCurrentlyVisible = !(element.style.display == "none");
194.2733 - if (value && !isCurrentlyVisible)
194.2734 - element.style.display = "";
194.2735 - else if ((!value) && isCurrentlyVisible)
194.2736 - element.style.display = "none";
194.2737 - }
194.2738 -};
194.2739 -// 'click' is just a shorthand for the usual full-length event:{click:handler}
194.2740 -makeEventHandlerShortcut('click');
194.2741 -// If you want to make a custom template engine,
194.2742 -//
194.2743 -// [1] Inherit from this class (like ko.nativeTemplateEngine does)
194.2744 -// [2] Override 'renderTemplateSource', supplying a function with this signature:
194.2745 -//
194.2746 -// function (templateSource, bindingContext, options) {
194.2747 -// // - templateSource.text() is the text of the template you should render
194.2748 -// // - bindingContext.$data is the data you should pass into the template
194.2749 -// // - you might also want to make bindingContext.$parent, bindingContext.$parents,
194.2750 -// // and bindingContext.$root available in the template too
194.2751 -// // - options gives you access to any other properties set on "data-bind: { template: options }"
194.2752 -// //
194.2753 -// // Return value: an array of DOM nodes
194.2754 -// }
194.2755 -//
194.2756 -// [3] Override 'createJavaScriptEvaluatorBlock', supplying a function with this signature:
194.2757 -//
194.2758 -// function (script) {
194.2759 -// // Return value: Whatever syntax means "Evaluate the JavaScript statement 'script' and output the result"
194.2760 -// // For example, the jquery.tmpl template engine converts 'someScript' to '${ someScript }'
194.2761 -// }
194.2762 -//
194.2763 -// This is only necessary if you want to allow data-bind attributes to reference arbitrary template variables.
194.2764 -// If you don't want to allow that, you can set the property 'allowTemplateRewriting' to false (like ko.nativeTemplateEngine does)
194.2765 -// and then you don't need to override 'createJavaScriptEvaluatorBlock'.
194.2766 -
194.2767 -ko.templateEngine = function () { };
194.2768 -
194.2769 -ko.templateEngine.prototype['renderTemplateSource'] = function (templateSource, bindingContext, options) {
194.2770 - throw new Error("Override renderTemplateSource");
194.2771 -};
194.2772 -
194.2773 -ko.templateEngine.prototype['createJavaScriptEvaluatorBlock'] = function (script) {
194.2774 - throw new Error("Override createJavaScriptEvaluatorBlock");
194.2775 -};
194.2776 -
194.2777 -ko.templateEngine.prototype['makeTemplateSource'] = function(template, templateDocument) {
194.2778 - // Named template
194.2779 - if (typeof template == "string") {
194.2780 - templateDocument = templateDocument || document;
194.2781 - var elem = templateDocument.getElementById(template);
194.2782 - if (!elem)
194.2783 - throw new Error("Cannot find template with ID " + template);
194.2784 - return new ko.templateSources.domElement(elem);
194.2785 - } else if ((template.nodeType == 1) || (template.nodeType == 8)) {
194.2786 - // Anonymous template
194.2787 - return new ko.templateSources.anonymousTemplate(template);
194.2788 - } else
194.2789 - throw new Error("Unknown template type: " + template);
194.2790 -};
194.2791 -
194.2792 -ko.templateEngine.prototype['renderTemplate'] = function (template, bindingContext, options, templateDocument) {
194.2793 - var templateSource = this['makeTemplateSource'](template, templateDocument);
194.2794 - return this['renderTemplateSource'](templateSource, bindingContext, options);
194.2795 -};
194.2796 -
194.2797 -ko.templateEngine.prototype['isTemplateRewritten'] = function (template, templateDocument) {
194.2798 - // Skip rewriting if requested
194.2799 - if (this['allowTemplateRewriting'] === false)
194.2800 - return true;
194.2801 - return this['makeTemplateSource'](template, templateDocument)['data']("isRewritten");
194.2802 -};
194.2803 -
194.2804 -ko.templateEngine.prototype['rewriteTemplate'] = function (template, rewriterCallback, templateDocument) {
194.2805 - var templateSource = this['makeTemplateSource'](template, templateDocument);
194.2806 - var rewritten = rewriterCallback(templateSource['text']());
194.2807 - templateSource['text'](rewritten);
194.2808 - templateSource['data']("isRewritten", true);
194.2809 -};
194.2810 -
194.2811 -ko.exportSymbol('templateEngine', ko.templateEngine);
194.2812 -
194.2813 -ko.templateRewriting = (function () {
194.2814 - var memoizeDataBindingAttributeSyntaxRegex = /(<[a-z]+\d*(\s+(?!data-bind=)[a-z0-9\-]+(=(\"[^\"]*\"|\'[^\']*\'))?)*\s+)data-bind=(["'])([\s\S]*?)\5/gi;
194.2815 - var memoizeVirtualContainerBindingSyntaxRegex = /<!--\s*ko\b\s*([\s\S]*?)\s*-->/g;
194.2816 -
194.2817 - function validateDataBindValuesForRewriting(keyValueArray) {
194.2818 - var allValidators = ko.expressionRewriting.bindingRewriteValidators;
194.2819 - for (var i = 0; i < keyValueArray.length; i++) {
194.2820 - var key = keyValueArray[i]['key'];
194.2821 - if (allValidators.hasOwnProperty(key)) {
194.2822 - var validator = allValidators[key];
194.2823 -
194.2824 - if (typeof validator === "function") {
194.2825 - var possibleErrorMessage = validator(keyValueArray[i]['value']);
194.2826 - if (possibleErrorMessage)
194.2827 - throw new Error(possibleErrorMessage);
194.2828 - } else if (!validator) {
194.2829 - throw new Error("This template engine does not support the '" + key + "' binding within its templates");
194.2830 - }
194.2831 - }
194.2832 - }
194.2833 - }
194.2834 -
194.2835 - function constructMemoizedTagReplacement(dataBindAttributeValue, tagToRetain, templateEngine) {
194.2836 - var dataBindKeyValueArray = ko.expressionRewriting.parseObjectLiteral(dataBindAttributeValue);
194.2837 - validateDataBindValuesForRewriting(dataBindKeyValueArray);
194.2838 - var rewrittenDataBindAttributeValue = ko.expressionRewriting.preProcessBindings(dataBindKeyValueArray);
194.2839 -
194.2840 - // For no obvious reason, Opera fails to evaluate rewrittenDataBindAttributeValue unless it's wrapped in an additional
194.2841 - // anonymous function, even though Opera's built-in debugger can evaluate it anyway. No other browser requires this
194.2842 - // extra indirection.
194.2843 - var applyBindingsToNextSiblingScript =
194.2844 - "ko.__tr_ambtns(function($context,$element){return(function(){return{ " + rewrittenDataBindAttributeValue + " } })()})";
194.2845 - return templateEngine['createJavaScriptEvaluatorBlock'](applyBindingsToNextSiblingScript) + tagToRetain;
194.2846 - }
194.2847 -
194.2848 - return {
194.2849 - ensureTemplateIsRewritten: function (template, templateEngine, templateDocument) {
194.2850 - if (!templateEngine['isTemplateRewritten'](template, templateDocument))
194.2851 - templateEngine['rewriteTemplate'](template, function (htmlString) {
194.2852 - return ko.templateRewriting.memoizeBindingAttributeSyntax(htmlString, templateEngine);
194.2853 - }, templateDocument);
194.2854 - },
194.2855 -
194.2856 - memoizeBindingAttributeSyntax: function (htmlString, templateEngine) {
194.2857 - return htmlString.replace(memoizeDataBindingAttributeSyntaxRegex, function () {
194.2858 - return constructMemoizedTagReplacement(/* dataBindAttributeValue: */ arguments[6], /* tagToRetain: */ arguments[1], templateEngine);
194.2859 - }).replace(memoizeVirtualContainerBindingSyntaxRegex, function() {
194.2860 - return constructMemoizedTagReplacement(/* dataBindAttributeValue: */ arguments[1], /* tagToRetain: */ "<!-- ko -->", templateEngine);
194.2861 - });
194.2862 - },
194.2863 -
194.2864 - applyMemoizedBindingsToNextSibling: function (bindings) {
194.2865 - return ko.memoization.memoize(function (domNode, bindingContext) {
194.2866 - if (domNode.nextSibling)
194.2867 - ko.applyBindingsToNode(domNode.nextSibling, bindings, bindingContext);
194.2868 - });
194.2869 - }
194.2870 - }
194.2871 -})();
194.2872 -
194.2873 -
194.2874 -// Exported only because it has to be referenced by string lookup from within rewritten template
194.2875 -ko.exportSymbol('__tr_ambtns', ko.templateRewriting.applyMemoizedBindingsToNextSibling);
194.2876 -(function() {
194.2877 - // A template source represents a read/write way of accessing a template. This is to eliminate the need for template loading/saving
194.2878 - // logic to be duplicated in every template engine (and means they can all work with anonymous templates, etc.)
194.2879 - //
194.2880 - // Two are provided by default:
194.2881 - // 1. ko.templateSources.domElement - reads/writes the text content of an arbitrary DOM element
194.2882 - // 2. ko.templateSources.anonymousElement - uses ko.utils.domData to read/write text *associated* with the DOM element, but
194.2883 - // without reading/writing the actual element text content, since it will be overwritten
194.2884 - // with the rendered template output.
194.2885 - // You can implement your own template source if you want to fetch/store templates somewhere other than in DOM elements.
194.2886 - // Template sources need to have the following functions:
194.2887 - // text() - returns the template text from your storage location
194.2888 - // text(value) - writes the supplied template text to your storage location
194.2889 - // data(key) - reads values stored using data(key, value) - see below
194.2890 - // data(key, value) - associates "value" with this template and the key "key". Is used to store information like "isRewritten".
194.2891 - //
194.2892 - // Optionally, template sources can also have the following functions:
194.2893 - // nodes() - returns a DOM element containing the nodes of this template, where available
194.2894 - // nodes(value) - writes the given DOM element to your storage location
194.2895 - // If a DOM element is available for a given template source, template engines are encouraged to use it in preference over text()
194.2896 - // for improved speed. However, all templateSources must supply text() even if they don't supply nodes().
194.2897 - //
194.2898 - // Once you've implemented a templateSource, make your template engine use it by subclassing whatever template engine you were
194.2899 - // using and overriding "makeTemplateSource" to return an instance of your custom template source.
194.2900 -
194.2901 - ko.templateSources = {};
194.2902 -
194.2903 - // ---- ko.templateSources.domElement -----
194.2904 -
194.2905 - ko.templateSources.domElement = function(element) {
194.2906 - this.domElement = element;
194.2907 - }
194.2908 -
194.2909 - ko.templateSources.domElement.prototype['text'] = function(/* valueToWrite */) {
194.2910 - var tagNameLower = ko.utils.tagNameLower(this.domElement),
194.2911 - elemContentsProperty = tagNameLower === "script" ? "text"
194.2912 - : tagNameLower === "textarea" ? "value"
194.2913 - : "innerHTML";
194.2914 -
194.2915 - if (arguments.length == 0) {
194.2916 - return this.domElement[elemContentsProperty];
194.2917 - } else {
194.2918 - var valueToWrite = arguments[0];
194.2919 - if (elemContentsProperty === "innerHTML")
194.2920 - ko.utils.setHtml(this.domElement, valueToWrite);
194.2921 - else
194.2922 - this.domElement[elemContentsProperty] = valueToWrite;
194.2923 - }
194.2924 - };
194.2925 -
194.2926 - ko.templateSources.domElement.prototype['data'] = function(key /*, valueToWrite */) {
194.2927 - if (arguments.length === 1) {
194.2928 - return ko.utils.domData.get(this.domElement, "templateSourceData_" + key);
194.2929 - } else {
194.2930 - ko.utils.domData.set(this.domElement, "templateSourceData_" + key, arguments[1]);
194.2931 - }
194.2932 - };
194.2933 -
194.2934 - // ---- ko.templateSources.anonymousTemplate -----
194.2935 - // Anonymous templates are normally saved/retrieved as DOM nodes through "nodes".
194.2936 - // For compatibility, you can also read "text"; it will be serialized from the nodes on demand.
194.2937 - // Writing to "text" is still supported, but then the template data will not be available as DOM nodes.
194.2938 -
194.2939 - var anonymousTemplatesDomDataKey = "__ko_anon_template__";
194.2940 - ko.templateSources.anonymousTemplate = function(element) {
194.2941 - this.domElement = element;
194.2942 - }
194.2943 - ko.templateSources.anonymousTemplate.prototype = new ko.templateSources.domElement();
194.2944 - ko.templateSources.anonymousTemplate.prototype['text'] = function(/* valueToWrite */) {
194.2945 - if (arguments.length == 0) {
194.2946 - var templateData = ko.utils.domData.get(this.domElement, anonymousTemplatesDomDataKey) || {};
194.2947 - if (templateData.textData === undefined && templateData.containerData)
194.2948 - templateData.textData = templateData.containerData.innerHTML;
194.2949 - return templateData.textData;
194.2950 - } else {
194.2951 - var valueToWrite = arguments[0];
194.2952 - ko.utils.domData.set(this.domElement, anonymousTemplatesDomDataKey, {textData: valueToWrite});
194.2953 - }
194.2954 - };
194.2955 - ko.templateSources.domElement.prototype['nodes'] = function(/* valueToWrite */) {
194.2956 - if (arguments.length == 0) {
194.2957 - var templateData = ko.utils.domData.get(this.domElement, anonymousTemplatesDomDataKey) || {};
194.2958 - return templateData.containerData;
194.2959 - } else {
194.2960 - var valueToWrite = arguments[0];
194.2961 - ko.utils.domData.set(this.domElement, anonymousTemplatesDomDataKey, {containerData: valueToWrite});
194.2962 - }
194.2963 - };
194.2964 -
194.2965 - ko.exportSymbol('templateSources', ko.templateSources);
194.2966 - ko.exportSymbol('templateSources.domElement', ko.templateSources.domElement);
194.2967 - ko.exportSymbol('templateSources.anonymousTemplate', ko.templateSources.anonymousTemplate);
194.2968 -})();
194.2969 -(function () {
194.2970 - var _templateEngine;
194.2971 - ko.setTemplateEngine = function (templateEngine) {
194.2972 - if ((templateEngine != undefined) && !(templateEngine instanceof ko.templateEngine))
194.2973 - throw new Error("templateEngine must inherit from ko.templateEngine");
194.2974 - _templateEngine = templateEngine;
194.2975 - }
194.2976 -
194.2977 - function invokeForEachNodeOrCommentInContinuousRange(firstNode, lastNode, action) {
194.2978 - var node, nextInQueue = firstNode, firstOutOfRangeNode = ko.virtualElements.nextSibling(lastNode);
194.2979 - while (nextInQueue && ((node = nextInQueue) !== firstOutOfRangeNode)) {
194.2980 - nextInQueue = ko.virtualElements.nextSibling(node);
194.2981 - if (node.nodeType === 1 || node.nodeType === 8)
194.2982 - action(node);
194.2983 - }
194.2984 - }
194.2985 -
194.2986 - function activateBindingsOnContinuousNodeArray(continuousNodeArray, bindingContext) {
194.2987 - // To be used on any nodes that have been rendered by a template and have been inserted into some parent element
194.2988 - // Walks through continuousNodeArray (which *must* be continuous, i.e., an uninterrupted sequence of sibling nodes, because
194.2989 - // the algorithm for walking them relies on this), and for each top-level item in the virtual-element sense,
194.2990 - // (1) Does a regular "applyBindings" to associate bindingContext with this node and to activate any non-memoized bindings
194.2991 - // (2) Unmemoizes any memos in the DOM subtree (e.g., to activate bindings that had been memoized during template rewriting)
194.2992 -
194.2993 - if (continuousNodeArray.length) {
194.2994 - var firstNode = continuousNodeArray[0], lastNode = continuousNodeArray[continuousNodeArray.length - 1];
194.2995 -
194.2996 - // Need to applyBindings *before* unmemoziation, because unmemoization might introduce extra nodes (that we don't want to re-bind)
194.2997 - // whereas a regular applyBindings won't introduce new memoized nodes
194.2998 - invokeForEachNodeOrCommentInContinuousRange(firstNode, lastNode, function(node) {
194.2999 - ko.applyBindings(bindingContext, node);
194.3000 - });
194.3001 - invokeForEachNodeOrCommentInContinuousRange(firstNode, lastNode, function(node) {
194.3002 - ko.memoization.unmemoizeDomNodeAndDescendants(node, [bindingContext]);
194.3003 - });
194.3004 - }
194.3005 - }
194.3006 -
194.3007 - function getFirstNodeFromPossibleArray(nodeOrNodeArray) {
194.3008 - return nodeOrNodeArray.nodeType ? nodeOrNodeArray
194.3009 - : nodeOrNodeArray.length > 0 ? nodeOrNodeArray[0]
194.3010 - : null;
194.3011 - }
194.3012 -
194.3013 - function executeTemplate(targetNodeOrNodeArray, renderMode, template, bindingContext, options) {
194.3014 - options = options || {};
194.3015 - var firstTargetNode = targetNodeOrNodeArray && getFirstNodeFromPossibleArray(targetNodeOrNodeArray);
194.3016 - var templateDocument = firstTargetNode && firstTargetNode.ownerDocument;
194.3017 - var templateEngineToUse = (options['templateEngine'] || _templateEngine);
194.3018 - ko.templateRewriting.ensureTemplateIsRewritten(template, templateEngineToUse, templateDocument);
194.3019 - var renderedNodesArray = templateEngineToUse['renderTemplate'](template, bindingContext, options, templateDocument);
194.3020 -
194.3021 - // Loosely check result is an array of DOM nodes
194.3022 - if ((typeof renderedNodesArray.length != "number") || (renderedNodesArray.length > 0 && typeof renderedNodesArray[0].nodeType != "number"))
194.3023 - throw new Error("Template engine must return an array of DOM nodes");
194.3024 -
194.3025 - var haveAddedNodesToParent = false;
194.3026 - switch (renderMode) {
194.3027 - case "replaceChildren":
194.3028 - ko.virtualElements.setDomNodeChildren(targetNodeOrNodeArray, renderedNodesArray);
194.3029 - haveAddedNodesToParent = true;
194.3030 - break;
194.3031 - case "replaceNode":
194.3032 - ko.utils.replaceDomNodes(targetNodeOrNodeArray, renderedNodesArray);
194.3033 - haveAddedNodesToParent = true;
194.3034 - break;
194.3035 - case "ignoreTargetNode": break;
194.3036 - default:
194.3037 - throw new Error("Unknown renderMode: " + renderMode);
194.3038 - }
194.3039 -
194.3040 - if (haveAddedNodesToParent) {
194.3041 - activateBindingsOnContinuousNodeArray(renderedNodesArray, bindingContext);
194.3042 - if (options['afterRender'])
194.3043 - ko.dependencyDetection.ignore(options['afterRender'], null, [renderedNodesArray, bindingContext['$data']]);
194.3044 - }
194.3045 -
194.3046 - return renderedNodesArray;
194.3047 - }
194.3048 -
194.3049 - ko.renderTemplate = function (template, dataOrBindingContext, options, targetNodeOrNodeArray, renderMode) {
194.3050 - options = options || {};
194.3051 - if ((options['templateEngine'] || _templateEngine) == undefined)
194.3052 - throw new Error("Set a template engine before calling renderTemplate");
194.3053 - renderMode = renderMode || "replaceChildren";
194.3054 -
194.3055 - if (targetNodeOrNodeArray) {
194.3056 - var firstTargetNode = getFirstNodeFromPossibleArray(targetNodeOrNodeArray);
194.3057 -
194.3058 - var whenToDispose = function () { return (!firstTargetNode) || !ko.utils.domNodeIsAttachedToDocument(firstTargetNode); }; // Passive disposal (on next evaluation)
194.3059 - var activelyDisposeWhenNodeIsRemoved = (firstTargetNode && renderMode == "replaceNode") ? firstTargetNode.parentNode : firstTargetNode;
194.3060 -
194.3061 - return ko.dependentObservable( // So the DOM is automatically updated when any dependency changes
194.3062 - function () {
194.3063 - // Ensure we've got a proper binding context to work with
194.3064 - var bindingContext = (dataOrBindingContext && (dataOrBindingContext instanceof ko.bindingContext))
194.3065 - ? dataOrBindingContext
194.3066 - : new ko.bindingContext(ko.utils.unwrapObservable(dataOrBindingContext));
194.3067 -
194.3068 - // Support selecting template as a function of the data being rendered
194.3069 - var templateName = typeof(template) == 'function' ? template(bindingContext['$data'], bindingContext) : template;
194.3070 -
194.3071 - var renderedNodesArray = executeTemplate(targetNodeOrNodeArray, renderMode, templateName, bindingContext, options);
194.3072 - if (renderMode == "replaceNode") {
194.3073 - targetNodeOrNodeArray = renderedNodesArray;
194.3074 - firstTargetNode = getFirstNodeFromPossibleArray(targetNodeOrNodeArray);
194.3075 - }
194.3076 - },
194.3077 - null,
194.3078 - { disposeWhen: whenToDispose, disposeWhenNodeIsRemoved: activelyDisposeWhenNodeIsRemoved }
194.3079 - );
194.3080 - } else {
194.3081 - // We don't yet have a DOM node to evaluate, so use a memo and render the template later when there is a DOM node
194.3082 - return ko.memoization.memoize(function (domNode) {
194.3083 - ko.renderTemplate(template, dataOrBindingContext, options, domNode, "replaceNode");
194.3084 - });
194.3085 - }
194.3086 - };
194.3087 -
194.3088 - ko.renderTemplateForEach = function (template, arrayOrObservableArray, options, targetNode, parentBindingContext) {
194.3089 - // Since setDomNodeChildrenFromArrayMapping always calls executeTemplateForArrayItem and then
194.3090 - // activateBindingsCallback for added items, we can store the binding context in the former to use in the latter.
194.3091 - var arrayItemContext;
194.3092 -
194.3093 - // This will be called by setDomNodeChildrenFromArrayMapping to get the nodes to add to targetNode
194.3094 - var executeTemplateForArrayItem = function (arrayValue, index) {
194.3095 - // Support selecting template as a function of the data being rendered
194.3096 - arrayItemContext = parentBindingContext['createChildContext'](ko.utils.unwrapObservable(arrayValue), options['as']);
194.3097 - arrayItemContext['$index'] = index;
194.3098 - var templateName = typeof(template) == 'function' ? template(arrayValue, arrayItemContext) : template;
194.3099 - return executeTemplate(null, "ignoreTargetNode", templateName, arrayItemContext, options);
194.3100 - }
194.3101 -
194.3102 - // This will be called whenever setDomNodeChildrenFromArrayMapping has added nodes to targetNode
194.3103 - var activateBindingsCallback = function(arrayValue, addedNodesArray, index) {
194.3104 - activateBindingsOnContinuousNodeArray(addedNodesArray, arrayItemContext);
194.3105 - if (options['afterRender'])
194.3106 - options['afterRender'](addedNodesArray, arrayValue);
194.3107 - };
194.3108 -
194.3109 - return ko.dependentObservable(function () {
194.3110 - var unwrappedArray = ko.utils.unwrapObservable(arrayOrObservableArray) || [];
194.3111 - if (typeof unwrappedArray.length == "undefined") // Coerce single value into array
194.3112 - unwrappedArray = [unwrappedArray];
194.3113 -
194.3114 - // Filter out any entries marked as destroyed
194.3115 - var filteredArray = ko.utils.arrayFilter(unwrappedArray, function(item) {
194.3116 - return options['includeDestroyed'] || item === undefined || item === null || !ko.utils.unwrapObservable(item['_destroy']);
194.3117 - });
194.3118 -
194.3119 - // Call setDomNodeChildrenFromArrayMapping, ignoring any observables unwrapped within (most likely from a callback function).
194.3120 - // If the array items are observables, though, they will be unwrapped in executeTemplateForArrayItem and managed within setDomNodeChildrenFromArrayMapping.
194.3121 - ko.dependencyDetection.ignore(ko.utils.setDomNodeChildrenFromArrayMapping, null, [targetNode, filteredArray, executeTemplateForArrayItem, options, activateBindingsCallback]);
194.3122 -
194.3123 - }, null, { disposeWhenNodeIsRemoved: targetNode });
194.3124 - };
194.3125 -
194.3126 - var templateComputedDomDataKey = '__ko__templateComputedDomDataKey__';
194.3127 - function disposeOldComputedAndStoreNewOne(element, newComputed) {
194.3128 - var oldComputed = ko.utils.domData.get(element, templateComputedDomDataKey);
194.3129 - if (oldComputed && (typeof(oldComputed.dispose) == 'function'))
194.3130 - oldComputed.dispose();
194.3131 - ko.utils.domData.set(element, templateComputedDomDataKey, (newComputed && newComputed.isActive()) ? newComputed : undefined);
194.3132 - }
194.3133 -
194.3134 - ko.bindingHandlers['template'] = {
194.3135 - 'init': function(element, valueAccessor) {
194.3136 - // Support anonymous templates
194.3137 - var bindingValue = ko.utils.unwrapObservable(valueAccessor());
194.3138 - if ((typeof bindingValue != "string") && (!bindingValue['name']) && (element.nodeType == 1 || element.nodeType == 8)) {
194.3139 - // It's an anonymous template - store the element contents, then clear the element
194.3140 - var templateNodes = element.nodeType == 1 ? element.childNodes : ko.virtualElements.childNodes(element),
194.3141 - container = ko.utils.moveCleanedNodesToContainerElement(templateNodes); // This also removes the nodes from their current parent
194.3142 - new ko.templateSources.anonymousTemplate(element)['nodes'](container);
194.3143 - }
194.3144 - return { 'controlsDescendantBindings': true };
194.3145 - },
194.3146 - 'update': function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
194.3147 - var templateName = ko.utils.unwrapObservable(valueAccessor()),
194.3148 - options = {},
194.3149 - shouldDisplay = true,
194.3150 - dataValue,
194.3151 - templateComputed = null;
194.3152 -
194.3153 - if (typeof templateName != "string") {
194.3154 - options = templateName;
194.3155 - templateName = options['name'];
194.3156 -
194.3157 - // Support "if"/"ifnot" conditions
194.3158 - if ('if' in options)
194.3159 - shouldDisplay = ko.utils.unwrapObservable(options['if']);
194.3160 - if (shouldDisplay && 'ifnot' in options)
194.3161 - shouldDisplay = !ko.utils.unwrapObservable(options['ifnot']);
194.3162 -
194.3163 - dataValue = ko.utils.unwrapObservable(options['data']);
194.3164 - }
194.3165 -
194.3166 - if ('foreach' in options) {
194.3167 - // Render once for each data point (treating data set as empty if shouldDisplay==false)
194.3168 - var dataArray = (shouldDisplay && options['foreach']) || [];
194.3169 - templateComputed = ko.renderTemplateForEach(templateName || element, dataArray, options, element, bindingContext);
194.3170 - } else if (!shouldDisplay) {
194.3171 - ko.virtualElements.emptyNode(element);
194.3172 - } else {
194.3173 - // Render once for this single data point (or use the viewModel if no data was provided)
194.3174 - var innerBindingContext = ('data' in options) ?
194.3175 - bindingContext['createChildContext'](dataValue, options['as']) : // Given an explitit 'data' value, we create a child binding context for it
194.3176 - bindingContext; // Given no explicit 'data' value, we retain the same binding context
194.3177 - templateComputed = ko.renderTemplate(templateName || element, innerBindingContext, options, element);
194.3178 - }
194.3179 -
194.3180 - // It only makes sense to have a single template computed per element (otherwise which one should have its output displayed?)
194.3181 - disposeOldComputedAndStoreNewOne(element, templateComputed);
194.3182 - }
194.3183 - };
194.3184 -
194.3185 - // Anonymous templates can't be rewritten. Give a nice error message if you try to do it.
194.3186 - ko.expressionRewriting.bindingRewriteValidators['template'] = function(bindingValue) {
194.3187 - var parsedBindingValue = ko.expressionRewriting.parseObjectLiteral(bindingValue);
194.3188 -
194.3189 - if ((parsedBindingValue.length == 1) && parsedBindingValue[0]['unknown'])
194.3190 - return null; // It looks like a string literal, not an object literal, so treat it as a named template (which is allowed for rewriting)
194.3191 -
194.3192 - if (ko.expressionRewriting.keyValueArrayContainsKey(parsedBindingValue, "name"))
194.3193 - return null; // Named templates can be rewritten, so return "no error"
194.3194 - return "This template engine does not support anonymous templates nested within its templates";
194.3195 - };
194.3196 -
194.3197 - ko.virtualElements.allowedBindings['template'] = true;
194.3198 -})();
194.3199 -
194.3200 -ko.exportSymbol('setTemplateEngine', ko.setTemplateEngine);
194.3201 -ko.exportSymbol('renderTemplate', ko.renderTemplate);
194.3202 -
194.3203 -ko.utils.compareArrays = (function () {
194.3204 - var statusNotInOld = 'added', statusNotInNew = 'deleted';
194.3205 -
194.3206 - // Simple calculation based on Levenshtein distance.
194.3207 - function compareArrays(oldArray, newArray, dontLimitMoves) {
194.3208 - oldArray = oldArray || [];
194.3209 - newArray = newArray || [];
194.3210 -
194.3211 - if (oldArray.length <= newArray.length)
194.3212 - return compareSmallArrayToBigArray(oldArray, newArray, statusNotInOld, statusNotInNew, dontLimitMoves);
194.3213 - else
194.3214 - return compareSmallArrayToBigArray(newArray, oldArray, statusNotInNew, statusNotInOld, dontLimitMoves);
194.3215 - }
194.3216 -
194.3217 - function compareSmallArrayToBigArray(smlArray, bigArray, statusNotInSml, statusNotInBig, dontLimitMoves) {
194.3218 - var myMin = Math.min,
194.3219 - myMax = Math.max,
194.3220 - editDistanceMatrix = [],
194.3221 - smlIndex, smlIndexMax = smlArray.length,
194.3222 - bigIndex, bigIndexMax = bigArray.length,
194.3223 - compareRange = (bigIndexMax - smlIndexMax) || 1,
194.3224 - maxDistance = smlIndexMax + bigIndexMax + 1,
194.3225 - thisRow, lastRow,
194.3226 - bigIndexMaxForRow, bigIndexMinForRow;
194.3227 -
194.3228 - for (smlIndex = 0; smlIndex <= smlIndexMax; smlIndex++) {
194.3229 - lastRow = thisRow;
194.3230 - editDistanceMatrix.push(thisRow = []);
194.3231 - bigIndexMaxForRow = myMin(bigIndexMax, smlIndex + compareRange);
194.3232 - bigIndexMinForRow = myMax(0, smlIndex - 1);
194.3233 - for (bigIndex = bigIndexMinForRow; bigIndex <= bigIndexMaxForRow; bigIndex++) {
194.3234 - if (!bigIndex)
194.3235 - thisRow[bigIndex] = smlIndex + 1;
194.3236 - else if (!smlIndex) // Top row - transform empty array into new array via additions
194.3237 - thisRow[bigIndex] = bigIndex + 1;
194.3238 - else if (smlArray[smlIndex - 1] === bigArray[bigIndex - 1])
194.3239 - thisRow[bigIndex] = lastRow[bigIndex - 1]; // copy value (no edit)
194.3240 - else {
194.3241 - var northDistance = lastRow[bigIndex] || maxDistance; // not in big (deletion)
194.3242 - var westDistance = thisRow[bigIndex - 1] || maxDistance; // not in small (addition)
194.3243 - thisRow[bigIndex] = myMin(northDistance, westDistance) + 1;
194.3244 - }
194.3245 - }
194.3246 - }
194.3247 -
194.3248 - var editScript = [], meMinusOne, notInSml = [], notInBig = [];
194.3249 - for (smlIndex = smlIndexMax, bigIndex = bigIndexMax; smlIndex || bigIndex;) {
194.3250 - meMinusOne = editDistanceMatrix[smlIndex][bigIndex] - 1;
194.3251 - if (bigIndex && meMinusOne === editDistanceMatrix[smlIndex][bigIndex-1]) {
194.3252 - notInSml.push(editScript[editScript.length] = { // added
194.3253 - 'status': statusNotInSml,
194.3254 - 'value': bigArray[--bigIndex],
194.3255 - 'index': bigIndex });
194.3256 - } else if (smlIndex && meMinusOne === editDistanceMatrix[smlIndex - 1][bigIndex]) {
194.3257 - notInBig.push(editScript[editScript.length] = { // deleted
194.3258 - 'status': statusNotInBig,
194.3259 - 'value': smlArray[--smlIndex],
194.3260 - 'index': smlIndex });
194.3261 - } else {
194.3262 - editScript.push({
194.3263 - 'status': "retained",
194.3264 - 'value': bigArray[--bigIndex] });
194.3265 - --smlIndex;
194.3266 - }
194.3267 - }
194.3268 -
194.3269 - if (notInSml.length && notInBig.length) {
194.3270 - // Set a limit on the number of consecutive non-matching comparisons; having it a multiple of
194.3271 - // smlIndexMax keeps the time complexity of this algorithm linear.
194.3272 - var limitFailedCompares = smlIndexMax * 10, failedCompares,
194.3273 - a, d, notInSmlItem, notInBigItem;
194.3274 - // Go through the items that have been added and deleted and try to find matches between them.
194.3275 - for (failedCompares = a = 0; (dontLimitMoves || failedCompares < limitFailedCompares) && (notInSmlItem = notInSml[a]); a++) {
194.3276 - for (d = 0; notInBigItem = notInBig[d]; d++) {
194.3277 - if (notInSmlItem['value'] === notInBigItem['value']) {
194.3278 - notInSmlItem['moved'] = notInBigItem['index'];
194.3279 - notInBigItem['moved'] = notInSmlItem['index'];
194.3280 - notInBig.splice(d,1); // This item is marked as moved; so remove it from notInBig list
194.3281 - failedCompares = d = 0; // Reset failed compares count because we're checking for consecutive failures
194.3282 - break;
194.3283 - }
194.3284 - }
194.3285 - failedCompares += d;
194.3286 - }
194.3287 - }
194.3288 - return editScript.reverse();
194.3289 - }
194.3290 -
194.3291 - return compareArrays;
194.3292 -})();
194.3293 -
194.3294 -ko.exportSymbol('utils.compareArrays', ko.utils.compareArrays);
194.3295 -
194.3296 -(function () {
194.3297 - // Objective:
194.3298 - // * Given an input array, a container DOM node, and a function from array elements to arrays of DOM nodes,
194.3299 - // map the array elements to arrays of DOM nodes, concatenate together all these arrays, and use them to populate the container DOM node
194.3300 - // * Next time we're given the same combination of things (with the array possibly having mutated), update the container DOM node
194.3301 - // so that its children is again the concatenation of the mappings of the array elements, but don't re-map any array elements that we
194.3302 - // previously mapped - retain those nodes, and just insert/delete other ones
194.3303 -
194.3304 - // "callbackAfterAddingNodes" will be invoked after any "mapping"-generated nodes are inserted into the container node
194.3305 - // You can use this, for example, to activate bindings on those nodes.
194.3306 -
194.3307 - function fixUpNodesToBeMovedOrRemoved(contiguousNodeArray) {
194.3308 - // Before moving, deleting, or replacing a set of nodes that were previously outputted by the "map" function, we have to reconcile
194.3309 - // them against what is in the DOM right now. It may be that some of the nodes have already been removed from the document,
194.3310 - // or that new nodes might have been inserted in the middle, for example by a binding. Also, there may previously have been
194.3311 - // leading comment nodes (created by rewritten string-based templates) that have since been removed during binding.
194.3312 - // So, this function translates the old "map" output array into its best guess of what set of current DOM nodes should be removed.
194.3313 - //
194.3314 - // Rules:
194.3315 - // [A] Any leading nodes that aren't in the document any more should be ignored
194.3316 - // These most likely correspond to memoization nodes that were already removed during binding
194.3317 - // See https://github.com/SteveSanderson/knockout/pull/440
194.3318 - // [B] We want to output a contiguous series of nodes that are still in the document. So, ignore any nodes that
194.3319 - // have already been removed, and include any nodes that have been inserted among the previous collection
194.3320 -
194.3321 - // Rule [A]
194.3322 - while (contiguousNodeArray.length && !ko.utils.domNodeIsAttachedToDocument(contiguousNodeArray[0]))
194.3323 - contiguousNodeArray.splice(0, 1);
194.3324 -
194.3325 - // Rule [B]
194.3326 - if (contiguousNodeArray.length > 1) {
194.3327 - // Build up the actual new contiguous node set
194.3328 - var current = contiguousNodeArray[0], last = contiguousNodeArray[contiguousNodeArray.length - 1], newContiguousSet = [current];
194.3329 - while (current !== last) {
194.3330 - current = current.nextSibling;
194.3331 - if (!current) // Won't happen, except if the developer has manually removed some DOM elements (then we're in an undefined scenario)
194.3332 - return;
194.3333 - newContiguousSet.push(current);
194.3334 - }
194.3335 -
194.3336 - // ... then mutate the input array to match this.
194.3337 - // (The following line replaces the contents of contiguousNodeArray with newContiguousSet)
194.3338 - Array.prototype.splice.apply(contiguousNodeArray, [0, contiguousNodeArray.length].concat(newContiguousSet));
194.3339 - }
194.3340 - return contiguousNodeArray;
194.3341 - }
194.3342 -
194.3343 - function mapNodeAndRefreshWhenChanged(containerNode, mapping, valueToMap, callbackAfterAddingNodes, index) {
194.3344 - // Map this array value inside a dependentObservable so we re-map when any dependency changes
194.3345 - var mappedNodes = [];
194.3346 - var dependentObservable = ko.dependentObservable(function() {
194.3347 - var newMappedNodes = mapping(valueToMap, index) || [];
194.3348 -
194.3349 - // On subsequent evaluations, just replace the previously-inserted DOM nodes
194.3350 - if (mappedNodes.length > 0) {
194.3351 - ko.utils.replaceDomNodes(fixUpNodesToBeMovedOrRemoved(mappedNodes), newMappedNodes);
194.3352 - if (callbackAfterAddingNodes)
194.3353 - ko.dependencyDetection.ignore(callbackAfterAddingNodes, null, [valueToMap, newMappedNodes, index]);
194.3354 - }
194.3355 -
194.3356 - // Replace the contents of the mappedNodes array, thereby updating the record
194.3357 - // of which nodes would be deleted if valueToMap was itself later removed
194.3358 - mappedNodes.splice(0, mappedNodes.length);
194.3359 - ko.utils.arrayPushAll(mappedNodes, newMappedNodes);
194.3360 - }, null, { disposeWhenNodeIsRemoved: containerNode, disposeWhen: function() { return (mappedNodes.length == 0) || !ko.utils.domNodeIsAttachedToDocument(mappedNodes[0]) } });
194.3361 - return { mappedNodes : mappedNodes, dependentObservable : (dependentObservable.isActive() ? dependentObservable : undefined) };
194.3362 - }
194.3363 -
194.3364 - var lastMappingResultDomDataKey = "setDomNodeChildrenFromArrayMapping_lastMappingResult";
194.3365 -
194.3366 - ko.utils.setDomNodeChildrenFromArrayMapping = function (domNode, array, mapping, options, callbackAfterAddingNodes) {
194.3367 - // Compare the provided array against the previous one
194.3368 - array = array || [];
194.3369 - options = options || {};
194.3370 - var isFirstExecution = ko.utils.domData.get(domNode, lastMappingResultDomDataKey) === undefined;
194.3371 - var lastMappingResult = ko.utils.domData.get(domNode, lastMappingResultDomDataKey) || [];
194.3372 - var lastArray = ko.utils.arrayMap(lastMappingResult, function (x) { return x.arrayEntry; });
194.3373 - var editScript = ko.utils.compareArrays(lastArray, array);
194.3374 -
194.3375 - // Build the new mapping result
194.3376 - var newMappingResult = [];
194.3377 - var lastMappingResultIndex = 0;
194.3378 - var newMappingResultIndex = 0;
194.3379 -
194.3380 - var nodesToDelete = [];
194.3381 - var itemsToProcess = [];
194.3382 - var itemsForBeforeRemoveCallbacks = [];
194.3383 - var itemsForMoveCallbacks = [];
194.3384 - var itemsForAfterAddCallbacks = [];
194.3385 - var mapData;
194.3386 -
194.3387 - function itemMovedOrRetained(editScriptIndex, oldPosition) {
194.3388 - mapData = lastMappingResult[oldPosition];
194.3389 - if (newMappingResultIndex !== oldPosition)
194.3390 - itemsForMoveCallbacks[editScriptIndex] = mapData;
194.3391 - // Since updating the index might change the nodes, do so before calling fixUpNodesToBeMovedOrRemoved
194.3392 - mapData.indexObservable(newMappingResultIndex++);
194.3393 - fixUpNodesToBeMovedOrRemoved(mapData.mappedNodes);
194.3394 - newMappingResult.push(mapData);
194.3395 - itemsToProcess.push(mapData);
194.3396 - }
194.3397 -
194.3398 - function callCallback(callback, items) {
194.3399 - if (callback) {
194.3400 - for (var i = 0, n = items.length; i < n; i++) {
194.3401 - if (items[i]) {
194.3402 - ko.utils.arrayForEach(items[i].mappedNodes, function(node) {
194.3403 - callback(node, i, items[i].arrayEntry);
194.3404 - });
194.3405 - }
194.3406 - }
194.3407 - }
194.3408 - }
194.3409 -
194.3410 - for (var i = 0, editScriptItem, movedIndex; editScriptItem = editScript[i]; i++) {
194.3411 - movedIndex = editScriptItem['moved'];
194.3412 - switch (editScriptItem['status']) {
194.3413 - case "deleted":
194.3414 - if (movedIndex === undefined) {
194.3415 - mapData = lastMappingResult[lastMappingResultIndex];
194.3416 -
194.3417 - // Stop tracking changes to the mapping for these nodes
194.3418 - if (mapData.dependentObservable)
194.3419 - mapData.dependentObservable.dispose();
194.3420 -
194.3421 - // Queue these nodes for later removal
194.3422 - nodesToDelete.push.apply(nodesToDelete, fixUpNodesToBeMovedOrRemoved(mapData.mappedNodes));
194.3423 - if (options['beforeRemove']) {
194.3424 - itemsForBeforeRemoveCallbacks[i] = mapData;
194.3425 - itemsToProcess.push(mapData);
194.3426 - }
194.3427 - }
194.3428 - lastMappingResultIndex++;
194.3429 - break;
194.3430 -
194.3431 - case "retained":
194.3432 - itemMovedOrRetained(i, lastMappingResultIndex++);
194.3433 - break;
194.3434 -
194.3435 - case "added":
194.3436 - if (movedIndex !== undefined) {
194.3437 - itemMovedOrRetained(i, movedIndex);
194.3438 - } else {
194.3439 - mapData = { arrayEntry: editScriptItem['value'], indexObservable: ko.observable(newMappingResultIndex++) };
194.3440 - newMappingResult.push(mapData);
194.3441 - itemsToProcess.push(mapData);
194.3442 - if (!isFirstExecution)
194.3443 - itemsForAfterAddCallbacks[i] = mapData;
194.3444 - }
194.3445 - break;
194.3446 - }
194.3447 - }
194.3448 -
194.3449 - // Call beforeMove first before any changes have been made to the DOM
194.3450 - callCallback(options['beforeMove'], itemsForMoveCallbacks);
194.3451 -
194.3452 - // Next remove nodes for deleted items (or just clean if there's a beforeRemove callback)
194.3453 - ko.utils.arrayForEach(nodesToDelete, options['beforeRemove'] ? ko.cleanNode : ko.removeNode);
194.3454 -
194.3455 - // Next add/reorder the remaining items (will include deleted items if there's a beforeRemove callback)
194.3456 - for (var i = 0, nextNode = ko.virtualElements.firstChild(domNode), lastNode, node; mapData = itemsToProcess[i]; i++) {
194.3457 - // Get nodes for newly added items
194.3458 - if (!mapData.mappedNodes)
194.3459 - ko.utils.extend(mapData, mapNodeAndRefreshWhenChanged(domNode, mapping, mapData.arrayEntry, callbackAfterAddingNodes, mapData.indexObservable));
194.3460 -
194.3461 - // Put nodes in the right place if they aren't there already
194.3462 - for (var j = 0; node = mapData.mappedNodes[j]; nextNode = node.nextSibling, lastNode = node, j++) {
194.3463 - if (node !== nextNode)
194.3464 - ko.virtualElements.insertAfter(domNode, node, lastNode);
194.3465 - }
194.3466 -
194.3467 - // Run the callbacks for newly added nodes (for example, to apply bindings, etc.)
194.3468 - if (!mapData.initialized && callbackAfterAddingNodes) {
194.3469 - callbackAfterAddingNodes(mapData.arrayEntry, mapData.mappedNodes, mapData.indexObservable);
194.3470 - mapData.initialized = true;
194.3471 - }
194.3472 - }
194.3473 -
194.3474 - // If there's a beforeRemove callback, call it after reordering.
194.3475 - // Note that we assume that the beforeRemove callback will usually be used to remove the nodes using
194.3476 - // some sort of animation, which is why we first reorder the nodes that will be removed. If the
194.3477 - // callback instead removes the nodes right away, it would be more efficient to skip reordering them.
194.3478 - // Perhaps we'll make that change in the future if this scenario becomes more common.
194.3479 - callCallback(options['beforeRemove'], itemsForBeforeRemoveCallbacks);
194.3480 -
194.3481 - // Finally call afterMove and afterAdd callbacks
194.3482 - callCallback(options['afterMove'], itemsForMoveCallbacks);
194.3483 - callCallback(options['afterAdd'], itemsForAfterAddCallbacks);
194.3484 -
194.3485 - // Store a copy of the array items we just considered so we can difference it next time
194.3486 - ko.utils.domData.set(domNode, lastMappingResultDomDataKey, newMappingResult);
194.3487 - }
194.3488 -})();
194.3489 -
194.3490 -ko.exportSymbol('utils.setDomNodeChildrenFromArrayMapping', ko.utils.setDomNodeChildrenFromArrayMapping);
194.3491 -ko.nativeTemplateEngine = function () {
194.3492 - this['allowTemplateRewriting'] = false;
194.3493 -}
194.3494 -
194.3495 -ko.nativeTemplateEngine.prototype = new ko.templateEngine();
194.3496 -ko.nativeTemplateEngine.prototype['renderTemplateSource'] = function (templateSource, bindingContext, options) {
194.3497 - var useNodesIfAvailable = !(ko.utils.ieVersion < 9), // IE<9 cloneNode doesn't work properly
194.3498 - templateNodesFunc = useNodesIfAvailable ? templateSource['nodes'] : null,
194.3499 - templateNodes = templateNodesFunc ? templateSource['nodes']() : null;
194.3500 -
194.3501 - if (templateNodes) {
194.3502 - return ko.utils.makeArray(templateNodes.cloneNode(true).childNodes);
194.3503 - } else {
194.3504 - var templateText = templateSource['text']();
194.3505 - return ko.utils.parseHtmlFragment(templateText);
194.3506 - }
194.3507 -};
194.3508 -
194.3509 -ko.nativeTemplateEngine.instance = new ko.nativeTemplateEngine();
194.3510 -ko.setTemplateEngine(ko.nativeTemplateEngine.instance);
194.3511 -
194.3512 -ko.exportSymbol('nativeTemplateEngine', ko.nativeTemplateEngine);
194.3513 -(function() {
194.3514 - ko.jqueryTmplTemplateEngine = function () {
194.3515 - // Detect which version of jquery-tmpl you're using. Unfortunately jquery-tmpl
194.3516 - // doesn't expose a version number, so we have to infer it.
194.3517 - // Note that as of Knockout 1.3, we only support jQuery.tmpl 1.0.0pre and later,
194.3518 - // which KO internally refers to as version "2", so older versions are no longer detected.
194.3519 - var jQueryTmplVersion = this.jQueryTmplVersion = (function() {
194.3520 - if ((typeof(jQuery) == "undefined") || !(jQuery['tmpl']))
194.3521 - return 0;
194.3522 - // Since it exposes no official version number, we use our own numbering system. To be updated as jquery-tmpl evolves.
194.3523 - try {
194.3524 - if (jQuery['tmpl']['tag']['tmpl']['open'].toString().indexOf('__') >= 0) {
194.3525 - // Since 1.0.0pre, custom tags should append markup to an array called "__"
194.3526 - return 2; // Final version of jquery.tmpl
194.3527 - }
194.3528 - } catch(ex) { /* Apparently not the version we were looking for */ }
194.3529 -
194.3530 - return 1; // Any older version that we don't support
194.3531 - })();
194.3532 -
194.3533 - function ensureHasReferencedJQueryTemplates() {
194.3534 - if (jQueryTmplVersion < 2)
194.3535 - throw new Error("Your version of jQuery.tmpl is too old. Please upgrade to jQuery.tmpl 1.0.0pre or later.");
194.3536 - }
194.3537 -
194.3538 - function executeTemplate(compiledTemplate, data, jQueryTemplateOptions) {
194.3539 - return jQuery['tmpl'](compiledTemplate, data, jQueryTemplateOptions);
194.3540 - }
194.3541 -
194.3542 - this['renderTemplateSource'] = function(templateSource, bindingContext, options) {
194.3543 - options = options || {};
194.3544 - ensureHasReferencedJQueryTemplates();
194.3545 -
194.3546 - // Ensure we have stored a precompiled version of this template (don't want to reparse on every render)
194.3547 - var precompiled = templateSource['data']('precompiled');
194.3548 - if (!precompiled) {
194.3549 - var templateText = templateSource['text']() || "";
194.3550 - // Wrap in "with($whatever.koBindingContext) { ... }"
194.3551 - templateText = "{{ko_with $item.koBindingContext}}" + templateText + "{{/ko_with}}";
194.3552 -
194.3553 - precompiled = jQuery['template'](null, templateText);
194.3554 - templateSource['data']('precompiled', precompiled);
194.3555 - }
194.3556 -
194.3557 - var data = [bindingContext['$data']]; // Prewrap the data in an array to stop jquery.tmpl from trying to unwrap any arrays
194.3558 - var jQueryTemplateOptions = jQuery['extend']({ 'koBindingContext': bindingContext }, options['templateOptions']);
194.3559 -
194.3560 - var resultNodes = executeTemplate(precompiled, data, jQueryTemplateOptions);
194.3561 - resultNodes['appendTo'](document.createElement("div")); // Using "appendTo" forces jQuery/jQuery.tmpl to perform necessary cleanup work
194.3562 -
194.3563 - jQuery['fragments'] = {}; // Clear jQuery's fragment cache to avoid a memory leak after a large number of template renders
194.3564 - return resultNodes;
194.3565 - };
194.3566 -
194.3567 - this['createJavaScriptEvaluatorBlock'] = function(script) {
194.3568 - return "{{ko_code ((function() { return " + script + " })()) }}";
194.3569 - };
194.3570 -
194.3571 - this['addTemplate'] = function(templateName, templateMarkup) {
194.3572 - document.write("<script type='text/html' id='" + templateName + "'>" + templateMarkup + "</script>");
194.3573 - };
194.3574 -
194.3575 - if (jQueryTmplVersion > 0) {
194.3576 - jQuery['tmpl']['tag']['ko_code'] = {
194.3577 - open: "__.push($1 || '');"
194.3578 - };
194.3579 - jQuery['tmpl']['tag']['ko_with'] = {
194.3580 - open: "with($1) {",
194.3581 - close: "} "
194.3582 - };
194.3583 - }
194.3584 - };
194.3585 -
194.3586 - ko.jqueryTmplTemplateEngine.prototype = new ko.templateEngine();
194.3587 -
194.3588 - // Use this one by default *only if jquery.tmpl is referenced*
194.3589 - var jqueryTmplTemplateEngineInstance = new ko.jqueryTmplTemplateEngine();
194.3590 - if (jqueryTmplTemplateEngineInstance.jQueryTmplVersion > 0)
194.3591 - ko.setTemplateEngine(jqueryTmplTemplateEngineInstance);
194.3592 -
194.3593 - ko.exportSymbol('jqueryTmplTemplateEngine', ko.jqueryTmplTemplateEngine);
194.3594 -})();
194.3595 -});
194.3596 -})(window,document,navigator,window["jQuery"]);
194.3597 -})();
194.3598 \ No newline at end of file
195.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
195.2 +++ b/ko-fx/src/main/resources/org/netbeans/html/kofx/knockout-2.2.1.js Tue Jan 07 08:21:57 2014 +0100
195.3 @@ -0,0 +1,3594 @@
195.4 +// Knockout JavaScript library v2.2.1
195.5 +// (c) Steven Sanderson - http://knockoutjs.com/
195.6 +// License: MIT (http://www.opensource.org/licenses/mit-license.php)
195.7 +
195.8 +(function(){
195.9 +var DEBUG=true;
195.10 +(function(window,document,navigator,jQuery,undefined){
195.11 +!function(factory) {
195.12 + // Support three module loading scenarios
195.13 + if (typeof require === 'function' && typeof exports === 'object' && typeof module === 'object') {
195.14 + // [1] CommonJS/Node.js
195.15 + var target = module['exports'] || exports; // module.exports is for Node.js
195.16 + factory(target);
195.17 + } else if (typeof define === 'function' && define['amd']) {
195.18 + // [2] AMD anonymous module
195.19 + define(['exports'], factory);
195.20 + } else {
195.21 + // [3] No module loader (plain <script> tag) - put directly in global namespace
195.22 + factory(window['ko'] = {});
195.23 + }
195.24 +}(function(koExports){
195.25 +// Internally, all KO objects are attached to koExports (even the non-exported ones whose names will be minified by the closure compiler).
195.26 +// In the future, the following "ko" variable may be made distinct from "koExports" so that private objects are not externally reachable.
195.27 +var ko = typeof koExports !== 'undefined' ? koExports : {};
195.28 +// Google Closure Compiler helpers (used only to make the minified file smaller)
195.29 +ko.exportSymbol = function(koPath, object) {
195.30 + var tokens = koPath.split(".");
195.31 +
195.32 + // In the future, "ko" may become distinct from "koExports" (so that non-exported objects are not reachable)
195.33 + // At that point, "target" would be set to: (typeof koExports !== "undefined" ? koExports : ko)
195.34 + var target = ko;
195.35 +
195.36 + for (var i = 0; i < tokens.length - 1; i++)
195.37 + target = target[tokens[i]];
195.38 + target[tokens[tokens.length - 1]] = object;
195.39 +};
195.40 +ko.exportProperty = function(owner, publicName, object) {
195.41 + owner[publicName] = object;
195.42 +};
195.43 +ko.version = "2.2.1";
195.44 +
195.45 +ko.exportSymbol('version', ko.version);
195.46 +ko.utils = new (function () {
195.47 + var stringTrimRegex = /^(\s|\u00A0)+|(\s|\u00A0)+$/g;
195.48 +
195.49 + // Represent the known event types in a compact way, then at runtime transform it into a hash with event name as key (for fast lookup)
195.50 + var knownEvents = {}, knownEventTypesByEventName = {};
195.51 + var keyEventTypeName = /Firefox\/2/i.test(navigator.userAgent) ? 'KeyboardEvent' : 'UIEvents';
195.52 + knownEvents[keyEventTypeName] = ['keyup', 'keydown', 'keypress'];
195.53 + knownEvents['MouseEvents'] = ['click', 'dblclick', 'mousedown', 'mouseup', 'mousemove', 'mouseover', 'mouseout', 'mouseenter', 'mouseleave'];
195.54 + for (var eventType in knownEvents) {
195.55 + var knownEventsForType = knownEvents[eventType];
195.56 + if (knownEventsForType.length) {
195.57 + for (var i = 0, j = knownEventsForType.length; i < j; i++)
195.58 + knownEventTypesByEventName[knownEventsForType[i]] = eventType;
195.59 + }
195.60 + }
195.61 + var eventsThatMustBeRegisteredUsingAttachEvent = { 'propertychange': true }; // Workaround for an IE9 issue - https://github.com/SteveSanderson/knockout/issues/406
195.62 +
195.63 + // Detect IE versions for bug workarounds (uses IE conditionals, not UA string, for robustness)
195.64 + // Note that, since IE 10 does not support conditional comments, the following logic only detects IE < 10.
195.65 + // Currently this is by design, since IE 10+ behaves correctly when treated as a standard browser.
195.66 + // If there is a future need to detect specific versions of IE10+, we will amend this.
195.67 + var ieVersion = (function() {
195.68 + var version = 3, div = document.createElement('div'), iElems = div.getElementsByTagName('i');
195.69 +
195.70 + // Keep constructing conditional HTML blocks until we hit one that resolves to an empty fragment
195.71 + while (
195.72 + div.innerHTML = '<!--[if gt IE ' + (++version) + ']><i></i><![endif]-->',
195.73 + iElems[0]
195.74 + );
195.75 + return version > 4 ? version : undefined;
195.76 + }());
195.77 + var isIe6 = ieVersion === 6,
195.78 + isIe7 = ieVersion === 7;
195.79 +
195.80 + function isClickOnCheckableElement(element, eventType) {
195.81 + if ((ko.utils.tagNameLower(element) !== "input") || !element.type) return false;
195.82 + if (eventType.toLowerCase() != "click") return false;
195.83 + var inputType = element.type;
195.84 + return (inputType == "checkbox") || (inputType == "radio");
195.85 + }
195.86 +
195.87 + return {
195.88 + fieldsIncludedWithJsonPost: ['authenticity_token', /^__RequestVerificationToken(_.*)?$/],
195.89 +
195.90 + arrayForEach: function (array, action) {
195.91 + for (var i = 0, j = array.length; i < j; i++)
195.92 + action(array[i]);
195.93 + },
195.94 +
195.95 + arrayIndexOf: function (array, item) {
195.96 + if (typeof Array.prototype.indexOf == "function")
195.97 + return Array.prototype.indexOf.call(array, item);
195.98 + for (var i = 0, j = array.length; i < j; i++)
195.99 + if (array[i] === item)
195.100 + return i;
195.101 + return -1;
195.102 + },
195.103 +
195.104 + arrayFirst: function (array, predicate, predicateOwner) {
195.105 + for (var i = 0, j = array.length; i < j; i++)
195.106 + if (predicate.call(predicateOwner, array[i]))
195.107 + return array[i];
195.108 + return null;
195.109 + },
195.110 +
195.111 + arrayRemoveItem: function (array, itemToRemove) {
195.112 + var index = ko.utils.arrayIndexOf(array, itemToRemove);
195.113 + if (index >= 0)
195.114 + array.splice(index, 1);
195.115 + },
195.116 +
195.117 + arrayGetDistinctValues: function (array) {
195.118 + array = array || [];
195.119 + var result = [];
195.120 + for (var i = 0, j = array.length; i < j; i++) {
195.121 + if (ko.utils.arrayIndexOf(result, array[i]) < 0)
195.122 + result.push(array[i]);
195.123 + }
195.124 + return result;
195.125 + },
195.126 +
195.127 + arrayMap: function (array, mapping) {
195.128 + array = array || [];
195.129 + var result = [];
195.130 + for (var i = 0, j = array.length; i < j; i++)
195.131 + result.push(mapping(array[i]));
195.132 + return result;
195.133 + },
195.134 +
195.135 + arrayFilter: function (array, predicate) {
195.136 + array = array || [];
195.137 + var result = [];
195.138 + for (var i = 0, j = array.length; i < j; i++)
195.139 + if (predicate(array[i]))
195.140 + result.push(array[i]);
195.141 + return result;
195.142 + },
195.143 +
195.144 + arrayPushAll: function (array, valuesToPush) {
195.145 + if (valuesToPush instanceof Array)
195.146 + array.push.apply(array, valuesToPush);
195.147 + else
195.148 + for (var i = 0, j = valuesToPush.length; i < j; i++)
195.149 + array.push(valuesToPush[i]);
195.150 + return array;
195.151 + },
195.152 +
195.153 + extend: function (target, source) {
195.154 + if (source) {
195.155 + for(var prop in source) {
195.156 + if(source.hasOwnProperty(prop)) {
195.157 + target[prop] = source[prop];
195.158 + }
195.159 + }
195.160 + }
195.161 + return target;
195.162 + },
195.163 +
195.164 + emptyDomNode: function (domNode) {
195.165 + while (domNode.firstChild) {
195.166 + ko.removeNode(domNode.firstChild);
195.167 + }
195.168 + },
195.169 +
195.170 + moveCleanedNodesToContainerElement: function(nodes) {
195.171 + // Ensure it's a real array, as we're about to reparent the nodes and
195.172 + // we don't want the underlying collection to change while we're doing that.
195.173 + var nodesArray = ko.utils.makeArray(nodes);
195.174 +
195.175 + var container = document.createElement('div');
195.176 + for (var i = 0, j = nodesArray.length; i < j; i++) {
195.177 + container.appendChild(ko.cleanNode(nodesArray[i]));
195.178 + }
195.179 + return container;
195.180 + },
195.181 +
195.182 + cloneNodes: function (nodesArray, shouldCleanNodes) {
195.183 + for (var i = 0, j = nodesArray.length, newNodesArray = []; i < j; i++) {
195.184 + var clonedNode = nodesArray[i].cloneNode(true);
195.185 + newNodesArray.push(shouldCleanNodes ? ko.cleanNode(clonedNode) : clonedNode);
195.186 + }
195.187 + return newNodesArray;
195.188 + },
195.189 +
195.190 + setDomNodeChildren: function (domNode, childNodes) {
195.191 + ko.utils.emptyDomNode(domNode);
195.192 + if (childNodes) {
195.193 + for (var i = 0, j = childNodes.length; i < j; i++)
195.194 + domNode.appendChild(childNodes[i]);
195.195 + }
195.196 + },
195.197 +
195.198 + replaceDomNodes: function (nodeToReplaceOrNodeArray, newNodesArray) {
195.199 + var nodesToReplaceArray = nodeToReplaceOrNodeArray.nodeType ? [nodeToReplaceOrNodeArray] : nodeToReplaceOrNodeArray;
195.200 + if (nodesToReplaceArray.length > 0) {
195.201 + var insertionPoint = nodesToReplaceArray[0];
195.202 + var parent = insertionPoint.parentNode;
195.203 + for (var i = 0, j = newNodesArray.length; i < j; i++)
195.204 + parent.insertBefore(newNodesArray[i], insertionPoint);
195.205 + for (var i = 0, j = nodesToReplaceArray.length; i < j; i++) {
195.206 + ko.removeNode(nodesToReplaceArray[i]);
195.207 + }
195.208 + }
195.209 + },
195.210 +
195.211 + setOptionNodeSelectionState: function (optionNode, isSelected) {
195.212 + // IE6 sometimes throws "unknown error" if you try to write to .selected directly, whereas Firefox struggles with setAttribute. Pick one based on browser.
195.213 + if (ieVersion < 7)
195.214 + optionNode.setAttribute("selected", isSelected);
195.215 + else
195.216 + optionNode.selected = isSelected;
195.217 + },
195.218 +
195.219 + stringTrim: function (string) {
195.220 + return (string || "").replace(stringTrimRegex, "");
195.221 + },
195.222 +
195.223 + stringTokenize: function (string, delimiter) {
195.224 + var result = [];
195.225 + var tokens = (string || "").split(delimiter);
195.226 + for (var i = 0, j = tokens.length; i < j; i++) {
195.227 + var trimmed = ko.utils.stringTrim(tokens[i]);
195.228 + if (trimmed !== "")
195.229 + result.push(trimmed);
195.230 + }
195.231 + return result;
195.232 + },
195.233 +
195.234 + stringStartsWith: function (string, startsWith) {
195.235 + string = string || "";
195.236 + if (startsWith.length > string.length)
195.237 + return false;
195.238 + return string.substring(0, startsWith.length) === startsWith;
195.239 + },
195.240 +
195.241 + domNodeIsContainedBy: function (node, containedByNode) {
195.242 + if (containedByNode.compareDocumentPosition)
195.243 + return (containedByNode.compareDocumentPosition(node) & 16) == 16;
195.244 + while (node != null) {
195.245 + if (node == containedByNode)
195.246 + return true;
195.247 + node = node.parentNode;
195.248 + }
195.249 + return false;
195.250 + },
195.251 +
195.252 + domNodeIsAttachedToDocument: function (node) {
195.253 + return ko.utils.domNodeIsContainedBy(node, node.ownerDocument);
195.254 + },
195.255 +
195.256 + tagNameLower: function(element) {
195.257 + // For HTML elements, tagName will always be upper case; for XHTML elements, it'll be lower case.
195.258 + // Possible future optimization: If we know it's an element from an XHTML document (not HTML),
195.259 + // we don't need to do the .toLowerCase() as it will always be lower case anyway.
195.260 + return element && element.tagName && element.tagName.toLowerCase();
195.261 + },
195.262 +
195.263 + registerEventHandler: function (element, eventType, handler) {
195.264 + var mustUseAttachEvent = ieVersion && eventsThatMustBeRegisteredUsingAttachEvent[eventType];
195.265 + if (!mustUseAttachEvent && typeof jQuery != "undefined") {
195.266 + if (isClickOnCheckableElement(element, eventType)) {
195.267 + // For click events on checkboxes, jQuery interferes with the event handling in an awkward way:
195.268 + // it toggles the element checked state *after* the click event handlers run, whereas native
195.269 + // click events toggle the checked state *before* the event handler.
195.270 + // Fix this by intecepting the handler and applying the correct checkedness before it runs.
195.271 + var originalHandler = handler;
195.272 + handler = function(event, eventData) {
195.273 + var jQuerySuppliedCheckedState = this.checked;
195.274 + if (eventData)
195.275 + this.checked = eventData.checkedStateBeforeEvent !== true;
195.276 + originalHandler.call(this, event);
195.277 + this.checked = jQuerySuppliedCheckedState; // Restore the state jQuery applied
195.278 + };
195.279 + }
195.280 + jQuery(element)['bind'](eventType, handler);
195.281 + } else if (!mustUseAttachEvent && typeof element.addEventListener == "function")
195.282 + element.addEventListener(eventType, handler, false);
195.283 + else if (typeof element.attachEvent != "undefined")
195.284 + element.attachEvent("on" + eventType, function (event) {
195.285 + handler.call(element, event);
195.286 + });
195.287 + else
195.288 + throw new Error("Browser doesn't support addEventListener or attachEvent");
195.289 + },
195.290 +
195.291 + triggerEvent: function (element, eventType) {
195.292 + if (!(element && element.nodeType))
195.293 + throw new Error("element must be a DOM node when calling triggerEvent");
195.294 +
195.295 + if (typeof jQuery != "undefined") {
195.296 + var eventData = [];
195.297 + if (isClickOnCheckableElement(element, eventType)) {
195.298 + // Work around the jQuery "click events on checkboxes" issue described above by storing the original checked state before triggering the handler
195.299 + eventData.push({ checkedStateBeforeEvent: element.checked });
195.300 + }
195.301 + jQuery(element)['trigger'](eventType, eventData);
195.302 + } else if (typeof document.createEvent == "function") {
195.303 + if (typeof element.dispatchEvent == "function") {
195.304 + var eventCategory = knownEventTypesByEventName[eventType] || "HTMLEvents";
195.305 + var event = document.createEvent(eventCategory);
195.306 + event.initEvent(eventType, true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, element);
195.307 + element.dispatchEvent(event);
195.308 + }
195.309 + else
195.310 + throw new Error("The supplied element doesn't support dispatchEvent");
195.311 + } else if (typeof element.fireEvent != "undefined") {
195.312 + // Unlike other browsers, IE doesn't change the checked state of checkboxes/radiobuttons when you trigger their "click" event
195.313 + // so to make it consistent, we'll do it manually here
195.314 + if (isClickOnCheckableElement(element, eventType))
195.315 + element.checked = element.checked !== true;
195.316 + element.fireEvent("on" + eventType);
195.317 + }
195.318 + else
195.319 + throw new Error("Browser doesn't support triggering events");
195.320 + },
195.321 +
195.322 + unwrapObservable: function (value) {
195.323 + return ko.isObservable(value) ? value() : value;
195.324 + },
195.325 +
195.326 + peekObservable: function (value) {
195.327 + return ko.isObservable(value) ? value.peek() : value;
195.328 + },
195.329 +
195.330 + toggleDomNodeCssClass: function (node, classNames, shouldHaveClass) {
195.331 + if (classNames) {
195.332 + var cssClassNameRegex = /[\w-]+/g,
195.333 + currentClassNames = node.className.match(cssClassNameRegex) || [];
195.334 + ko.utils.arrayForEach(classNames.match(cssClassNameRegex), function(className) {
195.335 + var indexOfClass = ko.utils.arrayIndexOf(currentClassNames, className);
195.336 + if (indexOfClass >= 0) {
195.337 + if (!shouldHaveClass)
195.338 + currentClassNames.splice(indexOfClass, 1);
195.339 + } else {
195.340 + if (shouldHaveClass)
195.341 + currentClassNames.push(className);
195.342 + }
195.343 + });
195.344 + node.className = currentClassNames.join(" ");
195.345 + }
195.346 + },
195.347 +
195.348 + setTextContent: function(element, textContent) {
195.349 + var value = ko.utils.unwrapObservable(textContent);
195.350 + if ((value === null) || (value === undefined))
195.351 + value = "";
195.352 +
195.353 + if (element.nodeType === 3) {
195.354 + element.data = value;
195.355 + } else {
195.356 + // We need there to be exactly one child: a text node.
195.357 + // If there are no children, more than one, or if it's not a text node,
195.358 + // we'll clear everything and create a single text node.
195.359 + var innerTextNode = ko.virtualElements.firstChild(element);
195.360 + if (!innerTextNode || innerTextNode.nodeType != 3 || ko.virtualElements.nextSibling(innerTextNode)) {
195.361 + ko.virtualElements.setDomNodeChildren(element, [document.createTextNode(value)]);
195.362 + } else {
195.363 + innerTextNode.data = value;
195.364 + }
195.365 +
195.366 + ko.utils.forceRefresh(element);
195.367 + }
195.368 + },
195.369 +
195.370 + setElementName: function(element, name) {
195.371 + element.name = name;
195.372 +
195.373 + // Workaround IE 6/7 issue
195.374 + // - https://github.com/SteveSanderson/knockout/issues/197
195.375 + // - http://www.matts411.com/post/setting_the_name_attribute_in_ie_dom/
195.376 + if (ieVersion <= 7) {
195.377 + try {
195.378 + element.mergeAttributes(document.createElement("<input name='" + element.name + "'/>"), false);
195.379 + }
195.380 + catch(e) {} // For IE9 with doc mode "IE9 Standards" and browser mode "IE9 Compatibility View"
195.381 + }
195.382 + },
195.383 +
195.384 + forceRefresh: function(node) {
195.385 + // Workaround for an IE9 rendering bug - https://github.com/SteveSanderson/knockout/issues/209
195.386 + if (ieVersion >= 9) {
195.387 + // For text nodes and comment nodes (most likely virtual elements), we will have to refresh the container
195.388 + var elem = node.nodeType == 1 ? node : node.parentNode;
195.389 + if (elem.style)
195.390 + elem.style.zoom = elem.style.zoom;
195.391 + }
195.392 + },
195.393 +
195.394 + ensureSelectElementIsRenderedCorrectly: function(selectElement) {
195.395 + // Workaround for IE9 rendering bug - it doesn't reliably display all the text in dynamically-added select boxes unless you force it to re-render by updating the width.
195.396 + // (See https://github.com/SteveSanderson/knockout/issues/312, http://stackoverflow.com/questions/5908494/select-only-shows-first-char-of-selected-option)
195.397 + if (ieVersion >= 9) {
195.398 + var originalWidth = selectElement.style.width;
195.399 + selectElement.style.width = 0;
195.400 + selectElement.style.width = originalWidth;
195.401 + }
195.402 + },
195.403 +
195.404 + range: function (min, max) {
195.405 + min = ko.utils.unwrapObservable(min);
195.406 + max = ko.utils.unwrapObservable(max);
195.407 + var result = [];
195.408 + for (var i = min; i <= max; i++)
195.409 + result.push(i);
195.410 + return result;
195.411 + },
195.412 +
195.413 + makeArray: function(arrayLikeObject) {
195.414 + var result = [];
195.415 + for (var i = 0, j = arrayLikeObject.length; i < j; i++) {
195.416 + result.push(arrayLikeObject[i]);
195.417 + };
195.418 + return result;
195.419 + },
195.420 +
195.421 + isIe6 : isIe6,
195.422 + isIe7 : isIe7,
195.423 + ieVersion : ieVersion,
195.424 +
195.425 + getFormFields: function(form, fieldName) {
195.426 + var fields = ko.utils.makeArray(form.getElementsByTagName("input")).concat(ko.utils.makeArray(form.getElementsByTagName("textarea")));
195.427 + var isMatchingField = (typeof fieldName == 'string')
195.428 + ? function(field) { return field.name === fieldName }
195.429 + : function(field) { return fieldName.test(field.name) }; // Treat fieldName as regex or object containing predicate
195.430 + var matches = [];
195.431 + for (var i = fields.length - 1; i >= 0; i--) {
195.432 + if (isMatchingField(fields[i]))
195.433 + matches.push(fields[i]);
195.434 + };
195.435 + return matches;
195.436 + },
195.437 +
195.438 + parseJson: function (jsonString) {
195.439 + if (typeof jsonString == "string") {
195.440 + jsonString = ko.utils.stringTrim(jsonString);
195.441 + if (jsonString) {
195.442 + if (window.JSON && window.JSON.parse) // Use native parsing where available
195.443 + return window.JSON.parse(jsonString);
195.444 + return (new Function("return " + jsonString))(); // Fallback on less safe parsing for older browsers
195.445 + }
195.446 + }
195.447 + return null;
195.448 + },
195.449 +
195.450 + stringifyJson: function (data, replacer, space) { // replacer and space are optional
195.451 + if ((typeof JSON == "undefined") || (typeof JSON.stringify == "undefined"))
195.452 + throw new Error("Cannot find JSON.stringify(). Some browsers (e.g., IE < 8) don't support it natively, but you can overcome this by adding a script reference to json2.js, downloadable from http://www.json.org/json2.js");
195.453 + return JSON.stringify(ko.utils.unwrapObservable(data), replacer, space);
195.454 + },
195.455 +
195.456 + postJson: function (urlOrForm, data, options) {
195.457 + options = options || {};
195.458 + var params = options['params'] || {};
195.459 + var includeFields = options['includeFields'] || this.fieldsIncludedWithJsonPost;
195.460 + var url = urlOrForm;
195.461 +
195.462 + // If we were given a form, use its 'action' URL and pick out any requested field values
195.463 + if((typeof urlOrForm == 'object') && (ko.utils.tagNameLower(urlOrForm) === "form")) {
195.464 + var originalForm = urlOrForm;
195.465 + url = originalForm.action;
195.466 + for (var i = includeFields.length - 1; i >= 0; i--) {
195.467 + var fields = ko.utils.getFormFields(originalForm, includeFields[i]);
195.468 + for (var j = fields.length - 1; j >= 0; j--)
195.469 + params[fields[j].name] = fields[j].value;
195.470 + }
195.471 + }
195.472 +
195.473 + data = ko.utils.unwrapObservable(data);
195.474 + var form = document.createElement("form");
195.475 + form.style.display = "none";
195.476 + form.action = url;
195.477 + form.method = "post";
195.478 + for (var key in data) {
195.479 + var input = document.createElement("input");
195.480 + input.name = key;
195.481 + input.value = ko.utils.stringifyJson(ko.utils.unwrapObservable(data[key]));
195.482 + form.appendChild(input);
195.483 + }
195.484 + for (var key in params) {
195.485 + var input = document.createElement("input");
195.486 + input.name = key;
195.487 + input.value = params[key];
195.488 + form.appendChild(input);
195.489 + }
195.490 + document.body.appendChild(form);
195.491 + options['submitter'] ? options['submitter'](form) : form.submit();
195.492 + setTimeout(function () { form.parentNode.removeChild(form); }, 0);
195.493 + }
195.494 + }
195.495 +})();
195.496 +
195.497 +ko.exportSymbol('utils', ko.utils);
195.498 +ko.exportSymbol('utils.arrayForEach', ko.utils.arrayForEach);
195.499 +ko.exportSymbol('utils.arrayFirst', ko.utils.arrayFirst);
195.500 +ko.exportSymbol('utils.arrayFilter', ko.utils.arrayFilter);
195.501 +ko.exportSymbol('utils.arrayGetDistinctValues', ko.utils.arrayGetDistinctValues);
195.502 +ko.exportSymbol('utils.arrayIndexOf', ko.utils.arrayIndexOf);
195.503 +ko.exportSymbol('utils.arrayMap', ko.utils.arrayMap);
195.504 +ko.exportSymbol('utils.arrayPushAll', ko.utils.arrayPushAll);
195.505 +ko.exportSymbol('utils.arrayRemoveItem', ko.utils.arrayRemoveItem);
195.506 +ko.exportSymbol('utils.extend', ko.utils.extend);
195.507 +ko.exportSymbol('utils.fieldsIncludedWithJsonPost', ko.utils.fieldsIncludedWithJsonPost);
195.508 +ko.exportSymbol('utils.getFormFields', ko.utils.getFormFields);
195.509 +ko.exportSymbol('utils.peekObservable', ko.utils.peekObservable);
195.510 +ko.exportSymbol('utils.postJson', ko.utils.postJson);
195.511 +ko.exportSymbol('utils.parseJson', ko.utils.parseJson);
195.512 +ko.exportSymbol('utils.registerEventHandler', ko.utils.registerEventHandler);
195.513 +ko.exportSymbol('utils.stringifyJson', ko.utils.stringifyJson);
195.514 +ko.exportSymbol('utils.range', ko.utils.range);
195.515 +ko.exportSymbol('utils.toggleDomNodeCssClass', ko.utils.toggleDomNodeCssClass);
195.516 +ko.exportSymbol('utils.triggerEvent', ko.utils.triggerEvent);
195.517 +ko.exportSymbol('utils.unwrapObservable', ko.utils.unwrapObservable);
195.518 +
195.519 +if (!Function.prototype['bind']) {
195.520 + // Function.prototype.bind is a standard part of ECMAScript 5th Edition (December 2009, http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf)
195.521 + // In case the browser doesn't implement it natively, provide a JavaScript implementation. This implementation is based on the one in prototype.js
195.522 + Function.prototype['bind'] = function (object) {
195.523 + var originalFunction = this, args = Array.prototype.slice.call(arguments), object = args.shift();
195.524 + return function () {
195.525 + return originalFunction.apply(object, args.concat(Array.prototype.slice.call(arguments)));
195.526 + };
195.527 + };
195.528 +}
195.529 +
195.530 +ko.utils.domData = new (function () {
195.531 + var uniqueId = 0;
195.532 + var dataStoreKeyExpandoPropertyName = "__ko__" + (new Date).getTime();
195.533 + var dataStore = {};
195.534 + return {
195.535 + get: function (node, key) {
195.536 + var allDataForNode = ko.utils.domData.getAll(node, false);
195.537 + return allDataForNode === undefined ? undefined : allDataForNode[key];
195.538 + },
195.539 + set: function (node, key, value) {
195.540 + if (value === undefined) {
195.541 + // Make sure we don't actually create a new domData key if we are actually deleting a value
195.542 + if (ko.utils.domData.getAll(node, false) === undefined)
195.543 + return;
195.544 + }
195.545 + var allDataForNode = ko.utils.domData.getAll(node, true);
195.546 + allDataForNode[key] = value;
195.547 + },
195.548 + getAll: function (node, createIfNotFound) {
195.549 + var dataStoreKey = node[dataStoreKeyExpandoPropertyName];
195.550 + var hasExistingDataStore = dataStoreKey && (dataStoreKey !== "null") && dataStore[dataStoreKey];
195.551 + if (!hasExistingDataStore) {
195.552 + if (!createIfNotFound)
195.553 + return undefined;
195.554 + dataStoreKey = node[dataStoreKeyExpandoPropertyName] = "ko" + uniqueId++;
195.555 + dataStore[dataStoreKey] = {};
195.556 + }
195.557 + return dataStore[dataStoreKey];
195.558 + },
195.559 + clear: function (node) {
195.560 + var dataStoreKey = node[dataStoreKeyExpandoPropertyName];
195.561 + if (dataStoreKey) {
195.562 + delete dataStore[dataStoreKey];
195.563 + node[dataStoreKeyExpandoPropertyName] = null;
195.564 + return true; // Exposing "did clean" flag purely so specs can infer whether things have been cleaned up as intended
195.565 + }
195.566 + return false;
195.567 + }
195.568 + }
195.569 +})();
195.570 +
195.571 +ko.exportSymbol('utils.domData', ko.utils.domData);
195.572 +ko.exportSymbol('utils.domData.clear', ko.utils.domData.clear); // Exporting only so specs can clear up after themselves fully
195.573 +
195.574 +ko.utils.domNodeDisposal = new (function () {
195.575 + var domDataKey = "__ko_domNodeDisposal__" + (new Date).getTime();
195.576 + var cleanableNodeTypes = { 1: true, 8: true, 9: true }; // Element, Comment, Document
195.577 + var cleanableNodeTypesWithDescendants = { 1: true, 9: true }; // Element, Document
195.578 +
195.579 + function getDisposeCallbacksCollection(node, createIfNotFound) {
195.580 + var allDisposeCallbacks = ko.utils.domData.get(node, domDataKey);
195.581 + if ((allDisposeCallbacks === undefined) && createIfNotFound) {
195.582 + allDisposeCallbacks = [];
195.583 + ko.utils.domData.set(node, domDataKey, allDisposeCallbacks);
195.584 + }
195.585 + return allDisposeCallbacks;
195.586 + }
195.587 + function destroyCallbacksCollection(node) {
195.588 + ko.utils.domData.set(node, domDataKey, undefined);
195.589 + }
195.590 +
195.591 + function cleanSingleNode(node) {
195.592 + // Run all the dispose callbacks
195.593 + var callbacks = getDisposeCallbacksCollection(node, false);
195.594 + if (callbacks) {
195.595 + callbacks = callbacks.slice(0); // Clone, as the array may be modified during iteration (typically, callbacks will remove themselves)
195.596 + for (var i = 0; i < callbacks.length; i++)
195.597 + callbacks[i](node);
195.598 + }
195.599 +
195.600 + // Also erase the DOM data
195.601 + ko.utils.domData.clear(node);
195.602 +
195.603 + // Special support for jQuery here because it's so commonly used.
195.604 + // Many jQuery plugins (including jquery.tmpl) store data using jQuery's equivalent of domData
195.605 + // so notify it to tear down any resources associated with the node & descendants here.
195.606 + if ((typeof jQuery == "function") && (typeof jQuery['cleanData'] == "function"))
195.607 + jQuery['cleanData']([node]);
195.608 +
195.609 + // Also clear any immediate-child comment nodes, as these wouldn't have been found by
195.610 + // node.getElementsByTagName("*") in cleanNode() (comment nodes aren't elements)
195.611 + if (cleanableNodeTypesWithDescendants[node.nodeType])
195.612 + cleanImmediateCommentTypeChildren(node);
195.613 + }
195.614 +
195.615 + function cleanImmediateCommentTypeChildren(nodeWithChildren) {
195.616 + var child, nextChild = nodeWithChildren.firstChild;
195.617 + while (child = nextChild) {
195.618 + nextChild = child.nextSibling;
195.619 + if (child.nodeType === 8)
195.620 + cleanSingleNode(child);
195.621 + }
195.622 + }
195.623 +
195.624 + return {
195.625 + addDisposeCallback : function(node, callback) {
195.626 + if (typeof callback != "function")
195.627 + throw new Error("Callback must be a function");
195.628 + getDisposeCallbacksCollection(node, true).push(callback);
195.629 + },
195.630 +
195.631 + removeDisposeCallback : function(node, callback) {
195.632 + var callbacksCollection = getDisposeCallbacksCollection(node, false);
195.633 + if (callbacksCollection) {
195.634 + ko.utils.arrayRemoveItem(callbacksCollection, callback);
195.635 + if (callbacksCollection.length == 0)
195.636 + destroyCallbacksCollection(node);
195.637 + }
195.638 + },
195.639 +
195.640 + cleanNode : function(node) {
195.641 + // First clean this node, where applicable
195.642 + if (cleanableNodeTypes[node.nodeType]) {
195.643 + cleanSingleNode(node);
195.644 +
195.645 + // ... then its descendants, where applicable
195.646 + if (cleanableNodeTypesWithDescendants[node.nodeType]) {
195.647 + // Clone the descendants list in case it changes during iteration
195.648 + var descendants = [];
195.649 + ko.utils.arrayPushAll(descendants, node.getElementsByTagName("*"));
195.650 + for (var i = 0, j = descendants.length; i < j; i++)
195.651 + cleanSingleNode(descendants[i]);
195.652 + }
195.653 + }
195.654 + return node;
195.655 + },
195.656 +
195.657 + removeNode : function(node) {
195.658 + ko.cleanNode(node);
195.659 + if (node.parentNode)
195.660 + node.parentNode.removeChild(node);
195.661 + }
195.662 + }
195.663 +})();
195.664 +ko.cleanNode = ko.utils.domNodeDisposal.cleanNode; // Shorthand name for convenience
195.665 +ko.removeNode = ko.utils.domNodeDisposal.removeNode; // Shorthand name for convenience
195.666 +ko.exportSymbol('cleanNode', ko.cleanNode);
195.667 +ko.exportSymbol('removeNode', ko.removeNode);
195.668 +ko.exportSymbol('utils.domNodeDisposal', ko.utils.domNodeDisposal);
195.669 +ko.exportSymbol('utils.domNodeDisposal.addDisposeCallback', ko.utils.domNodeDisposal.addDisposeCallback);
195.670 +ko.exportSymbol('utils.domNodeDisposal.removeDisposeCallback', ko.utils.domNodeDisposal.removeDisposeCallback);
195.671 +(function () {
195.672 + var leadingCommentRegex = /^(\s*)<!--(.*?)-->/;
195.673 +
195.674 + function simpleHtmlParse(html) {
195.675 + // Based on jQuery's "clean" function, but only accounting for table-related elements.
195.676 + // If you have referenced jQuery, this won't be used anyway - KO will use jQuery's "clean" function directly
195.677 +
195.678 + // Note that there's still an issue in IE < 9 whereby it will discard comment nodes that are the first child of
195.679 + // a descendant node. For example: "<div><!-- mycomment -->abc</div>" will get parsed as "<div>abc</div>"
195.680 + // This won't affect anyone who has referenced jQuery, and there's always the workaround of inserting a dummy node
195.681 + // (possibly a text node) in front of the comment. So, KO does not attempt to workaround this IE issue automatically at present.
195.682 +
195.683 + // Trim whitespace, otherwise indexOf won't work as expected
195.684 + var tags = ko.utils.stringTrim(html).toLowerCase(), div = document.createElement("div");
195.685 +
195.686 + // Finds the first match from the left column, and returns the corresponding "wrap" data from the right column
195.687 + var wrap = tags.match(/^<(thead|tbody|tfoot)/) && [1, "<table>", "</table>"] ||
195.688 + !tags.indexOf("<tr") && [2, "<table><tbody>", "</tbody></table>"] ||
195.689 + (!tags.indexOf("<td") || !tags.indexOf("<th")) && [3, "<table><tbody><tr>", "</tr></tbody></table>"] ||
195.690 + /* anything else */ [0, "", ""];
195.691 +
195.692 + // Go to html and back, then peel off extra wrappers
195.693 + // Note that we always prefix with some dummy text, because otherwise, IE<9 will strip out leading comment nodes in descendants. Total madness.
195.694 + var markup = "ignored<div>" + wrap[1] + html + wrap[2] + "</div>";
195.695 + if (typeof window['innerShiv'] == "function") {
195.696 + div.appendChild(window['innerShiv'](markup));
195.697 + } else {
195.698 + div.innerHTML = markup;
195.699 + }
195.700 +
195.701 + // Move to the right depth
195.702 + while (wrap[0]--)
195.703 + div = div.lastChild;
195.704 +
195.705 + return ko.utils.makeArray(div.lastChild.childNodes);
195.706 + }
195.707 +
195.708 + function jQueryHtmlParse(html) {
195.709 + // jQuery's "parseHTML" function was introduced in jQuery 1.8.0 and is a documented public API.
195.710 + if (jQuery['parseHTML']) {
195.711 + return jQuery['parseHTML'](html);
195.712 + } else {
195.713 + // For jQuery < 1.8.0, we fall back on the undocumented internal "clean" function.
195.714 + var elems = jQuery['clean']([html]);
195.715 +
195.716 + // As of jQuery 1.7.1, jQuery parses the HTML by appending it to some dummy parent nodes held in an in-memory document fragment.
195.717 + // Unfortunately, it never clears the dummy parent nodes from the document fragment, so it leaks memory over time.
195.718 + // Fix this by finding the top-most dummy parent element, and detaching it from its owner fragment.
195.719 + if (elems && elems[0]) {
195.720 + // Find the top-most parent element that's a direct child of a document fragment
195.721 + var elem = elems[0];
195.722 + while (elem.parentNode && elem.parentNode.nodeType !== 11 /* i.e., DocumentFragment */)
195.723 + elem = elem.parentNode;
195.724 + // ... then detach it
195.725 + if (elem.parentNode)
195.726 + elem.parentNode.removeChild(elem);
195.727 + }
195.728 +
195.729 + return elems;
195.730 + }
195.731 + }
195.732 +
195.733 + ko.utils.parseHtmlFragment = function(html) {
195.734 + return typeof jQuery != 'undefined' ? jQueryHtmlParse(html) // As below, benefit from jQuery's optimisations where possible
195.735 + : simpleHtmlParse(html); // ... otherwise, this simple logic will do in most common cases.
195.736 + };
195.737 +
195.738 + ko.utils.setHtml = function(node, html) {
195.739 + ko.utils.emptyDomNode(node);
195.740 +
195.741 + // There's no legitimate reason to display a stringified observable without unwrapping it, so we'll unwrap it
195.742 + html = ko.utils.unwrapObservable(html);
195.743 +
195.744 + if ((html !== null) && (html !== undefined)) {
195.745 + if (typeof html != 'string')
195.746 + html = html.toString();
195.747 +
195.748 + // jQuery contains a lot of sophisticated code to parse arbitrary HTML fragments,
195.749 + // for example <tr> elements which are not normally allowed to exist on their own.
195.750 + // If you've referenced jQuery we'll use that rather than duplicating its code.
195.751 + if (typeof jQuery != 'undefined') {
195.752 + jQuery(node)['html'](html);
195.753 + } else {
195.754 + // ... otherwise, use KO's own parsing logic.
195.755 + var parsedNodes = ko.utils.parseHtmlFragment(html);
195.756 + for (var i = 0; i < parsedNodes.length; i++)
195.757 + node.appendChild(parsedNodes[i]);
195.758 + }
195.759 + }
195.760 + };
195.761 +})();
195.762 +
195.763 +ko.exportSymbol('utils.parseHtmlFragment', ko.utils.parseHtmlFragment);
195.764 +ko.exportSymbol('utils.setHtml', ko.utils.setHtml);
195.765 +
195.766 +ko.memoization = (function () {
195.767 + var memos = {};
195.768 +
195.769 + function randomMax8HexChars() {
195.770 + return (((1 + Math.random()) * 0x100000000) | 0).toString(16).substring(1);
195.771 + }
195.772 + function generateRandomId() {
195.773 + return randomMax8HexChars() + randomMax8HexChars();
195.774 + }
195.775 + function findMemoNodes(rootNode, appendToArray) {
195.776 + if (!rootNode)
195.777 + return;
195.778 + if (rootNode.nodeType == 8) {
195.779 + var memoId = ko.memoization.parseMemoText(rootNode.nodeValue);
195.780 + if (memoId != null)
195.781 + appendToArray.push({ domNode: rootNode, memoId: memoId });
195.782 + } else if (rootNode.nodeType == 1) {
195.783 + for (var i = 0, childNodes = rootNode.childNodes, j = childNodes.length; i < j; i++)
195.784 + findMemoNodes(childNodes[i], appendToArray);
195.785 + }
195.786 + }
195.787 +
195.788 + return {
195.789 + memoize: function (callback) {
195.790 + if (typeof callback != "function")
195.791 + throw new Error("You can only pass a function to ko.memoization.memoize()");
195.792 + var memoId = generateRandomId();
195.793 + memos[memoId] = callback;
195.794 + return "<!--[ko_memo:" + memoId + "]-->";
195.795 + },
195.796 +
195.797 + unmemoize: function (memoId, callbackParams) {
195.798 + var callback = memos[memoId];
195.799 + if (callback === undefined)
195.800 + throw new Error("Couldn't find any memo with ID " + memoId + ". Perhaps it's already been unmemoized.");
195.801 + try {
195.802 + callback.apply(null, callbackParams || []);
195.803 + return true;
195.804 + }
195.805 + finally { delete memos[memoId]; }
195.806 + },
195.807 +
195.808 + unmemoizeDomNodeAndDescendants: function (domNode, extraCallbackParamsArray) {
195.809 + var memos = [];
195.810 + findMemoNodes(domNode, memos);
195.811 + for (var i = 0, j = memos.length; i < j; i++) {
195.812 + var node = memos[i].domNode;
195.813 + var combinedParams = [node];
195.814 + if (extraCallbackParamsArray)
195.815 + ko.utils.arrayPushAll(combinedParams, extraCallbackParamsArray);
195.816 + ko.memoization.unmemoize(memos[i].memoId, combinedParams);
195.817 + node.nodeValue = ""; // Neuter this node so we don't try to unmemoize it again
195.818 + if (node.parentNode)
195.819 + node.parentNode.removeChild(node); // If possible, erase it totally (not always possible - someone else might just hold a reference to it then call unmemoizeDomNodeAndDescendants again)
195.820 + }
195.821 + },
195.822 +
195.823 + parseMemoText: function (memoText) {
195.824 + var match = memoText.match(/^\[ko_memo\:(.*?)\]$/);
195.825 + return match ? match[1] : null;
195.826 + }
195.827 + };
195.828 +})();
195.829 +
195.830 +ko.exportSymbol('memoization', ko.memoization);
195.831 +ko.exportSymbol('memoization.memoize', ko.memoization.memoize);
195.832 +ko.exportSymbol('memoization.unmemoize', ko.memoization.unmemoize);
195.833 +ko.exportSymbol('memoization.parseMemoText', ko.memoization.parseMemoText);
195.834 +ko.exportSymbol('memoization.unmemoizeDomNodeAndDescendants', ko.memoization.unmemoizeDomNodeAndDescendants);
195.835 +ko.extenders = {
195.836 + 'throttle': function(target, timeout) {
195.837 + // Throttling means two things:
195.838 +
195.839 + // (1) For dependent observables, we throttle *evaluations* so that, no matter how fast its dependencies
195.840 + // notify updates, the target doesn't re-evaluate (and hence doesn't notify) faster than a certain rate
195.841 + target['throttleEvaluation'] = timeout;
195.842 +
195.843 + // (2) For writable targets (observables, or writable dependent observables), we throttle *writes*
195.844 + // so the target cannot change value synchronously or faster than a certain rate
195.845 + var writeTimeoutInstance = null;
195.846 + return ko.dependentObservable({
195.847 + 'read': target,
195.848 + 'write': function(value) {
195.849 + clearTimeout(writeTimeoutInstance);
195.850 + writeTimeoutInstance = setTimeout(function() {
195.851 + target(value);
195.852 + }, timeout);
195.853 + }
195.854 + });
195.855 + },
195.856 +
195.857 + 'notify': function(target, notifyWhen) {
195.858 + target["equalityComparer"] = notifyWhen == "always"
195.859 + ? function() { return false } // Treat all values as not equal
195.860 + : ko.observable["fn"]["equalityComparer"];
195.861 + return target;
195.862 + }
195.863 +};
195.864 +
195.865 +function applyExtenders(requestedExtenders) {
195.866 + var target = this;
195.867 + if (requestedExtenders) {
195.868 + for (var key in requestedExtenders) {
195.869 + var extenderHandler = ko.extenders[key];
195.870 + if (typeof extenderHandler == 'function') {
195.871 + target = extenderHandler(target, requestedExtenders[key]);
195.872 + }
195.873 + }
195.874 + }
195.875 + return target;
195.876 +}
195.877 +
195.878 +ko.exportSymbol('extenders', ko.extenders);
195.879 +
195.880 +ko.subscription = function (target, callback, disposeCallback) {
195.881 + this.target = target;
195.882 + this.callback = callback;
195.883 + this.disposeCallback = disposeCallback;
195.884 + ko.exportProperty(this, 'dispose', this.dispose);
195.885 +};
195.886 +ko.subscription.prototype.dispose = function () {
195.887 + this.isDisposed = true;
195.888 + this.disposeCallback();
195.889 +};
195.890 +
195.891 +ko.subscribable = function () {
195.892 + this._subscriptions = {};
195.893 +
195.894 + ko.utils.extend(this, ko.subscribable['fn']);
195.895 + ko.exportProperty(this, 'subscribe', this.subscribe);
195.896 + ko.exportProperty(this, 'extend', this.extend);
195.897 + ko.exportProperty(this, 'getSubscriptionsCount', this.getSubscriptionsCount);
195.898 +}
195.899 +
195.900 +var defaultEvent = "change";
195.901 +
195.902 +ko.subscribable['fn'] = {
195.903 + subscribe: function (callback, callbackTarget, event) {
195.904 + event = event || defaultEvent;
195.905 + var boundCallback = callbackTarget ? callback.bind(callbackTarget) : callback;
195.906 +
195.907 + var subscription = new ko.subscription(this, boundCallback, function () {
195.908 + ko.utils.arrayRemoveItem(this._subscriptions[event], subscription);
195.909 + }.bind(this));
195.910 +
195.911 + if (!this._subscriptions[event])
195.912 + this._subscriptions[event] = [];
195.913 + this._subscriptions[event].push(subscription);
195.914 + return subscription;
195.915 + },
195.916 +
195.917 + "notifySubscribers": function (valueToNotify, event) {
195.918 + event = event || defaultEvent;
195.919 + if (this._subscriptions[event]) {
195.920 + ko.dependencyDetection.ignore(function() {
195.921 + ko.utils.arrayForEach(this._subscriptions[event].slice(0), function (subscription) {
195.922 + // In case a subscription was disposed during the arrayForEach cycle, check
195.923 + // for isDisposed on each subscription before invoking its callback
195.924 + if (subscription && (subscription.isDisposed !== true))
195.925 + subscription.callback(valueToNotify);
195.926 + });
195.927 + }, this);
195.928 + }
195.929 + },
195.930 +
195.931 + getSubscriptionsCount: function () {
195.932 + var total = 0;
195.933 + for (var eventName in this._subscriptions) {
195.934 + if (this._subscriptions.hasOwnProperty(eventName))
195.935 + total += this._subscriptions[eventName].length;
195.936 + }
195.937 + return total;
195.938 + },
195.939 +
195.940 + extend: applyExtenders
195.941 +};
195.942 +
195.943 +
195.944 +ko.isSubscribable = function (instance) {
195.945 + return typeof instance.subscribe == "function" && typeof instance["notifySubscribers"] == "function";
195.946 +};
195.947 +
195.948 +ko.exportSymbol('subscribable', ko.subscribable);
195.949 +ko.exportSymbol('isSubscribable', ko.isSubscribable);
195.950 +
195.951 +ko.dependencyDetection = (function () {
195.952 + var _frames = [];
195.953 +
195.954 + return {
195.955 + begin: function (callback) {
195.956 + _frames.push({ callback: callback, distinctDependencies:[] });
195.957 + },
195.958 +
195.959 + end: function () {
195.960 + _frames.pop();
195.961 + },
195.962 +
195.963 + registerDependency: function (subscribable) {
195.964 + if (!ko.isSubscribable(subscribable))
195.965 + throw new Error("Only subscribable things can act as dependencies");
195.966 + if (_frames.length > 0) {
195.967 + var topFrame = _frames[_frames.length - 1];
195.968 + if (!topFrame || ko.utils.arrayIndexOf(topFrame.distinctDependencies, subscribable) >= 0)
195.969 + return;
195.970 + topFrame.distinctDependencies.push(subscribable);
195.971 + topFrame.callback(subscribable);
195.972 + }
195.973 + },
195.974 +
195.975 + ignore: function(callback, callbackTarget, callbackArgs) {
195.976 + try {
195.977 + _frames.push(null);
195.978 + return callback.apply(callbackTarget, callbackArgs || []);
195.979 + } finally {
195.980 + _frames.pop();
195.981 + }
195.982 + }
195.983 + };
195.984 +})();
195.985 +var primitiveTypes = { 'undefined':true, 'boolean':true, 'number':true, 'string':true };
195.986 +
195.987 +ko.observable = function (initialValue) {
195.988 + var _latestValue = initialValue;
195.989 +
195.990 + function observable() {
195.991 + if (arguments.length > 0) {
195.992 + // Write
195.993 +
195.994 + // Ignore writes if the value hasn't changed
195.995 + if ((!observable['equalityComparer']) || !observable['equalityComparer'](_latestValue, arguments[0])) {
195.996 + observable.valueWillMutate();
195.997 + _latestValue = arguments[0];
195.998 + if (DEBUG) observable._latestValue = _latestValue;
195.999 + observable.valueHasMutated();
195.1000 + }
195.1001 + return this; // Permits chained assignments
195.1002 + }
195.1003 + else {
195.1004 + // Read
195.1005 + ko.dependencyDetection.registerDependency(observable); // The caller only needs to be notified of changes if they did a "read" operation
195.1006 + return _latestValue;
195.1007 + }
195.1008 + }
195.1009 + if (DEBUG) observable._latestValue = _latestValue;
195.1010 + ko.subscribable.call(observable);
195.1011 + observable.peek = function() { return _latestValue };
195.1012 + observable.valueHasMutated = function () { observable["notifySubscribers"](_latestValue); }
195.1013 + observable.valueWillMutate = function () { observable["notifySubscribers"](_latestValue, "beforeChange"); }
195.1014 + ko.utils.extend(observable, ko.observable['fn']);
195.1015 +
195.1016 + ko.exportProperty(observable, 'peek', observable.peek);
195.1017 + ko.exportProperty(observable, "valueHasMutated", observable.valueHasMutated);
195.1018 + ko.exportProperty(observable, "valueWillMutate", observable.valueWillMutate);
195.1019 +
195.1020 + return observable;
195.1021 +}
195.1022 +
195.1023 +ko.observable['fn'] = {
195.1024 + "equalityComparer": function valuesArePrimitiveAndEqual(a, b) {
195.1025 + var oldValueIsPrimitive = (a === null) || (typeof(a) in primitiveTypes);
195.1026 + return oldValueIsPrimitive ? (a === b) : false;
195.1027 + }
195.1028 +};
195.1029 +
195.1030 +var protoProperty = ko.observable.protoProperty = "__ko_proto__";
195.1031 +ko.observable['fn'][protoProperty] = ko.observable;
195.1032 +
195.1033 +ko.hasPrototype = function(instance, prototype) {
195.1034 + if ((instance === null) || (instance === undefined) || (instance[protoProperty] === undefined)) return false;
195.1035 + if (instance[protoProperty] === prototype) return true;
195.1036 + return ko.hasPrototype(instance[protoProperty], prototype); // Walk the prototype chain
195.1037 +};
195.1038 +
195.1039 +ko.isObservable = function (instance) {
195.1040 + return ko.hasPrototype(instance, ko.observable);
195.1041 +}
195.1042 +ko.isWriteableObservable = function (instance) {
195.1043 + // Observable
195.1044 + if ((typeof instance == "function") && instance[protoProperty] === ko.observable)
195.1045 + return true;
195.1046 + // Writeable dependent observable
195.1047 + if ((typeof instance == "function") && (instance[protoProperty] === ko.dependentObservable) && (instance.hasWriteFunction))
195.1048 + return true;
195.1049 + // Anything else
195.1050 + return false;
195.1051 +}
195.1052 +
195.1053 +
195.1054 +ko.exportSymbol('observable', ko.observable);
195.1055 +ko.exportSymbol('isObservable', ko.isObservable);
195.1056 +ko.exportSymbol('isWriteableObservable', ko.isWriteableObservable);
195.1057 +ko.observableArray = function (initialValues) {
195.1058 + if (arguments.length == 0) {
195.1059 + // Zero-parameter constructor initializes to empty array
195.1060 + initialValues = [];
195.1061 + }
195.1062 + if ((initialValues !== null) && (initialValues !== undefined) && !('length' in initialValues))
195.1063 + throw new Error("The argument passed when initializing an observable array must be an array, or null, or undefined.");
195.1064 +
195.1065 + var result = ko.observable(initialValues);
195.1066 + ko.utils.extend(result, ko.observableArray['fn']);
195.1067 + return result;
195.1068 +}
195.1069 +
195.1070 +ko.observableArray['fn'] = {
195.1071 + 'remove': function (valueOrPredicate) {
195.1072 + var underlyingArray = this.peek();
195.1073 + var removedValues = [];
195.1074 + var predicate = typeof valueOrPredicate == "function" ? valueOrPredicate : function (value) { return value === valueOrPredicate; };
195.1075 + for (var i = 0; i < underlyingArray.length; i++) {
195.1076 + var value = underlyingArray[i];
195.1077 + if (predicate(value)) {
195.1078 + if (removedValues.length === 0) {
195.1079 + this.valueWillMutate();
195.1080 + }
195.1081 + removedValues.push(value);
195.1082 + underlyingArray.splice(i, 1);
195.1083 + i--;
195.1084 + }
195.1085 + }
195.1086 + if (removedValues.length) {
195.1087 + this.valueHasMutated();
195.1088 + }
195.1089 + return removedValues;
195.1090 + },
195.1091 +
195.1092 + 'removeAll': function (arrayOfValues) {
195.1093 + // If you passed zero args, we remove everything
195.1094 + if (arrayOfValues === undefined) {
195.1095 + var underlyingArray = this.peek();
195.1096 + var allValues = underlyingArray.slice(0);
195.1097 + this.valueWillMutate();
195.1098 + underlyingArray.splice(0, underlyingArray.length);
195.1099 + this.valueHasMutated();
195.1100 + return allValues;
195.1101 + }
195.1102 + // If you passed an arg, we interpret it as an array of entries to remove
195.1103 + if (!arrayOfValues)
195.1104 + return [];
195.1105 + return this['remove'](function (value) {
195.1106 + return ko.utils.arrayIndexOf(arrayOfValues, value) >= 0;
195.1107 + });
195.1108 + },
195.1109 +
195.1110 + 'destroy': function (valueOrPredicate) {
195.1111 + var underlyingArray = this.peek();
195.1112 + var predicate = typeof valueOrPredicate == "function" ? valueOrPredicate : function (value) { return value === valueOrPredicate; };
195.1113 + this.valueWillMutate();
195.1114 + for (var i = underlyingArray.length - 1; i >= 0; i--) {
195.1115 + var value = underlyingArray[i];
195.1116 + if (predicate(value))
195.1117 + underlyingArray[i]["_destroy"] = true;
195.1118 + }
195.1119 + this.valueHasMutated();
195.1120 + },
195.1121 +
195.1122 + 'destroyAll': function (arrayOfValues) {
195.1123 + // If you passed zero args, we destroy everything
195.1124 + if (arrayOfValues === undefined)
195.1125 + return this['destroy'](function() { return true });
195.1126 +
195.1127 + // If you passed an arg, we interpret it as an array of entries to destroy
195.1128 + if (!arrayOfValues)
195.1129 + return [];
195.1130 + return this['destroy'](function (value) {
195.1131 + return ko.utils.arrayIndexOf(arrayOfValues, value) >= 0;
195.1132 + });
195.1133 + },
195.1134 +
195.1135 + 'indexOf': function (item) {
195.1136 + var underlyingArray = this();
195.1137 + return ko.utils.arrayIndexOf(underlyingArray, item);
195.1138 + },
195.1139 +
195.1140 + 'replace': function(oldItem, newItem) {
195.1141 + var index = this['indexOf'](oldItem);
195.1142 + if (index >= 0) {
195.1143 + this.valueWillMutate();
195.1144 + this.peek()[index] = newItem;
195.1145 + this.valueHasMutated();
195.1146 + }
195.1147 + }
195.1148 +}
195.1149 +
195.1150 +// Populate ko.observableArray.fn with read/write functions from native arrays
195.1151 +// Important: Do not add any additional functions here that may reasonably be used to *read* data from the array
195.1152 +// because we'll eval them without causing subscriptions, so ko.computed output could end up getting stale
195.1153 +ko.utils.arrayForEach(["pop", "push", "reverse", "shift", "sort", "splice", "unshift"], function (methodName) {
195.1154 + ko.observableArray['fn'][methodName] = function () {
195.1155 + // Use "peek" to avoid creating a subscription in any computed that we're executing in the context of
195.1156 + // (for consistency with mutating regular observables)
195.1157 + var underlyingArray = this.peek();
195.1158 + this.valueWillMutate();
195.1159 + var methodCallResult = underlyingArray[methodName].apply(underlyingArray, arguments);
195.1160 + this.valueHasMutated();
195.1161 + return methodCallResult;
195.1162 + };
195.1163 +});
195.1164 +
195.1165 +// Populate ko.observableArray.fn with read-only functions from native arrays
195.1166 +ko.utils.arrayForEach(["slice"], function (methodName) {
195.1167 + ko.observableArray['fn'][methodName] = function () {
195.1168 + var underlyingArray = this();
195.1169 + return underlyingArray[methodName].apply(underlyingArray, arguments);
195.1170 + };
195.1171 +});
195.1172 +
195.1173 +ko.exportSymbol('observableArray', ko.observableArray);
195.1174 +ko.dependentObservable = function (evaluatorFunctionOrOptions, evaluatorFunctionTarget, options) {
195.1175 + var _latestValue,
195.1176 + _hasBeenEvaluated = false,
195.1177 + _isBeingEvaluated = false,
195.1178 + readFunction = evaluatorFunctionOrOptions;
195.1179 +
195.1180 + if (readFunction && typeof readFunction == "object") {
195.1181 + // Single-parameter syntax - everything is on this "options" param
195.1182 + options = readFunction;
195.1183 + readFunction = options["read"];
195.1184 + } else {
195.1185 + // Multi-parameter syntax - construct the options according to the params passed
195.1186 + options = options || {};
195.1187 + if (!readFunction)
195.1188 + readFunction = options["read"];
195.1189 + }
195.1190 + if (typeof readFunction != "function")
195.1191 + throw new Error("Pass a function that returns the value of the ko.computed");
195.1192 +
195.1193 + function addSubscriptionToDependency(subscribable) {
195.1194 + _subscriptionsToDependencies.push(subscribable.subscribe(evaluatePossiblyAsync));
195.1195 + }
195.1196 +
195.1197 + function disposeAllSubscriptionsToDependencies() {
195.1198 + ko.utils.arrayForEach(_subscriptionsToDependencies, function (subscription) {
195.1199 + subscription.dispose();
195.1200 + });
195.1201 + _subscriptionsToDependencies = [];
195.1202 + }
195.1203 +
195.1204 + function evaluatePossiblyAsync() {
195.1205 + var throttleEvaluationTimeout = dependentObservable['throttleEvaluation'];
195.1206 + if (throttleEvaluationTimeout && throttleEvaluationTimeout >= 0) {
195.1207 + clearTimeout(evaluationTimeoutInstance);
195.1208 + evaluationTimeoutInstance = setTimeout(evaluateImmediate, throttleEvaluationTimeout);
195.1209 + } else
195.1210 + evaluateImmediate();
195.1211 + }
195.1212 +
195.1213 + function evaluateImmediate() {
195.1214 + if (_isBeingEvaluated) {
195.1215 + // If the evaluation of a ko.computed causes side effects, it's possible that it will trigger its own re-evaluation.
195.1216 + // This is not desirable (it's hard for a developer to realise a chain of dependencies might cause this, and they almost
195.1217 + // certainly didn't intend infinite re-evaluations). So, for predictability, we simply prevent ko.computeds from causing
195.1218 + // their own re-evaluation. Further discussion at https://github.com/SteveSanderson/knockout/pull/387
195.1219 + return;
195.1220 + }
195.1221 +
195.1222 + // Don't dispose on first evaluation, because the "disposeWhen" callback might
195.1223 + // e.g., dispose when the associated DOM element isn't in the doc, and it's not
195.1224 + // going to be in the doc until *after* the first evaluation
195.1225 + if (_hasBeenEvaluated && disposeWhen()) {
195.1226 + dispose();
195.1227 + return;
195.1228 + }
195.1229 +
195.1230 + _isBeingEvaluated = true;
195.1231 + try {
195.1232 + // Initially, we assume that none of the subscriptions are still being used (i.e., all are candidates for disposal).
195.1233 + // Then, during evaluation, we cross off any that are in fact still being used.
195.1234 + var disposalCandidates = ko.utils.arrayMap(_subscriptionsToDependencies, function(item) {return item.target;});
195.1235 +
195.1236 + ko.dependencyDetection.begin(function(subscribable) {
195.1237 + var inOld;
195.1238 + if ((inOld = ko.utils.arrayIndexOf(disposalCandidates, subscribable)) >= 0)
195.1239 + disposalCandidates[inOld] = undefined; // Don't want to dispose this subscription, as it's still being used
195.1240 + else
195.1241 + addSubscriptionToDependency(subscribable); // Brand new subscription - add it
195.1242 + });
195.1243 +
195.1244 + var newValue = readFunction.call(evaluatorFunctionTarget);
195.1245 +
195.1246 + // For each subscription no longer being used, remove it from the active subscriptions list and dispose it
195.1247 + for (var i = disposalCandidates.length - 1; i >= 0; i--) {
195.1248 + if (disposalCandidates[i])
195.1249 + _subscriptionsToDependencies.splice(i, 1)[0].dispose();
195.1250 + }
195.1251 + _hasBeenEvaluated = true;
195.1252 +
195.1253 + dependentObservable["notifySubscribers"](_latestValue, "beforeChange");
195.1254 + _latestValue = newValue;
195.1255 + if (DEBUG) dependentObservable._latestValue = _latestValue;
195.1256 + } finally {
195.1257 + ko.dependencyDetection.end();
195.1258 + }
195.1259 +
195.1260 + dependentObservable["notifySubscribers"](_latestValue);
195.1261 + _isBeingEvaluated = false;
195.1262 + if (!_subscriptionsToDependencies.length)
195.1263 + dispose();
195.1264 + }
195.1265 +
195.1266 + function dependentObservable() {
195.1267 + if (arguments.length > 0) {
195.1268 + if (typeof writeFunction === "function") {
195.1269 + // Writing a value
195.1270 + writeFunction.apply(evaluatorFunctionTarget, arguments);
195.1271 + } else {
195.1272 + throw new Error("Cannot write a value to a ko.computed unless you specify a 'write' option. If you wish to read the current value, don't pass any parameters.");
195.1273 + }
195.1274 + return this; // Permits chained assignments
195.1275 + } else {
195.1276 + // Reading the value
195.1277 + if (!_hasBeenEvaluated)
195.1278 + evaluateImmediate();
195.1279 + ko.dependencyDetection.registerDependency(dependentObservable);
195.1280 + return _latestValue;
195.1281 + }
195.1282 + }
195.1283 +
195.1284 + function peek() {
195.1285 + if (!_hasBeenEvaluated)
195.1286 + evaluateImmediate();
195.1287 + return _latestValue;
195.1288 + }
195.1289 +
195.1290 + function isActive() {
195.1291 + return !_hasBeenEvaluated || _subscriptionsToDependencies.length > 0;
195.1292 + }
195.1293 +
195.1294 + // By here, "options" is always non-null
195.1295 + var writeFunction = options["write"],
195.1296 + disposeWhenNodeIsRemoved = options["disposeWhenNodeIsRemoved"] || options.disposeWhenNodeIsRemoved || null,
195.1297 + disposeWhen = options["disposeWhen"] || options.disposeWhen || function() { return false; },
195.1298 + dispose = disposeAllSubscriptionsToDependencies,
195.1299 + _subscriptionsToDependencies = [],
195.1300 + evaluationTimeoutInstance = null;
195.1301 +
195.1302 + if (!evaluatorFunctionTarget)
195.1303 + evaluatorFunctionTarget = options["owner"];
195.1304 +
195.1305 + dependentObservable.peek = peek;
195.1306 + dependentObservable.getDependenciesCount = function () { return _subscriptionsToDependencies.length; };
195.1307 + dependentObservable.hasWriteFunction = typeof options["write"] === "function";
195.1308 + dependentObservable.dispose = function () { dispose(); };
195.1309 + dependentObservable.isActive = isActive;
195.1310 + dependentObservable.valueHasMutated = function() {
195.1311 + _hasBeenEvaluated = false;
195.1312 + evaluateImmediate();
195.1313 + };
195.1314 +
195.1315 + ko.subscribable.call(dependentObservable);
195.1316 + ko.utils.extend(dependentObservable, ko.dependentObservable['fn']);
195.1317 +
195.1318 + ko.exportProperty(dependentObservable, 'peek', dependentObservable.peek);
195.1319 + ko.exportProperty(dependentObservable, 'dispose', dependentObservable.dispose);
195.1320 + ko.exportProperty(dependentObservable, 'isActive', dependentObservable.isActive);
195.1321 + ko.exportProperty(dependentObservable, 'getDependenciesCount', dependentObservable.getDependenciesCount);
195.1322 +
195.1323 + // Evaluate, unless deferEvaluation is true
195.1324 + if (options['deferEvaluation'] !== true)
195.1325 + evaluateImmediate();
195.1326 +
195.1327 + // Build "disposeWhenNodeIsRemoved" and "disposeWhenNodeIsRemovedCallback" option values.
195.1328 + // But skip if isActive is false (there will never be any dependencies to dispose).
195.1329 + // (Note: "disposeWhenNodeIsRemoved" option both proactively disposes as soon as the node is removed using ko.removeNode(),
195.1330 + // plus adds a "disposeWhen" callback that, on each evaluation, disposes if the node was removed by some other means.)
195.1331 + if (disposeWhenNodeIsRemoved && isActive()) {
195.1332 + dispose = function() {
195.1333 + ko.utils.domNodeDisposal.removeDisposeCallback(disposeWhenNodeIsRemoved, arguments.callee);
195.1334 + disposeAllSubscriptionsToDependencies();
195.1335 + };
195.1336 + ko.utils.domNodeDisposal.addDisposeCallback(disposeWhenNodeIsRemoved, dispose);
195.1337 + var existingDisposeWhenFunction = disposeWhen;
195.1338 + disposeWhen = function () {
195.1339 + return !ko.utils.domNodeIsAttachedToDocument(disposeWhenNodeIsRemoved) || existingDisposeWhenFunction();
195.1340 + }
195.1341 + }
195.1342 +
195.1343 + return dependentObservable;
195.1344 +};
195.1345 +
195.1346 +ko.isComputed = function(instance) {
195.1347 + return ko.hasPrototype(instance, ko.dependentObservable);
195.1348 +};
195.1349 +
195.1350 +var protoProp = ko.observable.protoProperty; // == "__ko_proto__"
195.1351 +ko.dependentObservable[protoProp] = ko.observable;
195.1352 +
195.1353 +ko.dependentObservable['fn'] = {};
195.1354 +ko.dependentObservable['fn'][protoProp] = ko.dependentObservable;
195.1355 +
195.1356 +ko.exportSymbol('dependentObservable', ko.dependentObservable);
195.1357 +ko.exportSymbol('computed', ko.dependentObservable); // Make "ko.computed" an alias for "ko.dependentObservable"
195.1358 +ko.exportSymbol('isComputed', ko.isComputed);
195.1359 +
195.1360 +(function() {
195.1361 + var maxNestedObservableDepth = 10; // Escape the (unlikely) pathalogical case where an observable's current value is itself (or similar reference cycle)
195.1362 +
195.1363 + ko.toJS = function(rootObject) {
195.1364 + if (arguments.length == 0)
195.1365 + throw new Error("When calling ko.toJS, pass the object you want to convert.");
195.1366 +
195.1367 + // We just unwrap everything at every level in the object graph
195.1368 + return mapJsObjectGraph(rootObject, function(valueToMap) {
195.1369 + // Loop because an observable's value might in turn be another observable wrapper
195.1370 + for (var i = 0; ko.isObservable(valueToMap) && (i < maxNestedObservableDepth); i++)
195.1371 + valueToMap = valueToMap();
195.1372 + return valueToMap;
195.1373 + });
195.1374 + };
195.1375 +
195.1376 + ko.toJSON = function(rootObject, replacer, space) { // replacer and space are optional
195.1377 + var plainJavaScriptObject = ko.toJS(rootObject);
195.1378 + return ko.utils.stringifyJson(plainJavaScriptObject, replacer, space);
195.1379 + };
195.1380 +
195.1381 + function mapJsObjectGraph(rootObject, mapInputCallback, visitedObjects) {
195.1382 + visitedObjects = visitedObjects || new objectLookup();
195.1383 +
195.1384 + rootObject = mapInputCallback(rootObject);
195.1385 + var canHaveProperties = (typeof rootObject == "object") && (rootObject !== null) && (rootObject !== undefined) && (!(rootObject instanceof Date));
195.1386 + if (!canHaveProperties)
195.1387 + return rootObject;
195.1388 +
195.1389 + var outputProperties = rootObject instanceof Array ? [] : {};
195.1390 + visitedObjects.save(rootObject, outputProperties);
195.1391 +
195.1392 + visitPropertiesOrArrayEntries(rootObject, function(indexer) {
195.1393 + var propertyValue = mapInputCallback(rootObject[indexer]);
195.1394 +
195.1395 + switch (typeof propertyValue) {
195.1396 + case "boolean":
195.1397 + case "number":
195.1398 + case "string":
195.1399 + case "function":
195.1400 + outputProperties[indexer] = propertyValue;
195.1401 + break;
195.1402 + case "object":
195.1403 + case "undefined":
195.1404 + var previouslyMappedValue = visitedObjects.get(propertyValue);
195.1405 + outputProperties[indexer] = (previouslyMappedValue !== undefined)
195.1406 + ? previouslyMappedValue
195.1407 + : mapJsObjectGraph(propertyValue, mapInputCallback, visitedObjects);
195.1408 + break;
195.1409 + }
195.1410 + });
195.1411 +
195.1412 + return outputProperties;
195.1413 + }
195.1414 +
195.1415 + function visitPropertiesOrArrayEntries(rootObject, visitorCallback) {
195.1416 + if (rootObject instanceof Array) {
195.1417 + for (var i = 0; i < rootObject.length; i++)
195.1418 + visitorCallback(i);
195.1419 +
195.1420 + // For arrays, also respect toJSON property for custom mappings (fixes #278)
195.1421 + if (typeof rootObject['toJSON'] == 'function')
195.1422 + visitorCallback('toJSON');
195.1423 + } else {
195.1424 + for (var propertyName in rootObject)
195.1425 + visitorCallback(propertyName);
195.1426 + }
195.1427 + };
195.1428 +
195.1429 + function objectLookup() {
195.1430 + var keys = [];
195.1431 + var values = [];
195.1432 + this.save = function(key, value) {
195.1433 + var existingIndex = ko.utils.arrayIndexOf(keys, key);
195.1434 + if (existingIndex >= 0)
195.1435 + values[existingIndex] = value;
195.1436 + else {
195.1437 + keys.push(key);
195.1438 + values.push(value);
195.1439 + }
195.1440 + };
195.1441 + this.get = function(key) {
195.1442 + var existingIndex = ko.utils.arrayIndexOf(keys, key);
195.1443 + return (existingIndex >= 0) ? values[existingIndex] : undefined;
195.1444 + };
195.1445 + };
195.1446 +})();
195.1447 +
195.1448 +ko.exportSymbol('toJS', ko.toJS);
195.1449 +ko.exportSymbol('toJSON', ko.toJSON);
195.1450 +(function () {
195.1451 + var hasDomDataExpandoProperty = '__ko__hasDomDataOptionValue__';
195.1452 +
195.1453 + // Normally, SELECT elements and their OPTIONs can only take value of type 'string' (because the values
195.1454 + // are stored on DOM attributes). ko.selectExtensions provides a way for SELECTs/OPTIONs to have values
195.1455 + // that are arbitrary objects. This is very convenient when implementing things like cascading dropdowns.
195.1456 + ko.selectExtensions = {
195.1457 + readValue : function(element) {
195.1458 + switch (ko.utils.tagNameLower(element)) {
195.1459 + case 'option':
195.1460 + if (element[hasDomDataExpandoProperty] === true)
195.1461 + return ko.utils.domData.get(element, ko.bindingHandlers.options.optionValueDomDataKey);
195.1462 + return ko.utils.ieVersion <= 7
195.1463 + ? (element.getAttributeNode('value').specified ? element.value : element.text)
195.1464 + : element.value;
195.1465 + case 'select':
195.1466 + return element.selectedIndex >= 0 ? ko.selectExtensions.readValue(element.options[element.selectedIndex]) : undefined;
195.1467 + default:
195.1468 + return element.value;
195.1469 + }
195.1470 + },
195.1471 +
195.1472 + writeValue: function(element, value) {
195.1473 + switch (ko.utils.tagNameLower(element)) {
195.1474 + case 'option':
195.1475 + switch(typeof value) {
195.1476 + case "string":
195.1477 + ko.utils.domData.set(element, ko.bindingHandlers.options.optionValueDomDataKey, undefined);
195.1478 + if (hasDomDataExpandoProperty in element) { // IE <= 8 throws errors if you delete non-existent properties from a DOM node
195.1479 + delete element[hasDomDataExpandoProperty];
195.1480 + }
195.1481 + element.value = value;
195.1482 + break;
195.1483 + default:
195.1484 + // Store arbitrary object using DomData
195.1485 + ko.utils.domData.set(element, ko.bindingHandlers.options.optionValueDomDataKey, value);
195.1486 + element[hasDomDataExpandoProperty] = true;
195.1487 +
195.1488 + // Special treatment of numbers is just for backward compatibility. KO 1.2.1 wrote numerical values to element.value.
195.1489 + element.value = typeof value === "number" ? value : "";
195.1490 + break;
195.1491 + }
195.1492 + break;
195.1493 + case 'select':
195.1494 + for (var i = element.options.length - 1; i >= 0; i--) {
195.1495 + if (ko.selectExtensions.readValue(element.options[i]) == value) {
195.1496 + element.selectedIndex = i;
195.1497 + break;
195.1498 + }
195.1499 + }
195.1500 + break;
195.1501 + default:
195.1502 + if ((value === null) || (value === undefined))
195.1503 + value = "";
195.1504 + element.value = value;
195.1505 + break;
195.1506 + }
195.1507 + }
195.1508 + };
195.1509 +})();
195.1510 +
195.1511 +ko.exportSymbol('selectExtensions', ko.selectExtensions);
195.1512 +ko.exportSymbol('selectExtensions.readValue', ko.selectExtensions.readValue);
195.1513 +ko.exportSymbol('selectExtensions.writeValue', ko.selectExtensions.writeValue);
195.1514 +ko.expressionRewriting = (function () {
195.1515 + var restoreCapturedTokensRegex = /\@ko_token_(\d+)\@/g;
195.1516 + var javaScriptReservedWords = ["true", "false"];
195.1517 +
195.1518 + // Matches something that can be assigned to--either an isolated identifier or something ending with a property accessor
195.1519 + // This is designed to be simple and avoid false negatives, but could produce false positives (e.g., a+b.c).
195.1520 + var javaScriptAssignmentTarget = /^(?:[$_a-z][$\w]*|(.+)(\.\s*[$_a-z][$\w]*|\[.+\]))$/i;
195.1521 +
195.1522 + function restoreTokens(string, tokens) {
195.1523 + var prevValue = null;
195.1524 + while (string != prevValue) { // Keep restoring tokens until it no longer makes a difference (they may be nested)
195.1525 + prevValue = string;
195.1526 + string = string.replace(restoreCapturedTokensRegex, function (match, tokenIndex) {
195.1527 + return tokens[tokenIndex];
195.1528 + });
195.1529 + }
195.1530 + return string;
195.1531 + }
195.1532 +
195.1533 + function getWriteableValue(expression) {
195.1534 + if (ko.utils.arrayIndexOf(javaScriptReservedWords, ko.utils.stringTrim(expression).toLowerCase()) >= 0)
195.1535 + return false;
195.1536 + var match = expression.match(javaScriptAssignmentTarget);
195.1537 + return match === null ? false : match[1] ? ('Object(' + match[1] + ')' + match[2]) : expression;
195.1538 + }
195.1539 +
195.1540 + function ensureQuoted(key) {
195.1541 + var trimmedKey = ko.utils.stringTrim(key);
195.1542 + switch (trimmedKey.length && trimmedKey.charAt(0)) {
195.1543 + case "'":
195.1544 + case '"':
195.1545 + return key;
195.1546 + default:
195.1547 + return "'" + trimmedKey + "'";
195.1548 + }
195.1549 + }
195.1550 +
195.1551 + return {
195.1552 + bindingRewriteValidators: [],
195.1553 +
195.1554 + parseObjectLiteral: function(objectLiteralString) {
195.1555 + // A full tokeniser+lexer would add too much weight to this library, so here's a simple parser
195.1556 + // that is sufficient just to split an object literal string into a set of top-level key-value pairs
195.1557 +
195.1558 + var str = ko.utils.stringTrim(objectLiteralString);
195.1559 + if (str.length < 3)
195.1560 + return [];
195.1561 + if (str.charAt(0) === "{")// Ignore any braces surrounding the whole object literal
195.1562 + str = str.substring(1, str.length - 1);
195.1563 +
195.1564 + // Pull out any string literals and regex literals
195.1565 + var tokens = [];
195.1566 + var tokenStart = null, tokenEndChar;
195.1567 + for (var position = 0; position < str.length; position++) {
195.1568 + var c = str.charAt(position);
195.1569 + if (tokenStart === null) {
195.1570 + switch (c) {
195.1571 + case '"':
195.1572 + case "'":
195.1573 + case "/":
195.1574 + tokenStart = position;
195.1575 + tokenEndChar = c;
195.1576 + break;
195.1577 + }
195.1578 + } else if ((c == tokenEndChar) && (str.charAt(position - 1) !== "\\")) {
195.1579 + var token = str.substring(tokenStart, position + 1);
195.1580 + tokens.push(token);
195.1581 + var replacement = "@ko_token_" + (tokens.length - 1) + "@";
195.1582 + str = str.substring(0, tokenStart) + replacement + str.substring(position + 1);
195.1583 + position -= (token.length - replacement.length);
195.1584 + tokenStart = null;
195.1585 + }
195.1586 + }
195.1587 +
195.1588 + // Next pull out balanced paren, brace, and bracket blocks
195.1589 + tokenStart = null;
195.1590 + tokenEndChar = null;
195.1591 + var tokenDepth = 0, tokenStartChar = null;
195.1592 + for (var position = 0; position < str.length; position++) {
195.1593 + var c = str.charAt(position);
195.1594 + if (tokenStart === null) {
195.1595 + switch (c) {
195.1596 + case "{": tokenStart = position; tokenStartChar = c;
195.1597 + tokenEndChar = "}";
195.1598 + break;
195.1599 + case "(": tokenStart = position; tokenStartChar = c;
195.1600 + tokenEndChar = ")";
195.1601 + break;
195.1602 + case "[": tokenStart = position; tokenStartChar = c;
195.1603 + tokenEndChar = "]";
195.1604 + break;
195.1605 + }
195.1606 + }
195.1607 +
195.1608 + if (c === tokenStartChar)
195.1609 + tokenDepth++;
195.1610 + else if (c === tokenEndChar) {
195.1611 + tokenDepth--;
195.1612 + if (tokenDepth === 0) {
195.1613 + var token = str.substring(tokenStart, position + 1);
195.1614 + tokens.push(token);
195.1615 + var replacement = "@ko_token_" + (tokens.length - 1) + "@";
195.1616 + str = str.substring(0, tokenStart) + replacement + str.substring(position + 1);
195.1617 + position -= (token.length - replacement.length);
195.1618 + tokenStart = null;
195.1619 + }
195.1620 + }
195.1621 + }
195.1622 +
195.1623 + // Now we can safely split on commas to get the key/value pairs
195.1624 + var result = [];
195.1625 + var keyValuePairs = str.split(",");
195.1626 + for (var i = 0, j = keyValuePairs.length; i < j; i++) {
195.1627 + var pair = keyValuePairs[i];
195.1628 + var colonPos = pair.indexOf(":");
195.1629 + if ((colonPos > 0) && (colonPos < pair.length - 1)) {
195.1630 + var key = pair.substring(0, colonPos);
195.1631 + var value = pair.substring(colonPos + 1);
195.1632 + result.push({ 'key': restoreTokens(key, tokens), 'value': restoreTokens(value, tokens) });
195.1633 + } else {
195.1634 + result.push({ 'unknown': restoreTokens(pair, tokens) });
195.1635 + }
195.1636 + }
195.1637 + return result;
195.1638 + },
195.1639 +
195.1640 + preProcessBindings: function (objectLiteralStringOrKeyValueArray) {
195.1641 + var keyValueArray = typeof objectLiteralStringOrKeyValueArray === "string"
195.1642 + ? ko.expressionRewriting.parseObjectLiteral(objectLiteralStringOrKeyValueArray)
195.1643 + : objectLiteralStringOrKeyValueArray;
195.1644 + var resultStrings = [], propertyAccessorResultStrings = [];
195.1645 +
195.1646 + var keyValueEntry;
195.1647 + for (var i = 0; keyValueEntry = keyValueArray[i]; i++) {
195.1648 + if (resultStrings.length > 0)
195.1649 + resultStrings.push(",");
195.1650 +
195.1651 + if (keyValueEntry['key']) {
195.1652 + var quotedKey = ensureQuoted(keyValueEntry['key']), val = keyValueEntry['value'];
195.1653 + resultStrings.push(quotedKey);
195.1654 + resultStrings.push(":");
195.1655 + resultStrings.push(val);
195.1656 +
195.1657 + if (val = getWriteableValue(ko.utils.stringTrim(val))) {
195.1658 + if (propertyAccessorResultStrings.length > 0)
195.1659 + propertyAccessorResultStrings.push(", ");
195.1660 + propertyAccessorResultStrings.push(quotedKey + " : function(__ko_value) { " + val + " = __ko_value; }");
195.1661 + }
195.1662 + } else if (keyValueEntry['unknown']) {
195.1663 + resultStrings.push(keyValueEntry['unknown']);
195.1664 + }
195.1665 + }
195.1666 +
195.1667 + var combinedResult = resultStrings.join("");
195.1668 + if (propertyAccessorResultStrings.length > 0) {
195.1669 + var allPropertyAccessors = propertyAccessorResultStrings.join("");
195.1670 + combinedResult = combinedResult + ", '_ko_property_writers' : { " + allPropertyAccessors + " } ";
195.1671 + }
195.1672 +
195.1673 + return combinedResult;
195.1674 + },
195.1675 +
195.1676 + keyValueArrayContainsKey: function(keyValueArray, key) {
195.1677 + for (var i = 0; i < keyValueArray.length; i++)
195.1678 + if (ko.utils.stringTrim(keyValueArray[i]['key']) == key)
195.1679 + return true;
195.1680 + return false;
195.1681 + },
195.1682 +
195.1683 + // Internal, private KO utility for updating model properties from within bindings
195.1684 + // property: If the property being updated is (or might be) an observable, pass it here
195.1685 + // If it turns out to be a writable observable, it will be written to directly
195.1686 + // allBindingsAccessor: All bindings in the current execution context.
195.1687 + // This will be searched for a '_ko_property_writers' property in case you're writing to a non-observable
195.1688 + // key: The key identifying the property to be written. Example: for { hasFocus: myValue }, write to 'myValue' by specifying the key 'hasFocus'
195.1689 + // value: The value to be written
195.1690 + // checkIfDifferent: If true, and if the property being written is a writable observable, the value will only be written if
195.1691 + // it is !== existing value on that writable observable
195.1692 + writeValueToProperty: function(property, allBindingsAccessor, key, value, checkIfDifferent) {
195.1693 + if (!property || !ko.isWriteableObservable(property)) {
195.1694 + var propWriters = allBindingsAccessor()['_ko_property_writers'];
195.1695 + if (propWriters && propWriters[key])
195.1696 + propWriters[key](value);
195.1697 + } else if (!checkIfDifferent || property.peek() !== value) {
195.1698 + property(value);
195.1699 + }
195.1700 + }
195.1701 + };
195.1702 +})();
195.1703 +
195.1704 +ko.exportSymbol('expressionRewriting', ko.expressionRewriting);
195.1705 +ko.exportSymbol('expressionRewriting.bindingRewriteValidators', ko.expressionRewriting.bindingRewriteValidators);
195.1706 +ko.exportSymbol('expressionRewriting.parseObjectLiteral', ko.expressionRewriting.parseObjectLiteral);
195.1707 +ko.exportSymbol('expressionRewriting.preProcessBindings', ko.expressionRewriting.preProcessBindings);
195.1708 +
195.1709 +// For backward compatibility, define the following aliases. (Previously, these function names were misleading because
195.1710 +// they referred to JSON specifically, even though they actually work with arbitrary JavaScript object literal expressions.)
195.1711 +ko.exportSymbol('jsonExpressionRewriting', ko.expressionRewriting);
195.1712 +ko.exportSymbol('jsonExpressionRewriting.insertPropertyAccessorsIntoJson', ko.expressionRewriting.preProcessBindings);(function() {
195.1713 + // "Virtual elements" is an abstraction on top of the usual DOM API which understands the notion that comment nodes
195.1714 + // may be used to represent hierarchy (in addition to the DOM's natural hierarchy).
195.1715 + // If you call the DOM-manipulating functions on ko.virtualElements, you will be able to read and write the state
195.1716 + // of that virtual hierarchy
195.1717 + //
195.1718 + // The point of all this is to support containerless templates (e.g., <!-- ko foreach:someCollection -->blah<!-- /ko -->)
195.1719 + // without having to scatter special cases all over the binding and templating code.
195.1720 +
195.1721 + // IE 9 cannot reliably read the "nodeValue" property of a comment node (see https://github.com/SteveSanderson/knockout/issues/186)
195.1722 + // but it does give them a nonstandard alternative property called "text" that it can read reliably. Other browsers don't have that property.
195.1723 + // So, use node.text where available, and node.nodeValue elsewhere
195.1724 + var commentNodesHaveTextProperty = document.createComment("test").text === "<!--test-->";
195.1725 +
195.1726 + var startCommentRegex = commentNodesHaveTextProperty ? /^<!--\s*ko(?:\s+(.+\s*\:[\s\S]*))?\s*-->$/ : /^\s*ko(?:\s+(.+\s*\:[\s\S]*))?\s*$/;
195.1727 + var endCommentRegex = commentNodesHaveTextProperty ? /^<!--\s*\/ko\s*-->$/ : /^\s*\/ko\s*$/;
195.1728 + var htmlTagsWithOptionallyClosingChildren = { 'ul': true, 'ol': true };
195.1729 +
195.1730 + function isStartComment(node) {
195.1731 + return (node.nodeType == 8) && (commentNodesHaveTextProperty ? node.text : node.nodeValue).match(startCommentRegex);
195.1732 + }
195.1733 +
195.1734 + function isEndComment(node) {
195.1735 + return (node.nodeType == 8) && (commentNodesHaveTextProperty ? node.text : node.nodeValue).match(endCommentRegex);
195.1736 + }
195.1737 +
195.1738 + function getVirtualChildren(startComment, allowUnbalanced) {
195.1739 + var currentNode = startComment;
195.1740 + var depth = 1;
195.1741 + var children = [];
195.1742 + while (currentNode = currentNode.nextSibling) {
195.1743 + if (isEndComment(currentNode)) {
195.1744 + depth--;
195.1745 + if (depth === 0)
195.1746 + return children;
195.1747 + }
195.1748 +
195.1749 + children.push(currentNode);
195.1750 +
195.1751 + if (isStartComment(currentNode))
195.1752 + depth++;
195.1753 + }
195.1754 + if (!allowUnbalanced)
195.1755 + throw new Error("Cannot find closing comment tag to match: " + startComment.nodeValue);
195.1756 + return null;
195.1757 + }
195.1758 +
195.1759 + function getMatchingEndComment(startComment, allowUnbalanced) {
195.1760 + var allVirtualChildren = getVirtualChildren(startComment, allowUnbalanced);
195.1761 + if (allVirtualChildren) {
195.1762 + if (allVirtualChildren.length > 0)
195.1763 + return allVirtualChildren[allVirtualChildren.length - 1].nextSibling;
195.1764 + return startComment.nextSibling;
195.1765 + } else
195.1766 + return null; // Must have no matching end comment, and allowUnbalanced is true
195.1767 + }
195.1768 +
195.1769 + function getUnbalancedChildTags(node) {
195.1770 + // e.g., from <div>OK</div><!-- ko blah --><span>Another</span>, returns: <!-- ko blah --><span>Another</span>
195.1771 + // from <div>OK</div><!-- /ko --><!-- /ko -->, returns: <!-- /ko --><!-- /ko -->
195.1772 + var childNode = node.firstChild, captureRemaining = null;
195.1773 + if (childNode) {
195.1774 + do {
195.1775 + if (captureRemaining) // We already hit an unbalanced node and are now just scooping up all subsequent nodes
195.1776 + captureRemaining.push(childNode);
195.1777 + else if (isStartComment(childNode)) {
195.1778 + var matchingEndComment = getMatchingEndComment(childNode, /* allowUnbalanced: */ true);
195.1779 + if (matchingEndComment) // It's a balanced tag, so skip immediately to the end of this virtual set
195.1780 + childNode = matchingEndComment;
195.1781 + else
195.1782 + captureRemaining = [childNode]; // It's unbalanced, so start capturing from this point
195.1783 + } else if (isEndComment(childNode)) {
195.1784 + captureRemaining = [childNode]; // It's unbalanced (if it wasn't, we'd have skipped over it already), so start capturing
195.1785 + }
195.1786 + } while (childNode = childNode.nextSibling);
195.1787 + }
195.1788 + return captureRemaining;
195.1789 + }
195.1790 +
195.1791 + ko.virtualElements = {
195.1792 + allowedBindings: {},
195.1793 +
195.1794 + childNodes: function(node) {
195.1795 + return isStartComment(node) ? getVirtualChildren(node) : node.childNodes;
195.1796 + },
195.1797 +
195.1798 + emptyNode: function(node) {
195.1799 + if (!isStartComment(node))
195.1800 + ko.utils.emptyDomNode(node);
195.1801 + else {
195.1802 + var virtualChildren = ko.virtualElements.childNodes(node);
195.1803 + for (var i = 0, j = virtualChildren.length; i < j; i++)
195.1804 + ko.removeNode(virtualChildren[i]);
195.1805 + }
195.1806 + },
195.1807 +
195.1808 + setDomNodeChildren: function(node, childNodes) {
195.1809 + if (!isStartComment(node))
195.1810 + ko.utils.setDomNodeChildren(node, childNodes);
195.1811 + else {
195.1812 + ko.virtualElements.emptyNode(node);
195.1813 + var endCommentNode = node.nextSibling; // Must be the next sibling, as we just emptied the children
195.1814 + for (var i = 0, j = childNodes.length; i < j; i++)
195.1815 + endCommentNode.parentNode.insertBefore(childNodes[i], endCommentNode);
195.1816 + }
195.1817 + },
195.1818 +
195.1819 + prepend: function(containerNode, nodeToPrepend) {
195.1820 + if (!isStartComment(containerNode)) {
195.1821 + if (containerNode.firstChild)
195.1822 + containerNode.insertBefore(nodeToPrepend, containerNode.firstChild);
195.1823 + else
195.1824 + containerNode.appendChild(nodeToPrepend);
195.1825 + } else {
195.1826 + // Start comments must always have a parent and at least one following sibling (the end comment)
195.1827 + containerNode.parentNode.insertBefore(nodeToPrepend, containerNode.nextSibling);
195.1828 + }
195.1829 + },
195.1830 +
195.1831 + insertAfter: function(containerNode, nodeToInsert, insertAfterNode) {
195.1832 + if (!insertAfterNode) {
195.1833 + ko.virtualElements.prepend(containerNode, nodeToInsert);
195.1834 + } else if (!isStartComment(containerNode)) {
195.1835 + // Insert after insertion point
195.1836 + if (insertAfterNode.nextSibling)
195.1837 + containerNode.insertBefore(nodeToInsert, insertAfterNode.nextSibling);
195.1838 + else
195.1839 + containerNode.appendChild(nodeToInsert);
195.1840 + } else {
195.1841 + // Children of start comments must always have a parent and at least one following sibling (the end comment)
195.1842 + containerNode.parentNode.insertBefore(nodeToInsert, insertAfterNode.nextSibling);
195.1843 + }
195.1844 + },
195.1845 +
195.1846 + firstChild: function(node) {
195.1847 + if (!isStartComment(node))
195.1848 + return node.firstChild;
195.1849 + if (!node.nextSibling || isEndComment(node.nextSibling))
195.1850 + return null;
195.1851 + return node.nextSibling;
195.1852 + },
195.1853 +
195.1854 + nextSibling: function(node) {
195.1855 + if (isStartComment(node))
195.1856 + node = getMatchingEndComment(node);
195.1857 + if (node.nextSibling && isEndComment(node.nextSibling))
195.1858 + return null;
195.1859 + return node.nextSibling;
195.1860 + },
195.1861 +
195.1862 + virtualNodeBindingValue: function(node) {
195.1863 + var regexMatch = isStartComment(node);
195.1864 + return regexMatch ? regexMatch[1] : null;
195.1865 + },
195.1866 +
195.1867 + normaliseVirtualElementDomStructure: function(elementVerified) {
195.1868 + // Workaround for https://github.com/SteveSanderson/knockout/issues/155
195.1869 + // (IE <= 8 or IE 9 quirks mode parses your HTML weirdly, treating closing </li> tags as if they don't exist, thereby moving comment nodes
195.1870 + // that are direct descendants of <ul> into the preceding <li>)
195.1871 + if (!htmlTagsWithOptionallyClosingChildren[ko.utils.tagNameLower(elementVerified)])
195.1872 + return;
195.1873 +
195.1874 + // Scan immediate children to see if they contain unbalanced comment tags. If they do, those comment tags
195.1875 + // must be intended to appear *after* that child, so move them there.
195.1876 + var childNode = elementVerified.firstChild;
195.1877 + if (childNode) {
195.1878 + do {
195.1879 + if (childNode.nodeType === 1) {
195.1880 + var unbalancedTags = getUnbalancedChildTags(childNode);
195.1881 + if (unbalancedTags) {
195.1882 + // Fix up the DOM by moving the unbalanced tags to where they most likely were intended to be placed - *after* the child
195.1883 + var nodeToInsertBefore = childNode.nextSibling;
195.1884 + for (var i = 0; i < unbalancedTags.length; i++) {
195.1885 + if (nodeToInsertBefore)
195.1886 + elementVerified.insertBefore(unbalancedTags[i], nodeToInsertBefore);
195.1887 + else
195.1888 + elementVerified.appendChild(unbalancedTags[i]);
195.1889 + }
195.1890 + }
195.1891 + }
195.1892 + } while (childNode = childNode.nextSibling);
195.1893 + }
195.1894 + }
195.1895 + };
195.1896 +})();
195.1897 +ko.exportSymbol('virtualElements', ko.virtualElements);
195.1898 +ko.exportSymbol('virtualElements.allowedBindings', ko.virtualElements.allowedBindings);
195.1899 +ko.exportSymbol('virtualElements.emptyNode', ko.virtualElements.emptyNode);
195.1900 +//ko.exportSymbol('virtualElements.firstChild', ko.virtualElements.firstChild); // firstChild is not minified
195.1901 +ko.exportSymbol('virtualElements.insertAfter', ko.virtualElements.insertAfter);
195.1902 +//ko.exportSymbol('virtualElements.nextSibling', ko.virtualElements.nextSibling); // nextSibling is not minified
195.1903 +ko.exportSymbol('virtualElements.prepend', ko.virtualElements.prepend);
195.1904 +ko.exportSymbol('virtualElements.setDomNodeChildren', ko.virtualElements.setDomNodeChildren);
195.1905 +(function() {
195.1906 + var defaultBindingAttributeName = "data-bind";
195.1907 +
195.1908 + ko.bindingProvider = function() {
195.1909 + this.bindingCache = {};
195.1910 + };
195.1911 +
195.1912 + ko.utils.extend(ko.bindingProvider.prototype, {
195.1913 + 'nodeHasBindings': function(node) {
195.1914 + switch (node.nodeType) {
195.1915 + case 1: return node.getAttribute(defaultBindingAttributeName) != null; // Element
195.1916 + case 8: return ko.virtualElements.virtualNodeBindingValue(node) != null; // Comment node
195.1917 + default: return false;
195.1918 + }
195.1919 + },
195.1920 +
195.1921 + 'getBindings': function(node, bindingContext) {
195.1922 + var bindingsString = this['getBindingsString'](node, bindingContext);
195.1923 + return bindingsString ? this['parseBindingsString'](bindingsString, bindingContext, node) : null;
195.1924 + },
195.1925 +
195.1926 + // The following function is only used internally by this default provider.
195.1927 + // It's not part of the interface definition for a general binding provider.
195.1928 + 'getBindingsString': function(node, bindingContext) {
195.1929 + switch (node.nodeType) {
195.1930 + case 1: return node.getAttribute(defaultBindingAttributeName); // Element
195.1931 + case 8: return ko.virtualElements.virtualNodeBindingValue(node); // Comment node
195.1932 + default: return null;
195.1933 + }
195.1934 + },
195.1935 +
195.1936 + // The following function is only used internally by this default provider.
195.1937 + // It's not part of the interface definition for a general binding provider.
195.1938 + 'parseBindingsString': function(bindingsString, bindingContext, node) {
195.1939 + try {
195.1940 + var bindingFunction = createBindingsStringEvaluatorViaCache(bindingsString, this.bindingCache);
195.1941 + return bindingFunction(bindingContext, node);
195.1942 + } catch (ex) {
195.1943 + throw new Error("Unable to parse bindings.\nMessage: " + ex + ";\nBindings value: " + bindingsString);
195.1944 + }
195.1945 + }
195.1946 + });
195.1947 +
195.1948 + ko.bindingProvider['instance'] = new ko.bindingProvider();
195.1949 +
195.1950 + function createBindingsStringEvaluatorViaCache(bindingsString, cache) {
195.1951 + var cacheKey = bindingsString;
195.1952 + return cache[cacheKey]
195.1953 + || (cache[cacheKey] = createBindingsStringEvaluator(bindingsString));
195.1954 + }
195.1955 +
195.1956 + function createBindingsStringEvaluator(bindingsString) {
195.1957 + // Build the source for a function that evaluates "expression"
195.1958 + // For each scope variable, add an extra level of "with" nesting
195.1959 + // Example result: with(sc1) { with(sc0) { return (expression) } }
195.1960 + var rewrittenBindings = ko.expressionRewriting.preProcessBindings(bindingsString),
195.1961 + functionBody = "with($context){with($data||{}){return{" + rewrittenBindings + "}}}";
195.1962 + return new Function("$context", "$element", functionBody);
195.1963 + }
195.1964 +})();
195.1965 +
195.1966 +ko.exportSymbol('bindingProvider', ko.bindingProvider);
195.1967 +(function () {
195.1968 + ko.bindingHandlers = {};
195.1969 +
195.1970 + ko.bindingContext = function(dataItem, parentBindingContext, dataItemAlias) {
195.1971 + if (parentBindingContext) {
195.1972 + ko.utils.extend(this, parentBindingContext); // Inherit $root and any custom properties
195.1973 + this['$parentContext'] = parentBindingContext;
195.1974 + this['$parent'] = parentBindingContext['$data'];
195.1975 + this['$parents'] = (parentBindingContext['$parents'] || []).slice(0);
195.1976 + this['$parents'].unshift(this['$parent']);
195.1977 + } else {
195.1978 + this['$parents'] = [];
195.1979 + this['$root'] = dataItem;
195.1980 + // Export 'ko' in the binding context so it will be available in bindings and templates
195.1981 + // even if 'ko' isn't exported as a global, such as when using an AMD loader.
195.1982 + // See https://github.com/SteveSanderson/knockout/issues/490
195.1983 + this['ko'] = ko;
195.1984 + }
195.1985 + this['$data'] = dataItem;
195.1986 + if (dataItemAlias)
195.1987 + this[dataItemAlias] = dataItem;
195.1988 + }
195.1989 + ko.bindingContext.prototype['createChildContext'] = function (dataItem, dataItemAlias) {
195.1990 + return new ko.bindingContext(dataItem, this, dataItemAlias);
195.1991 + };
195.1992 + ko.bindingContext.prototype['extend'] = function(properties) {
195.1993 + var clone = ko.utils.extend(new ko.bindingContext(), this);
195.1994 + return ko.utils.extend(clone, properties);
195.1995 + };
195.1996 +
195.1997 + function validateThatBindingIsAllowedForVirtualElements(bindingName) {
195.1998 + var validator = ko.virtualElements.allowedBindings[bindingName];
195.1999 + if (!validator)
195.2000 + throw new Error("The binding '" + bindingName + "' cannot be used with virtual elements")
195.2001 + }
195.2002 +
195.2003 + function applyBindingsToDescendantsInternal (viewModel, elementOrVirtualElement, bindingContextsMayDifferFromDomParentElement) {
195.2004 + var currentChild, nextInQueue = ko.virtualElements.firstChild(elementOrVirtualElement);
195.2005 + while (currentChild = nextInQueue) {
195.2006 + // Keep a record of the next child *before* applying bindings, in case the binding removes the current child from its position
195.2007 + nextInQueue = ko.virtualElements.nextSibling(currentChild);
195.2008 + applyBindingsToNodeAndDescendantsInternal(viewModel, currentChild, bindingContextsMayDifferFromDomParentElement);
195.2009 + }
195.2010 + }
195.2011 +
195.2012 + function applyBindingsToNodeAndDescendantsInternal (viewModel, nodeVerified, bindingContextMayDifferFromDomParentElement) {
195.2013 + var shouldBindDescendants = true;
195.2014 +
195.2015 + // Perf optimisation: Apply bindings only if...
195.2016 + // (1) We need to store the binding context on this node (because it may differ from the DOM parent node's binding context)
195.2017 + // Note that we can't store binding contexts on non-elements (e.g., text nodes), as IE doesn't allow expando properties for those
195.2018 + // (2) It might have bindings (e.g., it has a data-bind attribute, or it's a marker for a containerless template)
195.2019 + var isElement = (nodeVerified.nodeType === 1);
195.2020 + if (isElement) // Workaround IE <= 8 HTML parsing weirdness
195.2021 + ko.virtualElements.normaliseVirtualElementDomStructure(nodeVerified);
195.2022 +
195.2023 + var shouldApplyBindings = (isElement && bindingContextMayDifferFromDomParentElement) // Case (1)
195.2024 + || ko.bindingProvider['instance']['nodeHasBindings'](nodeVerified); // Case (2)
195.2025 + if (shouldApplyBindings)
195.2026 + shouldBindDescendants = applyBindingsToNodeInternal(nodeVerified, null, viewModel, bindingContextMayDifferFromDomParentElement).shouldBindDescendants;
195.2027 +
195.2028 + if (shouldBindDescendants) {
195.2029 + // We're recursing automatically into (real or virtual) child nodes without changing binding contexts. So,
195.2030 + // * For children of a *real* element, the binding context is certainly the same as on their DOM .parentNode,
195.2031 + // hence bindingContextsMayDifferFromDomParentElement is false
195.2032 + // * For children of a *virtual* element, we can't be sure. Evaluating .parentNode on those children may
195.2033 + // skip over any number of intermediate virtual elements, any of which might define a custom binding context,
195.2034 + // hence bindingContextsMayDifferFromDomParentElement is true
195.2035 + applyBindingsToDescendantsInternal(viewModel, nodeVerified, /* bindingContextsMayDifferFromDomParentElement: */ !isElement);
195.2036 + }
195.2037 + }
195.2038 +
195.2039 + function applyBindingsToNodeInternal (node, bindings, viewModelOrBindingContext, bindingContextMayDifferFromDomParentElement) {
195.2040 + // Need to be sure that inits are only run once, and updates never run until all the inits have been run
195.2041 + var initPhase = 0; // 0 = before all inits, 1 = during inits, 2 = after all inits
195.2042 +
195.2043 + // Each time the dependentObservable is evaluated (after data changes),
195.2044 + // the binding attribute is reparsed so that it can pick out the correct
195.2045 + // model properties in the context of the changed data.
195.2046 + // DOM event callbacks need to be able to access this changed data,
195.2047 + // so we need a single parsedBindings variable (shared by all callbacks
195.2048 + // associated with this node's bindings) that all the closures can access.
195.2049 + var parsedBindings;
195.2050 + function makeValueAccessor(bindingKey) {
195.2051 + return function () { return parsedBindings[bindingKey] }
195.2052 + }
195.2053 + function parsedBindingsAccessor() {
195.2054 + return parsedBindings;
195.2055 + }
195.2056 +
195.2057 + var bindingHandlerThatControlsDescendantBindings;
195.2058 + ko.dependentObservable(
195.2059 + function () {
195.2060 + // Ensure we have a nonnull binding context to work with
195.2061 + var bindingContextInstance = viewModelOrBindingContext && (viewModelOrBindingContext instanceof ko.bindingContext)
195.2062 + ? viewModelOrBindingContext
195.2063 + : new ko.bindingContext(ko.utils.unwrapObservable(viewModelOrBindingContext));
195.2064 + var viewModel = bindingContextInstance['$data'];
195.2065 +
195.2066 + // Optimization: Don't store the binding context on this node if it's definitely the same as on node.parentNode, because
195.2067 + // we can easily recover it just by scanning up the node's ancestors in the DOM
195.2068 + // (note: here, parent node means "real DOM parent" not "virtual parent", as there's no O(1) way to find the virtual parent)
195.2069 + if (bindingContextMayDifferFromDomParentElement)
195.2070 + ko.storedBindingContextForNode(node, bindingContextInstance);
195.2071 +
195.2072 + // Use evaluatedBindings if given, otherwise fall back on asking the bindings provider to give us some bindings
195.2073 + var evaluatedBindings = (typeof bindings == "function") ? bindings(bindingContextInstance, node) : bindings;
195.2074 + parsedBindings = evaluatedBindings || ko.bindingProvider['instance']['getBindings'](node, bindingContextInstance);
195.2075 +
195.2076 + if (parsedBindings) {
195.2077 + // First run all the inits, so bindings can register for notification on changes
195.2078 + if (initPhase === 0) {
195.2079 + initPhase = 1;
195.2080 + for (var bindingKey in parsedBindings) {
195.2081 + var binding = ko.bindingHandlers[bindingKey];
195.2082 + if (binding && node.nodeType === 8)
195.2083 + validateThatBindingIsAllowedForVirtualElements(bindingKey);
195.2084 +
195.2085 + if (binding && typeof binding["init"] == "function") {
195.2086 + var handlerInitFn = binding["init"];
195.2087 + var initResult = handlerInitFn(node, makeValueAccessor(bindingKey), parsedBindingsAccessor, viewModel, bindingContextInstance);
195.2088 +
195.2089 + // If this binding handler claims to control descendant bindings, make a note of this
195.2090 + if (initResult && initResult['controlsDescendantBindings']) {
195.2091 + if (bindingHandlerThatControlsDescendantBindings !== undefined)
195.2092 + throw new Error("Multiple bindings (" + bindingHandlerThatControlsDescendantBindings + " and " + bindingKey + ") are trying to control descendant bindings of the same element. You cannot use these bindings together on the same element.");
195.2093 + bindingHandlerThatControlsDescendantBindings = bindingKey;
195.2094 + }
195.2095 + }
195.2096 + }
195.2097 + initPhase = 2;
195.2098 + }
195.2099 +
195.2100 + // ... then run all the updates, which might trigger changes even on the first evaluation
195.2101 + if (initPhase === 2) {
195.2102 + for (var bindingKey in parsedBindings) {
195.2103 + var binding = ko.bindingHandlers[bindingKey];
195.2104 + if (binding && typeof binding["update"] == "function") {
195.2105 + var handlerUpdateFn = binding["update"];
195.2106 + handlerUpdateFn(node, makeValueAccessor(bindingKey), parsedBindingsAccessor, viewModel, bindingContextInstance);
195.2107 + }
195.2108 + }
195.2109 + }
195.2110 + }
195.2111 + },
195.2112 + null,
195.2113 + { disposeWhenNodeIsRemoved : node }
195.2114 + );
195.2115 +
195.2116 + return {
195.2117 + shouldBindDescendants: bindingHandlerThatControlsDescendantBindings === undefined
195.2118 + };
195.2119 + };
195.2120 +
195.2121 + var storedBindingContextDomDataKey = "__ko_bindingContext__";
195.2122 + ko.storedBindingContextForNode = function (node, bindingContext) {
195.2123 + if (arguments.length == 2)
195.2124 + ko.utils.domData.set(node, storedBindingContextDomDataKey, bindingContext);
195.2125 + else
195.2126 + return ko.utils.domData.get(node, storedBindingContextDomDataKey);
195.2127 + }
195.2128 +
195.2129 + ko.applyBindingsToNode = function (node, bindings, viewModel) {
195.2130 + if (node.nodeType === 1) // If it's an element, workaround IE <= 8 HTML parsing weirdness
195.2131 + ko.virtualElements.normaliseVirtualElementDomStructure(node);
195.2132 + return applyBindingsToNodeInternal(node, bindings, viewModel, true);
195.2133 + };
195.2134 +
195.2135 + ko.applyBindingsToDescendants = function(viewModel, rootNode) {
195.2136 + if (rootNode.nodeType === 1 || rootNode.nodeType === 8)
195.2137 + applyBindingsToDescendantsInternal(viewModel, rootNode, true);
195.2138 + };
195.2139 +
195.2140 + ko.applyBindings = function (viewModel, rootNode) {
195.2141 + if (rootNode && (rootNode.nodeType !== 1) && (rootNode.nodeType !== 8))
195.2142 + throw new Error("ko.applyBindings: first parameter should be your view model; second parameter should be a DOM node");
195.2143 + rootNode = rootNode || window.document.body; // Make "rootNode" parameter optional
195.2144 +
195.2145 + applyBindingsToNodeAndDescendantsInternal(viewModel, rootNode, true);
195.2146 + };
195.2147 +
195.2148 + // Retrieving binding context from arbitrary nodes
195.2149 + ko.contextFor = function(node) {
195.2150 + // We can only do something meaningful for elements and comment nodes (in particular, not text nodes, as IE can't store domdata for them)
195.2151 + switch (node.nodeType) {
195.2152 + case 1:
195.2153 + case 8:
195.2154 + var context = ko.storedBindingContextForNode(node);
195.2155 + if (context) return context;
195.2156 + if (node.parentNode) return ko.contextFor(node.parentNode);
195.2157 + break;
195.2158 + }
195.2159 + return undefined;
195.2160 + };
195.2161 + ko.dataFor = function(node) {
195.2162 + var context = ko.contextFor(node);
195.2163 + return context ? context['$data'] : undefined;
195.2164 + };
195.2165 +
195.2166 + ko.exportSymbol('bindingHandlers', ko.bindingHandlers);
195.2167 + ko.exportSymbol('applyBindings', ko.applyBindings);
195.2168 + ko.exportSymbol('applyBindingsToDescendants', ko.applyBindingsToDescendants);
195.2169 + ko.exportSymbol('applyBindingsToNode', ko.applyBindingsToNode);
195.2170 + ko.exportSymbol('contextFor', ko.contextFor);
195.2171 + ko.exportSymbol('dataFor', ko.dataFor);
195.2172 +})();
195.2173 +var attrHtmlToJavascriptMap = { 'class': 'className', 'for': 'htmlFor' };
195.2174 +ko.bindingHandlers['attr'] = {
195.2175 + 'update': function(element, valueAccessor, allBindingsAccessor) {
195.2176 + var value = ko.utils.unwrapObservable(valueAccessor()) || {};
195.2177 + for (var attrName in value) {
195.2178 + if (typeof attrName == "string") {
195.2179 + var attrValue = ko.utils.unwrapObservable(value[attrName]);
195.2180 +
195.2181 + // To cover cases like "attr: { checked:someProp }", we want to remove the attribute entirely
195.2182 + // when someProp is a "no value"-like value (strictly null, false, or undefined)
195.2183 + // (because the absence of the "checked" attr is how to mark an element as not checked, etc.)
195.2184 + var toRemove = (attrValue === false) || (attrValue === null) || (attrValue === undefined);
195.2185 + if (toRemove)
195.2186 + element.removeAttribute(attrName);
195.2187 +
195.2188 + // In IE <= 7 and IE8 Quirks Mode, you have to use the Javascript property name instead of the
195.2189 + // HTML attribute name for certain attributes. IE8 Standards Mode supports the correct behavior,
195.2190 + // but instead of figuring out the mode, we'll just set the attribute through the Javascript
195.2191 + // property for IE <= 8.
195.2192 + if (ko.utils.ieVersion <= 8 && attrName in attrHtmlToJavascriptMap) {
195.2193 + attrName = attrHtmlToJavascriptMap[attrName];
195.2194 + if (toRemove)
195.2195 + element.removeAttribute(attrName);
195.2196 + else
195.2197 + element[attrName] = attrValue;
195.2198 + } else if (!toRemove) {
195.2199 + try {
195.2200 + element.setAttribute(attrName, attrValue.toString());
195.2201 + } catch (err) {
195.2202 + // ignore for now
195.2203 + if (console) {
195.2204 + console.log("Can't set attribute " + attrName + " to " + attrValue + " error: " + err);
195.2205 + }
195.2206 + }
195.2207 + }
195.2208 +
195.2209 + // Treat "name" specially - although you can think of it as an attribute, it also needs
195.2210 + // special handling on older versions of IE (https://github.com/SteveSanderson/knockout/pull/333)
195.2211 + // Deliberately being case-sensitive here because XHTML would regard "Name" as a different thing
195.2212 + // entirely, and there's no strong reason to allow for such casing in HTML.
195.2213 + if (attrName === "name") {
195.2214 + ko.utils.setElementName(element, toRemove ? "" : attrValue.toString());
195.2215 + }
195.2216 + }
195.2217 + }
195.2218 + }
195.2219 +};
195.2220 +ko.bindingHandlers['checked'] = {
195.2221 + 'init': function (element, valueAccessor, allBindingsAccessor) {
195.2222 + var updateHandler = function() {
195.2223 + var valueToWrite;
195.2224 + if (element.type == "checkbox") {
195.2225 + valueToWrite = element.checked;
195.2226 + } else if ((element.type == "radio") && (element.checked)) {
195.2227 + valueToWrite = element.value;
195.2228 + } else {
195.2229 + return; // "checked" binding only responds to checkboxes and selected radio buttons
195.2230 + }
195.2231 +
195.2232 + var modelValue = valueAccessor(), unwrappedValue = ko.utils.unwrapObservable(modelValue);
195.2233 + if ((element.type == "checkbox") && (unwrappedValue instanceof Array)) {
195.2234 + // For checkboxes bound to an array, we add/remove the checkbox value to that array
195.2235 + // This works for both observable and non-observable arrays
195.2236 + var existingEntryIndex = ko.utils.arrayIndexOf(unwrappedValue, element.value);
195.2237 + if (element.checked && (existingEntryIndex < 0))
195.2238 + modelValue.push(element.value);
195.2239 + else if ((!element.checked) && (existingEntryIndex >= 0))
195.2240 + modelValue.splice(existingEntryIndex, 1);
195.2241 + } else {
195.2242 + ko.expressionRewriting.writeValueToProperty(modelValue, allBindingsAccessor, 'checked', valueToWrite, true);
195.2243 + }
195.2244 + };
195.2245 + ko.utils.registerEventHandler(element, "click", updateHandler);
195.2246 +
195.2247 + // IE 6 won't allow radio buttons to be selected unless they have a name
195.2248 + if ((element.type == "radio") && !element.name)
195.2249 + ko.bindingHandlers['uniqueName']['init'](element, function() { return true });
195.2250 + },
195.2251 + 'update': function (element, valueAccessor) {
195.2252 + var value = ko.utils.unwrapObservable(valueAccessor());
195.2253 +
195.2254 + if (element.type == "checkbox") {
195.2255 + if (value instanceof Array) {
195.2256 + // When bound to an array, the checkbox being checked represents its value being present in that array
195.2257 + element.checked = ko.utils.arrayIndexOf(value, element.value) >= 0;
195.2258 + } else {
195.2259 + // When bound to anything other value (not an array), the checkbox being checked represents the value being trueish
195.2260 + element.checked = value;
195.2261 + }
195.2262 + } else if (element.type == "radio") {
195.2263 + element.checked = (element.value == value);
195.2264 + }
195.2265 + }
195.2266 +};
195.2267 +var classesWrittenByBindingKey = '__ko__cssValue';
195.2268 +ko.bindingHandlers['css'] = {
195.2269 + 'update': function (element, valueAccessor) {
195.2270 + var value = ko.utils.unwrapObservable(valueAccessor());
195.2271 + if (typeof value == "object") {
195.2272 + for (var className in value) {
195.2273 + var shouldHaveClass = ko.utils.unwrapObservable(value[className]);
195.2274 + ko.utils.toggleDomNodeCssClass(element, className, shouldHaveClass);
195.2275 + }
195.2276 + } else {
195.2277 + value = String(value || ''); // Make sure we don't try to store or set a non-string value
195.2278 + ko.utils.toggleDomNodeCssClass(element, element[classesWrittenByBindingKey], false);
195.2279 + element[classesWrittenByBindingKey] = value;
195.2280 + ko.utils.toggleDomNodeCssClass(element, value, true);
195.2281 + }
195.2282 + }
195.2283 +};
195.2284 +ko.bindingHandlers['enable'] = {
195.2285 + 'update': function (element, valueAccessor) {
195.2286 + var value = ko.utils.unwrapObservable(valueAccessor());
195.2287 + if (value && element.disabled)
195.2288 + element.removeAttribute("disabled");
195.2289 + else if ((!value) && (!element.disabled))
195.2290 + element.disabled = true;
195.2291 + }
195.2292 +};
195.2293 +
195.2294 +ko.bindingHandlers['disable'] = {
195.2295 + 'update': function (element, valueAccessor) {
195.2296 + ko.bindingHandlers['enable']['update'](element, function() { return !ko.utils.unwrapObservable(valueAccessor()) });
195.2297 + }
195.2298 +};
195.2299 +// For certain common events (currently just 'click'), allow a simplified data-binding syntax
195.2300 +// e.g. click:handler instead of the usual full-length event:{click:handler}
195.2301 +function makeEventHandlerShortcut(eventName) {
195.2302 + ko.bindingHandlers[eventName] = {
195.2303 + 'init': function(element, valueAccessor, allBindingsAccessor, viewModel) {
195.2304 + var newValueAccessor = function () {
195.2305 + var result = {};
195.2306 + result[eventName] = valueAccessor();
195.2307 + return result;
195.2308 + };
195.2309 + return ko.bindingHandlers['event']['init'].call(this, element, newValueAccessor, allBindingsAccessor, viewModel);
195.2310 + }
195.2311 + }
195.2312 +}
195.2313 +
195.2314 +ko.bindingHandlers['event'] = {
195.2315 + 'init' : function (element, valueAccessor, allBindingsAccessor, viewModel) {
195.2316 + var eventsToHandle = valueAccessor() || {};
195.2317 + for(var eventNameOutsideClosure in eventsToHandle) {
195.2318 + (function() {
195.2319 + var eventName = eventNameOutsideClosure; // Separate variable to be captured by event handler closure
195.2320 + if (typeof eventName == "string") {
195.2321 + ko.utils.registerEventHandler(element, eventName, function (event) {
195.2322 + var handlerReturnValue;
195.2323 + var handlerFunction = valueAccessor()[eventName];
195.2324 + if (!handlerFunction)
195.2325 + return;
195.2326 + var allBindings = allBindingsAccessor();
195.2327 +
195.2328 + try {
195.2329 + // Take all the event args, and prefix with the viewmodel
195.2330 + var argsForHandler = ko.utils.makeArray(arguments);
195.2331 + argsForHandler.unshift(viewModel);
195.2332 + handlerReturnValue = handlerFunction.apply(viewModel, argsForHandler);
195.2333 + } finally {
195.2334 + if (handlerReturnValue !== true) { // Normally we want to prevent default action. Developer can override this be explicitly returning true.
195.2335 + if (event.preventDefault)
195.2336 + event.preventDefault();
195.2337 + else
195.2338 + event.returnValue = false;
195.2339 + }
195.2340 + }
195.2341 +
195.2342 + var bubble = allBindings[eventName + 'Bubble'] !== false;
195.2343 + if (!bubble) {
195.2344 + event.cancelBubble = true;
195.2345 + if (event.stopPropagation)
195.2346 + event.stopPropagation();
195.2347 + }
195.2348 + });
195.2349 + }
195.2350 + })();
195.2351 + }
195.2352 + }
195.2353 +};
195.2354 +// "foreach: someExpression" is equivalent to "template: { foreach: someExpression }"
195.2355 +// "foreach: { data: someExpression, afterAdd: myfn }" is equivalent to "template: { foreach: someExpression, afterAdd: myfn }"
195.2356 +ko.bindingHandlers['foreach'] = {
195.2357 + makeTemplateValueAccessor: function(valueAccessor) {
195.2358 + return function() {
195.2359 + var modelValue = valueAccessor(),
195.2360 + unwrappedValue = ko.utils.peekObservable(modelValue); // Unwrap without setting a dependency here
195.2361 +
195.2362 + // If unwrappedValue is the array, pass in the wrapped value on its own
195.2363 + // The value will be unwrapped and tracked within the template binding
195.2364 + // (See https://github.com/SteveSanderson/knockout/issues/523)
195.2365 + if ((!unwrappedValue) || typeof unwrappedValue.length == "number")
195.2366 + return { 'foreach': modelValue, 'templateEngine': ko.nativeTemplateEngine.instance };
195.2367 +
195.2368 + // If unwrappedValue.data is the array, preserve all relevant options and unwrap again value so we get updates
195.2369 + ko.utils.unwrapObservable(modelValue);
195.2370 + return {
195.2371 + 'foreach': unwrappedValue['data'],
195.2372 + 'as': unwrappedValue['as'],
195.2373 + 'includeDestroyed': unwrappedValue['includeDestroyed'],
195.2374 + 'afterAdd': unwrappedValue['afterAdd'],
195.2375 + 'beforeRemove': unwrappedValue['beforeRemove'],
195.2376 + 'afterRender': unwrappedValue['afterRender'],
195.2377 + 'beforeMove': unwrappedValue['beforeMove'],
195.2378 + 'afterMove': unwrappedValue['afterMove'],
195.2379 + 'templateEngine': ko.nativeTemplateEngine.instance
195.2380 + };
195.2381 + };
195.2382 + },
195.2383 + 'init': function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
195.2384 + return ko.bindingHandlers['template']['init'](element, ko.bindingHandlers['foreach'].makeTemplateValueAccessor(valueAccessor));
195.2385 + },
195.2386 + 'update': function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
195.2387 + return ko.bindingHandlers['template']['update'](element, ko.bindingHandlers['foreach'].makeTemplateValueAccessor(valueAccessor), allBindingsAccessor, viewModel, bindingContext);
195.2388 + }
195.2389 +};
195.2390 +ko.expressionRewriting.bindingRewriteValidators['foreach'] = false; // Can't rewrite control flow bindings
195.2391 +ko.virtualElements.allowedBindings['foreach'] = true;
195.2392 +var hasfocusUpdatingProperty = '__ko_hasfocusUpdating';
195.2393 +ko.bindingHandlers['hasfocus'] = {
195.2394 + 'init': function(element, valueAccessor, allBindingsAccessor) {
195.2395 + var handleElementFocusChange = function(isFocused) {
195.2396 + // Where possible, ignore which event was raised and determine focus state using activeElement,
195.2397 + // as this avoids phantom focus/blur events raised when changing tabs in modern browsers.
195.2398 + // However, not all KO-targeted browsers (Firefox 2) support activeElement. For those browsers,
195.2399 + // prevent a loss of focus when changing tabs/windows by setting a flag that prevents hasfocus
195.2400 + // from calling 'blur()' on the element when it loses focus.
195.2401 + // Discussion at https://github.com/SteveSanderson/knockout/pull/352
195.2402 + element[hasfocusUpdatingProperty] = true;
195.2403 + var ownerDoc = element.ownerDocument;
195.2404 + if ("activeElement" in ownerDoc) {
195.2405 + isFocused = (ownerDoc.activeElement === element);
195.2406 + }
195.2407 + var modelValue = valueAccessor();
195.2408 + ko.expressionRewriting.writeValueToProperty(modelValue, allBindingsAccessor, 'hasfocus', isFocused, true);
195.2409 + element[hasfocusUpdatingProperty] = false;
195.2410 + };
195.2411 + var handleElementFocusIn = handleElementFocusChange.bind(null, true);
195.2412 + var handleElementFocusOut = handleElementFocusChange.bind(null, false);
195.2413 +
195.2414 + ko.utils.registerEventHandler(element, "focus", handleElementFocusIn);
195.2415 + ko.utils.registerEventHandler(element, "focusin", handleElementFocusIn); // For IE
195.2416 + ko.utils.registerEventHandler(element, "blur", handleElementFocusOut);
195.2417 + ko.utils.registerEventHandler(element, "focusout", handleElementFocusOut); // For IE
195.2418 + },
195.2419 + 'update': function(element, valueAccessor) {
195.2420 + var value = ko.utils.unwrapObservable(valueAccessor());
195.2421 + if (!element[hasfocusUpdatingProperty]) {
195.2422 + value ? element.focus() : element.blur();
195.2423 + ko.dependencyDetection.ignore(ko.utils.triggerEvent, null, [element, value ? "focusin" : "focusout"]); // For IE, which doesn't reliably fire "focus" or "blur" events synchronously
195.2424 + }
195.2425 + }
195.2426 +};
195.2427 +ko.bindingHandlers['html'] = {
195.2428 + 'init': function() {
195.2429 + // Prevent binding on the dynamically-injected HTML (as developers are unlikely to expect that, and it has security implications)
195.2430 + return { 'controlsDescendantBindings': true };
195.2431 + },
195.2432 + 'update': function (element, valueAccessor) {
195.2433 + // setHtml will unwrap the value if needed
195.2434 + ko.utils.setHtml(element, valueAccessor());
195.2435 + }
195.2436 +};
195.2437 +var withIfDomDataKey = '__ko_withIfBindingData';
195.2438 +// Makes a binding like with or if
195.2439 +function makeWithIfBinding(bindingKey, isWith, isNot, makeContextCallback) {
195.2440 + ko.bindingHandlers[bindingKey] = {
195.2441 + 'init': function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
195.2442 + ko.utils.domData.set(element, withIfDomDataKey, {});
195.2443 + return { 'controlsDescendantBindings': true };
195.2444 + },
195.2445 + 'update': function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
195.2446 + var withIfData = ko.utils.domData.get(element, withIfDomDataKey),
195.2447 + dataValue = ko.utils.unwrapObservable(valueAccessor()),
195.2448 + shouldDisplay = !isNot !== !dataValue, // equivalent to isNot ? !dataValue : !!dataValue
195.2449 + isFirstRender = !withIfData.savedNodes,
195.2450 + needsRefresh = isFirstRender || isWith || (shouldDisplay !== withIfData.didDisplayOnLastUpdate);
195.2451 +
195.2452 + if (needsRefresh) {
195.2453 + if (isFirstRender) {
195.2454 + withIfData.savedNodes = ko.utils.cloneNodes(ko.virtualElements.childNodes(element), true /* shouldCleanNodes */);
195.2455 + }
195.2456 +
195.2457 + if (shouldDisplay) {
195.2458 + if (!isFirstRender) {
195.2459 + ko.virtualElements.setDomNodeChildren(element, ko.utils.cloneNodes(withIfData.savedNodes));
195.2460 + }
195.2461 + ko.applyBindingsToDescendants(makeContextCallback ? makeContextCallback(bindingContext, dataValue) : bindingContext, element);
195.2462 + } else {
195.2463 + ko.virtualElements.emptyNode(element);
195.2464 + }
195.2465 +
195.2466 + withIfData.didDisplayOnLastUpdate = shouldDisplay;
195.2467 + }
195.2468 + }
195.2469 + };
195.2470 + ko.expressionRewriting.bindingRewriteValidators[bindingKey] = false; // Can't rewrite control flow bindings
195.2471 + ko.virtualElements.allowedBindings[bindingKey] = true;
195.2472 +}
195.2473 +
195.2474 +// Construct the actual binding handlers
195.2475 +makeWithIfBinding('if');
195.2476 +makeWithIfBinding('ifnot', false /* isWith */, true /* isNot */);
195.2477 +makeWithIfBinding('with', true /* isWith */, false /* isNot */,
195.2478 + function(bindingContext, dataValue) {
195.2479 + return bindingContext['createChildContext'](dataValue);
195.2480 + }
195.2481 +);
195.2482 +function ensureDropdownSelectionIsConsistentWithModelValue(element, modelValue, preferModelValue) {
195.2483 + if (preferModelValue) {
195.2484 + if (modelValue !== ko.selectExtensions.readValue(element))
195.2485 + ko.selectExtensions.writeValue(element, modelValue);
195.2486 + }
195.2487 +
195.2488 + // No matter which direction we're syncing in, we want the end result to be equality between dropdown value and model value.
195.2489 + // If they aren't equal, either we prefer the dropdown value, or the model value couldn't be represented, so either way,
195.2490 + // change the model value to match the dropdown.
195.2491 + if (modelValue !== ko.selectExtensions.readValue(element))
195.2492 + ko.dependencyDetection.ignore(ko.utils.triggerEvent, null, [element, "change"]);
195.2493 +};
195.2494 +
195.2495 +ko.bindingHandlers['options'] = {
195.2496 + 'update': function (element, valueAccessor, allBindingsAccessor) {
195.2497 + if (ko.utils.tagNameLower(element) !== "select")
195.2498 + throw new Error("options binding applies only to SELECT elements");
195.2499 +
195.2500 + var selectWasPreviouslyEmpty = element.length == 0;
195.2501 + var previousSelectedValues = ko.utils.arrayMap(ko.utils.arrayFilter(element.childNodes, function (node) {
195.2502 + return node.tagName && (ko.utils.tagNameLower(node) === "option") && node.selected;
195.2503 + }), function (node) {
195.2504 + return ko.selectExtensions.readValue(node) || node.innerText || node.textContent;
195.2505 + });
195.2506 + var previousScrollTop = element.scrollTop;
195.2507 +
195.2508 + var value = ko.utils.unwrapObservable(valueAccessor());
195.2509 + var selectedValue = element.value;
195.2510 +
195.2511 + // Remove all existing <option>s.
195.2512 + // Need to use .remove() rather than .removeChild() for <option>s otherwise IE behaves oddly (https://github.com/SteveSanderson/knockout/issues/134)
195.2513 + while (element.length > 0) {
195.2514 + ko.cleanNode(element.options[0]);
195.2515 + element.remove(0);
195.2516 + }
195.2517 +
195.2518 + if (value) {
195.2519 + var allBindings = allBindingsAccessor(),
195.2520 + includeDestroyed = allBindings['optionsIncludeDestroyed'];
195.2521 +
195.2522 + if (typeof value.length != "number")
195.2523 + value = [value];
195.2524 + if (allBindings['optionsCaption']) {
195.2525 + var option = document.createElement("option");
195.2526 + ko.utils.setHtml(option, allBindings['optionsCaption']);
195.2527 + ko.selectExtensions.writeValue(option, undefined);
195.2528 + element.appendChild(option);
195.2529 + }
195.2530 +
195.2531 + for (var i = 0, j = value.length; i < j; i++) {
195.2532 + // Skip destroyed items
195.2533 + var arrayEntry = value[i];
195.2534 + if (arrayEntry && arrayEntry['_destroy'] && !includeDestroyed)
195.2535 + continue;
195.2536 +
195.2537 + var option = document.createElement("option");
195.2538 +
195.2539 + function applyToObject(object, predicate, defaultValue) {
195.2540 + var predicateType = typeof predicate;
195.2541 + if (predicateType == "function") // Given a function; run it against the data value
195.2542 + return predicate(object);
195.2543 + else if (predicateType == "string") // Given a string; treat it as a property name on the data value
195.2544 + return object[predicate];
195.2545 + else // Given no optionsText arg; use the data value itself
195.2546 + return defaultValue;
195.2547 + }
195.2548 +
195.2549 + // Apply a value to the option element
195.2550 + var optionValue = applyToObject(arrayEntry, allBindings['optionsValue'], arrayEntry);
195.2551 + ko.selectExtensions.writeValue(option, ko.utils.unwrapObservable(optionValue));
195.2552 +
195.2553 + // Apply some text to the option element
195.2554 + var optionText = applyToObject(arrayEntry, allBindings['optionsText'], optionValue);
195.2555 + ko.utils.setTextContent(option, optionText);
195.2556 +
195.2557 + element.appendChild(option);
195.2558 + }
195.2559 +
195.2560 + // IE6 doesn't like us to assign selection to OPTION nodes before they're added to the document.
195.2561 + // That's why we first added them without selection. Now it's time to set the selection.
195.2562 + var newOptions = element.getElementsByTagName("option");
195.2563 + var countSelectionsRetained = 0;
195.2564 + for (var i = 0, j = newOptions.length; i < j; i++) {
195.2565 + if (ko.utils.arrayIndexOf(previousSelectedValues, ko.selectExtensions.readValue(newOptions[i])) >= 0) {
195.2566 + ko.utils.setOptionNodeSelectionState(newOptions[i], true);
195.2567 + countSelectionsRetained++;
195.2568 + }
195.2569 + }
195.2570 +
195.2571 + element.scrollTop = previousScrollTop;
195.2572 +
195.2573 + if (selectWasPreviouslyEmpty && ('value' in allBindings)) {
195.2574 + // Ensure consistency between model value and selected option.
195.2575 + // If the dropdown is being populated for the first time here (or was otherwise previously empty),
195.2576 + // the dropdown selection state is meaningless, so we preserve the model value.
195.2577 + ensureDropdownSelectionIsConsistentWithModelValue(element, ko.utils.peekObservable(allBindings['value']), /* preferModelValue */ true);
195.2578 + }
195.2579 +
195.2580 + // Workaround for IE9 bug
195.2581 + ko.utils.ensureSelectElementIsRenderedCorrectly(element);
195.2582 + }
195.2583 + }
195.2584 +};
195.2585 +ko.bindingHandlers['options'].optionValueDomDataKey = '__ko.optionValueDomData__';
195.2586 +ko.bindingHandlers['selectedOptions'] = {
195.2587 + 'init': function (element, valueAccessor, allBindingsAccessor) {
195.2588 + ko.utils.registerEventHandler(element, "change", function () {
195.2589 + var value = valueAccessor(), valueToWrite = [];
195.2590 + ko.utils.arrayForEach(element.getElementsByTagName("option"), function(node) {
195.2591 + if (node.selected)
195.2592 + valueToWrite.push(ko.selectExtensions.readValue(node));
195.2593 + });
195.2594 + ko.expressionRewriting.writeValueToProperty(value, allBindingsAccessor, 'value', valueToWrite);
195.2595 + });
195.2596 + },
195.2597 + 'update': function (element, valueAccessor) {
195.2598 + if (ko.utils.tagNameLower(element) != "select")
195.2599 + throw new Error("values binding applies only to SELECT elements");
195.2600 +
195.2601 + var newValue = ko.utils.unwrapObservable(valueAccessor());
195.2602 + if (newValue && typeof newValue.length == "number") {
195.2603 + ko.utils.arrayForEach(element.getElementsByTagName("option"), function(node) {
195.2604 + var isSelected = ko.utils.arrayIndexOf(newValue, ko.selectExtensions.readValue(node)) >= 0;
195.2605 + ko.utils.setOptionNodeSelectionState(node, isSelected);
195.2606 + });
195.2607 + }
195.2608 + }
195.2609 +};
195.2610 +ko.bindingHandlers['style'] = {
195.2611 + 'update': function (element, valueAccessor) {
195.2612 + var value = ko.utils.unwrapObservable(valueAccessor() || {});
195.2613 + for (var styleName in value) {
195.2614 + if (typeof styleName == "string") {
195.2615 + var styleValue = ko.utils.unwrapObservable(value[styleName]);
195.2616 + element.style[styleName] = styleValue || ""; // Empty string removes the value, whereas null/undefined have no effect
195.2617 + }
195.2618 + }
195.2619 + }
195.2620 +};
195.2621 +ko.bindingHandlers['submit'] = {
195.2622 + 'init': function (element, valueAccessor, allBindingsAccessor, viewModel) {
195.2623 + if (typeof valueAccessor() != "function")
195.2624 + throw new Error("The value for a submit binding must be a function");
195.2625 + ko.utils.registerEventHandler(element, "submit", function (event) {
195.2626 + var handlerReturnValue;
195.2627 + var value = valueAccessor();
195.2628 + try { handlerReturnValue = value.call(viewModel, element); }
195.2629 + finally {
195.2630 + if (handlerReturnValue !== true) { // Normally we want to prevent default action. Developer can override this be explicitly returning true.
195.2631 + if (event.preventDefault)
195.2632 + event.preventDefault();
195.2633 + else
195.2634 + event.returnValue = false;
195.2635 + }
195.2636 + }
195.2637 + });
195.2638 + }
195.2639 +};
195.2640 +ko.bindingHandlers['text'] = {
195.2641 + 'update': function (element, valueAccessor) {
195.2642 + ko.utils.setTextContent(element, valueAccessor());
195.2643 + }
195.2644 +};
195.2645 +ko.virtualElements.allowedBindings['text'] = true;
195.2646 +ko.bindingHandlers['uniqueName'] = {
195.2647 + 'init': function (element, valueAccessor) {
195.2648 + if (valueAccessor()) {
195.2649 + var name = "ko_unique_" + (++ko.bindingHandlers['uniqueName'].currentIndex);
195.2650 + ko.utils.setElementName(element, name);
195.2651 + }
195.2652 + }
195.2653 +};
195.2654 +ko.bindingHandlers['uniqueName'].currentIndex = 0;
195.2655 +ko.bindingHandlers['value'] = {
195.2656 + 'init': function (element, valueAccessor, allBindingsAccessor) {
195.2657 + // Always catch "change" event; possibly other events too if asked
195.2658 + var eventsToCatch = ["change"];
195.2659 + var requestedEventsToCatch = allBindingsAccessor()["valueUpdate"];
195.2660 + var propertyChangedFired = false;
195.2661 + if (requestedEventsToCatch) {
195.2662 + if (typeof requestedEventsToCatch == "string") // Allow both individual event names, and arrays of event names
195.2663 + requestedEventsToCatch = [requestedEventsToCatch];
195.2664 + ko.utils.arrayPushAll(eventsToCatch, requestedEventsToCatch);
195.2665 + eventsToCatch = ko.utils.arrayGetDistinctValues(eventsToCatch);
195.2666 + }
195.2667 +
195.2668 + var valueUpdateHandler = function() {
195.2669 + propertyChangedFired = false;
195.2670 + var modelValue = valueAccessor();
195.2671 + var elementValue = ko.selectExtensions.readValue(element);
195.2672 + ko.expressionRewriting.writeValueToProperty(modelValue, allBindingsAccessor, 'value', elementValue);
195.2673 + }
195.2674 +
195.2675 + // Workaround for https://github.com/SteveSanderson/knockout/issues/122
195.2676 + // IE doesn't fire "change" events on textboxes if the user selects a value from its autocomplete list
195.2677 + var ieAutoCompleteHackNeeded = ko.utils.ieVersion && element.tagName.toLowerCase() == "input" && element.type == "text"
195.2678 + && element.autocomplete != "off" && (!element.form || element.form.autocomplete != "off");
195.2679 + if (ieAutoCompleteHackNeeded && ko.utils.arrayIndexOf(eventsToCatch, "propertychange") == -1) {
195.2680 + ko.utils.registerEventHandler(element, "propertychange", function () { propertyChangedFired = true });
195.2681 + ko.utils.registerEventHandler(element, "blur", function() {
195.2682 + if (propertyChangedFired) {
195.2683 + valueUpdateHandler();
195.2684 + }
195.2685 + });
195.2686 + }
195.2687 +
195.2688 + ko.utils.arrayForEach(eventsToCatch, function(eventName) {
195.2689 + // The syntax "after<eventname>" means "run the handler asynchronously after the event"
195.2690 + // This is useful, for example, to catch "keydown" events after the browser has updated the control
195.2691 + // (otherwise, ko.selectExtensions.readValue(this) will receive the control's value *before* the key event)
195.2692 + var handler = valueUpdateHandler;
195.2693 + if (ko.utils.stringStartsWith(eventName, "after")) {
195.2694 + handler = function() { setTimeout(valueUpdateHandler, 0) };
195.2695 + eventName = eventName.substring("after".length);
195.2696 + }
195.2697 + ko.utils.registerEventHandler(element, eventName, handler);
195.2698 + });
195.2699 + },
195.2700 + 'update': function (element, valueAccessor) {
195.2701 + var valueIsSelectOption = ko.utils.tagNameLower(element) === "select";
195.2702 + var newValue = ko.utils.unwrapObservable(valueAccessor());
195.2703 + var elementValue = ko.selectExtensions.readValue(element);
195.2704 + var valueHasChanged = (newValue != elementValue);
195.2705 +
195.2706 + // JavaScript's 0 == "" behavious is unfortunate here as it prevents writing 0 to an empty text box (loose equality suggests the values are the same).
195.2707 + // We don't want to do a strict equality comparison as that is more confusing for developers in certain cases, so we specifically special case 0 != "" here.
195.2708 + if ((newValue === 0) && (elementValue !== 0) && (elementValue !== "0"))
195.2709 + valueHasChanged = true;
195.2710 +
195.2711 + if (valueHasChanged) {
195.2712 + var applyValueAction = function () { ko.selectExtensions.writeValue(element, newValue); };
195.2713 + applyValueAction();
195.2714 +
195.2715 + // Workaround for IE6 bug: It won't reliably apply values to SELECT nodes during the same execution thread
195.2716 + // right after you've changed the set of OPTION nodes on it. So for that node type, we'll schedule a second thread
195.2717 + // to apply the value as well.
195.2718 + var alsoApplyAsynchronously = valueIsSelectOption;
195.2719 + if (alsoApplyAsynchronously)
195.2720 + setTimeout(applyValueAction, 0);
195.2721 + }
195.2722 +
195.2723 + // If you try to set a model value that can't be represented in an already-populated dropdown, reject that change,
195.2724 + // because you're not allowed to have a model value that disagrees with a visible UI selection.
195.2725 + if (valueIsSelectOption && (element.length > 0))
195.2726 + ensureDropdownSelectionIsConsistentWithModelValue(element, newValue, /* preferModelValue */ false);
195.2727 + }
195.2728 +};
195.2729 +ko.bindingHandlers['visible'] = {
195.2730 + 'update': function (element, valueAccessor) {
195.2731 + var value = ko.utils.unwrapObservable(valueAccessor());
195.2732 + var isCurrentlyVisible = !(element.style.display == "none");
195.2733 + if (value && !isCurrentlyVisible)
195.2734 + element.style.display = "";
195.2735 + else if ((!value) && isCurrentlyVisible)
195.2736 + element.style.display = "none";
195.2737 + }
195.2738 +};
195.2739 +// 'click' is just a shorthand for the usual full-length event:{click:handler}
195.2740 +makeEventHandlerShortcut('click');
195.2741 +// If you want to make a custom template engine,
195.2742 +//
195.2743 +// [1] Inherit from this class (like ko.nativeTemplateEngine does)
195.2744 +// [2] Override 'renderTemplateSource', supplying a function with this signature:
195.2745 +//
195.2746 +// function (templateSource, bindingContext, options) {
195.2747 +// // - templateSource.text() is the text of the template you should render
195.2748 +// // - bindingContext.$data is the data you should pass into the template
195.2749 +// // - you might also want to make bindingContext.$parent, bindingContext.$parents,
195.2750 +// // and bindingContext.$root available in the template too
195.2751 +// // - options gives you access to any other properties set on "data-bind: { template: options }"
195.2752 +// //
195.2753 +// // Return value: an array of DOM nodes
195.2754 +// }
195.2755 +//
195.2756 +// [3] Override 'createJavaScriptEvaluatorBlock', supplying a function with this signature:
195.2757 +//
195.2758 +// function (script) {
195.2759 +// // Return value: Whatever syntax means "Evaluate the JavaScript statement 'script' and output the result"
195.2760 +// // For example, the jquery.tmpl template engine converts 'someScript' to '${ someScript }'
195.2761 +// }
195.2762 +//
195.2763 +// This is only necessary if you want to allow data-bind attributes to reference arbitrary template variables.
195.2764 +// If you don't want to allow that, you can set the property 'allowTemplateRewriting' to false (like ko.nativeTemplateEngine does)
195.2765 +// and then you don't need to override 'createJavaScriptEvaluatorBlock'.
195.2766 +
195.2767 +ko.templateEngine = function () { };
195.2768 +
195.2769 +ko.templateEngine.prototype['renderTemplateSource'] = function (templateSource, bindingContext, options) {
195.2770 + throw new Error("Override renderTemplateSource");
195.2771 +};
195.2772 +
195.2773 +ko.templateEngine.prototype['createJavaScriptEvaluatorBlock'] = function (script) {
195.2774 + throw new Error("Override createJavaScriptEvaluatorBlock");
195.2775 +};
195.2776 +
195.2777 +ko.templateEngine.prototype['makeTemplateSource'] = function(template, templateDocument) {
195.2778 + // Named template
195.2779 + if (typeof template == "string") {
195.2780 + templateDocument = templateDocument || document;
195.2781 + var elem = templateDocument.getElementById(template);
195.2782 + if (!elem)
195.2783 + throw new Error("Cannot find template with ID " + template);
195.2784 + return new ko.templateSources.domElement(elem);
195.2785 + } else if ((template.nodeType == 1) || (template.nodeType == 8)) {
195.2786 + // Anonymous template
195.2787 + return new ko.templateSources.anonymousTemplate(template);
195.2788 + } else
195.2789 + throw new Error("Unknown template type: " + template);
195.2790 +};
195.2791 +
195.2792 +ko.templateEngine.prototype['renderTemplate'] = function (template, bindingContext, options, templateDocument) {
195.2793 + var templateSource = this['makeTemplateSource'](template, templateDocument);
195.2794 + return this['renderTemplateSource'](templateSource, bindingContext, options);
195.2795 +};
195.2796 +
195.2797 +ko.templateEngine.prototype['isTemplateRewritten'] = function (template, templateDocument) {
195.2798 + // Skip rewriting if requested
195.2799 + if (this['allowTemplateRewriting'] === false)
195.2800 + return true;
195.2801 + return this['makeTemplateSource'](template, templateDocument)['data']("isRewritten");
195.2802 +};
195.2803 +
195.2804 +ko.templateEngine.prototype['rewriteTemplate'] = function (template, rewriterCallback, templateDocument) {
195.2805 + var templateSource = this['makeTemplateSource'](template, templateDocument);
195.2806 + var rewritten = rewriterCallback(templateSource['text']());
195.2807 + templateSource['text'](rewritten);
195.2808 + templateSource['data']("isRewritten", true);
195.2809 +};
195.2810 +
195.2811 +ko.exportSymbol('templateEngine', ko.templateEngine);
195.2812 +
195.2813 +ko.templateRewriting = (function () {
195.2814 + var memoizeDataBindingAttributeSyntaxRegex = /(<[a-z]+\d*(\s+(?!data-bind=)[a-z0-9\-]+(=(\"[^\"]*\"|\'[^\']*\'))?)*\s+)data-bind=(["'])([\s\S]*?)\5/gi;
195.2815 + var memoizeVirtualContainerBindingSyntaxRegex = /<!--\s*ko\b\s*([\s\S]*?)\s*-->/g;
195.2816 +
195.2817 + function validateDataBindValuesForRewriting(keyValueArray) {
195.2818 + var allValidators = ko.expressionRewriting.bindingRewriteValidators;
195.2819 + for (var i = 0; i < keyValueArray.length; i++) {
195.2820 + var key = keyValueArray[i]['key'];
195.2821 + if (allValidators.hasOwnProperty(key)) {
195.2822 + var validator = allValidators[key];
195.2823 +
195.2824 + if (typeof validator === "function") {
195.2825 + var possibleErrorMessage = validator(keyValueArray[i]['value']);
195.2826 + if (possibleErrorMessage)
195.2827 + throw new Error(possibleErrorMessage);
195.2828 + } else if (!validator) {
195.2829 + throw new Error("This template engine does not support the '" + key + "' binding within its templates");
195.2830 + }
195.2831 + }
195.2832 + }
195.2833 + }
195.2834 +
195.2835 + function constructMemoizedTagReplacement(dataBindAttributeValue, tagToRetain, templateEngine) {
195.2836 + var dataBindKeyValueArray = ko.expressionRewriting.parseObjectLiteral(dataBindAttributeValue);
195.2837 + validateDataBindValuesForRewriting(dataBindKeyValueArray);
195.2838 + var rewrittenDataBindAttributeValue = ko.expressionRewriting.preProcessBindings(dataBindKeyValueArray);
195.2839 +
195.2840 + // For no obvious reason, Opera fails to evaluate rewrittenDataBindAttributeValue unless it's wrapped in an additional
195.2841 + // anonymous function, even though Opera's built-in debugger can evaluate it anyway. No other browser requires this
195.2842 + // extra indirection.
195.2843 + var applyBindingsToNextSiblingScript =
195.2844 + "ko.__tr_ambtns(function($context,$element){return(function(){return{ " + rewrittenDataBindAttributeValue + " } })()})";
195.2845 + return templateEngine['createJavaScriptEvaluatorBlock'](applyBindingsToNextSiblingScript) + tagToRetain;
195.2846 + }
195.2847 +
195.2848 + return {
195.2849 + ensureTemplateIsRewritten: function (template, templateEngine, templateDocument) {
195.2850 + if (!templateEngine['isTemplateRewritten'](template, templateDocument))
195.2851 + templateEngine['rewriteTemplate'](template, function (htmlString) {
195.2852 + return ko.templateRewriting.memoizeBindingAttributeSyntax(htmlString, templateEngine);
195.2853 + }, templateDocument);
195.2854 + },
195.2855 +
195.2856 + memoizeBindingAttributeSyntax: function (htmlString, templateEngine) {
195.2857 + return htmlString.replace(memoizeDataBindingAttributeSyntaxRegex, function () {
195.2858 + return constructMemoizedTagReplacement(/* dataBindAttributeValue: */ arguments[6], /* tagToRetain: */ arguments[1], templateEngine);
195.2859 + }).replace(memoizeVirtualContainerBindingSyntaxRegex, function() {
195.2860 + return constructMemoizedTagReplacement(/* dataBindAttributeValue: */ arguments[1], /* tagToRetain: */ "<!-- ko -->", templateEngine);
195.2861 + });
195.2862 + },
195.2863 +
195.2864 + applyMemoizedBindingsToNextSibling: function (bindings) {
195.2865 + return ko.memoization.memoize(function (domNode, bindingContext) {
195.2866 + if (domNode.nextSibling)
195.2867 + ko.applyBindingsToNode(domNode.nextSibling, bindings, bindingContext);
195.2868 + });
195.2869 + }
195.2870 + }
195.2871 +})();
195.2872 +
195.2873 +
195.2874 +// Exported only because it has to be referenced by string lookup from within rewritten template
195.2875 +ko.exportSymbol('__tr_ambtns', ko.templateRewriting.applyMemoizedBindingsToNextSibling);
195.2876 +(function() {
195.2877 + // A template source represents a read/write way of accessing a template. This is to eliminate the need for template loading/saving
195.2878 + // logic to be duplicated in every template engine (and means they can all work with anonymous templates, etc.)
195.2879 + //
195.2880 + // Two are provided by default:
195.2881 + // 1. ko.templateSources.domElement - reads/writes the text content of an arbitrary DOM element
195.2882 + // 2. ko.templateSources.anonymousElement - uses ko.utils.domData to read/write text *associated* with the DOM element, but
195.2883 + // without reading/writing the actual element text content, since it will be overwritten
195.2884 + // with the rendered template output.
195.2885 + // You can implement your own template source if you want to fetch/store templates somewhere other than in DOM elements.
195.2886 + // Template sources need to have the following functions:
195.2887 + // text() - returns the template text from your storage location
195.2888 + // text(value) - writes the supplied template text to your storage location
195.2889 + // data(key) - reads values stored using data(key, value) - see below
195.2890 + // data(key, value) - associates "value" with this template and the key "key". Is used to store information like "isRewritten".
195.2891 + //
195.2892 + // Optionally, template sources can also have the following functions:
195.2893 + // nodes() - returns a DOM element containing the nodes of this template, where available
195.2894 + // nodes(value) - writes the given DOM element to your storage location
195.2895 + // If a DOM element is available for a given template source, template engines are encouraged to use it in preference over text()
195.2896 + // for improved speed. However, all templateSources must supply text() even if they don't supply nodes().
195.2897 + //
195.2898 + // Once you've implemented a templateSource, make your template engine use it by subclassing whatever template engine you were
195.2899 + // using and overriding "makeTemplateSource" to return an instance of your custom template source.
195.2900 +
195.2901 + ko.templateSources = {};
195.2902 +
195.2903 + // ---- ko.templateSources.domElement -----
195.2904 +
195.2905 + ko.templateSources.domElement = function(element) {
195.2906 + this.domElement = element;
195.2907 + }
195.2908 +
195.2909 + ko.templateSources.domElement.prototype['text'] = function(/* valueToWrite */) {
195.2910 + var tagNameLower = ko.utils.tagNameLower(this.domElement),
195.2911 + elemContentsProperty = tagNameLower === "script" ? "text"
195.2912 + : tagNameLower === "textarea" ? "value"
195.2913 + : "innerHTML";
195.2914 +
195.2915 + if (arguments.length == 0) {
195.2916 + return this.domElement[elemContentsProperty];
195.2917 + } else {
195.2918 + var valueToWrite = arguments[0];
195.2919 + if (elemContentsProperty === "innerHTML")
195.2920 + ko.utils.setHtml(this.domElement, valueToWrite);
195.2921 + else
195.2922 + this.domElement[elemContentsProperty] = valueToWrite;
195.2923 + }
195.2924 + };
195.2925 +
195.2926 + ko.templateSources.domElement.prototype['data'] = function(key /*, valueToWrite */) {
195.2927 + if (arguments.length === 1) {
195.2928 + return ko.utils.domData.get(this.domElement, "templateSourceData_" + key);
195.2929 + } else {
195.2930 + ko.utils.domData.set(this.domElement, "templateSourceData_" + key, arguments[1]);
195.2931 + }
195.2932 + };
195.2933 +
195.2934 + // ---- ko.templateSources.anonymousTemplate -----
195.2935 + // Anonymous templates are normally saved/retrieved as DOM nodes through "nodes".
195.2936 + // For compatibility, you can also read "text"; it will be serialized from the nodes on demand.
195.2937 + // Writing to "text" is still supported, but then the template data will not be available as DOM nodes.
195.2938 +
195.2939 + var anonymousTemplatesDomDataKey = "__ko_anon_template__";
195.2940 + ko.templateSources.anonymousTemplate = function(element) {
195.2941 + this.domElement = element;
195.2942 + }
195.2943 + ko.templateSources.anonymousTemplate.prototype = new ko.templateSources.domElement();
195.2944 + ko.templateSources.anonymousTemplate.prototype['text'] = function(/* valueToWrite */) {
195.2945 + if (arguments.length == 0) {
195.2946 + var templateData = ko.utils.domData.get(this.domElement, anonymousTemplatesDomDataKey) || {};
195.2947 + if (templateData.textData === undefined && templateData.containerData)
195.2948 + templateData.textData = templateData.containerData.innerHTML;
195.2949 + return templateData.textData;
195.2950 + } else {
195.2951 + var valueToWrite = arguments[0];
195.2952 + ko.utils.domData.set(this.domElement, anonymousTemplatesDomDataKey, {textData: valueToWrite});
195.2953 + }
195.2954 + };
195.2955 + ko.templateSources.domElement.prototype['nodes'] = function(/* valueToWrite */) {
195.2956 + if (arguments.length == 0) {
195.2957 + var templateData = ko.utils.domData.get(this.domElement, anonymousTemplatesDomDataKey) || {};
195.2958 + return templateData.containerData;
195.2959 + } else {
195.2960 + var valueToWrite = arguments[0];
195.2961 + ko.utils.domData.set(this.domElement, anonymousTemplatesDomDataKey, {containerData: valueToWrite});
195.2962 + }
195.2963 + };
195.2964 +
195.2965 + ko.exportSymbol('templateSources', ko.templateSources);
195.2966 + ko.exportSymbol('templateSources.domElement', ko.templateSources.domElement);
195.2967 + ko.exportSymbol('templateSources.anonymousTemplate', ko.templateSources.anonymousTemplate);
195.2968 +})();
195.2969 +(function () {
195.2970 + var _templateEngine;
195.2971 + ko.setTemplateEngine = function (templateEngine) {
195.2972 + if ((templateEngine != undefined) && !(templateEngine instanceof ko.templateEngine))
195.2973 + throw new Error("templateEngine must inherit from ko.templateEngine");
195.2974 + _templateEngine = templateEngine;
195.2975 + }
195.2976 +
195.2977 + function invokeForEachNodeOrCommentInContinuousRange(firstNode, lastNode, action) {
195.2978 + var node, nextInQueue = firstNode, firstOutOfRangeNode = ko.virtualElements.nextSibling(lastNode);
195.2979 + while (nextInQueue && ((node = nextInQueue) !== firstOutOfRangeNode)) {
195.2980 + nextInQueue = ko.virtualElements.nextSibling(node);
195.2981 + if (node.nodeType === 1 || node.nodeType === 8)
195.2982 + action(node);
195.2983 + }
195.2984 + }
195.2985 +
195.2986 + function activateBindingsOnContinuousNodeArray(continuousNodeArray, bindingContext) {
195.2987 + // To be used on any nodes that have been rendered by a template and have been inserted into some parent element
195.2988 + // Walks through continuousNodeArray (which *must* be continuous, i.e., an uninterrupted sequence of sibling nodes, because
195.2989 + // the algorithm for walking them relies on this), and for each top-level item in the virtual-element sense,
195.2990 + // (1) Does a regular "applyBindings" to associate bindingContext with this node and to activate any non-memoized bindings
195.2991 + // (2) Unmemoizes any memos in the DOM subtree (e.g., to activate bindings that had been memoized during template rewriting)
195.2992 +
195.2993 + if (continuousNodeArray.length) {
195.2994 + var firstNode = continuousNodeArray[0], lastNode = continuousNodeArray[continuousNodeArray.length - 1];
195.2995 +
195.2996 + // Need to applyBindings *before* unmemoziation, because unmemoization might introduce extra nodes (that we don't want to re-bind)
195.2997 + // whereas a regular applyBindings won't introduce new memoized nodes
195.2998 + invokeForEachNodeOrCommentInContinuousRange(firstNode, lastNode, function(node) {
195.2999 + ko.applyBindings(bindingContext, node);
195.3000 + });
195.3001 + invokeForEachNodeOrCommentInContinuousRange(firstNode, lastNode, function(node) {
195.3002 + ko.memoization.unmemoizeDomNodeAndDescendants(node, [bindingContext]);
195.3003 + });
195.3004 + }
195.3005 + }
195.3006 +
195.3007 + function getFirstNodeFromPossibleArray(nodeOrNodeArray) {
195.3008 + return nodeOrNodeArray.nodeType ? nodeOrNodeArray
195.3009 + : nodeOrNodeArray.length > 0 ? nodeOrNodeArray[0]
195.3010 + : null;
195.3011 + }
195.3012 +
195.3013 + function executeTemplate(targetNodeOrNodeArray, renderMode, template, bindingContext, options) {
195.3014 + options = options || {};
195.3015 + var firstTargetNode = targetNodeOrNodeArray && getFirstNodeFromPossibleArray(targetNodeOrNodeArray);
195.3016 + var templateDocument = firstTargetNode && firstTargetNode.ownerDocument;
195.3017 + var templateEngineToUse = (options['templateEngine'] || _templateEngine);
195.3018 + ko.templateRewriting.ensureTemplateIsRewritten(template, templateEngineToUse, templateDocument);
195.3019 + var renderedNodesArray = templateEngineToUse['renderTemplate'](template, bindingContext, options, templateDocument);
195.3020 +
195.3021 + // Loosely check result is an array of DOM nodes
195.3022 + if ((typeof renderedNodesArray.length != "number") || (renderedNodesArray.length > 0 && typeof renderedNodesArray[0].nodeType != "number"))
195.3023 + throw new Error("Template engine must return an array of DOM nodes");
195.3024 +
195.3025 + var haveAddedNodesToParent = false;
195.3026 + switch (renderMode) {
195.3027 + case "replaceChildren":
195.3028 + ko.virtualElements.setDomNodeChildren(targetNodeOrNodeArray, renderedNodesArray);
195.3029 + haveAddedNodesToParent = true;
195.3030 + break;
195.3031 + case "replaceNode":
195.3032 + ko.utils.replaceDomNodes(targetNodeOrNodeArray, renderedNodesArray);
195.3033 + haveAddedNodesToParent = true;
195.3034 + break;
195.3035 + case "ignoreTargetNode": break;
195.3036 + default:
195.3037 + throw new Error("Unknown renderMode: " + renderMode);
195.3038 + }
195.3039 +
195.3040 + if (haveAddedNodesToParent) {
195.3041 + activateBindingsOnContinuousNodeArray(renderedNodesArray, bindingContext);
195.3042 + if (options['afterRender'])
195.3043 + ko.dependencyDetection.ignore(options['afterRender'], null, [renderedNodesArray, bindingContext['$data']]);
195.3044 + }
195.3045 +
195.3046 + return renderedNodesArray;
195.3047 + }
195.3048 +
195.3049 + ko.renderTemplate = function (template, dataOrBindingContext, options, targetNodeOrNodeArray, renderMode) {
195.3050 + options = options || {};
195.3051 + if ((options['templateEngine'] || _templateEngine) == undefined)
195.3052 + throw new Error("Set a template engine before calling renderTemplate");
195.3053 + renderMode = renderMode || "replaceChildren";
195.3054 +
195.3055 + if (targetNodeOrNodeArray) {
195.3056 + var firstTargetNode = getFirstNodeFromPossibleArray(targetNodeOrNodeArray);
195.3057 +
195.3058 + var whenToDispose = function () { return (!firstTargetNode) || !ko.utils.domNodeIsAttachedToDocument(firstTargetNode); }; // Passive disposal (on next evaluation)
195.3059 + var activelyDisposeWhenNodeIsRemoved = (firstTargetNode && renderMode == "replaceNode") ? firstTargetNode.parentNode : firstTargetNode;
195.3060 +
195.3061 + return ko.dependentObservable( // So the DOM is automatically updated when any dependency changes
195.3062 + function () {
195.3063 + // Ensure we've got a proper binding context to work with
195.3064 + var bindingContext = (dataOrBindingContext && (dataOrBindingContext instanceof ko.bindingContext))
195.3065 + ? dataOrBindingContext
195.3066 + : new ko.bindingContext(ko.utils.unwrapObservable(dataOrBindingContext));
195.3067 +
195.3068 + // Support selecting template as a function of the data being rendered
195.3069 + var templateName = typeof(template) == 'function' ? template(bindingContext['$data'], bindingContext) : template;
195.3070 +
195.3071 + var renderedNodesArray = executeTemplate(targetNodeOrNodeArray, renderMode, templateName, bindingContext, options);
195.3072 + if (renderMode == "replaceNode") {
195.3073 + targetNodeOrNodeArray = renderedNodesArray;
195.3074 + firstTargetNode = getFirstNodeFromPossibleArray(targetNodeOrNodeArray);
195.3075 + }
195.3076 + },
195.3077 + null,
195.3078 + { disposeWhen: whenToDispose, disposeWhenNodeIsRemoved: activelyDisposeWhenNodeIsRemoved }
195.3079 + );
195.3080 + } else {
195.3081 + // We don't yet have a DOM node to evaluate, so use a memo and render the template later when there is a DOM node
195.3082 + return ko.memoization.memoize(function (domNode) {
195.3083 + ko.renderTemplate(template, dataOrBindingContext, options, domNode, "replaceNode");
195.3084 + });
195.3085 + }
195.3086 + };
195.3087 +
195.3088 + ko.renderTemplateForEach = function (template, arrayOrObservableArray, options, targetNode, parentBindingContext) {
195.3089 + // Since setDomNodeChildrenFromArrayMapping always calls executeTemplateForArrayItem and then
195.3090 + // activateBindingsCallback for added items, we can store the binding context in the former to use in the latter.
195.3091 + var arrayItemContext;
195.3092 +
195.3093 + // This will be called by setDomNodeChildrenFromArrayMapping to get the nodes to add to targetNode
195.3094 + var executeTemplateForArrayItem = function (arrayValue, index) {
195.3095 + // Support selecting template as a function of the data being rendered
195.3096 + arrayItemContext = parentBindingContext['createChildContext'](ko.utils.unwrapObservable(arrayValue), options['as']);
195.3097 + arrayItemContext['$index'] = index;
195.3098 + var templateName = typeof(template) == 'function' ? template(arrayValue, arrayItemContext) : template;
195.3099 + return executeTemplate(null, "ignoreTargetNode", templateName, arrayItemContext, options);
195.3100 + }
195.3101 +
195.3102 + // This will be called whenever setDomNodeChildrenFromArrayMapping has added nodes to targetNode
195.3103 + var activateBindingsCallback = function(arrayValue, addedNodesArray, index) {
195.3104 + activateBindingsOnContinuousNodeArray(addedNodesArray, arrayItemContext);
195.3105 + if (options['afterRender'])
195.3106 + options['afterRender'](addedNodesArray, arrayValue);
195.3107 + };
195.3108 +
195.3109 + return ko.dependentObservable(function () {
195.3110 + var unwrappedArray = ko.utils.unwrapObservable(arrayOrObservableArray) || [];
195.3111 + if (typeof unwrappedArray.length == "undefined") // Coerce single value into array
195.3112 + unwrappedArray = [unwrappedArray];
195.3113 +
195.3114 + // Filter out any entries marked as destroyed
195.3115 + var filteredArray = ko.utils.arrayFilter(unwrappedArray, function(item) {
195.3116 + return options['includeDestroyed'] || item === undefined || item === null || !ko.utils.unwrapObservable(item['_destroy']);
195.3117 + });
195.3118 +
195.3119 + // Call setDomNodeChildrenFromArrayMapping, ignoring any observables unwrapped within (most likely from a callback function).
195.3120 + // If the array items are observables, though, they will be unwrapped in executeTemplateForArrayItem and managed within setDomNodeChildrenFromArrayMapping.
195.3121 + ko.dependencyDetection.ignore(ko.utils.setDomNodeChildrenFromArrayMapping, null, [targetNode, filteredArray, executeTemplateForArrayItem, options, activateBindingsCallback]);
195.3122 +
195.3123 + }, null, { disposeWhenNodeIsRemoved: targetNode });
195.3124 + };
195.3125 +
195.3126 + var templateComputedDomDataKey = '__ko__templateComputedDomDataKey__';
195.3127 + function disposeOldComputedAndStoreNewOne(element, newComputed) {
195.3128 + var oldComputed = ko.utils.domData.get(element, templateComputedDomDataKey);
195.3129 + if (oldComputed && (typeof(oldComputed.dispose) == 'function'))
195.3130 + oldComputed.dispose();
195.3131 + ko.utils.domData.set(element, templateComputedDomDataKey, (newComputed && newComputed.isActive()) ? newComputed : undefined);
195.3132 + }
195.3133 +
195.3134 + ko.bindingHandlers['template'] = {
195.3135 + 'init': function(element, valueAccessor) {
195.3136 + // Support anonymous templates
195.3137 + var bindingValue = ko.utils.unwrapObservable(valueAccessor());
195.3138 + if ((typeof bindingValue != "string") && (!bindingValue['name']) && (element.nodeType == 1 || element.nodeType == 8)) {
195.3139 + // It's an anonymous template - store the element contents, then clear the element
195.3140 + var templateNodes = element.nodeType == 1 ? element.childNodes : ko.virtualElements.childNodes(element),
195.3141 + container = ko.utils.moveCleanedNodesToContainerElement(templateNodes); // This also removes the nodes from their current parent
195.3142 + new ko.templateSources.anonymousTemplate(element)['nodes'](container);
195.3143 + }
195.3144 + return { 'controlsDescendantBindings': true };
195.3145 + },
195.3146 + 'update': function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
195.3147 + var templateName = ko.utils.unwrapObservable(valueAccessor()),
195.3148 + options = {},
195.3149 + shouldDisplay = true,
195.3150 + dataValue,
195.3151 + templateComputed = null;
195.3152 +
195.3153 + if (typeof templateName != "string") {
195.3154 + options = templateName;
195.3155 + templateName = options['name'];
195.3156 +
195.3157 + // Support "if"/"ifnot" conditions
195.3158 + if ('if' in options)
195.3159 + shouldDisplay = ko.utils.unwrapObservable(options['if']);
195.3160 + if (shouldDisplay && 'ifnot' in options)
195.3161 + shouldDisplay = !ko.utils.unwrapObservable(options['ifnot']);
195.3162 +
195.3163 + dataValue = ko.utils.unwrapObservable(options['data']);
195.3164 + }
195.3165 +
195.3166 + if ('foreach' in options) {
195.3167 + // Render once for each data point (treating data set as empty if shouldDisplay==false)
195.3168 + var dataArray = (shouldDisplay && options['foreach']) || [];
195.3169 + templateComputed = ko.renderTemplateForEach(templateName || element, dataArray, options, element, bindingContext);
195.3170 + } else if (!shouldDisplay) {
195.3171 + ko.virtualElements.emptyNode(element);
195.3172 + } else {
195.3173 + // Render once for this single data point (or use the viewModel if no data was provided)
195.3174 + var innerBindingContext = ('data' in options) ?
195.3175 + bindingContext['createChildContext'](dataValue, options['as']) : // Given an explitit 'data' value, we create a child binding context for it
195.3176 + bindingContext; // Given no explicit 'data' value, we retain the same binding context
195.3177 + templateComputed = ko.renderTemplate(templateName || element, innerBindingContext, options, element);
195.3178 + }
195.3179 +
195.3180 + // It only makes sense to have a single template computed per element (otherwise which one should have its output displayed?)
195.3181 + disposeOldComputedAndStoreNewOne(element, templateComputed);
195.3182 + }
195.3183 + };
195.3184 +
195.3185 + // Anonymous templates can't be rewritten. Give a nice error message if you try to do it.
195.3186 + ko.expressionRewriting.bindingRewriteValidators['template'] = function(bindingValue) {
195.3187 + var parsedBindingValue = ko.expressionRewriting.parseObjectLiteral(bindingValue);
195.3188 +
195.3189 + if ((parsedBindingValue.length == 1) && parsedBindingValue[0]['unknown'])
195.3190 + return null; // It looks like a string literal, not an object literal, so treat it as a named template (which is allowed for rewriting)
195.3191 +
195.3192 + if (ko.expressionRewriting.keyValueArrayContainsKey(parsedBindingValue, "name"))
195.3193 + return null; // Named templates can be rewritten, so return "no error"
195.3194 + return "This template engine does not support anonymous templates nested within its templates";
195.3195 + };
195.3196 +
195.3197 + ko.virtualElements.allowedBindings['template'] = true;
195.3198 +})();
195.3199 +
195.3200 +ko.exportSymbol('setTemplateEngine', ko.setTemplateEngine);
195.3201 +ko.exportSymbol('renderTemplate', ko.renderTemplate);
195.3202 +
195.3203 +ko.utils.compareArrays = (function () {
195.3204 + var statusNotInOld = 'added', statusNotInNew = 'deleted';
195.3205 +
195.3206 + // Simple calculation based on Levenshtein distance.
195.3207 + function compareArrays(oldArray, newArray, dontLimitMoves) {
195.3208 + oldArray = oldArray || [];
195.3209 + newArray = newArray || [];
195.3210 +
195.3211 + if (oldArray.length <= newArray.length)
195.3212 + return compareSmallArrayToBigArray(oldArray, newArray, statusNotInOld, statusNotInNew, dontLimitMoves);
195.3213 + else
195.3214 + return compareSmallArrayToBigArray(newArray, oldArray, statusNotInNew, statusNotInOld, dontLimitMoves);
195.3215 + }
195.3216 +
195.3217 + function compareSmallArrayToBigArray(smlArray, bigArray, statusNotInSml, statusNotInBig, dontLimitMoves) {
195.3218 + var myMin = Math.min,
195.3219 + myMax = Math.max,
195.3220 + editDistanceMatrix = [],
195.3221 + smlIndex, smlIndexMax = smlArray.length,
195.3222 + bigIndex, bigIndexMax = bigArray.length,
195.3223 + compareRange = (bigIndexMax - smlIndexMax) || 1,
195.3224 + maxDistance = smlIndexMax + bigIndexMax + 1,
195.3225 + thisRow, lastRow,
195.3226 + bigIndexMaxForRow, bigIndexMinForRow;
195.3227 +
195.3228 + for (smlIndex = 0; smlIndex <= smlIndexMax; smlIndex++) {
195.3229 + lastRow = thisRow;
195.3230 + editDistanceMatrix.push(thisRow = []);
195.3231 + bigIndexMaxForRow = myMin(bigIndexMax, smlIndex + compareRange);
195.3232 + bigIndexMinForRow = myMax(0, smlIndex - 1);
195.3233 + for (bigIndex = bigIndexMinForRow; bigIndex <= bigIndexMaxForRow; bigIndex++) {
195.3234 + if (!bigIndex)
195.3235 + thisRow[bigIndex] = smlIndex + 1;
195.3236 + else if (!smlIndex) // Top row - transform empty array into new array via additions
195.3237 + thisRow[bigIndex] = bigIndex + 1;
195.3238 + else if (smlArray[smlIndex - 1] === bigArray[bigIndex - 1])
195.3239 + thisRow[bigIndex] = lastRow[bigIndex - 1]; // copy value (no edit)
195.3240 + else {
195.3241 + var northDistance = lastRow[bigIndex] || maxDistance; // not in big (deletion)
195.3242 + var westDistance = thisRow[bigIndex - 1] || maxDistance; // not in small (addition)
195.3243 + thisRow[bigIndex] = myMin(northDistance, westDistance) + 1;
195.3244 + }
195.3245 + }
195.3246 + }
195.3247 +
195.3248 + var editScript = [], meMinusOne, notInSml = [], notInBig = [];
195.3249 + for (smlIndex = smlIndexMax, bigIndex = bigIndexMax; smlIndex || bigIndex;) {
195.3250 + meMinusOne = editDistanceMatrix[smlIndex][bigIndex] - 1;
195.3251 + if (bigIndex && meMinusOne === editDistanceMatrix[smlIndex][bigIndex-1]) {
195.3252 + notInSml.push(editScript[editScript.length] = { // added
195.3253 + 'status': statusNotInSml,
195.3254 + 'value': bigArray[--bigIndex],
195.3255 + 'index': bigIndex });
195.3256 + } else if (smlIndex && meMinusOne === editDistanceMatrix[smlIndex - 1][bigIndex]) {
195.3257 + notInBig.push(editScript[editScript.length] = { // deleted
195.3258 + 'status': statusNotInBig,
195.3259 + 'value': smlArray[--smlIndex],
195.3260 + 'index': smlIndex });
195.3261 + } else {
195.3262 + editScript.push({
195.3263 + 'status': "retained",
195.3264 + 'value': bigArray[--bigIndex] });
195.3265 + --smlIndex;
195.3266 + }
195.3267 + }
195.3268 +
195.3269 + if (notInSml.length && notInBig.length) {
195.3270 + // Set a limit on the number of consecutive non-matching comparisons; having it a multiple of
195.3271 + // smlIndexMax keeps the time complexity of this algorithm linear.
195.3272 + var limitFailedCompares = smlIndexMax * 10, failedCompares,
195.3273 + a, d, notInSmlItem, notInBigItem;
195.3274 + // Go through the items that have been added and deleted and try to find matches between them.
195.3275 + for (failedCompares = a = 0; (dontLimitMoves || failedCompares < limitFailedCompares) && (notInSmlItem = notInSml[a]); a++) {
195.3276 + for (d = 0; notInBigItem = notInBig[d]; d++) {
195.3277 + if (notInSmlItem['value'] === notInBigItem['value']) {
195.3278 + notInSmlItem['moved'] = notInBigItem['index'];
195.3279 + notInBigItem['moved'] = notInSmlItem['index'];
195.3280 + notInBig.splice(d,1); // This item is marked as moved; so remove it from notInBig list
195.3281 + failedCompares = d = 0; // Reset failed compares count because we're checking for consecutive failures
195.3282 + break;
195.3283 + }
195.3284 + }
195.3285 + failedCompares += d;
195.3286 + }
195.3287 + }
195.3288 + return editScript.reverse();
195.3289 + }
195.3290 +
195.3291 + return compareArrays;
195.3292 +})();
195.3293 +
195.3294 +ko.exportSymbol('utils.compareArrays', ko.utils.compareArrays);
195.3295 +
195.3296 +(function () {
195.3297 + // Objective:
195.3298 + // * Given an input array, a container DOM node, and a function from array elements to arrays of DOM nodes,
195.3299 + // map the array elements to arrays of DOM nodes, concatenate together all these arrays, and use them to populate the container DOM node
195.3300 + // * Next time we're given the same combination of things (with the array possibly having mutated), update the container DOM node
195.3301 + // so that its children is again the concatenation of the mappings of the array elements, but don't re-map any array elements that we
195.3302 + // previously mapped - retain those nodes, and just insert/delete other ones
195.3303 +
195.3304 + // "callbackAfterAddingNodes" will be invoked after any "mapping"-generated nodes are inserted into the container node
195.3305 + // You can use this, for example, to activate bindings on those nodes.
195.3306 +
195.3307 + function fixUpNodesToBeMovedOrRemoved(contiguousNodeArray) {
195.3308 + // Before moving, deleting, or replacing a set of nodes that were previously outputted by the "map" function, we have to reconcile
195.3309 + // them against what is in the DOM right now. It may be that some of the nodes have already been removed from the document,
195.3310 + // or that new nodes might have been inserted in the middle, for example by a binding. Also, there may previously have been
195.3311 + // leading comment nodes (created by rewritten string-based templates) that have since been removed during binding.
195.3312 + // So, this function translates the old "map" output array into its best guess of what set of current DOM nodes should be removed.
195.3313 + //
195.3314 + // Rules:
195.3315 + // [A] Any leading nodes that aren't in the document any more should be ignored
195.3316 + // These most likely correspond to memoization nodes that were already removed during binding
195.3317 + // See https://github.com/SteveSanderson/knockout/pull/440
195.3318 + // [B] We want to output a contiguous series of nodes that are still in the document. So, ignore any nodes that
195.3319 + // have already been removed, and include any nodes that have been inserted among the previous collection
195.3320 +
195.3321 + // Rule [A]
195.3322 + while (contiguousNodeArray.length && !ko.utils.domNodeIsAttachedToDocument(contiguousNodeArray[0]))
195.3323 + contiguousNodeArray.splice(0, 1);
195.3324 +
195.3325 + // Rule [B]
195.3326 + if (contiguousNodeArray.length > 1) {
195.3327 + // Build up the actual new contiguous node set
195.3328 + var current = contiguousNodeArray[0], last = contiguousNodeArray[contiguousNodeArray.length - 1], newContiguousSet = [current];
195.3329 + while (current !== last) {
195.3330 + current = current.nextSibling;
195.3331 + if (!current) // Won't happen, except if the developer has manually removed some DOM elements (then we're in an undefined scenario)
195.3332 + return;
195.3333 + newContiguousSet.push(current);
195.3334 + }
195.3335 +
195.3336 + // ... then mutate the input array to match this.
195.3337 + // (The following line replaces the contents of contiguousNodeArray with newContiguousSet)
195.3338 + Array.prototype.splice.apply(contiguousNodeArray, [0, contiguousNodeArray.length].concat(newContiguousSet));
195.3339 + }
195.3340 + return contiguousNodeArray;
195.3341 + }
195.3342 +
195.3343 + function mapNodeAndRefreshWhenChanged(containerNode, mapping, valueToMap, callbackAfterAddingNodes, index) {
195.3344 + // Map this array value inside a dependentObservable so we re-map when any dependency changes
195.3345 + var mappedNodes = [];
195.3346 + var dependentObservable = ko.dependentObservable(function() {
195.3347 + var newMappedNodes = mapping(valueToMap, index) || [];
195.3348 +
195.3349 + // On subsequent evaluations, just replace the previously-inserted DOM nodes
195.3350 + if (mappedNodes.length > 0) {
195.3351 + ko.utils.replaceDomNodes(fixUpNodesToBeMovedOrRemoved(mappedNodes), newMappedNodes);
195.3352 + if (callbackAfterAddingNodes)
195.3353 + ko.dependencyDetection.ignore(callbackAfterAddingNodes, null, [valueToMap, newMappedNodes, index]);
195.3354 + }
195.3355 +
195.3356 + // Replace the contents of the mappedNodes array, thereby updating the record
195.3357 + // of which nodes would be deleted if valueToMap was itself later removed
195.3358 + mappedNodes.splice(0, mappedNodes.length);
195.3359 + ko.utils.arrayPushAll(mappedNodes, newMappedNodes);
195.3360 + }, null, { disposeWhenNodeIsRemoved: containerNode, disposeWhen: function() { return (mappedNodes.length == 0) || !ko.utils.domNodeIsAttachedToDocument(mappedNodes[0]) } });
195.3361 + return { mappedNodes : mappedNodes, dependentObservable : (dependentObservable.isActive() ? dependentObservable : undefined) };
195.3362 + }
195.3363 +
195.3364 + var lastMappingResultDomDataKey = "setDomNodeChildrenFromArrayMapping_lastMappingResult";
195.3365 +
195.3366 + ko.utils.setDomNodeChildrenFromArrayMapping = function (domNode, array, mapping, options, callbackAfterAddingNodes) {
195.3367 + // Compare the provided array against the previous one
195.3368 + array = array || [];
195.3369 + options = options || {};
195.3370 + var isFirstExecution = ko.utils.domData.get(domNode, lastMappingResultDomDataKey) === undefined;
195.3371 + var lastMappingResult = ko.utils.domData.get(domNode, lastMappingResultDomDataKey) || [];
195.3372 + var lastArray = ko.utils.arrayMap(lastMappingResult, function (x) { return x.arrayEntry; });
195.3373 + var editScript = ko.utils.compareArrays(lastArray, array);
195.3374 +
195.3375 + // Build the new mapping result
195.3376 + var newMappingResult = [];
195.3377 + var lastMappingResultIndex = 0;
195.3378 + var newMappingResultIndex = 0;
195.3379 +
195.3380 + var nodesToDelete = [];
195.3381 + var itemsToProcess = [];
195.3382 + var itemsForBeforeRemoveCallbacks = [];
195.3383 + var itemsForMoveCallbacks = [];
195.3384 + var itemsForAfterAddCallbacks = [];
195.3385 + var mapData;
195.3386 +
195.3387 + function itemMovedOrRetained(editScriptIndex, oldPosition) {
195.3388 + mapData = lastMappingResult[oldPosition];
195.3389 + if (newMappingResultIndex !== oldPosition)
195.3390 + itemsForMoveCallbacks[editScriptIndex] = mapData;
195.3391 + // Since updating the index might change the nodes, do so before calling fixUpNodesToBeMovedOrRemoved
195.3392 + mapData.indexObservable(newMappingResultIndex++);
195.3393 + fixUpNodesToBeMovedOrRemoved(mapData.mappedNodes);
195.3394 + newMappingResult.push(mapData);
195.3395 + itemsToProcess.push(mapData);
195.3396 + }
195.3397 +
195.3398 + function callCallback(callback, items) {
195.3399 + if (callback) {
195.3400 + for (var i = 0, n = items.length; i < n; i++) {
195.3401 + if (items[i]) {
195.3402 + ko.utils.arrayForEach(items[i].mappedNodes, function(node) {
195.3403 + callback(node, i, items[i].arrayEntry);
195.3404 + });
195.3405 + }
195.3406 + }
195.3407 + }
195.3408 + }
195.3409 +
195.3410 + for (var i = 0, editScriptItem, movedIndex; editScriptItem = editScript[i]; i++) {
195.3411 + movedIndex = editScriptItem['moved'];
195.3412 + switch (editScriptItem['status']) {
195.3413 + case "deleted":
195.3414 + if (movedIndex === undefined) {
195.3415 + mapData = lastMappingResult[lastMappingResultIndex];
195.3416 +
195.3417 + // Stop tracking changes to the mapping for these nodes
195.3418 + if (mapData.dependentObservable)
195.3419 + mapData.dependentObservable.dispose();
195.3420 +
195.3421 + // Queue these nodes for later removal
195.3422 + nodesToDelete.push.apply(nodesToDelete, fixUpNodesToBeMovedOrRemoved(mapData.mappedNodes));
195.3423 + if (options['beforeRemove']) {
195.3424 + itemsForBeforeRemoveCallbacks[i] = mapData;
195.3425 + itemsToProcess.push(mapData);
195.3426 + }
195.3427 + }
195.3428 + lastMappingResultIndex++;
195.3429 + break;
195.3430 +
195.3431 + case "retained":
195.3432 + itemMovedOrRetained(i, lastMappingResultIndex++);
195.3433 + break;
195.3434 +
195.3435 + case "added":
195.3436 + if (movedIndex !== undefined) {
195.3437 + itemMovedOrRetained(i, movedIndex);
195.3438 + } else {
195.3439 + mapData = { arrayEntry: editScriptItem['value'], indexObservable: ko.observable(newMappingResultIndex++) };
195.3440 + newMappingResult.push(mapData);
195.3441 + itemsToProcess.push(mapData);
195.3442 + if (!isFirstExecution)
195.3443 + itemsForAfterAddCallbacks[i] = mapData;
195.3444 + }
195.3445 + break;
195.3446 + }
195.3447 + }
195.3448 +
195.3449 + // Call beforeMove first before any changes have been made to the DOM
195.3450 + callCallback(options['beforeMove'], itemsForMoveCallbacks);
195.3451 +
195.3452 + // Next remove nodes for deleted items (or just clean if there's a beforeRemove callback)
195.3453 + ko.utils.arrayForEach(nodesToDelete, options['beforeRemove'] ? ko.cleanNode : ko.removeNode);
195.3454 +
195.3455 + // Next add/reorder the remaining items (will include deleted items if there's a beforeRemove callback)
195.3456 + for (var i = 0, nextNode = ko.virtualElements.firstChild(domNode), lastNode, node; mapData = itemsToProcess[i]; i++) {
195.3457 + // Get nodes for newly added items
195.3458 + if (!mapData.mappedNodes)
195.3459 + ko.utils.extend(mapData, mapNodeAndRefreshWhenChanged(domNode, mapping, mapData.arrayEntry, callbackAfterAddingNodes, mapData.indexObservable));
195.3460 +
195.3461 + // Put nodes in the right place if they aren't there already
195.3462 + for (var j = 0; node = mapData.mappedNodes[j]; nextNode = node.nextSibling, lastNode = node, j++) {
195.3463 + if (node !== nextNode)
195.3464 + ko.virtualElements.insertAfter(domNode, node, lastNode);
195.3465 + }
195.3466 +
195.3467 + // Run the callbacks for newly added nodes (for example, to apply bindings, etc.)
195.3468 + if (!mapData.initialized && callbackAfterAddingNodes) {
195.3469 + callbackAfterAddingNodes(mapData.arrayEntry, mapData.mappedNodes, mapData.indexObservable);
195.3470 + mapData.initialized = true;
195.3471 + }
195.3472 + }
195.3473 +
195.3474 + // If there's a beforeRemove callback, call it after reordering.
195.3475 + // Note that we assume that the beforeRemove callback will usually be used to remove the nodes using
195.3476 + // some sort of animation, which is why we first reorder the nodes that will be removed. If the
195.3477 + // callback instead removes the nodes right away, it would be more efficient to skip reordering them.
195.3478 + // Perhaps we'll make that change in the future if this scenario becomes more common.
195.3479 + callCallback(options['beforeRemove'], itemsForBeforeRemoveCallbacks);
195.3480 +
195.3481 + // Finally call afterMove and afterAdd callbacks
195.3482 + callCallback(options['afterMove'], itemsForMoveCallbacks);
195.3483 + callCallback(options['afterAdd'], itemsForAfterAddCallbacks);
195.3484 +
195.3485 + // Store a copy of the array items we just considered so we can difference it next time
195.3486 + ko.utils.domData.set(domNode, lastMappingResultDomDataKey, newMappingResult);
195.3487 + }
195.3488 +})();
195.3489 +
195.3490 +ko.exportSymbol('utils.setDomNodeChildrenFromArrayMapping', ko.utils.setDomNodeChildrenFromArrayMapping);
195.3491 +ko.nativeTemplateEngine = function () {
195.3492 + this['allowTemplateRewriting'] = false;
195.3493 +}
195.3494 +
195.3495 +ko.nativeTemplateEngine.prototype = new ko.templateEngine();
195.3496 +ko.nativeTemplateEngine.prototype['renderTemplateSource'] = function (templateSource, bindingContext, options) {
195.3497 + var useNodesIfAvailable = !(ko.utils.ieVersion < 9), // IE<9 cloneNode doesn't work properly
195.3498 + templateNodesFunc = useNodesIfAvailable ? templateSource['nodes'] : null,
195.3499 + templateNodes = templateNodesFunc ? templateSource['nodes']() : null;
195.3500 +
195.3501 + if (templateNodes) {
195.3502 + return ko.utils.makeArray(templateNodes.cloneNode(true).childNodes);
195.3503 + } else {
195.3504 + var templateText = templateSource['text']();
195.3505 + return ko.utils.parseHtmlFragment(templateText);
195.3506 + }
195.3507 +};
195.3508 +
195.3509 +ko.nativeTemplateEngine.instance = new ko.nativeTemplateEngine();
195.3510 +ko.setTemplateEngine(ko.nativeTemplateEngine.instance);
195.3511 +
195.3512 +ko.exportSymbol('nativeTemplateEngine', ko.nativeTemplateEngine);
195.3513 +(function() {
195.3514 + ko.jqueryTmplTemplateEngine = function () {
195.3515 + // Detect which version of jquery-tmpl you're using. Unfortunately jquery-tmpl
195.3516 + // doesn't expose a version number, so we have to infer it.
195.3517 + // Note that as of Knockout 1.3, we only support jQuery.tmpl 1.0.0pre and later,
195.3518 + // which KO internally refers to as version "2", so older versions are no longer detected.
195.3519 + var jQueryTmplVersion = this.jQueryTmplVersion = (function() {
195.3520 + if ((typeof(jQuery) == "undefined") || !(jQuery['tmpl']))
195.3521 + return 0;
195.3522 + // Since it exposes no official version number, we use our own numbering system. To be updated as jquery-tmpl evolves.
195.3523 + try {
195.3524 + if (jQuery['tmpl']['tag']['tmpl']['open'].toString().indexOf('__') >= 0) {
195.3525 + // Since 1.0.0pre, custom tags should append markup to an array called "__"
195.3526 + return 2; // Final version of jquery.tmpl
195.3527 + }
195.3528 + } catch(ex) { /* Apparently not the version we were looking for */ }
195.3529 +
195.3530 + return 1; // Any older version that we don't support
195.3531 + })();
195.3532 +
195.3533 + function ensureHasReferencedJQueryTemplates() {
195.3534 + if (jQueryTmplVersion < 2)
195.3535 + throw new Error("Your version of jQuery.tmpl is too old. Please upgrade to jQuery.tmpl 1.0.0pre or later.");
195.3536 + }
195.3537 +
195.3538 + function executeTemplate(compiledTemplate, data, jQueryTemplateOptions) {
195.3539 + return jQuery['tmpl'](compiledTemplate, data, jQueryTemplateOptions);
195.3540 + }
195.3541 +
195.3542 + this['renderTemplateSource'] = function(templateSource, bindingContext, options) {
195.3543 + options = options || {};
195.3544 + ensureHasReferencedJQueryTemplates();
195.3545 +
195.3546 + // Ensure we have stored a precompiled version of this template (don't want to reparse on every render)
195.3547 + var precompiled = templateSource['data']('precompiled');
195.3548 + if (!precompiled) {
195.3549 + var templateText = templateSource['text']() || "";
195.3550 + // Wrap in "with($whatever.koBindingContext) { ... }"
195.3551 + templateText = "{{ko_with $item.koBindingContext}}" + templateText + "{{/ko_with}}";
195.3552 +
195.3553 + precompiled = jQuery['template'](null, templateText);
195.3554 + templateSource['data']('precompiled', precompiled);
195.3555 + }
195.3556 +
195.3557 + var data = [bindingContext['$data']]; // Prewrap the data in an array to stop jquery.tmpl from trying to unwrap any arrays
195.3558 + var jQueryTemplateOptions = jQuery['extend']({ 'koBindingContext': bindingContext }, options['templateOptions']);
195.3559 +
195.3560 + var resultNodes = executeTemplate(precompiled, data, jQueryTemplateOptions);
195.3561 + resultNodes['appendTo'](document.createElement("div")); // Using "appendTo" forces jQuery/jQuery.tmpl to perform necessary cleanup work
195.3562 +
195.3563 + jQuery['fragments'] = {}; // Clear jQuery's fragment cache to avoid a memory leak after a large number of template renders
195.3564 + return resultNodes;
195.3565 + };
195.3566 +
195.3567 + this['createJavaScriptEvaluatorBlock'] = function(script) {
195.3568 + return "{{ko_code ((function() { return " + script + " })()) }}";
195.3569 + };
195.3570 +
195.3571 + this['addTemplate'] = function(templateName, templateMarkup) {
195.3572 + document.write("<script type='text/html' id='" + templateName + "'>" + templateMarkup + "</script>");
195.3573 + };
195.3574 +
195.3575 + if (jQueryTmplVersion > 0) {
195.3576 + jQuery['tmpl']['tag']['ko_code'] = {
195.3577 + open: "__.push($1 || '');"
195.3578 + };
195.3579 + jQuery['tmpl']['tag']['ko_with'] = {
195.3580 + open: "with($1) {",
195.3581 + close: "} "
195.3582 + };
195.3583 + }
195.3584 + };
195.3585 +
195.3586 + ko.jqueryTmplTemplateEngine.prototype = new ko.templateEngine();
195.3587 +
195.3588 + // Use this one by default *only if jquery.tmpl is referenced*
195.3589 + var jqueryTmplTemplateEngineInstance = new ko.jqueryTmplTemplateEngine();
195.3590 + if (jqueryTmplTemplateEngineInstance.jQueryTmplVersion > 0)
195.3591 + ko.setTemplateEngine(jqueryTmplTemplateEngineInstance);
195.3592 +
195.3593 + ko.exportSymbol('jqueryTmplTemplateEngine', ko.jqueryTmplTemplateEngine);
195.3594 +})();
195.3595 +});
195.3596 +})(window,document,navigator,window["jQuery"]);
195.3597 +})();
195.3598 \ No newline at end of file
196.1 --- a/ko-fx/src/test/java/org/apidesign/html/kofx/DynamicHTTP.java Thu Dec 19 17:11:01 2013 +0100
196.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
196.3 @@ -1,237 +0,0 @@
196.4 -/**
196.5 - * HTML via Java(tm) Language Bindings
196.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
196.7 - *
196.8 - * This program is free software: you can redistribute it and/or modify
196.9 - * it under the terms of the GNU General Public License as published by
196.10 - * the Free Software Foundation, version 2 of the License.
196.11 - *
196.12 - * This program is distributed in the hope that it will be useful,
196.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
196.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
196.15 - * GNU General Public License for more details. apidesign.org
196.16 - * designates this particular file as subject to the
196.17 - * "Classpath" exception as provided by apidesign.org
196.18 - * in the License file that accompanied this code.
196.19 - *
196.20 - * You should have received a copy of the GNU General Public License
196.21 - * along with this program. Look for COPYING file in the top folder.
196.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
196.23 - */
196.24 -package org.apidesign.html.kofx;
196.25 -
196.26 -import java.io.ByteArrayInputStream;
196.27 -import java.io.ByteArrayOutputStream;
196.28 -import java.io.IOException;
196.29 -import java.io.InputStream;
196.30 -import java.io.OutputStream;
196.31 -import java.io.Reader;
196.32 -import java.net.URI;
196.33 -import java.net.URISyntaxException;
196.34 -import java.util.ArrayList;
196.35 -import java.util.List;
196.36 -import java.util.logging.Level;
196.37 -import java.util.logging.Logger;
196.38 -import org.glassfish.grizzly.PortRange;
196.39 -import org.glassfish.grizzly.http.server.HttpHandler;
196.40 -import org.glassfish.grizzly.http.server.HttpServer;
196.41 -import org.glassfish.grizzly.http.server.NetworkListener;
196.42 -import org.glassfish.grizzly.http.server.Request;
196.43 -import org.glassfish.grizzly.http.server.Response;
196.44 -import org.glassfish.grizzly.http.server.ServerConfiguration;
196.45 -import org.glassfish.grizzly.websockets.WebSocket;
196.46 -import org.glassfish.grizzly.websockets.WebSocketAddOn;
196.47 -import org.glassfish.grizzly.websockets.WebSocketApplication;
196.48 -import org.glassfish.grizzly.websockets.WebSocketEngine;
196.49 -
196.50 -/**
196.51 - *
196.52 - * @author Jaroslav Tulach <jtulach@netbeans.org>
196.53 - */
196.54 -final class DynamicHTTP extends HttpHandler {
196.55 - private static final Logger LOG = Logger.getLogger(DynamicHTTP.class.getName());
196.56 - private static int resourcesCount;
196.57 - private static List<Resource> resources;
196.58 - private static ServerConfiguration conf;
196.59 - private static HttpServer server;
196.60 -
196.61 - private DynamicHTTP() {
196.62 - }
196.63 -
196.64 - static URI initServer() throws Exception {
196.65 - server = HttpServer.createSimpleServer(null, new PortRange(8080, 65535));
196.66 - final WebSocketAddOn addon = new WebSocketAddOn();
196.67 - for (NetworkListener listener : server.getListeners()) {
196.68 - listener.registerAddOn(addon);
196.69 - }
196.70 - resources = new ArrayList<Resource>();
196.71 -
196.72 - conf = server.getServerConfiguration();
196.73 - final DynamicHTTP dh = new DynamicHTTP();
196.74 -
196.75 - conf.addHttpHandler(dh, "/");
196.76 -
196.77 - server.start();
196.78 -
196.79 - return pageURL("http", server, "/test.html");
196.80 - }
196.81 -
196.82 - @Override
196.83 - public void service(Request request, Response response) throws Exception {
196.84 - if ("/test.html".equals(request.getRequestURI())) {
196.85 - response.setContentType("text/html");
196.86 - final InputStream is = DynamicHTTP.class.getResourceAsStream("test.html");
196.87 - copyStream(is, response.getOutputStream(), null);
196.88 - return;
196.89 - }
196.90 - if ("/dynamic".equals(request.getRequestURI())) {
196.91 - String mimeType = request.getParameter("mimeType");
196.92 - List<String> params = new ArrayList<String>();
196.93 - boolean webSocket = false;
196.94 - for (int i = 0;; i++) {
196.95 - String p = request.getParameter("param" + i);
196.96 - if (p == null) {
196.97 - break;
196.98 - }
196.99 - if ("protocol:ws".equals(p)) {
196.100 - webSocket = true;
196.101 - continue;
196.102 - }
196.103 - params.add(p);
196.104 - }
196.105 - final String cnt = request.getParameter("content");
196.106 - String mangle = cnt.replace("%20", " ").replace("%0A", "\n");
196.107 - ByteArrayInputStream is = new ByteArrayInputStream(mangle.getBytes("UTF-8"));
196.108 - URI url;
196.109 - final Resource res = new Resource(is, mimeType, "/dynamic/res" + ++resourcesCount, params.toArray(new String[params.size()]));
196.110 - if (webSocket) {
196.111 - url = registerWebSocket(res);
196.112 - } else {
196.113 - url = registerResource(res);
196.114 - }
196.115 - response.getWriter().write(url.toString());
196.116 - response.getWriter().write("\n");
196.117 - return;
196.118 - }
196.119 -
196.120 - for (Resource r : resources) {
196.121 - if (r.httpPath.equals(request.getRequestURI())) {
196.122 - response.setContentType(r.httpType);
196.123 - r.httpContent.reset();
196.124 - String[] params = null;
196.125 - if (r.parameters.length != 0) {
196.126 - params = new String[r.parameters.length];
196.127 - for (int i = 0; i < r.parameters.length; i++) {
196.128 - params[i] = request.getParameter(r.parameters[i]);
196.129 - if (params[i] == null) {
196.130 - if ("http.method".equals(r.parameters[i])) {
196.131 - params[i] = request.getMethod().toString();
196.132 - } else if ("http.requestBody".equals(r.parameters[i])) {
196.133 - Reader rdr = request.getReader();
196.134 - StringBuilder sb = new StringBuilder();
196.135 - for (;;) {
196.136 - int ch = rdr.read();
196.137 - if (ch == -1) {
196.138 - break;
196.139 - }
196.140 - sb.append((char) ch);
196.141 - }
196.142 - params[i] = sb.toString();
196.143 - }
196.144 - }
196.145 - if (params[i] == null) {
196.146 - params[i] = "null";
196.147 - }
196.148 - }
196.149 - }
196.150 -
196.151 - copyStream(r.httpContent, response.getOutputStream(), null, params);
196.152 - }
196.153 - }
196.154 - }
196.155 -
196.156 - private URI registerWebSocket(Resource r) {
196.157 - WebSocketEngine.getEngine().register("", r.httpPath, new WS(r));
196.158 - return pageURL("ws", server, r.httpPath);
196.159 - }
196.160 -
196.161 - private URI registerResource(Resource r) {
196.162 - if (!resources.contains(r)) {
196.163 - resources.add(r);
196.164 - conf.addHttpHandler(this, r.httpPath);
196.165 - }
196.166 - return pageURL("http", server, r.httpPath);
196.167 - }
196.168 -
196.169 - private static URI pageURL(String proto, HttpServer server, final String page) {
196.170 - NetworkListener listener = server.getListeners().iterator().next();
196.171 - int port = listener.getPort();
196.172 - try {
196.173 - return new URI(proto + "://localhost:" + port + page);
196.174 - } catch (URISyntaxException ex) {
196.175 - throw new IllegalStateException(ex);
196.176 - }
196.177 - }
196.178 -
196.179 - static final class Resource {
196.180 -
196.181 - final InputStream httpContent;
196.182 - final String httpType;
196.183 - final String httpPath;
196.184 - final String[] parameters;
196.185 -
196.186 - Resource(InputStream httpContent, String httpType, String httpPath,
196.187 - String[] parameters) {
196.188 - httpContent.mark(Integer.MAX_VALUE);
196.189 - this.httpContent = httpContent;
196.190 - this.httpType = httpType;
196.191 - this.httpPath = httpPath;
196.192 - this.parameters = parameters;
196.193 - }
196.194 - }
196.195 -
196.196 - static void copyStream(InputStream is, OutputStream os, String baseURL, String... params) throws IOException {
196.197 - for (;;) {
196.198 - int ch = is.read();
196.199 - if (ch == -1) {
196.200 - break;
196.201 - }
196.202 - if (ch == '$' && params.length > 0) {
196.203 - int cnt = is.read() - '0';
196.204 - if (baseURL != null && cnt == 'U' - '0') {
196.205 - os.write(baseURL.getBytes("UTF-8"));
196.206 - } else {
196.207 - if (cnt >= 0 && cnt < params.length) {
196.208 - os.write(params[cnt].getBytes("UTF-8"));
196.209 - } else {
196.210 - os.write('$');
196.211 - os.write(cnt + '0');
196.212 - }
196.213 - }
196.214 - } else {
196.215 - os.write(ch);
196.216 - }
196.217 - }
196.218 - }
196.219 -
196.220 - private static class WS extends WebSocketApplication {
196.221 - private final Resource r;
196.222 -
196.223 - private WS(Resource r) {
196.224 - this.r = r;
196.225 - }
196.226 -
196.227 - @Override
196.228 - public void onMessage(WebSocket socket, String text) {
196.229 - try {
196.230 - r.httpContent.reset();
196.231 - ByteArrayOutputStream out = new ByteArrayOutputStream();
196.232 - copyStream(r.httpContent, out, null, text);
196.233 - String s = new String(out.toByteArray(), "UTF-8");
196.234 - socket.send(s);
196.235 - } catch (IOException ex) {
196.236 - LOG.log(Level.WARNING, "Error processing message " + text, ex);
196.237 - }
196.238 - }
196.239 - }
196.240 -}
197.1 --- a/ko-fx/src/test/java/org/apidesign/html/kofx/KOFx.java Thu Dec 19 17:11:01 2013 +0100
197.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
197.3 @@ -1,96 +0,0 @@
197.4 -/**
197.5 - * HTML via Java(tm) Language Bindings
197.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
197.7 - *
197.8 - * This program is free software: you can redistribute it and/or modify
197.9 - * it under the terms of the GNU General Public License as published by
197.10 - * the Free Software Foundation, version 2 of the License.
197.11 - *
197.12 - * This program is distributed in the hope that it will be useful,
197.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
197.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
197.15 - * GNU General Public License for more details. apidesign.org
197.16 - * designates this particular file as subject to the
197.17 - * "Classpath" exception as provided by apidesign.org
197.18 - * in the License file that accompanied this code.
197.19 - *
197.20 - * You should have received a copy of the GNU General Public License
197.21 - * along with this program. Look for COPYING file in the top folder.
197.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
197.23 - */
197.24 -package org.apidesign.html.kofx;
197.25 -
197.26 -import java.io.Closeable;
197.27 -import java.lang.reflect.InvocationTargetException;
197.28 -import java.lang.reflect.Method;
197.29 -import javafx.application.Platform;
197.30 -import org.apidesign.html.boot.spi.Fn;
197.31 -import org.testng.ITest;
197.32 -import org.testng.annotations.Test;
197.33 -
197.34 -/**
197.35 - *
197.36 - * @author Jaroslav Tulach <jtulach@netbeans.org>
197.37 - */
197.38 -public final class KOFx implements ITest, Runnable {
197.39 - private final Fn.Presenter p;
197.40 - private final Method m;
197.41 - private Object result;
197.42 - private Object inst;
197.43 - private int count;
197.44 -
197.45 - KOFx(Fn.Presenter p, Method m) {
197.46 - this.p = p;
197.47 - this.m = m;
197.48 - }
197.49 -
197.50 - @Override
197.51 - public String getTestName() {
197.52 - return m.getName();
197.53 - }
197.54 -
197.55 - @Test
197.56 - public synchronized void executeTest() throws Exception {
197.57 - if (result == null) {
197.58 - Platform.runLater(this);
197.59 - wait();
197.60 - }
197.61 - if (result instanceof Exception) {
197.62 - throw (Exception)result;
197.63 - }
197.64 - if (result instanceof Error) {
197.65 - throw (Error)result;
197.66 - }
197.67 - }
197.68 -
197.69 - @Override
197.70 - public synchronized void run() {
197.71 - boolean notify = true;
197.72 - try (Closeable a = Fn.activate(p)) {
197.73 - if (inst == null) {
197.74 - inst = m.getDeclaringClass().newInstance();
197.75 - }
197.76 - result = m.invoke(inst);
197.77 - if (result == null) {
197.78 - result = this;
197.79 - }
197.80 - } catch (InvocationTargetException ex) {
197.81 - Throwable r = ex.getTargetException();
197.82 - if (r instanceof InterruptedException) {
197.83 - if (count++ < 10000) {
197.84 - notify = false;
197.85 - Platform.runLater(this);
197.86 - return;
197.87 - }
197.88 - }
197.89 - result = r;
197.90 - } catch (Exception ex) {
197.91 - result = ex;
197.92 - } finally {
197.93 - if (notify) {
197.94 - notifyAll();
197.95 - }
197.96 - }
197.97 - }
197.98 -
197.99 -}
198.1 --- a/ko-fx/src/test/java/org/apidesign/html/kofx/KnockoutFXTest.java Thu Dec 19 17:11:01 2013 +0100
198.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
198.3 @@ -1,207 +0,0 @@
198.4 -/**
198.5 - * HTML via Java(tm) Language Bindings
198.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
198.7 - *
198.8 - * This program is free software: you can redistribute it and/or modify
198.9 - * it under the terms of the GNU General Public License as published by
198.10 - * the Free Software Foundation, version 2 of the License.
198.11 - *
198.12 - * This program is distributed in the hope that it will be useful,
198.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
198.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
198.15 - * GNU General Public License for more details. apidesign.org
198.16 - * designates this particular file as subject to the
198.17 - * "Classpath" exception as provided by apidesign.org
198.18 - * in the License file that accompanied this code.
198.19 - *
198.20 - * You should have received a copy of the GNU General Public License
198.21 - * along with this program. Look for COPYING file in the top folder.
198.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
198.23 - */
198.24 -package org.apidesign.html.kofx;
198.25 -
198.26 -import java.io.BufferedReader;
198.27 -import java.io.IOException;
198.28 -import java.io.InputStreamReader;
198.29 -import java.lang.annotation.Annotation;
198.30 -import java.lang.reflect.Method;
198.31 -import java.net.URI;
198.32 -import java.net.URISyntaxException;
198.33 -import java.net.URL;
198.34 -import java.net.URLConnection;
198.35 -import java.util.ArrayList;
198.36 -import java.util.List;
198.37 -import java.util.Map;
198.38 -import java.util.concurrent.Executors;
198.39 -import net.java.html.BrwsrCtx;
198.40 -import net.java.html.boot.BrowserBuilder;
198.41 -import net.java.html.js.JavaScriptBody;
198.42 -import org.apidesign.html.boot.impl.FnContext;
198.43 -import org.apidesign.html.boot.spi.Fn;
198.44 -import org.apidesign.html.context.spi.Contexts;
198.45 -import org.apidesign.html.json.spi.Technology;
198.46 -import org.apidesign.html.json.spi.Transfer;
198.47 -import org.apidesign.html.json.spi.WSTransfer;
198.48 -import org.apidesign.html.json.tck.KOTest;
198.49 -import org.apidesign.html.json.tck.KnockoutTCK;
198.50 -import org.json.JSONException;
198.51 -import org.json.JSONObject;
198.52 -import org.openide.util.lookup.ServiceProvider;
198.53 -import org.testng.annotations.Factory;
198.54 -import static org.testng.Assert.*;
198.55 -
198.56 -/**
198.57 - *
198.58 - * @author Jaroslav Tulach <jtulach@netbeans.org>
198.59 - */
198.60 -@ServiceProvider(service = KnockoutTCK.class)
198.61 -public final class KnockoutFXTest extends KnockoutTCK {
198.62 - private static Class<?> browserClass;
198.63 - private static Fn.Presenter browserContext;
198.64 -
198.65 - public KnockoutFXTest() {
198.66 - }
198.67 -
198.68 - @Factory public static Object[] compatibilityTests() throws Exception {
198.69 - Class[] arr = testClasses();
198.70 - for (int i = 0; i < arr.length; i++) {
198.71 - assertEquals(
198.72 - arr[i].getClassLoader(),
198.73 - KnockoutFXTest.class.getClassLoader(),
198.74 - "All classes loaded by the same classloader"
198.75 - );
198.76 - }
198.77 -
198.78 - URI uri = DynamicHTTP.initServer();
198.79 -
198.80 - final BrowserBuilder bb = BrowserBuilder.newBrowser().loadClass(KnockoutFXTest.class).
198.81 - loadPage(uri.toString()).
198.82 - invoke("initialized");
198.83 -
198.84 - Executors.newSingleThreadExecutor().submit(new Runnable() {
198.85 - @Override
198.86 - public void run() {
198.87 - bb.showAndWait();
198.88 - }
198.89 - });
198.90 -
198.91 - ClassLoader l = getClassLoader();
198.92 - List<Object> res = new ArrayList<Object>();
198.93 - for (int i = 0; i < arr.length; i++) {
198.94 - Class<?> c = Class.forName(arr[i].getName(), true, l);
198.95 - seekKOTests(c, res);
198.96 - }
198.97 - Class<?> c = Class.forName(LessCallbacksCheck.class.getName(), true, l);
198.98 - seekKOTests(c, res);
198.99 - return res.toArray();
198.100 - }
198.101 -
198.102 - private static void seekKOTests(Class<?> c, List<Object> res) throws SecurityException, ClassNotFoundException {
198.103 - Class<? extends Annotation> koTest =
198.104 - c.getClassLoader().loadClass(KOTest.class.getName()).
198.105 - asSubclass(Annotation.class);
198.106 - for (Method m : c.getMethods()) {
198.107 - if (m.getAnnotation(koTest) != null) {
198.108 - res.add(new KOFx(browserContext, m));
198.109 - }
198.110 - }
198.111 - }
198.112 -
198.113 - static synchronized ClassLoader getClassLoader() throws InterruptedException {
198.114 - while (browserClass == null) {
198.115 - KnockoutFXTest.class.wait();
198.116 - }
198.117 - return browserClass.getClassLoader();
198.118 - }
198.119 -
198.120 - public static synchronized void initialized(Class<?> browserCls) throws Exception {
198.121 - browserClass = browserCls;
198.122 - browserContext = Fn.activePresenter();
198.123 - KnockoutFXTest.class.notifyAll();
198.124 - }
198.125 -
198.126 - public static void initialized() throws Exception {
198.127 - Class<?> classpathClass = ClassLoader.getSystemClassLoader().loadClass(KnockoutFXTest.class.getName());
198.128 - Method m = classpathClass.getMethod("initialized", Class.class);
198.129 - m.invoke(null, KnockoutFXTest.class);
198.130 - browserContext = Fn.activePresenter();
198.131 - }
198.132 -
198.133 - @Override
198.134 - public BrwsrCtx createContext() {
198.135 - FXContext fx = new FXContext(browserContext);
198.136 - Contexts.Builder cb = Contexts.newBuilder().
198.137 - register(Technology.class, fx, 10).
198.138 - register(Transfer.class, fx, 10);
198.139 - if (fx.areWebSocketsSupported()) {
198.140 - cb.register(WSTransfer.class, fx, 10);
198.141 - }
198.142 - return cb.build();
198.143 - }
198.144 -
198.145 - @Override
198.146 - public Object createJSON(Map<String, Object> values) {
198.147 - JSONObject json = new JSONObject();
198.148 - for (Map.Entry<String, Object> entry : values.entrySet()) {
198.149 - try {
198.150 - json.put(entry.getKey(), entry.getValue());
198.151 - } catch (JSONException ex) {
198.152 - throw new IllegalStateException(ex);
198.153 - }
198.154 - }
198.155 - return json;
198.156 - }
198.157 -
198.158 - @Override
198.159 - @JavaScriptBody(args = { "s", "args" }, body = ""
198.160 - + "var f = new Function(s); "
198.161 - + "return f.apply(null, args);"
198.162 - )
198.163 - public native Object executeScript(String script, Object[] arguments);
198.164 -
198.165 - @JavaScriptBody(args = { }, body =
198.166 - "var h;"
198.167 - + "if (!!window && !!window.location && !!window.location.href)\n"
198.168 - + " h = window.location.href;\n"
198.169 - + "else "
198.170 - + " h = null;"
198.171 - + "return h;\n"
198.172 - )
198.173 - private static native String findBaseURL();
198.174 -
198.175 - @Override
198.176 - public URI prepareURL(String content, String mimeType, String[] parameters) {
198.177 - try {
198.178 - final URL baseURL = new URL(findBaseURL());
198.179 - StringBuilder sb = new StringBuilder();
198.180 - sb.append("/dynamic?mimeType=").append(mimeType);
198.181 - for (int i = 0; i < parameters.length; i++) {
198.182 - sb.append("¶m" + i).append("=").append(parameters[i]);
198.183 - }
198.184 - String mangle = content.replace("\n", "%0a")
198.185 - .replace("\"", "\\\"").replace(" ", "%20");
198.186 - sb.append("&content=").append(mangle);
198.187 -
198.188 - URL query = new URL(baseURL, sb.toString());
198.189 - URLConnection c = query.openConnection();
198.190 - BufferedReader br = new BufferedReader(new InputStreamReader(c.getInputStream()));
198.191 - URI connectTo = new URI(br.readLine());
198.192 - return connectTo;
198.193 - } catch (IOException ex) {
198.194 - throw new IllegalStateException(ex);
198.195 - } catch (URISyntaxException ex) {
198.196 - throw new IllegalStateException(ex);
198.197 - }
198.198 - }
198.199 -
198.200 - @Override
198.201 - public boolean canFailWebSocketTest() {
198.202 - try {
198.203 - Class.forName("java.util.function.Function");
198.204 - return false;
198.205 - } catch (ClassNotFoundException ex) {
198.206 - // running on JDK7, FX WebView WebSocket impl does not work
198.207 - return true;
198.208 - }
198.209 - }
198.210 -}
199.1 --- a/ko-fx/src/test/java/org/apidesign/html/kofx/LessCallbacksCheck.java Thu Dec 19 17:11:01 2013 +0100
199.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
199.3 @@ -1,60 +0,0 @@
199.4 -/**
199.5 - * HTML via Java(tm) Language Bindings
199.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
199.7 - *
199.8 - * This program is free software: you can redistribute it and/or modify
199.9 - * it under the terms of the GNU General Public License as published by
199.10 - * the Free Software Foundation, version 2 of the License.
199.11 - *
199.12 - * This program is distributed in the hope that it will be useful,
199.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
199.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
199.15 - * GNU General Public License for more details. apidesign.org
199.16 - * designates this particular file as subject to the
199.17 - * "Classpath" exception as provided by apidesign.org
199.18 - * in the License file that accompanied this code.
199.19 - *
199.20 - * You should have received a copy of the GNU General Public License
199.21 - * along with this program. Look for COPYING file in the top folder.
199.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
199.23 - */
199.24 -package org.apidesign.html.kofx;
199.25 -
199.26 -import java.io.PrintWriter;
199.27 -import java.io.StringWriter;
199.28 -import net.java.html.json.ComputedProperty;
199.29 -import net.java.html.json.Model;
199.30 -import net.java.html.json.Property;
199.31 -import org.apidesign.html.json.tck.KOTest;
199.32 -
199.33 -/**
199.34 - *
199.35 - * @author Jaroslav Tulach <jtulach@netbeans.org>
199.36 - */
199.37 -@Model(className = "LessCalls", properties = {
199.38 - @Property(name = "value", type = int.class)
199.39 -})
199.40 -public class LessCallbacksCheck {
199.41 - private static StringWriter sw;
199.42 -
199.43 - @ComputedProperty static int plusOne(int value) {
199.44 - if (sw == null) {
199.45 - sw = new StringWriter();
199.46 - }
199.47 - new Exception("Who calls me?").printStackTrace(
199.48 - new PrintWriter(sw)
199.49 - );
199.50 - return value + 1;
199.51 - }
199.52 -
199.53 - @KOTest public void dontCallForInitialValueBackToJavaVM() {
199.54 - LessCalls m = new LessCalls(10).applyBindings();
199.55 - assert m.getPlusOne() == 11 : "Expecting 11: " + m.getPlusOne();
199.56 -
199.57 - assert sw != null : "StringWriter should be initialized: " + sw;
199.58 -
199.59 - if (sw.toString().contains("$JsCallbacks$")) {
199.60 - assert false : "Don't call for initial value via JsCallbacks:\n" + sw;
199.61 - }
199.62 - }
199.63 -}
200.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
200.2 +++ b/ko-fx/src/test/java/org/netbeans/html/kofx/DynamicHTTP.java Tue Jan 07 08:21:57 2014 +0100
200.3 @@ -0,0 +1,259 @@
200.4 +/**
200.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
200.6 + *
200.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
200.8 + *
200.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
200.10 + * Other names may be trademarks of their respective owners.
200.11 + *
200.12 + * The contents of this file are subject to the terms of either the GNU
200.13 + * General Public License Version 2 only ("GPL") or the Common
200.14 + * Development and Distribution License("CDDL") (collectively, the
200.15 + * "License"). You may not use this file except in compliance with the
200.16 + * License. You can obtain a copy of the License at
200.17 + * http://www.netbeans.org/cddl-gplv2.html
200.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
200.19 + * specific language governing permissions and limitations under the
200.20 + * License. When distributing the software, include this License Header
200.21 + * Notice in each file and include the License file at
200.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
200.23 + * particular file as subject to the "Classpath" exception as provided
200.24 + * by Oracle in the GPL Version 2 section of the License file that
200.25 + * accompanied this code. If applicable, add the following below the
200.26 + * License Header, with the fields enclosed by brackets [] replaced by
200.27 + * your own identifying information:
200.28 + * "Portions Copyrighted [year] [name of copyright owner]"
200.29 + *
200.30 + * Contributor(s):
200.31 + *
200.32 + * The Original Software is NetBeans. The Initial Developer of the Original
200.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
200.34 + *
200.35 + * If you wish your version of this file to be governed by only the CDDL
200.36 + * or only the GPL Version 2, indicate your decision by adding
200.37 + * "[Contributor] elects to include this software in this distribution
200.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
200.39 + * single choice of license, a recipient has the option to distribute
200.40 + * your version of this file under either the CDDL, the GPL Version 2 or
200.41 + * to extend the choice of license to its licensees as provided above.
200.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
200.43 + * Version 2 license, then the option applies only if the new code is
200.44 + * made subject to such option by the copyright holder.
200.45 + */
200.46 +package org.netbeans.html.kofx;
200.47 +
200.48 +import java.io.ByteArrayInputStream;
200.49 +import java.io.ByteArrayOutputStream;
200.50 +import java.io.IOException;
200.51 +import java.io.InputStream;
200.52 +import java.io.OutputStream;
200.53 +import java.io.Reader;
200.54 +import java.net.URI;
200.55 +import java.net.URISyntaxException;
200.56 +import java.util.ArrayList;
200.57 +import java.util.List;
200.58 +import java.util.logging.Level;
200.59 +import java.util.logging.Logger;
200.60 +import org.glassfish.grizzly.PortRange;
200.61 +import org.glassfish.grizzly.http.server.HttpHandler;
200.62 +import org.glassfish.grizzly.http.server.HttpServer;
200.63 +import org.glassfish.grizzly.http.server.NetworkListener;
200.64 +import org.glassfish.grizzly.http.server.Request;
200.65 +import org.glassfish.grizzly.http.server.Response;
200.66 +import org.glassfish.grizzly.http.server.ServerConfiguration;
200.67 +import org.glassfish.grizzly.websockets.WebSocket;
200.68 +import org.glassfish.grizzly.websockets.WebSocketAddOn;
200.69 +import org.glassfish.grizzly.websockets.WebSocketApplication;
200.70 +import org.glassfish.grizzly.websockets.WebSocketEngine;
200.71 +
200.72 +/**
200.73 + *
200.74 + * @author Jaroslav Tulach <jtulach@netbeans.org>
200.75 + */
200.76 +final class DynamicHTTP extends HttpHandler {
200.77 + private static final Logger LOG = Logger.getLogger(DynamicHTTP.class.getName());
200.78 + private static int resourcesCount;
200.79 + private static List<Resource> resources;
200.80 + private static ServerConfiguration conf;
200.81 + private static HttpServer server;
200.82 +
200.83 + private DynamicHTTP() {
200.84 + }
200.85 +
200.86 + static URI initServer() throws Exception {
200.87 + server = HttpServer.createSimpleServer(null, new PortRange(8080, 65535));
200.88 + final WebSocketAddOn addon = new WebSocketAddOn();
200.89 + for (NetworkListener listener : server.getListeners()) {
200.90 + listener.registerAddOn(addon);
200.91 + }
200.92 + resources = new ArrayList<Resource>();
200.93 +
200.94 + conf = server.getServerConfiguration();
200.95 + final DynamicHTTP dh = new DynamicHTTP();
200.96 +
200.97 + conf.addHttpHandler(dh, "/");
200.98 +
200.99 + server.start();
200.100 +
200.101 + return pageURL("http", server, "/test.html");
200.102 + }
200.103 +
200.104 + @Override
200.105 + public void service(Request request, Response response) throws Exception {
200.106 + if ("/test.html".equals(request.getRequestURI())) {
200.107 + response.setContentType("text/html");
200.108 + final InputStream is = DynamicHTTP.class.getResourceAsStream("test.html");
200.109 + copyStream(is, response.getOutputStream(), null);
200.110 + return;
200.111 + }
200.112 + if ("/dynamic".equals(request.getRequestURI())) {
200.113 + String mimeType = request.getParameter("mimeType");
200.114 + List<String> params = new ArrayList<String>();
200.115 + boolean webSocket = false;
200.116 + for (int i = 0;; i++) {
200.117 + String p = request.getParameter("param" + i);
200.118 + if (p == null) {
200.119 + break;
200.120 + }
200.121 + if ("protocol:ws".equals(p)) {
200.122 + webSocket = true;
200.123 + continue;
200.124 + }
200.125 + params.add(p);
200.126 + }
200.127 + final String cnt = request.getParameter("content");
200.128 + String mangle = cnt.replace("%20", " ").replace("%0A", "\n");
200.129 + ByteArrayInputStream is = new ByteArrayInputStream(mangle.getBytes("UTF-8"));
200.130 + URI url;
200.131 + final Resource res = new Resource(is, mimeType, "/dynamic/res" + ++resourcesCount, params.toArray(new String[params.size()]));
200.132 + if (webSocket) {
200.133 + url = registerWebSocket(res);
200.134 + } else {
200.135 + url = registerResource(res);
200.136 + }
200.137 + response.getWriter().write(url.toString());
200.138 + response.getWriter().write("\n");
200.139 + return;
200.140 + }
200.141 +
200.142 + for (Resource r : resources) {
200.143 + if (r.httpPath.equals(request.getRequestURI())) {
200.144 + response.setContentType(r.httpType);
200.145 + r.httpContent.reset();
200.146 + String[] params = null;
200.147 + if (r.parameters.length != 0) {
200.148 + params = new String[r.parameters.length];
200.149 + for (int i = 0; i < r.parameters.length; i++) {
200.150 + params[i] = request.getParameter(r.parameters[i]);
200.151 + if (params[i] == null) {
200.152 + if ("http.method".equals(r.parameters[i])) {
200.153 + params[i] = request.getMethod().toString();
200.154 + } else if ("http.requestBody".equals(r.parameters[i])) {
200.155 + Reader rdr = request.getReader();
200.156 + StringBuilder sb = new StringBuilder();
200.157 + for (;;) {
200.158 + int ch = rdr.read();
200.159 + if (ch == -1) {
200.160 + break;
200.161 + }
200.162 + sb.append((char) ch);
200.163 + }
200.164 + params[i] = sb.toString();
200.165 + }
200.166 + }
200.167 + if (params[i] == null) {
200.168 + params[i] = "null";
200.169 + }
200.170 + }
200.171 + }
200.172 +
200.173 + copyStream(r.httpContent, response.getOutputStream(), null, params);
200.174 + }
200.175 + }
200.176 + }
200.177 +
200.178 + private URI registerWebSocket(Resource r) {
200.179 + WebSocketEngine.getEngine().register("", r.httpPath, new WS(r));
200.180 + return pageURL("ws", server, r.httpPath);
200.181 + }
200.182 +
200.183 + private URI registerResource(Resource r) {
200.184 + if (!resources.contains(r)) {
200.185 + resources.add(r);
200.186 + conf.addHttpHandler(this, r.httpPath);
200.187 + }
200.188 + return pageURL("http", server, r.httpPath);
200.189 + }
200.190 +
200.191 + private static URI pageURL(String proto, HttpServer server, final String page) {
200.192 + NetworkListener listener = server.getListeners().iterator().next();
200.193 + int port = listener.getPort();
200.194 + try {
200.195 + return new URI(proto + "://localhost:" + port + page);
200.196 + } catch (URISyntaxException ex) {
200.197 + throw new IllegalStateException(ex);
200.198 + }
200.199 + }
200.200 +
200.201 + static final class Resource {
200.202 +
200.203 + final InputStream httpContent;
200.204 + final String httpType;
200.205 + final String httpPath;
200.206 + final String[] parameters;
200.207 +
200.208 + Resource(InputStream httpContent, String httpType, String httpPath,
200.209 + String[] parameters) {
200.210 + httpContent.mark(Integer.MAX_VALUE);
200.211 + this.httpContent = httpContent;
200.212 + this.httpType = httpType;
200.213 + this.httpPath = httpPath;
200.214 + this.parameters = parameters;
200.215 + }
200.216 + }
200.217 +
200.218 + static void copyStream(InputStream is, OutputStream os, String baseURL, String... params) throws IOException {
200.219 + for (;;) {
200.220 + int ch = is.read();
200.221 + if (ch == -1) {
200.222 + break;
200.223 + }
200.224 + if (ch == '$' && params.length > 0) {
200.225 + int cnt = is.read() - '0';
200.226 + if (baseURL != null && cnt == 'U' - '0') {
200.227 + os.write(baseURL.getBytes("UTF-8"));
200.228 + } else {
200.229 + if (cnt >= 0 && cnt < params.length) {
200.230 + os.write(params[cnt].getBytes("UTF-8"));
200.231 + } else {
200.232 + os.write('$');
200.233 + os.write(cnt + '0');
200.234 + }
200.235 + }
200.236 + } else {
200.237 + os.write(ch);
200.238 + }
200.239 + }
200.240 + }
200.241 +
200.242 + private static class WS extends WebSocketApplication {
200.243 + private final Resource r;
200.244 +
200.245 + private WS(Resource r) {
200.246 + this.r = r;
200.247 + }
200.248 +
200.249 + @Override
200.250 + public void onMessage(WebSocket socket, String text) {
200.251 + try {
200.252 + r.httpContent.reset();
200.253 + ByteArrayOutputStream out = new ByteArrayOutputStream();
200.254 + copyStream(r.httpContent, out, null, text);
200.255 + String s = new String(out.toByteArray(), "UTF-8");
200.256 + socket.send(s);
200.257 + } catch (IOException ex) {
200.258 + LOG.log(Level.WARNING, "Error processing message " + text, ex);
200.259 + }
200.260 + }
200.261 + }
200.262 +}
201.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
201.2 +++ b/ko-fx/src/test/java/org/netbeans/html/kofx/KOFx.java Tue Jan 07 08:21:57 2014 +0100
201.3 @@ -0,0 +1,118 @@
201.4 +/**
201.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
201.6 + *
201.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
201.8 + *
201.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
201.10 + * Other names may be trademarks of their respective owners.
201.11 + *
201.12 + * The contents of this file are subject to the terms of either the GNU
201.13 + * General Public License Version 2 only ("GPL") or the Common
201.14 + * Development and Distribution License("CDDL") (collectively, the
201.15 + * "License"). You may not use this file except in compliance with the
201.16 + * License. You can obtain a copy of the License at
201.17 + * http://www.netbeans.org/cddl-gplv2.html
201.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
201.19 + * specific language governing permissions and limitations under the
201.20 + * License. When distributing the software, include this License Header
201.21 + * Notice in each file and include the License file at
201.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
201.23 + * particular file as subject to the "Classpath" exception as provided
201.24 + * by Oracle in the GPL Version 2 section of the License file that
201.25 + * accompanied this code. If applicable, add the following below the
201.26 + * License Header, with the fields enclosed by brackets [] replaced by
201.27 + * your own identifying information:
201.28 + * "Portions Copyrighted [year] [name of copyright owner]"
201.29 + *
201.30 + * Contributor(s):
201.31 + *
201.32 + * The Original Software is NetBeans. The Initial Developer of the Original
201.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
201.34 + *
201.35 + * If you wish your version of this file to be governed by only the CDDL
201.36 + * or only the GPL Version 2, indicate your decision by adding
201.37 + * "[Contributor] elects to include this software in this distribution
201.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
201.39 + * single choice of license, a recipient has the option to distribute
201.40 + * your version of this file under either the CDDL, the GPL Version 2 or
201.41 + * to extend the choice of license to its licensees as provided above.
201.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
201.43 + * Version 2 license, then the option applies only if the new code is
201.44 + * made subject to such option by the copyright holder.
201.45 + */
201.46 +package org.netbeans.html.kofx;
201.47 +
201.48 +import java.io.Closeable;
201.49 +import java.lang.reflect.InvocationTargetException;
201.50 +import java.lang.reflect.Method;
201.51 +import javafx.application.Platform;
201.52 +import org.apidesign.html.boot.spi.Fn;
201.53 +import org.testng.ITest;
201.54 +import org.testng.annotations.Test;
201.55 +
201.56 +/**
201.57 + *
201.58 + * @author Jaroslav Tulach <jtulach@netbeans.org>
201.59 + */
201.60 +public final class KOFx implements ITest, Runnable {
201.61 + private final Fn.Presenter p;
201.62 + private final Method m;
201.63 + private Object result;
201.64 + private Object inst;
201.65 + private int count;
201.66 +
201.67 + KOFx(Fn.Presenter p, Method m) {
201.68 + this.p = p;
201.69 + this.m = m;
201.70 + }
201.71 +
201.72 + @Override
201.73 + public String getTestName() {
201.74 + return m.getName();
201.75 + }
201.76 +
201.77 + @Test
201.78 + public synchronized void executeTest() throws Exception {
201.79 + if (result == null) {
201.80 + Platform.runLater(this);
201.81 + wait();
201.82 + }
201.83 + if (result instanceof Exception) {
201.84 + throw (Exception)result;
201.85 + }
201.86 + if (result instanceof Error) {
201.87 + throw (Error)result;
201.88 + }
201.89 + }
201.90 +
201.91 + @Override
201.92 + public synchronized void run() {
201.93 + boolean notify = true;
201.94 + try (Closeable a = Fn.activate(p)) {
201.95 + if (inst == null) {
201.96 + inst = m.getDeclaringClass().newInstance();
201.97 + }
201.98 + result = m.invoke(inst);
201.99 + if (result == null) {
201.100 + result = this;
201.101 + }
201.102 + } catch (InvocationTargetException ex) {
201.103 + Throwable r = ex.getTargetException();
201.104 + if (r instanceof InterruptedException) {
201.105 + if (count++ < 10000) {
201.106 + notify = false;
201.107 + Platform.runLater(this);
201.108 + return;
201.109 + }
201.110 + }
201.111 + result = r;
201.112 + } catch (Exception ex) {
201.113 + result = ex;
201.114 + } finally {
201.115 + if (notify) {
201.116 + notifyAll();
201.117 + }
201.118 + }
201.119 + }
201.120 +
201.121 +}
202.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
202.2 +++ b/ko-fx/src/test/java/org/netbeans/html/kofx/KnockoutFXTest.java Tue Jan 07 08:21:57 2014 +0100
202.3 @@ -0,0 +1,229 @@
202.4 +/**
202.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
202.6 + *
202.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
202.8 + *
202.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
202.10 + * Other names may be trademarks of their respective owners.
202.11 + *
202.12 + * The contents of this file are subject to the terms of either the GNU
202.13 + * General Public License Version 2 only ("GPL") or the Common
202.14 + * Development and Distribution License("CDDL") (collectively, the
202.15 + * "License"). You may not use this file except in compliance with the
202.16 + * License. You can obtain a copy of the License at
202.17 + * http://www.netbeans.org/cddl-gplv2.html
202.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
202.19 + * specific language governing permissions and limitations under the
202.20 + * License. When distributing the software, include this License Header
202.21 + * Notice in each file and include the License file at
202.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
202.23 + * particular file as subject to the "Classpath" exception as provided
202.24 + * by Oracle in the GPL Version 2 section of the License file that
202.25 + * accompanied this code. If applicable, add the following below the
202.26 + * License Header, with the fields enclosed by brackets [] replaced by
202.27 + * your own identifying information:
202.28 + * "Portions Copyrighted [year] [name of copyright owner]"
202.29 + *
202.30 + * Contributor(s):
202.31 + *
202.32 + * The Original Software is NetBeans. The Initial Developer of the Original
202.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
202.34 + *
202.35 + * If you wish your version of this file to be governed by only the CDDL
202.36 + * or only the GPL Version 2, indicate your decision by adding
202.37 + * "[Contributor] elects to include this software in this distribution
202.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
202.39 + * single choice of license, a recipient has the option to distribute
202.40 + * your version of this file under either the CDDL, the GPL Version 2 or
202.41 + * to extend the choice of license to its licensees as provided above.
202.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
202.43 + * Version 2 license, then the option applies only if the new code is
202.44 + * made subject to such option by the copyright holder.
202.45 + */
202.46 +package org.netbeans.html.kofx;
202.47 +
202.48 +import java.io.BufferedReader;
202.49 +import java.io.IOException;
202.50 +import java.io.InputStreamReader;
202.51 +import java.lang.annotation.Annotation;
202.52 +import java.lang.reflect.Method;
202.53 +import java.net.URI;
202.54 +import java.net.URISyntaxException;
202.55 +import java.net.URL;
202.56 +import java.net.URLConnection;
202.57 +import java.util.ArrayList;
202.58 +import java.util.List;
202.59 +import java.util.Map;
202.60 +import java.util.concurrent.Executors;
202.61 +import net.java.html.BrwsrCtx;
202.62 +import net.java.html.boot.BrowserBuilder;
202.63 +import net.java.html.js.JavaScriptBody;
202.64 +import org.netbeans.html.boot.impl.FnContext;
202.65 +import org.apidesign.html.boot.spi.Fn;
202.66 +import org.apidesign.html.context.spi.Contexts;
202.67 +import org.apidesign.html.json.spi.Technology;
202.68 +import org.apidesign.html.json.spi.Transfer;
202.69 +import org.apidesign.html.json.spi.WSTransfer;
202.70 +import org.apidesign.html.json.tck.KOTest;
202.71 +import org.apidesign.html.json.tck.KnockoutTCK;
202.72 +import org.json.JSONException;
202.73 +import org.json.JSONObject;
202.74 +import org.openide.util.lookup.ServiceProvider;
202.75 +import org.testng.annotations.Factory;
202.76 +import static org.testng.Assert.*;
202.77 +
202.78 +/**
202.79 + *
202.80 + * @author Jaroslav Tulach <jtulach@netbeans.org>
202.81 + */
202.82 +@ServiceProvider(service = KnockoutTCK.class)
202.83 +public final class KnockoutFXTest extends KnockoutTCK {
202.84 + private static Class<?> browserClass;
202.85 + private static Fn.Presenter browserContext;
202.86 +
202.87 + public KnockoutFXTest() {
202.88 + }
202.89 +
202.90 + @Factory public static Object[] compatibilityTests() throws Exception {
202.91 + Class[] arr = testClasses();
202.92 + for (int i = 0; i < arr.length; i++) {
202.93 + assertEquals(
202.94 + arr[i].getClassLoader(),
202.95 + KnockoutFXTest.class.getClassLoader(),
202.96 + "All classes loaded by the same classloader"
202.97 + );
202.98 + }
202.99 +
202.100 + URI uri = DynamicHTTP.initServer();
202.101 +
202.102 + final BrowserBuilder bb = BrowserBuilder.newBrowser().loadClass(KnockoutFXTest.class).
202.103 + loadPage(uri.toString()).
202.104 + invoke("initialized");
202.105 +
202.106 + Executors.newSingleThreadExecutor().submit(new Runnable() {
202.107 + @Override
202.108 + public void run() {
202.109 + bb.showAndWait();
202.110 + }
202.111 + });
202.112 +
202.113 + ClassLoader l = getClassLoader();
202.114 + List<Object> res = new ArrayList<Object>();
202.115 + for (int i = 0; i < arr.length; i++) {
202.116 + Class<?> c = Class.forName(arr[i].getName(), true, l);
202.117 + seekKOTests(c, res);
202.118 + }
202.119 + Class<?> c = Class.forName(LessCallbacksCheck.class.getName(), true, l);
202.120 + seekKOTests(c, res);
202.121 + return res.toArray();
202.122 + }
202.123 +
202.124 + private static void seekKOTests(Class<?> c, List<Object> res) throws SecurityException, ClassNotFoundException {
202.125 + Class<? extends Annotation> koTest =
202.126 + c.getClassLoader().loadClass(KOTest.class.getName()).
202.127 + asSubclass(Annotation.class);
202.128 + for (Method m : c.getMethods()) {
202.129 + if (m.getAnnotation(koTest) != null) {
202.130 + res.add(new KOFx(browserContext, m));
202.131 + }
202.132 + }
202.133 + }
202.134 +
202.135 + static synchronized ClassLoader getClassLoader() throws InterruptedException {
202.136 + while (browserClass == null) {
202.137 + KnockoutFXTest.class.wait();
202.138 + }
202.139 + return browserClass.getClassLoader();
202.140 + }
202.141 +
202.142 + public static synchronized void initialized(Class<?> browserCls) throws Exception {
202.143 + browserClass = browserCls;
202.144 + browserContext = Fn.activePresenter();
202.145 + KnockoutFXTest.class.notifyAll();
202.146 + }
202.147 +
202.148 + public static void initialized() throws Exception {
202.149 + Class<?> classpathClass = ClassLoader.getSystemClassLoader().loadClass(KnockoutFXTest.class.getName());
202.150 + Method m = classpathClass.getMethod("initialized", Class.class);
202.151 + m.invoke(null, KnockoutFXTest.class);
202.152 + browserContext = Fn.activePresenter();
202.153 + }
202.154 +
202.155 + @Override
202.156 + public BrwsrCtx createContext() {
202.157 + FXContext fx = new FXContext(browserContext);
202.158 + Contexts.Builder cb = Contexts.newBuilder().
202.159 + register(Technology.class, fx, 10).
202.160 + register(Transfer.class, fx, 10);
202.161 + if (fx.areWebSocketsSupported()) {
202.162 + cb.register(WSTransfer.class, fx, 10);
202.163 + }
202.164 + return cb.build();
202.165 + }
202.166 +
202.167 + @Override
202.168 + public Object createJSON(Map<String, Object> values) {
202.169 + JSONObject json = new JSONObject();
202.170 + for (Map.Entry<String, Object> entry : values.entrySet()) {
202.171 + try {
202.172 + json.put(entry.getKey(), entry.getValue());
202.173 + } catch (JSONException ex) {
202.174 + throw new IllegalStateException(ex);
202.175 + }
202.176 + }
202.177 + return json;
202.178 + }
202.179 +
202.180 + @Override
202.181 + @JavaScriptBody(args = { "s", "args" }, body = ""
202.182 + + "var f = new Function(s); "
202.183 + + "return f.apply(null, args);"
202.184 + )
202.185 + public native Object executeScript(String script, Object[] arguments);
202.186 +
202.187 + @JavaScriptBody(args = { }, body =
202.188 + "var h;"
202.189 + + "if (!!window && !!window.location && !!window.location.href)\n"
202.190 + + " h = window.location.href;\n"
202.191 + + "else "
202.192 + + " h = null;"
202.193 + + "return h;\n"
202.194 + )
202.195 + private static native String findBaseURL();
202.196 +
202.197 + @Override
202.198 + public URI prepareURL(String content, String mimeType, String[] parameters) {
202.199 + try {
202.200 + final URL baseURL = new URL(findBaseURL());
202.201 + StringBuilder sb = new StringBuilder();
202.202 + sb.append("/dynamic?mimeType=").append(mimeType);
202.203 + for (int i = 0; i < parameters.length; i++) {
202.204 + sb.append("¶m" + i).append("=").append(parameters[i]);
202.205 + }
202.206 + String mangle = content.replace("\n", "%0a")
202.207 + .replace("\"", "\\\"").replace(" ", "%20");
202.208 + sb.append("&content=").append(mangle);
202.209 +
202.210 + URL query = new URL(baseURL, sb.toString());
202.211 + URLConnection c = query.openConnection();
202.212 + BufferedReader br = new BufferedReader(new InputStreamReader(c.getInputStream()));
202.213 + URI connectTo = new URI(br.readLine());
202.214 + return connectTo;
202.215 + } catch (IOException ex) {
202.216 + throw new IllegalStateException(ex);
202.217 + } catch (URISyntaxException ex) {
202.218 + throw new IllegalStateException(ex);
202.219 + }
202.220 + }
202.221 +
202.222 + @Override
202.223 + public boolean canFailWebSocketTest() {
202.224 + try {
202.225 + Class.forName("java.util.function.Function");
202.226 + return false;
202.227 + } catch (ClassNotFoundException ex) {
202.228 + // running on JDK7, FX WebView WebSocket impl does not work
202.229 + return true;
202.230 + }
202.231 + }
202.232 +}
203.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
203.2 +++ b/ko-fx/src/test/java/org/netbeans/html/kofx/LessCallbacksCheck.java Tue Jan 07 08:21:57 2014 +0100
203.3 @@ -0,0 +1,82 @@
203.4 +/**
203.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
203.6 + *
203.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
203.8 + *
203.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
203.10 + * Other names may be trademarks of their respective owners.
203.11 + *
203.12 + * The contents of this file are subject to the terms of either the GNU
203.13 + * General Public License Version 2 only ("GPL") or the Common
203.14 + * Development and Distribution License("CDDL") (collectively, the
203.15 + * "License"). You may not use this file except in compliance with the
203.16 + * License. You can obtain a copy of the License at
203.17 + * http://www.netbeans.org/cddl-gplv2.html
203.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
203.19 + * specific language governing permissions and limitations under the
203.20 + * License. When distributing the software, include this License Header
203.21 + * Notice in each file and include the License file at
203.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
203.23 + * particular file as subject to the "Classpath" exception as provided
203.24 + * by Oracle in the GPL Version 2 section of the License file that
203.25 + * accompanied this code. If applicable, add the following below the
203.26 + * License Header, with the fields enclosed by brackets [] replaced by
203.27 + * your own identifying information:
203.28 + * "Portions Copyrighted [year] [name of copyright owner]"
203.29 + *
203.30 + * Contributor(s):
203.31 + *
203.32 + * The Original Software is NetBeans. The Initial Developer of the Original
203.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
203.34 + *
203.35 + * If you wish your version of this file to be governed by only the CDDL
203.36 + * or only the GPL Version 2, indicate your decision by adding
203.37 + * "[Contributor] elects to include this software in this distribution
203.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
203.39 + * single choice of license, a recipient has the option to distribute
203.40 + * your version of this file under either the CDDL, the GPL Version 2 or
203.41 + * to extend the choice of license to its licensees as provided above.
203.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
203.43 + * Version 2 license, then the option applies only if the new code is
203.44 + * made subject to such option by the copyright holder.
203.45 + */
203.46 +package org.netbeans.html.kofx;
203.47 +
203.48 +import java.io.PrintWriter;
203.49 +import java.io.StringWriter;
203.50 +import net.java.html.json.ComputedProperty;
203.51 +import net.java.html.json.Model;
203.52 +import net.java.html.json.Property;
203.53 +import org.apidesign.html.json.tck.KOTest;
203.54 +
203.55 +/**
203.56 + *
203.57 + * @author Jaroslav Tulach <jtulach@netbeans.org>
203.58 + */
203.59 +@Model(className = "LessCalls", properties = {
203.60 + @Property(name = "value", type = int.class)
203.61 +})
203.62 +public class LessCallbacksCheck {
203.63 + private static StringWriter sw;
203.64 +
203.65 + @ComputedProperty static int plusOne(int value) {
203.66 + if (sw == null) {
203.67 + sw = new StringWriter();
203.68 + }
203.69 + new Exception("Who calls me?").printStackTrace(
203.70 + new PrintWriter(sw)
203.71 + );
203.72 + return value + 1;
203.73 + }
203.74 +
203.75 + @KOTest public void dontCallForInitialValueBackToJavaVM() {
203.76 + LessCalls m = new LessCalls(10).applyBindings();
203.77 + assert m.getPlusOne() == 11 : "Expecting 11: " + m.getPlusOne();
203.78 +
203.79 + assert sw != null : "StringWriter should be initialized: " + sw;
203.80 +
203.81 + if (sw.toString().contains("$JsCallbacks$")) {
203.82 + assert false : "Don't call for initial value via JsCallbacks:\n" + sw;
203.83 + }
203.84 + }
203.85 +}
204.1 --- a/ko-fx/src/test/resources/org/apidesign/html/kofx/test.html Thu Dec 19 17:11:01 2013 +0100
204.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
204.3 @@ -1,34 +0,0 @@
204.4 -<!--
204.5 -
204.6 - HTML via Java(tm) Language Bindings
204.7 - Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
204.8 -
204.9 - This program is free software: you can redistribute it and/or modify
204.10 - it under the terms of the GNU General Public License as published by
204.11 - the Free Software Foundation, version 2 of the License.
204.12 -
204.13 - This program is distributed in the hope that it will be useful,
204.14 - but WITHOUT ANY WARRANTY; without even the implied warranty of
204.15 - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
204.16 - GNU General Public License for more details. apidesign.org
204.17 - designates this particular file as subject to the
204.18 - "Classpath" exception as provided by apidesign.org
204.19 - in the License file that accompanied this code.
204.20 -
204.21 - You should have received a copy of the GNU General Public License
204.22 - along with this program. Look for COPYING file in the top folder.
204.23 - If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
204.24 -
204.25 --->
204.26 -<!DOCTYPE html>
204.27 -<html>
204.28 - <head>
204.29 - <title>Knockout.fx Execution Harness</title>
204.30 - <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
204.31 - <meta name="viewport" content="width=device-width">
204.32 - </head>
204.33 - <body>
204.34 - <h1>Knockout.fx Execution Harness</h1>
204.35 - </body>
204.36 - <script></script>
204.37 -</html>
205.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
205.2 +++ b/ko-fx/src/test/resources/org/netbeans/html/kofx/test.html Tue Jan 07 08:21:57 2014 +0100
205.3 @@ -0,0 +1,56 @@
205.4 +<!--
205.5 +
205.6 + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
205.7 +
205.8 + Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
205.9 +
205.10 + Oracle and Java are registered trademarks of Oracle and/or its affiliates.
205.11 + Other names may be trademarks of their respective owners.
205.12 +
205.13 + The contents of this file are subject to the terms of either the GNU
205.14 + General Public License Version 2 only ("GPL") or the Common
205.15 + Development and Distribution License("CDDL") (collectively, the
205.16 + "License"). You may not use this file except in compliance with the
205.17 + License. You can obtain a copy of the License at
205.18 + http://www.netbeans.org/cddl-gplv2.html
205.19 + or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
205.20 + specific language governing permissions and limitations under the
205.21 + License. When distributing the software, include this License Header
205.22 + Notice in each file and include the License file at
205.23 + nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
205.24 + particular file as subject to the "Classpath" exception as provided
205.25 + by Oracle in the GPL Version 2 section of the License file that
205.26 + accompanied this code. If applicable, add the following below the
205.27 + License Header, with the fields enclosed by brackets [] replaced by
205.28 + your own identifying information:
205.29 + "Portions Copyrighted [year] [name of copyright owner]"
205.30 +
205.31 + Contributor(s):
205.32 +
205.33 + The Original Software is NetBeans. The Initial Developer of the Original
205.34 + Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
205.35 +
205.36 + If you wish your version of this file to be governed by only the CDDL
205.37 + or only the GPL Version 2, indicate your decision by adding
205.38 + "[Contributor] elects to include this software in this distribution
205.39 + under the [CDDL or GPL Version 2] license." If you do not indicate a
205.40 + single choice of license, a recipient has the option to distribute
205.41 + your version of this file under either the CDDL, the GPL Version 2 or
205.42 + to extend the choice of license to its licensees as provided above.
205.43 + However, if you add GPL Version 2 code and therefore, elected the GPL
205.44 + Version 2 license, then the option applies only if the new code is
205.45 + made subject to such option by the copyright holder.
205.46 +
205.47 +-->
205.48 +<!DOCTYPE html>
205.49 +<html>
205.50 + <head>
205.51 + <title>Knockout.fx Execution Harness</title>
205.52 + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
205.53 + <meta name="viewport" content="width=device-width">
205.54 + </head>
205.55 + <body>
205.56 + <h1>Knockout.fx Execution Harness</h1>
205.57 + </body>
205.58 + <script></script>
205.59 +</html>
206.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
206.2 +++ b/ko-osgi-test/pom.xml Tue Jan 07 08:21:57 2014 +0100
206.3 @@ -0,0 +1,136 @@
206.4 +<?xml version="1.0" encoding="UTF-8"?>
206.5 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
206.6 + <modelVersion>4.0.0</modelVersion>
206.7 + <parent>
206.8 + <groupId>org.netbeans.html</groupId>
206.9 + <artifactId>pom</artifactId>
206.10 + <version>0.7-SNAPSHOT</version>
206.11 + </parent>
206.12 + <name>KO Tests in an OSGi Container</name>
206.13 + <artifactId>ko-osgi-test</artifactId>
206.14 + <packaging>bundle</packaging>
206.15 + <description>Runs the TCK for Knockout in an OSGi Container</description>
206.16 + <properties>
206.17 + <netbeans.compile.on.save>none</netbeans.compile.on.save>
206.18 + </properties>
206.19 + <build>
206.20 + <plugins>
206.21 + <plugin>
206.22 + <groupId>org.apache.felix</groupId>
206.23 + <artifactId>maven-bundle-plugin</artifactId>
206.24 + </plugin>
206.25 + <plugin>
206.26 + <groupId>org.apache.maven.plugins</groupId>
206.27 + <artifactId>maven-compiler-plugin</artifactId>
206.28 + <version>2.3.2</version>
206.29 + <configuration>
206.30 + <source>1.7</source>
206.31 + <target>1.7</target>
206.32 + </configuration>
206.33 + </plugin>
206.34 + <plugin>
206.35 + <artifactId>maven-failsafe-plugin</artifactId>
206.36 + <version>2.16</version>
206.37 + <configuration>
206.38 + <additionalClasspathElements>
206.39 + <additionalClasspathElement>${project.build.directory}/${project.build.finalName}.jar</additionalClasspathElement>
206.40 + </additionalClasspathElements>
206.41 + </configuration>
206.42 + <executions>
206.43 + <execution>
206.44 + <goals>
206.45 + <goal>integration-test</goal>
206.46 + <goal>verify</goal>
206.47 + </goals>
206.48 + </execution>
206.49 + </executions>
206.50 + </plugin>
206.51 + </plugins>
206.52 + </build>
206.53 + <dependencies>
206.54 + <dependency>
206.55 + <groupId>com.oracle</groupId>
206.56 + <artifactId>javafx</artifactId>
206.57 + <version>2.2</version>
206.58 + <scope>system</scope>
206.59 + <systemPath>${jfxrt.jar}</systemPath>
206.60 + </dependency>
206.61 + <dependency>
206.62 + <groupId>de.twentyeleven.skysail</groupId>
206.63 + <artifactId>org.json-osgi</artifactId>
206.64 + </dependency>
206.65 + <dependency>
206.66 + <groupId>org.netbeans.html</groupId>
206.67 + <artifactId>net.java.html.json</artifactId>
206.68 + <version>${project.version}</version>
206.69 + </dependency>
206.70 + <dependency>
206.71 + <groupId>org.testng</groupId>
206.72 + <artifactId>testng</artifactId>
206.73 + <scope>test</scope>
206.74 + </dependency>
206.75 + <dependency>
206.76 + <groupId>${project.groupId}</groupId>
206.77 + <artifactId>net.java.html.json.tck</artifactId>
206.78 + <version>${project.version}</version>
206.79 + </dependency>
206.80 + <dependency>
206.81 + <groupId>org.netbeans.api</groupId>
206.82 + <artifactId>org-openide-util-lookup</artifactId>
206.83 + <scope>provided</scope>
206.84 + </dependency>
206.85 + <dependency>
206.86 + <groupId>org.netbeans.html</groupId>
206.87 + <artifactId>net.java.html.boot</artifactId>
206.88 + <version>${project.version}</version>
206.89 + <type>jar</type>
206.90 + </dependency>
206.91 + <dependency>
206.92 + <groupId>${project.groupId}</groupId>
206.93 + <artifactId>ko-fx</artifactId>
206.94 + <version>${project.version}</version>
206.95 + </dependency>
206.96 + <dependency>
206.97 + <groupId>${project.groupId}</groupId>
206.98 + <artifactId>net.java.html.boot.fx</artifactId>
206.99 + <version>${project.version}</version>
206.100 + <scope>test</scope>
206.101 + </dependency>
206.102 + <dependency>
206.103 + <groupId>org.glassfish.grizzly</groupId>
206.104 + <artifactId>grizzly-http-server</artifactId>
206.105 + <version>2.3.3</version>
206.106 + <scope>test</scope>
206.107 + </dependency>
206.108 + <dependency>
206.109 + <groupId>org.glassfish.grizzly</groupId>
206.110 + <artifactId>grizzly-websockets-server</artifactId>
206.111 + <version>2.3.3</version>
206.112 + <scope>test</scope>
206.113 + <type>jar</type>
206.114 + </dependency>
206.115 + <dependency>
206.116 + <groupId>org.glassfish.grizzly</groupId>
206.117 + <artifactId>grizzly-http-servlet</artifactId>
206.118 + <version>2.3.3</version>
206.119 + <scope>test</scope>
206.120 + </dependency>
206.121 + <dependency>
206.122 + <groupId>javax.servlet</groupId>
206.123 + <artifactId>javax.servlet-api</artifactId>
206.124 + <scope>test</scope>
206.125 + <version>3.1.0</version>
206.126 + </dependency>
206.127 + <dependency>
206.128 + <groupId>org.eclipse</groupId>
206.129 + <artifactId>org.eclipse.osgi</artifactId>
206.130 + <version>3.8.0.v20120529-1548</version>
206.131 + </dependency>
206.132 + <dependency>
206.133 + <groupId>${project.groupId}</groupId>
206.134 + <artifactId>equinox-agentclass-hook</artifactId>
206.135 + <version>${project.version}</version>
206.136 + <scope>test</scope>
206.137 + </dependency>
206.138 + </dependencies>
206.139 +</project>
206.140 \ No newline at end of file
207.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
207.2 +++ b/ko-osgi-test/src/main/java/org/netbeans/html/ko/osgi/test/KnockoutEquinoxTCKImpl.java Tue Jan 07 08:21:57 2014 +0100
207.3 @@ -0,0 +1,219 @@
207.4 +/**
207.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
207.6 + *
207.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
207.8 + *
207.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
207.10 + * Other names may be trademarks of their respective owners.
207.11 + *
207.12 + * The contents of this file are subject to the terms of either the GNU
207.13 + * General Public License Version 2 only ("GPL") or the Common
207.14 + * Development and Distribution License("CDDL") (collectively, the
207.15 + * "License"). You may not use this file except in compliance with the
207.16 + * License. You can obtain a copy of the License at
207.17 + * http://www.netbeans.org/cddl-gplv2.html
207.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
207.19 + * specific language governing permissions and limitations under the
207.20 + * License. When distributing the software, include this License Header
207.21 + * Notice in each file and include the License file at
207.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
207.23 + * particular file as subject to the "Classpath" exception as provided
207.24 + * by Oracle in the GPL Version 2 section of the License file that
207.25 + * accompanied this code. If applicable, add the following below the
207.26 + * License Header, with the fields enclosed by brackets [] replaced by
207.27 + * your own identifying information:
207.28 + * "Portions Copyrighted [year] [name of copyright owner]"
207.29 + *
207.30 + * Contributor(s):
207.31 + *
207.32 + * The Original Software is NetBeans. The Initial Developer of the Original
207.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
207.34 + *
207.35 + * If you wish your version of this file to be governed by only the CDDL
207.36 + * or only the GPL Version 2, indicate your decision by adding
207.37 + * "[Contributor] elects to include this software in this distribution
207.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
207.39 + * single choice of license, a recipient has the option to distribute
207.40 + * your version of this file under either the CDDL, the GPL Version 2 or
207.41 + * to extend the choice of license to its licensees as provided above.
207.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
207.43 + * Version 2 license, then the option applies only if the new code is
207.44 + * made subject to such option by the copyright holder.
207.45 + */
207.46 +package org.netbeans.html.ko.osgi.test;
207.47 +
207.48 +import java.io.BufferedReader;
207.49 +import java.io.IOException;
207.50 +import java.io.InputStreamReader;
207.51 +import java.lang.reflect.Method;
207.52 +import java.net.URI;
207.53 +import java.net.URISyntaxException;
207.54 +import java.net.URL;
207.55 +import java.net.URLConnection;
207.56 +import java.util.Map;
207.57 +import java.util.concurrent.Callable;
207.58 +import java.util.concurrent.Executors;
207.59 +import net.java.html.BrwsrCtx;
207.60 +import net.java.html.boot.BrowserBuilder;
207.61 +import net.java.html.js.JavaScriptBody;
207.62 +import org.apidesign.html.boot.spi.Fn;
207.63 +import org.apidesign.html.context.spi.Contexts;
207.64 +import org.apidesign.html.json.spi.Technology;
207.65 +import org.apidesign.html.json.spi.Transfer;
207.66 +import org.apidesign.html.json.tck.KnockoutTCK;
207.67 +import org.json.JSONException;
207.68 +import org.json.JSONObject;
207.69 +import org.openide.util.lookup.ServiceProvider;
207.70 +import org.osgi.framework.Bundle;
207.71 +import org.osgi.framework.BundleContext;
207.72 +import org.osgi.framework.FrameworkUtil;
207.73 +
207.74 +/**
207.75 + *
207.76 + * @author Jaroslav Tulach <jtulach@netbeans.org>
207.77 + */
207.78 +@ServiceProvider(service = KnockoutTCK.class)
207.79 +public class KnockoutEquinoxTCKImpl extends KnockoutTCK implements Callable<Class[]> {
207.80 +
207.81 + private static Fn.Presenter browserContext;
207.82 +
207.83 + public static Class loadOSGiClass(String name, BundleContext ctx) throws Exception {
207.84 + for (Bundle b : ctx.getBundles()) {
207.85 + try {
207.86 + Class<?> osgiClass = b.loadClass(name);
207.87 + if (osgiClass != null && osgiClass.getClassLoader() != ClassLoader.getSystemClassLoader()) {
207.88 + return osgiClass;
207.89 + }
207.90 + } catch (ClassNotFoundException cnfe) {
207.91 + // go on
207.92 + }
207.93 + }
207.94 + throw new IllegalStateException("Cannot load " + name + " from the OSGi container!");
207.95 + }
207.96 +
207.97 + @Override
207.98 + public Class[] call() throws Exception {
207.99 + return testClasses();
207.100 + }
207.101 +
207.102 + public static void start(URI server) throws Exception {
207.103 + final BrowserBuilder bb = BrowserBuilder.newBrowser().loadClass(KnockoutEquinoxTCKImpl.class).
207.104 + loadPage(server.toString()).
207.105 + invoke("initialized");
207.106 +
207.107 + Executors.newSingleThreadExecutor().submit(new Runnable() {
207.108 + @Override
207.109 + public void run() {
207.110 + try {
207.111 + final ClassLoader osgiClassLoader = BrowserBuilder.class.getClassLoader();
207.112 + Thread.currentThread().setContextClassLoader(osgiClassLoader);
207.113 + bb.showAndWait();
207.114 + } catch (Throwable t) {
207.115 + t.printStackTrace();
207.116 + }
207.117 + }
207.118 + });
207.119 + }
207.120 +
207.121 + public static void initialized() throws Exception {
207.122 + Bundle bundle = FrameworkUtil.getBundle(KnockoutEquinoxTCKImpl.class);
207.123 + if (bundle == null) {
207.124 + throw new IllegalStateException(
207.125 + "Should be loaded from a bundle. But was: " + KnockoutEquinoxTCKImpl.class.getClassLoader()
207.126 + );
207.127 + }
207.128 + Class<?> classpathClass = ClassLoader.getSystemClassLoader().loadClass(
207.129 + "org.netbeans.html.ko.osgi.test.KnockoutEquinoxIT"
207.130 + );
207.131 + Method m = classpathClass.getMethod("initialized", Class.class, Object.class);
207.132 + browserContext = Fn.activePresenter();
207.133 + m.invoke(null, KnockoutEquinoxTCKImpl.class, browserContext);
207.134 + }
207.135 +
207.136 + @Override
207.137 + public BrwsrCtx createContext() {
207.138 + try {
207.139 + Class<?> fxCls = loadOSGiClass(
207.140 + "org.netbeans.html.kofx.FXContext",
207.141 + FrameworkUtil.getBundle(KnockoutEquinoxTCKImpl.class).getBundleContext()
207.142 + );
207.143 + Object fx = fxCls.getConstructor(Fn.Presenter.class).newInstance(browserContext);
207.144 + Contexts.Builder cb = Contexts.newBuilder().
207.145 + register(Technology.class, (Technology)fx, 10).
207.146 + register(Transfer.class, (Transfer)fx, 10);
207.147 +// if (fx.areWebSocketsSupported()) {
207.148 +// cb.register(WSTransfer.class, fx, 10);
207.149 +// }
207.150 + return cb.build();
207.151 + } catch (Exception ex) {
207.152 + throw new IllegalStateException(ex);
207.153 + }
207.154 + }
207.155 +
207.156 + @Override
207.157 + public Object createJSON(Map<String, Object> values) {
207.158 + JSONObject json = new JSONObject();
207.159 + for (Map.Entry<String, Object> entry : values.entrySet()) {
207.160 + try {
207.161 + json.put(entry.getKey(), entry.getValue());
207.162 + } catch (JSONException ex) {
207.163 + throw new IllegalStateException(ex);
207.164 + }
207.165 + }
207.166 + return json;
207.167 + }
207.168 +
207.169 + @Override
207.170 + @JavaScriptBody(args = { "s", "args" }, body = ""
207.171 + + "var f = new Function(s); "
207.172 + + "return f.apply(null, args);"
207.173 + )
207.174 + public native Object executeScript(String script, Object[] arguments);
207.175 +
207.176 + @JavaScriptBody(args = { }, body =
207.177 + "var h;"
207.178 + + "if (!!window && !!window.location && !!window.location.href)\n"
207.179 + + " h = window.location.href;\n"
207.180 + + "else "
207.181 + + " h = null;"
207.182 + + "return h;\n"
207.183 + )
207.184 + private static native String findBaseURL();
207.185 +
207.186 + @Override
207.187 + public URI prepareURL(String content, String mimeType, String[] parameters) {
207.188 + try {
207.189 + final URL baseURL = new URL(findBaseURL());
207.190 + StringBuilder sb = new StringBuilder();
207.191 + sb.append("/dynamic?mimeType=").append(mimeType);
207.192 + for (int i = 0; i < parameters.length; i++) {
207.193 + sb.append("¶m" + i).append("=").append(parameters[i]);
207.194 + }
207.195 + String mangle = content.replace("\n", "%0a")
207.196 + .replace("\"", "\\\"").replace(" ", "%20");
207.197 + sb.append("&content=").append(mangle);
207.198 +
207.199 + URL query = new URL(baseURL, sb.toString());
207.200 + URLConnection c = query.openConnection();
207.201 + BufferedReader br = new BufferedReader(new InputStreamReader(c.getInputStream()));
207.202 + URI connectTo = new URI(br.readLine());
207.203 + return connectTo;
207.204 + } catch (IOException ex) {
207.205 + throw new IllegalStateException(ex);
207.206 + } catch (URISyntaxException ex) {
207.207 + throw new IllegalStateException(ex);
207.208 + }
207.209 + }
207.210 +
207.211 + @Override
207.212 + public boolean canFailWebSocketTest() {
207.213 + try {
207.214 + Class.forName("java.util.function.Function");
207.215 + return false;
207.216 + } catch (ClassNotFoundException ex) {
207.217 + // running on JDK7, FX WebView WebSocket impl does not work
207.218 + return true;
207.219 + }
207.220 + }
207.221 +
207.222 +}
208.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
208.2 +++ b/ko-osgi-test/src/test/java/org/netbeans/html/ko/osgi/test/DynamicHTTP.java Tue Jan 07 08:21:57 2014 +0100
208.3 @@ -0,0 +1,259 @@
208.4 +/**
208.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
208.6 + *
208.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
208.8 + *
208.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
208.10 + * Other names may be trademarks of their respective owners.
208.11 + *
208.12 + * The contents of this file are subject to the terms of either the GNU
208.13 + * General Public License Version 2 only ("GPL") or the Common
208.14 + * Development and Distribution License("CDDL") (collectively, the
208.15 + * "License"). You may not use this file except in compliance with the
208.16 + * License. You can obtain a copy of the License at
208.17 + * http://www.netbeans.org/cddl-gplv2.html
208.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
208.19 + * specific language governing permissions and limitations under the
208.20 + * License. When distributing the software, include this License Header
208.21 + * Notice in each file and include the License file at
208.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
208.23 + * particular file as subject to the "Classpath" exception as provided
208.24 + * by Oracle in the GPL Version 2 section of the License file that
208.25 + * accompanied this code. If applicable, add the following below the
208.26 + * License Header, with the fields enclosed by brackets [] replaced by
208.27 + * your own identifying information:
208.28 + * "Portions Copyrighted [year] [name of copyright owner]"
208.29 + *
208.30 + * Contributor(s):
208.31 + *
208.32 + * The Original Software is NetBeans. The Initial Developer of the Original
208.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
208.34 + *
208.35 + * If you wish your version of this file to be governed by only the CDDL
208.36 + * or only the GPL Version 2, indicate your decision by adding
208.37 + * "[Contributor] elects to include this software in this distribution
208.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
208.39 + * single choice of license, a recipient has the option to distribute
208.40 + * your version of this file under either the CDDL, the GPL Version 2 or
208.41 + * to extend the choice of license to its licensees as provided above.
208.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
208.43 + * Version 2 license, then the option applies only if the new code is
208.44 + * made subject to such option by the copyright holder.
208.45 + */
208.46 +package org.netbeans.html.ko.osgi.test;
208.47 +
208.48 +import java.io.ByteArrayInputStream;
208.49 +import java.io.ByteArrayOutputStream;
208.50 +import java.io.IOException;
208.51 +import java.io.InputStream;
208.52 +import java.io.OutputStream;
208.53 +import java.io.Reader;
208.54 +import java.net.URI;
208.55 +import java.net.URISyntaxException;
208.56 +import java.util.ArrayList;
208.57 +import java.util.List;
208.58 +import java.util.logging.Level;
208.59 +import java.util.logging.Logger;
208.60 +import org.glassfish.grizzly.PortRange;
208.61 +import org.glassfish.grizzly.http.server.HttpHandler;
208.62 +import org.glassfish.grizzly.http.server.HttpServer;
208.63 +import org.glassfish.grizzly.http.server.NetworkListener;
208.64 +import org.glassfish.grizzly.http.server.Request;
208.65 +import org.glassfish.grizzly.http.server.Response;
208.66 +import org.glassfish.grizzly.http.server.ServerConfiguration;
208.67 +import org.glassfish.grizzly.websockets.WebSocket;
208.68 +import org.glassfish.grizzly.websockets.WebSocketAddOn;
208.69 +import org.glassfish.grizzly.websockets.WebSocketApplication;
208.70 +import org.glassfish.grizzly.websockets.WebSocketEngine;
208.71 +
208.72 +/**
208.73 + *
208.74 + * @author Jaroslav Tulach <jtulach@netbeans.org>
208.75 + */
208.76 +final class DynamicHTTP extends HttpHandler {
208.77 + private static final Logger LOG = Logger.getLogger(DynamicHTTP.class.getName());
208.78 + private static int resourcesCount;
208.79 + private static List<Resource> resources;
208.80 + private static ServerConfiguration conf;
208.81 + private static HttpServer server;
208.82 +
208.83 + private DynamicHTTP() {
208.84 + }
208.85 +
208.86 + static URI initServer() throws Exception {
208.87 + server = HttpServer.createSimpleServer(null, new PortRange(8080, 65535));
208.88 + final WebSocketAddOn addon = new WebSocketAddOn();
208.89 + for (NetworkListener listener : server.getListeners()) {
208.90 + listener.registerAddOn(addon);
208.91 + }
208.92 + resources = new ArrayList<Resource>();
208.93 +
208.94 + conf = server.getServerConfiguration();
208.95 + final DynamicHTTP dh = new DynamicHTTP();
208.96 +
208.97 + conf.addHttpHandler(dh, "/");
208.98 +
208.99 + server.start();
208.100 +
208.101 + return pageURL("http", server, "/test.html");
208.102 + }
208.103 +
208.104 + @Override
208.105 + public void service(Request request, Response response) throws Exception {
208.106 + if ("/test.html".equals(request.getRequestURI())) {
208.107 + response.setContentType("text/html");
208.108 + final InputStream is = DynamicHTTP.class.getResourceAsStream("test.html");
208.109 + copyStream(is, response.getOutputStream(), null);
208.110 + return;
208.111 + }
208.112 + if ("/dynamic".equals(request.getRequestURI())) {
208.113 + String mimeType = request.getParameter("mimeType");
208.114 + List<String> params = new ArrayList<String>();
208.115 + boolean webSocket = false;
208.116 + for (int i = 0;; i++) {
208.117 + String p = request.getParameter("param" + i);
208.118 + if (p == null) {
208.119 + break;
208.120 + }
208.121 + if ("protocol:ws".equals(p)) {
208.122 + webSocket = true;
208.123 + continue;
208.124 + }
208.125 + params.add(p);
208.126 + }
208.127 + final String cnt = request.getParameter("content");
208.128 + String mangle = cnt.replace("%20", " ").replace("%0A", "\n");
208.129 + ByteArrayInputStream is = new ByteArrayInputStream(mangle.getBytes("UTF-8"));
208.130 + URI url;
208.131 + final Resource res = new Resource(is, mimeType, "/dynamic/res" + ++resourcesCount, params.toArray(new String[params.size()]));
208.132 + if (webSocket) {
208.133 + url = registerWebSocket(res);
208.134 + } else {
208.135 + url = registerResource(res);
208.136 + }
208.137 + response.getWriter().write(url.toString());
208.138 + response.getWriter().write("\n");
208.139 + return;
208.140 + }
208.141 +
208.142 + for (Resource r : resources) {
208.143 + if (r.httpPath.equals(request.getRequestURI())) {
208.144 + response.setContentType(r.httpType);
208.145 + r.httpContent.reset();
208.146 + String[] params = null;
208.147 + if (r.parameters.length != 0) {
208.148 + params = new String[r.parameters.length];
208.149 + for (int i = 0; i < r.parameters.length; i++) {
208.150 + params[i] = request.getParameter(r.parameters[i]);
208.151 + if (params[i] == null) {
208.152 + if ("http.method".equals(r.parameters[i])) {
208.153 + params[i] = request.getMethod().toString();
208.154 + } else if ("http.requestBody".equals(r.parameters[i])) {
208.155 + Reader rdr = request.getReader();
208.156 + StringBuilder sb = new StringBuilder();
208.157 + for (;;) {
208.158 + int ch = rdr.read();
208.159 + if (ch == -1) {
208.160 + break;
208.161 + }
208.162 + sb.append((char) ch);
208.163 + }
208.164 + params[i] = sb.toString();
208.165 + }
208.166 + }
208.167 + if (params[i] == null) {
208.168 + params[i] = "null";
208.169 + }
208.170 + }
208.171 + }
208.172 +
208.173 + copyStream(r.httpContent, response.getOutputStream(), null, params);
208.174 + }
208.175 + }
208.176 + }
208.177 +
208.178 + private URI registerWebSocket(Resource r) {
208.179 + WebSocketEngine.getEngine().register("", r.httpPath, new WS(r));
208.180 + return pageURL("ws", server, r.httpPath);
208.181 + }
208.182 +
208.183 + private URI registerResource(Resource r) {
208.184 + if (!resources.contains(r)) {
208.185 + resources.add(r);
208.186 + conf.addHttpHandler(this, r.httpPath);
208.187 + }
208.188 + return pageURL("http", server, r.httpPath);
208.189 + }
208.190 +
208.191 + private static URI pageURL(String proto, HttpServer server, final String page) {
208.192 + NetworkListener listener = server.getListeners().iterator().next();
208.193 + int port = listener.getPort();
208.194 + try {
208.195 + return new URI(proto + "://localhost:" + port + page);
208.196 + } catch (URISyntaxException ex) {
208.197 + throw new IllegalStateException(ex);
208.198 + }
208.199 + }
208.200 +
208.201 + static final class Resource {
208.202 +
208.203 + final InputStream httpContent;
208.204 + final String httpType;
208.205 + final String httpPath;
208.206 + final String[] parameters;
208.207 +
208.208 + Resource(InputStream httpContent, String httpType, String httpPath,
208.209 + String[] parameters) {
208.210 + httpContent.mark(Integer.MAX_VALUE);
208.211 + this.httpContent = httpContent;
208.212 + this.httpType = httpType;
208.213 + this.httpPath = httpPath;
208.214 + this.parameters = parameters;
208.215 + }
208.216 + }
208.217 +
208.218 + static void copyStream(InputStream is, OutputStream os, String baseURL, String... params) throws IOException {
208.219 + for (;;) {
208.220 + int ch = is.read();
208.221 + if (ch == -1) {
208.222 + break;
208.223 + }
208.224 + if (ch == '$' && params.length > 0) {
208.225 + int cnt = is.read() - '0';
208.226 + if (baseURL != null && cnt == 'U' - '0') {
208.227 + os.write(baseURL.getBytes("UTF-8"));
208.228 + } else {
208.229 + if (cnt >= 0 && cnt < params.length) {
208.230 + os.write(params[cnt].getBytes("UTF-8"));
208.231 + } else {
208.232 + os.write('$');
208.233 + os.write(cnt + '0');
208.234 + }
208.235 + }
208.236 + } else {
208.237 + os.write(ch);
208.238 + }
208.239 + }
208.240 + }
208.241 +
208.242 + private static class WS extends WebSocketApplication {
208.243 + private final Resource r;
208.244 +
208.245 + private WS(Resource r) {
208.246 + this.r = r;
208.247 + }
208.248 +
208.249 + @Override
208.250 + public void onMessage(WebSocket socket, String text) {
208.251 + try {
208.252 + r.httpContent.reset();
208.253 + ByteArrayOutputStream out = new ByteArrayOutputStream();
208.254 + copyStream(r.httpContent, out, null, text);
208.255 + String s = new String(out.toByteArray(), "UTF-8");
208.256 + socket.send(s);
208.257 + } catch (IOException ex) {
208.258 + LOG.log(Level.WARNING, "Error processing message " + text, ex);
208.259 + }
208.260 + }
208.261 + }
208.262 +}
209.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
209.2 +++ b/ko-osgi-test/src/test/java/org/netbeans/html/ko/osgi/test/KOFx.java Tue Jan 07 08:21:57 2014 +0100
209.3 @@ -0,0 +1,118 @@
209.4 +/**
209.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
209.6 + *
209.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
209.8 + *
209.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
209.10 + * Other names may be trademarks of their respective owners.
209.11 + *
209.12 + * The contents of this file are subject to the terms of either the GNU
209.13 + * General Public License Version 2 only ("GPL") or the Common
209.14 + * Development and Distribution License("CDDL") (collectively, the
209.15 + * "License"). You may not use this file except in compliance with the
209.16 + * License. You can obtain a copy of the License at
209.17 + * http://www.netbeans.org/cddl-gplv2.html
209.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
209.19 + * specific language governing permissions and limitations under the
209.20 + * License. When distributing the software, include this License Header
209.21 + * Notice in each file and include the License file at
209.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
209.23 + * particular file as subject to the "Classpath" exception as provided
209.24 + * by Oracle in the GPL Version 2 section of the License file that
209.25 + * accompanied this code. If applicable, add the following below the
209.26 + * License Header, with the fields enclosed by brackets [] replaced by
209.27 + * your own identifying information:
209.28 + * "Portions Copyrighted [year] [name of copyright owner]"
209.29 + *
209.30 + * Contributor(s):
209.31 + *
209.32 + * The Original Software is NetBeans. The Initial Developer of the Original
209.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
209.34 + *
209.35 + * If you wish your version of this file to be governed by only the CDDL
209.36 + * or only the GPL Version 2, indicate your decision by adding
209.37 + * "[Contributor] elects to include this software in this distribution
209.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
209.39 + * single choice of license, a recipient has the option to distribute
209.40 + * your version of this file under either the CDDL, the GPL Version 2 or
209.41 + * to extend the choice of license to its licensees as provided above.
209.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
209.43 + * Version 2 license, then the option applies only if the new code is
209.44 + * made subject to such option by the copyright holder.
209.45 + */
209.46 +package org.netbeans.html.ko.osgi.test;
209.47 +
209.48 +import java.io.Closeable;
209.49 +import java.lang.reflect.InvocationTargetException;
209.50 +import java.lang.reflect.Method;
209.51 +import javafx.application.Platform;
209.52 +import org.apidesign.html.boot.spi.Fn;
209.53 +import org.testng.ITest;
209.54 +import org.testng.annotations.Test;
209.55 +
209.56 +/**
209.57 + *
209.58 + * @author Jaroslav Tulach <jtulach@netbeans.org>
209.59 + */
209.60 +public final class KOFx implements ITest, Runnable {
209.61 + private final Object p;
209.62 + private final Method m;
209.63 + private Object result;
209.64 + private Object inst;
209.65 + private int count;
209.66 +
209.67 + KOFx(Object p, Method m) {
209.68 + this.p = p;
209.69 + this.m = m;
209.70 + }
209.71 +
209.72 + @Override
209.73 + public String getTestName() {
209.74 + return m.getName();
209.75 + }
209.76 +
209.77 + @Test
209.78 + public synchronized void executeTest() throws Exception {
209.79 + if (result == null) {
209.80 + Platform.runLater(this);
209.81 + wait();
209.82 + }
209.83 + if (result instanceof Exception) {
209.84 + throw (Exception)result;
209.85 + }
209.86 + if (result instanceof Error) {
209.87 + throw (Error)result;
209.88 + }
209.89 + }
209.90 +
209.91 + @Override
209.92 + public synchronized void run() {
209.93 + boolean notify = true;
209.94 + try (Closeable a = KnockoutEquinoxIT.activateInOSGi(p)) {
209.95 + if (inst == null) {
209.96 + inst = m.getDeclaringClass().newInstance();
209.97 + }
209.98 + result = m.invoke(inst);
209.99 + if (result == null) {
209.100 + result = this;
209.101 + }
209.102 + } catch (InvocationTargetException ex) {
209.103 + Throwable r = ex.getTargetException();
209.104 + if (r instanceof InterruptedException) {
209.105 + if (count++ < 10000) {
209.106 + notify = false;
209.107 + Platform.runLater(this);
209.108 + return;
209.109 + }
209.110 + }
209.111 + result = r;
209.112 + } catch (Exception ex) {
209.113 + result = ex;
209.114 + } finally {
209.115 + if (notify) {
209.116 + notifyAll();
209.117 + }
209.118 + }
209.119 + }
209.120 +
209.121 +}
210.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
210.2 +++ b/ko-osgi-test/src/test/java/org/netbeans/html/ko/osgi/test/KnockoutEquinoxIT.java Tue Jan 07 08:21:57 2014 +0100
210.3 @@ -0,0 +1,243 @@
210.4 +/**
210.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
210.6 + *
210.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
210.8 + *
210.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
210.10 + * Other names may be trademarks of their respective owners.
210.11 + *
210.12 + * The contents of this file are subject to the terms of either the GNU
210.13 + * General Public License Version 2 only ("GPL") or the Common
210.14 + * Development and Distribution License("CDDL") (collectively, the
210.15 + * "License"). You may not use this file except in compliance with the
210.16 + * License. You can obtain a copy of the License at
210.17 + * http://www.netbeans.org/cddl-gplv2.html
210.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
210.19 + * specific language governing permissions and limitations under the
210.20 + * License. When distributing the software, include this License Header
210.21 + * Notice in each file and include the License file at
210.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
210.23 + * particular file as subject to the "Classpath" exception as provided
210.24 + * by Oracle in the GPL Version 2 section of the License file that
210.25 + * accompanied this code. If applicable, add the following below the
210.26 + * License Header, with the fields enclosed by brackets [] replaced by
210.27 + * your own identifying information:
210.28 + * "Portions Copyrighted [year] [name of copyright owner]"
210.29 + *
210.30 + * Contributor(s):
210.31 + *
210.32 + * The Original Software is NetBeans. The Initial Developer of the Original
210.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
210.34 + *
210.35 + * If you wish your version of this file to be governed by only the CDDL
210.36 + * or only the GPL Version 2, indicate your decision by adding
210.37 + * "[Contributor] elects to include this software in this distribution
210.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
210.39 + * single choice of license, a recipient has the option to distribute
210.40 + * your version of this file under either the CDDL, the GPL Version 2 or
210.41 + * to extend the choice of license to its licensees as provided above.
210.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
210.43 + * Version 2 license, then the option applies only if the new code is
210.44 + * made subject to such option by the copyright holder.
210.45 + */
210.46 +package org.netbeans.html.ko.osgi.test;
210.47 +
210.48 +import java.io.Closeable;
210.49 +import java.io.File;
210.50 +import java.io.IOException;
210.51 +import java.lang.annotation.Annotation;
210.52 +import java.lang.reflect.Method;
210.53 +import java.net.URI;
210.54 +import java.util.ArrayList;
210.55 +import java.util.HashMap;
210.56 +import java.util.List;
210.57 +import java.util.Map;
210.58 +import java.util.ServiceLoader;
210.59 +import java.util.concurrent.Callable;
210.60 +import java.util.jar.JarFile;
210.61 +import java.util.logging.Level;
210.62 +import java.util.logging.Logger;
210.63 +import org.apidesign.html.boot.spi.Fn;
210.64 +import org.apidesign.html.json.tck.KOTest;
210.65 +import org.apidesign.html.json.tck.KnockoutTCK;
210.66 +import org.osgi.framework.Bundle;
210.67 +import org.osgi.framework.BundleException;
210.68 +import org.osgi.framework.Constants;
210.69 +import org.osgi.framework.launch.Framework;
210.70 +import org.osgi.framework.launch.FrameworkFactory;
210.71 +import static org.testng.Assert.assertNotNull;
210.72 +import static org.testng.Assert.fail;
210.73 +import org.testng.annotations.AfterClass;
210.74 +import org.testng.annotations.Factory;
210.75 +
210.76 +/**
210.77 + *
210.78 + * @author Jaroslav Tulach <jtulach@netbeans.org>
210.79 + */
210.80 +public class KnockoutEquinoxIT {
210.81 + private static final Logger LOG = Logger.getLogger(KnockoutEquinoxIT.class.getName());
210.82 + private static Framework framework;
210.83 + private static File dir;
210.84 + static Framework framework() throws Exception {
210.85 + if (framework != null) {
210.86 + return framework;
210.87 + }
210.88 + for (FrameworkFactory ff : ServiceLoader.load(FrameworkFactory.class)) {
210.89 +
210.90 + String basedir = System.getProperty("basedir");
210.91 + assertNotNull("basedir preperty provided", basedir);
210.92 + File target = new File(basedir, "target");
210.93 + dir = new File(target, "osgi");
210.94 + dir.mkdirs();
210.95 +
210.96 + Map<String,String> config = new HashMap<>();
210.97 + config.put(Constants.FRAMEWORK_STORAGE, dir.getPath());
210.98 + config.put(Constants.FRAMEWORK_STORAGE_CLEAN, "true");
210.99 + config.put(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA, "sun.misc,"
210.100 + + "javafx.application,"
210.101 + + "javafx.beans.property,"
210.102 + + "javafx.beans.value,"
210.103 + + "javafx.collections,"
210.104 + + "javafx.concurrent,"
210.105 + + "javafx.event,"
210.106 + + "javafx.geometry,"
210.107 + + "javafx.scene,"
210.108 + + "javafx.scene.control,"
210.109 + + "javafx.scene.layout,"
210.110 + + "javafx.scene.text,"
210.111 + + "javafx.scene.web,"
210.112 + + "javafx.stage,"
210.113 + + "javafx.util,"
210.114 + + "netscape.javascript"
210.115 + );
210.116 + config.put("osgi.hook.configurators.include", "org.netbeans.html.equinox.agentclass.AgentHook");
210.117 + framework = ff.newFramework(config);
210.118 + framework.init();
210.119 + loadClassPathBundles(framework);
210.120 + framework.start();
210.121 + for (Bundle b : framework.getBundleContext().getBundles()) {
210.122 + try {
210.123 + if (b.getSymbolicName().contains("equinox-agentclass-hook")) {
210.124 + continue;
210.125 + }
210.126 + if (b.getSymbolicName().contains("grizzly.websockets-server")) {
210.127 + continue;
210.128 + }
210.129 + b.start();
210.130 + LOG.log(Level.INFO, "Started {0}", b.getSymbolicName());
210.131 + } catch (BundleException ex) {
210.132 + LOG.log(Level.WARNING, "Cannot start bundle " + b.getSymbolicName(), ex);
210.133 + }
210.134 + }
210.135 + return framework;
210.136 + }
210.137 + fail("No OSGi framework in the path");
210.138 + return null;
210.139 + }
210.140 +
210.141 + @AfterClass public static void cleanUp() throws Exception {
210.142 + if (framework != null) framework.stop();
210.143 + clearUpDir(dir);
210.144 + }
210.145 + private static void clearUpDir(File dir) {
210.146 + if (dir.isDirectory()) {
210.147 + for (File f : dir.listFiles()) {
210.148 + clearUpDir(f);
210.149 + }
210.150 + }
210.151 + dir.delete();
210.152 + }
210.153 +
210.154 +
210.155 +
210.156 + private static void loadClassPathBundles(Framework f) throws IOException, BundleException {
210.157 + for (String jar : System.getProperty("java.class.path").split(File.pathSeparator)) {
210.158 + File file = new File(jar);
210.159 + if (!file.isFile()) {
210.160 + LOG.info("Not loading " + file);
210.161 + continue;
210.162 + }
210.163 + JarFile jf = new JarFile(file);
210.164 + final String name = jf.getManifest().getMainAttributes().getValue("Bundle-SymbolicName");
210.165 + jf.close();
210.166 + if (name != null) {
210.167 + if (name.contains("org.eclipse.osgi")) {
210.168 + continue;
210.169 + }
210.170 + if (name.contains("testng")) {
210.171 + continue;
210.172 + }
210.173 + final String path = "reference:" + file.toURI().toString();
210.174 + try {
210.175 + Bundle b = f.getBundleContext().installBundle(path);
210.176 + } catch (BundleException ex) {
210.177 + LOG.log(Level.WARNING, "Cannot install " + file, ex);
210.178 + }
210.179 + }
210.180 + }
210.181 + }
210.182 +
210.183 + private static Class<?> loadOSGiClass(Class<?> c) throws Exception {
210.184 + return KnockoutEquinoxTCKImpl.loadOSGiClass(c.getName(), KnockoutEquinoxIT.framework().getBundleContext());
210.185 + }
210.186 +
210.187 + private static Class<?> browserClass;
210.188 + private static Object browserContext;
210.189 +
210.190 + @Factory public static Object[] compatibilityTests() throws Exception {
210.191 + Class<?> tck = loadOSGiClass(KnockoutTCK.class);
210.192 + Class<?> peer = loadOSGiClass(KnockoutEquinoxTCKImpl.class);
210.193 + // initialize the TCK
210.194 + Callable<Class[]> inst = (Callable<Class[]>) peer.newInstance();
210.195 +
210.196 + Class[] arr = inst.call();
210.197 + for (int i = 0; i < arr.length; i++) {
210.198 + if (arr[i].getClassLoader() == ClassLoader.getSystemClassLoader()) {
210.199 + fail("Should be an OSGi class: " + arr[i]);
210.200 + }
210.201 + }
210.202 +
210.203 + URI uri = DynamicHTTP.initServer();
210.204 +
210.205 + Method start = peer.getMethod("start", URI.class);
210.206 + start.invoke(null, uri);
210.207 +
210.208 + ClassLoader l = getClassLoader();
210.209 + List<Object> res = new ArrayList<Object>();
210.210 + for (int i = 0; i < arr.length; i++) {
210.211 + seekKOTests(arr[i], res);
210.212 + }
210.213 + return res.toArray();
210.214 + }
210.215 +
210.216 + private static void seekKOTests(Class<?> c, List<Object> res) throws SecurityException, ClassNotFoundException {
210.217 + Class<? extends Annotation> koTest =
210.218 + c.getClassLoader().loadClass(KOTest.class.getName()).
210.219 + asSubclass(Annotation.class);
210.220 + for (Method m : c.getMethods()) {
210.221 + if (m.getAnnotation(koTest) != null) {
210.222 + res.add(new KOFx(browserContext, m));
210.223 + }
210.224 + }
210.225 + }
210.226 +
210.227 + static synchronized ClassLoader getClassLoader() throws InterruptedException {
210.228 + while (browserClass == null) {
210.229 + KnockoutEquinoxIT.class.wait();
210.230 + }
210.231 + return browserClass.getClassLoader();
210.232 + }
210.233 +
210.234 + public static synchronized void initialized(Class<?> browserCls, Object presenter) throws Exception {
210.235 + browserClass = browserCls;
210.236 + browserContext = presenter;
210.237 + KnockoutEquinoxIT.class.notifyAll();
210.238 + }
210.239 +
210.240 + static Closeable activateInOSGi(Object presenter) throws Exception {
210.241 + Class<?> presenterClass = loadOSGiClass(Fn.Presenter.class);
210.242 + Class<?> fnClass = loadOSGiClass(Fn.class);
210.243 + Method m = fnClass.getMethod("activate", presenterClass);
210.244 + return (Closeable) m.invoke(null, presenter);
210.245 + }
210.246 +}
211.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
211.2 +++ b/ko-osgi-test/src/test/resources/org/netbeans/html/ko/osgi/test/test.html Tue Jan 07 08:21:57 2014 +0100
211.3 @@ -0,0 +1,56 @@
211.4 +<!--
211.5 +
211.6 + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
211.7 +
211.8 + Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
211.9 +
211.10 + Oracle and Java are registered trademarks of Oracle and/or its affiliates.
211.11 + Other names may be trademarks of their respective owners.
211.12 +
211.13 + The contents of this file are subject to the terms of either the GNU
211.14 + General Public License Version 2 only ("GPL") or the Common
211.15 + Development and Distribution License("CDDL") (collectively, the
211.16 + "License"). You may not use this file except in compliance with the
211.17 + License. You can obtain a copy of the License at
211.18 + http://www.netbeans.org/cddl-gplv2.html
211.19 + or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
211.20 + specific language governing permissions and limitations under the
211.21 + License. When distributing the software, include this License Header
211.22 + Notice in each file and include the License file at
211.23 + nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
211.24 + particular file as subject to the "Classpath" exception as provided
211.25 + by Oracle in the GPL Version 2 section of the License file that
211.26 + accompanied this code. If applicable, add the following below the
211.27 + License Header, with the fields enclosed by brackets [] replaced by
211.28 + your own identifying information:
211.29 + "Portions Copyrighted [year] [name of copyright owner]"
211.30 +
211.31 + Contributor(s):
211.32 +
211.33 + The Original Software is NetBeans. The Initial Developer of the Original
211.34 + Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
211.35 +
211.36 + If you wish your version of this file to be governed by only the CDDL
211.37 + or only the GPL Version 2, indicate your decision by adding
211.38 + "[Contributor] elects to include this software in this distribution
211.39 + under the [CDDL or GPL Version 2] license." If you do not indicate a
211.40 + single choice of license, a recipient has the option to distribute
211.41 + your version of this file under either the CDDL, the GPL Version 2 or
211.42 + to extend the choice of license to its licensees as provided above.
211.43 + However, if you add GPL Version 2 code and therefore, elected the GPL
211.44 + Version 2 license, then the option applies only if the new code is
211.45 + made subject to such option by the copyright holder.
211.46 +
211.47 +-->
211.48 +<!DOCTYPE html>
211.49 +<html>
211.50 + <head>
211.51 + <title>Knockout.fx Execution Harness</title>
211.52 + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
211.53 + <meta name="viewport" content="width=device-width">
211.54 + </head>
211.55 + <body>
211.56 + <h1>Knockout.fx Execution Harness</h1>
211.57 + </body>
211.58 + <script></script>
211.59 +</html>
212.1 --- a/ko-ws-tyrus/pom.xml Thu Dec 19 17:11:01 2013 +0100
212.2 +++ b/ko-ws-tyrus/pom.xml Tue Jan 07 08:21:57 2014 +0100
212.3 @@ -2,11 +2,11 @@
212.4 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
212.5 <modelVersion>4.0.0</modelVersion>
212.6 <parent>
212.7 - <groupId>org.apidesign</groupId>
212.8 - <artifactId>html</artifactId>
212.9 + <groupId>org.netbeans.html</groupId>
212.10 + <artifactId>pom</artifactId>
212.11 <version>0.7-SNAPSHOT</version>
212.12 </parent>
212.13 - <groupId>org.apidesign.html</groupId>
212.14 + <groupId>org.netbeans.html</groupId>
212.15 <artifactId>ko-ws-tyrus</artifactId>
212.16 <version>0.7-SNAPSHOT</version>
212.17 <packaging>bundle</packaging>
212.18 @@ -38,6 +38,7 @@
212.19 </build>
212.20 <properties>
212.21 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
212.22 + <bundleSymbolicName>org.netbeans.html.ko-ws-tyrus</bundleSymbolicName>
212.23 </properties>
212.24 <dependencies>
212.25 <!-- compile only deps -->
212.26 @@ -126,7 +127,7 @@
212.27 </dependency>
212.28 <dependency>
212.29 <groupId>${project.groupId}</groupId>
212.30 - <artifactId>boot-fx</artifactId>
212.31 + <artifactId>net.java.html.boot.fx</artifactId>
212.32 <version>${project.version}</version>
212.33 <scope>test</scope>
212.34 </dependency>
213.1 --- a/ko-ws-tyrus/src/main/java/org/apidesign/html/wstyrus/TyrusContext.java Thu Dec 19 17:11:01 2013 +0100
213.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
213.3 @@ -1,168 +0,0 @@
213.4 -/**
213.5 - * HTML via Java(tm) Language Bindings
213.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
213.7 - *
213.8 - * This program is free software: you can redistribute it and/or modify
213.9 - * it under the terms of the GNU General Public License as published by
213.10 - * the Free Software Foundation, version 2 of the License.
213.11 - *
213.12 - * This program is distributed in the hope that it will be useful,
213.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
213.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
213.15 - * GNU General Public License for more details. apidesign.org
213.16 - * designates this particular file as subject to the
213.17 - * "Classpath" exception as provided by apidesign.org
213.18 - * in the License file that accompanied this code.
213.19 - *
213.20 - * You should have received a copy of the GNU General Public License
213.21 - * along with this program. Look for COPYING file in the top folder.
213.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
213.23 - */
213.24 -package org.apidesign.html.wstyrus;
213.25 -
213.26 -import java.io.IOException;
213.27 -import java.net.URI;
213.28 -import java.net.URISyntaxException;
213.29 -import java.util.Iterator;
213.30 -import javax.websocket.ClientEndpoint;
213.31 -import javax.websocket.ContainerProvider;
213.32 -import javax.websocket.DeploymentException;
213.33 -import javax.websocket.OnClose;
213.34 -import javax.websocket.OnError;
213.35 -import javax.websocket.OnMessage;
213.36 -import javax.websocket.OnOpen;
213.37 -import javax.websocket.Session;
213.38 -import javax.websocket.WebSocketContainer;
213.39 -import net.java.html.json.OnReceive;
213.40 -import org.apidesign.html.context.spi.Contexts;
213.41 -import org.apidesign.html.json.spi.JSONCall;
213.42 -import org.apidesign.html.json.spi.WSTransfer;
213.43 -import org.apidesign.html.wstyrus.TyrusContext.Comm;
213.44 -import org.json.JSONArray;
213.45 -import org.json.JSONException;
213.46 -import org.json.JSONObject;
213.47 -import org.json.JSONTokener;
213.48 -import org.openide.util.lookup.ServiceProvider;
213.49 -
213.50 -/** This is an implementation module that provides support for
213.51 - * WebSocket protocol for {@link OnReceive} communication end point for
213.52 - * JDK7.
213.53 - * <p>
213.54 - * Don't deal with this module directly, rather use the
213.55 - * {@link OnReceive @OnReceive(url="ws://...", ...)} API to establish your
213.56 - * WebSocket connection.
213.57 - * <p>
213.58 - * There is no need to include this module in your application if you are
213.59 - * running on JDK8. JDK8 WebView provides its own implementation of the
213.60 - * WebSocket API based on WebSocket object inside a browser. This is included
213.61 - * in the <code>org.apidesign.html:ko-fx:0.5</code> module.
213.62 - *
213.63 - * @author Jaroslav Tulach <jtulach@netbeans.org>
213.64 - */
213.65 -@ServiceProvider(service = Contexts.Provider.class)
213.66 -public final class TyrusContext implements Contexts.Provider, WSTransfer<Comm> {
213.67 - @Override
213.68 - public void fillContext(Contexts.Builder context, Class<?> requestor) {
213.69 - // default WebSocket transfer implementation is registered
213.70 - // in ko-fx module with 100, provide this one as a fallback only
213.71 - context.register(WSTransfer.class, this, 1000);
213.72 - }
213.73 -
213.74 - @Override
213.75 - public Comm open(String url, JSONCall callback) {
213.76 - try {
213.77 - return new Comm(new URI(url), callback);
213.78 - } catch (URISyntaxException ex) {
213.79 - throw new IllegalStateException(ex);
213.80 - }
213.81 - }
213.82 -
213.83 - @Override
213.84 - public void send(Comm socket, JSONCall data) {
213.85 - socket.session.getAsyncRemote().sendText(data.getMessage());
213.86 - }
213.87 -
213.88 - @Override
213.89 - public void close(Comm socket) {
213.90 - try {
213.91 - final Session s = socket.session;
213.92 - if (s != null) {
213.93 - s.close();
213.94 - }
213.95 - } catch (IOException ex) {
213.96 - socket.callback.notifyError(ex);
213.97 - }
213.98 - }
213.99 -
213.100 - /** Implementation class in an implementation. Represents a {@link ClientEndpoint} of the
213.101 - * WebSocket channel. You are unlikely to get on hold of it.
213.102 - */
213.103 - @ClientEndpoint
213.104 - public static final class Comm {
213.105 - private final JSONCall callback;
213.106 - private Session session;
213.107 -
213.108 - Comm(final URI url, JSONCall callback) {
213.109 - this.callback = callback;
213.110 - try {
213.111 - final WebSocketContainer c = ContainerProvider.getWebSocketContainer();
213.112 - c.connectToServer(Comm.this, url);
213.113 - } catch (DeploymentException | IOException ex) {
213.114 - wasAnError(ex);
213.115 - }
213.116 - }
213.117 -
213.118 - @OnOpen
213.119 - public synchronized void open(Session s) {
213.120 - this.session = s;
213.121 - callback.notifySuccess(null);
213.122 - }
213.123 -
213.124 - @OnClose
213.125 - public void close() {
213.126 - this.session = null;
213.127 - callback.notifyError(null);
213.128 - }
213.129 -
213.130 - @OnMessage
213.131 - public void message(final String orig, Session s) {
213.132 - Object json;
213.133 - String data = orig.trim();
213.134 - try {
213.135 - JSONTokener tok = new JSONTokener(data);
213.136 - Object obj = data.startsWith("[") ? new JSONArray(tok) : new JSONObject(tok);
213.137 - json = convertToArray(obj);
213.138 - } catch (JSONException ex) {
213.139 - json = data;
213.140 - }
213.141 - callback.notifySuccess(json);
213.142 - }
213.143 -
213.144 - @OnError
213.145 - public void wasAnError(Throwable t) {
213.146 - callback.notifyError(t);
213.147 - }
213.148 -
213.149 - static Object convertToArray(Object o) throws JSONException {
213.150 - if (o instanceof JSONArray) {
213.151 - JSONArray ja = (JSONArray) o;
213.152 - Object[] arr = new Object[ja.length()];
213.153 - for (int i = 0; i < arr.length; i++) {
213.154 - arr[i] = convertToArray(ja.get(i));
213.155 - }
213.156 - return arr;
213.157 - } else if (o instanceof JSONObject) {
213.158 - JSONObject obj = (JSONObject) o;
213.159 - Iterator it = obj.keys();
213.160 - while (it.hasNext()) {
213.161 - String key = (String) it.next();
213.162 - obj.put(key, convertToArray(obj.get(key)));
213.163 - }
213.164 - return obj;
213.165 - } else {
213.166 - return o;
213.167 - }
213.168 - }
213.169 -
213.170 - } // end of Comm
213.171 -}
214.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
214.2 +++ b/ko-ws-tyrus/src/main/java/org/netbeans/html/wstyrus/TyrusContext.java Tue Jan 07 08:21:57 2014 +0100
214.3 @@ -0,0 +1,190 @@
214.4 +/**
214.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
214.6 + *
214.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
214.8 + *
214.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
214.10 + * Other names may be trademarks of their respective owners.
214.11 + *
214.12 + * The contents of this file are subject to the terms of either the GNU
214.13 + * General Public License Version 2 only ("GPL") or the Common
214.14 + * Development and Distribution License("CDDL") (collectively, the
214.15 + * "License"). You may not use this file except in compliance with the
214.16 + * License. You can obtain a copy of the License at
214.17 + * http://www.netbeans.org/cddl-gplv2.html
214.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
214.19 + * specific language governing permissions and limitations under the
214.20 + * License. When distributing the software, include this License Header
214.21 + * Notice in each file and include the License file at
214.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
214.23 + * particular file as subject to the "Classpath" exception as provided
214.24 + * by Oracle in the GPL Version 2 section of the License file that
214.25 + * accompanied this code. If applicable, add the following below the
214.26 + * License Header, with the fields enclosed by brackets [] replaced by
214.27 + * your own identifying information:
214.28 + * "Portions Copyrighted [year] [name of copyright owner]"
214.29 + *
214.30 + * Contributor(s):
214.31 + *
214.32 + * The Original Software is NetBeans. The Initial Developer of the Original
214.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
214.34 + *
214.35 + * If you wish your version of this file to be governed by only the CDDL
214.36 + * or only the GPL Version 2, indicate your decision by adding
214.37 + * "[Contributor] elects to include this software in this distribution
214.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
214.39 + * single choice of license, a recipient has the option to distribute
214.40 + * your version of this file under either the CDDL, the GPL Version 2 or
214.41 + * to extend the choice of license to its licensees as provided above.
214.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
214.43 + * Version 2 license, then the option applies only if the new code is
214.44 + * made subject to such option by the copyright holder.
214.45 + */
214.46 +package org.netbeans.html.wstyrus;
214.47 +
214.48 +import java.io.IOException;
214.49 +import java.net.URI;
214.50 +import java.net.URISyntaxException;
214.51 +import java.util.Iterator;
214.52 +import javax.websocket.ClientEndpoint;
214.53 +import javax.websocket.ContainerProvider;
214.54 +import javax.websocket.DeploymentException;
214.55 +import javax.websocket.OnClose;
214.56 +import javax.websocket.OnError;
214.57 +import javax.websocket.OnMessage;
214.58 +import javax.websocket.OnOpen;
214.59 +import javax.websocket.Session;
214.60 +import javax.websocket.WebSocketContainer;
214.61 +import net.java.html.json.OnReceive;
214.62 +import org.apidesign.html.context.spi.Contexts;
214.63 +import org.apidesign.html.json.spi.JSONCall;
214.64 +import org.apidesign.html.json.spi.WSTransfer;
214.65 +import org.netbeans.html.wstyrus.TyrusContext.Comm;
214.66 +import org.json.JSONArray;
214.67 +import org.json.JSONException;
214.68 +import org.json.JSONObject;
214.69 +import org.json.JSONTokener;
214.70 +import org.openide.util.lookup.ServiceProvider;
214.71 +
214.72 +/** This is an implementation module that provides support for
214.73 + * WebSocket protocol for {@link OnReceive} communication end point for
214.74 + * JDK7.
214.75 + * <p>
214.76 + * Don't deal with this module directly, rather use the
214.77 + * {@link OnReceive @OnReceive(url="ws://...", ...)} API to establish your
214.78 + * WebSocket connection.
214.79 + * <p>
214.80 + * There is no need to include this module in your application if you are
214.81 + * running on JDK8. JDK8 WebView provides its own implementation of the
214.82 + * WebSocket API based on WebSocket object inside a browser. This is included
214.83 + * in the <code>org.apidesign.html:ko-fx:0.5</code> module.
214.84 + *
214.85 + * @author Jaroslav Tulach <jtulach@netbeans.org>
214.86 + */
214.87 +@ServiceProvider(service = Contexts.Provider.class)
214.88 +public final class TyrusContext implements Contexts.Provider, WSTransfer<Comm> {
214.89 + @Override
214.90 + public void fillContext(Contexts.Builder context, Class<?> requestor) {
214.91 + // default WebSocket transfer implementation is registered
214.92 + // in ko-fx module with 100, provide this one as a fallback only
214.93 + context.register(WSTransfer.class, this, 1000);
214.94 + }
214.95 +
214.96 + @Override
214.97 + public Comm open(String url, JSONCall callback) {
214.98 + try {
214.99 + return new Comm(new URI(url), callback);
214.100 + } catch (URISyntaxException ex) {
214.101 + throw new IllegalStateException(ex);
214.102 + }
214.103 + }
214.104 +
214.105 + @Override
214.106 + public void send(Comm socket, JSONCall data) {
214.107 + socket.session.getAsyncRemote().sendText(data.getMessage());
214.108 + }
214.109 +
214.110 + @Override
214.111 + public void close(Comm socket) {
214.112 + try {
214.113 + final Session s = socket.session;
214.114 + if (s != null) {
214.115 + s.close();
214.116 + }
214.117 + } catch (IOException ex) {
214.118 + socket.callback.notifyError(ex);
214.119 + }
214.120 + }
214.121 +
214.122 + /** Implementation class in an implementation. Represents a {@link ClientEndpoint} of the
214.123 + * WebSocket channel. You are unlikely to get on hold of it.
214.124 + */
214.125 + @ClientEndpoint
214.126 + public static final class Comm {
214.127 + private final JSONCall callback;
214.128 + private Session session;
214.129 +
214.130 + Comm(final URI url, JSONCall callback) {
214.131 + this.callback = callback;
214.132 + try {
214.133 + final WebSocketContainer c = ContainerProvider.getWebSocketContainer();
214.134 + c.connectToServer(Comm.this, url);
214.135 + } catch (DeploymentException | IOException ex) {
214.136 + wasAnError(ex);
214.137 + }
214.138 + }
214.139 +
214.140 + @OnOpen
214.141 + public synchronized void open(Session s) {
214.142 + this.session = s;
214.143 + callback.notifySuccess(null);
214.144 + }
214.145 +
214.146 + @OnClose
214.147 + public void close() {
214.148 + this.session = null;
214.149 + callback.notifyError(null);
214.150 + }
214.151 +
214.152 + @OnMessage
214.153 + public void message(final String orig, Session s) {
214.154 + Object json;
214.155 + String data = orig.trim();
214.156 + try {
214.157 + JSONTokener tok = new JSONTokener(data);
214.158 + Object obj = data.startsWith("[") ? new JSONArray(tok) : new JSONObject(tok);
214.159 + json = convertToArray(obj);
214.160 + } catch (JSONException ex) {
214.161 + json = data;
214.162 + }
214.163 + callback.notifySuccess(json);
214.164 + }
214.165 +
214.166 + @OnError
214.167 + public void wasAnError(Throwable t) {
214.168 + callback.notifyError(t);
214.169 + }
214.170 +
214.171 + static Object convertToArray(Object o) throws JSONException {
214.172 + if (o instanceof JSONArray) {
214.173 + JSONArray ja = (JSONArray) o;
214.174 + Object[] arr = new Object[ja.length()];
214.175 + for (int i = 0; i < arr.length; i++) {
214.176 + arr[i] = convertToArray(ja.get(i));
214.177 + }
214.178 + return arr;
214.179 + } else if (o instanceof JSONObject) {
214.180 + JSONObject obj = (JSONObject) o;
214.181 + Iterator it = obj.keys();
214.182 + while (it.hasNext()) {
214.183 + String key = (String) it.next();
214.184 + obj.put(key, convertToArray(obj.get(key)));
214.185 + }
214.186 + return obj;
214.187 + } else {
214.188 + return o;
214.189 + }
214.190 + }
214.191 +
214.192 + } // end of Comm
214.193 +}
215.1 --- a/ko-ws-tyrus/src/test/java/org/apidesign/html/wstyrus/TyrusDynamicHTTP.java Thu Dec 19 17:11:01 2013 +0100
215.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
215.3 @@ -1,238 +0,0 @@
215.4 -/**
215.5 - * HTML via Java(tm) Language Bindings
215.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
215.7 - *
215.8 - * This program is free software: you can redistribute it and/or modify
215.9 - * it under the terms of the GNU General Public License as published by
215.10 - * the Free Software Foundation, version 2 of the License.
215.11 - *
215.12 - * This program is distributed in the hope that it will be useful,
215.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
215.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
215.15 - * GNU General Public License for more details. apidesign.org
215.16 - * designates this particular file as subject to the
215.17 - * "Classpath" exception as provided by apidesign.org
215.18 - * in the License file that accompanied this code.
215.19 - *
215.20 - * You should have received a copy of the GNU General Public License
215.21 - * along with this program. Look for COPYING file in the top folder.
215.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
215.23 - */
215.24 -package org.apidesign.html.wstyrus;
215.25 -
215.26 -import java.io.ByteArrayInputStream;
215.27 -import java.io.ByteArrayOutputStream;
215.28 -import java.io.IOException;
215.29 -import java.io.InputStream;
215.30 -import java.io.OutputStream;
215.31 -import java.io.Reader;
215.32 -import java.net.URI;
215.33 -import java.net.URISyntaxException;
215.34 -import java.util.ArrayList;
215.35 -import java.util.List;
215.36 -import java.util.logging.Level;
215.37 -import java.util.logging.Logger;
215.38 -import org.glassfish.grizzly.PortRange;
215.39 -import org.glassfish.grizzly.http.server.HttpHandler;
215.40 -import org.glassfish.grizzly.http.server.HttpServer;
215.41 -import org.glassfish.grizzly.http.server.NetworkListener;
215.42 -import org.glassfish.grizzly.http.server.Request;
215.43 -import org.glassfish.grizzly.http.server.Response;
215.44 -import org.glassfish.grizzly.http.server.ServerConfiguration;
215.45 -import org.glassfish.grizzly.websockets.WebSocket;
215.46 -import org.glassfish.grizzly.websockets.WebSocketAddOn;
215.47 -import org.glassfish.grizzly.websockets.WebSocketApplication;
215.48 -import org.glassfish.grizzly.websockets.WebSocketEngine;
215.49 -
215.50 -/**
215.51 - *
215.52 - * @author Jaroslav Tulach <jtulach@netbeans.org>
215.53 - */
215.54 -final class TyrusDynamicHTTP extends HttpHandler {
215.55 - private static int resourcesCount;
215.56 - private static List<Resource> resources;
215.57 - private static ServerConfiguration conf;
215.58 - private static HttpServer server;
215.59 -
215.60 - private TyrusDynamicHTTP() {
215.61 - }
215.62 -
215.63 - static URI initServer() throws Exception {
215.64 - server = HttpServer.createSimpleServer(null, new PortRange(8080, 65535));
215.65 - final WebSocketAddOn addon = new WebSocketAddOn();
215.66 - for (NetworkListener listener : server.getListeners()) {
215.67 - listener.registerAddOn(addon);
215.68 - }
215.69 - resources = new ArrayList<Resource>();
215.70 -
215.71 - conf = server.getServerConfiguration();
215.72 - final TyrusDynamicHTTP dh = new TyrusDynamicHTTP();
215.73 -
215.74 - conf.addHttpHandler(dh, "/");
215.75 -
215.76 - server.start();
215.77 -
215.78 - return pageURL("http", server, "/test.html");
215.79 - }
215.80 -
215.81 - @Override
215.82 - public void service(Request request, Response response) throws Exception {
215.83 - if ("/test.html".equals(request.getRequestURI())) {
215.84 - response.setContentType("text/html");
215.85 - final InputStream is = TyrusDynamicHTTP.class.getResourceAsStream("test.html");
215.86 - copyStream(is, response.getOutputStream(), null);
215.87 - return;
215.88 - }
215.89 - if ("/dynamic".equals(request.getRequestURI())) {
215.90 - String mimeType = request.getParameter("mimeType");
215.91 - List<String> params = new ArrayList<String>();
215.92 - boolean webSocket = false;
215.93 - for (int i = 0;; i++) {
215.94 - String p = request.getParameter("param" + i);
215.95 - if (p == null) {
215.96 - break;
215.97 - }
215.98 - if ("protocol:ws".equals(p)) {
215.99 - webSocket = true;
215.100 - continue;
215.101 - }
215.102 - params.add(p);
215.103 - }
215.104 - final String cnt = request.getParameter("content");
215.105 - String mangle = cnt.replace("%20", " ").replace("%0A", "\n");
215.106 - ByteArrayInputStream is = new ByteArrayInputStream(mangle.getBytes("UTF-8"));
215.107 - URI url;
215.108 - final Resource res = new Resource(is, mimeType, "/dynamic/res" + ++resourcesCount, params.toArray(new String[params.size()]));
215.109 - if (webSocket) {
215.110 - url = registerWebSocket(res);
215.111 - } else {
215.112 - url = registerResource(res);
215.113 - }
215.114 - response.getWriter().write(url.toString());
215.115 - response.getWriter().write("\n");
215.116 - return;
215.117 - }
215.118 -
215.119 - for (Resource r : resources) {
215.120 - if (r.httpPath.equals(request.getRequestURI())) {
215.121 - response.setContentType(r.httpType);
215.122 - r.httpContent.reset();
215.123 - String[] params = null;
215.124 - if (r.parameters.length != 0) {
215.125 - params = new String[r.parameters.length];
215.126 - for (int i = 0; i < r.parameters.length; i++) {
215.127 - params[i] = request.getParameter(r.parameters[i]);
215.128 - if (params[i] == null) {
215.129 - if ("http.method".equals(r.parameters[i])) {
215.130 - params[i] = request.getMethod().toString();
215.131 - } else if ("http.requestBody".equals(r.parameters[i])) {
215.132 - Reader rdr = request.getReader();
215.133 - StringBuilder sb = new StringBuilder();
215.134 - for (;;) {
215.135 - int ch = rdr.read();
215.136 - if (ch == -1) {
215.137 - break;
215.138 - }
215.139 - sb.append((char) ch);
215.140 - }
215.141 - params[i] = sb.toString();
215.142 - }
215.143 - }
215.144 - if (params[i] == null) {
215.145 - params[i] = "null";
215.146 - }
215.147 - }
215.148 - }
215.149 -
215.150 - copyStream(r.httpContent, response.getOutputStream(), null, params);
215.151 - }
215.152 - }
215.153 - }
215.154 -
215.155 - private URI registerWebSocket(Resource r) {
215.156 - WebSocketEngine.getEngine().register("", r.httpPath, new WS(r));
215.157 - return pageURL("ws", server, r.httpPath);
215.158 - }
215.159 -
215.160 - private URI registerResource(Resource r) {
215.161 - if (!resources.contains(r)) {
215.162 - resources.add(r);
215.163 - conf.addHttpHandler(this, r.httpPath);
215.164 - }
215.165 - return pageURL("http", server, r.httpPath);
215.166 - }
215.167 -
215.168 - private static URI pageURL(String proto, HttpServer server, final String page) {
215.169 - NetworkListener listener = server.getListeners().iterator().next();
215.170 - int port = listener.getPort();
215.171 - try {
215.172 - return new URI(proto + "://localhost:" + port + page);
215.173 - } catch (URISyntaxException ex) {
215.174 - throw new IllegalStateException(ex);
215.175 - }
215.176 - }
215.177 -
215.178 - static final class Resource {
215.179 -
215.180 - final InputStream httpContent;
215.181 - final String httpType;
215.182 - final String httpPath;
215.183 - final String[] parameters;
215.184 -
215.185 - Resource(InputStream httpContent, String httpType, String httpPath,
215.186 - String[] parameters) {
215.187 - httpContent.mark(Integer.MAX_VALUE);
215.188 - this.httpContent = httpContent;
215.189 - this.httpType = httpType;
215.190 - this.httpPath = httpPath;
215.191 - this.parameters = parameters;
215.192 - }
215.193 - }
215.194 -
215.195 - static void copyStream(InputStream is, OutputStream os, String baseURL, String... params) throws IOException {
215.196 - for (;;) {
215.197 - int ch = is.read();
215.198 - if (ch == -1) {
215.199 - break;
215.200 - }
215.201 - if (ch == '$' && params.length > 0) {
215.202 - int cnt = is.read() - '0';
215.203 - if (baseURL != null && cnt == 'U' - '0') {
215.204 - os.write(baseURL.getBytes("UTF-8"));
215.205 - } else {
215.206 - if (cnt >= 0 && cnt < params.length) {
215.207 - os.write(params[cnt].getBytes("UTF-8"));
215.208 - } else {
215.209 - os.write('$');
215.210 - os.write(cnt + '0');
215.211 - }
215.212 - }
215.213 - } else {
215.214 - os.write(ch);
215.215 - }
215.216 - }
215.217 - }
215.218 -
215.219 - private static class WS extends WebSocketApplication {
215.220 - private final Resource r;
215.221 -
215.222 - private WS(Resource r) {
215.223 - this.r = r;
215.224 - }
215.225 -
215.226 - @Override
215.227 - public void onMessage(WebSocket socket, String text) {
215.228 - try {
215.229 - r.httpContent.reset();
215.230 - ByteArrayOutputStream out = new ByteArrayOutputStream();
215.231 - copyStream(r.httpContent, out, null, text);
215.232 - String s = new String(out.toByteArray(), "UTF-8");
215.233 - socket.send(s);
215.234 - } catch (IOException ex) {
215.235 - LOG.log(Level.WARNING, null, ex);
215.236 - }
215.237 - }
215.238 - private static final Logger LOG = Logger.getLogger(WS.class.getName());
215.239 -
215.240 - }
215.241 -}
216.1 --- a/ko-ws-tyrus/src/test/java/org/apidesign/html/wstyrus/TyrusFX.java Thu Dec 19 17:11:01 2013 +0100
216.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
216.3 @@ -1,98 +0,0 @@
216.4 -/**
216.5 - * HTML via Java(tm) Language Bindings
216.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
216.7 - *
216.8 - * This program is free software: you can redistribute it and/or modify
216.9 - * it under the terms of the GNU General Public License as published by
216.10 - * the Free Software Foundation, version 2 of the License.
216.11 - *
216.12 - * This program is distributed in the hope that it will be useful,
216.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
216.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
216.15 - * GNU General Public License for more details. apidesign.org
216.16 - * designates this particular file as subject to the
216.17 - * "Classpath" exception as provided by apidesign.org
216.18 - * in the License file that accompanied this code.
216.19 - *
216.20 - * You should have received a copy of the GNU General Public License
216.21 - * along with this program. Look for COPYING file in the top folder.
216.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
216.23 - */
216.24 -package org.apidesign.html.wstyrus;
216.25 -
216.26 -import java.lang.reflect.InvocationTargetException;
216.27 -import java.lang.reflect.Method;
216.28 -import javafx.application.Platform;
216.29 -import org.apidesign.html.boot.impl.FnContext;
216.30 -import org.apidesign.html.boot.spi.Fn;
216.31 -import org.testng.ITest;
216.32 -import org.testng.annotations.Test;
216.33 -
216.34 -/**
216.35 - *
216.36 - * @author Jaroslav Tulach <jtulach@netbeans.org>
216.37 - */
216.38 -public final class TyrusFX implements ITest, Runnable {
216.39 - private final Fn.Presenter p;
216.40 - private final Method m;
216.41 - private Object result;
216.42 - private Object inst;
216.43 - private int count;
216.44 -
216.45 - TyrusFX(Fn.Presenter p, Method m) {
216.46 - this.p = p;
216.47 - this.m = m;
216.48 - }
216.49 -
216.50 - @Override
216.51 - public String getTestName() {
216.52 - return m.getName();
216.53 - }
216.54 -
216.55 - @Test
216.56 - public synchronized void executeTest() throws Exception {
216.57 - if (result == null) {
216.58 - Platform.runLater(this);
216.59 - wait();
216.60 - }
216.61 - if (result instanceof Exception) {
216.62 - throw (Exception)result;
216.63 - }
216.64 - if (result instanceof Error) {
216.65 - throw (Error)result;
216.66 - }
216.67 - }
216.68 -
216.69 - @Override
216.70 - public synchronized void run() {
216.71 - boolean notify = true;
216.72 - try {
216.73 - FnContext.currentPresenter(p);
216.74 - if (inst == null) {
216.75 - inst = m.getDeclaringClass().newInstance();
216.76 - }
216.77 - result = m.invoke(inst);
216.78 - if (result == null) {
216.79 - result = this;
216.80 - }
216.81 - } catch (InvocationTargetException ex) {
216.82 - Throwable r = ex.getTargetException();
216.83 - if (r instanceof InterruptedException) {
216.84 - if (count++ < 10000) {
216.85 - notify = false;
216.86 - Platform.runLater(this);
216.87 - return;
216.88 - }
216.89 - }
216.90 - result = r;
216.91 - } catch (Exception ex) {
216.92 - result = ex;
216.93 - } finally {
216.94 - if (notify) {
216.95 - notifyAll();
216.96 - }
216.97 - FnContext.currentPresenter(null);
216.98 - }
216.99 - }
216.100 -
216.101 -}
217.1 --- a/ko-ws-tyrus/src/test/java/org/apidesign/html/wstyrus/TyrusKnockoutTest.java Thu Dec 19 17:11:01 2013 +0100
217.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
217.3 @@ -1,191 +0,0 @@
217.4 -/**
217.5 - * HTML via Java(tm) Language Bindings
217.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
217.7 - *
217.8 - * This program is free software: you can redistribute it and/or modify
217.9 - * it under the terms of the GNU General Public License as published by
217.10 - * the Free Software Foundation, version 2 of the License.
217.11 - *
217.12 - * This program is distributed in the hope that it will be useful,
217.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
217.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
217.15 - * GNU General Public License for more details. apidesign.org
217.16 - * designates this particular file as subject to the
217.17 - * "Classpath" exception as provided by apidesign.org
217.18 - * in the License file that accompanied this code.
217.19 - *
217.20 - * You should have received a copy of the GNU General Public License
217.21 - * along with this program. Look for COPYING file in the top folder.
217.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
217.23 - */
217.24 -package org.apidesign.html.wstyrus;
217.25 -
217.26 -import java.io.BufferedReader;
217.27 -import java.io.IOException;
217.28 -import java.io.InputStreamReader;
217.29 -import java.lang.annotation.Annotation;
217.30 -import java.lang.reflect.Method;
217.31 -import java.net.URI;
217.32 -import java.net.URISyntaxException;
217.33 -import java.net.URL;
217.34 -import java.net.URLConnection;
217.35 -import java.util.ArrayList;
217.36 -import java.util.List;
217.37 -import java.util.Map;
217.38 -import java.util.concurrent.Executors;
217.39 -import net.java.html.BrwsrCtx;
217.40 -import net.java.html.boot.BrowserBuilder;
217.41 -import net.java.html.js.JavaScriptBody;
217.42 -import org.apidesign.html.boot.impl.FnContext;
217.43 -import org.apidesign.html.boot.impl.FnUtils;
217.44 -import org.apidesign.html.boot.spi.Fn;
217.45 -import org.apidesign.html.context.spi.Contexts;
217.46 -import org.apidesign.html.json.spi.Technology;
217.47 -import org.apidesign.html.json.spi.Transfer;
217.48 -import org.apidesign.html.json.spi.WSTransfer;
217.49 -import org.apidesign.html.json.tck.KOTest;
217.50 -import org.apidesign.html.json.tck.KnockoutTCK;
217.51 -import org.apidesign.html.kofx.FXContext;
217.52 -import org.json.JSONException;
217.53 -import org.json.JSONObject;
217.54 -import org.openide.util.lookup.ServiceProvider;
217.55 -import org.testng.annotations.Factory;
217.56 -import static org.testng.Assert.*;
217.57 -
217.58 -/**
217.59 - *
217.60 - * @author Jaroslav Tulach <jtulach@netbeans.org>
217.61 - */
217.62 -@ServiceProvider(service = KnockoutTCK.class)
217.63 -public final class TyrusKnockoutTest extends KnockoutTCK {
217.64 - private static Class<?> browserClass;
217.65 - private static Fn.Presenter browserContext;
217.66 -
217.67 - public TyrusKnockoutTest() {
217.68 - }
217.69 -
217.70 - @Factory public static Object[] compatibilityTests() throws Exception {
217.71 - Class[] arr = testClasses();
217.72 - for (int i = 0; i < arr.length; i++) {
217.73 - assertEquals(
217.74 - arr[i].getClassLoader(),
217.75 - TyrusKnockoutTest.class.getClassLoader(),
217.76 - "All classes loaded by the same classloader"
217.77 - );
217.78 - }
217.79 -
217.80 - URI uri = TyrusDynamicHTTP.initServer();
217.81 -
217.82 - final BrowserBuilder bb = BrowserBuilder.newBrowser().loadClass(TyrusKnockoutTest.class).
217.83 - loadPage(uri.toString()).
217.84 - invoke("initialized");
217.85 -
217.86 - Executors.newSingleThreadExecutor().submit(new Runnable() {
217.87 - @Override
217.88 - public void run() {
217.89 - bb.showAndWait();
217.90 - }
217.91 - });
217.92 -
217.93 - ClassLoader l = getClassLoader();
217.94 - List<Object> res = new ArrayList<Object>();
217.95 - for (int i = 0; i < arr.length; i++) {
217.96 - Class<?> c = Class.forName(arr[i].getName(), true, l);
217.97 - Class<? extends Annotation> koTest =
217.98 - c.getClassLoader().loadClass(KOTest.class.getName()).
217.99 - asSubclass(Annotation.class);
217.100 - for (Method m : c.getMethods()) {
217.101 - if (m.getAnnotation(koTest) != null) {
217.102 - res.add(new TyrusFX(browserContext, m));
217.103 - }
217.104 - }
217.105 - }
217.106 - return res.toArray();
217.107 - }
217.108 -
217.109 - static synchronized ClassLoader getClassLoader() throws InterruptedException {
217.110 - while (browserClass == null) {
217.111 - TyrusKnockoutTest.class.wait();
217.112 - }
217.113 - return browserClass.getClassLoader();
217.114 - }
217.115 -
217.116 - public static synchronized void initialized(Class<?> browserCls) throws Exception {
217.117 - browserClass = browserCls;
217.118 - browserContext = Fn.activePresenter();
217.119 - TyrusKnockoutTest.class.notifyAll();
217.120 - }
217.121 -
217.122 - public static void initialized() throws Exception {
217.123 - Class<?> classpathClass = ClassLoader.getSystemClassLoader().loadClass(TyrusKnockoutTest.class.getName());
217.124 - Method m = classpathClass.getMethod("initialized", Class.class);
217.125 - m.invoke(null, TyrusKnockoutTest.class);
217.126 - browserContext = Fn.activePresenter();
217.127 - }
217.128 -
217.129 - @Override
217.130 - public BrwsrCtx createContext() {
217.131 - FXContext fx = new FXContext(browserContext);
217.132 - TyrusContext tc = new TyrusContext();
217.133 - Contexts.Builder cb = Contexts.newBuilder().
217.134 - register(Technology.class, fx, 10).
217.135 - register(Transfer.class, fx, 10).
217.136 - register(WSTransfer.class, tc, 10);
217.137 - return cb.build();
217.138 - }
217.139 -
217.140 - @Override
217.141 - public Object createJSON(Map<String, Object> values) {
217.142 - JSONObject json = new JSONObject();
217.143 - for (Map.Entry<String, Object> entry : values.entrySet()) {
217.144 - try {
217.145 - json.put(entry.getKey(), entry.getValue());
217.146 - } catch (JSONException ex) {
217.147 - throw new IllegalStateException(ex);
217.148 - }
217.149 - }
217.150 - return json;
217.151 - }
217.152 -
217.153 - @Override
217.154 - @JavaScriptBody(args = { "s", "args" }, body = ""
217.155 - + "var f = new Function(s); "
217.156 - + "return f.apply(null, args);"
217.157 - )
217.158 - public native Object executeScript(String script, Object[] arguments);
217.159 -
217.160 - @JavaScriptBody(args = { }, body =
217.161 - "var h;"
217.162 - + "if (!!window && !!window.location && !!window.location.href)\n"
217.163 - + " h = window.location.href;\n"
217.164 - + "else "
217.165 - + " h = null;"
217.166 - + "return h;\n"
217.167 - )
217.168 - private static native String findBaseURL();
217.169 -
217.170 - @Override
217.171 - public URI prepareURL(String content, String mimeType, String[] parameters) {
217.172 - try {
217.173 - final URL baseURL = new URL(findBaseURL());
217.174 - StringBuilder sb = new StringBuilder();
217.175 - sb.append("/dynamic?mimeType=").append(mimeType);
217.176 - for (int i = 0; i < parameters.length; i++) {
217.177 - sb.append("¶m" + i).append("=").append(parameters[i]);
217.178 - }
217.179 - String mangle = content.replace("\n", "%0a")
217.180 - .replace("\"", "\\\"").replace(" ", "%20");
217.181 - sb.append("&content=").append(mangle);
217.182 -
217.183 - URL query = new URL(baseURL, sb.toString());
217.184 - URLConnection c = query.openConnection();
217.185 - BufferedReader br = new BufferedReader(new InputStreamReader(c.getInputStream()));
217.186 - URI connectTo = new URI(br.readLine());
217.187 - return connectTo;
217.188 - } catch (IOException ex) {
217.189 - throw new IllegalStateException(ex);
217.190 - } catch (URISyntaxException ex) {
217.191 - throw new IllegalStateException(ex);
217.192 - }
217.193 - }
217.194 -}
218.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
218.2 +++ b/ko-ws-tyrus/src/test/java/org/netbeans/html/wstyrus/TyrusDynamicHTTP.java Tue Jan 07 08:21:57 2014 +0100
218.3 @@ -0,0 +1,260 @@
218.4 +/**
218.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
218.6 + *
218.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
218.8 + *
218.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
218.10 + * Other names may be trademarks of their respective owners.
218.11 + *
218.12 + * The contents of this file are subject to the terms of either the GNU
218.13 + * General Public License Version 2 only ("GPL") or the Common
218.14 + * Development and Distribution License("CDDL") (collectively, the
218.15 + * "License"). You may not use this file except in compliance with the
218.16 + * License. You can obtain a copy of the License at
218.17 + * http://www.netbeans.org/cddl-gplv2.html
218.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
218.19 + * specific language governing permissions and limitations under the
218.20 + * License. When distributing the software, include this License Header
218.21 + * Notice in each file and include the License file at
218.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
218.23 + * particular file as subject to the "Classpath" exception as provided
218.24 + * by Oracle in the GPL Version 2 section of the License file that
218.25 + * accompanied this code. If applicable, add the following below the
218.26 + * License Header, with the fields enclosed by brackets [] replaced by
218.27 + * your own identifying information:
218.28 + * "Portions Copyrighted [year] [name of copyright owner]"
218.29 + *
218.30 + * Contributor(s):
218.31 + *
218.32 + * The Original Software is NetBeans. The Initial Developer of the Original
218.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
218.34 + *
218.35 + * If you wish your version of this file to be governed by only the CDDL
218.36 + * or only the GPL Version 2, indicate your decision by adding
218.37 + * "[Contributor] elects to include this software in this distribution
218.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
218.39 + * single choice of license, a recipient has the option to distribute
218.40 + * your version of this file under either the CDDL, the GPL Version 2 or
218.41 + * to extend the choice of license to its licensees as provided above.
218.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
218.43 + * Version 2 license, then the option applies only if the new code is
218.44 + * made subject to such option by the copyright holder.
218.45 + */
218.46 +package org.netbeans.html.wstyrus;
218.47 +
218.48 +import java.io.ByteArrayInputStream;
218.49 +import java.io.ByteArrayOutputStream;
218.50 +import java.io.IOException;
218.51 +import java.io.InputStream;
218.52 +import java.io.OutputStream;
218.53 +import java.io.Reader;
218.54 +import java.net.URI;
218.55 +import java.net.URISyntaxException;
218.56 +import java.util.ArrayList;
218.57 +import java.util.List;
218.58 +import java.util.logging.Level;
218.59 +import java.util.logging.Logger;
218.60 +import org.glassfish.grizzly.PortRange;
218.61 +import org.glassfish.grizzly.http.server.HttpHandler;
218.62 +import org.glassfish.grizzly.http.server.HttpServer;
218.63 +import org.glassfish.grizzly.http.server.NetworkListener;
218.64 +import org.glassfish.grizzly.http.server.Request;
218.65 +import org.glassfish.grizzly.http.server.Response;
218.66 +import org.glassfish.grizzly.http.server.ServerConfiguration;
218.67 +import org.glassfish.grizzly.websockets.WebSocket;
218.68 +import org.glassfish.grizzly.websockets.WebSocketAddOn;
218.69 +import org.glassfish.grizzly.websockets.WebSocketApplication;
218.70 +import org.glassfish.grizzly.websockets.WebSocketEngine;
218.71 +
218.72 +/**
218.73 + *
218.74 + * @author Jaroslav Tulach <jtulach@netbeans.org>
218.75 + */
218.76 +final class TyrusDynamicHTTP extends HttpHandler {
218.77 + private static int resourcesCount;
218.78 + private static List<Resource> resources;
218.79 + private static ServerConfiguration conf;
218.80 + private static HttpServer server;
218.81 +
218.82 + private TyrusDynamicHTTP() {
218.83 + }
218.84 +
218.85 + static URI initServer() throws Exception {
218.86 + server = HttpServer.createSimpleServer(null, new PortRange(8080, 65535));
218.87 + final WebSocketAddOn addon = new WebSocketAddOn();
218.88 + for (NetworkListener listener : server.getListeners()) {
218.89 + listener.registerAddOn(addon);
218.90 + }
218.91 + resources = new ArrayList<Resource>();
218.92 +
218.93 + conf = server.getServerConfiguration();
218.94 + final TyrusDynamicHTTP dh = new TyrusDynamicHTTP();
218.95 +
218.96 + conf.addHttpHandler(dh, "/");
218.97 +
218.98 + server.start();
218.99 +
218.100 + return pageURL("http", server, "/test.html");
218.101 + }
218.102 +
218.103 + @Override
218.104 + public void service(Request request, Response response) throws Exception {
218.105 + if ("/test.html".equals(request.getRequestURI())) {
218.106 + response.setContentType("text/html");
218.107 + final InputStream is = TyrusDynamicHTTP.class.getResourceAsStream("test.html");
218.108 + copyStream(is, response.getOutputStream(), null);
218.109 + return;
218.110 + }
218.111 + if ("/dynamic".equals(request.getRequestURI())) {
218.112 + String mimeType = request.getParameter("mimeType");
218.113 + List<String> params = new ArrayList<String>();
218.114 + boolean webSocket = false;
218.115 + for (int i = 0;; i++) {
218.116 + String p = request.getParameter("param" + i);
218.117 + if (p == null) {
218.118 + break;
218.119 + }
218.120 + if ("protocol:ws".equals(p)) {
218.121 + webSocket = true;
218.122 + continue;
218.123 + }
218.124 + params.add(p);
218.125 + }
218.126 + final String cnt = request.getParameter("content");
218.127 + String mangle = cnt.replace("%20", " ").replace("%0A", "\n");
218.128 + ByteArrayInputStream is = new ByteArrayInputStream(mangle.getBytes("UTF-8"));
218.129 + URI url;
218.130 + final Resource res = new Resource(is, mimeType, "/dynamic/res" + ++resourcesCount, params.toArray(new String[params.size()]));
218.131 + if (webSocket) {
218.132 + url = registerWebSocket(res);
218.133 + } else {
218.134 + url = registerResource(res);
218.135 + }
218.136 + response.getWriter().write(url.toString());
218.137 + response.getWriter().write("\n");
218.138 + return;
218.139 + }
218.140 +
218.141 + for (Resource r : resources) {
218.142 + if (r.httpPath.equals(request.getRequestURI())) {
218.143 + response.setContentType(r.httpType);
218.144 + r.httpContent.reset();
218.145 + String[] params = null;
218.146 + if (r.parameters.length != 0) {
218.147 + params = new String[r.parameters.length];
218.148 + for (int i = 0; i < r.parameters.length; i++) {
218.149 + params[i] = request.getParameter(r.parameters[i]);
218.150 + if (params[i] == null) {
218.151 + if ("http.method".equals(r.parameters[i])) {
218.152 + params[i] = request.getMethod().toString();
218.153 + } else if ("http.requestBody".equals(r.parameters[i])) {
218.154 + Reader rdr = request.getReader();
218.155 + StringBuilder sb = new StringBuilder();
218.156 + for (;;) {
218.157 + int ch = rdr.read();
218.158 + if (ch == -1) {
218.159 + break;
218.160 + }
218.161 + sb.append((char) ch);
218.162 + }
218.163 + params[i] = sb.toString();
218.164 + }
218.165 + }
218.166 + if (params[i] == null) {
218.167 + params[i] = "null";
218.168 + }
218.169 + }
218.170 + }
218.171 +
218.172 + copyStream(r.httpContent, response.getOutputStream(), null, params);
218.173 + }
218.174 + }
218.175 + }
218.176 +
218.177 + private URI registerWebSocket(Resource r) {
218.178 + WebSocketEngine.getEngine().register("", r.httpPath, new WS(r));
218.179 + return pageURL("ws", server, r.httpPath);
218.180 + }
218.181 +
218.182 + private URI registerResource(Resource r) {
218.183 + if (!resources.contains(r)) {
218.184 + resources.add(r);
218.185 + conf.addHttpHandler(this, r.httpPath);
218.186 + }
218.187 + return pageURL("http", server, r.httpPath);
218.188 + }
218.189 +
218.190 + private static URI pageURL(String proto, HttpServer server, final String page) {
218.191 + NetworkListener listener = server.getListeners().iterator().next();
218.192 + int port = listener.getPort();
218.193 + try {
218.194 + return new URI(proto + "://localhost:" + port + page);
218.195 + } catch (URISyntaxException ex) {
218.196 + throw new IllegalStateException(ex);
218.197 + }
218.198 + }
218.199 +
218.200 + static final class Resource {
218.201 +
218.202 + final InputStream httpContent;
218.203 + final String httpType;
218.204 + final String httpPath;
218.205 + final String[] parameters;
218.206 +
218.207 + Resource(InputStream httpContent, String httpType, String httpPath,
218.208 + String[] parameters) {
218.209 + httpContent.mark(Integer.MAX_VALUE);
218.210 + this.httpContent = httpContent;
218.211 + this.httpType = httpType;
218.212 + this.httpPath = httpPath;
218.213 + this.parameters = parameters;
218.214 + }
218.215 + }
218.216 +
218.217 + static void copyStream(InputStream is, OutputStream os, String baseURL, String... params) throws IOException {
218.218 + for (;;) {
218.219 + int ch = is.read();
218.220 + if (ch == -1) {
218.221 + break;
218.222 + }
218.223 + if (ch == '$' && params.length > 0) {
218.224 + int cnt = is.read() - '0';
218.225 + if (baseURL != null && cnt == 'U' - '0') {
218.226 + os.write(baseURL.getBytes("UTF-8"));
218.227 + } else {
218.228 + if (cnt >= 0 && cnt < params.length) {
218.229 + os.write(params[cnt].getBytes("UTF-8"));
218.230 + } else {
218.231 + os.write('$');
218.232 + os.write(cnt + '0');
218.233 + }
218.234 + }
218.235 + } else {
218.236 + os.write(ch);
218.237 + }
218.238 + }
218.239 + }
218.240 +
218.241 + private static class WS extends WebSocketApplication {
218.242 + private final Resource r;
218.243 +
218.244 + private WS(Resource r) {
218.245 + this.r = r;
218.246 + }
218.247 +
218.248 + @Override
218.249 + public void onMessage(WebSocket socket, String text) {
218.250 + try {
218.251 + r.httpContent.reset();
218.252 + ByteArrayOutputStream out = new ByteArrayOutputStream();
218.253 + copyStream(r.httpContent, out, null, text);
218.254 + String s = new String(out.toByteArray(), "UTF-8");
218.255 + socket.send(s);
218.256 + } catch (IOException ex) {
218.257 + LOG.log(Level.WARNING, null, ex);
218.258 + }
218.259 + }
218.260 + private static final Logger LOG = Logger.getLogger(WS.class.getName());
218.261 +
218.262 + }
218.263 +}
219.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
219.2 +++ b/ko-ws-tyrus/src/test/java/org/netbeans/html/wstyrus/TyrusFX.java Tue Jan 07 08:21:57 2014 +0100
219.3 @@ -0,0 +1,120 @@
219.4 +/**
219.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
219.6 + *
219.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
219.8 + *
219.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
219.10 + * Other names may be trademarks of their respective owners.
219.11 + *
219.12 + * The contents of this file are subject to the terms of either the GNU
219.13 + * General Public License Version 2 only ("GPL") or the Common
219.14 + * Development and Distribution License("CDDL") (collectively, the
219.15 + * "License"). You may not use this file except in compliance with the
219.16 + * License. You can obtain a copy of the License at
219.17 + * http://www.netbeans.org/cddl-gplv2.html
219.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
219.19 + * specific language governing permissions and limitations under the
219.20 + * License. When distributing the software, include this License Header
219.21 + * Notice in each file and include the License file at
219.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
219.23 + * particular file as subject to the "Classpath" exception as provided
219.24 + * by Oracle in the GPL Version 2 section of the License file that
219.25 + * accompanied this code. If applicable, add the following below the
219.26 + * License Header, with the fields enclosed by brackets [] replaced by
219.27 + * your own identifying information:
219.28 + * "Portions Copyrighted [year] [name of copyright owner]"
219.29 + *
219.30 + * Contributor(s):
219.31 + *
219.32 + * The Original Software is NetBeans. The Initial Developer of the Original
219.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
219.34 + *
219.35 + * If you wish your version of this file to be governed by only the CDDL
219.36 + * or only the GPL Version 2, indicate your decision by adding
219.37 + * "[Contributor] elects to include this software in this distribution
219.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
219.39 + * single choice of license, a recipient has the option to distribute
219.40 + * your version of this file under either the CDDL, the GPL Version 2 or
219.41 + * to extend the choice of license to its licensees as provided above.
219.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
219.43 + * Version 2 license, then the option applies only if the new code is
219.44 + * made subject to such option by the copyright holder.
219.45 + */
219.46 +package org.netbeans.html.wstyrus;
219.47 +
219.48 +import java.lang.reflect.InvocationTargetException;
219.49 +import java.lang.reflect.Method;
219.50 +import javafx.application.Platform;
219.51 +import org.netbeans.html.boot.impl.FnContext;
219.52 +import org.apidesign.html.boot.spi.Fn;
219.53 +import org.testng.ITest;
219.54 +import org.testng.annotations.Test;
219.55 +
219.56 +/**
219.57 + *
219.58 + * @author Jaroslav Tulach <jtulach@netbeans.org>
219.59 + */
219.60 +public final class TyrusFX implements ITest, Runnable {
219.61 + private final Fn.Presenter p;
219.62 + private final Method m;
219.63 + private Object result;
219.64 + private Object inst;
219.65 + private int count;
219.66 +
219.67 + TyrusFX(Fn.Presenter p, Method m) {
219.68 + this.p = p;
219.69 + this.m = m;
219.70 + }
219.71 +
219.72 + @Override
219.73 + public String getTestName() {
219.74 + return m.getName();
219.75 + }
219.76 +
219.77 + @Test
219.78 + public synchronized void executeTest() throws Exception {
219.79 + if (result == null) {
219.80 + Platform.runLater(this);
219.81 + wait();
219.82 + }
219.83 + if (result instanceof Exception) {
219.84 + throw (Exception)result;
219.85 + }
219.86 + if (result instanceof Error) {
219.87 + throw (Error)result;
219.88 + }
219.89 + }
219.90 +
219.91 + @Override
219.92 + public synchronized void run() {
219.93 + boolean notify = true;
219.94 + try {
219.95 + FnContext.currentPresenter(p);
219.96 + if (inst == null) {
219.97 + inst = m.getDeclaringClass().newInstance();
219.98 + }
219.99 + result = m.invoke(inst);
219.100 + if (result == null) {
219.101 + result = this;
219.102 + }
219.103 + } catch (InvocationTargetException ex) {
219.104 + Throwable r = ex.getTargetException();
219.105 + if (r instanceof InterruptedException) {
219.106 + if (count++ < 10000) {
219.107 + notify = false;
219.108 + Platform.runLater(this);
219.109 + return;
219.110 + }
219.111 + }
219.112 + result = r;
219.113 + } catch (Exception ex) {
219.114 + result = ex;
219.115 + } finally {
219.116 + if (notify) {
219.117 + notifyAll();
219.118 + }
219.119 + FnContext.currentPresenter(null);
219.120 + }
219.121 + }
219.122 +
219.123 +}
220.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
220.2 +++ b/ko-ws-tyrus/src/test/java/org/netbeans/html/wstyrus/TyrusKnockoutTest.java Tue Jan 07 08:21:57 2014 +0100
220.3 @@ -0,0 +1,212 @@
220.4 +/**
220.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
220.6 + *
220.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
220.8 + *
220.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
220.10 + * Other names may be trademarks of their respective owners.
220.11 + *
220.12 + * The contents of this file are subject to the terms of either the GNU
220.13 + * General Public License Version 2 only ("GPL") or the Common
220.14 + * Development and Distribution License("CDDL") (collectively, the
220.15 + * "License"). You may not use this file except in compliance with the
220.16 + * License. You can obtain a copy of the License at
220.17 + * http://www.netbeans.org/cddl-gplv2.html
220.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
220.19 + * specific language governing permissions and limitations under the
220.20 + * License. When distributing the software, include this License Header
220.21 + * Notice in each file and include the License file at
220.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
220.23 + * particular file as subject to the "Classpath" exception as provided
220.24 + * by Oracle in the GPL Version 2 section of the License file that
220.25 + * accompanied this code. If applicable, add the following below the
220.26 + * License Header, with the fields enclosed by brackets [] replaced by
220.27 + * your own identifying information:
220.28 + * "Portions Copyrighted [year] [name of copyright owner]"
220.29 + *
220.30 + * Contributor(s):
220.31 + *
220.32 + * The Original Software is NetBeans. The Initial Developer of the Original
220.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
220.34 + *
220.35 + * If you wish your version of this file to be governed by only the CDDL
220.36 + * or only the GPL Version 2, indicate your decision by adding
220.37 + * "[Contributor] elects to include this software in this distribution
220.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
220.39 + * single choice of license, a recipient has the option to distribute
220.40 + * your version of this file under either the CDDL, the GPL Version 2 or
220.41 + * to extend the choice of license to its licensees as provided above.
220.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
220.43 + * Version 2 license, then the option applies only if the new code is
220.44 + * made subject to such option by the copyright holder.
220.45 + */
220.46 +package org.netbeans.html.wstyrus;
220.47 +
220.48 +import java.io.BufferedReader;
220.49 +import java.io.IOException;
220.50 +import java.io.InputStreamReader;
220.51 +import java.lang.annotation.Annotation;
220.52 +import java.lang.reflect.Method;
220.53 +import java.net.URI;
220.54 +import java.net.URISyntaxException;
220.55 +import java.net.URL;
220.56 +import java.net.URLConnection;
220.57 +import java.util.ArrayList;
220.58 +import java.util.List;
220.59 +import java.util.Map;
220.60 +import java.util.concurrent.Executors;
220.61 +import net.java.html.BrwsrCtx;
220.62 +import net.java.html.boot.BrowserBuilder;
220.63 +import net.java.html.js.JavaScriptBody;
220.64 +import org.netbeans.html.boot.impl.FnContext;
220.65 +import org.apidesign.html.boot.spi.Fn;
220.66 +import org.apidesign.html.context.spi.Contexts;
220.67 +import org.apidesign.html.json.spi.Technology;
220.68 +import org.apidesign.html.json.spi.Transfer;
220.69 +import org.apidesign.html.json.spi.WSTransfer;
220.70 +import org.apidesign.html.json.tck.KOTest;
220.71 +import org.apidesign.html.json.tck.KnockoutTCK;
220.72 +import org.json.JSONException;
220.73 +import org.json.JSONObject;
220.74 +import org.netbeans.html.kofx.FXContext;
220.75 +import org.openide.util.lookup.ServiceProvider;
220.76 +import org.testng.annotations.Factory;
220.77 +import static org.testng.Assert.*;
220.78 +
220.79 +/**
220.80 + *
220.81 + * @author Jaroslav Tulach <jtulach@netbeans.org>
220.82 + */
220.83 +@ServiceProvider(service = KnockoutTCK.class)
220.84 +public final class TyrusKnockoutTest extends KnockoutTCK {
220.85 + private static Class<?> browserClass;
220.86 + private static Fn.Presenter browserContext;
220.87 +
220.88 + public TyrusKnockoutTest() {
220.89 + }
220.90 +
220.91 + @Factory public static Object[] compatibilityTests() throws Exception {
220.92 + Class[] arr = testClasses();
220.93 + for (int i = 0; i < arr.length; i++) {
220.94 + assertEquals(
220.95 + arr[i].getClassLoader(),
220.96 + TyrusKnockoutTest.class.getClassLoader(),
220.97 + "All classes loaded by the same classloader"
220.98 + );
220.99 + }
220.100 +
220.101 + URI uri = TyrusDynamicHTTP.initServer();
220.102 +
220.103 + final BrowserBuilder bb = BrowserBuilder.newBrowser().loadClass(TyrusKnockoutTest.class).
220.104 + loadPage(uri.toString()).
220.105 + invoke("initialized");
220.106 +
220.107 + Executors.newSingleThreadExecutor().submit(new Runnable() {
220.108 + @Override
220.109 + public void run() {
220.110 + bb.showAndWait();
220.111 + }
220.112 + });
220.113 +
220.114 + ClassLoader l = getClassLoader();
220.115 + List<Object> res = new ArrayList<Object>();
220.116 + for (int i = 0; i < arr.length; i++) {
220.117 + Class<?> c = Class.forName(arr[i].getName(), true, l);
220.118 + Class<? extends Annotation> koTest =
220.119 + c.getClassLoader().loadClass(KOTest.class.getName()).
220.120 + asSubclass(Annotation.class);
220.121 + for (Method m : c.getMethods()) {
220.122 + if (m.getAnnotation(koTest) != null) {
220.123 + res.add(new TyrusFX(browserContext, m));
220.124 + }
220.125 + }
220.126 + }
220.127 + return res.toArray();
220.128 + }
220.129 +
220.130 + static synchronized ClassLoader getClassLoader() throws InterruptedException {
220.131 + while (browserClass == null) {
220.132 + TyrusKnockoutTest.class.wait();
220.133 + }
220.134 + return browserClass.getClassLoader();
220.135 + }
220.136 +
220.137 + public static synchronized void initialized(Class<?> browserCls) throws Exception {
220.138 + browserClass = browserCls;
220.139 + browserContext = Fn.activePresenter();
220.140 + TyrusKnockoutTest.class.notifyAll();
220.141 + }
220.142 +
220.143 + public static void initialized() throws Exception {
220.144 + Class<?> classpathClass = ClassLoader.getSystemClassLoader().loadClass(TyrusKnockoutTest.class.getName());
220.145 + Method m = classpathClass.getMethod("initialized", Class.class);
220.146 + m.invoke(null, TyrusKnockoutTest.class);
220.147 + browserContext = Fn.activePresenter();
220.148 + }
220.149 +
220.150 + @Override
220.151 + public BrwsrCtx createContext() {
220.152 + FXContext fx = new FXContext(browserContext);
220.153 + TyrusContext tc = new TyrusContext();
220.154 + Contexts.Builder cb = Contexts.newBuilder().
220.155 + register(Technology.class, fx, 10).
220.156 + register(Transfer.class, fx, 10).
220.157 + register(WSTransfer.class, tc, 10);
220.158 + return cb.build();
220.159 + }
220.160 +
220.161 + @Override
220.162 + public Object createJSON(Map<String, Object> values) {
220.163 + JSONObject json = new JSONObject();
220.164 + for (Map.Entry<String, Object> entry : values.entrySet()) {
220.165 + try {
220.166 + json.put(entry.getKey(), entry.getValue());
220.167 + } catch (JSONException ex) {
220.168 + throw new IllegalStateException(ex);
220.169 + }
220.170 + }
220.171 + return json;
220.172 + }
220.173 +
220.174 + @Override
220.175 + @JavaScriptBody(args = { "s", "args" }, body = ""
220.176 + + "var f = new Function(s); "
220.177 + + "return f.apply(null, args);"
220.178 + )
220.179 + public native Object executeScript(String script, Object[] arguments);
220.180 +
220.181 + @JavaScriptBody(args = { }, body =
220.182 + "var h;"
220.183 + + "if (!!window && !!window.location && !!window.location.href)\n"
220.184 + + " h = window.location.href;\n"
220.185 + + "else "
220.186 + + " h = null;"
220.187 + + "return h;\n"
220.188 + )
220.189 + private static native String findBaseURL();
220.190 +
220.191 + @Override
220.192 + public URI prepareURL(String content, String mimeType, String[] parameters) {
220.193 + try {
220.194 + final URL baseURL = new URL(findBaseURL());
220.195 + StringBuilder sb = new StringBuilder();
220.196 + sb.append("/dynamic?mimeType=").append(mimeType);
220.197 + for (int i = 0; i < parameters.length; i++) {
220.198 + sb.append("¶m" + i).append("=").append(parameters[i]);
220.199 + }
220.200 + String mangle = content.replace("\n", "%0a")
220.201 + .replace("\"", "\\\"").replace(" ", "%20");
220.202 + sb.append("&content=").append(mangle);
220.203 +
220.204 + URL query = new URL(baseURL, sb.toString());
220.205 + URLConnection c = query.openConnection();
220.206 + BufferedReader br = new BufferedReader(new InputStreamReader(c.getInputStream()));
220.207 + URI connectTo = new URI(br.readLine());
220.208 + return connectTo;
220.209 + } catch (IOException ex) {
220.210 + throw new IllegalStateException(ex);
220.211 + } catch (URISyntaxException ex) {
220.212 + throw new IllegalStateException(ex);
220.213 + }
220.214 + }
220.215 +}
221.1 --- a/ko-ws-tyrus/src/test/resources/org/apidesign/html/wstyrus/test.html Thu Dec 19 17:11:01 2013 +0100
221.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
221.3 @@ -1,34 +0,0 @@
221.4 -<!--
221.5 -
221.6 - HTML via Java(tm) Language Bindings
221.7 - Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
221.8 -
221.9 - This program is free software: you can redistribute it and/or modify
221.10 - it under the terms of the GNU General Public License as published by
221.11 - the Free Software Foundation, version 2 of the License.
221.12 -
221.13 - This program is distributed in the hope that it will be useful,
221.14 - but WITHOUT ANY WARRANTY; without even the implied warranty of
221.15 - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
221.16 - GNU General Public License for more details. apidesign.org
221.17 - designates this particular file as subject to the
221.18 - "Classpath" exception as provided by apidesign.org
221.19 - in the License file that accompanied this code.
221.20 -
221.21 - You should have received a copy of the GNU General Public License
221.22 - along with this program. Look for COPYING file in the top folder.
221.23 - If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
221.24 -
221.25 --->
221.26 -<!DOCTYPE html>
221.27 -<html>
221.28 - <head>
221.29 - <title>Tyrus WebSockets Execution Harness</title>
221.30 - <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
221.31 - <meta name="viewport" content="width=device-width">
221.32 - </head>
221.33 - <body>
221.34 - <h1>Tyrus WebSockets Execution Harness</h1>
221.35 - </body>
221.36 - <script></script>
221.37 -</html>
222.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
222.2 +++ b/ko-ws-tyrus/src/test/resources/org/netbeans/html/wstyrus/test.html Tue Jan 07 08:21:57 2014 +0100
222.3 @@ -0,0 +1,56 @@
222.4 +<!--
222.5 +
222.6 + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
222.7 +
222.8 + Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
222.9 +
222.10 + Oracle and Java are registered trademarks of Oracle and/or its affiliates.
222.11 + Other names may be trademarks of their respective owners.
222.12 +
222.13 + The contents of this file are subject to the terms of either the GNU
222.14 + General Public License Version 2 only ("GPL") or the Common
222.15 + Development and Distribution License("CDDL") (collectively, the
222.16 + "License"). You may not use this file except in compliance with the
222.17 + License. You can obtain a copy of the License at
222.18 + http://www.netbeans.org/cddl-gplv2.html
222.19 + or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
222.20 + specific language governing permissions and limitations under the
222.21 + License. When distributing the software, include this License Header
222.22 + Notice in each file and include the License file at
222.23 + nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
222.24 + particular file as subject to the "Classpath" exception as provided
222.25 + by Oracle in the GPL Version 2 section of the License file that
222.26 + accompanied this code. If applicable, add the following below the
222.27 + License Header, with the fields enclosed by brackets [] replaced by
222.28 + your own identifying information:
222.29 + "Portions Copyrighted [year] [name of copyright owner]"
222.30 +
222.31 + Contributor(s):
222.32 +
222.33 + The Original Software is NetBeans. The Initial Developer of the Original
222.34 + Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
222.35 +
222.36 + If you wish your version of this file to be governed by only the CDDL
222.37 + or only the GPL Version 2, indicate your decision by adding
222.38 + "[Contributor] elects to include this software in this distribution
222.39 + under the [CDDL or GPL Version 2] license." If you do not indicate a
222.40 + single choice of license, a recipient has the option to distribute
222.41 + your version of this file under either the CDDL, the GPL Version 2 or
222.42 + to extend the choice of license to its licensees as provided above.
222.43 + However, if you add GPL Version 2 code and therefore, elected the GPL
222.44 + Version 2 license, then the option applies only if the new code is
222.45 + made subject to such option by the copyright holder.
222.46 +
222.47 +-->
222.48 +<!DOCTYPE html>
222.49 +<html>
222.50 + <head>
222.51 + <title>Tyrus WebSockets Execution Harness</title>
222.52 + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
222.53 + <meta name="viewport" content="width=device-width">
222.54 + </head>
222.55 + <body>
222.56 + <h1>Tyrus WebSockets Execution Harness</h1>
222.57 + </body>
222.58 + <script></script>
222.59 +</html>
223.1 --- a/pom.xml Thu Dec 19 17:11:01 2013 +0100
223.2 +++ b/pom.xml Tue Jan 07 08:21:57 2014 +0100
223.3 @@ -1,8 +1,8 @@
223.4 <?xml version="1.0" encoding="UTF-8"?>
223.5 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
223.6 <modelVersion>4.0.0</modelVersion>
223.7 - <groupId>org.apidesign</groupId>
223.8 - <artifactId>html</artifactId>
223.9 + <groupId>org.netbeans.html</groupId>
223.10 + <artifactId>pom</artifactId>
223.11 <version>0.7-SNAPSHOT</version>
223.12 <packaging>pom</packaging>
223.13 <name>HTML APIs via Java</name>
223.14 @@ -16,6 +16,7 @@
223.15 <netbeans.version>RELEASE73</netbeans.version>
223.16 <license>COPYING</license>
223.17 <publicPackages></publicPackages>
223.18 + <bundleSymbolicName>${project.artifactId}</bundleSymbolicName>
223.19 </properties>
223.20 <modules>
223.21 <module>json</module>
223.22 @@ -30,17 +31,19 @@
223.23 <module>geo</module>
223.24 <module>ko-ws-tyrus</module>
223.25 <module>html4j-maven-plugin</module>
223.26 + <module>ko-osgi-test</module>
223.27 + <module>equinox-agentclass-hook</module>
223.28 </modules>
223.29 <licenses>
223.30 <license>
223.31 - <name>GPL-2.0wCPexc</name>
223.32 - <url>http://opensource.org/licenses/GPL-2.0</url>
223.33 + <name>GPL-2.0wCPexc+CDDL</name>
223.34 + <url>http://www.netbeans.org/cddl-gplv2.html</url>
223.35 <distribution>repo</distribution>
223.36 </license>
223.37 </licenses>
223.38 <organization>
223.39 - <name>API Design</name>
223.40 - <url>http://apidesign.org</url>
223.41 + <name>NetBeans</name>
223.42 + <url>http://netbeans.org</url>
223.43 </organization>
223.44 <scm>
223.45 <connection>scm:hg:https://hg.apidesign.org/hg/html~html4j</connection>
223.46 @@ -92,7 +95,7 @@
223.47 <exclude>*</exclude>
223.48 <exclude>.*/**</exclude>
223.49 <exclude>ko-archetype/src/main/resources/**</exclude>
223.50 - <exclude>ko-fx/src/main/resources/org/apidesign/html/kofx/knockout*.js</exclude>
223.51 + <exclude>ko-fx/src/main/resources/org/netbeans/html/kofx/knockout*.js</exclude>
223.52 </excludes>
223.53 </configuration>
223.54 </plugin>
223.55 @@ -140,7 +143,7 @@
223.56 <configuration>
223.57 <instructions>
223.58 <Export-Package>${publicPackages},META-INF.services.*</Export-Package>
223.59 - <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
223.60 + <Bundle-SymbolicName>${bundleSymbolicName}</Bundle-SymbolicName>
223.61 </instructions>
223.62 </configuration>
223.63 </plugin>
224.1 --- a/sound/pom.xml Thu Dec 19 17:11:01 2013 +0100
224.2 +++ b/sound/pom.xml Tue Jan 07 08:21:57 2014 +0100
224.3 @@ -2,11 +2,11 @@
224.4 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
224.5 <modelVersion>4.0.0</modelVersion>
224.6 <parent>
224.7 - <groupId>org.apidesign</groupId>
224.8 - <artifactId>html</artifactId>
224.9 + <groupId>org.netbeans.html</groupId>
224.10 + <artifactId>pom</artifactId>
224.11 <version>0.7-SNAPSHOT</version>
224.12 </parent>
224.13 - <groupId>org.apidesign.html</groupId>
224.14 + <groupId>org.netbeans.html</groupId>
224.15 <artifactId>net.java.html.sound</artifactId>
224.16 <version>0.7-SNAPSHOT</version>
224.17 <packaging>bundle</packaging>
224.18 @@ -31,7 +31,7 @@
224.19 <scope>test</scope>
224.20 </dependency>
224.21 <dependency>
224.22 - <groupId>org.apidesign.html</groupId>
224.23 + <groupId>org.netbeans.html</groupId>
224.24 <artifactId>net.java.html.boot</artifactId>
224.25 <version>0.7-SNAPSHOT</version>
224.26 <type>jar</type>
225.1 --- a/sound/src/main/java/net/java/html/sound/AudioClip.java Thu Dec 19 17:11:01 2013 +0100
225.2 +++ b/sound/src/main/java/net/java/html/sound/AudioClip.java Tue Jan 07 08:21:57 2014 +0100
225.3 @@ -1,22 +1,44 @@
225.4 /**
225.5 - * HTML via Java(tm) Language Bindings
225.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
225.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
225.8 *
225.9 - * This program is free software: you can redistribute it and/or modify
225.10 - * it under the terms of the GNU General Public License as published by
225.11 - * the Free Software Foundation, version 2 of the License.
225.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
225.13 *
225.14 - * This program is distributed in the hope that it will be useful,
225.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
225.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
225.17 - * GNU General Public License for more details. apidesign.org
225.18 - * designates this particular file as subject to the
225.19 - * "Classpath" exception as provided by apidesign.org
225.20 - * in the License file that accompanied this code.
225.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
225.22 + * Other names may be trademarks of their respective owners.
225.23 *
225.24 - * You should have received a copy of the GNU General Public License
225.25 - * along with this program. Look for COPYING file in the top folder.
225.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
225.27 + * The contents of this file are subject to the terms of either the GNU
225.28 + * General Public License Version 2 only ("GPL") or the Common
225.29 + * Development and Distribution License("CDDL") (collectively, the
225.30 + * "License"). You may not use this file except in compliance with the
225.31 + * License. You can obtain a copy of the License at
225.32 + * http://www.netbeans.org/cddl-gplv2.html
225.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
225.34 + * specific language governing permissions and limitations under the
225.35 + * License. When distributing the software, include this License Header
225.36 + * Notice in each file and include the License file at
225.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
225.38 + * particular file as subject to the "Classpath" exception as provided
225.39 + * by Oracle in the GPL Version 2 section of the License file that
225.40 + * accompanied this code. If applicable, add the following below the
225.41 + * License Header, with the fields enclosed by brackets [] replaced by
225.42 + * your own identifying information:
225.43 + * "Portions Copyrighted [year] [name of copyright owner]"
225.44 + *
225.45 + * Contributor(s):
225.46 + *
225.47 + * The Original Software is NetBeans. The Initial Developer of the Original
225.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
225.49 + *
225.50 + * If you wish your version of this file to be governed by only the CDDL
225.51 + * or only the GPL Version 2, indicate your decision by adding
225.52 + * "[Contributor] elects to include this software in this distribution
225.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
225.54 + * single choice of license, a recipient has the option to distribute
225.55 + * your version of this file under either the CDDL, the GPL Version 2 or
225.56 + * to extend the choice of license to its licensees as provided above.
225.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
225.58 + * Version 2 license, then the option applies only if the new code is
225.59 + * made subject to such option by the copyright holder.
225.60 */
225.61 package net.java.html.sound;
225.62
226.1 --- a/sound/src/main/java/org/apidesign/html/sound/impl/BrowserAudioEnv.java Thu Dec 19 17:11:01 2013 +0100
226.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
226.3 @@ -1,59 +0,0 @@
226.4 -/**
226.5 - * HTML via Java(tm) Language Bindings
226.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
226.7 - *
226.8 - * This program is free software: you can redistribute it and/or modify
226.9 - * it under the terms of the GNU General Public License as published by
226.10 - * the Free Software Foundation, version 2 of the License.
226.11 - *
226.12 - * This program is distributed in the hope that it will be useful,
226.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
226.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
226.15 - * GNU General Public License for more details. apidesign.org
226.16 - * designates this particular file as subject to the
226.17 - * "Classpath" exception as provided by apidesign.org
226.18 - * in the License file that accompanied this code.
226.19 - *
226.20 - * You should have received a copy of the GNU General Public License
226.21 - * along with this program. Look for COPYING file in the top folder.
226.22 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
226.23 - */
226.24 -package org.apidesign.html.sound.impl;
226.25 -
226.26 -import net.java.html.js.JavaScriptBody;
226.27 -import org.apidesign.html.sound.spi.AudioEnvironment;
226.28 -import org.openide.util.lookup.ServiceProvider;
226.29 -
226.30 -/** Registers an audio provider that delegates to HTML5 Audio tag.
226.31 - *
226.32 - * @author Jaroslav Tulach <jtulach@netbeans.org>
226.33 - */
226.34 -@ServiceProvider(service = AudioEnvironment.class, position = 100)
226.35 -public final class BrowserAudioEnv implements AudioEnvironment<Object> {
226.36 - @Override
226.37 - @JavaScriptBody(args = { "src" }, body = ""
226.38 - + "if (!Audio) return null;"
226.39 - + "return new Audio(src);")
226.40 - public Object create(String src) {
226.41 - // null if not running in browser
226.42 - return null;
226.43 - }
226.44 -
226.45 - @Override @JavaScriptBody(args = { "a" }, body = "a.play();")
226.46 - public void play(Object a) {
226.47 - }
226.48 -
226.49 - @Override @JavaScriptBody(args = { "a" }, body = "a.pause();")
226.50 - public void pause(Object a) {
226.51 - }
226.52 -
226.53 - @Override @JavaScriptBody(args = { "a", "volume" }, body = "a.setVolume(volume);")
226.54 - public void setVolume(Object a, double volume) {
226.55 - }
226.56 -
226.57 - @Override
226.58 - @JavaScriptBody(args = "a", body = "return true;")
226.59 - public boolean isSupported(Object a) {
226.60 - return false;
226.61 - }
226.62 -}
227.1 --- a/sound/src/main/java/org/apidesign/html/sound/spi/AudioEnvironment.java Thu Dec 19 17:11:01 2013 +0100
227.2 +++ b/sound/src/main/java/org/apidesign/html/sound/spi/AudioEnvironment.java Tue Jan 07 08:21:57 2014 +0100
227.3 @@ -1,22 +1,44 @@
227.4 /**
227.5 - * HTML via Java(tm) Language Bindings
227.6 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
227.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
227.8 *
227.9 - * This program is free software: you can redistribute it and/or modify
227.10 - * it under the terms of the GNU General Public License as published by
227.11 - * the Free Software Foundation, version 2 of the License.
227.12 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
227.13 *
227.14 - * This program is distributed in the hope that it will be useful,
227.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
227.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
227.17 - * GNU General Public License for more details. apidesign.org
227.18 - * designates this particular file as subject to the
227.19 - * "Classpath" exception as provided by apidesign.org
227.20 - * in the License file that accompanied this code.
227.21 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
227.22 + * Other names may be trademarks of their respective owners.
227.23 *
227.24 - * You should have received a copy of the GNU General Public License
227.25 - * along with this program. Look for COPYING file in the top folder.
227.26 - * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
227.27 + * The contents of this file are subject to the terms of either the GNU
227.28 + * General Public License Version 2 only ("GPL") or the Common
227.29 + * Development and Distribution License("CDDL") (collectively, the
227.30 + * "License"). You may not use this file except in compliance with the
227.31 + * License. You can obtain a copy of the License at
227.32 + * http://www.netbeans.org/cddl-gplv2.html
227.33 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
227.34 + * specific language governing permissions and limitations under the
227.35 + * License. When distributing the software, include this License Header
227.36 + * Notice in each file and include the License file at
227.37 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
227.38 + * particular file as subject to the "Classpath" exception as provided
227.39 + * by Oracle in the GPL Version 2 section of the License file that
227.40 + * accompanied this code. If applicable, add the following below the
227.41 + * License Header, with the fields enclosed by brackets [] replaced by
227.42 + * your own identifying information:
227.43 + * "Portions Copyrighted [year] [name of copyright owner]"
227.44 + *
227.45 + * Contributor(s):
227.46 + *
227.47 + * The Original Software is NetBeans. The Initial Developer of the Original
227.48 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
227.49 + *
227.50 + * If you wish your version of this file to be governed by only the CDDL
227.51 + * or only the GPL Version 2, indicate your decision by adding
227.52 + * "[Contributor] elects to include this software in this distribution
227.53 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
227.54 + * single choice of license, a recipient has the option to distribute
227.55 + * your version of this file under either the CDDL, the GPL Version 2 or
227.56 + * to extend the choice of license to its licensees as provided above.
227.57 + * However, if you add GPL Version 2 code and therefore, elected the GPL
227.58 + * Version 2 license, then the option applies only if the new code is
227.59 + * made subject to such option by the copyright holder.
227.60 */
227.61 package org.apidesign.html.sound.spi;
227.62
228.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
228.2 +++ b/sound/src/main/java/org/netbeans/html/sound/impl/BrowserAudioEnv.java Tue Jan 07 08:21:57 2014 +0100
228.3 @@ -0,0 +1,81 @@
228.4 +/**
228.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
228.6 + *
228.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
228.8 + *
228.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
228.10 + * Other names may be trademarks of their respective owners.
228.11 + *
228.12 + * The contents of this file are subject to the terms of either the GNU
228.13 + * General Public License Version 2 only ("GPL") or the Common
228.14 + * Development and Distribution License("CDDL") (collectively, the
228.15 + * "License"). You may not use this file except in compliance with the
228.16 + * License. You can obtain a copy of the License at
228.17 + * http://www.netbeans.org/cddl-gplv2.html
228.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
228.19 + * specific language governing permissions and limitations under the
228.20 + * License. When distributing the software, include this License Header
228.21 + * Notice in each file and include the License file at
228.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
228.23 + * particular file as subject to the "Classpath" exception as provided
228.24 + * by Oracle in the GPL Version 2 section of the License file that
228.25 + * accompanied this code. If applicable, add the following below the
228.26 + * License Header, with the fields enclosed by brackets [] replaced by
228.27 + * your own identifying information:
228.28 + * "Portions Copyrighted [year] [name of copyright owner]"
228.29 + *
228.30 + * Contributor(s):
228.31 + *
228.32 + * The Original Software is NetBeans. The Initial Developer of the Original
228.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
228.34 + *
228.35 + * If you wish your version of this file to be governed by only the CDDL
228.36 + * or only the GPL Version 2, indicate your decision by adding
228.37 + * "[Contributor] elects to include this software in this distribution
228.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
228.39 + * single choice of license, a recipient has the option to distribute
228.40 + * your version of this file under either the CDDL, the GPL Version 2 or
228.41 + * to extend the choice of license to its licensees as provided above.
228.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
228.43 + * Version 2 license, then the option applies only if the new code is
228.44 + * made subject to such option by the copyright holder.
228.45 + */
228.46 +package org.netbeans.html.sound.impl;
228.47 +
228.48 +import net.java.html.js.JavaScriptBody;
228.49 +import org.apidesign.html.sound.spi.AudioEnvironment;
228.50 +import org.openide.util.lookup.ServiceProvider;
228.51 +
228.52 +/** Registers an audio provider that delegates to HTML5 Audio tag.
228.53 + *
228.54 + * @author Jaroslav Tulach <jtulach@netbeans.org>
228.55 + */
228.56 +@ServiceProvider(service = AudioEnvironment.class, position = 100)
228.57 +public final class BrowserAudioEnv implements AudioEnvironment<Object> {
228.58 + @Override
228.59 + @JavaScriptBody(args = { "src" }, body = ""
228.60 + + "if (!Audio) return null;"
228.61 + + "return new Audio(src);")
228.62 + public Object create(String src) {
228.63 + // null if not running in browser
228.64 + return null;
228.65 + }
228.66 +
228.67 + @Override @JavaScriptBody(args = { "a" }, body = "a.play();")
228.68 + public void play(Object a) {
228.69 + }
228.70 +
228.71 + @Override @JavaScriptBody(args = { "a" }, body = "a.pause();")
228.72 + public void pause(Object a) {
228.73 + }
228.74 +
228.75 + @Override @JavaScriptBody(args = { "a", "volume" }, body = "a.setVolume(volume);")
228.76 + public void setVolume(Object a, double volume) {
228.77 + }
228.78 +
228.79 + @Override
228.80 + @JavaScriptBody(args = "a", body = "return true;")
228.81 + public boolean isSupported(Object a) {
228.82 + return false;
228.83 + }
228.84 +}