1.1 --- a/boot-fx/src/main/java/net/java/html/boot/fx/FXBrowsers.java Mon Dec 16 15:48:09 2013 +0100
1.2 +++ b/boot-fx/src/main/java/net/java/html/boot/fx/FXBrowsers.java Mon Dec 16 16:59:43 2013 +0100
1.3 @@ -49,7 +49,7 @@
1.4 import javafx.scene.web.WebView;
1.5 import net.java.html.boot.BrowserBuilder;
1.6 import net.java.html.js.JavaScriptBody;
1.7 -import org.apidesign.html.boot.fx.AbstractFXPresenter;
1.8 +import org.netbeans.html.boot.fx.AbstractFXPresenter;
1.9
1.10 /** Utility methods for working with <em>JavaFX</em> <code>WebView</code>s.
1.11 *
2.1 --- a/boot-fx/src/main/java/org/apidesign/html/boot/fx/AbstractFXPresenter.java Mon Dec 16 15:48:09 2013 +0100
2.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2.3 @@ -1,190 +0,0 @@
2.4 -/**
2.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
2.6 - *
2.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
2.8 - *
2.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
2.10 - * Other names may be trademarks of their respective owners.
2.11 - *
2.12 - * The contents of this file are subject to the terms of either the GNU
2.13 - * General Public License Version 2 only ("GPL") or the Common
2.14 - * Development and Distribution License("CDDL") (collectively, the
2.15 - * "License"). You may not use this file except in compliance with the
2.16 - * License. You can obtain a copy of the License at
2.17 - * http://www.netbeans.org/cddl-gplv2.html
2.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
2.19 - * specific language governing permissions and limitations under the
2.20 - * License. When distributing the software, include this License Header
2.21 - * Notice in each file and include the License file at
2.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
2.23 - * particular file as subject to the "Classpath" exception as provided
2.24 - * by Oracle in the GPL Version 2 section of the License file that
2.25 - * accompanied this code. If applicable, add the following below the
2.26 - * License Header, with the fields enclosed by brackets [] replaced by
2.27 - * your own identifying information:
2.28 - * "Portions Copyrighted [year] [name of copyright owner]"
2.29 - *
2.30 - * Contributor(s):
2.31 - *
2.32 - * The Original Software is NetBeans. The Initial Developer of the Original
2.33 - * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
2.34 - *
2.35 - * If you wish your version of this file to be governed by only the CDDL
2.36 - * or only the GPL Version 2, indicate your decision by adding
2.37 - * "[Contributor] elects to include this software in this distribution
2.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
2.39 - * single choice of license, a recipient has the option to distribute
2.40 - * your version of this file under either the CDDL, the GPL Version 2 or
2.41 - * to extend the choice of license to its licensees as provided above.
2.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
2.43 - * Version 2 license, then the option applies only if the new code is
2.44 - * made subject to such option by the copyright holder.
2.45 - */
2.46 -package org.apidesign.html.boot.fx;
2.47 -
2.48 -import java.io.BufferedReader;
2.49 -import java.io.Reader;
2.50 -import java.net.URL;
2.51 -import java.util.ArrayList;
2.52 -import java.util.Arrays;
2.53 -import java.util.List;
2.54 -import java.util.logging.Level;
2.55 -import java.util.logging.Logger;
2.56 -import javafx.application.Platform;
2.57 -import javafx.scene.web.WebEngine;
2.58 -import javafx.scene.web.WebView;
2.59 -import netscape.javascript.JSObject;
2.60 -import org.apidesign.html.boot.spi.Fn;
2.61 -
2.62 -/**
2.63 - *
2.64 - * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
2.65 - */
2.66 -public abstract class AbstractFXPresenter implements Fn.Presenter {
2.67 - static final Logger LOG = Logger.getLogger(FXPresenter.class.getName());
2.68 - protected static int cnt;
2.69 - protected List<String> scripts;
2.70 - protected Runnable onLoad;
2.71 - protected WebEngine engine;
2.72 -
2.73 - @Override
2.74 - public Fn defineFn(String code, String... names) {
2.75 - StringBuilder sb = new StringBuilder();
2.76 - sb.append("(function() {");
2.77 - sb.append(" return function(");
2.78 - String sep = "";
2.79 - for (String n : names) {
2.80 - sb.append(sep).append(n);
2.81 - sep = ",";
2.82 - }
2.83 - sb.append(") {\n");
2.84 - sb.append(code);
2.85 - sb.append("};");
2.86 - sb.append("})()");
2.87 - if (LOG.isLoggable(Level.FINE)) {
2.88 - LOG.log(Level.FINE,
2.89 - "defining function #{0}:\n{1}\n",
2.90 - new Object[] { ++cnt, code }
2.91 - );
2.92 - }
2.93 - JSObject x = (JSObject) engine.executeScript(sb.toString());
2.94 - return new JSFn(this, x, cnt);
2.95 - }
2.96 -
2.97 - @Override
2.98 - public void loadScript(Reader code) throws Exception {
2.99 - BufferedReader r = new BufferedReader(code);
2.100 - StringBuilder sb = new StringBuilder();
2.101 - for (;;) {
2.102 - String l = r.readLine();
2.103 - if (l == null) {
2.104 - break;
2.105 - }
2.106 - sb.append(l).append('\n');
2.107 - }
2.108 - final String script = sb.toString();
2.109 - if (scripts != null) {
2.110 - scripts.add(script);
2.111 - }
2.112 - engine.executeScript(script);
2.113 - }
2.114 -
2.115 - protected final void onPageLoad() {
2.116 - if (scripts != null) {
2.117 - for (String s : scripts) {
2.118 - engine.executeScript(s);
2.119 - }
2.120 - }
2.121 - onLoad.run();
2.122 - }
2.123 -
2.124 - @Override
2.125 - public void displayPage(final URL resource, final Runnable onLoad) {
2.126 - this.onLoad = onLoad;
2.127 - final WebView view = findView(resource);
2.128 - this.engine = view.getEngine();
2.129 - try {
2.130 - if (FXInspect.initialize(engine)) {
2.131 - scripts = new ArrayList<String>();
2.132 - }
2.133 - } catch (Throwable ex) {
2.134 - ex.printStackTrace();
2.135 - }
2.136 -
2.137 - class Run implements Runnable {
2.138 -
2.139 - @Override
2.140 - public void run() {
2.141 - if (scripts != null) {
2.142 - view.setContextMenuEnabled(true);
2.143 - }
2.144 - engine.load(resource.toExternalForm());
2.145 - }
2.146 - }
2.147 - Run run = new Run();
2.148 - if (Platform.isFxApplicationThread()) {
2.149 - run.run();
2.150 - } else {
2.151 - Platform.runLater(run);
2.152 - }
2.153 - waitFinished();
2.154 - }
2.155 -
2.156 - protected abstract void waitFinished();
2.157 -
2.158 - protected abstract WebView findView(final URL resource);
2.159 -
2.160 - private static final class JSFn extends Fn {
2.161 -
2.162 - private final JSObject fn;
2.163 - private static int call;
2.164 - private final int id;
2.165 -
2.166 - public JSFn(AbstractFXPresenter p, JSObject fn, int id) {
2.167 - super(p);
2.168 - this.fn = fn;
2.169 - this.id = id;
2.170 - }
2.171 -
2.172 - @Override
2.173 - public Object invoke(Object thiz, Object... args) throws Exception {
2.174 - try {
2.175 - if (LOG.isLoggable(Level.FINE)) {
2.176 - LOG.log(Level.FINE, "calling {0} function #{1}", new Object[]{++call, id});
2.177 - }
2.178 - List<Object> all = new ArrayList<Object>(args.length + 1);
2.179 - all.add(thiz == null ? fn : thiz);
2.180 - all.addAll(Arrays.asList(args));
2.181 - Object ret = fn.call("call", all.toArray()); // NOI18N
2.182 - return ret == fn ? null : ret;
2.183 - } catch (Error t) {
2.184 - t.printStackTrace();
2.185 - throw t;
2.186 - } catch (Exception t) {
2.187 - t.printStackTrace();
2.188 - throw t;
2.189 - }
2.190 - }
2.191 - }
2.192 -
2.193 -}
3.1 --- a/boot-fx/src/main/java/org/apidesign/html/boot/fx/Dbgr.java Mon Dec 16 15:48:09 2013 +0100
3.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
3.3 @@ -1,87 +0,0 @@
3.4 -/**
3.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3.6 - *
3.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
3.8 - *
3.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
3.10 - * Other names may be trademarks of their respective owners.
3.11 - *
3.12 - * The contents of this file are subject to the terms of either the GNU
3.13 - * General Public License Version 2 only ("GPL") or the Common
3.14 - * Development and Distribution License("CDDL") (collectively, the
3.15 - * "License"). You may not use this file except in compliance with the
3.16 - * License. You can obtain a copy of the License at
3.17 - * http://www.netbeans.org/cddl-gplv2.html
3.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
3.19 - * specific language governing permissions and limitations under the
3.20 - * License. When distributing the software, include this License Header
3.21 - * Notice in each file and include the License file at
3.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
3.23 - * particular file as subject to the "Classpath" exception as provided
3.24 - * by Oracle in the GPL Version 2 section of the License file that
3.25 - * accompanied this code. If applicable, add the following below the
3.26 - * License Header, with the fields enclosed by brackets [] replaced by
3.27 - * your own identifying information:
3.28 - * "Portions Copyrighted [year] [name of copyright owner]"
3.29 - *
3.30 - * Contributor(s):
3.31 - *
3.32 - * The Original Software is NetBeans. The Initial Developer of the Original
3.33 - * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
3.34 - *
3.35 - * If you wish your version of this file to be governed by only the CDDL
3.36 - * or only the GPL Version 2, indicate your decision by adding
3.37 - * "[Contributor] elects to include this software in this distribution
3.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
3.39 - * single choice of license, a recipient has the option to distribute
3.40 - * your version of this file under either the CDDL, the GPL Version 2 or
3.41 - * to extend the choice of license to its licensees as provided above.
3.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
3.43 - * Version 2 license, then the option applies only if the new code is
3.44 - * made subject to such option by the copyright holder.
3.45 - */
3.46 -package org.apidesign.html.boot.fx;
3.47 -
3.48 -import java.lang.reflect.Method;
3.49 -import java.util.logging.Level;
3.50 -import javafx.scene.web.WebEngine;
3.51 -import javafx.util.Callback;
3.52 -import static org.apidesign.html.boot.fx.AbstractFXPresenter.LOG;
3.53 -
3.54 -/** Debugger bridge to shield us from propriatory impl APIs.
3.55 - *
3.56 - * @author Jaroslav Tulach <jtulach@netbeans.org>
3.57 - */
3.58 -final class Dbgr {
3.59 - final Object dbg;
3.60 - final Method sendMsg;
3.61 -
3.62 - Dbgr(WebEngine eng, Callback<String,Void> callback) {
3.63 - Object d;
3.64 - Method m;
3.65 - try {
3.66 - d = eng.getClass().getMethod("impl_getDebugger").invoke(eng); // NOI18N
3.67 - Class<?> debugger = eng.getClass().getClassLoader().loadClass("com.sun.javafx.scene.web.Debugger"); // NOI18N
3.68 - debugger.getMethod("setEnabled", boolean.class).invoke(d, true); // NOI18N
3.69 - debugger.getMethod("setMessageCallback", Callback.class).invoke(d, callback); // NOI18N
3.70 - m = debugger.getMethod("sendMessage", String.class); // NOI18N
3.71 - } catch (Exception ex) {
3.72 - LOG.log(Level.INFO, null, ex);
3.73 - d = null;
3.74 - m = null;
3.75 - }
3.76 - dbg = d;
3.77 - sendMsg = m;
3.78 - }
3.79 -
3.80 - void sendMessage(String msg) {
3.81 - try {
3.82 - if (dbg != null) {
3.83 - sendMsg.invoke(dbg, msg);
3.84 - }
3.85 - } catch (Exception ex) {
3.86 - LOG.log(Level.INFO, null, ex);
3.87 - }
3.88 - }
3.89 -
3.90 -}
4.1 --- a/boot-fx/src/main/java/org/apidesign/html/boot/fx/FXBrwsr.java Mon Dec 16 15:48:09 2013 +0100
4.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
4.3 @@ -1,193 +0,0 @@
4.4 -/**
4.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4.6 - *
4.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
4.8 - *
4.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
4.10 - * Other names may be trademarks of their respective owners.
4.11 - *
4.12 - * The contents of this file are subject to the terms of either the GNU
4.13 - * General Public License Version 2 only ("GPL") or the Common
4.14 - * Development and Distribution License("CDDL") (collectively, the
4.15 - * "License"). You may not use this file except in compliance with the
4.16 - * License. You can obtain a copy of the License at
4.17 - * http://www.netbeans.org/cddl-gplv2.html
4.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
4.19 - * specific language governing permissions and limitations under the
4.20 - * License. When distributing the software, include this License Header
4.21 - * Notice in each file and include the License file at
4.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
4.23 - * particular file as subject to the "Classpath" exception as provided
4.24 - * by Oracle in the GPL Version 2 section of the License file that
4.25 - * accompanied this code. If applicable, add the following below the
4.26 - * License Header, with the fields enclosed by brackets [] replaced by
4.27 - * your own identifying information:
4.28 - * "Portions Copyrighted [year] [name of copyright owner]"
4.29 - *
4.30 - * Contributor(s):
4.31 - *
4.32 - * The Original Software is NetBeans. The Initial Developer of the Original
4.33 - * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
4.34 - *
4.35 - * If you wish your version of this file to be governed by only the CDDL
4.36 - * or only the GPL Version 2, indicate your decision by adding
4.37 - * "[Contributor] elects to include this software in this distribution
4.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
4.39 - * single choice of license, a recipient has the option to distribute
4.40 - * your version of this file under either the CDDL, the GPL Version 2 or
4.41 - * to extend the choice of license to its licensees as provided above.
4.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
4.43 - * Version 2 license, then the option applies only if the new code is
4.44 - * made subject to such option by the copyright holder.
4.45 - */
4.46 -package org.apidesign.html.boot.fx;
4.47 -
4.48 -import java.net.URL;
4.49 -import java.util.concurrent.CountDownLatch;
4.50 -import java.util.concurrent.Executors;
4.51 -import java.util.logging.Level;
4.52 -import java.util.logging.Logger;
4.53 -import javafx.application.Application;
4.54 -import javafx.application.Platform;
4.55 -import javafx.beans.value.ChangeListener;
4.56 -import javafx.beans.value.ObservableValue;
4.57 -import javafx.concurrent.Worker;
4.58 -import javafx.event.ActionEvent;
4.59 -import javafx.event.EventHandler;
4.60 -import javafx.geometry.Insets;
4.61 -import javafx.geometry.Pos;
4.62 -import javafx.scene.Scene;
4.63 -import javafx.scene.control.Button;
4.64 -import javafx.scene.layout.BorderPane;
4.65 -import javafx.scene.layout.VBox;
4.66 -import javafx.scene.text.Text;
4.67 -import javafx.scene.web.WebEvent;
4.68 -import javafx.scene.web.WebView;
4.69 -import javafx.stage.Modality;
4.70 -import javafx.stage.Stage;
4.71 -
4.72 -/** This is an implementation class, use {@link BrowserBuilder} API. Just
4.73 - * include this JAR on classpath and the {@link BrowserBuilder} API will find
4.74 - * this implementation automatically.
4.75 - */
4.76 -public class FXBrwsr extends Application {
4.77 - private static final Logger LOG = Logger.getLogger(FXBrwsr.class.getName());
4.78 - private static FXBrwsr INSTANCE;
4.79 - private static final CountDownLatch FINISHED = new CountDownLatch(1);
4.80 - private BorderPane root;
4.81 -
4.82 - public static synchronized WebView findWebView(final URL url, final FXPresenter onLoad) {
4.83 - if (INSTANCE == null) {
4.84 - Executors.newFixedThreadPool(1).submit(new Runnable() {
4.85 - @Override
4.86 - public void run() {
4.87 - try {
4.88 - FXBrwsr.launch(FXBrwsr.class);
4.89 - } catch (Throwable ex) {
4.90 - ex.printStackTrace();
4.91 - } finally {
4.92 - FINISHED.countDown();
4.93 - }
4.94 - }
4.95 - });
4.96 - }
4.97 - while (INSTANCE == null) {
4.98 - try {
4.99 - FXBrwsr.class.wait();
4.100 - } catch (InterruptedException ex) {
4.101 - // wait more
4.102 - }
4.103 - }
4.104 - if (!Platform.isFxApplicationThread()) {
4.105 - final WebView[] arr = {null};
4.106 - final CountDownLatch waitForResult = new CountDownLatch(1);
4.107 - Platform.runLater(new Runnable() {
4.108 - @Override
4.109 - public void run() {
4.110 - arr[0] = INSTANCE.newView(url, onLoad);
4.111 - waitForResult.countDown();
4.112 - }
4.113 - });
4.114 - for (;;) {
4.115 - try {
4.116 - waitForResult.await();
4.117 - break;
4.118 - } catch (InterruptedException ex) {
4.119 - LOG.log(Level.INFO, null, ex);
4.120 - }
4.121 - }
4.122 - return arr[0];
4.123 - } else {
4.124 - return INSTANCE.newView(url, onLoad);
4.125 - }
4.126 - }
4.127 -
4.128 - @Override
4.129 - public void start(Stage primaryStage) throws Exception {
4.130 - synchronized (FXBrwsr.class) {
4.131 - INSTANCE = this;
4.132 - FXBrwsr.class.notifyAll();
4.133 - }
4.134 - BorderPane r = new BorderPane();
4.135 - Scene scene = new Scene(r, 800, 600);
4.136 - primaryStage.setScene(scene);
4.137 - primaryStage.show();
4.138 - this.root = r;
4.139 - }
4.140 -
4.141 - private WebView newView(final URL url, final FXPresenter onLoad) {
4.142 - final WebView view = new WebView();
4.143 - view.setContextMenuEnabled(false);
4.144 - view.getEngine().setOnAlert(new EventHandler<WebEvent<String>>() {
4.145 - @Override
4.146 - public void handle(WebEvent<String> t) {
4.147 - final Stage dialogStage = new Stage();
4.148 - dialogStage.initModality(Modality.WINDOW_MODAL);
4.149 - dialogStage.setTitle("Warning");
4.150 - final Button button = new Button("Close");
4.151 - final Text text = new Text(t.getData());
4.152 - VBox box = new VBox();
4.153 - box.setAlignment(Pos.CENTER);
4.154 - box.setSpacing(10);
4.155 - box.setPadding(new Insets(10));
4.156 - box.getChildren().addAll(text, button);
4.157 - dialogStage.setScene(new Scene(box));
4.158 - button.setCancelButton(true);
4.159 - button.setOnAction(new EventHandler<ActionEvent>() {
4.160 - @Override
4.161 - public void handle(ActionEvent t) {
4.162 - dialogStage.close();
4.163 - }
4.164 - });
4.165 - dialogStage.centerOnScreen();
4.166 - dialogStage.showAndWait();
4.167 - }
4.168 - });
4.169 - root.setCenter(view);
4.170 - final Worker<Void> w = view.getEngine().getLoadWorker();
4.171 - w.stateProperty().addListener(new ChangeListener<Worker.State>() {
4.172 - @Override
4.173 - public void changed(ObservableValue<? extends Worker.State> ov, Worker.State t, Worker.State newState) {
4.174 - if (newState.equals(Worker.State.SUCCEEDED)) {
4.175 - onLoad.onPageLoad();
4.176 - }
4.177 - if (newState.equals(Worker.State.FAILED)) {
4.178 - throw new IllegalStateException("Failed to load " + url);
4.179 - }
4.180 - }
4.181 - });
4.182 - return view;
4.183 - }
4.184 -
4.185 - static void waitFinished() {
4.186 - for (;;) {
4.187 - try {
4.188 - FINISHED.await();
4.189 - break;
4.190 - } catch (InterruptedException ex) {
4.191 - LOG.log(Level.INFO, null, ex);
4.192 - }
4.193 - }
4.194 - }
4.195 -
4.196 -}
5.1 --- a/boot-fx/src/main/java/org/apidesign/html/boot/fx/FXInspect.java Mon Dec 16 15:48:09 2013 +0100
5.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
5.3 @@ -1,134 +0,0 @@
5.4 -/**
5.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
5.6 - *
5.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
5.8 - *
5.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
5.10 - * Other names may be trademarks of their respective owners.
5.11 - *
5.12 - * The contents of this file are subject to the terms of either the GNU
5.13 - * General Public License Version 2 only ("GPL") or the Common
5.14 - * Development and Distribution License("CDDL") (collectively, the
5.15 - * "License"). You may not use this file except in compliance with the
5.16 - * License. You can obtain a copy of the License at
5.17 - * http://www.netbeans.org/cddl-gplv2.html
5.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
5.19 - * specific language governing permissions and limitations under the
5.20 - * License. When distributing the software, include this License Header
5.21 - * Notice in each file and include the License file at
5.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
5.23 - * particular file as subject to the "Classpath" exception as provided
5.24 - * by Oracle in the GPL Version 2 section of the License file that
5.25 - * accompanied this code. If applicable, add the following below the
5.26 - * License Header, with the fields enclosed by brackets [] replaced by
5.27 - * your own identifying information:
5.28 - * "Portions Copyrighted [year] [name of copyright owner]"
5.29 - *
5.30 - * Contributor(s):
5.31 - *
5.32 - * The Original Software is NetBeans. The Initial Developer of the Original
5.33 - * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
5.34 - *
5.35 - * If you wish your version of this file to be governed by only the CDDL
5.36 - * or only the GPL Version 2, indicate your decision by adding
5.37 - * "[Contributor] elects to include this software in this distribution
5.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
5.39 - * single choice of license, a recipient has the option to distribute
5.40 - * your version of this file under either the CDDL, the GPL Version 2 or
5.41 - * to extend the choice of license to its licensees as provided above.
5.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
5.43 - * Version 2 license, then the option applies only if the new code is
5.44 - * made subject to such option by the copyright holder.
5.45 - */
5.46 -package org.apidesign.html.boot.fx;
5.47 -
5.48 -import java.io.IOException;
5.49 -import java.io.ObjectInputStream;
5.50 -import java.io.ObjectOutputStream;
5.51 -import java.net.InetAddress;
5.52 -import java.net.Socket;
5.53 -import java.nio.charset.StandardCharsets;
5.54 -import java.util.logging.Level;
5.55 -import java.util.logging.Logger;
5.56 -import javafx.application.Platform;
5.57 -import javafx.scene.web.WebEngine;
5.58 -import javafx.util.Callback;
5.59 -
5.60 -/**
5.61 - *
5.62 - * @author Jaroslav Tulach <jtulach@netbeans.org>
5.63 - */
5.64 -final class FXInspect implements Runnable {
5.65 - private static final Logger LOG = Logger.getLogger(FXInspect.class.getName());
5.66 -
5.67 -
5.68 - private final WebEngine engine;
5.69 - private final ObjectInputStream input;
5.70 - private Dbgr dbg;
5.71 -
5.72 - private FXInspect(WebEngine engine, int port) throws IOException {
5.73 - this.engine = engine;
5.74 -
5.75 - Socket socket = new Socket(InetAddress.getByName(null), port);
5.76 - ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
5.77 - this.input = new ObjectInputStream(socket.getInputStream());
5.78 - initializeDebugger(output);
5.79 - }
5.80 -
5.81 - static boolean initialize(WebEngine engine) {
5.82 - final int inspectPort = Integer.getInteger("netbeans.inspect.port", -1); // NOI18N
5.83 - if (inspectPort != -1) {
5.84 - try {
5.85 - FXInspect inspector = new FXInspect(engine, inspectPort);
5.86 - Thread t = new Thread(inspector, "FX<->NetBeans Inspector");
5.87 - t.start();
5.88 - return true;
5.89 - } catch (IOException ex) {
5.90 - LOG.log(Level.INFO, "Cannot connect to NetBeans IDE to port " + inspectPort, ex); // NOI18N
5.91 - }
5.92 - }
5.93 - return false;
5.94 - }
5.95 -
5.96 - private void initializeDebugger(final ObjectOutputStream output) {
5.97 - Platform.runLater(new Runnable() {
5.98 - @Override
5.99 - public void run() {
5.100 - dbg = new Dbgr(engine, new Callback<String,Void>() {
5.101 - @Override
5.102 - public Void call(String message) {
5.103 - try {
5.104 - byte[] bytes = message.getBytes(StandardCharsets.UTF_8);
5.105 - output.writeInt(bytes.length);
5.106 - output.write(bytes);
5.107 - output.flush();
5.108 - } catch (IOException ioex) {
5.109 - ioex.printStackTrace();
5.110 - }
5.111 - return null;
5.112 - }
5.113 - });
5.114 - }
5.115 - });
5.116 - }
5.117 -
5.118 - @Override
5.119 - public void run() {
5.120 - try {
5.121 - while (true) {
5.122 - int length = input.readInt();
5.123 - byte[] bytes = new byte[length];
5.124 - input.readFully(bytes);
5.125 - final String message = new String(bytes, StandardCharsets.UTF_8);
5.126 - Platform.runLater(new Runnable() {
5.127 - @Override
5.128 - public void run() {
5.129 - dbg.sendMessage(message);
5.130 - }
5.131 - });
5.132 - }
5.133 - } catch (IOException ex) {
5.134 - LOG.log(Level.WARNING, null, ex);
5.135 - }
5.136 - }
5.137 -}
6.1 --- a/boot-fx/src/main/java/org/apidesign/html/boot/fx/FXPresenter.java Mon Dec 16 15:48:09 2013 +0100
6.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
6.3 @@ -1,98 +0,0 @@
6.4 -/**
6.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
6.6 - *
6.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
6.8 - *
6.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
6.10 - * Other names may be trademarks of their respective owners.
6.11 - *
6.12 - * The contents of this file are subject to the terms of either the GNU
6.13 - * General Public License Version 2 only ("GPL") or the Common
6.14 - * Development and Distribution License("CDDL") (collectively, the
6.15 - * "License"). You may not use this file except in compliance with the
6.16 - * License. You can obtain a copy of the License at
6.17 - * http://www.netbeans.org/cddl-gplv2.html
6.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
6.19 - * specific language governing permissions and limitations under the
6.20 - * License. When distributing the software, include this License Header
6.21 - * Notice in each file and include the License file at
6.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
6.23 - * particular file as subject to the "Classpath" exception as provided
6.24 - * by Oracle in the GPL Version 2 section of the License file that
6.25 - * accompanied this code. If applicable, add the following below the
6.26 - * License Header, with the fields enclosed by brackets [] replaced by
6.27 - * your own identifying information:
6.28 - * "Portions Copyrighted [year] [name of copyright owner]"
6.29 - *
6.30 - * Contributor(s):
6.31 - *
6.32 - * The Original Software is NetBeans. The Initial Developer of the Original
6.33 - * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
6.34 - *
6.35 - * If you wish your version of this file to be governed by only the CDDL
6.36 - * or only the GPL Version 2, indicate your decision by adding
6.37 - * "[Contributor] elects to include this software in this distribution
6.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
6.39 - * single choice of license, a recipient has the option to distribute
6.40 - * your version of this file under either the CDDL, the GPL Version 2 or
6.41 - * to extend the choice of license to its licensees as provided above.
6.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
6.43 - * Version 2 license, then the option applies only if the new code is
6.44 - * made subject to such option by the copyright holder.
6.45 - */
6.46 -package org.apidesign.html.boot.fx;
6.47 -
6.48 -import java.io.BufferedReader;
6.49 -import java.io.File;
6.50 -import java.io.Reader;
6.51 -import java.lang.reflect.Method;
6.52 -import java.net.URL;
6.53 -import java.net.URLClassLoader;
6.54 -import java.util.ArrayList;
6.55 -import java.util.Arrays;
6.56 -import java.util.List;
6.57 -import java.util.logging.Level;
6.58 -import java.util.logging.Logger;
6.59 -import javafx.application.Platform;
6.60 -import javafx.scene.web.WebEngine;
6.61 -import javafx.scene.web.WebView;
6.62 -import net.java.html.boot.BrowserBuilder;
6.63 -import netscape.javascript.JSObject;
6.64 -import org.apidesign.html.boot.spi.Fn;
6.65 -import org.openide.util.lookup.ServiceProvider;
6.66 -
6.67 -/** This is an implementation class, use {@link BrowserBuilder} API. Just
6.68 - * include this JAR on classpath and the {@link BrowserBuilder} API will find
6.69 - * this implementation automatically.
6.70 - *
6.71 - * @author Jaroslav Tulach <jtulach@netbeans.org>
6.72 - */
6.73 -@ServiceProvider(service = Fn.Presenter.class)
6.74 -public final class FXPresenter extends AbstractFXPresenter {
6.75 - static {
6.76 - try {
6.77 - try {
6.78 - Class<?> c = Class.forName("javafx.application.Platform");
6.79 - // OK, on classpath
6.80 - } catch (ClassNotFoundException classNotFoundException) {
6.81 - Method m = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
6.82 - m.setAccessible(true);
6.83 - File f = new File(System.getProperty("java.home"), "lib/jfxrt.jar");
6.84 - if (f.exists()) {
6.85 - URL l = f.toURI().toURL();
6.86 - m.invoke(ClassLoader.getSystemClassLoader(), l);
6.87 - }
6.88 - }
6.89 - } catch (Exception ex) {
6.90 - throw new LinkageError("Can't add jfxrt.jar on the classpath", ex);
6.91 - }
6.92 - }
6.93 -
6.94 - protected void waitFinished() {
6.95 - FXBrwsr.waitFinished();
6.96 - }
6.97 -
6.98 - protected WebView findView(final URL resource) {
6.99 - return FXBrwsr.findWebView(resource, this);
6.100 - }
6.101 -}
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/boot-fx/src/main/java/org/netbeans/html/boot/fx/AbstractFXPresenter.java Mon Dec 16 16:59:43 2013 +0100
7.3 @@ -0,0 +1,190 @@
7.4 +/**
7.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
7.6 + *
7.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
7.8 + *
7.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7.10 + * Other names may be trademarks of their respective owners.
7.11 + *
7.12 + * The contents of this file are subject to the terms of either the GNU
7.13 + * General Public License Version 2 only ("GPL") or the Common
7.14 + * Development and Distribution License("CDDL") (collectively, the
7.15 + * "License"). You may not use this file except in compliance with the
7.16 + * License. You can obtain a copy of the License at
7.17 + * http://www.netbeans.org/cddl-gplv2.html
7.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
7.19 + * specific language governing permissions and limitations under the
7.20 + * License. When distributing the software, include this License Header
7.21 + * Notice in each file and include the License file at
7.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
7.23 + * particular file as subject to the "Classpath" exception as provided
7.24 + * by Oracle in the GPL Version 2 section of the License file that
7.25 + * accompanied this code. If applicable, add the following below the
7.26 + * License Header, with the fields enclosed by brackets [] replaced by
7.27 + * your own identifying information:
7.28 + * "Portions Copyrighted [year] [name of copyright owner]"
7.29 + *
7.30 + * Contributor(s):
7.31 + *
7.32 + * The Original Software is NetBeans. The Initial Developer of the Original
7.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
7.34 + *
7.35 + * If you wish your version of this file to be governed by only the CDDL
7.36 + * or only the GPL Version 2, indicate your decision by adding
7.37 + * "[Contributor] elects to include this software in this distribution
7.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
7.39 + * single choice of license, a recipient has the option to distribute
7.40 + * your version of this file under either the CDDL, the GPL Version 2 or
7.41 + * to extend the choice of license to its licensees as provided above.
7.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
7.43 + * Version 2 license, then the option applies only if the new code is
7.44 + * made subject to such option by the copyright holder.
7.45 + */
7.46 +package org.netbeans.html.boot.fx;
7.47 +
7.48 +import java.io.BufferedReader;
7.49 +import java.io.Reader;
7.50 +import java.net.URL;
7.51 +import java.util.ArrayList;
7.52 +import java.util.Arrays;
7.53 +import java.util.List;
7.54 +import java.util.logging.Level;
7.55 +import java.util.logging.Logger;
7.56 +import javafx.application.Platform;
7.57 +import javafx.scene.web.WebEngine;
7.58 +import javafx.scene.web.WebView;
7.59 +import netscape.javascript.JSObject;
7.60 +import org.apidesign.html.boot.spi.Fn;
7.61 +
7.62 +/**
7.63 + *
7.64 + * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
7.65 + */
7.66 +public abstract class AbstractFXPresenter implements Fn.Presenter {
7.67 + static final Logger LOG = Logger.getLogger(FXPresenter.class.getName());
7.68 + protected static int cnt;
7.69 + protected List<String> scripts;
7.70 + protected Runnable onLoad;
7.71 + protected WebEngine engine;
7.72 +
7.73 + @Override
7.74 + public Fn defineFn(String code, String... names) {
7.75 + StringBuilder sb = new StringBuilder();
7.76 + sb.append("(function() {");
7.77 + sb.append(" return function(");
7.78 + String sep = "";
7.79 + for (String n : names) {
7.80 + sb.append(sep).append(n);
7.81 + sep = ",";
7.82 + }
7.83 + sb.append(") {\n");
7.84 + sb.append(code);
7.85 + sb.append("};");
7.86 + sb.append("})()");
7.87 + if (LOG.isLoggable(Level.FINE)) {
7.88 + LOG.log(Level.FINE,
7.89 + "defining function #{0}:\n{1}\n",
7.90 + new Object[] { ++cnt, code }
7.91 + );
7.92 + }
7.93 + JSObject x = (JSObject) engine.executeScript(sb.toString());
7.94 + return new JSFn(this, x, cnt);
7.95 + }
7.96 +
7.97 + @Override
7.98 + public void loadScript(Reader code) throws Exception {
7.99 + BufferedReader r = new BufferedReader(code);
7.100 + StringBuilder sb = new StringBuilder();
7.101 + for (;;) {
7.102 + String l = r.readLine();
7.103 + if (l == null) {
7.104 + break;
7.105 + }
7.106 + sb.append(l).append('\n');
7.107 + }
7.108 + final String script = sb.toString();
7.109 + if (scripts != null) {
7.110 + scripts.add(script);
7.111 + }
7.112 + engine.executeScript(script);
7.113 + }
7.114 +
7.115 + protected final void onPageLoad() {
7.116 + if (scripts != null) {
7.117 + for (String s : scripts) {
7.118 + engine.executeScript(s);
7.119 + }
7.120 + }
7.121 + onLoad.run();
7.122 + }
7.123 +
7.124 + @Override
7.125 + public void displayPage(final URL resource, final Runnable onLoad) {
7.126 + this.onLoad = onLoad;
7.127 + final WebView view = findView(resource);
7.128 + this.engine = view.getEngine();
7.129 + try {
7.130 + if (FXInspect.initialize(engine)) {
7.131 + scripts = new ArrayList<String>();
7.132 + }
7.133 + } catch (Throwable ex) {
7.134 + ex.printStackTrace();
7.135 + }
7.136 +
7.137 + class Run implements Runnable {
7.138 +
7.139 + @Override
7.140 + public void run() {
7.141 + if (scripts != null) {
7.142 + view.setContextMenuEnabled(true);
7.143 + }
7.144 + engine.load(resource.toExternalForm());
7.145 + }
7.146 + }
7.147 + Run run = new Run();
7.148 + if (Platform.isFxApplicationThread()) {
7.149 + run.run();
7.150 + } else {
7.151 + Platform.runLater(run);
7.152 + }
7.153 + waitFinished();
7.154 + }
7.155 +
7.156 + protected abstract void waitFinished();
7.157 +
7.158 + protected abstract WebView findView(final URL resource);
7.159 +
7.160 + private static final class JSFn extends Fn {
7.161 +
7.162 + private final JSObject fn;
7.163 + private static int call;
7.164 + private final int id;
7.165 +
7.166 + public JSFn(AbstractFXPresenter p, JSObject fn, int id) {
7.167 + super(p);
7.168 + this.fn = fn;
7.169 + this.id = id;
7.170 + }
7.171 +
7.172 + @Override
7.173 + public Object invoke(Object thiz, Object... args) throws Exception {
7.174 + try {
7.175 + if (LOG.isLoggable(Level.FINE)) {
7.176 + LOG.log(Level.FINE, "calling {0} function #{1}", new Object[]{++call, id});
7.177 + }
7.178 + List<Object> all = new ArrayList<Object>(args.length + 1);
7.179 + all.add(thiz == null ? fn : thiz);
7.180 + all.addAll(Arrays.asList(args));
7.181 + Object ret = fn.call("call", all.toArray()); // NOI18N
7.182 + return ret == fn ? null : ret;
7.183 + } catch (Error t) {
7.184 + t.printStackTrace();
7.185 + throw t;
7.186 + } catch (Exception t) {
7.187 + t.printStackTrace();
7.188 + throw t;
7.189 + }
7.190 + }
7.191 + }
7.192 +
7.193 +}
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
8.2 +++ b/boot-fx/src/main/java/org/netbeans/html/boot/fx/Dbgr.java Mon Dec 16 16:59:43 2013 +0100
8.3 @@ -0,0 +1,87 @@
8.4 +/**
8.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
8.6 + *
8.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
8.8 + *
8.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
8.10 + * Other names may be trademarks of their respective owners.
8.11 + *
8.12 + * The contents of this file are subject to the terms of either the GNU
8.13 + * General Public License Version 2 only ("GPL") or the Common
8.14 + * Development and Distribution License("CDDL") (collectively, the
8.15 + * "License"). You may not use this file except in compliance with the
8.16 + * License. You can obtain a copy of the License at
8.17 + * http://www.netbeans.org/cddl-gplv2.html
8.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
8.19 + * specific language governing permissions and limitations under the
8.20 + * License. When distributing the software, include this License Header
8.21 + * Notice in each file and include the License file at
8.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
8.23 + * particular file as subject to the "Classpath" exception as provided
8.24 + * by Oracle in the GPL Version 2 section of the License file that
8.25 + * accompanied this code. If applicable, add the following below the
8.26 + * License Header, with the fields enclosed by brackets [] replaced by
8.27 + * your own identifying information:
8.28 + * "Portions Copyrighted [year] [name of copyright owner]"
8.29 + *
8.30 + * Contributor(s):
8.31 + *
8.32 + * The Original Software is NetBeans. The Initial Developer of the Original
8.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
8.34 + *
8.35 + * If you wish your version of this file to be governed by only the CDDL
8.36 + * or only the GPL Version 2, indicate your decision by adding
8.37 + * "[Contributor] elects to include this software in this distribution
8.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
8.39 + * single choice of license, a recipient has the option to distribute
8.40 + * your version of this file under either the CDDL, the GPL Version 2 or
8.41 + * to extend the choice of license to its licensees as provided above.
8.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
8.43 + * Version 2 license, then the option applies only if the new code is
8.44 + * made subject to such option by the copyright holder.
8.45 + */
8.46 +package org.netbeans.html.boot.fx;
8.47 +
8.48 +import java.lang.reflect.Method;
8.49 +import java.util.logging.Level;
8.50 +import javafx.scene.web.WebEngine;
8.51 +import javafx.util.Callback;
8.52 +import static org.netbeans.html.boot.fx.AbstractFXPresenter.LOG;
8.53 +
8.54 +/** Debugger bridge to shield us from propriatory impl APIs.
8.55 + *
8.56 + * @author Jaroslav Tulach <jtulach@netbeans.org>
8.57 + */
8.58 +final class Dbgr {
8.59 + final Object dbg;
8.60 + final Method sendMsg;
8.61 +
8.62 + Dbgr(WebEngine eng, Callback<String,Void> callback) {
8.63 + Object d;
8.64 + Method m;
8.65 + try {
8.66 + d = eng.getClass().getMethod("impl_getDebugger").invoke(eng); // NOI18N
8.67 + Class<?> debugger = eng.getClass().getClassLoader().loadClass("com.sun.javafx.scene.web.Debugger"); // NOI18N
8.68 + debugger.getMethod("setEnabled", boolean.class).invoke(d, true); // NOI18N
8.69 + debugger.getMethod("setMessageCallback", Callback.class).invoke(d, callback); // NOI18N
8.70 + m = debugger.getMethod("sendMessage", String.class); // NOI18N
8.71 + } catch (Exception ex) {
8.72 + LOG.log(Level.INFO, null, ex);
8.73 + d = null;
8.74 + m = null;
8.75 + }
8.76 + dbg = d;
8.77 + sendMsg = m;
8.78 + }
8.79 +
8.80 + void sendMessage(String msg) {
8.81 + try {
8.82 + if (dbg != null) {
8.83 + sendMsg.invoke(dbg, msg);
8.84 + }
8.85 + } catch (Exception ex) {
8.86 + LOG.log(Level.INFO, null, ex);
8.87 + }
8.88 + }
8.89 +
8.90 +}
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
9.2 +++ b/boot-fx/src/main/java/org/netbeans/html/boot/fx/FXBrwsr.java Mon Dec 16 16:59:43 2013 +0100
9.3 @@ -0,0 +1,193 @@
9.4 +/**
9.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
9.6 + *
9.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
9.8 + *
9.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
9.10 + * Other names may be trademarks of their respective owners.
9.11 + *
9.12 + * The contents of this file are subject to the terms of either the GNU
9.13 + * General Public License Version 2 only ("GPL") or the Common
9.14 + * Development and Distribution License("CDDL") (collectively, the
9.15 + * "License"). You may not use this file except in compliance with the
9.16 + * License. You can obtain a copy of the License at
9.17 + * http://www.netbeans.org/cddl-gplv2.html
9.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
9.19 + * specific language governing permissions and limitations under the
9.20 + * License. When distributing the software, include this License Header
9.21 + * Notice in each file and include the License file at
9.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
9.23 + * particular file as subject to the "Classpath" exception as provided
9.24 + * by Oracle in the GPL Version 2 section of the License file that
9.25 + * accompanied this code. If applicable, add the following below the
9.26 + * License Header, with the fields enclosed by brackets [] replaced by
9.27 + * your own identifying information:
9.28 + * "Portions Copyrighted [year] [name of copyright owner]"
9.29 + *
9.30 + * Contributor(s):
9.31 + *
9.32 + * The Original Software is NetBeans. The Initial Developer of the Original
9.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
9.34 + *
9.35 + * If you wish your version of this file to be governed by only the CDDL
9.36 + * or only the GPL Version 2, indicate your decision by adding
9.37 + * "[Contributor] elects to include this software in this distribution
9.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
9.39 + * single choice of license, a recipient has the option to distribute
9.40 + * your version of this file under either the CDDL, the GPL Version 2 or
9.41 + * to extend the choice of license to its licensees as provided above.
9.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
9.43 + * Version 2 license, then the option applies only if the new code is
9.44 + * made subject to such option by the copyright holder.
9.45 + */
9.46 +package org.netbeans.html.boot.fx;
9.47 +
9.48 +import java.net.URL;
9.49 +import java.util.concurrent.CountDownLatch;
9.50 +import java.util.concurrent.Executors;
9.51 +import java.util.logging.Level;
9.52 +import java.util.logging.Logger;
9.53 +import javafx.application.Application;
9.54 +import javafx.application.Platform;
9.55 +import javafx.beans.value.ChangeListener;
9.56 +import javafx.beans.value.ObservableValue;
9.57 +import javafx.concurrent.Worker;
9.58 +import javafx.event.ActionEvent;
9.59 +import javafx.event.EventHandler;
9.60 +import javafx.geometry.Insets;
9.61 +import javafx.geometry.Pos;
9.62 +import javafx.scene.Scene;
9.63 +import javafx.scene.control.Button;
9.64 +import javafx.scene.layout.BorderPane;
9.65 +import javafx.scene.layout.VBox;
9.66 +import javafx.scene.text.Text;
9.67 +import javafx.scene.web.WebEvent;
9.68 +import javafx.scene.web.WebView;
9.69 +import javafx.stage.Modality;
9.70 +import javafx.stage.Stage;
9.71 +
9.72 +/** This is an implementation class, use {@link BrowserBuilder} API. Just
9.73 + * include this JAR on classpath and the {@link BrowserBuilder} API will find
9.74 + * this implementation automatically.
9.75 + */
9.76 +public class FXBrwsr extends Application {
9.77 + private static final Logger LOG = Logger.getLogger(FXBrwsr.class.getName());
9.78 + private static FXBrwsr INSTANCE;
9.79 + private static final CountDownLatch FINISHED = new CountDownLatch(1);
9.80 + private BorderPane root;
9.81 +
9.82 + public static synchronized WebView findWebView(final URL url, final FXPresenter onLoad) {
9.83 + if (INSTANCE == null) {
9.84 + Executors.newFixedThreadPool(1).submit(new Runnable() {
9.85 + @Override
9.86 + public void run() {
9.87 + try {
9.88 + FXBrwsr.launch(FXBrwsr.class);
9.89 + } catch (Throwable ex) {
9.90 + ex.printStackTrace();
9.91 + } finally {
9.92 + FINISHED.countDown();
9.93 + }
9.94 + }
9.95 + });
9.96 + }
9.97 + while (INSTANCE == null) {
9.98 + try {
9.99 + FXBrwsr.class.wait();
9.100 + } catch (InterruptedException ex) {
9.101 + // wait more
9.102 + }
9.103 + }
9.104 + if (!Platform.isFxApplicationThread()) {
9.105 + final WebView[] arr = {null};
9.106 + final CountDownLatch waitForResult = new CountDownLatch(1);
9.107 + Platform.runLater(new Runnable() {
9.108 + @Override
9.109 + public void run() {
9.110 + arr[0] = INSTANCE.newView(url, onLoad);
9.111 + waitForResult.countDown();
9.112 + }
9.113 + });
9.114 + for (;;) {
9.115 + try {
9.116 + waitForResult.await();
9.117 + break;
9.118 + } catch (InterruptedException ex) {
9.119 + LOG.log(Level.INFO, null, ex);
9.120 + }
9.121 + }
9.122 + return arr[0];
9.123 + } else {
9.124 + return INSTANCE.newView(url, onLoad);
9.125 + }
9.126 + }
9.127 +
9.128 + @Override
9.129 + public void start(Stage primaryStage) throws Exception {
9.130 + synchronized (FXBrwsr.class) {
9.131 + INSTANCE = this;
9.132 + FXBrwsr.class.notifyAll();
9.133 + }
9.134 + BorderPane r = new BorderPane();
9.135 + Scene scene = new Scene(r, 800, 600);
9.136 + primaryStage.setScene(scene);
9.137 + primaryStage.show();
9.138 + this.root = r;
9.139 + }
9.140 +
9.141 + private WebView newView(final URL url, final FXPresenter onLoad) {
9.142 + final WebView view = new WebView();
9.143 + view.setContextMenuEnabled(false);
9.144 + view.getEngine().setOnAlert(new EventHandler<WebEvent<String>>() {
9.145 + @Override
9.146 + public void handle(WebEvent<String> t) {
9.147 + final Stage dialogStage = new Stage();
9.148 + dialogStage.initModality(Modality.WINDOW_MODAL);
9.149 + dialogStage.setTitle("Warning");
9.150 + final Button button = new Button("Close");
9.151 + final Text text = new Text(t.getData());
9.152 + VBox box = new VBox();
9.153 + box.setAlignment(Pos.CENTER);
9.154 + box.setSpacing(10);
9.155 + box.setPadding(new Insets(10));
9.156 + box.getChildren().addAll(text, button);
9.157 + dialogStage.setScene(new Scene(box));
9.158 + button.setCancelButton(true);
9.159 + button.setOnAction(new EventHandler<ActionEvent>() {
9.160 + @Override
9.161 + public void handle(ActionEvent t) {
9.162 + dialogStage.close();
9.163 + }
9.164 + });
9.165 + dialogStage.centerOnScreen();
9.166 + dialogStage.showAndWait();
9.167 + }
9.168 + });
9.169 + root.setCenter(view);
9.170 + final Worker<Void> w = view.getEngine().getLoadWorker();
9.171 + w.stateProperty().addListener(new ChangeListener<Worker.State>() {
9.172 + @Override
9.173 + public void changed(ObservableValue<? extends Worker.State> ov, Worker.State t, Worker.State newState) {
9.174 + if (newState.equals(Worker.State.SUCCEEDED)) {
9.175 + onLoad.onPageLoad();
9.176 + }
9.177 + if (newState.equals(Worker.State.FAILED)) {
9.178 + throw new IllegalStateException("Failed to load " + url);
9.179 + }
9.180 + }
9.181 + });
9.182 + return view;
9.183 + }
9.184 +
9.185 + static void waitFinished() {
9.186 + for (;;) {
9.187 + try {
9.188 + FINISHED.await();
9.189 + break;
9.190 + } catch (InterruptedException ex) {
9.191 + LOG.log(Level.INFO, null, ex);
9.192 + }
9.193 + }
9.194 + }
9.195 +
9.196 +}
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/FXInspect.java Mon Dec 16 16:59:43 2013 +0100
10.3 @@ -0,0 +1,134 @@
10.4 +/**
10.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
10.6 + *
10.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
10.8 + *
10.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
10.10 + * Other names may be trademarks of their respective owners.
10.11 + *
10.12 + * The contents of this file are subject to the terms of either the GNU
10.13 + * General Public License Version 2 only ("GPL") or the Common
10.14 + * Development and Distribution License("CDDL") (collectively, the
10.15 + * "License"). You may not use this file except in compliance with the
10.16 + * License. You can obtain a copy of the License at
10.17 + * http://www.netbeans.org/cddl-gplv2.html
10.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
10.19 + * specific language governing permissions and limitations under the
10.20 + * License. When distributing the software, include this License Header
10.21 + * Notice in each file and include the License file at
10.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
10.23 + * particular file as subject to the "Classpath" exception as provided
10.24 + * by Oracle in the GPL Version 2 section of the License file that
10.25 + * accompanied this code. If applicable, add the following below the
10.26 + * License Header, with the fields enclosed by brackets [] replaced by
10.27 + * your own identifying information:
10.28 + * "Portions Copyrighted [year] [name of copyright owner]"
10.29 + *
10.30 + * Contributor(s):
10.31 + *
10.32 + * The Original Software is NetBeans. The Initial Developer of the Original
10.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
10.34 + *
10.35 + * If you wish your version of this file to be governed by only the CDDL
10.36 + * or only the GPL Version 2, indicate your decision by adding
10.37 + * "[Contributor] elects to include this software in this distribution
10.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
10.39 + * single choice of license, a recipient has the option to distribute
10.40 + * your version of this file under either the CDDL, the GPL Version 2 or
10.41 + * to extend the choice of license to its licensees as provided above.
10.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
10.43 + * Version 2 license, then the option applies only if the new code is
10.44 + * made subject to such option by the copyright holder.
10.45 + */
10.46 +package org.netbeans.html.boot.fx;
10.47 +
10.48 +import java.io.IOException;
10.49 +import java.io.ObjectInputStream;
10.50 +import java.io.ObjectOutputStream;
10.51 +import java.net.InetAddress;
10.52 +import java.net.Socket;
10.53 +import java.nio.charset.StandardCharsets;
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.util.Callback;
10.59 +
10.60 +/**
10.61 + *
10.62 + * @author Jaroslav Tulach <jtulach@netbeans.org>
10.63 + */
10.64 +final class FXInspect implements Runnable {
10.65 + private static final Logger LOG = Logger.getLogger(FXInspect.class.getName());
10.66 +
10.67 +
10.68 + private final WebEngine engine;
10.69 + private final ObjectInputStream input;
10.70 + private Dbgr dbg;
10.71 +
10.72 + private FXInspect(WebEngine engine, int port) throws IOException {
10.73 + this.engine = engine;
10.74 +
10.75 + Socket socket = new Socket(InetAddress.getByName(null), port);
10.76 + ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
10.77 + this.input = new ObjectInputStream(socket.getInputStream());
10.78 + initializeDebugger(output);
10.79 + }
10.80 +
10.81 + static boolean initialize(WebEngine engine) {
10.82 + final int inspectPort = Integer.getInteger("netbeans.inspect.port", -1); // NOI18N
10.83 + if (inspectPort != -1) {
10.84 + try {
10.85 + FXInspect inspector = new FXInspect(engine, inspectPort);
10.86 + Thread t = new Thread(inspector, "FX<->NetBeans Inspector");
10.87 + t.start();
10.88 + return true;
10.89 + } catch (IOException ex) {
10.90 + LOG.log(Level.INFO, "Cannot connect to NetBeans IDE to port " + inspectPort, ex); // NOI18N
10.91 + }
10.92 + }
10.93 + return false;
10.94 + }
10.95 +
10.96 + private void initializeDebugger(final ObjectOutputStream output) {
10.97 + Platform.runLater(new Runnable() {
10.98 + @Override
10.99 + public void run() {
10.100 + dbg = new Dbgr(engine, new Callback<String,Void>() {
10.101 + @Override
10.102 + public Void call(String message) {
10.103 + try {
10.104 + byte[] bytes = message.getBytes(StandardCharsets.UTF_8);
10.105 + output.writeInt(bytes.length);
10.106 + output.write(bytes);
10.107 + output.flush();
10.108 + } catch (IOException ioex) {
10.109 + ioex.printStackTrace();
10.110 + }
10.111 + return null;
10.112 + }
10.113 + });
10.114 + }
10.115 + });
10.116 + }
10.117 +
10.118 + @Override
10.119 + public void run() {
10.120 + try {
10.121 + while (true) {
10.122 + int length = input.readInt();
10.123 + byte[] bytes = new byte[length];
10.124 + input.readFully(bytes);
10.125 + final String message = new String(bytes, StandardCharsets.UTF_8);
10.126 + Platform.runLater(new Runnable() {
10.127 + @Override
10.128 + public void run() {
10.129 + dbg.sendMessage(message);
10.130 + }
10.131 + });
10.132 + }
10.133 + } catch (IOException ex) {
10.134 + LOG.log(Level.WARNING, null, ex);
10.135 + }
10.136 + }
10.137 +}
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/FXPresenter.java Mon Dec 16 16:59:43 2013 +0100
11.3 @@ -0,0 +1,98 @@
11.4 +/**
11.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
11.6 + *
11.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
11.8 + *
11.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
11.10 + * Other names may be trademarks of their respective owners.
11.11 + *
11.12 + * The contents of this file are subject to the terms of either the GNU
11.13 + * General Public License Version 2 only ("GPL") or the Common
11.14 + * Development and Distribution License("CDDL") (collectively, the
11.15 + * "License"). You may not use this file except in compliance with the
11.16 + * License. You can obtain a copy of the License at
11.17 + * http://www.netbeans.org/cddl-gplv2.html
11.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
11.19 + * specific language governing permissions and limitations under the
11.20 + * License. When distributing the software, include this License Header
11.21 + * Notice in each file and include the License file at
11.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
11.23 + * particular file as subject to the "Classpath" exception as provided
11.24 + * by Oracle in the GPL Version 2 section of the License file that
11.25 + * accompanied this code. If applicable, add the following below the
11.26 + * License Header, with the fields enclosed by brackets [] replaced by
11.27 + * your own identifying information:
11.28 + * "Portions Copyrighted [year] [name of copyright owner]"
11.29 + *
11.30 + * Contributor(s):
11.31 + *
11.32 + * The Original Software is NetBeans. The Initial Developer of the Original
11.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
11.34 + *
11.35 + * If you wish your version of this file to be governed by only the CDDL
11.36 + * or only the GPL Version 2, indicate your decision by adding
11.37 + * "[Contributor] elects to include this software in this distribution
11.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
11.39 + * single choice of license, a recipient has the option to distribute
11.40 + * your version of this file under either the CDDL, the GPL Version 2 or
11.41 + * to extend the choice of license to its licensees as provided above.
11.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
11.43 + * Version 2 license, then the option applies only if the new code is
11.44 + * made subject to such option by the copyright holder.
11.45 + */
11.46 +package org.netbeans.html.boot.fx;
11.47 +
11.48 +import java.io.BufferedReader;
11.49 +import java.io.File;
11.50 +import java.io.Reader;
11.51 +import java.lang.reflect.Method;
11.52 +import java.net.URL;
11.53 +import java.net.URLClassLoader;
11.54 +import java.util.ArrayList;
11.55 +import java.util.Arrays;
11.56 +import java.util.List;
11.57 +import java.util.logging.Level;
11.58 +import java.util.logging.Logger;
11.59 +import javafx.application.Platform;
11.60 +import javafx.scene.web.WebEngine;
11.61 +import javafx.scene.web.WebView;
11.62 +import net.java.html.boot.BrowserBuilder;
11.63 +import netscape.javascript.JSObject;
11.64 +import org.apidesign.html.boot.spi.Fn;
11.65 +import org.openide.util.lookup.ServiceProvider;
11.66 +
11.67 +/** This is an implementation class, use {@link BrowserBuilder} API. Just
11.68 + * include this JAR on classpath and the {@link BrowserBuilder} API will find
11.69 + * this implementation automatically.
11.70 + *
11.71 + * @author Jaroslav Tulach <jtulach@netbeans.org>
11.72 + */
11.73 +@ServiceProvider(service = Fn.Presenter.class)
11.74 +public final class FXPresenter extends AbstractFXPresenter {
11.75 + static {
11.76 + try {
11.77 + try {
11.78 + Class<?> c = Class.forName("javafx.application.Platform");
11.79 + // OK, on classpath
11.80 + } catch (ClassNotFoundException classNotFoundException) {
11.81 + Method m = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
11.82 + m.setAccessible(true);
11.83 + File f = new File(System.getProperty("java.home"), "lib/jfxrt.jar");
11.84 + if (f.exists()) {
11.85 + URL l = f.toURI().toURL();
11.86 + m.invoke(ClassLoader.getSystemClassLoader(), l);
11.87 + }
11.88 + }
11.89 + } catch (Exception ex) {
11.90 + throw new LinkageError("Can't add jfxrt.jar on the classpath", ex);
11.91 + }
11.92 + }
11.93 +
11.94 + protected void waitFinished() {
11.95 + FXBrwsr.waitFinished();
11.96 + }
11.97 +
11.98 + protected WebView findView(final URL resource) {
11.99 + return FXBrwsr.findWebView(resource, this);
11.100 + }
11.101 +}
12.1 --- a/boot-fx/src/test/java/net/java/html/boot/fx/FXBrowsersOnResourceTest.java Mon Dec 16 15:48:09 2013 +0100
12.2 +++ b/boot-fx/src/test/java/net/java/html/boot/fx/FXBrowsersOnResourceTest.java Mon Dec 16 16:59:43 2013 +0100
12.3 @@ -95,7 +95,7 @@
12.4 }
12.5
12.6 private void doTest() throws Throwable {
12.7 - URL u = FXBrowsersOnResourceTest.class.getResource("/org/apidesign/html/boot/fx/empty.html");
12.8 + URL u = FXBrowsersOnResourceTest.class.getResource("/org/netbeans/html/boot/fx/empty.html");
12.9 assertNotNull(u, "URL found");
12.10 FXBrowsers.load(App.getV1(), u, OnPages.class, "first");
12.11
12.12 @@ -131,7 +131,7 @@
12.13
12.14 assertEquals(increment(), 1, "Now it is one");
12.15
12.16 - URL u = FXBrowsersOnResourceTest.class.getResource("/org/apidesign/html/boot/fx/empty.html");
12.17 + URL u = FXBrowsersOnResourceTest.class.getResource("/org/netbeans/html/boot/fx/empty.html");
12.18 assertNotNull(u, "URL found");
12.19 FXBrowsers.load(App.getV2(), u, OnPages.class, "second", "Hello");
12.20
13.1 --- a/boot-fx/src/test/java/net/java/html/boot/fx/FXBrowsersTest.java Mon Dec 16 15:48:09 2013 +0100
13.2 +++ b/boot-fx/src/test/java/net/java/html/boot/fx/FXBrowsersTest.java Mon Dec 16 16:59:43 2013 +0100
13.3 @@ -95,7 +95,7 @@
13.4 }
13.5
13.6 private void doTest() throws Throwable {
13.7 - URL u = FXBrowsersTest.class.getResource("/org/apidesign/html/boot/fx/empty.html");
13.8 + URL u = FXBrowsersTest.class.getResource("/org/netbeans/html/boot/fx/empty.html");
13.9 assertNotNull(u, "URL found");
13.10 FXBrowsers.load(App.getV1(), u, OnPages.class, "first");
13.11
13.12 @@ -130,7 +130,7 @@
13.13
13.14 assertEquals(increment(), 1, "Now it is one");
13.15
13.16 - URL u = FXBrowsersTest.class.getResource("/org/apidesign/html/boot/fx/empty.html");
13.17 + URL u = FXBrowsersTest.class.getResource("/org/netbeans/html/boot/fx/empty.html");
13.18 assertNotNull(u, "URL found");
13.19 FXBrowsers.load(App.getV2(), u, OnPages.class, "second", "Hello");
13.20
14.1 --- a/boot-fx/src/test/java/org/apidesign/html/boot/fx/BootstrapTest.java Mon Dec 16 15:48:09 2013 +0100
14.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
14.3 @@ -1,109 +0,0 @@
14.4 -/**
14.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
14.6 - *
14.7 - * Copyright 1997-2010 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.apidesign.html.boot.fx;
14.47 -
14.48 -import java.lang.annotation.Annotation;
14.49 -import java.lang.reflect.Method;
14.50 -import java.util.ArrayList;
14.51 -import java.util.List;
14.52 -import java.util.concurrent.Executors;
14.53 -import net.java.html.boot.BrowserBuilder;
14.54 -import org.apidesign.html.boot.impl.FnContext;
14.55 -import org.apidesign.html.boot.spi.Fn;
14.56 -import org.testng.annotations.Factory;
14.57 -import org.testng.annotations.Test;
14.58 -
14.59 -/**
14.60 - *
14.61 - * @author Jaroslav Tulach <jtulach@netbeans.org>
14.62 - */
14.63 -public class BootstrapTest {
14.64 - private static Class<?> browserClass;
14.65 - private static Fn.Presenter browserPresenter;
14.66 -
14.67 - public BootstrapTest() {
14.68 - }
14.69 -
14.70 - @Factory public static Object[] compatibilityTests() throws Exception {
14.71 - final BrowserBuilder bb = BrowserBuilder.newBrowser().loadClass(BootstrapTest.class).
14.72 - loadPage("empty.html").
14.73 - invoke("initialized");
14.74 -
14.75 - Executors.newSingleThreadExecutor().submit(new Runnable() {
14.76 - @Override
14.77 - public void run() {
14.78 - bb.showAndWait();
14.79 - }
14.80 - });
14.81 -
14.82 - List<Object> res = new ArrayList<Object>();
14.83 - Class<? extends Annotation> test =
14.84 - loadClass().getClassLoader().loadClass(Test.class.getName()).
14.85 - asSubclass(Annotation.class);
14.86 - for (Method m : loadClass().getMethods()) {
14.87 - if (m.getAnnotation(test) != null) {
14.88 - res.add(new KOFx(browserPresenter, m));
14.89 - }
14.90 - }
14.91 - return res.toArray();
14.92 - }
14.93 -
14.94 - static synchronized Class<?> loadClass() throws InterruptedException {
14.95 - while (browserClass == null) {
14.96 - BootstrapTest.class.wait();
14.97 - }
14.98 - return browserClass;
14.99 - }
14.100 -
14.101 - public static synchronized void ready(Class<?> browserCls) throws Exception {
14.102 - browserClass = browserCls;
14.103 - browserPresenter = FnContext.currentPresenter();
14.104 - BootstrapTest.class.notifyAll();
14.105 - }
14.106 -
14.107 - public static void initialized() throws Exception {
14.108 - Class<?> classpathClass = ClassLoader.getSystemClassLoader().loadClass(BootstrapTest.class.getName());
14.109 - Method m = classpathClass.getMethod("ready", Class.class);
14.110 - m.invoke(null, FXPresenterTst.class);
14.111 - }
14.112 -}
15.1 --- a/boot-fx/src/test/java/org/apidesign/html/boot/fx/FXPresenterTst.java Mon Dec 16 15:48:09 2013 +0100
15.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
15.3 @@ -1,71 +0,0 @@
15.4 -/**
15.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
15.6 - *
15.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
15.8 - *
15.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
15.10 - * Other names may be trademarks of their respective owners.
15.11 - *
15.12 - * The contents of this file are subject to the terms of either the GNU
15.13 - * General Public License Version 2 only ("GPL") or the Common
15.14 - * Development and Distribution License("CDDL") (collectively, the
15.15 - * "License"). You may not use this file except in compliance with the
15.16 - * License. You can obtain a copy of the License at
15.17 - * http://www.netbeans.org/cddl-gplv2.html
15.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
15.19 - * specific language governing permissions and limitations under the
15.20 - * License. When distributing the software, include this License Header
15.21 - * Notice in each file and include the License file at
15.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
15.23 - * particular file as subject to the "Classpath" exception as provided
15.24 - * by Oracle in the GPL Version 2 section of the License file that
15.25 - * accompanied this code. If applicable, add the following below the
15.26 - * License Header, with the fields enclosed by brackets [] replaced by
15.27 - * your own identifying information:
15.28 - * "Portions Copyrighted [year] [name of copyright owner]"
15.29 - *
15.30 - * Contributor(s):
15.31 - *
15.32 - * The Original Software is NetBeans. The Initial Developer of the Original
15.33 - * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
15.34 - *
15.35 - * If you wish your version of this file to be governed by only the CDDL
15.36 - * or only the GPL Version 2, indicate your decision by adding
15.37 - * "[Contributor] elects to include this software in this distribution
15.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
15.39 - * single choice of license, a recipient has the option to distribute
15.40 - * your version of this file under either the CDDL, the GPL Version 2 or
15.41 - * to extend the choice of license to its licensees as provided above.
15.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
15.43 - * Version 2 license, then the option applies only if the new code is
15.44 - * made subject to such option by the copyright holder.
15.45 - */
15.46 -package org.apidesign.html.boot.fx;
15.47 -
15.48 -import net.java.html.js.JavaScriptBody;
15.49 -import static org.testng.Assert.*;
15.50 -import org.testng.annotations.Test;
15.51 -
15.52 -/**
15.53 - *
15.54 - * @author Jaroslav Tulach <jtulach@netbeans.org>
15.55 - */
15.56 -public class FXPresenterTst {
15.57 - @Test public void showClassLoader() {
15.58 - R run = new R();
15.59 - callback(run);
15.60 - assertEquals(run.cnt, 1, "Can call even private implementation classes");
15.61 - }
15.62 -
15.63 - @JavaScriptBody(args = { "r" }, javacall = true, body = "r.@java.lang.Runnable::run()();")
15.64 - private static native void callback(Runnable r);
15.65 -
15.66 - private static class R implements Runnable {
15.67 - int cnt;
15.68 -
15.69 - @Override
15.70 - public void run() {
15.71 - cnt++;
15.72 - }
15.73 - }
15.74 -}
16.1 --- a/boot-fx/src/test/java/org/apidesign/html/boot/fx/KOFx.java Mon Dec 16 15:48:09 2013 +0100
16.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
16.3 @@ -1,125 +0,0 @@
16.4 -/**
16.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
16.6 - *
16.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
16.8 - *
16.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
16.10 - * Other names may be trademarks of their respective owners.
16.11 - *
16.12 - * The contents of this file are subject to the terms of either the GNU
16.13 - * General Public License Version 2 only ("GPL") or the Common
16.14 - * Development and Distribution License("CDDL") (collectively, the
16.15 - * "License"). You may not use this file except in compliance with the
16.16 - * License. You can obtain a copy of the License at
16.17 - * http://www.netbeans.org/cddl-gplv2.html
16.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16.19 - * specific language governing permissions and limitations under the
16.20 - * License. When distributing the software, include this License Header
16.21 - * Notice in each file and include the License file at
16.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
16.23 - * particular file as subject to the "Classpath" exception as provided
16.24 - * by Oracle in the GPL Version 2 section of the License file that
16.25 - * accompanied this code. If applicable, add the following below the
16.26 - * License Header, with the fields enclosed by brackets [] replaced by
16.27 - * your own identifying information:
16.28 - * "Portions Copyrighted [year] [name of copyright owner]"
16.29 - *
16.30 - * Contributor(s):
16.31 - *
16.32 - * The Original Software is NetBeans. The Initial Developer of the Original
16.33 - * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
16.34 - *
16.35 - * If you wish your version of this file to be governed by only the CDDL
16.36 - * or only the GPL Version 2, indicate your decision by adding
16.37 - * "[Contributor] elects to include this software in this distribution
16.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
16.39 - * single choice of license, a recipient has the option to distribute
16.40 - * your version of this file under either the CDDL, the GPL Version 2 or
16.41 - * to extend the choice of license to its licensees as provided above.
16.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
16.43 - * Version 2 license, then the option applies only if the new code is
16.44 - * made subject to such option by the copyright holder.
16.45 - */
16.46 -package org.apidesign.html.boot.fx;
16.47 -
16.48 -import java.lang.reflect.InvocationTargetException;
16.49 -import java.lang.reflect.Method;
16.50 -import javafx.application.Platform;
16.51 -import org.apidesign.html.boot.impl.FnContext;
16.52 -import org.apidesign.html.boot.spi.Fn;
16.53 -import org.testng.IHookCallBack;
16.54 -import org.testng.IHookable;
16.55 -import org.testng.ITest;
16.56 -import org.testng.ITestResult;
16.57 -import org.testng.annotations.Test;
16.58 -
16.59 -/**
16.60 - *
16.61 - * @author Jaroslav Tulach <jtulach@netbeans.org>
16.62 - */
16.63 -public final class KOFx implements ITest, IHookable, Runnable {
16.64 - private final Fn.Presenter p;
16.65 - private final Method m;
16.66 - private Object result;
16.67 - private Object inst;
16.68 -
16.69 - KOFx(Fn.Presenter p, Method m) {
16.70 - this.p = p;
16.71 - this.m = m;
16.72 - }
16.73 -
16.74 - @Override
16.75 - public String getTestName() {
16.76 - return m.getName();
16.77 - }
16.78 -
16.79 - @Test
16.80 - public synchronized void executeTest() throws Exception {
16.81 - if (result == null) {
16.82 - Platform.runLater(this);
16.83 - wait();
16.84 - }
16.85 - if (result instanceof Exception) {
16.86 - throw (Exception)result;
16.87 - }
16.88 - if (result instanceof Error) {
16.89 - throw (Error)result;
16.90 - }
16.91 - }
16.92 -
16.93 - @Override
16.94 - public synchronized void run() {
16.95 - boolean notify = true;
16.96 - try {
16.97 - FnContext.currentPresenter(p);
16.98 - if (inst == null) {
16.99 - inst = m.getDeclaringClass().newInstance();
16.100 - }
16.101 - result = m.invoke(inst);
16.102 - if (result == null) {
16.103 - result = this;
16.104 - }
16.105 - } catch (InvocationTargetException ex) {
16.106 - Throwable r = ex.getTargetException();
16.107 - if (r instanceof InterruptedException) {
16.108 - notify = false;
16.109 - Platform.runLater(this);
16.110 - return;
16.111 - }
16.112 - result = r;
16.113 - } catch (Exception ex) {
16.114 - result = ex;
16.115 - } finally {
16.116 - if (notify) {
16.117 - notifyAll();
16.118 - }
16.119 - FnContext.currentPresenter(null);
16.120 - }
16.121 - }
16.122 -
16.123 - @Override
16.124 - public void run(IHookCallBack ihcb, ITestResult itr) {
16.125 - ihcb.runTestMethod(itr);
16.126 - }
16.127 -
16.128 -}
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
17.2 +++ b/boot-fx/src/test/java/org/netbeans/html/boot/fx/BootstrapTest.java Mon Dec 16 16:59:43 2013 +0100
17.3 @@ -0,0 +1,109 @@
17.4 +/**
17.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
17.6 + *
17.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
17.8 + *
17.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
17.10 + * Other names may be trademarks of their respective owners.
17.11 + *
17.12 + * The contents of this file are subject to the terms of either the GNU
17.13 + * General Public License Version 2 only ("GPL") or the Common
17.14 + * Development and Distribution License("CDDL") (collectively, the
17.15 + * "License"). You may not use this file except in compliance with the
17.16 + * License. You can obtain a copy of the License at
17.17 + * http://www.netbeans.org/cddl-gplv2.html
17.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
17.19 + * specific language governing permissions and limitations under the
17.20 + * License. When distributing the software, include this License Header
17.21 + * Notice in each file and include the License file at
17.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
17.23 + * particular file as subject to the "Classpath" exception as provided
17.24 + * by Oracle in the GPL Version 2 section of the License file that
17.25 + * accompanied this code. If applicable, add the following below the
17.26 + * License Header, with the fields enclosed by brackets [] replaced by
17.27 + * your own identifying information:
17.28 + * "Portions Copyrighted [year] [name of copyright owner]"
17.29 + *
17.30 + * Contributor(s):
17.31 + *
17.32 + * The Original Software is NetBeans. The Initial Developer of the Original
17.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
17.34 + *
17.35 + * If you wish your version of this file to be governed by only the CDDL
17.36 + * or only the GPL Version 2, indicate your decision by adding
17.37 + * "[Contributor] elects to include this software in this distribution
17.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
17.39 + * single choice of license, a recipient has the option to distribute
17.40 + * your version of this file under either the CDDL, the GPL Version 2 or
17.41 + * to extend the choice of license to its licensees as provided above.
17.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
17.43 + * Version 2 license, then the option applies only if the new code is
17.44 + * made subject to such option by the copyright holder.
17.45 + */
17.46 +package org.netbeans.html.boot.fx;
17.47 +
17.48 +import java.lang.annotation.Annotation;
17.49 +import java.lang.reflect.Method;
17.50 +import java.util.ArrayList;
17.51 +import java.util.List;
17.52 +import java.util.concurrent.Executors;
17.53 +import net.java.html.boot.BrowserBuilder;
17.54 +import org.netbeans.html.boot.impl.FnContext;
17.55 +import org.apidesign.html.boot.spi.Fn;
17.56 +import org.testng.annotations.Factory;
17.57 +import org.testng.annotations.Test;
17.58 +
17.59 +/**
17.60 + *
17.61 + * @author Jaroslav Tulach <jtulach@netbeans.org>
17.62 + */
17.63 +public class BootstrapTest {
17.64 + private static Class<?> browserClass;
17.65 + private static Fn.Presenter browserPresenter;
17.66 +
17.67 + public BootstrapTest() {
17.68 + }
17.69 +
17.70 + @Factory public static Object[] compatibilityTests() throws Exception {
17.71 + final BrowserBuilder bb = BrowserBuilder.newBrowser().loadClass(BootstrapTest.class).
17.72 + loadPage("empty.html").
17.73 + invoke("initialized");
17.74 +
17.75 + Executors.newSingleThreadExecutor().submit(new Runnable() {
17.76 + @Override
17.77 + public void run() {
17.78 + bb.showAndWait();
17.79 + }
17.80 + });
17.81 +
17.82 + List<Object> res = new ArrayList<Object>();
17.83 + Class<? extends Annotation> test =
17.84 + loadClass().getClassLoader().loadClass(Test.class.getName()).
17.85 + asSubclass(Annotation.class);
17.86 + for (Method m : loadClass().getMethods()) {
17.87 + if (m.getAnnotation(test) != null) {
17.88 + res.add(new KOFx(browserPresenter, m));
17.89 + }
17.90 + }
17.91 + return res.toArray();
17.92 + }
17.93 +
17.94 + static synchronized Class<?> loadClass() throws InterruptedException {
17.95 + while (browserClass == null) {
17.96 + BootstrapTest.class.wait();
17.97 + }
17.98 + return browserClass;
17.99 + }
17.100 +
17.101 + public static synchronized void ready(Class<?> browserCls) throws Exception {
17.102 + browserClass = browserCls;
17.103 + browserPresenter = FnContext.currentPresenter();
17.104 + BootstrapTest.class.notifyAll();
17.105 + }
17.106 +
17.107 + public static void initialized() throws Exception {
17.108 + Class<?> classpathClass = ClassLoader.getSystemClassLoader().loadClass(BootstrapTest.class.getName());
17.109 + Method m = classpathClass.getMethod("ready", Class.class);
17.110 + m.invoke(null, FXPresenterTst.class);
17.111 + }
17.112 +}
18.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
18.2 +++ b/boot-fx/src/test/java/org/netbeans/html/boot/fx/FXPresenterTst.java Mon Dec 16 16:59:43 2013 +0100
18.3 @@ -0,0 +1,71 @@
18.4 +/**
18.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
18.6 + *
18.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
18.8 + *
18.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
18.10 + * Other names may be trademarks of their respective owners.
18.11 + *
18.12 + * The contents of this file are subject to the terms of either the GNU
18.13 + * General Public License Version 2 only ("GPL") or the Common
18.14 + * Development and Distribution License("CDDL") (collectively, the
18.15 + * "License"). You may not use this file except in compliance with the
18.16 + * License. You can obtain a copy of the License at
18.17 + * http://www.netbeans.org/cddl-gplv2.html
18.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
18.19 + * specific language governing permissions and limitations under the
18.20 + * License. When distributing the software, include this License Header
18.21 + * Notice in each file and include the License file at
18.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
18.23 + * particular file as subject to the "Classpath" exception as provided
18.24 + * by Oracle in the GPL Version 2 section of the License file that
18.25 + * accompanied this code. If applicable, add the following below the
18.26 + * License Header, with the fields enclosed by brackets [] replaced by
18.27 + * your own identifying information:
18.28 + * "Portions Copyrighted [year] [name of copyright owner]"
18.29 + *
18.30 + * Contributor(s):
18.31 + *
18.32 + * The Original Software is NetBeans. The Initial Developer of the Original
18.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
18.34 + *
18.35 + * If you wish your version of this file to be governed by only the CDDL
18.36 + * or only the GPL Version 2, indicate your decision by adding
18.37 + * "[Contributor] elects to include this software in this distribution
18.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
18.39 + * single choice of license, a recipient has the option to distribute
18.40 + * your version of this file under either the CDDL, the GPL Version 2 or
18.41 + * to extend the choice of license to its licensees as provided above.
18.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
18.43 + * Version 2 license, then the option applies only if the new code is
18.44 + * made subject to such option by the copyright holder.
18.45 + */
18.46 +package org.netbeans.html.boot.fx;
18.47 +
18.48 +import net.java.html.js.JavaScriptBody;
18.49 +import static org.testng.Assert.*;
18.50 +import org.testng.annotations.Test;
18.51 +
18.52 +/**
18.53 + *
18.54 + * @author Jaroslav Tulach <jtulach@netbeans.org>
18.55 + */
18.56 +public class FXPresenterTst {
18.57 + @Test public void showClassLoader() {
18.58 + R run = new R();
18.59 + callback(run);
18.60 + assertEquals(run.cnt, 1, "Can call even private implementation classes");
18.61 + }
18.62 +
18.63 + @JavaScriptBody(args = { "r" }, javacall = true, body = "r.@java.lang.Runnable::run()();")
18.64 + private static native void callback(Runnable r);
18.65 +
18.66 + private static class R implements Runnable {
18.67 + int cnt;
18.68 +
18.69 + @Override
18.70 + public void run() {
18.71 + cnt++;
18.72 + }
18.73 + }
18.74 +}
19.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
19.2 +++ b/boot-fx/src/test/java/org/netbeans/html/boot/fx/KOFx.java Mon Dec 16 16:59:43 2013 +0100
19.3 @@ -0,0 +1,125 @@
19.4 +/**
19.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
19.6 + *
19.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
19.8 + *
19.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
19.10 + * Other names may be trademarks of their respective owners.
19.11 + *
19.12 + * The contents of this file are subject to the terms of either the GNU
19.13 + * General Public License Version 2 only ("GPL") or the Common
19.14 + * Development and Distribution License("CDDL") (collectively, the
19.15 + * "License"). You may not use this file except in compliance with the
19.16 + * License. You can obtain a copy of the License at
19.17 + * http://www.netbeans.org/cddl-gplv2.html
19.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
19.19 + * specific language governing permissions and limitations under the
19.20 + * License. When distributing the software, include this License Header
19.21 + * Notice in each file and include the License file at
19.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
19.23 + * particular file as subject to the "Classpath" exception as provided
19.24 + * by Oracle in the GPL Version 2 section of the License file that
19.25 + * accompanied this code. If applicable, add the following below the
19.26 + * License Header, with the fields enclosed by brackets [] replaced by
19.27 + * your own identifying information:
19.28 + * "Portions Copyrighted [year] [name of copyright owner]"
19.29 + *
19.30 + * Contributor(s):
19.31 + *
19.32 + * The Original Software is NetBeans. The Initial Developer of the Original
19.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
19.34 + *
19.35 + * If you wish your version of this file to be governed by only the CDDL
19.36 + * or only the GPL Version 2, indicate your decision by adding
19.37 + * "[Contributor] elects to include this software in this distribution
19.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
19.39 + * single choice of license, a recipient has the option to distribute
19.40 + * your version of this file under either the CDDL, the GPL Version 2 or
19.41 + * to extend the choice of license to its licensees as provided above.
19.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
19.43 + * Version 2 license, then the option applies only if the new code is
19.44 + * made subject to such option by the copyright holder.
19.45 + */
19.46 +package org.netbeans.html.boot.fx;
19.47 +
19.48 +import java.lang.reflect.InvocationTargetException;
19.49 +import java.lang.reflect.Method;
19.50 +import javafx.application.Platform;
19.51 +import org.netbeans.html.boot.impl.FnContext;
19.52 +import org.apidesign.html.boot.spi.Fn;
19.53 +import org.testng.IHookCallBack;
19.54 +import org.testng.IHookable;
19.55 +import org.testng.ITest;
19.56 +import org.testng.ITestResult;
19.57 +import org.testng.annotations.Test;
19.58 +
19.59 +/**
19.60 + *
19.61 + * @author Jaroslav Tulach <jtulach@netbeans.org>
19.62 + */
19.63 +public final class KOFx implements ITest, IHookable, Runnable {
19.64 + private final Fn.Presenter p;
19.65 + private final Method m;
19.66 + private Object result;
19.67 + private Object inst;
19.68 +
19.69 + KOFx(Fn.Presenter p, Method m) {
19.70 + this.p = p;
19.71 + this.m = m;
19.72 + }
19.73 +
19.74 + @Override
19.75 + public String getTestName() {
19.76 + return m.getName();
19.77 + }
19.78 +
19.79 + @Test
19.80 + public synchronized void executeTest() throws Exception {
19.81 + if (result == null) {
19.82 + Platform.runLater(this);
19.83 + wait();
19.84 + }
19.85 + if (result instanceof Exception) {
19.86 + throw (Exception)result;
19.87 + }
19.88 + if (result instanceof Error) {
19.89 + throw (Error)result;
19.90 + }
19.91 + }
19.92 +
19.93 + @Override
19.94 + public synchronized void run() {
19.95 + boolean notify = true;
19.96 + try {
19.97 + FnContext.currentPresenter(p);
19.98 + if (inst == null) {
19.99 + inst = m.getDeclaringClass().newInstance();
19.100 + }
19.101 + result = m.invoke(inst);
19.102 + if (result == null) {
19.103 + result = this;
19.104 + }
19.105 + } catch (InvocationTargetException ex) {
19.106 + Throwable r = ex.getTargetException();
19.107 + if (r instanceof InterruptedException) {
19.108 + notify = false;
19.109 + Platform.runLater(this);
19.110 + return;
19.111 + }
19.112 + result = r;
19.113 + } catch (Exception ex) {
19.114 + result = ex;
19.115 + } finally {
19.116 + if (notify) {
19.117 + notifyAll();
19.118 + }
19.119 + FnContext.currentPresenter(null);
19.120 + }
19.121 + }
19.122 +
19.123 + @Override
19.124 + public void run(IHookCallBack ihcb, ITestResult itr) {
19.125 + ihcb.runTestMethod(itr);
19.126 + }
19.127 +
19.128 +}
20.1 --- a/boot-fx/src/test/resources/org/apidesign/html/boot/fx/empty.html Mon Dec 16 15:48:09 2013 +0100
20.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
20.3 @@ -1,55 +0,0 @@
20.4 -<!--
20.5 -
20.6 - DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
20.7 -
20.8 - Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
20.9 -
20.10 - Oracle and Java are registered trademarks of Oracle and/or its affiliates.
20.11 - Other names may be trademarks of their respective owners.
20.12 -
20.13 - The contents of this file are subject to the terms of either the GNU
20.14 - General Public License Version 2 only ("GPL") or the Common
20.15 - Development and Distribution License("CDDL") (collectively, the
20.16 - "License"). You may not use this file except in compliance with the
20.17 - License. You can obtain a copy of the License at
20.18 - http://www.netbeans.org/cddl-gplv2.html
20.19 - or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
20.20 - specific language governing permissions and limitations under the
20.21 - License. When distributing the software, include this License Header
20.22 - Notice in each file and include the License file at
20.23 - nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
20.24 - particular file as subject to the "Classpath" exception as provided
20.25 - by Oracle in the GPL Version 2 section of the License file that
20.26 - accompanied this code. If applicable, add the following below the
20.27 - License Header, with the fields enclosed by brackets [] replaced by
20.28 - your own identifying information:
20.29 - "Portions Copyrighted [year] [name of copyright owner]"
20.30 -
20.31 - Contributor(s):
20.32 -
20.33 - The Original Software is NetBeans. The Initial Developer of the Original
20.34 - Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
20.35 -
20.36 - If you wish your version of this file to be governed by only the CDDL
20.37 - or only the GPL Version 2, indicate your decision by adding
20.38 - "[Contributor] elects to include this software in this distribution
20.39 - under the [CDDL or GPL Version 2] license." If you do not indicate a
20.40 - single choice of license, a recipient has the option to distribute
20.41 - your version of this file under either the CDDL, the GPL Version 2 or
20.42 - to extend the choice of license to its licensees as provided above.
20.43 - However, if you add GPL Version 2 code and therefore, elected the GPL
20.44 - Version 2 license, then the option applies only if the new code is
20.45 - made subject to such option by the copyright holder.
20.46 -
20.47 --->
20.48 -<!DOCTYPE html>
20.49 -<html>
20.50 - <head>
20.51 - <title>FX Presenter Harness</title>
20.52 - <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
20.53 - <meta name="viewport" content="width=device-width">
20.54 - </head>
20.55 - <body>
20.56 - <div>FX Presenter Harness</div>
20.57 - </body>
20.58 -</html>
21.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
21.2 +++ b/boot-fx/src/test/resources/org/netbeans/html/boot/fx/empty.html Mon Dec 16 16:59:43 2013 +0100
21.3 @@ -0,0 +1,55 @@
21.4 +<!--
21.5 +
21.6 + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
21.7 +
21.8 + Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
21.9 +
21.10 + Oracle and Java are registered trademarks of Oracle and/or its affiliates.
21.11 + Other names may be trademarks of their respective owners.
21.12 +
21.13 + The contents of this file are subject to the terms of either the GNU
21.14 + General Public License Version 2 only ("GPL") or the Common
21.15 + Development and Distribution License("CDDL") (collectively, the
21.16 + "License"). You may not use this file except in compliance with the
21.17 + License. You can obtain a copy of the License at
21.18 + http://www.netbeans.org/cddl-gplv2.html
21.19 + or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
21.20 + specific language governing permissions and limitations under the
21.21 + License. When distributing the software, include this License Header
21.22 + Notice in each file and include the License file at
21.23 + nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
21.24 + particular file as subject to the "Classpath" exception as provided
21.25 + by Oracle in the GPL Version 2 section of the License file that
21.26 + accompanied this code. If applicable, add the following below the
21.27 + License Header, with the fields enclosed by brackets [] replaced by
21.28 + your own identifying information:
21.29 + "Portions Copyrighted [year] [name of copyright owner]"
21.30 +
21.31 + Contributor(s):
21.32 +
21.33 + The Original Software is NetBeans. The Initial Developer of the Original
21.34 + Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
21.35 +
21.36 + If you wish your version of this file to be governed by only the CDDL
21.37 + or only the GPL Version 2, indicate your decision by adding
21.38 + "[Contributor] elects to include this software in this distribution
21.39 + under the [CDDL or GPL Version 2] license." If you do not indicate a
21.40 + single choice of license, a recipient has the option to distribute
21.41 + your version of this file under either the CDDL, the GPL Version 2 or
21.42 + to extend the choice of license to its licensees as provided above.
21.43 + However, if you add GPL Version 2 code and therefore, elected the GPL
21.44 + Version 2 license, then the option applies only if the new code is
21.45 + made subject to such option by the copyright holder.
21.46 +
21.47 +-->
21.48 +<!DOCTYPE html>
21.49 +<html>
21.50 + <head>
21.51 + <title>FX Presenter Harness</title>
21.52 + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
21.53 + <meta name="viewport" content="width=device-width">
21.54 + </head>
21.55 + <body>
21.56 + <div>FX Presenter Harness</div>
21.57 + </body>
21.58 +</html>
22.1 --- a/boot/src/main/java/net/java/html/boot/BrowserBuilder.java Mon Dec 16 15:48:09 2013 +0100
22.2 +++ b/boot/src/main/java/net/java/html/boot/BrowserBuilder.java Mon Dec 16 16:59:43 2013 +0100
22.3 @@ -54,10 +54,10 @@
22.4 import java.util.logging.Level;
22.5 import java.util.logging.Logger;
22.6 import net.java.html.js.JavaScriptBody;
22.7 -import org.apidesign.html.boot.impl.FnUtils;
22.8 +import org.netbeans.html.boot.impl.FnUtils;
22.9 import org.apidesign.html.boot.spi.Fn;
22.10 -import org.apidesign.html.boot.impl.FindResources;
22.11 -import org.apidesign.html.boot.impl.FnContext;
22.12 +import org.netbeans.html.boot.impl.FindResources;
22.13 +import org.netbeans.html.boot.impl.FnContext;
22.14
22.15 /** Use this builder to launch your Java/HTML based application. Typical
22.16 * usage in a main method of your application looks like this:
23.1 --- a/boot/src/main/java/org/apidesign/html/boot/impl/FindResources.java Mon Dec 16 15:48:09 2013 +0100
23.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
23.3 @@ -1,56 +0,0 @@
23.4 -/**
23.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
23.6 - *
23.7 - * Copyright 1997-2010 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.apidesign.html.boot.impl;
23.47 -
23.48 -import java.net.URL;
23.49 -import java.util.Collection;
23.50 -
23.51 -/**
23.52 - *
23.53 - * @author Jaroslav Tulach <jtulach@netbeans.org>
23.54 - */
23.55 -public interface FindResources {
23.56 -
23.57 - public void findResources(String path, Collection<? super URL> results, boolean oneIsEnough);
23.58 -
23.59 -}
24.1 --- a/boot/src/main/java/org/apidesign/html/boot/impl/FnContext.java Mon Dec 16 15:48:09 2013 +0100
24.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
24.3 @@ -1,98 +0,0 @@
24.4 -/**
24.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
24.6 - *
24.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
24.8 - *
24.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
24.10 - * Other names may be trademarks of their respective owners.
24.11 - *
24.12 - * The contents of this file are subject to the terms of either the GNU
24.13 - * General Public License Version 2 only ("GPL") or the Common
24.14 - * Development and Distribution License("CDDL") (collectively, the
24.15 - * "License"). You may not use this file except in compliance with the
24.16 - * License. You can obtain a copy of the License at
24.17 - * http://www.netbeans.org/cddl-gplv2.html
24.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
24.19 - * specific language governing permissions and limitations under the
24.20 - * License. When distributing the software, include this License Header
24.21 - * Notice in each file and include the License file at
24.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
24.23 - * particular file as subject to the "Classpath" exception as provided
24.24 - * by Oracle in the GPL Version 2 section of the License file that
24.25 - * accompanied this code. If applicable, add the following below the
24.26 - * License Header, with the fields enclosed by brackets [] replaced by
24.27 - * your own identifying information:
24.28 - * "Portions Copyrighted [year] [name of copyright owner]"
24.29 - *
24.30 - * Contributor(s):
24.31 - *
24.32 - * The Original Software is NetBeans. The Initial Developer of the Original
24.33 - * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
24.34 - *
24.35 - * If you wish your version of this file to be governed by only the CDDL
24.36 - * or only the GPL Version 2, indicate your decision by adding
24.37 - * "[Contributor] elects to include this software in this distribution
24.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
24.39 - * single choice of license, a recipient has the option to distribute
24.40 - * your version of this file under either the CDDL, the GPL Version 2 or
24.41 - * to extend the choice of license to its licensees as provided above.
24.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
24.43 - * Version 2 license, then the option applies only if the new code is
24.44 - * made subject to such option by the copyright holder.
24.45 - */
24.46 -package org.apidesign.html.boot.impl;
24.47 -
24.48 -import java.io.Closeable;
24.49 -import java.io.IOException;
24.50 -import java.util.logging.Logger;
24.51 -import org.apidesign.html.boot.spi.Fn;
24.52 -
24.53 -/**
24.54 - *
24.55 - * @author Jaroslav Tulach <jtulach@netbeans.org>
24.56 - */
24.57 -public final class FnContext implements Closeable {
24.58 - private static final Logger LOG = Logger.getLogger(FnContext.class.getName());
24.59 -
24.60 - private Object prev;
24.61 - private FnContext(Fn.Presenter p) {
24.62 - this.prev = p;
24.63 - }
24.64 -
24.65 - @Override
24.66 - public void close() throws IOException {
24.67 - if (prev != this) {
24.68 - currentPresenter((Fn.Presenter)prev);
24.69 - prev = this;
24.70 - }
24.71 - }
24.72 -/*
24.73 - @Override
24.74 - protected void finalize() throws Throwable {
24.75 - if (prev != null) {
24.76 - LOG.warning("Unclosed context!");
24.77 - }
24.78 - }
24.79 -*/
24.80 - public static Closeable activate(Fn.Presenter newP) {
24.81 - return new FnContext(currentPresenter(newP));
24.82 - }
24.83 -
24.84 -
24.85 - private static final ThreadLocal<Fn.Presenter> CURRENT = new ThreadLocal<Fn.Presenter>();
24.86 -
24.87 - public static Fn.Presenter currentPresenter(Fn.Presenter p) {
24.88 - Fn.Presenter prev = CURRENT.get();
24.89 - CURRENT.set(p);
24.90 - return prev;
24.91 - }
24.92 -
24.93 - public static Fn.Presenter currentPresenter() {
24.94 - Fn.Presenter p = CURRENT.get();
24.95 - if (p == null) {
24.96 - throw new IllegalStateException("No current WebView context around!");
24.97 - }
24.98 - return p;
24.99 - }
24.100 -
24.101 -}
25.1 --- a/boot/src/main/java/org/apidesign/html/boot/impl/FnUtils.java Mon Dec 16 15:48:09 2013 +0100
25.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
25.3 @@ -1,597 +0,0 @@
25.4 -/**
25.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
25.6 - *
25.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
25.8 - *
25.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
25.10 - * Other names may be trademarks of their respective owners.
25.11 - *
25.12 - * The contents of this file are subject to the terms of either the GNU
25.13 - * General Public License Version 2 only ("GPL") or the Common
25.14 - * Development and Distribution License("CDDL") (collectively, the
25.15 - * "License"). You may not use this file except in compliance with the
25.16 - * License. You can obtain a copy of the License at
25.17 - * http://www.netbeans.org/cddl-gplv2.html
25.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
25.19 - * specific language governing permissions and limitations under the
25.20 - * License. When distributing the software, include this License Header
25.21 - * Notice in each file and include the License file at
25.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
25.23 - * particular file as subject to the "Classpath" exception as provided
25.24 - * by Oracle in the GPL Version 2 section of the License file that
25.25 - * accompanied this code. If applicable, add the following below the
25.26 - * License Header, with the fields enclosed by brackets [] replaced by
25.27 - * your own identifying information:
25.28 - * "Portions Copyrighted [year] [name of copyright owner]"
25.29 - *
25.30 - * Contributor(s):
25.31 - *
25.32 - * The Original Software is NetBeans. The Initial Developer of the Original
25.33 - * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
25.34 - *
25.35 - * If you wish your version of this file to be governed by only the CDDL
25.36 - * or only the GPL Version 2, indicate your decision by adding
25.37 - * "[Contributor] elects to include this software in this distribution
25.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
25.39 - * single choice of license, a recipient has the option to distribute
25.40 - * your version of this file under either the CDDL, the GPL Version 2 or
25.41 - * to extend the choice of license to its licensees as provided above.
25.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
25.43 - * Version 2 license, then the option applies only if the new code is
25.44 - * made subject to such option by the copyright holder.
25.45 - */
25.46 -package org.apidesign.html.boot.impl;
25.47 -
25.48 -import java.io.Closeable;
25.49 -import java.io.InputStream;
25.50 -import java.io.InputStreamReader;
25.51 -import java.io.Reader;
25.52 -import java.net.URL;
25.53 -import java.util.ArrayList;
25.54 -import java.util.Collections;
25.55 -import java.util.Enumeration;
25.56 -import java.util.List;
25.57 -import java.util.concurrent.Callable;
25.58 -import org.apidesign.html.boot.spi.Fn;
25.59 -import org.objectweb.asm.AnnotationVisitor;
25.60 -import org.objectweb.asm.ClassReader;
25.61 -import org.objectweb.asm.ClassVisitor;
25.62 -import org.objectweb.asm.ClassWriter;
25.63 -import org.objectweb.asm.Label;
25.64 -import org.objectweb.asm.MethodVisitor;
25.65 -import org.objectweb.asm.Opcodes;
25.66 -import org.objectweb.asm.Type;
25.67 -import org.objectweb.asm.signature.SignatureReader;
25.68 -import org.objectweb.asm.signature.SignatureVisitor;
25.69 -import org.objectweb.asm.signature.SignatureWriter;
25.70 -
25.71 -/**
25.72 - *
25.73 - * @author Jaroslav Tulach <jtulach@netbeans.org>
25.74 - */
25.75 -public final class FnUtils implements Fn.Presenter {
25.76 -
25.77 - private FnUtils() {
25.78 - }
25.79 -
25.80 - public static boolean isJavaScriptCapable(ClassLoader l) {
25.81 - if (l instanceof JsClassLoader) {
25.82 - return true;
25.83 - }
25.84 - Class<?> clazz;
25.85 - try (Closeable c = Fn.activate(new FnUtils())) {
25.86 - clazz = Class.forName(Test.class.getName(), true, l);
25.87 - final Object is = ((Callable<?>)clazz.newInstance()).call();
25.88 - return Boolean.TRUE.equals(is);
25.89 - } catch (Exception ex) {
25.90 - return false;
25.91 - }
25.92 - }
25.93 -
25.94 - public static boolean isValid(Fn fn) {
25.95 - return fn != null && fn.isValid();
25.96 - }
25.97 -
25.98 - public static ClassLoader newLoader(final FindResources f, final Fn.Presenter d, ClassLoader parent) {
25.99 - return new JsClassLoader(parent) {
25.100 - @Override
25.101 - protected URL findResource(String name) {
25.102 - List<URL> l = res(name, true);
25.103 - return l.isEmpty() ? null : l.get(0);
25.104 - }
25.105 -
25.106 - @Override
25.107 - protected Enumeration<URL> findResources(String name) {
25.108 - return Collections.enumeration(res(name, false));
25.109 - }
25.110 -
25.111 - private List<URL> res(String name, boolean oneIsEnough) {
25.112 - List<URL> l = new ArrayList<URL>();
25.113 - f.findResources(name, l, oneIsEnough);
25.114 - return l;
25.115 - }
25.116 -
25.117 - @Override
25.118 - protected Fn defineFn(String code, String... names) {
25.119 - return d.defineFn(code, names);
25.120 - }
25.121 -
25.122 - @Override
25.123 - protected void loadScript(Reader code) throws Exception {
25.124 - d.loadScript(code);
25.125 - }
25.126 - };
25.127 - }
25.128 -
25.129 - static String callback(final String body) {
25.130 - return new JsCallback() {
25.131 - @Override
25.132 - protected CharSequence callMethod(
25.133 - String ident, String fqn, String method, String params
25.134 - ) {
25.135 - StringBuilder sb = new StringBuilder();
25.136 - sb.append("vm.").append(mangle(fqn, method, params));
25.137 - sb.append("(");
25.138 - if (ident != null) {
25.139 - sb.append(ident);
25.140 - }
25.141 - return sb;
25.142 - }
25.143 -
25.144 - }.parse(body);
25.145 - }
25.146 -
25.147 - static void loadScript(ClassLoader jcl, String resource) {
25.148 - final InputStream script = jcl.getResourceAsStream(resource);
25.149 - if (script == null) {
25.150 - throw new NullPointerException("Can't find " + resource);
25.151 - }
25.152 - try {
25.153 - Reader isr = null;
25.154 - try {
25.155 - isr = new InputStreamReader(script, "UTF-8");
25.156 - FnContext.currentPresenter().loadScript(isr);
25.157 - } finally {
25.158 - if (isr != null) {
25.159 - isr.close();
25.160 - }
25.161 - }
25.162 - } catch (Exception ex) {
25.163 - throw new IllegalStateException("Can't execute " + resource, ex);
25.164 - }
25.165 - }
25.166 -
25.167 - @Override
25.168 - public Fn defineFn(String code, String... names) {
25.169 - return new TrueFn();
25.170 - }
25.171 -
25.172 - @Override
25.173 - public void displayPage(URL page, Runnable onPageLoad) {
25.174 - }
25.175 -
25.176 - @Override
25.177 - public void loadScript(Reader code) throws Exception {
25.178 - }
25.179 -
25.180 - private static final class FindInClass extends ClassVisitor {
25.181 - private String name;
25.182 - private int found;
25.183 - private ClassLoader loader;
25.184 - private String resource;
25.185 -
25.186 - public FindInClass(ClassLoader l, ClassVisitor cv) {
25.187 - super(Opcodes.ASM4, cv);
25.188 - this.loader = l;
25.189 - }
25.190 -
25.191 - @Override
25.192 - public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
25.193 - this.name = name;
25.194 - super.visit(version, access, name, signature, superName, interfaces);
25.195 - }
25.196 -
25.197 - @Override
25.198 - public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
25.199 - if ("Lnet/java/html/js/JavaScriptResource;".equals(desc)) {
25.200 - return new LoadResource();
25.201 - }
25.202 - return super.visitAnnotation(desc, visible);
25.203 - }
25.204 -
25.205 - @Override
25.206 - public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
25.207 - return new FindInMethod(access, name, desc,
25.208 - super.visitMethod(access & (~Opcodes.ACC_NATIVE), name, desc, signature, exceptions)
25.209 - );
25.210 - }
25.211 -
25.212 - private final class FindInMethod extends MethodVisitor {
25.213 -
25.214 - private final String name;
25.215 - private final String desc;
25.216 - private final int access;
25.217 - private List<String> args;
25.218 - private String body;
25.219 - private boolean bodyGenerated;
25.220 -
25.221 - public FindInMethod(int access, String name, String desc, MethodVisitor mv) {
25.222 - super(Opcodes.ASM4, mv);
25.223 - this.access = access;
25.224 - this.name = name;
25.225 - this.desc = desc;
25.226 - }
25.227 -
25.228 - @Override
25.229 - public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
25.230 - if ("Lnet/java/html/js/JavaScriptBody;".equals(desc) // NOI18N
25.231 - || "Lorg/apidesign/bck2brwsr/core/JavaScriptBody;".equals(desc) // NOI18N
25.232 - ) {
25.233 - found++;
25.234 - return new FindInAnno();
25.235 - }
25.236 - return super.visitAnnotation(desc, visible);
25.237 - }
25.238 -
25.239 - private void generateJSBody(List<String> args, String body) {
25.240 - this.args = args;
25.241 - this.body = body;
25.242 - }
25.243 -
25.244 - @Override
25.245 - public void visitCode() {
25.246 - if (body == null) {
25.247 - return;
25.248 - }
25.249 - generateBody();
25.250 - }
25.251 -
25.252 - private boolean generateBody() {
25.253 - if (bodyGenerated) {
25.254 - return false;
25.255 - }
25.256 - bodyGenerated = true;
25.257 -
25.258 - super.visitFieldInsn(
25.259 - Opcodes.GETSTATIC, FindInClass.this.name,
25.260 - "$$fn$$" + name + "_" + found,
25.261 - "Lorg/apidesign/html/boot/spi/Fn;"
25.262 - );
25.263 - super.visitInsn(Opcodes.DUP);
25.264 - super.visitMethodInsn(
25.265 - Opcodes.INVOKESTATIC,
25.266 - "org/apidesign/html/boot/spi/Fn", "isValid",
25.267 - "(Lorg/apidesign/html/boot/spi/Fn;)Z"
25.268 - );
25.269 - Label ifNotNull = new Label();
25.270 - super.visitJumpInsn(Opcodes.IFNE, ifNotNull);
25.271 -
25.272 - // init Fn
25.273 - super.visitInsn(Opcodes.POP);
25.274 - super.visitLdcInsn(Type.getObjectType(FindInClass.this.name));
25.275 - super.visitLdcInsn(body);
25.276 - super.visitIntInsn(Opcodes.SIPUSH, args.size());
25.277 - super.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/String");
25.278 - boolean needsVM = false;
25.279 - for (int i = 0; i < args.size(); i++) {
25.280 - assert !needsVM;
25.281 - String argName = args.get(i);
25.282 - needsVM = "vm".equals(argName);
25.283 - super.visitInsn(Opcodes.DUP);
25.284 - super.visitIntInsn(Opcodes.BIPUSH, i);
25.285 - super.visitLdcInsn(argName);
25.286 - super.visitInsn(Opcodes.AASTORE);
25.287 - }
25.288 - super.visitMethodInsn(Opcodes.INVOKESTATIC,
25.289 - "org/apidesign/html/boot/spi/Fn", "define",
25.290 - "(Ljava/lang/Class;Ljava/lang/String;[Ljava/lang/String;)Lorg/apidesign/html/boot/spi/Fn;"
25.291 - );
25.292 - if (resource != null) {
25.293 - super.visitLdcInsn(Type.getObjectType(FindInClass.this.name));
25.294 - super.visitLdcInsn(resource);
25.295 - super.visitMethodInsn(Opcodes.INVOKESTATIC,
25.296 - "org/apidesign/html/boot/spi/Fn", "preload",
25.297 - "(Lorg/apidesign/html/boot/spi/Fn;Ljava/lang/Class;Ljava/lang/String;)Lorg/apidesign/html/boot/spi/Fn;"
25.298 - );
25.299 - }
25.300 - super.visitInsn(Opcodes.DUP);
25.301 - super.visitFieldInsn(
25.302 - Opcodes.PUTSTATIC, FindInClass.this.name,
25.303 - "$$fn$$" + name + "_" + found,
25.304 - "Lorg/apidesign/html/boot/spi/Fn;"
25.305 - );
25.306 - // end of Fn init
25.307 -
25.308 - super.visitLabel(ifNotNull);
25.309 -
25.310 - final int offset;
25.311 - if ((access & Opcodes.ACC_STATIC) == 0) {
25.312 - offset = 1;
25.313 - super.visitIntInsn(Opcodes.ALOAD, 0);
25.314 - } else {
25.315 - offset = 0;
25.316 - super.visitInsn(Opcodes.ACONST_NULL);
25.317 - }
25.318 -
25.319 - super.visitIntInsn(Opcodes.SIPUSH, args.size());
25.320 - super.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object");
25.321 -
25.322 - class SV extends SignatureVisitor {
25.323 -
25.324 - private boolean nowReturn;
25.325 - private Type returnType;
25.326 - private int index;
25.327 - private int loadIndex = offset;
25.328 -
25.329 - public SV() {
25.330 - super(Opcodes.ASM4);
25.331 - }
25.332 -
25.333 - @Override
25.334 - public void visitBaseType(char descriptor) {
25.335 - final Type t = Type.getType("" + descriptor);
25.336 - if (nowReturn) {
25.337 - returnType = t;
25.338 - return;
25.339 - }
25.340 - FindInMethod.super.visitInsn(Opcodes.DUP);
25.341 - FindInMethod.super.visitIntInsn(Opcodes.SIPUSH, index++);
25.342 - FindInMethod.super.visitVarInsn(t.getOpcode(Opcodes.ILOAD), loadIndex++);
25.343 - String factory;
25.344 - switch (descriptor) {
25.345 - case 'I':
25.346 - factory = "java/lang/Integer";
25.347 - break;
25.348 - case 'J':
25.349 - factory = "java/lang/Long";
25.350 - loadIndex++;
25.351 - break;
25.352 - case 'S':
25.353 - factory = "java/lang/Short";
25.354 - break;
25.355 - case 'F':
25.356 - factory = "java/lang/Float";
25.357 - break;
25.358 - case 'D':
25.359 - factory = "java/lang/Double";
25.360 - loadIndex++;
25.361 - break;
25.362 - case 'Z':
25.363 - factory = "java/lang/Boolean";
25.364 - break;
25.365 - case 'C':
25.366 - factory = "java/lang/Character";
25.367 - break;
25.368 - case 'B':
25.369 - factory = "java/lang/Byte";
25.370 - break;
25.371 - default:
25.372 - throw new IllegalStateException(t.toString());
25.373 - }
25.374 - FindInMethod.super.visitMethodInsn(Opcodes.INVOKESTATIC,
25.375 - factory, "valueOf", "(" + descriptor + ")L" + factory + ";"
25.376 - );
25.377 - FindInMethod.super.visitInsn(Opcodes.AASTORE);
25.378 - }
25.379 -
25.380 - @Override
25.381 - public SignatureVisitor visitArrayType() {
25.382 - if (nowReturn) {
25.383 - throw new IllegalStateException("Not supported yet");
25.384 - }
25.385 - loadObject();
25.386 - return new SignatureWriter();
25.387 - }
25.388 -
25.389 - @Override
25.390 - public void visitClassType(String name) {
25.391 - if (nowReturn) {
25.392 - returnType = Type.getObjectType(name);
25.393 - return;
25.394 - }
25.395 - loadObject();
25.396 - }
25.397 -
25.398 - @Override
25.399 - public SignatureVisitor visitReturnType() {
25.400 - nowReturn = true;
25.401 - return this;
25.402 - }
25.403 -
25.404 - private void loadObject() {
25.405 - FindInMethod.super.visitInsn(Opcodes.DUP);
25.406 - FindInMethod.super.visitIntInsn(Opcodes.SIPUSH, index++);
25.407 - FindInMethod.super.visitVarInsn(Opcodes.ALOAD, loadIndex++);
25.408 - FindInMethod.super.visitInsn(Opcodes.AASTORE);
25.409 - }
25.410 -
25.411 - }
25.412 - SV sv = new SV();
25.413 - SignatureReader sr = new SignatureReader(desc);
25.414 - sr.accept(sv);
25.415 -
25.416 - if (needsVM) {
25.417 - FindInMethod.super.visitInsn(Opcodes.DUP);
25.418 - FindInMethod.super.visitIntInsn(Opcodes.SIPUSH, sv.index);
25.419 - int lastSlash = FindInClass.this.name.lastIndexOf('/');
25.420 - String jsCallbacks = FindInClass.this.name.substring(0, lastSlash + 1) + "$JsCallbacks$";
25.421 - FindInMethod.super.visitFieldInsn(Opcodes.GETSTATIC, jsCallbacks, "VM", "L" + jsCallbacks + ";");
25.422 - FindInMethod.super.visitMethodInsn(Opcodes.INVOKEVIRTUAL, jsCallbacks, "current", "()L" + jsCallbacks + ";");
25.423 - FindInMethod.super.visitInsn(Opcodes.AASTORE);
25.424 - }
25.425 -
25.426 - super.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
25.427 - "org/apidesign/html/boot/spi/Fn", "invoke", "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;"
25.428 - );
25.429 - switch (sv.returnType.getSort()) {
25.430 - case Type.VOID:
25.431 - super.visitInsn(Opcodes.RETURN);
25.432 - break;
25.433 - case Type.ARRAY:
25.434 - case Type.OBJECT:
25.435 - super.visitTypeInsn(Opcodes.CHECKCAST, sv.returnType.getInternalName());
25.436 - super.visitInsn(Opcodes.ARETURN);
25.437 - break;
25.438 - case Type.BOOLEAN:
25.439 - super.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Boolean");
25.440 - super.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
25.441 - "java/lang/Boolean", "booleanValue", "()Z"
25.442 - );
25.443 - super.visitInsn(Opcodes.IRETURN);
25.444 - break;
25.445 - default:
25.446 - super.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Number");
25.447 - super.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
25.448 - "java/lang/Number", sv.returnType.getClassName() + "Value", "()" + sv.returnType.getDescriptor()
25.449 - );
25.450 - super.visitInsn(sv.returnType.getOpcode(Opcodes.IRETURN));
25.451 - }
25.452 - return true;
25.453 - }
25.454 -
25.455 - @Override
25.456 - public void visitEnd() {
25.457 - super.visitEnd();
25.458 - if (body != null) {
25.459 - if (generateBody()) {
25.460 - // native method
25.461 - super.visitMaxs(1, 0);
25.462 - }
25.463 - FindInClass.this.visitField(
25.464 - Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC,
25.465 - "$$fn$$" + name + "_" + found,
25.466 - "Lorg/apidesign/html/boot/spi/Fn;",
25.467 - null, null
25.468 - );
25.469 - }
25.470 - }
25.471 -
25.472 - private final class FindInAnno extends AnnotationVisitor {
25.473 -
25.474 - private List<String> args = new ArrayList<String>();
25.475 - private String body;
25.476 - private boolean javacall = false;
25.477 -
25.478 - public FindInAnno() {
25.479 - super(Opcodes.ASM4);
25.480 - }
25.481 -
25.482 - @Override
25.483 - public void visit(String name, Object value) {
25.484 - if (name == null) {
25.485 - args.add((String) value);
25.486 - return;
25.487 - }
25.488 - if (name.equals("javacall")) { // NOI18N
25.489 - javacall = (Boolean) value;
25.490 - return;
25.491 - }
25.492 - assert name.equals("body");
25.493 - body = (String) value;
25.494 - }
25.495 -
25.496 - @Override
25.497 - public AnnotationVisitor visitArray(String name) {
25.498 - return this;
25.499 - }
25.500 -
25.501 - @Override
25.502 - public void visitEnd() {
25.503 - if (body != null) {
25.504 - if (javacall) {
25.505 - body = callback(body);
25.506 - args.add("vm");
25.507 - }
25.508 - generateJSBody(args, body);
25.509 - }
25.510 - }
25.511 - }
25.512 - }
25.513 -
25.514 - private final class LoadResource extends AnnotationVisitor {
25.515 -
25.516 - public LoadResource() {
25.517 - super(Opcodes.ASM4);
25.518 - }
25.519 -
25.520 - @Override
25.521 - public void visit(String attrName, Object value) {
25.522 - String relPath = (String) value;
25.523 - if (relPath.startsWith("/")) {
25.524 - resource = relPath;
25.525 - } else {
25.526 - int last = name.lastIndexOf('/');
25.527 - String fullPath = name.substring(0, last + 1) + relPath;
25.528 - resource = fullPath;
25.529 - }
25.530 - }
25.531 - }
25.532 - }
25.533 -
25.534 - private static class ClassWriterEx extends ClassWriter {
25.535 -
25.536 - private ClassLoader loader;
25.537 -
25.538 - public ClassWriterEx(ClassLoader l, ClassReader classReader, int flags) {
25.539 - super(classReader, flags);
25.540 - this.loader = l;
25.541 - }
25.542 -
25.543 - @Override
25.544 - protected String getCommonSuperClass(final String type1, final String type2) {
25.545 - Class<?> c, d;
25.546 - try {
25.547 - c = Class.forName(type1.replace('/', '.'), false, loader);
25.548 - d = Class.forName(type2.replace('/', '.'), false, loader);
25.549 - } catch (Exception e) {
25.550 - throw new RuntimeException(e.toString());
25.551 - }
25.552 - if (c.isAssignableFrom(d)) {
25.553 - return type1;
25.554 - }
25.555 - if (d.isAssignableFrom(c)) {
25.556 - return type2;
25.557 - }
25.558 - if (c.isInterface() || d.isInterface()) {
25.559 - return "java/lang/Object";
25.560 - } else {
25.561 - do {
25.562 - c = c.getSuperclass();
25.563 - } while (!c.isAssignableFrom(d));
25.564 - return c.getName().replace('.', '/');
25.565 - }
25.566 - }
25.567 - }
25.568 -
25.569 - static byte[] transform(ClassLoader loader, byte[] arr) {
25.570 - ClassReader cr = new ClassReader(arr) {
25.571 - // to allow us to compile with -profile compact1 on
25.572 - // JDK8 while processing the class as JDK7, the highest
25.573 - // class format asm 4.1 understands to
25.574 - @Override
25.575 - public short readShort(int index) {
25.576 - short s = super.readShort(index);
25.577 - if (index == 6 && s > Opcodes.V1_7) {
25.578 - return Opcodes.V1_7;
25.579 - }
25.580 - return s;
25.581 - }
25.582 - };
25.583 - FindInClass tst = new FindInClass(loader, null);
25.584 - cr.accept(tst, 0);
25.585 - if (tst.found > 0) {
25.586 - ClassWriter w = new ClassWriterEx(loader, cr, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
25.587 - FindInClass fic = new FindInClass(loader, w);
25.588 - cr.accept(fic, 0);
25.589 - arr = w.toByteArray();
25.590 - }
25.591 - return arr;
25.592 - }
25.593 -
25.594 - private static final class TrueFn extends Fn {
25.595 - @Override
25.596 - public Object invoke(Object thiz, Object... args) throws Exception {
25.597 - return Boolean.TRUE;
25.598 - }
25.599 - } // end of TrueFn
25.600 -}
26.1 --- a/boot/src/main/java/org/apidesign/html/boot/impl/JavaScriptProcesor.java Mon Dec 16 15:48:09 2013 +0100
26.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
26.3 @@ -1,369 +0,0 @@
26.4 -/**
26.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
26.6 - *
26.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
26.8 - *
26.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
26.10 - * Other names may be trademarks of their respective owners.
26.11 - *
26.12 - * The contents of this file are subject to the terms of either the GNU
26.13 - * General Public License Version 2 only ("GPL") or the Common
26.14 - * Development and Distribution License("CDDL") (collectively, the
26.15 - * "License"). You may not use this file except in compliance with the
26.16 - * License. You can obtain a copy of the License at
26.17 - * http://www.netbeans.org/cddl-gplv2.html
26.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
26.19 - * specific language governing permissions and limitations under the
26.20 - * License. When distributing the software, include this License Header
26.21 - * Notice in each file and include the License file at
26.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
26.23 - * particular file as subject to the "Classpath" exception as provided
26.24 - * by Oracle in the GPL Version 2 section of the License file that
26.25 - * accompanied this code. If applicable, add the following below the
26.26 - * License Header, with the fields enclosed by brackets [] replaced by
26.27 - * your own identifying information:
26.28 - * "Portions Copyrighted [year] [name of copyright owner]"
26.29 - *
26.30 - * Contributor(s):
26.31 - *
26.32 - * The Original Software is NetBeans. The Initial Developer of the Original
26.33 - * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
26.34 - *
26.35 - * If you wish your version of this file to be governed by only the CDDL
26.36 - * or only the GPL Version 2, indicate your decision by adding
26.37 - * "[Contributor] elects to include this software in this distribution
26.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
26.39 - * single choice of license, a recipient has the option to distribute
26.40 - * your version of this file under either the CDDL, the GPL Version 2 or
26.41 - * to extend the choice of license to its licensees as provided above.
26.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
26.43 - * Version 2 license, then the option applies only if the new code is
26.44 - * made subject to such option by the copyright holder.
26.45 - */
26.46 -package org.apidesign.html.boot.impl;
26.47 -
26.48 -import java.io.IOException;
26.49 -import java.io.Writer;
26.50 -import java.util.Collections;
26.51 -import java.util.HashMap;
26.52 -import java.util.HashSet;
26.53 -import java.util.List;
26.54 -import java.util.Map;
26.55 -import java.util.Set;
26.56 -import java.util.TreeMap;
26.57 -import javax.annotation.processing.AbstractProcessor;
26.58 -import javax.annotation.processing.Completion;
26.59 -import javax.annotation.processing.Completions;
26.60 -import javax.annotation.processing.Messager;
26.61 -import javax.annotation.processing.Processor;
26.62 -import javax.annotation.processing.RoundEnvironment;
26.63 -import javax.lang.model.SourceVersion;
26.64 -import javax.lang.model.element.AnnotationMirror;
26.65 -import javax.lang.model.element.Element;
26.66 -import javax.lang.model.element.ElementKind;
26.67 -import javax.lang.model.element.ExecutableElement;
26.68 -import javax.lang.model.element.Modifier;
26.69 -import javax.lang.model.element.PackageElement;
26.70 -import javax.lang.model.element.TypeElement;
26.71 -import javax.lang.model.element.VariableElement;
26.72 -import javax.lang.model.type.ArrayType;
26.73 -import javax.lang.model.type.ExecutableType;
26.74 -import javax.lang.model.type.TypeKind;
26.75 -import javax.lang.model.type.TypeMirror;
26.76 -import javax.tools.Diagnostic;
26.77 -import javax.tools.FileObject;
26.78 -import javax.tools.StandardLocation;
26.79 -import net.java.html.js.JavaScriptBody;
26.80 -import net.java.html.js.JavaScriptResource;
26.81 -import org.openide.util.lookup.ServiceProvider;
26.82 -
26.83 -/**
26.84 - *
26.85 - * @author Jaroslav Tulach <jtulach@netbeans.org>
26.86 - */
26.87 -@ServiceProvider(service = Processor.class)
26.88 -public final class JavaScriptProcesor extends AbstractProcessor {
26.89 - private final Map<String,Map<String,ExecutableElement>> javacalls =
26.90 - new HashMap<String,Map<String,ExecutableElement>>();
26.91 -
26.92 - @Override
26.93 - public Set<String> getSupportedAnnotationTypes() {
26.94 - Set<String> set = new HashSet<String>();
26.95 - set.add(JavaScriptBody.class.getName());
26.96 - set.add(JavaScriptResource.class.getName());
26.97 - return set;
26.98 - }
26.99 -
26.100 - @Override
26.101 - public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
26.102 - final Messager msg = processingEnv.getMessager();
26.103 - for (Element e : roundEnv.getElementsAnnotatedWith(JavaScriptBody.class)) {
26.104 - if (e.getKind() != ElementKind.METHOD && e.getKind() != ElementKind.CONSTRUCTOR) {
26.105 - continue;
26.106 - }
26.107 - ExecutableElement ee = (ExecutableElement)e;
26.108 - List<? extends VariableElement> params = ee.getParameters();
26.109 -
26.110 - JavaScriptBody jsb = e.getAnnotation(JavaScriptBody.class);
26.111 - if (jsb == null) {
26.112 - continue;
26.113 - }
26.114 - String[] arr = jsb.args();
26.115 - if (params.size() != arr.length) {
26.116 - msg.printMessage(Diagnostic.Kind.ERROR, "Number of args arguments does not match real arguments!", e);
26.117 - }
26.118 - if (!jsb.javacall() && jsb.body().contains(".@")) {
26.119 - msg.printMessage(Diagnostic.Kind.WARNING, "Usage of .@ usually requires javacall=true", e);
26.120 - }
26.121 - if (jsb.javacall()) {
26.122 - JsCallback verify = new VerifyCallback(e);
26.123 - try {
26.124 - verify.parse(jsb.body());
26.125 - } catch (IllegalStateException ex) {
26.126 - msg.printMessage(Diagnostic.Kind.ERROR, ex.getLocalizedMessage(), e);
26.127 - }
26.128 - }
26.129 - }
26.130 - for (Element e : roundEnv.getElementsAnnotatedWith(JavaScriptResource.class)) {
26.131 - JavaScriptResource r = e.getAnnotation(JavaScriptResource.class);
26.132 - if (r == null) {
26.133 - continue;
26.134 - }
26.135 - final String res;
26.136 - if (r.value().startsWith("/")) {
26.137 - res = r.value();
26.138 - } else {
26.139 - res = findPkg(e).replace('.', '/') + "/" + r.value();
26.140 - }
26.141 -
26.142 - try {
26.143 - FileObject os = processingEnv.getFiler().getResource(StandardLocation.SOURCE_PATH, "", res);
26.144 - os.openInputStream().close();
26.145 - } catch (IOException ex1) {
26.146 - try {
26.147 - FileObject os2 = processingEnv.getFiler().getResource(StandardLocation.CLASS_OUTPUT, "", res);
26.148 - os2.openInputStream().close();
26.149 - } catch (IOException ex2) {
26.150 - msg.printMessage(Diagnostic.Kind.ERROR, "Cannot find " + res + " in " + res + " package", e);
26.151 - }
26.152 - }
26.153 - }
26.154 -
26.155 - if (roundEnv.processingOver()) {
26.156 - generateCallbackClass(javacalls);
26.157 - javacalls.clear();
26.158 - }
26.159 - return true;
26.160 - }
26.161 -
26.162 - @Override
26.163 - public Iterable<? extends Completion> getCompletions(Element e,
26.164 - AnnotationMirror annotation, ExecutableElement member, String userText
26.165 - ) {
26.166 - StringBuilder sb = new StringBuilder();
26.167 - if (e.getKind() == ElementKind.METHOD && member.getSimpleName().contentEquals("args")) {
26.168 - ExecutableElement ee = (ExecutableElement) e;
26.169 - String sep = "";
26.170 - sb.append("{ ");
26.171 - for (VariableElement ve : ee.getParameters()) {
26.172 - sb.append(sep).append('"').append(ve.getSimpleName())
26.173 - .append('"');
26.174 - sep = ", ";
26.175 - }
26.176 - sb.append(" }");
26.177 - return Collections.nCopies(1, Completions.of(sb.toString()));
26.178 - }
26.179 - return null;
26.180 - }
26.181 -
26.182 - private class VerifyCallback extends JsCallback {
26.183 - private final Element e;
26.184 - public VerifyCallback(Element e) {
26.185 - this.e = e;
26.186 - }
26.187 -
26.188 - @Override
26.189 - protected CharSequence callMethod(String ident, String fqn, String method, String params) {
26.190 - final TypeElement type = processingEnv.getElementUtils().getTypeElement(fqn);
26.191 - if (type == null) {
26.192 - processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
26.193 - "Callback to non-existing class " + fqn, e
26.194 - );
26.195 - return "";
26.196 - }
26.197 - ExecutableElement found = null;
26.198 - StringBuilder foundParams = new StringBuilder();
26.199 - for (Element m : type.getEnclosedElements()) {
26.200 - if (m.getKind() != ElementKind.METHOD) {
26.201 - continue;
26.202 - }
26.203 - if (m.getSimpleName().contentEquals(method)) {
26.204 - String paramTypes = findParamTypes((ExecutableElement)m);
26.205 - if (paramTypes.equals(params)) {
26.206 - found = (ExecutableElement) m;
26.207 - break;
26.208 - }
26.209 - foundParams.append(paramTypes).append("\n");
26.210 - }
26.211 - }
26.212 - if (found == null) {
26.213 - if (foundParams.length() == 0) {
26.214 - processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
26.215 - "Callback to class " + fqn + " with unknown method " + method, e
26.216 - );
26.217 - } else {
26.218 - processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
26.219 - "Callback to " + fqn + "." + method + " with wrong parameters: " +
26.220 - params + ". Only known parameters are " + foundParams, e
26.221 - );
26.222 - }
26.223 - } else {
26.224 - Map<String,ExecutableElement> mangledOnes = javacalls.get(findPkg(e));
26.225 - if (mangledOnes == null) {
26.226 - mangledOnes = new TreeMap<String, ExecutableElement>();
26.227 - javacalls.put(findPkg(e), mangledOnes);
26.228 - }
26.229 - String mangled = JsCallback.mangle(fqn, method, findParamTypes(found));
26.230 - mangledOnes.put(mangled, found);
26.231 - }
26.232 - return "";
26.233 - }
26.234 -
26.235 - private String findParamTypes(ExecutableElement method) {
26.236 - ExecutableType t = (ExecutableType) method.asType();
26.237 - StringBuilder sb = new StringBuilder();
26.238 - sb.append('(');
26.239 - for (TypeMirror tm : t.getParameterTypes()) {
26.240 - if (tm.getKind().isPrimitive()) {
26.241 - switch (tm.getKind()) {
26.242 - case INT: sb.append('I'); break;
26.243 - case BOOLEAN: sb.append('Z'); break;
26.244 - case BYTE: sb.append('B'); break;
26.245 - case CHAR: sb.append('C'); break;
26.246 - case SHORT: sb.append('S'); break;
26.247 - case DOUBLE: sb.append('D'); break;
26.248 - case FLOAT: sb.append('F'); break;
26.249 - case LONG: sb.append('J'); break;
26.250 - default:
26.251 - throw new IllegalStateException("Uknown " + tm.getKind());
26.252 - }
26.253 - } else {
26.254 - while (tm.getKind() == TypeKind.ARRAY) {
26.255 - sb.append('[');
26.256 - tm = ((ArrayType)tm).getComponentType();
26.257 - }
26.258 - sb.append('L');
26.259 - sb.append(tm.toString().replace('.', '/'));
26.260 - sb.append(';');
26.261 - }
26.262 - }
26.263 - sb.append(')');
26.264 - return sb.toString();
26.265 - }
26.266 - }
26.267 -
26.268 - private void generateCallbackClass(Map<String,Map<String, ExecutableElement>> process) {
26.269 - for (Map.Entry<String, Map<String, ExecutableElement>> pkgEn : process.entrySet()) {
26.270 - String pkgName = pkgEn.getKey();
26.271 - Map<String, ExecutableElement> map = pkgEn.getValue();
26.272 - StringBuilder source = new StringBuilder();
26.273 - source.append("package ").append(pkgName).append(";\n");
26.274 - source.append("public final class $JsCallbacks$ {\n");
26.275 - source.append(" static final $JsCallbacks$ VM = new $JsCallbacks$(null);\n");
26.276 - source.append(" private final org.apidesign.html.boot.spi.Fn.Presenter p;\n");
26.277 - source.append(" private $JsCallbacks$ last;\n");
26.278 - source.append(" private $JsCallbacks$(org.apidesign.html.boot.spi.Fn.Presenter p) {\n");
26.279 - source.append(" this.p = p;\n");
26.280 - source.append(" }\n");
26.281 - source.append(" final $JsCallbacks$ current() {\n");
26.282 - source.append(" org.apidesign.html.boot.spi.Fn.Presenter now = org.apidesign.html.boot.spi.Fn.activePresenter();\n");
26.283 - source.append(" if (now == p) return this;\n");
26.284 - source.append(" if (last != null && now == last.p) return last;\n");
26.285 - source.append(" return last = new $JsCallbacks$(now);\n");
26.286 - source.append(" }\n");
26.287 - for (Map.Entry<String, ExecutableElement> entry : map.entrySet()) {
26.288 - final String mangled = entry.getKey();
26.289 - final ExecutableElement m = entry.getValue();
26.290 - final boolean isStatic = m.getModifiers().contains(Modifier.STATIC);
26.291 -
26.292 - source.append("\n public java.lang.Object ")
26.293 - .append(mangled)
26.294 - .append("(");
26.295 -
26.296 - String sep = "";
26.297 - if (!isStatic) {
26.298 - source.append(((TypeElement)m.getEnclosingElement()).getQualifiedName());
26.299 - source.append(" self");
26.300 - sep = ", ";
26.301 - }
26.302 -
26.303 - int cnt = 0;
26.304 - for (VariableElement ve : m.getParameters()) {
26.305 - source.append(sep);
26.306 - source.append(ve.asType());
26.307 - source.append(" arg").append(++cnt);
26.308 - sep = ", ";
26.309 - }
26.310 - source.append(") throws Throwable {\n");
26.311 - if (processingEnv.getSourceVersion().compareTo(SourceVersion.RELEASE_7) >= 0) {
26.312 - source.append(" try (java.io.Closeable a = org.apidesign.html.boot.spi.Fn.activate(p)) { \n");
26.313 - } else {
26.314 - source.append(" java.io.Closeable a = org.apidesign.html.boot.spi.Fn.activate(p); try {\n");
26.315 - }
26.316 - source.append(" ");
26.317 - if (m.getReturnType().getKind() != TypeKind.VOID) {
26.318 - source.append("return ");
26.319 - }
26.320 - if (isStatic) {
26.321 - source.append(((TypeElement)m.getEnclosingElement()).getQualifiedName());
26.322 - source.append('.');
26.323 - } else {
26.324 - source.append("self.");
26.325 - }
26.326 - source.append(m.getSimpleName());
26.327 - source.append("(");
26.328 - cnt = 0;
26.329 - sep = "";
26.330 - for (VariableElement ve : m.getParameters()) {
26.331 - source.append(sep);
26.332 - source.append("arg").append(++cnt);
26.333 - sep = ", ";
26.334 - }
26.335 - source.append(");\n");
26.336 - if (m.getReturnType().getKind() == TypeKind.VOID) {
26.337 - source.append(" return null;\n");
26.338 - }
26.339 - if (processingEnv.getSourceVersion().compareTo(SourceVersion.RELEASE_7) >= 0) {
26.340 - source.append(" }\n");
26.341 - } else {
26.342 -
26.343 - source.append(" } finally {\n");
26.344 - source.append(" a.close();\n");
26.345 - source.append(" }\n");
26.346 - }
26.347 - source.append(" }\n");
26.348 - }
26.349 - source.append("}\n");
26.350 - final String srcName = pkgName + ".$JsCallbacks$";
26.351 - try {
26.352 - Writer w = processingEnv.getFiler().createSourceFile(srcName,
26.353 - map.values().toArray(new Element[map.size()])
26.354 - ).openWriter();
26.355 - w.write(source.toString());
26.356 - w.close();
26.357 - } catch (IOException ex) {
26.358 - processingEnv.getMessager().printMessage(
26.359 - Diagnostic.Kind.ERROR, "Can't write " + srcName + ": " + ex.getMessage()
26.360 - );
26.361 - }
26.362 - }
26.363 - }
26.364 -
26.365 - private static String findPkg(Element e) {
26.366 - while (e.getKind() != ElementKind.PACKAGE) {
26.367 - e = e.getEnclosingElement();
26.368 - }
26.369 - return ((PackageElement)e).getQualifiedName().toString();
26.370 - }
26.371 -
26.372 -}
27.1 --- a/boot/src/main/java/org/apidesign/html/boot/impl/JsAgent.java Mon Dec 16 15:48:09 2013 +0100
27.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
27.3 @@ -1,67 +0,0 @@
27.4 -/**
27.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
27.6 - *
27.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
27.8 - *
27.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
27.10 - * Other names may be trademarks of their respective owners.
27.11 - *
27.12 - * The contents of this file are subject to the terms of either the GNU
27.13 - * General Public License Version 2 only ("GPL") or the Common
27.14 - * Development and Distribution License("CDDL") (collectively, the
27.15 - * "License"). You may not use this file except in compliance with the
27.16 - * License. You can obtain a copy of the License at
27.17 - * http://www.netbeans.org/cddl-gplv2.html
27.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
27.19 - * specific language governing permissions and limitations under the
27.20 - * License. When distributing the software, include this License Header
27.21 - * Notice in each file and include the License file at
27.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
27.23 - * particular file as subject to the "Classpath" exception as provided
27.24 - * by Oracle in the GPL Version 2 section of the License file that
27.25 - * accompanied this code. If applicable, add the following below the
27.26 - * License Header, with the fields enclosed by brackets [] replaced by
27.27 - * your own identifying information:
27.28 - * "Portions Copyrighted [year] [name of copyright owner]"
27.29 - *
27.30 - * Contributor(s):
27.31 - *
27.32 - * The Original Software is NetBeans. The Initial Developer of the Original
27.33 - * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
27.34 - *
27.35 - * If you wish your version of this file to be governed by only the CDDL
27.36 - * or only the GPL Version 2, indicate your decision by adding
27.37 - * "[Contributor] elects to include this software in this distribution
27.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
27.39 - * single choice of license, a recipient has the option to distribute
27.40 - * your version of this file under either the CDDL, the GPL Version 2 or
27.41 - * to extend the choice of license to its licensees as provided above.
27.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
27.43 - * Version 2 license, then the option applies only if the new code is
27.44 - * made subject to such option by the copyright holder.
27.45 - */
27.46 -package org.apidesign.html.boot.impl;
27.47 -
27.48 -import java.lang.instrument.ClassFileTransformer;
27.49 -import java.lang.instrument.IllegalClassFormatException;
27.50 -import java.lang.instrument.Instrumentation;
27.51 -import java.security.ProtectionDomain;
27.52 -
27.53 -/**
27.54 - *
27.55 - * @author Jaroslav Tulach <jtulach@netbeans.org>
27.56 - */
27.57 -public final class JsAgent implements ClassFileTransformer {
27.58 - public static void agentmain(String args, Instrumentation instr) {
27.59 - instr.addTransformer(new JsAgent());
27.60 - }
27.61 -
27.62 - @Override
27.63 - public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
27.64 - try {
27.65 - return FnUtils.transform(loader, classfileBuffer);
27.66 - } catch (Exception ex) {
27.67 - return classfileBuffer;
27.68 - }
27.69 - }
27.70 -}
28.1 --- a/boot/src/main/java/org/apidesign/html/boot/impl/JsCallback.java Mon Dec 16 15:48:09 2013 +0100
28.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
28.3 @@ -1,160 +0,0 @@
28.4 -/**
28.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
28.6 - *
28.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
28.8 - *
28.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
28.10 - * Other names may be trademarks of their respective owners.
28.11 - *
28.12 - * The contents of this file are subject to the terms of either the GNU
28.13 - * General Public License Version 2 only ("GPL") or the Common
28.14 - * Development and Distribution License("CDDL") (collectively, the
28.15 - * "License"). You may not use this file except in compliance with the
28.16 - * License. You can obtain a copy of the License at
28.17 - * http://www.netbeans.org/cddl-gplv2.html
28.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
28.19 - * specific language governing permissions and limitations under the
28.20 - * License. When distributing the software, include this License Header
28.21 - * Notice in each file and include the License file at
28.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
28.23 - * particular file as subject to the "Classpath" exception as provided
28.24 - * by Oracle in the GPL Version 2 section of the License file that
28.25 - * accompanied this code. If applicable, add the following below the
28.26 - * License Header, with the fields enclosed by brackets [] replaced by
28.27 - * your own identifying information:
28.28 - * "Portions Copyrighted [year] [name of copyright owner]"
28.29 - *
28.30 - * Contributor(s):
28.31 - *
28.32 - * The Original Software is NetBeans. The Initial Developer of the Original
28.33 - * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
28.34 - *
28.35 - * If you wish your version of this file to be governed by only the CDDL
28.36 - * or only the GPL Version 2, indicate your decision by adding
28.37 - * "[Contributor] elects to include this software in this distribution
28.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
28.39 - * single choice of license, a recipient has the option to distribute
28.40 - * your version of this file under either the CDDL, the GPL Version 2 or
28.41 - * to extend the choice of license to its licensees as provided above.
28.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
28.43 - * Version 2 license, then the option applies only if the new code is
28.44 - * made subject to such option by the copyright holder.
28.45 - */
28.46 -package org.apidesign.html.boot.impl;
28.47 -
28.48 -
28.49 -/**
28.50 - *
28.51 - * @author Jaroslav Tulach <jtulach@netbeans.org>
28.52 - */
28.53 -abstract class JsCallback {
28.54 - final String parse(String body) {
28.55 - StringBuilder sb = new StringBuilder();
28.56 - int pos = 0;
28.57 - for (;;) {
28.58 - int next = body.indexOf(".@", pos);
28.59 - if (next == -1) {
28.60 - sb.append(body.substring(pos));
28.61 - body = sb.toString();
28.62 - break;
28.63 - }
28.64 - int ident = next;
28.65 - while (ident > 0) {
28.66 - if (!Character.isJavaIdentifierPart(body.charAt(--ident))) {
28.67 - ident++;
28.68 - break;
28.69 - }
28.70 - }
28.71 - String refId = body.substring(ident, next);
28.72 -
28.73 - sb.append(body.substring(pos, ident));
28.74 -
28.75 - int sigBeg = body.indexOf('(', next);
28.76 - int sigEnd = body.indexOf(')', sigBeg);
28.77 - int colon4 = body.indexOf("::", next);
28.78 - if (sigBeg == -1 || sigEnd == -1 || colon4 == -1) {
28.79 - throw new IllegalStateException(
28.80 - "Wrong format of instance callback. "
28.81 - + "Should be: 'inst.@pkg.Class::method(Ljava/lang/Object;)(param)':\n"
28.82 - + body
28.83 - );
28.84 - }
28.85 - String fqn = body.substring(next + 2, colon4);
28.86 - String method = body.substring(colon4 + 2, sigBeg);
28.87 - String params = body.substring(sigBeg, sigEnd + 1);
28.88 -
28.89 - int paramBeg = body.indexOf('(', sigEnd + 1);
28.90 - if (paramBeg == -1) {
28.91 - throw new IllegalStateException(
28.92 - "Wrong format of instance callback. "
28.93 - + "Should be: 'inst.@pkg.Class::method(Ljava/lang/Object;)(param)':\n"
28.94 - + body
28.95 - );
28.96 - }
28.97 -
28.98 - sb.append(callMethod(refId, fqn, method, params));
28.99 - if (body.charAt(paramBeg + 1) != (')')) {
28.100 - sb.append(",");
28.101 - }
28.102 - pos = paramBeg + 1;
28.103 - }
28.104 - pos = 0;
28.105 - sb = null;
28.106 - for (;;) {
28.107 - int next = body.indexOf("@", pos);
28.108 - if (next == -1) {
28.109 - if (sb == null) {
28.110 - return body;
28.111 - }
28.112 - sb.append(body.substring(pos));
28.113 - return sb.toString();
28.114 - }
28.115 - if (sb == null) {
28.116 - sb = new StringBuilder();
28.117 - }
28.118 -
28.119 - sb.append(body.substring(pos, next));
28.120 -
28.121 - int sigBeg = body.indexOf('(', next);
28.122 - int sigEnd = body.indexOf(')', sigBeg);
28.123 - int colon4 = body.indexOf("::", next);
28.124 - if (sigBeg == -1 || sigEnd == -1 || colon4 == -1) {
28.125 - throw new IllegalStateException(
28.126 - "Wrong format of static callback. "
28.127 - + "Should be: '@pkg.Class::staticMethod(Ljava/lang/Object;)(param)':\n"
28.128 - + body
28.129 - );
28.130 - }
28.131 - String fqn = body.substring(next + 1, colon4);
28.132 - String method = body.substring(colon4 + 2, sigBeg);
28.133 - String params = body.substring(sigBeg, sigEnd + 1);
28.134 -
28.135 - int paramBeg = body.indexOf('(', sigEnd + 1);
28.136 -
28.137 - sb.append(callMethod(null, fqn, method, params));
28.138 - pos = paramBeg + 1;
28.139 - }
28.140 - }
28.141 -
28.142 - protected abstract CharSequence callMethod(
28.143 - String ident, String fqn, String method, String params
28.144 - );
28.145 -
28.146 - static String mangle(String fqn, String method, String params) {
28.147 - if (params.startsWith("(")) {
28.148 - params = params.substring(1);
28.149 - }
28.150 - if (params.endsWith(")")) {
28.151 - params = params.substring(0, params.length() - 1);
28.152 - }
28.153 - return
28.154 - replace(fqn) + "$" + replace(method) + "$" + replace(params);
28.155 - }
28.156 -
28.157 - private static String replace(String orig) {
28.158 - return orig.replace("_", "_1").
28.159 - replace(";", "_2").
28.160 - replace("[", "_3").
28.161 - replace('.', '_').replace('/', '_');
28.162 - }
28.163 -}
29.1 --- a/boot/src/main/java/org/apidesign/html/boot/impl/JsClassLoader.java Mon Dec 16 15:48:09 2013 +0100
29.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
29.3 @@ -1,133 +0,0 @@
29.4 -/**
29.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
29.6 - *
29.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
29.8 - *
29.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
29.10 - * Other names may be trademarks of their respective owners.
29.11 - *
29.12 - * The contents of this file are subject to the terms of either the GNU
29.13 - * General Public License Version 2 only ("GPL") or the Common
29.14 - * Development and Distribution License("CDDL") (collectively, the
29.15 - * "License"). You may not use this file except in compliance with the
29.16 - * License. You can obtain a copy of the License at
29.17 - * http://www.netbeans.org/cddl-gplv2.html
29.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
29.19 - * specific language governing permissions and limitations under the
29.20 - * License. When distributing the software, include this License Header
29.21 - * Notice in each file and include the License file at
29.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
29.23 - * particular file as subject to the "Classpath" exception as provided
29.24 - * by Oracle in the GPL Version 2 section of the License file that
29.25 - * accompanied this code. If applicable, add the following below the
29.26 - * License Header, with the fields enclosed by brackets [] replaced by
29.27 - * your own identifying information:
29.28 - * "Portions Copyrighted [year] [name of copyright owner]"
29.29 - *
29.30 - * Contributor(s):
29.31 - *
29.32 - * The Original Software is NetBeans. The Initial Developer of the Original
29.33 - * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
29.34 - *
29.35 - * If you wish your version of this file to be governed by only the CDDL
29.36 - * or only the GPL Version 2, indicate your decision by adding
29.37 - * "[Contributor] elects to include this software in this distribution
29.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
29.39 - * single choice of license, a recipient has the option to distribute
29.40 - * your version of this file under either the CDDL, the GPL Version 2 or
29.41 - * to extend the choice of license to its licensees as provided above.
29.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
29.43 - * Version 2 license, then the option applies only if the new code is
29.44 - * made subject to such option by the copyright holder.
29.45 - */
29.46 -package org.apidesign.html.boot.impl;
29.47 -
29.48 -import org.apidesign.html.boot.spi.Fn;
29.49 -import java.io.IOException;
29.50 -import java.io.InputStream;
29.51 -import java.io.Reader;
29.52 -import java.net.URL;
29.53 -import java.util.Enumeration;
29.54 -
29.55 -/**
29.56 - *
29.57 - * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
29.58 - */
29.59 -abstract class JsClassLoader extends ClassLoader {
29.60 - JsClassLoader(ClassLoader parent) {
29.61 - super(parent);
29.62 - setDefaultAssertionStatus(JsClassLoader.class.desiredAssertionStatus());
29.63 - }
29.64 -
29.65 - @Override
29.66 - protected abstract URL findResource(String name);
29.67 -
29.68 - @Override
29.69 - protected abstract Enumeration<URL> findResources(String name);
29.70 -
29.71 - @Override
29.72 - protected Class<?> findClass(String name) throws ClassNotFoundException {
29.73 - if (name.startsWith("javafx")) {
29.74 - return Class.forName(name);
29.75 - }
29.76 - if (name.startsWith("netscape")) {
29.77 - return Class.forName(name);
29.78 - }
29.79 - if (name.startsWith("com.sun")) {
29.80 - return Class.forName(name);
29.81 - }
29.82 - if (name.equals(JsClassLoader.class.getName())) {
29.83 - return JsClassLoader.class;
29.84 - }
29.85 - if (name.equals(Fn.class.getName())) {
29.86 - return Fn.class;
29.87 - }
29.88 - if (name.equals(Fn.Presenter.class.getName())) {
29.89 - return Fn.Presenter.class;
29.90 - }
29.91 - if (name.equals(FnUtils.class.getName())) {
29.92 - return FnUtils.class;
29.93 - }
29.94 - if (
29.95 - name.equals("org.apidesign.html.boot.spi.Fn") ||
29.96 - name.equals("org.apidesign.html.boot.impl.FnUtils") ||
29.97 - name.equals("org.apidesign.html.boot.impl.FnContext")
29.98 - ) {
29.99 - return Class.forName(name);
29.100 - }
29.101 - URL u = findResource(name.replace('.', '/') + ".class");
29.102 - if (u != null) {
29.103 - InputStream is = null;
29.104 - try {
29.105 - is = u.openStream();
29.106 - byte[] arr = new byte[is.available()];
29.107 - int len = 0;
29.108 - while (len < arr.length) {
29.109 - int read = is.read(arr, len, arr.length - len);
29.110 - if (read == -1) {
29.111 - throw new IOException("Can't read " + u);
29.112 - }
29.113 - len += read;
29.114 - }
29.115 - is.close();
29.116 - is = null;
29.117 - arr = FnUtils.transform(JsClassLoader.this, arr);
29.118 - if (arr != null) {
29.119 - return defineClass(name, arr, 0, arr.length);
29.120 - }
29.121 - } catch (IOException ex) {
29.122 - throw new ClassNotFoundException("Can't load " + name, ex);
29.123 - } finally {
29.124 - try {
29.125 - if (is != null) is.close();
29.126 - } catch (IOException ex) {
29.127 - throw new ClassNotFoundException(null, ex);
29.128 - }
29.129 - }
29.130 - }
29.131 - return super.findClass(name);
29.132 - }
29.133 -
29.134 - protected abstract Fn defineFn(String code, String... names);
29.135 - protected abstract void loadScript(Reader code) throws Exception;
29.136 -}
30.1 --- a/boot/src/main/java/org/apidesign/html/boot/impl/Test.java Mon Dec 16 15:48:09 2013 +0100
30.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
30.3 @@ -1,57 +0,0 @@
30.4 -/**
30.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
30.6 - *
30.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
30.8 - *
30.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
30.10 - * Other names may be trademarks of their respective owners.
30.11 - *
30.12 - * The contents of this file are subject to the terms of either the GNU
30.13 - * General Public License Version 2 only ("GPL") or the Common
30.14 - * Development and Distribution License("CDDL") (collectively, the
30.15 - * "License"). You may not use this file except in compliance with the
30.16 - * License. You can obtain a copy of the License at
30.17 - * http://www.netbeans.org/cddl-gplv2.html
30.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
30.19 - * specific language governing permissions and limitations under the
30.20 - * License. When distributing the software, include this License Header
30.21 - * Notice in each file and include the License file at
30.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
30.23 - * particular file as subject to the "Classpath" exception as provided
30.24 - * by Oracle in the GPL Version 2 section of the License file that
30.25 - * accompanied this code. If applicable, add the following below the
30.26 - * License Header, with the fields enclosed by brackets [] replaced by
30.27 - * your own identifying information:
30.28 - * "Portions Copyrighted [year] [name of copyright owner]"
30.29 - *
30.30 - * Contributor(s):
30.31 - *
30.32 - * The Original Software is NetBeans. The Initial Developer of the Original
30.33 - * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
30.34 - *
30.35 - * If you wish your version of this file to be governed by only the CDDL
30.36 - * or only the GPL Version 2, indicate your decision by adding
30.37 - * "[Contributor] elects to include this software in this distribution
30.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
30.39 - * single choice of license, a recipient has the option to distribute
30.40 - * your version of this file under either the CDDL, the GPL Version 2 or
30.41 - * to extend the choice of license to its licensees as provided above.
30.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
30.43 - * Version 2 license, then the option applies only if the new code is
30.44 - * made subject to such option by the copyright holder.
30.45 - */
30.46 -package org.apidesign.html.boot.impl;
30.47 -
30.48 -import java.util.concurrent.Callable;
30.49 -import net.java.html.js.JavaScriptBody;
30.50 -
30.51 -/**
30.52 - *
30.53 - * @author Jaroslav Tulach <jtulach@netbeans.org>
30.54 - */
30.55 -public final class Test implements Callable<Boolean> {
30.56 - @Override @JavaScriptBody(args = {}, body = "return true;")
30.57 - public Boolean call() {
30.58 - return false;
30.59 - }
30.60 -}
31.1 --- a/boot/src/main/java/org/apidesign/html/boot/spi/Fn.java Mon Dec 16 15:48:09 2013 +0100
31.2 +++ b/boot/src/main/java/org/apidesign/html/boot/spi/Fn.java Mon Dec 16 16:59:43 2013 +0100
31.3 @@ -51,9 +51,8 @@
31.4 import java.util.HashSet;
31.5 import java.util.Map;
31.6 import java.util.Set;
31.7 -import java.util.WeakHashMap;
31.8 import net.java.html.js.JavaScriptBody;
31.9 -import org.apidesign.html.boot.impl.FnContext;
31.10 +import org.netbeans.html.boot.impl.FnContext;
31.11
31.12 /** Represents single JavaScript function that can be invoked.
31.13 * Created via {@link Presenter#defineFn(java.lang.String, java.lang.String...)}.
32.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
32.2 +++ b/boot/src/main/java/org/netbeans/html/boot/impl/FindResources.java Mon Dec 16 16:59:43 2013 +0100
32.3 @@ -0,0 +1,56 @@
32.4 +/**
32.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
32.6 + *
32.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
32.8 + *
32.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
32.10 + * Other names may be trademarks of their respective owners.
32.11 + *
32.12 + * The contents of this file are subject to the terms of either the GNU
32.13 + * General Public License Version 2 only ("GPL") or the Common
32.14 + * Development and Distribution License("CDDL") (collectively, the
32.15 + * "License"). You may not use this file except in compliance with the
32.16 + * License. You can obtain a copy of the License at
32.17 + * http://www.netbeans.org/cddl-gplv2.html
32.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
32.19 + * specific language governing permissions and limitations under the
32.20 + * License. When distributing the software, include this License Header
32.21 + * Notice in each file and include the License file at
32.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
32.23 + * particular file as subject to the "Classpath" exception as provided
32.24 + * by Oracle in the GPL Version 2 section of the License file that
32.25 + * accompanied this code. If applicable, add the following below the
32.26 + * License Header, with the fields enclosed by brackets [] replaced by
32.27 + * your own identifying information:
32.28 + * "Portions Copyrighted [year] [name of copyright owner]"
32.29 + *
32.30 + * Contributor(s):
32.31 + *
32.32 + * The Original Software is NetBeans. The Initial Developer of the Original
32.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
32.34 + *
32.35 + * If you wish your version of this file to be governed by only the CDDL
32.36 + * or only the GPL Version 2, indicate your decision by adding
32.37 + * "[Contributor] elects to include this software in this distribution
32.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
32.39 + * single choice of license, a recipient has the option to distribute
32.40 + * your version of this file under either the CDDL, the GPL Version 2 or
32.41 + * to extend the choice of license to its licensees as provided above.
32.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
32.43 + * Version 2 license, then the option applies only if the new code is
32.44 + * made subject to such option by the copyright holder.
32.45 + */
32.46 +package org.netbeans.html.boot.impl;
32.47 +
32.48 +import java.net.URL;
32.49 +import java.util.Collection;
32.50 +
32.51 +/**
32.52 + *
32.53 + * @author Jaroslav Tulach <jtulach@netbeans.org>
32.54 + */
32.55 +public interface FindResources {
32.56 +
32.57 + public void findResources(String path, Collection<? super URL> results, boolean oneIsEnough);
32.58 +
32.59 +}
33.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
33.2 +++ b/boot/src/main/java/org/netbeans/html/boot/impl/FnContext.java Mon Dec 16 16:59:43 2013 +0100
33.3 @@ -0,0 +1,98 @@
33.4 +/**
33.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
33.6 + *
33.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
33.8 + *
33.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
33.10 + * Other names may be trademarks of their respective owners.
33.11 + *
33.12 + * The contents of this file are subject to the terms of either the GNU
33.13 + * General Public License Version 2 only ("GPL") or the Common
33.14 + * Development and Distribution License("CDDL") (collectively, the
33.15 + * "License"). You may not use this file except in compliance with the
33.16 + * License. You can obtain a copy of the License at
33.17 + * http://www.netbeans.org/cddl-gplv2.html
33.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
33.19 + * specific language governing permissions and limitations under the
33.20 + * License. When distributing the software, include this License Header
33.21 + * Notice in each file and include the License file at
33.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
33.23 + * particular file as subject to the "Classpath" exception as provided
33.24 + * by Oracle in the GPL Version 2 section of the License file that
33.25 + * accompanied this code. If applicable, add the following below the
33.26 + * License Header, with the fields enclosed by brackets [] replaced by
33.27 + * your own identifying information:
33.28 + * "Portions Copyrighted [year] [name of copyright owner]"
33.29 + *
33.30 + * Contributor(s):
33.31 + *
33.32 + * The Original Software is NetBeans. The Initial Developer of the Original
33.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
33.34 + *
33.35 + * If you wish your version of this file to be governed by only the CDDL
33.36 + * or only the GPL Version 2, indicate your decision by adding
33.37 + * "[Contributor] elects to include this software in this distribution
33.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
33.39 + * single choice of license, a recipient has the option to distribute
33.40 + * your version of this file under either the CDDL, the GPL Version 2 or
33.41 + * to extend the choice of license to its licensees as provided above.
33.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
33.43 + * Version 2 license, then the option applies only if the new code is
33.44 + * made subject to such option by the copyright holder.
33.45 + */
33.46 +package org.netbeans.html.boot.impl;
33.47 +
33.48 +import java.io.Closeable;
33.49 +import java.io.IOException;
33.50 +import java.util.logging.Logger;
33.51 +import org.apidesign.html.boot.spi.Fn;
33.52 +
33.53 +/**
33.54 + *
33.55 + * @author Jaroslav Tulach <jtulach@netbeans.org>
33.56 + */
33.57 +public final class FnContext implements Closeable {
33.58 + private static final Logger LOG = Logger.getLogger(FnContext.class.getName());
33.59 +
33.60 + private Object prev;
33.61 + private FnContext(Fn.Presenter p) {
33.62 + this.prev = p;
33.63 + }
33.64 +
33.65 + @Override
33.66 + public void close() throws IOException {
33.67 + if (prev != this) {
33.68 + currentPresenter((Fn.Presenter)prev);
33.69 + prev = this;
33.70 + }
33.71 + }
33.72 +/*
33.73 + @Override
33.74 + protected void finalize() throws Throwable {
33.75 + if (prev != null) {
33.76 + LOG.warning("Unclosed context!");
33.77 + }
33.78 + }
33.79 +*/
33.80 + public static Closeable activate(Fn.Presenter newP) {
33.81 + return new FnContext(currentPresenter(newP));
33.82 + }
33.83 +
33.84 +
33.85 + private static final ThreadLocal<Fn.Presenter> CURRENT = new ThreadLocal<Fn.Presenter>();
33.86 +
33.87 + public static Fn.Presenter currentPresenter(Fn.Presenter p) {
33.88 + Fn.Presenter prev = CURRENT.get();
33.89 + CURRENT.set(p);
33.90 + return prev;
33.91 + }
33.92 +
33.93 + public static Fn.Presenter currentPresenter() {
33.94 + Fn.Presenter p = CURRENT.get();
33.95 + if (p == null) {
33.96 + throw new IllegalStateException("No current WebView context around!");
33.97 + }
33.98 + return p;
33.99 + }
33.100 +
33.101 +}
34.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
34.2 +++ b/boot/src/main/java/org/netbeans/html/boot/impl/FnUtils.java Mon Dec 16 16:59:43 2013 +0100
34.3 @@ -0,0 +1,597 @@
34.4 +/**
34.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
34.6 + *
34.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
34.8 + *
34.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
34.10 + * Other names may be trademarks of their respective owners.
34.11 + *
34.12 + * The contents of this file are subject to the terms of either the GNU
34.13 + * General Public License Version 2 only ("GPL") or the Common
34.14 + * Development and Distribution License("CDDL") (collectively, the
34.15 + * "License"). You may not use this file except in compliance with the
34.16 + * License. You can obtain a copy of the License at
34.17 + * http://www.netbeans.org/cddl-gplv2.html
34.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
34.19 + * specific language governing permissions and limitations under the
34.20 + * License. When distributing the software, include this License Header
34.21 + * Notice in each file and include the License file at
34.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
34.23 + * particular file as subject to the "Classpath" exception as provided
34.24 + * by Oracle in the GPL Version 2 section of the License file that
34.25 + * accompanied this code. If applicable, add the following below the
34.26 + * License Header, with the fields enclosed by brackets [] replaced by
34.27 + * your own identifying information:
34.28 + * "Portions Copyrighted [year] [name of copyright owner]"
34.29 + *
34.30 + * Contributor(s):
34.31 + *
34.32 + * The Original Software is NetBeans. The Initial Developer of the Original
34.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
34.34 + *
34.35 + * If you wish your version of this file to be governed by only the CDDL
34.36 + * or only the GPL Version 2, indicate your decision by adding
34.37 + * "[Contributor] elects to include this software in this distribution
34.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
34.39 + * single choice of license, a recipient has the option to distribute
34.40 + * your version of this file under either the CDDL, the GPL Version 2 or
34.41 + * to extend the choice of license to its licensees as provided above.
34.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
34.43 + * Version 2 license, then the option applies only if the new code is
34.44 + * made subject to such option by the copyright holder.
34.45 + */
34.46 +package org.netbeans.html.boot.impl;
34.47 +
34.48 +import java.io.Closeable;
34.49 +import java.io.InputStream;
34.50 +import java.io.InputStreamReader;
34.51 +import java.io.Reader;
34.52 +import java.net.URL;
34.53 +import java.util.ArrayList;
34.54 +import java.util.Collections;
34.55 +import java.util.Enumeration;
34.56 +import java.util.List;
34.57 +import java.util.concurrent.Callable;
34.58 +import org.apidesign.html.boot.spi.Fn;
34.59 +import org.objectweb.asm.AnnotationVisitor;
34.60 +import org.objectweb.asm.ClassReader;
34.61 +import org.objectweb.asm.ClassVisitor;
34.62 +import org.objectweb.asm.ClassWriter;
34.63 +import org.objectweb.asm.Label;
34.64 +import org.objectweb.asm.MethodVisitor;
34.65 +import org.objectweb.asm.Opcodes;
34.66 +import org.objectweb.asm.Type;
34.67 +import org.objectweb.asm.signature.SignatureReader;
34.68 +import org.objectweb.asm.signature.SignatureVisitor;
34.69 +import org.objectweb.asm.signature.SignatureWriter;
34.70 +
34.71 +/**
34.72 + *
34.73 + * @author Jaroslav Tulach <jtulach@netbeans.org>
34.74 + */
34.75 +public final class FnUtils implements Fn.Presenter {
34.76 +
34.77 + private FnUtils() {
34.78 + }
34.79 +
34.80 + public static boolean isJavaScriptCapable(ClassLoader l) {
34.81 + if (l instanceof JsClassLoader) {
34.82 + return true;
34.83 + }
34.84 + Class<?> clazz;
34.85 + try (Closeable c = Fn.activate(new FnUtils())) {
34.86 + clazz = Class.forName(Test.class.getName(), true, l);
34.87 + final Object is = ((Callable<?>)clazz.newInstance()).call();
34.88 + return Boolean.TRUE.equals(is);
34.89 + } catch (Exception ex) {
34.90 + return false;
34.91 + }
34.92 + }
34.93 +
34.94 + public static boolean isValid(Fn fn) {
34.95 + return fn != null && fn.isValid();
34.96 + }
34.97 +
34.98 + public static ClassLoader newLoader(final FindResources f, final Fn.Presenter d, ClassLoader parent) {
34.99 + return new JsClassLoader(parent) {
34.100 + @Override
34.101 + protected URL findResource(String name) {
34.102 + List<URL> l = res(name, true);
34.103 + return l.isEmpty() ? null : l.get(0);
34.104 + }
34.105 +
34.106 + @Override
34.107 + protected Enumeration<URL> findResources(String name) {
34.108 + return Collections.enumeration(res(name, false));
34.109 + }
34.110 +
34.111 + private List<URL> res(String name, boolean oneIsEnough) {
34.112 + List<URL> l = new ArrayList<URL>();
34.113 + f.findResources(name, l, oneIsEnough);
34.114 + return l;
34.115 + }
34.116 +
34.117 + @Override
34.118 + protected Fn defineFn(String code, String... names) {
34.119 + return d.defineFn(code, names);
34.120 + }
34.121 +
34.122 + @Override
34.123 + protected void loadScript(Reader code) throws Exception {
34.124 + d.loadScript(code);
34.125 + }
34.126 + };
34.127 + }
34.128 +
34.129 + static String callback(final String body) {
34.130 + return new JsCallback() {
34.131 + @Override
34.132 + protected CharSequence callMethod(
34.133 + String ident, String fqn, String method, String params
34.134 + ) {
34.135 + StringBuilder sb = new StringBuilder();
34.136 + sb.append("vm.").append(mangle(fqn, method, params));
34.137 + sb.append("(");
34.138 + if (ident != null) {
34.139 + sb.append(ident);
34.140 + }
34.141 + return sb;
34.142 + }
34.143 +
34.144 + }.parse(body);
34.145 + }
34.146 +
34.147 + static void loadScript(ClassLoader jcl, String resource) {
34.148 + final InputStream script = jcl.getResourceAsStream(resource);
34.149 + if (script == null) {
34.150 + throw new NullPointerException("Can't find " + resource);
34.151 + }
34.152 + try {
34.153 + Reader isr = null;
34.154 + try {
34.155 + isr = new InputStreamReader(script, "UTF-8");
34.156 + FnContext.currentPresenter().loadScript(isr);
34.157 + } finally {
34.158 + if (isr != null) {
34.159 + isr.close();
34.160 + }
34.161 + }
34.162 + } catch (Exception ex) {
34.163 + throw new IllegalStateException("Can't execute " + resource, ex);
34.164 + }
34.165 + }
34.166 +
34.167 + @Override
34.168 + public Fn defineFn(String code, String... names) {
34.169 + return new TrueFn();
34.170 + }
34.171 +
34.172 + @Override
34.173 + public void displayPage(URL page, Runnable onPageLoad) {
34.174 + }
34.175 +
34.176 + @Override
34.177 + public void loadScript(Reader code) throws Exception {
34.178 + }
34.179 +
34.180 + private static final class FindInClass extends ClassVisitor {
34.181 + private String name;
34.182 + private int found;
34.183 + private ClassLoader loader;
34.184 + private String resource;
34.185 +
34.186 + public FindInClass(ClassLoader l, ClassVisitor cv) {
34.187 + super(Opcodes.ASM4, cv);
34.188 + this.loader = l;
34.189 + }
34.190 +
34.191 + @Override
34.192 + public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
34.193 + this.name = name;
34.194 + super.visit(version, access, name, signature, superName, interfaces);
34.195 + }
34.196 +
34.197 + @Override
34.198 + public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
34.199 + if ("Lnet/java/html/js/JavaScriptResource;".equals(desc)) {
34.200 + return new LoadResource();
34.201 + }
34.202 + return super.visitAnnotation(desc, visible);
34.203 + }
34.204 +
34.205 + @Override
34.206 + public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
34.207 + return new FindInMethod(access, name, desc,
34.208 + super.visitMethod(access & (~Opcodes.ACC_NATIVE), name, desc, signature, exceptions)
34.209 + );
34.210 + }
34.211 +
34.212 + private final class FindInMethod extends MethodVisitor {
34.213 +
34.214 + private final String name;
34.215 + private final String desc;
34.216 + private final int access;
34.217 + private List<String> args;
34.218 + private String body;
34.219 + private boolean bodyGenerated;
34.220 +
34.221 + public FindInMethod(int access, String name, String desc, MethodVisitor mv) {
34.222 + super(Opcodes.ASM4, mv);
34.223 + this.access = access;
34.224 + this.name = name;
34.225 + this.desc = desc;
34.226 + }
34.227 +
34.228 + @Override
34.229 + public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
34.230 + if ("Lnet/java/html/js/JavaScriptBody;".equals(desc) // NOI18N
34.231 + || "Lorg/apidesign/bck2brwsr/core/JavaScriptBody;".equals(desc) // NOI18N
34.232 + ) {
34.233 + found++;
34.234 + return new FindInAnno();
34.235 + }
34.236 + return super.visitAnnotation(desc, visible);
34.237 + }
34.238 +
34.239 + private void generateJSBody(List<String> args, String body) {
34.240 + this.args = args;
34.241 + this.body = body;
34.242 + }
34.243 +
34.244 + @Override
34.245 + public void visitCode() {
34.246 + if (body == null) {
34.247 + return;
34.248 + }
34.249 + generateBody();
34.250 + }
34.251 +
34.252 + private boolean generateBody() {
34.253 + if (bodyGenerated) {
34.254 + return false;
34.255 + }
34.256 + bodyGenerated = true;
34.257 +
34.258 + super.visitFieldInsn(
34.259 + Opcodes.GETSTATIC, FindInClass.this.name,
34.260 + "$$fn$$" + name + "_" + found,
34.261 + "Lorg/apidesign/html/boot/spi/Fn;"
34.262 + );
34.263 + super.visitInsn(Opcodes.DUP);
34.264 + super.visitMethodInsn(
34.265 + Opcodes.INVOKESTATIC,
34.266 + "org/apidesign/html/boot/spi/Fn", "isValid",
34.267 + "(Lorg/apidesign/html/boot/spi/Fn;)Z"
34.268 + );
34.269 + Label ifNotNull = new Label();
34.270 + super.visitJumpInsn(Opcodes.IFNE, ifNotNull);
34.271 +
34.272 + // init Fn
34.273 + super.visitInsn(Opcodes.POP);
34.274 + super.visitLdcInsn(Type.getObjectType(FindInClass.this.name));
34.275 + super.visitLdcInsn(body);
34.276 + super.visitIntInsn(Opcodes.SIPUSH, args.size());
34.277 + super.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/String");
34.278 + boolean needsVM = false;
34.279 + for (int i = 0; i < args.size(); i++) {
34.280 + assert !needsVM;
34.281 + String argName = args.get(i);
34.282 + needsVM = "vm".equals(argName);
34.283 + super.visitInsn(Opcodes.DUP);
34.284 + super.visitIntInsn(Opcodes.BIPUSH, i);
34.285 + super.visitLdcInsn(argName);
34.286 + super.visitInsn(Opcodes.AASTORE);
34.287 + }
34.288 + super.visitMethodInsn(Opcodes.INVOKESTATIC,
34.289 + "org/apidesign/html/boot/spi/Fn", "define",
34.290 + "(Ljava/lang/Class;Ljava/lang/String;[Ljava/lang/String;)Lorg/apidesign/html/boot/spi/Fn;"
34.291 + );
34.292 + if (resource != null) {
34.293 + super.visitLdcInsn(Type.getObjectType(FindInClass.this.name));
34.294 + super.visitLdcInsn(resource);
34.295 + super.visitMethodInsn(Opcodes.INVOKESTATIC,
34.296 + "org/apidesign/html/boot/spi/Fn", "preload",
34.297 + "(Lorg/apidesign/html/boot/spi/Fn;Ljava/lang/Class;Ljava/lang/String;)Lorg/apidesign/html/boot/spi/Fn;"
34.298 + );
34.299 + }
34.300 + super.visitInsn(Opcodes.DUP);
34.301 + super.visitFieldInsn(
34.302 + Opcodes.PUTSTATIC, FindInClass.this.name,
34.303 + "$$fn$$" + name + "_" + found,
34.304 + "Lorg/apidesign/html/boot/spi/Fn;"
34.305 + );
34.306 + // end of Fn init
34.307 +
34.308 + super.visitLabel(ifNotNull);
34.309 +
34.310 + final int offset;
34.311 + if ((access & Opcodes.ACC_STATIC) == 0) {
34.312 + offset = 1;
34.313 + super.visitIntInsn(Opcodes.ALOAD, 0);
34.314 + } else {
34.315 + offset = 0;
34.316 + super.visitInsn(Opcodes.ACONST_NULL);
34.317 + }
34.318 +
34.319 + super.visitIntInsn(Opcodes.SIPUSH, args.size());
34.320 + super.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object");
34.321 +
34.322 + class SV extends SignatureVisitor {
34.323 +
34.324 + private boolean nowReturn;
34.325 + private Type returnType;
34.326 + private int index;
34.327 + private int loadIndex = offset;
34.328 +
34.329 + public SV() {
34.330 + super(Opcodes.ASM4);
34.331 + }
34.332 +
34.333 + @Override
34.334 + public void visitBaseType(char descriptor) {
34.335 + final Type t = Type.getType("" + descriptor);
34.336 + if (nowReturn) {
34.337 + returnType = t;
34.338 + return;
34.339 + }
34.340 + FindInMethod.super.visitInsn(Opcodes.DUP);
34.341 + FindInMethod.super.visitIntInsn(Opcodes.SIPUSH, index++);
34.342 + FindInMethod.super.visitVarInsn(t.getOpcode(Opcodes.ILOAD), loadIndex++);
34.343 + String factory;
34.344 + switch (descriptor) {
34.345 + case 'I':
34.346 + factory = "java/lang/Integer";
34.347 + break;
34.348 + case 'J':
34.349 + factory = "java/lang/Long";
34.350 + loadIndex++;
34.351 + break;
34.352 + case 'S':
34.353 + factory = "java/lang/Short";
34.354 + break;
34.355 + case 'F':
34.356 + factory = "java/lang/Float";
34.357 + break;
34.358 + case 'D':
34.359 + factory = "java/lang/Double";
34.360 + loadIndex++;
34.361 + break;
34.362 + case 'Z':
34.363 + factory = "java/lang/Boolean";
34.364 + break;
34.365 + case 'C':
34.366 + factory = "java/lang/Character";
34.367 + break;
34.368 + case 'B':
34.369 + factory = "java/lang/Byte";
34.370 + break;
34.371 + default:
34.372 + throw new IllegalStateException(t.toString());
34.373 + }
34.374 + FindInMethod.super.visitMethodInsn(Opcodes.INVOKESTATIC,
34.375 + factory, "valueOf", "(" + descriptor + ")L" + factory + ";"
34.376 + );
34.377 + FindInMethod.super.visitInsn(Opcodes.AASTORE);
34.378 + }
34.379 +
34.380 + @Override
34.381 + public SignatureVisitor visitArrayType() {
34.382 + if (nowReturn) {
34.383 + throw new IllegalStateException("Not supported yet");
34.384 + }
34.385 + loadObject();
34.386 + return new SignatureWriter();
34.387 + }
34.388 +
34.389 + @Override
34.390 + public void visitClassType(String name) {
34.391 + if (nowReturn) {
34.392 + returnType = Type.getObjectType(name);
34.393 + return;
34.394 + }
34.395 + loadObject();
34.396 + }
34.397 +
34.398 + @Override
34.399 + public SignatureVisitor visitReturnType() {
34.400 + nowReturn = true;
34.401 + return this;
34.402 + }
34.403 +
34.404 + private void loadObject() {
34.405 + FindInMethod.super.visitInsn(Opcodes.DUP);
34.406 + FindInMethod.super.visitIntInsn(Opcodes.SIPUSH, index++);
34.407 + FindInMethod.super.visitVarInsn(Opcodes.ALOAD, loadIndex++);
34.408 + FindInMethod.super.visitInsn(Opcodes.AASTORE);
34.409 + }
34.410 +
34.411 + }
34.412 + SV sv = new SV();
34.413 + SignatureReader sr = new SignatureReader(desc);
34.414 + sr.accept(sv);
34.415 +
34.416 + if (needsVM) {
34.417 + FindInMethod.super.visitInsn(Opcodes.DUP);
34.418 + FindInMethod.super.visitIntInsn(Opcodes.SIPUSH, sv.index);
34.419 + int lastSlash = FindInClass.this.name.lastIndexOf('/');
34.420 + String jsCallbacks = FindInClass.this.name.substring(0, lastSlash + 1) + "$JsCallbacks$";
34.421 + FindInMethod.super.visitFieldInsn(Opcodes.GETSTATIC, jsCallbacks, "VM", "L" + jsCallbacks + ";");
34.422 + FindInMethod.super.visitMethodInsn(Opcodes.INVOKEVIRTUAL, jsCallbacks, "current", "()L" + jsCallbacks + ";");
34.423 + FindInMethod.super.visitInsn(Opcodes.AASTORE);
34.424 + }
34.425 +
34.426 + super.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
34.427 + "org/apidesign/html/boot/spi/Fn", "invoke", "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;"
34.428 + );
34.429 + switch (sv.returnType.getSort()) {
34.430 + case Type.VOID:
34.431 + super.visitInsn(Opcodes.RETURN);
34.432 + break;
34.433 + case Type.ARRAY:
34.434 + case Type.OBJECT:
34.435 + super.visitTypeInsn(Opcodes.CHECKCAST, sv.returnType.getInternalName());
34.436 + super.visitInsn(Opcodes.ARETURN);
34.437 + break;
34.438 + case Type.BOOLEAN:
34.439 + super.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Boolean");
34.440 + super.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
34.441 + "java/lang/Boolean", "booleanValue", "()Z"
34.442 + );
34.443 + super.visitInsn(Opcodes.IRETURN);
34.444 + break;
34.445 + default:
34.446 + super.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Number");
34.447 + super.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
34.448 + "java/lang/Number", sv.returnType.getClassName() + "Value", "()" + sv.returnType.getDescriptor()
34.449 + );
34.450 + super.visitInsn(sv.returnType.getOpcode(Opcodes.IRETURN));
34.451 + }
34.452 + return true;
34.453 + }
34.454 +
34.455 + @Override
34.456 + public void visitEnd() {
34.457 + super.visitEnd();
34.458 + if (body != null) {
34.459 + if (generateBody()) {
34.460 + // native method
34.461 + super.visitMaxs(1, 0);
34.462 + }
34.463 + FindInClass.this.visitField(
34.464 + Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC,
34.465 + "$$fn$$" + name + "_" + found,
34.466 + "Lorg/apidesign/html/boot/spi/Fn;",
34.467 + null, null
34.468 + );
34.469 + }
34.470 + }
34.471 +
34.472 + private final class FindInAnno extends AnnotationVisitor {
34.473 +
34.474 + private List<String> args = new ArrayList<String>();
34.475 + private String body;
34.476 + private boolean javacall = false;
34.477 +
34.478 + public FindInAnno() {
34.479 + super(Opcodes.ASM4);
34.480 + }
34.481 +
34.482 + @Override
34.483 + public void visit(String name, Object value) {
34.484 + if (name == null) {
34.485 + args.add((String) value);
34.486 + return;
34.487 + }
34.488 + if (name.equals("javacall")) { // NOI18N
34.489 + javacall = (Boolean) value;
34.490 + return;
34.491 + }
34.492 + assert name.equals("body");
34.493 + body = (String) value;
34.494 + }
34.495 +
34.496 + @Override
34.497 + public AnnotationVisitor visitArray(String name) {
34.498 + return this;
34.499 + }
34.500 +
34.501 + @Override
34.502 + public void visitEnd() {
34.503 + if (body != null) {
34.504 + if (javacall) {
34.505 + body = callback(body);
34.506 + args.add("vm");
34.507 + }
34.508 + generateJSBody(args, body);
34.509 + }
34.510 + }
34.511 + }
34.512 + }
34.513 +
34.514 + private final class LoadResource extends AnnotationVisitor {
34.515 +
34.516 + public LoadResource() {
34.517 + super(Opcodes.ASM4);
34.518 + }
34.519 +
34.520 + @Override
34.521 + public void visit(String attrName, Object value) {
34.522 + String relPath = (String) value;
34.523 + if (relPath.startsWith("/")) {
34.524 + resource = relPath;
34.525 + } else {
34.526 + int last = name.lastIndexOf('/');
34.527 + String fullPath = name.substring(0, last + 1) + relPath;
34.528 + resource = fullPath;
34.529 + }
34.530 + }
34.531 + }
34.532 + }
34.533 +
34.534 + private static class ClassWriterEx extends ClassWriter {
34.535 +
34.536 + private ClassLoader loader;
34.537 +
34.538 + public ClassWriterEx(ClassLoader l, ClassReader classReader, int flags) {
34.539 + super(classReader, flags);
34.540 + this.loader = l;
34.541 + }
34.542 +
34.543 + @Override
34.544 + protected String getCommonSuperClass(final String type1, final String type2) {
34.545 + Class<?> c, d;
34.546 + try {
34.547 + c = Class.forName(type1.replace('/', '.'), false, loader);
34.548 + d = Class.forName(type2.replace('/', '.'), false, loader);
34.549 + } catch (Exception e) {
34.550 + throw new RuntimeException(e.toString());
34.551 + }
34.552 + if (c.isAssignableFrom(d)) {
34.553 + return type1;
34.554 + }
34.555 + if (d.isAssignableFrom(c)) {
34.556 + return type2;
34.557 + }
34.558 + if (c.isInterface() || d.isInterface()) {
34.559 + return "java/lang/Object";
34.560 + } else {
34.561 + do {
34.562 + c = c.getSuperclass();
34.563 + } while (!c.isAssignableFrom(d));
34.564 + return c.getName().replace('.', '/');
34.565 + }
34.566 + }
34.567 + }
34.568 +
34.569 + static byte[] transform(ClassLoader loader, byte[] arr) {
34.570 + ClassReader cr = new ClassReader(arr) {
34.571 + // to allow us to compile with -profile compact1 on
34.572 + // JDK8 while processing the class as JDK7, the highest
34.573 + // class format asm 4.1 understands to
34.574 + @Override
34.575 + public short readShort(int index) {
34.576 + short s = super.readShort(index);
34.577 + if (index == 6 && s > Opcodes.V1_7) {
34.578 + return Opcodes.V1_7;
34.579 + }
34.580 + return s;
34.581 + }
34.582 + };
34.583 + FindInClass tst = new FindInClass(loader, null);
34.584 + cr.accept(tst, 0);
34.585 + if (tst.found > 0) {
34.586 + ClassWriter w = new ClassWriterEx(loader, cr, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
34.587 + FindInClass fic = new FindInClass(loader, w);
34.588 + cr.accept(fic, 0);
34.589 + arr = w.toByteArray();
34.590 + }
34.591 + return arr;
34.592 + }
34.593 +
34.594 + private static final class TrueFn extends Fn {
34.595 + @Override
34.596 + public Object invoke(Object thiz, Object... args) throws Exception {
34.597 + return Boolean.TRUE;
34.598 + }
34.599 + } // end of TrueFn
34.600 +}
35.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
35.2 +++ b/boot/src/main/java/org/netbeans/html/boot/impl/JavaScriptProcesor.java Mon Dec 16 16:59:43 2013 +0100
35.3 @@ -0,0 +1,369 @@
35.4 +/**
35.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
35.6 + *
35.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
35.8 + *
35.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
35.10 + * Other names may be trademarks of their respective owners.
35.11 + *
35.12 + * The contents of this file are subject to the terms of either the GNU
35.13 + * General Public License Version 2 only ("GPL") or the Common
35.14 + * Development and Distribution License("CDDL") (collectively, the
35.15 + * "License"). You may not use this file except in compliance with the
35.16 + * License. You can obtain a copy of the License at
35.17 + * http://www.netbeans.org/cddl-gplv2.html
35.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
35.19 + * specific language governing permissions and limitations under the
35.20 + * License. When distributing the software, include this License Header
35.21 + * Notice in each file and include the License file at
35.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
35.23 + * particular file as subject to the "Classpath" exception as provided
35.24 + * by Oracle in the GPL Version 2 section of the License file that
35.25 + * accompanied this code. If applicable, add the following below the
35.26 + * License Header, with the fields enclosed by brackets [] replaced by
35.27 + * your own identifying information:
35.28 + * "Portions Copyrighted [year] [name of copyright owner]"
35.29 + *
35.30 + * Contributor(s):
35.31 + *
35.32 + * The Original Software is NetBeans. The Initial Developer of the Original
35.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
35.34 + *
35.35 + * If you wish your version of this file to be governed by only the CDDL
35.36 + * or only the GPL Version 2, indicate your decision by adding
35.37 + * "[Contributor] elects to include this software in this distribution
35.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
35.39 + * single choice of license, a recipient has the option to distribute
35.40 + * your version of this file under either the CDDL, the GPL Version 2 or
35.41 + * to extend the choice of license to its licensees as provided above.
35.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
35.43 + * Version 2 license, then the option applies only if the new code is
35.44 + * made subject to such option by the copyright holder.
35.45 + */
35.46 +package org.netbeans.html.boot.impl;
35.47 +
35.48 +import java.io.IOException;
35.49 +import java.io.Writer;
35.50 +import java.util.Collections;
35.51 +import java.util.HashMap;
35.52 +import java.util.HashSet;
35.53 +import java.util.List;
35.54 +import java.util.Map;
35.55 +import java.util.Set;
35.56 +import java.util.TreeMap;
35.57 +import javax.annotation.processing.AbstractProcessor;
35.58 +import javax.annotation.processing.Completion;
35.59 +import javax.annotation.processing.Completions;
35.60 +import javax.annotation.processing.Messager;
35.61 +import javax.annotation.processing.Processor;
35.62 +import javax.annotation.processing.RoundEnvironment;
35.63 +import javax.lang.model.SourceVersion;
35.64 +import javax.lang.model.element.AnnotationMirror;
35.65 +import javax.lang.model.element.Element;
35.66 +import javax.lang.model.element.ElementKind;
35.67 +import javax.lang.model.element.ExecutableElement;
35.68 +import javax.lang.model.element.Modifier;
35.69 +import javax.lang.model.element.PackageElement;
35.70 +import javax.lang.model.element.TypeElement;
35.71 +import javax.lang.model.element.VariableElement;
35.72 +import javax.lang.model.type.ArrayType;
35.73 +import javax.lang.model.type.ExecutableType;
35.74 +import javax.lang.model.type.TypeKind;
35.75 +import javax.lang.model.type.TypeMirror;
35.76 +import javax.tools.Diagnostic;
35.77 +import javax.tools.FileObject;
35.78 +import javax.tools.StandardLocation;
35.79 +import net.java.html.js.JavaScriptBody;
35.80 +import net.java.html.js.JavaScriptResource;
35.81 +import org.openide.util.lookup.ServiceProvider;
35.82 +
35.83 +/**
35.84 + *
35.85 + * @author Jaroslav Tulach <jtulach@netbeans.org>
35.86 + */
35.87 +@ServiceProvider(service = Processor.class)
35.88 +public final class JavaScriptProcesor extends AbstractProcessor {
35.89 + private final Map<String,Map<String,ExecutableElement>> javacalls =
35.90 + new HashMap<String,Map<String,ExecutableElement>>();
35.91 +
35.92 + @Override
35.93 + public Set<String> getSupportedAnnotationTypes() {
35.94 + Set<String> set = new HashSet<String>();
35.95 + set.add(JavaScriptBody.class.getName());
35.96 + set.add(JavaScriptResource.class.getName());
35.97 + return set;
35.98 + }
35.99 +
35.100 + @Override
35.101 + public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
35.102 + final Messager msg = processingEnv.getMessager();
35.103 + for (Element e : roundEnv.getElementsAnnotatedWith(JavaScriptBody.class)) {
35.104 + if (e.getKind() != ElementKind.METHOD && e.getKind() != ElementKind.CONSTRUCTOR) {
35.105 + continue;
35.106 + }
35.107 + ExecutableElement ee = (ExecutableElement)e;
35.108 + List<? extends VariableElement> params = ee.getParameters();
35.109 +
35.110 + JavaScriptBody jsb = e.getAnnotation(JavaScriptBody.class);
35.111 + if (jsb == null) {
35.112 + continue;
35.113 + }
35.114 + String[] arr = jsb.args();
35.115 + if (params.size() != arr.length) {
35.116 + msg.printMessage(Diagnostic.Kind.ERROR, "Number of args arguments does not match real arguments!", e);
35.117 + }
35.118 + if (!jsb.javacall() && jsb.body().contains(".@")) {
35.119 + msg.printMessage(Diagnostic.Kind.WARNING, "Usage of .@ usually requires javacall=true", e);
35.120 + }
35.121 + if (jsb.javacall()) {
35.122 + JsCallback verify = new VerifyCallback(e);
35.123 + try {
35.124 + verify.parse(jsb.body());
35.125 + } catch (IllegalStateException ex) {
35.126 + msg.printMessage(Diagnostic.Kind.ERROR, ex.getLocalizedMessage(), e);
35.127 + }
35.128 + }
35.129 + }
35.130 + for (Element e : roundEnv.getElementsAnnotatedWith(JavaScriptResource.class)) {
35.131 + JavaScriptResource r = e.getAnnotation(JavaScriptResource.class);
35.132 + if (r == null) {
35.133 + continue;
35.134 + }
35.135 + final String res;
35.136 + if (r.value().startsWith("/")) {
35.137 + res = r.value();
35.138 + } else {
35.139 + res = findPkg(e).replace('.', '/') + "/" + r.value();
35.140 + }
35.141 +
35.142 + try {
35.143 + FileObject os = processingEnv.getFiler().getResource(StandardLocation.SOURCE_PATH, "", res);
35.144 + os.openInputStream().close();
35.145 + } catch (IOException ex1) {
35.146 + try {
35.147 + FileObject os2 = processingEnv.getFiler().getResource(StandardLocation.CLASS_OUTPUT, "", res);
35.148 + os2.openInputStream().close();
35.149 + } catch (IOException ex2) {
35.150 + msg.printMessage(Diagnostic.Kind.ERROR, "Cannot find " + res + " in " + res + " package", e);
35.151 + }
35.152 + }
35.153 + }
35.154 +
35.155 + if (roundEnv.processingOver()) {
35.156 + generateCallbackClass(javacalls);
35.157 + javacalls.clear();
35.158 + }
35.159 + return true;
35.160 + }
35.161 +
35.162 + @Override
35.163 + public Iterable<? extends Completion> getCompletions(Element e,
35.164 + AnnotationMirror annotation, ExecutableElement member, String userText
35.165 + ) {
35.166 + StringBuilder sb = new StringBuilder();
35.167 + if (e.getKind() == ElementKind.METHOD && member.getSimpleName().contentEquals("args")) {
35.168 + ExecutableElement ee = (ExecutableElement) e;
35.169 + String sep = "";
35.170 + sb.append("{ ");
35.171 + for (VariableElement ve : ee.getParameters()) {
35.172 + sb.append(sep).append('"').append(ve.getSimpleName())
35.173 + .append('"');
35.174 + sep = ", ";
35.175 + }
35.176 + sb.append(" }");
35.177 + return Collections.nCopies(1, Completions.of(sb.toString()));
35.178 + }
35.179 + return null;
35.180 + }
35.181 +
35.182 + private class VerifyCallback extends JsCallback {
35.183 + private final Element e;
35.184 + public VerifyCallback(Element e) {
35.185 + this.e = e;
35.186 + }
35.187 +
35.188 + @Override
35.189 + protected CharSequence callMethod(String ident, String fqn, String method, String params) {
35.190 + final TypeElement type = processingEnv.getElementUtils().getTypeElement(fqn);
35.191 + if (type == null) {
35.192 + processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
35.193 + "Callback to non-existing class " + fqn, e
35.194 + );
35.195 + return "";
35.196 + }
35.197 + ExecutableElement found = null;
35.198 + StringBuilder foundParams = new StringBuilder();
35.199 + for (Element m : type.getEnclosedElements()) {
35.200 + if (m.getKind() != ElementKind.METHOD) {
35.201 + continue;
35.202 + }
35.203 + if (m.getSimpleName().contentEquals(method)) {
35.204 + String paramTypes = findParamTypes((ExecutableElement)m);
35.205 + if (paramTypes.equals(params)) {
35.206 + found = (ExecutableElement) m;
35.207 + break;
35.208 + }
35.209 + foundParams.append(paramTypes).append("\n");
35.210 + }
35.211 + }
35.212 + if (found == null) {
35.213 + if (foundParams.length() == 0) {
35.214 + processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
35.215 + "Callback to class " + fqn + " with unknown method " + method, e
35.216 + );
35.217 + } else {
35.218 + processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
35.219 + "Callback to " + fqn + "." + method + " with wrong parameters: " +
35.220 + params + ". Only known parameters are " + foundParams, e
35.221 + );
35.222 + }
35.223 + } else {
35.224 + Map<String,ExecutableElement> mangledOnes = javacalls.get(findPkg(e));
35.225 + if (mangledOnes == null) {
35.226 + mangledOnes = new TreeMap<String, ExecutableElement>();
35.227 + javacalls.put(findPkg(e), mangledOnes);
35.228 + }
35.229 + String mangled = JsCallback.mangle(fqn, method, findParamTypes(found));
35.230 + mangledOnes.put(mangled, found);
35.231 + }
35.232 + return "";
35.233 + }
35.234 +
35.235 + private String findParamTypes(ExecutableElement method) {
35.236 + ExecutableType t = (ExecutableType) method.asType();
35.237 + StringBuilder sb = new StringBuilder();
35.238 + sb.append('(');
35.239 + for (TypeMirror tm : t.getParameterTypes()) {
35.240 + if (tm.getKind().isPrimitive()) {
35.241 + switch (tm.getKind()) {
35.242 + case INT: sb.append('I'); break;
35.243 + case BOOLEAN: sb.append('Z'); break;
35.244 + case BYTE: sb.append('B'); break;
35.245 + case CHAR: sb.append('C'); break;
35.246 + case SHORT: sb.append('S'); break;
35.247 + case DOUBLE: sb.append('D'); break;
35.248 + case FLOAT: sb.append('F'); break;
35.249 + case LONG: sb.append('J'); break;
35.250 + default:
35.251 + throw new IllegalStateException("Uknown " + tm.getKind());
35.252 + }
35.253 + } else {
35.254 + while (tm.getKind() == TypeKind.ARRAY) {
35.255 + sb.append('[');
35.256 + tm = ((ArrayType)tm).getComponentType();
35.257 + }
35.258 + sb.append('L');
35.259 + sb.append(tm.toString().replace('.', '/'));
35.260 + sb.append(';');
35.261 + }
35.262 + }
35.263 + sb.append(')');
35.264 + return sb.toString();
35.265 + }
35.266 + }
35.267 +
35.268 + private void generateCallbackClass(Map<String,Map<String, ExecutableElement>> process) {
35.269 + for (Map.Entry<String, Map<String, ExecutableElement>> pkgEn : process.entrySet()) {
35.270 + String pkgName = pkgEn.getKey();
35.271 + Map<String, ExecutableElement> map = pkgEn.getValue();
35.272 + StringBuilder source = new StringBuilder();
35.273 + source.append("package ").append(pkgName).append(";\n");
35.274 + source.append("public final class $JsCallbacks$ {\n");
35.275 + source.append(" static final $JsCallbacks$ VM = new $JsCallbacks$(null);\n");
35.276 + source.append(" private final org.apidesign.html.boot.spi.Fn.Presenter p;\n");
35.277 + source.append(" private $JsCallbacks$ last;\n");
35.278 + source.append(" private $JsCallbacks$(org.apidesign.html.boot.spi.Fn.Presenter p) {\n");
35.279 + source.append(" this.p = p;\n");
35.280 + source.append(" }\n");
35.281 + source.append(" final $JsCallbacks$ current() {\n");
35.282 + source.append(" org.apidesign.html.boot.spi.Fn.Presenter now = org.apidesign.html.boot.spi.Fn.activePresenter();\n");
35.283 + source.append(" if (now == p) return this;\n");
35.284 + source.append(" if (last != null && now == last.p) return last;\n");
35.285 + source.append(" return last = new $JsCallbacks$(now);\n");
35.286 + source.append(" }\n");
35.287 + for (Map.Entry<String, ExecutableElement> entry : map.entrySet()) {
35.288 + final String mangled = entry.getKey();
35.289 + final ExecutableElement m = entry.getValue();
35.290 + final boolean isStatic = m.getModifiers().contains(Modifier.STATIC);
35.291 +
35.292 + source.append("\n public java.lang.Object ")
35.293 + .append(mangled)
35.294 + .append("(");
35.295 +
35.296 + String sep = "";
35.297 + if (!isStatic) {
35.298 + source.append(((TypeElement)m.getEnclosingElement()).getQualifiedName());
35.299 + source.append(" self");
35.300 + sep = ", ";
35.301 + }
35.302 +
35.303 + int cnt = 0;
35.304 + for (VariableElement ve : m.getParameters()) {
35.305 + source.append(sep);
35.306 + source.append(ve.asType());
35.307 + source.append(" arg").append(++cnt);
35.308 + sep = ", ";
35.309 + }
35.310 + source.append(") throws Throwable {\n");
35.311 + if (processingEnv.getSourceVersion().compareTo(SourceVersion.RELEASE_7) >= 0) {
35.312 + source.append(" try (java.io.Closeable a = org.apidesign.html.boot.spi.Fn.activate(p)) { \n");
35.313 + } else {
35.314 + source.append(" java.io.Closeable a = org.apidesign.html.boot.spi.Fn.activate(p); try {\n");
35.315 + }
35.316 + source.append(" ");
35.317 + if (m.getReturnType().getKind() != TypeKind.VOID) {
35.318 + source.append("return ");
35.319 + }
35.320 + if (isStatic) {
35.321 + source.append(((TypeElement)m.getEnclosingElement()).getQualifiedName());
35.322 + source.append('.');
35.323 + } else {
35.324 + source.append("self.");
35.325 + }
35.326 + source.append(m.getSimpleName());
35.327 + source.append("(");
35.328 + cnt = 0;
35.329 + sep = "";
35.330 + for (VariableElement ve : m.getParameters()) {
35.331 + source.append(sep);
35.332 + source.append("arg").append(++cnt);
35.333 + sep = ", ";
35.334 + }
35.335 + source.append(");\n");
35.336 + if (m.getReturnType().getKind() == TypeKind.VOID) {
35.337 + source.append(" return null;\n");
35.338 + }
35.339 + if (processingEnv.getSourceVersion().compareTo(SourceVersion.RELEASE_7) >= 0) {
35.340 + source.append(" }\n");
35.341 + } else {
35.342 +
35.343 + source.append(" } finally {\n");
35.344 + source.append(" a.close();\n");
35.345 + source.append(" }\n");
35.346 + }
35.347 + source.append(" }\n");
35.348 + }
35.349 + source.append("}\n");
35.350 + final String srcName = pkgName + ".$JsCallbacks$";
35.351 + try {
35.352 + Writer w = processingEnv.getFiler().createSourceFile(srcName,
35.353 + map.values().toArray(new Element[map.size()])
35.354 + ).openWriter();
35.355 + w.write(source.toString());
35.356 + w.close();
35.357 + } catch (IOException ex) {
35.358 + processingEnv.getMessager().printMessage(
35.359 + Diagnostic.Kind.ERROR, "Can't write " + srcName + ": " + ex.getMessage()
35.360 + );
35.361 + }
35.362 + }
35.363 + }
35.364 +
35.365 + private static String findPkg(Element e) {
35.366 + while (e.getKind() != ElementKind.PACKAGE) {
35.367 + e = e.getEnclosingElement();
35.368 + }
35.369 + return ((PackageElement)e).getQualifiedName().toString();
35.370 + }
35.371 +
35.372 +}
36.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
36.2 +++ b/boot/src/main/java/org/netbeans/html/boot/impl/JsAgent.java Mon Dec 16 16:59:43 2013 +0100
36.3 @@ -0,0 +1,67 @@
36.4 +/**
36.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
36.6 + *
36.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
36.8 + *
36.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
36.10 + * Other names may be trademarks of their respective owners.
36.11 + *
36.12 + * The contents of this file are subject to the terms of either the GNU
36.13 + * General Public License Version 2 only ("GPL") or the Common
36.14 + * Development and Distribution License("CDDL") (collectively, the
36.15 + * "License"). You may not use this file except in compliance with the
36.16 + * License. You can obtain a copy of the License at
36.17 + * http://www.netbeans.org/cddl-gplv2.html
36.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
36.19 + * specific language governing permissions and limitations under the
36.20 + * License. When distributing the software, include this License Header
36.21 + * Notice in each file and include the License file at
36.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
36.23 + * particular file as subject to the "Classpath" exception as provided
36.24 + * by Oracle in the GPL Version 2 section of the License file that
36.25 + * accompanied this code. If applicable, add the following below the
36.26 + * License Header, with the fields enclosed by brackets [] replaced by
36.27 + * your own identifying information:
36.28 + * "Portions Copyrighted [year] [name of copyright owner]"
36.29 + *
36.30 + * Contributor(s):
36.31 + *
36.32 + * The Original Software is NetBeans. The Initial Developer of the Original
36.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
36.34 + *
36.35 + * If you wish your version of this file to be governed by only the CDDL
36.36 + * or only the GPL Version 2, indicate your decision by adding
36.37 + * "[Contributor] elects to include this software in this distribution
36.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
36.39 + * single choice of license, a recipient has the option to distribute
36.40 + * your version of this file under either the CDDL, the GPL Version 2 or
36.41 + * to extend the choice of license to its licensees as provided above.
36.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
36.43 + * Version 2 license, then the option applies only if the new code is
36.44 + * made subject to such option by the copyright holder.
36.45 + */
36.46 +package org.netbeans.html.boot.impl;
36.47 +
36.48 +import java.lang.instrument.ClassFileTransformer;
36.49 +import java.lang.instrument.IllegalClassFormatException;
36.50 +import java.lang.instrument.Instrumentation;
36.51 +import java.security.ProtectionDomain;
36.52 +
36.53 +/**
36.54 + *
36.55 + * @author Jaroslav Tulach <jtulach@netbeans.org>
36.56 + */
36.57 +public final class JsAgent implements ClassFileTransformer {
36.58 + public static void agentmain(String args, Instrumentation instr) {
36.59 + instr.addTransformer(new JsAgent());
36.60 + }
36.61 +
36.62 + @Override
36.63 + public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
36.64 + try {
36.65 + return FnUtils.transform(loader, classfileBuffer);
36.66 + } catch (Exception ex) {
36.67 + return classfileBuffer;
36.68 + }
36.69 + }
36.70 +}
37.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
37.2 +++ b/boot/src/main/java/org/netbeans/html/boot/impl/JsCallback.java Mon Dec 16 16:59:43 2013 +0100
37.3 @@ -0,0 +1,160 @@
37.4 +/**
37.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
37.6 + *
37.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
37.8 + *
37.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
37.10 + * Other names may be trademarks of their respective owners.
37.11 + *
37.12 + * The contents of this file are subject to the terms of either the GNU
37.13 + * General Public License Version 2 only ("GPL") or the Common
37.14 + * Development and Distribution License("CDDL") (collectively, the
37.15 + * "License"). You may not use this file except in compliance with the
37.16 + * License. You can obtain a copy of the License at
37.17 + * http://www.netbeans.org/cddl-gplv2.html
37.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
37.19 + * specific language governing permissions and limitations under the
37.20 + * License. When distributing the software, include this License Header
37.21 + * Notice in each file and include the License file at
37.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
37.23 + * particular file as subject to the "Classpath" exception as provided
37.24 + * by Oracle in the GPL Version 2 section of the License file that
37.25 + * accompanied this code. If applicable, add the following below the
37.26 + * License Header, with the fields enclosed by brackets [] replaced by
37.27 + * your own identifying information:
37.28 + * "Portions Copyrighted [year] [name of copyright owner]"
37.29 + *
37.30 + * Contributor(s):
37.31 + *
37.32 + * The Original Software is NetBeans. The Initial Developer of the Original
37.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
37.34 + *
37.35 + * If you wish your version of this file to be governed by only the CDDL
37.36 + * or only the GPL Version 2, indicate your decision by adding
37.37 + * "[Contributor] elects to include this software in this distribution
37.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
37.39 + * single choice of license, a recipient has the option to distribute
37.40 + * your version of this file under either the CDDL, the GPL Version 2 or
37.41 + * to extend the choice of license to its licensees as provided above.
37.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
37.43 + * Version 2 license, then the option applies only if the new code is
37.44 + * made subject to such option by the copyright holder.
37.45 + */
37.46 +package org.netbeans.html.boot.impl;
37.47 +
37.48 +
37.49 +/**
37.50 + *
37.51 + * @author Jaroslav Tulach <jtulach@netbeans.org>
37.52 + */
37.53 +abstract class JsCallback {
37.54 + final String parse(String body) {
37.55 + StringBuilder sb = new StringBuilder();
37.56 + int pos = 0;
37.57 + for (;;) {
37.58 + int next = body.indexOf(".@", pos);
37.59 + if (next == -1) {
37.60 + sb.append(body.substring(pos));
37.61 + body = sb.toString();
37.62 + break;
37.63 + }
37.64 + int ident = next;
37.65 + while (ident > 0) {
37.66 + if (!Character.isJavaIdentifierPart(body.charAt(--ident))) {
37.67 + ident++;
37.68 + break;
37.69 + }
37.70 + }
37.71 + String refId = body.substring(ident, next);
37.72 +
37.73 + sb.append(body.substring(pos, ident));
37.74 +
37.75 + int sigBeg = body.indexOf('(', next);
37.76 + int sigEnd = body.indexOf(')', sigBeg);
37.77 + int colon4 = body.indexOf("::", next);
37.78 + if (sigBeg == -1 || sigEnd == -1 || colon4 == -1) {
37.79 + throw new IllegalStateException(
37.80 + "Wrong format of instance callback. "
37.81 + + "Should be: 'inst.@pkg.Class::method(Ljava/lang/Object;)(param)':\n"
37.82 + + body
37.83 + );
37.84 + }
37.85 + String fqn = body.substring(next + 2, colon4);
37.86 + String method = body.substring(colon4 + 2, sigBeg);
37.87 + String params = body.substring(sigBeg, sigEnd + 1);
37.88 +
37.89 + int paramBeg = body.indexOf('(', sigEnd + 1);
37.90 + if (paramBeg == -1) {
37.91 + throw new IllegalStateException(
37.92 + "Wrong format of instance callback. "
37.93 + + "Should be: 'inst.@pkg.Class::method(Ljava/lang/Object;)(param)':\n"
37.94 + + body
37.95 + );
37.96 + }
37.97 +
37.98 + sb.append(callMethod(refId, fqn, method, params));
37.99 + if (body.charAt(paramBeg + 1) != (')')) {
37.100 + sb.append(",");
37.101 + }
37.102 + pos = paramBeg + 1;
37.103 + }
37.104 + pos = 0;
37.105 + sb = null;
37.106 + for (;;) {
37.107 + int next = body.indexOf("@", pos);
37.108 + if (next == -1) {
37.109 + if (sb == null) {
37.110 + return body;
37.111 + }
37.112 + sb.append(body.substring(pos));
37.113 + return sb.toString();
37.114 + }
37.115 + if (sb == null) {
37.116 + sb = new StringBuilder();
37.117 + }
37.118 +
37.119 + sb.append(body.substring(pos, next));
37.120 +
37.121 + int sigBeg = body.indexOf('(', next);
37.122 + int sigEnd = body.indexOf(')', sigBeg);
37.123 + int colon4 = body.indexOf("::", next);
37.124 + if (sigBeg == -1 || sigEnd == -1 || colon4 == -1) {
37.125 + throw new IllegalStateException(
37.126 + "Wrong format of static callback. "
37.127 + + "Should be: '@pkg.Class::staticMethod(Ljava/lang/Object;)(param)':\n"
37.128 + + body
37.129 + );
37.130 + }
37.131 + String fqn = body.substring(next + 1, colon4);
37.132 + String method = body.substring(colon4 + 2, sigBeg);
37.133 + String params = body.substring(sigBeg, sigEnd + 1);
37.134 +
37.135 + int paramBeg = body.indexOf('(', sigEnd + 1);
37.136 +
37.137 + sb.append(callMethod(null, fqn, method, params));
37.138 + pos = paramBeg + 1;
37.139 + }
37.140 + }
37.141 +
37.142 + protected abstract CharSequence callMethod(
37.143 + String ident, String fqn, String method, String params
37.144 + );
37.145 +
37.146 + static String mangle(String fqn, String method, String params) {
37.147 + if (params.startsWith("(")) {
37.148 + params = params.substring(1);
37.149 + }
37.150 + if (params.endsWith(")")) {
37.151 + params = params.substring(0, params.length() - 1);
37.152 + }
37.153 + return
37.154 + replace(fqn) + "$" + replace(method) + "$" + replace(params);
37.155 + }
37.156 +
37.157 + private static String replace(String orig) {
37.158 + return orig.replace("_", "_1").
37.159 + replace(";", "_2").
37.160 + replace("[", "_3").
37.161 + replace('.', '_').replace('/', '_');
37.162 + }
37.163 +}
38.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
38.2 +++ b/boot/src/main/java/org/netbeans/html/boot/impl/JsClassLoader.java Mon Dec 16 16:59:43 2013 +0100
38.3 @@ -0,0 +1,133 @@
38.4 +/**
38.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
38.6 + *
38.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
38.8 + *
38.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
38.10 + * Other names may be trademarks of their respective owners.
38.11 + *
38.12 + * The contents of this file are subject to the terms of either the GNU
38.13 + * General Public License Version 2 only ("GPL") or the Common
38.14 + * Development and Distribution License("CDDL") (collectively, the
38.15 + * "License"). You may not use this file except in compliance with the
38.16 + * License. You can obtain a copy of the License at
38.17 + * http://www.netbeans.org/cddl-gplv2.html
38.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
38.19 + * specific language governing permissions and limitations under the
38.20 + * License. When distributing the software, include this License Header
38.21 + * Notice in each file and include the License file at
38.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
38.23 + * particular file as subject to the "Classpath" exception as provided
38.24 + * by Oracle in the GPL Version 2 section of the License file that
38.25 + * accompanied this code. If applicable, add the following below the
38.26 + * License Header, with the fields enclosed by brackets [] replaced by
38.27 + * your own identifying information:
38.28 + * "Portions Copyrighted [year] [name of copyright owner]"
38.29 + *
38.30 + * Contributor(s):
38.31 + *
38.32 + * The Original Software is NetBeans. The Initial Developer of the Original
38.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
38.34 + *
38.35 + * If you wish your version of this file to be governed by only the CDDL
38.36 + * or only the GPL Version 2, indicate your decision by adding
38.37 + * "[Contributor] elects to include this software in this distribution
38.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
38.39 + * single choice of license, a recipient has the option to distribute
38.40 + * your version of this file under either the CDDL, the GPL Version 2 or
38.41 + * to extend the choice of license to its licensees as provided above.
38.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
38.43 + * Version 2 license, then the option applies only if the new code is
38.44 + * made subject to such option by the copyright holder.
38.45 + */
38.46 +package org.netbeans.html.boot.impl;
38.47 +
38.48 +import org.apidesign.html.boot.spi.Fn;
38.49 +import java.io.IOException;
38.50 +import java.io.InputStream;
38.51 +import java.io.Reader;
38.52 +import java.net.URL;
38.53 +import java.util.Enumeration;
38.54 +
38.55 +/**
38.56 + *
38.57 + * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
38.58 + */
38.59 +abstract class JsClassLoader extends ClassLoader {
38.60 + JsClassLoader(ClassLoader parent) {
38.61 + super(parent);
38.62 + setDefaultAssertionStatus(JsClassLoader.class.desiredAssertionStatus());
38.63 + }
38.64 +
38.65 + @Override
38.66 + protected abstract URL findResource(String name);
38.67 +
38.68 + @Override
38.69 + protected abstract Enumeration<URL> findResources(String name);
38.70 +
38.71 + @Override
38.72 + protected Class<?> findClass(String name) throws ClassNotFoundException {
38.73 + if (name.startsWith("javafx")) {
38.74 + return Class.forName(name);
38.75 + }
38.76 + if (name.startsWith("netscape")) {
38.77 + return Class.forName(name);
38.78 + }
38.79 + if (name.startsWith("com.sun")) {
38.80 + return Class.forName(name);
38.81 + }
38.82 + if (name.equals(JsClassLoader.class.getName())) {
38.83 + return JsClassLoader.class;
38.84 + }
38.85 + if (name.equals(Fn.class.getName())) {
38.86 + return Fn.class;
38.87 + }
38.88 + if (name.equals(Fn.Presenter.class.getName())) {
38.89 + return Fn.Presenter.class;
38.90 + }
38.91 + if (name.equals(FnUtils.class.getName())) {
38.92 + return FnUtils.class;
38.93 + }
38.94 + if (
38.95 + name.equals("org.apidesign.html.boot.spi.Fn") ||
38.96 + name.equals("org.netbeans.html.boot.impl.FnUtils") ||
38.97 + name.equals("org.netbeans.html.boot.impl.FnContext")
38.98 + ) {
38.99 + return Class.forName(name);
38.100 + }
38.101 + URL u = findResource(name.replace('.', '/') + ".class");
38.102 + if (u != null) {
38.103 + InputStream is = null;
38.104 + try {
38.105 + is = u.openStream();
38.106 + byte[] arr = new byte[is.available()];
38.107 + int len = 0;
38.108 + while (len < arr.length) {
38.109 + int read = is.read(arr, len, arr.length - len);
38.110 + if (read == -1) {
38.111 + throw new IOException("Can't read " + u);
38.112 + }
38.113 + len += read;
38.114 + }
38.115 + is.close();
38.116 + is = null;
38.117 + arr = FnUtils.transform(JsClassLoader.this, arr);
38.118 + if (arr != null) {
38.119 + return defineClass(name, arr, 0, arr.length);
38.120 + }
38.121 + } catch (IOException ex) {
38.122 + throw new ClassNotFoundException("Can't load " + name, ex);
38.123 + } finally {
38.124 + try {
38.125 + if (is != null) is.close();
38.126 + } catch (IOException ex) {
38.127 + throw new ClassNotFoundException(null, ex);
38.128 + }
38.129 + }
38.130 + }
38.131 + return super.findClass(name);
38.132 + }
38.133 +
38.134 + protected abstract Fn defineFn(String code, String... names);
38.135 + protected abstract void loadScript(Reader code) throws Exception;
38.136 +}
39.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
39.2 +++ b/boot/src/main/java/org/netbeans/html/boot/impl/Test.java Mon Dec 16 16:59:43 2013 +0100
39.3 @@ -0,0 +1,57 @@
39.4 +/**
39.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
39.6 + *
39.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
39.8 + *
39.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
39.10 + * Other names may be trademarks of their respective owners.
39.11 + *
39.12 + * The contents of this file are subject to the terms of either the GNU
39.13 + * General Public License Version 2 only ("GPL") or the Common
39.14 + * Development and Distribution License("CDDL") (collectively, the
39.15 + * "License"). You may not use this file except in compliance with the
39.16 + * License. You can obtain a copy of the License at
39.17 + * http://www.netbeans.org/cddl-gplv2.html
39.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
39.19 + * specific language governing permissions and limitations under the
39.20 + * License. When distributing the software, include this License Header
39.21 + * Notice in each file and include the License file at
39.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
39.23 + * particular file as subject to the "Classpath" exception as provided
39.24 + * by Oracle in the GPL Version 2 section of the License file that
39.25 + * accompanied this code. If applicable, add the following below the
39.26 + * License Header, with the fields enclosed by brackets [] replaced by
39.27 + * your own identifying information:
39.28 + * "Portions Copyrighted [year] [name of copyright owner]"
39.29 + *
39.30 + * Contributor(s):
39.31 + *
39.32 + * The Original Software is NetBeans. The Initial Developer of the Original
39.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
39.34 + *
39.35 + * If you wish your version of this file to be governed by only the CDDL
39.36 + * or only the GPL Version 2, indicate your decision by adding
39.37 + * "[Contributor] elects to include this software in this distribution
39.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
39.39 + * single choice of license, a recipient has the option to distribute
39.40 + * your version of this file under either the CDDL, the GPL Version 2 or
39.41 + * to extend the choice of license to its licensees as provided above.
39.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
39.43 + * Version 2 license, then the option applies only if the new code is
39.44 + * made subject to such option by the copyright holder.
39.45 + */
39.46 +package org.netbeans.html.boot.impl;
39.47 +
39.48 +import java.util.concurrent.Callable;
39.49 +import net.java.html.js.JavaScriptBody;
39.50 +
39.51 +/**
39.52 + *
39.53 + * @author Jaroslav Tulach <jtulach@netbeans.org>
39.54 + */
39.55 +public final class Test implements Callable<Boolean> {
39.56 + @Override @JavaScriptBody(args = {}, body = "return true;")
39.57 + public Boolean call() {
39.58 + return false;
39.59 + }
39.60 +}
40.1 --- a/boot/src/test/java/org/apidesign/html/boot/impl/Arithm.java Mon Dec 16 15:48:09 2013 +0100
40.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
40.3 @@ -1,53 +0,0 @@
40.4 -/**
40.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
40.6 - *
40.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
40.8 - *
40.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
40.10 - * Other names may be trademarks of their respective owners.
40.11 - *
40.12 - * The contents of this file are subject to the terms of either the GNU
40.13 - * General Public License Version 2 only ("GPL") or the Common
40.14 - * Development and Distribution License("CDDL") (collectively, the
40.15 - * "License"). You may not use this file except in compliance with the
40.16 - * License. You can obtain a copy of the License at
40.17 - * http://www.netbeans.org/cddl-gplv2.html
40.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
40.19 - * specific language governing permissions and limitations under the
40.20 - * License. When distributing the software, include this License Header
40.21 - * Notice in each file and include the License file at
40.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
40.23 - * particular file as subject to the "Classpath" exception as provided
40.24 - * by Oracle in the GPL Version 2 section of the License file that
40.25 - * accompanied this code. If applicable, add the following below the
40.26 - * License Header, with the fields enclosed by brackets [] replaced by
40.27 - * your own identifying information:
40.28 - * "Portions Copyrighted [year] [name of copyright owner]"
40.29 - *
40.30 - * Contributor(s):
40.31 - *
40.32 - * The Original Software is NetBeans. The Initial Developer of the Original
40.33 - * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
40.34 - *
40.35 - * If you wish your version of this file to be governed by only the CDDL
40.36 - * or only the GPL Version 2, indicate your decision by adding
40.37 - * "[Contributor] elects to include this software in this distribution
40.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
40.39 - * single choice of license, a recipient has the option to distribute
40.40 - * your version of this file under either the CDDL, the GPL Version 2 or
40.41 - * to extend the choice of license to its licensees as provided above.
40.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
40.43 - * Version 2 license, then the option applies only if the new code is
40.44 - * made subject to such option by the copyright holder.
40.45 - */
40.46 -package org.apidesign.html.boot.impl;
40.47 -
40.48 -/**
40.49 - *
40.50 - * @author Jaroslav Tulach <jtulach@netbeans.org>
40.51 - */
40.52 -public class Arithm {
40.53 - public int sumTwo(int a, int b) {
40.54 - return a + b;
40.55 - }
40.56 -}
41.1 --- a/boot/src/test/java/org/apidesign/html/boot/impl/Compile.java Mon Dec 16 15:48:09 2013 +0100
41.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
41.3 @@ -1,291 +0,0 @@
41.4 -/**
41.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
41.6 - *
41.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
41.8 - *
41.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
41.10 - * Other names may be trademarks of their respective owners.
41.11 - *
41.12 - * The contents of this file are subject to the terms of either the GNU
41.13 - * General Public License Version 2 only ("GPL") or the Common
41.14 - * Development and Distribution License("CDDL") (collectively, the
41.15 - * "License"). You may not use this file except in compliance with the
41.16 - * License. You can obtain a copy of the License at
41.17 - * http://www.netbeans.org/cddl-gplv2.html
41.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
41.19 - * specific language governing permissions and limitations under the
41.20 - * License. When distributing the software, include this License Header
41.21 - * Notice in each file and include the License file at
41.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
41.23 - * particular file as subject to the "Classpath" exception as provided
41.24 - * by Oracle in the GPL Version 2 section of the License file that
41.25 - * accompanied this code. If applicable, add the following below the
41.26 - * License Header, with the fields enclosed by brackets [] replaced by
41.27 - * your own identifying information:
41.28 - * "Portions Copyrighted [year] [name of copyright owner]"
41.29 - *
41.30 - * Contributor(s):
41.31 - *
41.32 - * The Original Software is NetBeans. The Initial Developer of the Original
41.33 - * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
41.34 - *
41.35 - * If you wish your version of this file to be governed by only the CDDL
41.36 - * or only the GPL Version 2, indicate your decision by adding
41.37 - * "[Contributor] elects to include this software in this distribution
41.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
41.39 - * single choice of license, a recipient has the option to distribute
41.40 - * your version of this file under either the CDDL, the GPL Version 2 or
41.41 - * to extend the choice of license to its licensees as provided above.
41.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
41.43 - * Version 2 license, then the option applies only if the new code is
41.44 - * made subject to such option by the copyright holder.
41.45 - */
41.46 -package org.apidesign.html.boot.impl;
41.47 -
41.48 -import java.io.ByteArrayInputStream;
41.49 -import java.io.ByteArrayOutputStream;
41.50 -import java.io.IOException;
41.51 -import java.io.InputStream;
41.52 -import java.io.OutputStream;
41.53 -import java.net.URI;
41.54 -import java.net.URISyntaxException;
41.55 -import java.util.ArrayList;
41.56 -import java.util.Arrays;
41.57 -import java.util.HashMap;
41.58 -import java.util.List;
41.59 -import java.util.Locale;
41.60 -import java.util.Map;
41.61 -import java.util.regex.Matcher;
41.62 -import java.util.regex.Pattern;
41.63 -import javax.tools.Diagnostic;
41.64 -import javax.tools.DiagnosticListener;
41.65 -import javax.tools.FileObject;
41.66 -import javax.tools.ForwardingJavaFileManager;
41.67 -import javax.tools.JavaFileManager;
41.68 -import javax.tools.JavaFileObject;
41.69 -import javax.tools.JavaFileObject.Kind;
41.70 -import javax.tools.SimpleJavaFileObject;
41.71 -import javax.tools.StandardJavaFileManager;
41.72 -import javax.tools.StandardLocation;
41.73 -import javax.tools.ToolProvider;
41.74 -import static org.testng.Assert.assertTrue;
41.75 -import static org.testng.Assert.assertFalse;
41.76 -import static org.testng.Assert.fail;
41.77 -
41.78 -/**
41.79 - *
41.80 - * @author Jaroslav Tulach <jtulach@netbeans.org>
41.81 - */
41.82 -final class Compile implements DiagnosticListener<JavaFileObject> {
41.83 - private final List<Diagnostic<? extends JavaFileObject>> errors =
41.84 - new ArrayList<Diagnostic<? extends JavaFileObject>>();
41.85 - private final Map<String, byte[]> classes;
41.86 - private final String pkg;
41.87 - private final String cls;
41.88 - private final String html;
41.89 - private final String sourceLevel;
41.90 -
41.91 - private Compile(String html, String code, String sl) throws IOException {
41.92 - this.pkg = findPkg(code);
41.93 - this.cls = findCls(code);
41.94 - this.html = html;
41.95 - this.sourceLevel = sl;
41.96 - classes = compile(html, code);
41.97 - }
41.98 -
41.99 - /** Performs compilation of given HTML page and associated Java code
41.100 - */
41.101 - public static Compile create(String html, String code) throws IOException {
41.102 - return create(html, code, "1.7");
41.103 - }
41.104 - static Compile create(String html, String code, String sourceLevel) throws IOException {
41.105 - return new Compile(html, code, sourceLevel);
41.106 - }
41.107 -
41.108 - /** Checks for given class among compiled resources */
41.109 - public byte[] get(String res) {
41.110 - return classes.get(res);
41.111 - }
41.112 -
41.113 - /** Obtains errors created during compilation.
41.114 - */
41.115 - public List<Diagnostic<? extends JavaFileObject>> getErrors() {
41.116 - List<Diagnostic<? extends JavaFileObject>> err;
41.117 - err = new ArrayList<Diagnostic<? extends JavaFileObject>>();
41.118 - for (Diagnostic<? extends JavaFileObject> diagnostic : errors) {
41.119 - if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
41.120 - err.add(diagnostic);
41.121 - }
41.122 - }
41.123 - return err;
41.124 - }
41.125 -
41.126 - private Map<String, byte[]> compile(final String html, final String code) throws IOException {
41.127 - StandardJavaFileManager sjfm = ToolProvider.getSystemJavaCompiler().getStandardFileManager(this, null, null);
41.128 -
41.129 - final Map<String, ByteArrayOutputStream> class2BAOS;
41.130 - class2BAOS = new HashMap<String, ByteArrayOutputStream>();
41.131 -
41.132 - JavaFileObject file = new SimpleJavaFileObject(URI.create("mem://mem"), Kind.SOURCE) {
41.133 - @Override
41.134 - public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
41.135 - return code;
41.136 - }
41.137 - };
41.138 - final JavaFileObject htmlFile = new SimpleJavaFileObject(URI.create("mem://mem2"), Kind.OTHER) {
41.139 - @Override
41.140 - public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
41.141 - return html;
41.142 - }
41.143 -
41.144 - @Override
41.145 - public InputStream openInputStream() throws IOException {
41.146 - return new ByteArrayInputStream(html.getBytes());
41.147 - }
41.148 - };
41.149 -
41.150 - final URI scratch;
41.151 - try {
41.152 - scratch = new URI("mem://mem3");
41.153 - } catch (URISyntaxException ex) {
41.154 - throw new IOException(ex);
41.155 - }
41.156 -
41.157 - JavaFileManager jfm = new ForwardingJavaFileManager<JavaFileManager>(sjfm) {
41.158 - @Override
41.159 - public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) throws IOException {
41.160 - if (kind == Kind.CLASS) {
41.161 - final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
41.162 -
41.163 - class2BAOS.put(className.replace('.', '/') + ".class", buffer);
41.164 - return new SimpleJavaFileObject(sibling.toUri(), kind) {
41.165 - @Override
41.166 - public OutputStream openOutputStream() throws IOException {
41.167 - return buffer;
41.168 - }
41.169 - };
41.170 - }
41.171 -
41.172 - if (kind == Kind.SOURCE) {
41.173 - final String n = className.replace('.', '/') + ".java";
41.174 - final URI un;
41.175 - try {
41.176 - un = new URI("mem://" + n);
41.177 - } catch (URISyntaxException ex) {
41.178 - throw new IOException(ex);
41.179 - }
41.180 - return new VirtFO(un/*sibling.toUri()*/, kind, n);
41.181 - }
41.182 -
41.183 - throw new IllegalStateException();
41.184 - }
41.185 -
41.186 - @Override
41.187 - public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException {
41.188 - if (location == StandardLocation.SOURCE_PATH) {
41.189 - if (packageName.equals(pkg)) {
41.190 - return htmlFile;
41.191 - }
41.192 - }
41.193 -
41.194 - return null;
41.195 - }
41.196 -
41.197 - @Override
41.198 - public boolean isSameFile(FileObject a, FileObject b) {
41.199 - if (a instanceof VirtFO && b instanceof VirtFO) {
41.200 - return ((VirtFO)a).getName().equals(((VirtFO)b).getName());
41.201 - }
41.202 -
41.203 - return super.isSameFile(a, b);
41.204 - }
41.205 -
41.206 - class VirtFO extends SimpleJavaFileObject {
41.207 -
41.208 - private final String n;
41.209 -
41.210 - public VirtFO(URI uri, Kind kind, String n) {
41.211 - super(uri, kind);
41.212 - this.n = n;
41.213 - }
41.214 - private final ByteArrayOutputStream data = new ByteArrayOutputStream();
41.215 -
41.216 - @Override
41.217 - public OutputStream openOutputStream() throws IOException {
41.218 - return data;
41.219 - }
41.220 -
41.221 - @Override
41.222 - public String getName() {
41.223 - return n;
41.224 - }
41.225 -
41.226 - @Override
41.227 - public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
41.228 - data.close();
41.229 - return new String(data.toByteArray());
41.230 - }
41.231 - }
41.232 - };
41.233 -
41.234 - ToolProvider.getSystemJavaCompiler().getTask(null, jfm, this, /*XXX:*/Arrays.asList("-source", sourceLevel, "-target", "1.7"), null, Arrays.asList(file)).call();
41.235 -
41.236 - Map<String, byte[]> result = new HashMap<String, byte[]>();
41.237 -
41.238 - for (Map.Entry<String, ByteArrayOutputStream> e : class2BAOS.entrySet()) {
41.239 - result.put(e.getKey(), e.getValue().toByteArray());
41.240 - }
41.241 -
41.242 - return result;
41.243 - }
41.244 -
41.245 -
41.246 - @Override
41.247 - public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
41.248 - errors.add(diagnostic);
41.249 - }
41.250 - private static String findPkg(String java) throws IOException {
41.251 - Pattern p = Pattern.compile("package\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}*;", Pattern.MULTILINE);
41.252 - Matcher m = p.matcher(java);
41.253 - if (!m.find()) {
41.254 - throw new IOException("Can't find package declaration in the java file");
41.255 - }
41.256 - String pkg = m.group(1);
41.257 - return pkg;
41.258 - }
41.259 - private static String findCls(String java) throws IOException {
41.260 - Pattern p = Pattern.compile("class\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}", Pattern.MULTILINE);
41.261 - Matcher m = p.matcher(java);
41.262 - if (!m.find()) {
41.263 - throw new IOException("Can't find package declaration in the java file");
41.264 - }
41.265 - String cls = m.group(1);
41.266 - return cls;
41.267 - }
41.268 -
41.269 - String getHtml() {
41.270 - String fqn = "'" + pkg + '.' + cls + "'";
41.271 - return html.replace("'${fqn}'", fqn);
41.272 - }
41.273 - void assertErrors() {
41.274 - assertFalse(getErrors().isEmpty(), "There are supposed to be some errors");
41.275 - }
41.276 -
41.277 - void assertError(String expMsg) {
41.278 - StringBuilder sb = new StringBuilder();
41.279 - sb.append("Can't find ").append(expMsg).append(" among:");
41.280 - for (Diagnostic<? extends JavaFileObject> e : errors) {
41.281 - String msg = e.getMessage(Locale.US);
41.282 - if (msg.contains(expMsg)) {
41.283 - return;
41.284 - }
41.285 - sb.append("\n");
41.286 - sb.append(msg);
41.287 - }
41.288 - fail(sb.toString());
41.289 - }
41.290 -
41.291 - void assertNoErrors() {
41.292 - assertTrue(getErrors().isEmpty(), "No errors expected: " + getErrors());
41.293 - }
41.294 -}
42.1 --- a/boot/src/test/java/org/apidesign/html/boot/impl/FnTest.java Mon Dec 16 15:48:09 2013 +0100
42.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
42.3 @@ -1,148 +0,0 @@
42.4 -/**
42.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
42.6 - *
42.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
42.8 - *
42.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
42.10 - * Other names may be trademarks of their respective owners.
42.11 - *
42.12 - * The contents of this file are subject to the terms of either the GNU
42.13 - * General Public License Version 2 only ("GPL") or the Common
42.14 - * Development and Distribution License("CDDL") (collectively, the
42.15 - * "License"). You may not use this file except in compliance with the
42.16 - * License. You can obtain a copy of the License at
42.17 - * http://www.netbeans.org/cddl-gplv2.html
42.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
42.19 - * specific language governing permissions and limitations under the
42.20 - * License. When distributing the software, include this License Header
42.21 - * Notice in each file and include the License file at
42.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
42.23 - * particular file as subject to the "Classpath" exception as provided
42.24 - * by Oracle in the GPL Version 2 section of the License file that
42.25 - * accompanied this code. If applicable, add the following below the
42.26 - * License Header, with the fields enclosed by brackets [] replaced by
42.27 - * your own identifying information:
42.28 - * "Portions Copyrighted [year] [name of copyright owner]"
42.29 - *
42.30 - * Contributor(s):
42.31 - *
42.32 - * The Original Software is NetBeans. The Initial Developer of the Original
42.33 - * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
42.34 - *
42.35 - * If you wish your version of this file to be governed by only the CDDL
42.36 - * or only the GPL Version 2, indicate your decision by adding
42.37 - * "[Contributor] elects to include this software in this distribution
42.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
42.39 - * single choice of license, a recipient has the option to distribute
42.40 - * your version of this file under either the CDDL, the GPL Version 2 or
42.41 - * to extend the choice of license to its licensees as provided above.
42.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
42.43 - * Version 2 license, then the option applies only if the new code is
42.44 - * made subject to such option by the copyright holder.
42.45 - */
42.46 -package org.apidesign.html.boot.impl;
42.47 -
42.48 -import java.io.Closeable;
42.49 -import java.io.Reader;
42.50 -import java.net.URL;
42.51 -import java.net.URLClassLoader;
42.52 -import java.util.ArrayList;
42.53 -import java.util.Arrays;
42.54 -import java.util.Collection;
42.55 -import java.util.List;
42.56 -import javax.script.Invocable;
42.57 -import javax.script.ScriptEngine;
42.58 -import javax.script.ScriptEngineManager;
42.59 -import javax.script.ScriptException;
42.60 -import org.apidesign.html.boot.spi.Fn;
42.61 -import org.testng.annotations.BeforeClass;
42.62 -import org.testng.annotations.BeforeMethod;
42.63 -
42.64 -/**
42.65 - *
42.66 - * @author Jaroslav Tulach <jtulach@netbeans.org>
42.67 - */
42.68 -public class FnTest extends JsClassLoaderBase {
42.69 - private static Fn.Presenter presenter;
42.70 -
42.71 - public FnTest() {
42.72 - }
42.73 -
42.74 - @BeforeClass
42.75 - public static void createClassLoader() throws Exception {
42.76 - ScriptEngineManager sem = new ScriptEngineManager();
42.77 - final ScriptEngine eng = sem.getEngineByMimeType("text/javascript");
42.78 -
42.79 - final URL my = FnTest.class.getProtectionDomain().getCodeSource().getLocation();
42.80 - ClassLoader parent = JsClassLoaderTest.class.getClassLoader().getParent();
42.81 - final URLClassLoader ul = new URLClassLoader(new URL[] { my }, parent);
42.82 -
42.83 - class Impl implements FindResources, Fn.Presenter {
42.84 - @Override
42.85 - public void findResources(String path, Collection<? super URL> results, boolean oneIsEnough) {
42.86 - URL u = ul.findResource(path);
42.87 - if (u != null) {
42.88 - results.add(u);
42.89 - }
42.90 - }
42.91 -
42.92 - @Override
42.93 - public Fn defineFn(String code, String... names) {
42.94 - StringBuilder sb = new StringBuilder();
42.95 - sb.append("(function() {");
42.96 - sb.append("return function(");
42.97 - String sep = "";
42.98 - for (String n : names) {
42.99 - sb.append(sep);
42.100 - sb.append(n);
42.101 - sep = ", ";
42.102 - }
42.103 - sb.append(") {");
42.104 - sb.append(code);
42.105 - sb.append("};");
42.106 - sb.append("})()");
42.107 - try {
42.108 - final Object val = eng.eval(sb.toString());
42.109 - return new Fn(this) {
42.110 - @Override
42.111 - public Object invoke(Object thiz, Object... args) throws Exception {
42.112 - List<Object> all = new ArrayList<Object>(args.length + 1);
42.113 - all.add(thiz == null ? val : thiz);
42.114 - all.addAll(Arrays.asList(args));
42.115 - Invocable inv = (Invocable)eng;
42.116 - try {
42.117 - Object ret = inv.invokeMethod(val, "call", all.toArray());
42.118 - return val.equals(ret) ? null : ret;
42.119 - } catch (ScriptException ex) {
42.120 - throw ex;
42.121 - }
42.122 - }
42.123 - };
42.124 - } catch (ScriptException ex) {
42.125 - throw new LinkageError("Can't parse: " + sb, ex);
42.126 - }
42.127 - }
42.128 -
42.129 - @Override
42.130 - public void displayPage(URL resource, Runnable r) {
42.131 - throw new UnsupportedOperationException();
42.132 - }
42.133 -
42.134 - @Override
42.135 - public void loadScript(Reader code) throws Exception {
42.136 - eng.eval(code);
42.137 - }
42.138 - }
42.139 - Impl impl = new Impl();
42.140 - ClassLoader loader = FnUtils.newLoader(impl, impl, parent);
42.141 - presenter = impl;
42.142 -
42.143 - Closeable close = FnContext.activate(impl);
42.144 - methodClass = loader.loadClass(JsMethods.class.getName());
42.145 - close.close();
42.146 - }
42.147 -
42.148 - @BeforeMethod public void initPresenter() {
42.149 - FnContext.currentPresenter(presenter);
42.150 - }
42.151 -}
43.1 --- a/boot/src/test/java/org/apidesign/html/boot/impl/JavaScriptProcesorTest.java Mon Dec 16 15:48:09 2013 +0100
43.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
43.3 @@ -1,129 +0,0 @@
43.4 -/**
43.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
43.6 - *
43.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
43.8 - *
43.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
43.10 - * Other names may be trademarks of their respective owners.
43.11 - *
43.12 - * The contents of this file are subject to the terms of either the GNU
43.13 - * General Public License Version 2 only ("GPL") or the Common
43.14 - * Development and Distribution License("CDDL") (collectively, the
43.15 - * "License"). You may not use this file except in compliance with the
43.16 - * License. You can obtain a copy of the License at
43.17 - * http://www.netbeans.org/cddl-gplv2.html
43.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
43.19 - * specific language governing permissions and limitations under the
43.20 - * License. When distributing the software, include this License Header
43.21 - * Notice in each file and include the License file at
43.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
43.23 - * particular file as subject to the "Classpath" exception as provided
43.24 - * by Oracle in the GPL Version 2 section of the License file that
43.25 - * accompanied this code. If applicable, add the following below the
43.26 - * License Header, with the fields enclosed by brackets [] replaced by
43.27 - * your own identifying information:
43.28 - * "Portions Copyrighted [year] [name of copyright owner]"
43.29 - *
43.30 - * Contributor(s):
43.31 - *
43.32 - * The Original Software is NetBeans. The Initial Developer of the Original
43.33 - * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
43.34 - *
43.35 - * If you wish your version of this file to be governed by only the CDDL
43.36 - * or only the GPL Version 2, indicate your decision by adding
43.37 - * "[Contributor] elects to include this software in this distribution
43.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
43.39 - * single choice of license, a recipient has the option to distribute
43.40 - * your version of this file under either the CDDL, the GPL Version 2 or
43.41 - * to extend the choice of license to its licensees as provided above.
43.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
43.43 - * Version 2 license, then the option applies only if the new code is
43.44 - * made subject to such option by the copyright holder.
43.45 - */
43.46 -package org.apidesign.html.boot.impl;
43.47 -
43.48 -import java.io.IOException;
43.49 -import java.lang.reflect.Field;
43.50 -import java.lang.reflect.Method;
43.51 -import static org.testng.Assert.assertEquals;
43.52 -import static org.testng.Assert.assertTrue;
43.53 -import org.testng.annotations.Test;
43.54 -
43.55 -/**
43.56 - *
43.57 - * @author Jaroslav Tulach <jtulach@netbeans.org>
43.58 - */
43.59 -public class JavaScriptProcesorTest {
43.60 -
43.61 - @Test public void detectCallbackToNonExistingClass() throws IOException {
43.62 - String code = "package x.y.z;\n"
43.63 - + "import net.java.html.js.JavaScriptBody;\n"
43.64 - + "class X {\n"
43.65 - + " @JavaScriptBody(args={\"r\"}, javacall=true, body =\n"
43.66 - + " \"r.@java.lang.Runable::run()();\"\n" // typo
43.67 - + " )\n"
43.68 - + " private static native void callback(Runnable r);\n"
43.69 - + "}\n";
43.70 -
43.71 - Compile c = Compile.create("", code);
43.72 - c.assertErrors();
43.73 - c.assertError("java.lang.Runable"); // typo
43.74 - }
43.75 -
43.76 - @Test public void detectCallbackToNonExistingMethod() throws IOException {
43.77 - String code = "package x.y.z;\n"
43.78 - + "import net.java.html.js.JavaScriptBody;\n"
43.79 - + "class X {\n"
43.80 - + " @JavaScriptBody(args={\"r\"}, javacall=true, body =\n"
43.81 - + " \"r.@java.lang.Runnable::cancel()();\"\n"
43.82 - + " )\n"
43.83 - + " private static native void callback(Runnable r);\n"
43.84 - + "}\n";
43.85 -
43.86 - Compile c = Compile.create("", code);
43.87 - c.assertErrors();
43.88 - c.assertError("method cancel");
43.89 - }
43.90 -
43.91 - @Test public void detectCallbackToNonExistingParams() throws IOException {
43.92 - String code = "package x.y.z;\n"
43.93 - + "import net.java.html.js.JavaScriptBody;\n"
43.94 - + "class X {\n"
43.95 - + " @JavaScriptBody(args={\"r\"}, javacall=true, body =\n"
43.96 - + " \"r.@java.lang.Runnable::run(I)(10);\"\n"
43.97 - + " )\n"
43.98 - + " private static native void callback(Runnable r);\n"
43.99 - + "}\n";
43.100 -
43.101 - Compile c = Compile.create("", code);
43.102 - c.assertErrors();
43.103 - c.assertError("wrong parameters: (I)");
43.104 - }
43.105 -
43.106 - @Test public void objectTypeParamsAreOK() throws IOException {
43.107 - String code = "package x.y.z;\n"
43.108 - + "import net.java.html.js.JavaScriptBody;\n"
43.109 - + "class X {\n"
43.110 - + " @JavaScriptBody(args={\"r\"}, javacall=true, body =\n"
43.111 - + " \"r.@java.lang.Object::equals(Ljava/lang/Object;)(null);\"\n"
43.112 - + " )\n"
43.113 - + " private static native void testEqual(Object r);\n"
43.114 - + "}\n";
43.115 -
43.116 - Compile c = Compile.create("", code);
43.117 - c.assertNoErrors();
43.118 - }
43.119 -
43.120 - @Test public void generatesCallbacksThatReturnObject() throws Exception {
43.121 - Class<?> callbacksForTestPkg = Class.forName("org.apidesign.html.boot.impl.$JsCallbacks$");
43.122 - Method m = callbacksForTestPkg.getDeclaredMethod("java_lang_Runnable$run$", Runnable.class);
43.123 - assertEquals(m.getReturnType(), Object.class, "All methods always return object");
43.124 - }
43.125 -
43.126 - @Test public void hasInstanceField() throws Exception {
43.127 - Class<?> callbacksForTestPkg = Class.forName("org.apidesign.html.boot.impl.$JsCallbacks$");
43.128 - Field f = callbacksForTestPkg.getDeclaredField("VM");
43.129 - f.setAccessible(true);
43.130 - assertTrue(callbacksForTestPkg.isInstance(f.get(null)), "Singleton field VM");
43.131 - }
43.132 -}
44.1 --- a/boot/src/test/java/org/apidesign/html/boot/impl/JsClassLoaderBase.java Mon Dec 16 15:48:09 2013 +0100
44.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
44.3 @@ -1,201 +0,0 @@
44.4 -/**
44.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
44.6 - *
44.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
44.8 - *
44.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
44.10 - * Other names may be trademarks of their respective owners.
44.11 - *
44.12 - * The contents of this file are subject to the terms of either the GNU
44.13 - * General Public License Version 2 only ("GPL") or the Common
44.14 - * Development and Distribution License("CDDL") (collectively, the
44.15 - * "License"). You may not use this file except in compliance with the
44.16 - * License. You can obtain a copy of the License at
44.17 - * http://www.netbeans.org/cddl-gplv2.html
44.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
44.19 - * specific language governing permissions and limitations under the
44.20 - * License. When distributing the software, include this License Header
44.21 - * Notice in each file and include the License file at
44.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
44.23 - * particular file as subject to the "Classpath" exception as provided
44.24 - * by Oracle in the GPL Version 2 section of the License file that
44.25 - * accompanied this code. If applicable, add the following below the
44.26 - * License Header, with the fields enclosed by brackets [] replaced by
44.27 - * your own identifying information:
44.28 - * "Portions Copyrighted [year] [name of copyright owner]"
44.29 - *
44.30 - * Contributor(s):
44.31 - *
44.32 - * The Original Software is NetBeans. The Initial Developer of the Original
44.33 - * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
44.34 - *
44.35 - * If you wish your version of this file to be governed by only the CDDL
44.36 - * or only the GPL Version 2, indicate your decision by adding
44.37 - * "[Contributor] elects to include this software in this distribution
44.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
44.39 - * single choice of license, a recipient has the option to distribute
44.40 - * your version of this file under either the CDDL, the GPL Version 2 or
44.41 - * to extend the choice of license to its licensees as provided above.
44.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
44.43 - * Version 2 license, then the option applies only if the new code is
44.44 - * made subject to such option by the copyright holder.
44.45 - */
44.46 -package org.apidesign.html.boot.impl;
44.47 -
44.48 -import java.lang.reflect.InvocationTargetException;
44.49 -import java.lang.reflect.Method;
44.50 -import java.lang.reflect.Modifier;
44.51 -import static org.testng.Assert.*;
44.52 -import org.testng.annotations.BeforeMethod;
44.53 -import org.testng.annotations.Test;
44.54 -
44.55 -/**
44.56 - *
44.57 - * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
44.58 - */
44.59 -public class JsClassLoaderBase {
44.60 - protected static Class<?> methodClass;
44.61 -
44.62 - public JsClassLoaderBase() {
44.63 - }
44.64 -
44.65 - @BeforeMethod
44.66 - public void assertClassDefined() {
44.67 - assertNotNull(methodClass, "BeforeClass set up code should provide methodClass");
44.68 - }
44.69 -
44.70 - @Test public void noParamMethod() throws Throwable {
44.71 - Method plus = methodClass.getMethod("fortyTwo");
44.72 - try {
44.73 - final Object val = plus.invoke(null);
44.74 - assertTrue(val instanceof Number, "A number returned " + val);
44.75 - assertEquals(((Number)val).intValue(), 42);
44.76 - } catch (InvocationTargetException ex) {
44.77 - throw ex.getTargetException();
44.78 - }
44.79 - }
44.80 -
44.81 - @Test public void testExecuteScript() throws Throwable {
44.82 - Method plus = methodClass.getMethod("plus", int.class, int.class);
44.83 - try {
44.84 - assertEquals(plus.invoke(null, 10, 20), 30);
44.85 - } catch (InvocationTargetException ex) {
44.86 - throw ex.getTargetException();
44.87 - }
44.88 - }
44.89 -
44.90 - @Test public void overloadedMethod() throws Throwable {
44.91 - Method plus = methodClass.getMethod("plus", int.class);
44.92 - try {
44.93 - assertEquals(plus.invoke(null, 10), 10);
44.94 - } catch (InvocationTargetException ex) {
44.95 - throw ex.getTargetException();
44.96 - }
44.97 - }
44.98 -
44.99 - @Test public void instanceMethod() throws Throwable {
44.100 - Method plus = methodClass.getMethod("plusInst", int.class);
44.101 - Object inst = methodClass.newInstance();
44.102 - try {
44.103 - assertEquals(plus.invoke(inst, 10), 10);
44.104 - } catch (InvocationTargetException ex) {
44.105 - throw ex.getTargetException();
44.106 - }
44.107 - }
44.108 -
44.109 - @Test public void staticThis() throws Throwable {
44.110 - Method st = methodClass.getMethod("staticThis");
44.111 - try {
44.112 - assertNull(st.invoke(null));
44.113 - } catch (InvocationTargetException ex) {
44.114 - throw ex.getTargetException();
44.115 - }
44.116 - }
44.117 -
44.118 - @Test public void getThis() throws Throwable {
44.119 - Object th = methodClass.newInstance();
44.120 - Method st = methodClass.getMethod("getThis");
44.121 - try {
44.122 - assertEquals(st.invoke(th), th);
44.123 - } catch (InvocationTargetException ex) {
44.124 - throw ex.getTargetException();
44.125 - }
44.126 - }
44.127 -
44.128 - @Test public void truth() throws Throwable {
44.129 - Method st = methodClass.getMethod("truth");
44.130 - assertTrue((st.getModifiers() & Modifier.STATIC) != 0, "Is static");
44.131 - assertEquals(st.invoke(null), Boolean.TRUE, "Can return boolean");
44.132 - }
44.133 -
44.134 - @Test public void callback() throws Throwable {
44.135 - class R implements Runnable {
44.136 - int cnt;
44.137 -
44.138 - @Override
44.139 - public void run() {
44.140 - cnt++;
44.141 - }
44.142 - }
44.143 - R r = new R();
44.144 -
44.145 - Method inc = methodClass.getMethod("callback", Runnable.class);
44.146 - inc.invoke(null, r);
44.147 -
44.148 - assertEquals(r.cnt, 1, "Callback happened");
44.149 - }
44.150 -
44.151 - @Test public void sumArray() throws Throwable {
44.152 - Method st = methodClass.getMethod("sumArr", int[].class);
44.153 - assertEquals(st.invoke(null, new int[] { 1, 2, 3 }), 6, "1+2+3 is six");
44.154 - }
44.155 -
44.156 - @Test public void javaScriptResource() throws Throwable {
44.157 - try {
44.158 - Method st = methodClass.getMethod("useExternalMul", int.class, int.class);
44.159 - assertEquals(st.invoke(null, 6, 7), 42, "Meaning of JavaScript?");
44.160 - } catch (InvocationTargetException ex) {
44.161 - throw ex.getTargetException();
44.162 - }
44.163 - }
44.164 -
44.165 - @Test public void callJavaScriptMethodOnOwnClass() throws Throwable {
44.166 - try {
44.167 - Object thiz = methodClass.newInstance();
44.168 - Method st = methodClass.getMethod("returnYourSelf", methodClass);
44.169 - assertEquals(st.invoke(null, thiz), thiz, "Returns this");
44.170 - } catch (InvocationTargetException ex) {
44.171 - throw ex.getTargetException();
44.172 - }
44.173 - }
44.174 -
44.175 - @Test public void callStaticJavaMethod() throws Throwable {
44.176 - Method st = methodClass.getMethod("staticCallback", int.class, int.class);
44.177 - assertEquals(st.invoke(null, 6, 7), 42, "Meaning of JavaScript?");
44.178 - }
44.179 -
44.180 - @Test public void callStaticStringParamMethod() throws Throwable {
44.181 - Method st = methodClass.getMethod("parseInt", String.class);
44.182 - assertEquals(st.invoke(null, "42"), 42, "Meaning of JavaScript?");
44.183 - }
44.184 -
44.185 - @Test public void firstLong() throws Throwable {
44.186 - Method st = methodClass.getMethod("chooseLong", boolean.class, boolean.class, long.class, long.class);
44.187 - assertEquals(st.invoke(null, true, false, 10, 20), 10L, "Take first value");
44.188 - }
44.189 -
44.190 - @Test public void secondLong() throws Throwable {
44.191 - Method st = methodClass.getMethod("chooseLong", boolean.class, boolean.class, long.class, long.class);
44.192 - assertEquals(st.invoke(null, false, true, 10, 20), 20L, "Take 2nd value");
44.193 - }
44.194 -
44.195 - @Test public void bothLong() throws Throwable {
44.196 - Method st = methodClass.getMethod("chooseLong", boolean.class, boolean.class, long.class, long.class);
44.197 - assertEquals(st.invoke(null, true, true, 10, 20), 30L, "Take both values");
44.198 - }
44.199 -
44.200 - @Test public void recordError() throws Throwable {
44.201 - Method st = methodClass.getMethod("recordError", Object.class);
44.202 - assertEquals(st.invoke(methodClass.newInstance(), "Hello"), "Hello", "The same parameter returned");
44.203 - }
44.204 -}
44.205 \ No newline at end of file
45.1 --- a/boot/src/test/java/org/apidesign/html/boot/impl/JsClassLoaderTest.java Mon Dec 16 15:48:09 2013 +0100
45.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
45.3 @@ -1,155 +0,0 @@
45.4 -/**
45.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
45.6 - *
45.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
45.8 - *
45.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
45.10 - * Other names may be trademarks of their respective owners.
45.11 - *
45.12 - * The contents of this file are subject to the terms of either the GNU
45.13 - * General Public License Version 2 only ("GPL") or the Common
45.14 - * Development and Distribution License("CDDL") (collectively, the
45.15 - * "License"). You may not use this file except in compliance with the
45.16 - * License. You can obtain a copy of the License at
45.17 - * http://www.netbeans.org/cddl-gplv2.html
45.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
45.19 - * specific language governing permissions and limitations under the
45.20 - * License. When distributing the software, include this License Header
45.21 - * Notice in each file and include the License file at
45.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
45.23 - * particular file as subject to the "Classpath" exception as provided
45.24 - * by Oracle in the GPL Version 2 section of the License file that
45.25 - * accompanied this code. If applicable, add the following below the
45.26 - * License Header, with the fields enclosed by brackets [] replaced by
45.27 - * your own identifying information:
45.28 - * "Portions Copyrighted [year] [name of copyright owner]"
45.29 - *
45.30 - * Contributor(s):
45.31 - *
45.32 - * The Original Software is NetBeans. The Initial Developer of the Original
45.33 - * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
45.34 - *
45.35 - * If you wish your version of this file to be governed by only the CDDL
45.36 - * or only the GPL Version 2, indicate your decision by adding
45.37 - * "[Contributor] elects to include this software in this distribution
45.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
45.39 - * single choice of license, a recipient has the option to distribute
45.40 - * your version of this file under either the CDDL, the GPL Version 2 or
45.41 - * to extend the choice of license to its licensees as provided above.
45.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
45.43 - * Version 2 license, then the option applies only if the new code is
45.44 - * made subject to such option by the copyright holder.
45.45 - */
45.46 -package org.apidesign.html.boot.impl;
45.47 -
45.48 -import java.io.Closeable;
45.49 -import java.io.Reader;
45.50 -import org.apidesign.html.boot.spi.Fn;
45.51 -import java.net.URL;
45.52 -import java.net.URLClassLoader;
45.53 -import java.util.ArrayList;
45.54 -import java.util.Arrays;
45.55 -import java.util.Enumeration;
45.56 -import java.util.List;
45.57 -import javax.script.Invocable;
45.58 -import javax.script.ScriptEngine;
45.59 -import javax.script.ScriptEngineManager;
45.60 -import javax.script.ScriptException;
45.61 -import org.testng.annotations.AfterClass;
45.62 -import org.testng.annotations.BeforeClass;
45.63 -import org.testng.annotations.BeforeMethod;
45.64 -
45.65 -/**
45.66 - *
45.67 - * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
45.68 - */
45.69 -public class JsClassLoaderTest extends JsClassLoaderBase{
45.70 - private static Fn.Presenter loader;
45.71 -
45.72 - @BeforeClass
45.73 - public static void setUpClass() throws Exception {
45.74 - ScriptEngineManager sem = new ScriptEngineManager();
45.75 - final ScriptEngine eng = sem.getEngineByMimeType("text/javascript");
45.76 -
45.77 - final URL my = JsClassLoaderTest.class.getProtectionDomain().getCodeSource().getLocation();
45.78 - ClassLoader parent = JsClassLoaderTest.class.getClassLoader().getParent();
45.79 - final URLClassLoader ul = new URLClassLoader(new URL[] { my }, parent);
45.80 - class MyCL extends JsClassLoader implements Fn.Presenter {
45.81 -
45.82 - public MyCL(ClassLoader parent) {
45.83 - super(parent);
45.84 - }
45.85 -
45.86 - @Override
45.87 - protected URL findResource(String name) {
45.88 - return ul.getResource(name);
45.89 - }
45.90 - @Override
45.91 - public Fn defineFn(String code, String... names) {
45.92 - StringBuilder sb = new StringBuilder();
45.93 - sb.append("(function() {");
45.94 - sb.append("return function(");
45.95 - String sep = "";
45.96 - for (String n : names) {
45.97 - sb.append(sep);
45.98 - sb.append(n);
45.99 - sep = ", ";
45.100 - }
45.101 - sb.append(") {");
45.102 - sb.append(code);
45.103 - sb.append("};");
45.104 - sb.append("})()");
45.105 - try {
45.106 - final Object val = eng.eval(sb.toString());
45.107 - return new Fn(this) {
45.108 - @Override
45.109 - public Object invoke(Object thiz, Object... args) throws Exception {
45.110 - List<Object> all = new ArrayList<Object>(args.length + 1);
45.111 - all.add(thiz == null ? val : thiz);
45.112 - all.addAll(Arrays.asList(args));
45.113 - Invocable inv = (Invocable)eng;
45.114 - try {
45.115 - Object ret = inv.invokeMethod(val, "call", all.toArray());
45.116 - return val.equals(ret) ? null : ret;
45.117 - } catch (Exception ex) {
45.118 - throw ex;
45.119 - }
45.120 - }
45.121 - };
45.122 - } catch (ScriptException ex) {
45.123 - throw new LinkageError("Can't parse: " + sb, ex);
45.124 - }
45.125 - }
45.126 -
45.127 - @Override
45.128 - protected Enumeration<URL> findResources(String name) {
45.129 - throw new UnsupportedOperationException();
45.130 - }
45.131 -
45.132 - @Override
45.133 - public void loadScript(Reader code) throws ScriptException {
45.134 - eng.eval(code);
45.135 - }
45.136 -
45.137 - @Override
45.138 - public void displayPage(URL page, Runnable onPageLoad) {
45.139 - throw new UnsupportedOperationException();
45.140 - }
45.141 - };
45.142 -
45.143 - MyCL l = new MyCL(parent);
45.144 - Closeable close = FnContext.activate(l);
45.145 - methodClass = l.loadClass(JsMethods.class.getName());
45.146 - close.close();
45.147 - loader = l;
45.148 - }
45.149 -
45.150 - @BeforeMethod public void initPresenter() {
45.151 - FnContext.currentPresenter(loader);
45.152 - }
45.153 -
45.154 - @AfterClass
45.155 - public static void cleanUp() {
45.156 - methodClass = null;
45.157 - }
45.158 -}
45.159 \ No newline at end of file
46.1 --- a/boot/src/test/java/org/apidesign/html/boot/impl/JsMethods.java Mon Dec 16 15:48:09 2013 +0100
46.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
46.3 @@ -1,129 +0,0 @@
46.4 -/**
46.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
46.6 - *
46.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
46.8 - *
46.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
46.10 - * Other names may be trademarks of their respective owners.
46.11 - *
46.12 - * The contents of this file are subject to the terms of either the GNU
46.13 - * General Public License Version 2 only ("GPL") or the Common
46.14 - * Development and Distribution License("CDDL") (collectively, the
46.15 - * "License"). You may not use this file except in compliance with the
46.16 - * License. You can obtain a copy of the License at
46.17 - * http://www.netbeans.org/cddl-gplv2.html
46.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
46.19 - * specific language governing permissions and limitations under the
46.20 - * License. When distributing the software, include this License Header
46.21 - * Notice in each file and include the License file at
46.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
46.23 - * particular file as subject to the "Classpath" exception as provided
46.24 - * by Oracle in the GPL Version 2 section of the License file that
46.25 - * accompanied this code. If applicable, add the following below the
46.26 - * License Header, with the fields enclosed by brackets [] replaced by
46.27 - * your own identifying information:
46.28 - * "Portions Copyrighted [year] [name of copyright owner]"
46.29 - *
46.30 - * Contributor(s):
46.31 - *
46.32 - * The Original Software is NetBeans. The Initial Developer of the Original
46.33 - * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
46.34 - *
46.35 - * If you wish your version of this file to be governed by only the CDDL
46.36 - * or only the GPL Version 2, indicate your decision by adding
46.37 - * "[Contributor] elects to include this software in this distribution
46.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
46.39 - * single choice of license, a recipient has the option to distribute
46.40 - * your version of this file under either the CDDL, the GPL Version 2 or
46.41 - * to extend the choice of license to its licensees as provided above.
46.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
46.43 - * Version 2 license, then the option applies only if the new code is
46.44 - * made subject to such option by the copyright holder.
46.45 - */
46.46 -package org.apidesign.html.boot.impl;
46.47 -
46.48 -import net.java.html.js.JavaScriptBody;
46.49 -import net.java.html.js.JavaScriptResource;
46.50 -
46.51 -
46.52 -/**
46.53 - *
46.54 - * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
46.55 - */
46.56 -@JavaScriptResource("jsmethods.js")
46.57 -public class JsMethods {
46.58 - private Object value;
46.59 -
46.60 - @JavaScriptBody(args = {}, body = "return 42;")
46.61 - public static Object fortyTwo() {
46.62 - return -42;
46.63 - }
46.64 -
46.65 - @JavaScriptBody(args = {"x", "y" }, body = "return x + y;")
46.66 - public static native int plus(int x, int y);
46.67 -
46.68 - @JavaScriptBody(args = {"x"}, body = "return x;")
46.69 - public static native int plus(int x);
46.70 -
46.71 - @JavaScriptBody(args = {}, body = "return this;")
46.72 - public static native Object staticThis();
46.73 -
46.74 - @JavaScriptBody(args = {}, body = "return this;")
46.75 - public native Object getThis();
46.76 - @JavaScriptBody(args = {"x"}, body = "return x;")
46.77 - public native int plusInst(int x);
46.78 -
46.79 - @JavaScriptBody(args = {}, body = "return true;")
46.80 - public static boolean truth() {
46.81 - return false;
46.82 - }
46.83 -
46.84 - @JavaScriptBody(args = { "r" }, javacall=true, body = "r.@java.lang.Runnable::run()();")
46.85 - public static native void callback(Runnable r);
46.86 -
46.87 - @JavaScriptBody(args = { "at", "arr" }, javacall = true, body =
46.88 - "var a = 0;\n"
46.89 - + "for (var i = 0; i < arr.length; i++) {\n"
46.90 - + " a = at.@org.apidesign.html.boot.impl.Arithm::sumTwo(II)(a, arr[i]);\n"
46.91 - + "}\n"
46.92 - + "return a;"
46.93 - )
46.94 - private static native int sumArr(Arithm at, int... arr);
46.95 -
46.96 - public static int sumArr(int... arr) {
46.97 - return sumArr(new Arithm(), arr);
46.98 - }
46.99 -
46.100 - @JavaScriptBody(args = { "x", "y" }, body = "return mul(x, y);")
46.101 - public static native int useExternalMul(int x, int y);
46.102 -
46.103 - @JavaScriptBody(args = { "m" }, javacall = true, body = "return m.@org.apidesign.html.boot.impl.JsMethods::getThis()();")
46.104 - public static native JsMethods returnYourSelf(JsMethods m);
46.105 -
46.106 - @JavaScriptBody(args = { "x", "y" }, javacall = true, body = "return @org.apidesign.html.boot.impl.JsMethods::useExternalMul(II)(x, y);")
46.107 - public static native int staticCallback(int x, int y);
46.108 -
46.109 - @JavaScriptBody(args = { "v" }, javacall = true, body = "return @java.lang.Integer::parseInt(Ljava/lang/String;)(v);")
46.110 - public static native int parseInt(String v);
46.111 -
46.112 - @JavaScriptBody(args = { "useA", "useB", "a", "b" }, body = "var l = 0;"
46.113 - + "if (useA) l += a;\n"
46.114 - + "if (useB) l += b;\n"
46.115 - + "return l;\n"
46.116 - )
46.117 - public static native long chooseLong(boolean useA, boolean useB, long a, long b);
46.118 -
46.119 - protected void onError(Object o) throws Exception {
46.120 - value = o;
46.121 - }
46.122 -
46.123 - Object getError() {
46.124 - return value;
46.125 - }
46.126 -
46.127 - @JavaScriptBody(args = { "err" }, javacall = true, body =
46.128 - "this.@org.apidesign.html.boot.impl.JsMethods::onError(Ljava/lang/Object;)(err);"
46.129 - + "return this.@org.apidesign.html.boot.impl.JsMethods::getError()();"
46.130 - )
46.131 - public native Object recordError(Object err);
46.132 -}
47.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
47.2 +++ b/boot/src/test/java/org/netbeans/html/boot/impl/Arithm.java Mon Dec 16 16:59:43 2013 +0100
47.3 @@ -0,0 +1,53 @@
47.4 +/**
47.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
47.6 + *
47.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
47.8 + *
47.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
47.10 + * Other names may be trademarks of their respective owners.
47.11 + *
47.12 + * The contents of this file are subject to the terms of either the GNU
47.13 + * General Public License Version 2 only ("GPL") or the Common
47.14 + * Development and Distribution License("CDDL") (collectively, the
47.15 + * "License"). You may not use this file except in compliance with the
47.16 + * License. You can obtain a copy of the License at
47.17 + * http://www.netbeans.org/cddl-gplv2.html
47.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
47.19 + * specific language governing permissions and limitations under the
47.20 + * License. When distributing the software, include this License Header
47.21 + * Notice in each file and include the License file at
47.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
47.23 + * particular file as subject to the "Classpath" exception as provided
47.24 + * by Oracle in the GPL Version 2 section of the License file that
47.25 + * accompanied this code. If applicable, add the following below the
47.26 + * License Header, with the fields enclosed by brackets [] replaced by
47.27 + * your own identifying information:
47.28 + * "Portions Copyrighted [year] [name of copyright owner]"
47.29 + *
47.30 + * Contributor(s):
47.31 + *
47.32 + * The Original Software is NetBeans. The Initial Developer of the Original
47.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
47.34 + *
47.35 + * If you wish your version of this file to be governed by only the CDDL
47.36 + * or only the GPL Version 2, indicate your decision by adding
47.37 + * "[Contributor] elects to include this software in this distribution
47.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
47.39 + * single choice of license, a recipient has the option to distribute
47.40 + * your version of this file under either the CDDL, the GPL Version 2 or
47.41 + * to extend the choice of license to its licensees as provided above.
47.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
47.43 + * Version 2 license, then the option applies only if the new code is
47.44 + * made subject to such option by the copyright holder.
47.45 + */
47.46 +package org.netbeans.html.boot.impl;
47.47 +
47.48 +/**
47.49 + *
47.50 + * @author Jaroslav Tulach <jtulach@netbeans.org>
47.51 + */
47.52 +public class Arithm {
47.53 + public int sumTwo(int a, int b) {
47.54 + return a + b;
47.55 + }
47.56 +}
48.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
48.2 +++ b/boot/src/test/java/org/netbeans/html/boot/impl/Compile.java Mon Dec 16 16:59:43 2013 +0100
48.3 @@ -0,0 +1,291 @@
48.4 +/**
48.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
48.6 + *
48.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
48.8 + *
48.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
48.10 + * Other names may be trademarks of their respective owners.
48.11 + *
48.12 + * The contents of this file are subject to the terms of either the GNU
48.13 + * General Public License Version 2 only ("GPL") or the Common
48.14 + * Development and Distribution License("CDDL") (collectively, the
48.15 + * "License"). You may not use this file except in compliance with the
48.16 + * License. You can obtain a copy of the License at
48.17 + * http://www.netbeans.org/cddl-gplv2.html
48.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
48.19 + * specific language governing permissions and limitations under the
48.20 + * License. When distributing the software, include this License Header
48.21 + * Notice in each file and include the License file at
48.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
48.23 + * particular file as subject to the "Classpath" exception as provided
48.24 + * by Oracle in the GPL Version 2 section of the License file that
48.25 + * accompanied this code. If applicable, add the following below the
48.26 + * License Header, with the fields enclosed by brackets [] replaced by
48.27 + * your own identifying information:
48.28 + * "Portions Copyrighted [year] [name of copyright owner]"
48.29 + *
48.30 + * Contributor(s):
48.31 + *
48.32 + * The Original Software is NetBeans. The Initial Developer of the Original
48.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
48.34 + *
48.35 + * If you wish your version of this file to be governed by only the CDDL
48.36 + * or only the GPL Version 2, indicate your decision by adding
48.37 + * "[Contributor] elects to include this software in this distribution
48.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
48.39 + * single choice of license, a recipient has the option to distribute
48.40 + * your version of this file under either the CDDL, the GPL Version 2 or
48.41 + * to extend the choice of license to its licensees as provided above.
48.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
48.43 + * Version 2 license, then the option applies only if the new code is
48.44 + * made subject to such option by the copyright holder.
48.45 + */
48.46 +package org.netbeans.html.boot.impl;
48.47 +
48.48 +import java.io.ByteArrayInputStream;
48.49 +import java.io.ByteArrayOutputStream;
48.50 +import java.io.IOException;
48.51 +import java.io.InputStream;
48.52 +import java.io.OutputStream;
48.53 +import java.net.URI;
48.54 +import java.net.URISyntaxException;
48.55 +import java.util.ArrayList;
48.56 +import java.util.Arrays;
48.57 +import java.util.HashMap;
48.58 +import java.util.List;
48.59 +import java.util.Locale;
48.60 +import java.util.Map;
48.61 +import java.util.regex.Matcher;
48.62 +import java.util.regex.Pattern;
48.63 +import javax.tools.Diagnostic;
48.64 +import javax.tools.DiagnosticListener;
48.65 +import javax.tools.FileObject;
48.66 +import javax.tools.ForwardingJavaFileManager;
48.67 +import javax.tools.JavaFileManager;
48.68 +import javax.tools.JavaFileObject;
48.69 +import javax.tools.JavaFileObject.Kind;
48.70 +import javax.tools.SimpleJavaFileObject;
48.71 +import javax.tools.StandardJavaFileManager;
48.72 +import javax.tools.StandardLocation;
48.73 +import javax.tools.ToolProvider;
48.74 +import static org.testng.Assert.assertTrue;
48.75 +import static org.testng.Assert.assertFalse;
48.76 +import static org.testng.Assert.fail;
48.77 +
48.78 +/**
48.79 + *
48.80 + * @author Jaroslav Tulach <jtulach@netbeans.org>
48.81 + */
48.82 +final class Compile implements DiagnosticListener<JavaFileObject> {
48.83 + private final List<Diagnostic<? extends JavaFileObject>> errors =
48.84 + new ArrayList<Diagnostic<? extends JavaFileObject>>();
48.85 + private final Map<String, byte[]> classes;
48.86 + private final String pkg;
48.87 + private final String cls;
48.88 + private final String html;
48.89 + private final String sourceLevel;
48.90 +
48.91 + private Compile(String html, String code, String sl) throws IOException {
48.92 + this.pkg = findPkg(code);
48.93 + this.cls = findCls(code);
48.94 + this.html = html;
48.95 + this.sourceLevel = sl;
48.96 + classes = compile(html, code);
48.97 + }
48.98 +
48.99 + /** Performs compilation of given HTML page and associated Java code
48.100 + */
48.101 + public static Compile create(String html, String code) throws IOException {
48.102 + return create(html, code, "1.7");
48.103 + }
48.104 + static Compile create(String html, String code, String sourceLevel) throws IOException {
48.105 + return new Compile(html, code, sourceLevel);
48.106 + }
48.107 +
48.108 + /** Checks for given class among compiled resources */
48.109 + public byte[] get(String res) {
48.110 + return classes.get(res);
48.111 + }
48.112 +
48.113 + /** Obtains errors created during compilation.
48.114 + */
48.115 + public List<Diagnostic<? extends JavaFileObject>> getErrors() {
48.116 + List<Diagnostic<? extends JavaFileObject>> err;
48.117 + err = new ArrayList<Diagnostic<? extends JavaFileObject>>();
48.118 + for (Diagnostic<? extends JavaFileObject> diagnostic : errors) {
48.119 + if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
48.120 + err.add(diagnostic);
48.121 + }
48.122 + }
48.123 + return err;
48.124 + }
48.125 +
48.126 + private Map<String, byte[]> compile(final String html, final String code) throws IOException {
48.127 + StandardJavaFileManager sjfm = ToolProvider.getSystemJavaCompiler().getStandardFileManager(this, null, null);
48.128 +
48.129 + final Map<String, ByteArrayOutputStream> class2BAOS;
48.130 + class2BAOS = new HashMap<String, ByteArrayOutputStream>();
48.131 +
48.132 + JavaFileObject file = new SimpleJavaFileObject(URI.create("mem://mem"), Kind.SOURCE) {
48.133 + @Override
48.134 + public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
48.135 + return code;
48.136 + }
48.137 + };
48.138 + final JavaFileObject htmlFile = new SimpleJavaFileObject(URI.create("mem://mem2"), Kind.OTHER) {
48.139 + @Override
48.140 + public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
48.141 + return html;
48.142 + }
48.143 +
48.144 + @Override
48.145 + public InputStream openInputStream() throws IOException {
48.146 + return new ByteArrayInputStream(html.getBytes());
48.147 + }
48.148 + };
48.149 +
48.150 + final URI scratch;
48.151 + try {
48.152 + scratch = new URI("mem://mem3");
48.153 + } catch (URISyntaxException ex) {
48.154 + throw new IOException(ex);
48.155 + }
48.156 +
48.157 + JavaFileManager jfm = new ForwardingJavaFileManager<JavaFileManager>(sjfm) {
48.158 + @Override
48.159 + public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) throws IOException {
48.160 + if (kind == Kind.CLASS) {
48.161 + final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
48.162 +
48.163 + class2BAOS.put(className.replace('.', '/') + ".class", buffer);
48.164 + return new SimpleJavaFileObject(sibling.toUri(), kind) {
48.165 + @Override
48.166 + public OutputStream openOutputStream() throws IOException {
48.167 + return buffer;
48.168 + }
48.169 + };
48.170 + }
48.171 +
48.172 + if (kind == Kind.SOURCE) {
48.173 + final String n = className.replace('.', '/') + ".java";
48.174 + final URI un;
48.175 + try {
48.176 + un = new URI("mem://" + n);
48.177 + } catch (URISyntaxException ex) {
48.178 + throw new IOException(ex);
48.179 + }
48.180 + return new VirtFO(un/*sibling.toUri()*/, kind, n);
48.181 + }
48.182 +
48.183 + throw new IllegalStateException();
48.184 + }
48.185 +
48.186 + @Override
48.187 + public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException {
48.188 + if (location == StandardLocation.SOURCE_PATH) {
48.189 + if (packageName.equals(pkg)) {
48.190 + return htmlFile;
48.191 + }
48.192 + }
48.193 +
48.194 + return null;
48.195 + }
48.196 +
48.197 + @Override
48.198 + public boolean isSameFile(FileObject a, FileObject b) {
48.199 + if (a instanceof VirtFO && b instanceof VirtFO) {
48.200 + return ((VirtFO)a).getName().equals(((VirtFO)b).getName());
48.201 + }
48.202 +
48.203 + return super.isSameFile(a, b);
48.204 + }
48.205 +
48.206 + class VirtFO extends SimpleJavaFileObject {
48.207 +
48.208 + private final String n;
48.209 +
48.210 + public VirtFO(URI uri, Kind kind, String n) {
48.211 + super(uri, kind);
48.212 + this.n = n;
48.213 + }
48.214 + private final ByteArrayOutputStream data = new ByteArrayOutputStream();
48.215 +
48.216 + @Override
48.217 + public OutputStream openOutputStream() throws IOException {
48.218 + return data;
48.219 + }
48.220 +
48.221 + @Override
48.222 + public String getName() {
48.223 + return n;
48.224 + }
48.225 +
48.226 + @Override
48.227 + public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
48.228 + data.close();
48.229 + return new String(data.toByteArray());
48.230 + }
48.231 + }
48.232 + };
48.233 +
48.234 + ToolProvider.getSystemJavaCompiler().getTask(null, jfm, this, /*XXX:*/Arrays.asList("-source", sourceLevel, "-target", "1.7"), null, Arrays.asList(file)).call();
48.235 +
48.236 + Map<String, byte[]> result = new HashMap<String, byte[]>();
48.237 +
48.238 + for (Map.Entry<String, ByteArrayOutputStream> e : class2BAOS.entrySet()) {
48.239 + result.put(e.getKey(), e.getValue().toByteArray());
48.240 + }
48.241 +
48.242 + return result;
48.243 + }
48.244 +
48.245 +
48.246 + @Override
48.247 + public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
48.248 + errors.add(diagnostic);
48.249 + }
48.250 + private static String findPkg(String java) throws IOException {
48.251 + Pattern p = Pattern.compile("package\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}*;", Pattern.MULTILINE);
48.252 + Matcher m = p.matcher(java);
48.253 + if (!m.find()) {
48.254 + throw new IOException("Can't find package declaration in the java file");
48.255 + }
48.256 + String pkg = m.group(1);
48.257 + return pkg;
48.258 + }
48.259 + private static String findCls(String java) throws IOException {
48.260 + Pattern p = Pattern.compile("class\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}", Pattern.MULTILINE);
48.261 + Matcher m = p.matcher(java);
48.262 + if (!m.find()) {
48.263 + throw new IOException("Can't find package declaration in the java file");
48.264 + }
48.265 + String cls = m.group(1);
48.266 + return cls;
48.267 + }
48.268 +
48.269 + String getHtml() {
48.270 + String fqn = "'" + pkg + '.' + cls + "'";
48.271 + return html.replace("'${fqn}'", fqn);
48.272 + }
48.273 + void assertErrors() {
48.274 + assertFalse(getErrors().isEmpty(), "There are supposed to be some errors");
48.275 + }
48.276 +
48.277 + void assertError(String expMsg) {
48.278 + StringBuilder sb = new StringBuilder();
48.279 + sb.append("Can't find ").append(expMsg).append(" among:");
48.280 + for (Diagnostic<? extends JavaFileObject> e : errors) {
48.281 + String msg = e.getMessage(Locale.US);
48.282 + if (msg.contains(expMsg)) {
48.283 + return;
48.284 + }
48.285 + sb.append("\n");
48.286 + sb.append(msg);
48.287 + }
48.288 + fail(sb.toString());
48.289 + }
48.290 +
48.291 + void assertNoErrors() {
48.292 + assertTrue(getErrors().isEmpty(), "No errors expected: " + getErrors());
48.293 + }
48.294 +}
49.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
49.2 +++ b/boot/src/test/java/org/netbeans/html/boot/impl/FnTest.java Mon Dec 16 16:59:43 2013 +0100
49.3 @@ -0,0 +1,148 @@
49.4 +/**
49.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
49.6 + *
49.7 + * Copyright 1997-2010 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 java.io.Closeable;
49.49 +import java.io.Reader;
49.50 +import java.net.URL;
49.51 +import java.net.URLClassLoader;
49.52 +import java.util.ArrayList;
49.53 +import java.util.Arrays;
49.54 +import java.util.Collection;
49.55 +import java.util.List;
49.56 +import javax.script.Invocable;
49.57 +import javax.script.ScriptEngine;
49.58 +import javax.script.ScriptEngineManager;
49.59 +import javax.script.ScriptException;
49.60 +import org.apidesign.html.boot.spi.Fn;
49.61 +import org.testng.annotations.BeforeClass;
49.62 +import org.testng.annotations.BeforeMethod;
49.63 +
49.64 +/**
49.65 + *
49.66 + * @author Jaroslav Tulach <jtulach@netbeans.org>
49.67 + */
49.68 +public class FnTest extends JsClassLoaderBase {
49.69 + private static Fn.Presenter presenter;
49.70 +
49.71 + public FnTest() {
49.72 + }
49.73 +
49.74 + @BeforeClass
49.75 + public static void createClassLoader() throws Exception {
49.76 + ScriptEngineManager sem = new ScriptEngineManager();
49.77 + final ScriptEngine eng = sem.getEngineByMimeType("text/javascript");
49.78 +
49.79 + final URL my = FnTest.class.getProtectionDomain().getCodeSource().getLocation();
49.80 + ClassLoader parent = JsClassLoaderTest.class.getClassLoader().getParent();
49.81 + final URLClassLoader ul = new URLClassLoader(new URL[] { my }, parent);
49.82 +
49.83 + class Impl implements FindResources, Fn.Presenter {
49.84 + @Override
49.85 + public void findResources(String path, Collection<? super URL> results, boolean oneIsEnough) {
49.86 + URL u = ul.findResource(path);
49.87 + if (u != null) {
49.88 + results.add(u);
49.89 + }
49.90 + }
49.91 +
49.92 + @Override
49.93 + public Fn defineFn(String code, String... names) {
49.94 + StringBuilder sb = new StringBuilder();
49.95 + sb.append("(function() {");
49.96 + sb.append("return function(");
49.97 + String sep = "";
49.98 + for (String n : names) {
49.99 + sb.append(sep);
49.100 + sb.append(n);
49.101 + sep = ", ";
49.102 + }
49.103 + sb.append(") {");
49.104 + sb.append(code);
49.105 + sb.append("};");
49.106 + sb.append("})()");
49.107 + try {
49.108 + final Object val = eng.eval(sb.toString());
49.109 + return new Fn(this) {
49.110 + @Override
49.111 + public Object invoke(Object thiz, Object... args) throws Exception {
49.112 + List<Object> all = new ArrayList<Object>(args.length + 1);
49.113 + all.add(thiz == null ? val : thiz);
49.114 + all.addAll(Arrays.asList(args));
49.115 + Invocable inv = (Invocable)eng;
49.116 + try {
49.117 + Object ret = inv.invokeMethod(val, "call", all.toArray());
49.118 + return val.equals(ret) ? null : ret;
49.119 + } catch (ScriptException ex) {
49.120 + throw ex;
49.121 + }
49.122 + }
49.123 + };
49.124 + } catch (ScriptException ex) {
49.125 + throw new LinkageError("Can't parse: " + sb, ex);
49.126 + }
49.127 + }
49.128 +
49.129 + @Override
49.130 + public void displayPage(URL resource, Runnable r) {
49.131 + throw new UnsupportedOperationException();
49.132 + }
49.133 +
49.134 + @Override
49.135 + public void loadScript(Reader code) throws Exception {
49.136 + eng.eval(code);
49.137 + }
49.138 + }
49.139 + Impl impl = new Impl();
49.140 + ClassLoader loader = FnUtils.newLoader(impl, impl, parent);
49.141 + presenter = impl;
49.142 +
49.143 + Closeable close = FnContext.activate(impl);
49.144 + methodClass = loader.loadClass(JsMethods.class.getName());
49.145 + close.close();
49.146 + }
49.147 +
49.148 + @BeforeMethod public void initPresenter() {
49.149 + FnContext.currentPresenter(presenter);
49.150 + }
49.151 +}
50.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
50.2 +++ b/boot/src/test/java/org/netbeans/html/boot/impl/JavaScriptProcesorTest.java Mon Dec 16 16:59:43 2013 +0100
50.3 @@ -0,0 +1,129 @@
50.4 +/**
50.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
50.6 + *
50.7 + * Copyright 1997-2010 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.io.IOException;
50.49 +import java.lang.reflect.Field;
50.50 +import java.lang.reflect.Method;
50.51 +import static org.testng.Assert.assertEquals;
50.52 +import static org.testng.Assert.assertTrue;
50.53 +import org.testng.annotations.Test;
50.54 +
50.55 +/**
50.56 + *
50.57 + * @author Jaroslav Tulach <jtulach@netbeans.org>
50.58 + */
50.59 +public class JavaScriptProcesorTest {
50.60 +
50.61 + @Test public void detectCallbackToNonExistingClass() throws IOException {
50.62 + String code = "package x.y.z;\n"
50.63 + + "import net.java.html.js.JavaScriptBody;\n"
50.64 + + "class X {\n"
50.65 + + " @JavaScriptBody(args={\"r\"}, javacall=true, body =\n"
50.66 + + " \"r.@java.lang.Runable::run()();\"\n" // typo
50.67 + + " )\n"
50.68 + + " private static native void callback(Runnable r);\n"
50.69 + + "}\n";
50.70 +
50.71 + Compile c = Compile.create("", code);
50.72 + c.assertErrors();
50.73 + c.assertError("java.lang.Runable"); // typo
50.74 + }
50.75 +
50.76 + @Test public void detectCallbackToNonExistingMethod() throws IOException {
50.77 + String code = "package x.y.z;\n"
50.78 + + "import net.java.html.js.JavaScriptBody;\n"
50.79 + + "class X {\n"
50.80 + + " @JavaScriptBody(args={\"r\"}, javacall=true, body =\n"
50.81 + + " \"r.@java.lang.Runnable::cancel()();\"\n"
50.82 + + " )\n"
50.83 + + " private static native void callback(Runnable r);\n"
50.84 + + "}\n";
50.85 +
50.86 + Compile c = Compile.create("", code);
50.87 + c.assertErrors();
50.88 + c.assertError("method cancel");
50.89 + }
50.90 +
50.91 + @Test public void detectCallbackToNonExistingParams() throws IOException {
50.92 + String code = "package x.y.z;\n"
50.93 + + "import net.java.html.js.JavaScriptBody;\n"
50.94 + + "class X {\n"
50.95 + + " @JavaScriptBody(args={\"r\"}, javacall=true, body =\n"
50.96 + + " \"r.@java.lang.Runnable::run(I)(10);\"\n"
50.97 + + " )\n"
50.98 + + " private static native void callback(Runnable r);\n"
50.99 + + "}\n";
50.100 +
50.101 + Compile c = Compile.create("", code);
50.102 + c.assertErrors();
50.103 + c.assertError("wrong parameters: (I)");
50.104 + }
50.105 +
50.106 + @Test public void objectTypeParamsAreOK() throws IOException {
50.107 + String code = "package x.y.z;\n"
50.108 + + "import net.java.html.js.JavaScriptBody;\n"
50.109 + + "class X {\n"
50.110 + + " @JavaScriptBody(args={\"r\"}, javacall=true, body =\n"
50.111 + + " \"r.@java.lang.Object::equals(Ljava/lang/Object;)(null);\"\n"
50.112 + + " )\n"
50.113 + + " private static native void testEqual(Object r);\n"
50.114 + + "}\n";
50.115 +
50.116 + Compile c = Compile.create("", code);
50.117 + c.assertNoErrors();
50.118 + }
50.119 +
50.120 + @Test public void generatesCallbacksThatReturnObject() throws Exception {
50.121 + Class<?> callbacksForTestPkg = Class.forName("org.netbeans.html.boot.impl.$JsCallbacks$");
50.122 + Method m = callbacksForTestPkg.getDeclaredMethod("java_lang_Runnable$run$", Runnable.class);
50.123 + assertEquals(m.getReturnType(), Object.class, "All methods always return object");
50.124 + }
50.125 +
50.126 + @Test public void hasInstanceField() throws Exception {
50.127 + Class<?> callbacksForTestPkg = Class.forName("org.netbeans.html.boot.impl.$JsCallbacks$");
50.128 + Field f = callbacksForTestPkg.getDeclaredField("VM");
50.129 + f.setAccessible(true);
50.130 + assertTrue(callbacksForTestPkg.isInstance(f.get(null)), "Singleton field VM");
50.131 + }
50.132 +}
51.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
51.2 +++ b/boot/src/test/java/org/netbeans/html/boot/impl/JsClassLoaderBase.java Mon Dec 16 16:59:43 2013 +0100
51.3 @@ -0,0 +1,201 @@
51.4 +/**
51.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
51.6 + *
51.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
51.8 + *
51.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
51.10 + * Other names may be trademarks of their respective owners.
51.11 + *
51.12 + * The contents of this file are subject to the terms of either the GNU
51.13 + * General Public License Version 2 only ("GPL") or the Common
51.14 + * Development and Distribution License("CDDL") (collectively, the
51.15 + * "License"). You may not use this file except in compliance with the
51.16 + * License. You can obtain a copy of the License at
51.17 + * http://www.netbeans.org/cddl-gplv2.html
51.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
51.19 + * specific language governing permissions and limitations under the
51.20 + * License. When distributing the software, include this License Header
51.21 + * Notice in each file and include the License file at
51.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
51.23 + * particular file as subject to the "Classpath" exception as provided
51.24 + * by Oracle in the GPL Version 2 section of the License file that
51.25 + * accompanied this code. If applicable, add the following below the
51.26 + * License Header, with the fields enclosed by brackets [] replaced by
51.27 + * your own identifying information:
51.28 + * "Portions Copyrighted [year] [name of copyright owner]"
51.29 + *
51.30 + * Contributor(s):
51.31 + *
51.32 + * The Original Software is NetBeans. The Initial Developer of the Original
51.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
51.34 + *
51.35 + * If you wish your version of this file to be governed by only the CDDL
51.36 + * or only the GPL Version 2, indicate your decision by adding
51.37 + * "[Contributor] elects to include this software in this distribution
51.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
51.39 + * single choice of license, a recipient has the option to distribute
51.40 + * your version of this file under either the CDDL, the GPL Version 2 or
51.41 + * to extend the choice of license to its licensees as provided above.
51.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
51.43 + * Version 2 license, then the option applies only if the new code is
51.44 + * made subject to such option by the copyright holder.
51.45 + */
51.46 +package org.netbeans.html.boot.impl;
51.47 +
51.48 +import java.lang.reflect.InvocationTargetException;
51.49 +import java.lang.reflect.Method;
51.50 +import java.lang.reflect.Modifier;
51.51 +import static org.testng.Assert.*;
51.52 +import org.testng.annotations.BeforeMethod;
51.53 +import org.testng.annotations.Test;
51.54 +
51.55 +/**
51.56 + *
51.57 + * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
51.58 + */
51.59 +public class JsClassLoaderBase {
51.60 + protected static Class<?> methodClass;
51.61 +
51.62 + public JsClassLoaderBase() {
51.63 + }
51.64 +
51.65 + @BeforeMethod
51.66 + public void assertClassDefined() {
51.67 + assertNotNull(methodClass, "BeforeClass set up code should provide methodClass");
51.68 + }
51.69 +
51.70 + @Test public void noParamMethod() throws Throwable {
51.71 + Method plus = methodClass.getMethod("fortyTwo");
51.72 + try {
51.73 + final Object val = plus.invoke(null);
51.74 + assertTrue(val instanceof Number, "A number returned " + val);
51.75 + assertEquals(((Number)val).intValue(), 42);
51.76 + } catch (InvocationTargetException ex) {
51.77 + throw ex.getTargetException();
51.78 + }
51.79 + }
51.80 +
51.81 + @Test public void testExecuteScript() throws Throwable {
51.82 + Method plus = methodClass.getMethod("plus", int.class, int.class);
51.83 + try {
51.84 + assertEquals(plus.invoke(null, 10, 20), 30);
51.85 + } catch (InvocationTargetException ex) {
51.86 + throw ex.getTargetException();
51.87 + }
51.88 + }
51.89 +
51.90 + @Test public void overloadedMethod() throws Throwable {
51.91 + Method plus = methodClass.getMethod("plus", int.class);
51.92 + try {
51.93 + assertEquals(plus.invoke(null, 10), 10);
51.94 + } catch (InvocationTargetException ex) {
51.95 + throw ex.getTargetException();
51.96 + }
51.97 + }
51.98 +
51.99 + @Test public void instanceMethod() throws Throwable {
51.100 + Method plus = methodClass.getMethod("plusInst", int.class);
51.101 + Object inst = methodClass.newInstance();
51.102 + try {
51.103 + assertEquals(plus.invoke(inst, 10), 10);
51.104 + } catch (InvocationTargetException ex) {
51.105 + throw ex.getTargetException();
51.106 + }
51.107 + }
51.108 +
51.109 + @Test public void staticThis() throws Throwable {
51.110 + Method st = methodClass.getMethod("staticThis");
51.111 + try {
51.112 + assertNull(st.invoke(null));
51.113 + } catch (InvocationTargetException ex) {
51.114 + throw ex.getTargetException();
51.115 + }
51.116 + }
51.117 +
51.118 + @Test public void getThis() throws Throwable {
51.119 + Object th = methodClass.newInstance();
51.120 + Method st = methodClass.getMethod("getThis");
51.121 + try {
51.122 + assertEquals(st.invoke(th), th);
51.123 + } catch (InvocationTargetException ex) {
51.124 + throw ex.getTargetException();
51.125 + }
51.126 + }
51.127 +
51.128 + @Test public void truth() throws Throwable {
51.129 + Method st = methodClass.getMethod("truth");
51.130 + assertTrue((st.getModifiers() & Modifier.STATIC) != 0, "Is static");
51.131 + assertEquals(st.invoke(null), Boolean.TRUE, "Can return boolean");
51.132 + }
51.133 +
51.134 + @Test public void callback() throws Throwable {
51.135 + class R implements Runnable {
51.136 + int cnt;
51.137 +
51.138 + @Override
51.139 + public void run() {
51.140 + cnt++;
51.141 + }
51.142 + }
51.143 + R r = new R();
51.144 +
51.145 + Method inc = methodClass.getMethod("callback", Runnable.class);
51.146 + inc.invoke(null, r);
51.147 +
51.148 + assertEquals(r.cnt, 1, "Callback happened");
51.149 + }
51.150 +
51.151 + @Test public void sumArray() throws Throwable {
51.152 + Method st = methodClass.getMethod("sumArr", int[].class);
51.153 + assertEquals(st.invoke(null, new int[] { 1, 2, 3 }), 6, "1+2+3 is six");
51.154 + }
51.155 +
51.156 + @Test public void javaScriptResource() throws Throwable {
51.157 + try {
51.158 + Method st = methodClass.getMethod("useExternalMul", int.class, int.class);
51.159 + assertEquals(st.invoke(null, 6, 7), 42, "Meaning of JavaScript?");
51.160 + } catch (InvocationTargetException ex) {
51.161 + throw ex.getTargetException();
51.162 + }
51.163 + }
51.164 +
51.165 + @Test public void callJavaScriptMethodOnOwnClass() throws Throwable {
51.166 + try {
51.167 + Object thiz = methodClass.newInstance();
51.168 + Method st = methodClass.getMethod("returnYourSelf", methodClass);
51.169 + assertEquals(st.invoke(null, thiz), thiz, "Returns this");
51.170 + } catch (InvocationTargetException ex) {
51.171 + throw ex.getTargetException();
51.172 + }
51.173 + }
51.174 +
51.175 + @Test public void callStaticJavaMethod() throws Throwable {
51.176 + Method st = methodClass.getMethod("staticCallback", int.class, int.class);
51.177 + assertEquals(st.invoke(null, 6, 7), 42, "Meaning of JavaScript?");
51.178 + }
51.179 +
51.180 + @Test public void callStaticStringParamMethod() throws Throwable {
51.181 + Method st = methodClass.getMethod("parseInt", String.class);
51.182 + assertEquals(st.invoke(null, "42"), 42, "Meaning of JavaScript?");
51.183 + }
51.184 +
51.185 + @Test public void firstLong() throws Throwable {
51.186 + Method st = methodClass.getMethod("chooseLong", boolean.class, boolean.class, long.class, long.class);
51.187 + assertEquals(st.invoke(null, true, false, 10, 20), 10L, "Take first value");
51.188 + }
51.189 +
51.190 + @Test public void secondLong() throws Throwable {
51.191 + Method st = methodClass.getMethod("chooseLong", boolean.class, boolean.class, long.class, long.class);
51.192 + assertEquals(st.invoke(null, false, true, 10, 20), 20L, "Take 2nd value");
51.193 + }
51.194 +
51.195 + @Test public void bothLong() throws Throwable {
51.196 + Method st = methodClass.getMethod("chooseLong", boolean.class, boolean.class, long.class, long.class);
51.197 + assertEquals(st.invoke(null, true, true, 10, 20), 30L, "Take both values");
51.198 + }
51.199 +
51.200 + @Test public void recordError() throws Throwable {
51.201 + Method st = methodClass.getMethod("recordError", Object.class);
51.202 + assertEquals(st.invoke(methodClass.newInstance(), "Hello"), "Hello", "The same parameter returned");
51.203 + }
51.204 +}
51.205 \ No newline at end of file
52.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
52.2 +++ b/boot/src/test/java/org/netbeans/html/boot/impl/JsClassLoaderTest.java Mon Dec 16 16:59:43 2013 +0100
52.3 @@ -0,0 +1,155 @@
52.4 +/**
52.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
52.6 + *
52.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
52.8 + *
52.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
52.10 + * Other names may be trademarks of their respective owners.
52.11 + *
52.12 + * The contents of this file are subject to the terms of either the GNU
52.13 + * General Public License Version 2 only ("GPL") or the Common
52.14 + * Development and Distribution License("CDDL") (collectively, the
52.15 + * "License"). You may not use this file except in compliance with the
52.16 + * License. You can obtain a copy of the License at
52.17 + * http://www.netbeans.org/cddl-gplv2.html
52.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
52.19 + * specific language governing permissions and limitations under the
52.20 + * License. When distributing the software, include this License Header
52.21 + * Notice in each file and include the License file at
52.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
52.23 + * particular file as subject to the "Classpath" exception as provided
52.24 + * by Oracle in the GPL Version 2 section of the License file that
52.25 + * accompanied this code. If applicable, add the following below the
52.26 + * License Header, with the fields enclosed by brackets [] replaced by
52.27 + * your own identifying information:
52.28 + * "Portions Copyrighted [year] [name of copyright owner]"
52.29 + *
52.30 + * Contributor(s):
52.31 + *
52.32 + * The Original Software is NetBeans. The Initial Developer of the Original
52.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
52.34 + *
52.35 + * If you wish your version of this file to be governed by only the CDDL
52.36 + * or only the GPL Version 2, indicate your decision by adding
52.37 + * "[Contributor] elects to include this software in this distribution
52.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
52.39 + * single choice of license, a recipient has the option to distribute
52.40 + * your version of this file under either the CDDL, the GPL Version 2 or
52.41 + * to extend the choice of license to its licensees as provided above.
52.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
52.43 + * Version 2 license, then the option applies only if the new code is
52.44 + * made subject to such option by the copyright holder.
52.45 + */
52.46 +package org.netbeans.html.boot.impl;
52.47 +
52.48 +import java.io.Closeable;
52.49 +import java.io.Reader;
52.50 +import org.apidesign.html.boot.spi.Fn;
52.51 +import java.net.URL;
52.52 +import java.net.URLClassLoader;
52.53 +import java.util.ArrayList;
52.54 +import java.util.Arrays;
52.55 +import java.util.Enumeration;
52.56 +import java.util.List;
52.57 +import javax.script.Invocable;
52.58 +import javax.script.ScriptEngine;
52.59 +import javax.script.ScriptEngineManager;
52.60 +import javax.script.ScriptException;
52.61 +import org.testng.annotations.AfterClass;
52.62 +import org.testng.annotations.BeforeClass;
52.63 +import org.testng.annotations.BeforeMethod;
52.64 +
52.65 +/**
52.66 + *
52.67 + * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
52.68 + */
52.69 +public class JsClassLoaderTest extends JsClassLoaderBase{
52.70 + private static Fn.Presenter loader;
52.71 +
52.72 + @BeforeClass
52.73 + public static void setUpClass() throws Exception {
52.74 + ScriptEngineManager sem = new ScriptEngineManager();
52.75 + final ScriptEngine eng = sem.getEngineByMimeType("text/javascript");
52.76 +
52.77 + final URL my = JsClassLoaderTest.class.getProtectionDomain().getCodeSource().getLocation();
52.78 + ClassLoader parent = JsClassLoaderTest.class.getClassLoader().getParent();
52.79 + final URLClassLoader ul = new URLClassLoader(new URL[] { my }, parent);
52.80 + class MyCL extends JsClassLoader implements Fn.Presenter {
52.81 +
52.82 + public MyCL(ClassLoader parent) {
52.83 + super(parent);
52.84 + }
52.85 +
52.86 + @Override
52.87 + protected URL findResource(String name) {
52.88 + return ul.getResource(name);
52.89 + }
52.90 + @Override
52.91 + public Fn defineFn(String code, String... names) {
52.92 + StringBuilder sb = new StringBuilder();
52.93 + sb.append("(function() {");
52.94 + sb.append("return function(");
52.95 + String sep = "";
52.96 + for (String n : names) {
52.97 + sb.append(sep);
52.98 + sb.append(n);
52.99 + sep = ", ";
52.100 + }
52.101 + sb.append(") {");
52.102 + sb.append(code);
52.103 + sb.append("};");
52.104 + sb.append("})()");
52.105 + try {
52.106 + final Object val = eng.eval(sb.toString());
52.107 + return new Fn(this) {
52.108 + @Override
52.109 + public Object invoke(Object thiz, Object... args) throws Exception {
52.110 + List<Object> all = new ArrayList<Object>(args.length + 1);
52.111 + all.add(thiz == null ? val : thiz);
52.112 + all.addAll(Arrays.asList(args));
52.113 + Invocable inv = (Invocable)eng;
52.114 + try {
52.115 + Object ret = inv.invokeMethod(val, "call", all.toArray());
52.116 + return val.equals(ret) ? null : ret;
52.117 + } catch (Exception ex) {
52.118 + throw ex;
52.119 + }
52.120 + }
52.121 + };
52.122 + } catch (ScriptException ex) {
52.123 + throw new LinkageError("Can't parse: " + sb, ex);
52.124 + }
52.125 + }
52.126 +
52.127 + @Override
52.128 + protected Enumeration<URL> findResources(String name) {
52.129 + throw new UnsupportedOperationException();
52.130 + }
52.131 +
52.132 + @Override
52.133 + public void loadScript(Reader code) throws ScriptException {
52.134 + eng.eval(code);
52.135 + }
52.136 +
52.137 + @Override
52.138 + public void displayPage(URL page, Runnable onPageLoad) {
52.139 + throw new UnsupportedOperationException();
52.140 + }
52.141 + };
52.142 +
52.143 + MyCL l = new MyCL(parent);
52.144 + Closeable close = FnContext.activate(l);
52.145 + methodClass = l.loadClass(JsMethods.class.getName());
52.146 + close.close();
52.147 + loader = l;
52.148 + }
52.149 +
52.150 + @BeforeMethod public void initPresenter() {
52.151 + FnContext.currentPresenter(loader);
52.152 + }
52.153 +
52.154 + @AfterClass
52.155 + public static void cleanUp() {
52.156 + methodClass = null;
52.157 + }
52.158 +}
52.159 \ No newline at end of file
53.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
53.2 +++ b/boot/src/test/java/org/netbeans/html/boot/impl/JsMethods.java Mon Dec 16 16:59:43 2013 +0100
53.3 @@ -0,0 +1,129 @@
53.4 +/**
53.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
53.6 + *
53.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
53.8 + *
53.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
53.10 + * Other names may be trademarks of their respective owners.
53.11 + *
53.12 + * The contents of this file are subject to the terms of either the GNU
53.13 + * General Public License Version 2 only ("GPL") or the Common
53.14 + * Development and Distribution License("CDDL") (collectively, the
53.15 + * "License"). You may not use this file except in compliance with the
53.16 + * License. You can obtain a copy of the License at
53.17 + * http://www.netbeans.org/cddl-gplv2.html
53.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
53.19 + * specific language governing permissions and limitations under the
53.20 + * License. When distributing the software, include this License Header
53.21 + * Notice in each file and include the License file at
53.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
53.23 + * particular file as subject to the "Classpath" exception as provided
53.24 + * by Oracle in the GPL Version 2 section of the License file that
53.25 + * accompanied this code. If applicable, add the following below the
53.26 + * License Header, with the fields enclosed by brackets [] replaced by
53.27 + * your own identifying information:
53.28 + * "Portions Copyrighted [year] [name of copyright owner]"
53.29 + *
53.30 + * Contributor(s):
53.31 + *
53.32 + * The Original Software is NetBeans. The Initial Developer of the Original
53.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
53.34 + *
53.35 + * If you wish your version of this file to be governed by only the CDDL
53.36 + * or only the GPL Version 2, indicate your decision by adding
53.37 + * "[Contributor] elects to include this software in this distribution
53.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
53.39 + * single choice of license, a recipient has the option to distribute
53.40 + * your version of this file under either the CDDL, the GPL Version 2 or
53.41 + * to extend the choice of license to its licensees as provided above.
53.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
53.43 + * Version 2 license, then the option applies only if the new code is
53.44 + * made subject to such option by the copyright holder.
53.45 + */
53.46 +package org.netbeans.html.boot.impl;
53.47 +
53.48 +import net.java.html.js.JavaScriptBody;
53.49 +import net.java.html.js.JavaScriptResource;
53.50 +
53.51 +
53.52 +/**
53.53 + *
53.54 + * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
53.55 + */
53.56 +@JavaScriptResource("jsmethods.js")
53.57 +public class JsMethods {
53.58 + private Object value;
53.59 +
53.60 + @JavaScriptBody(args = {}, body = "return 42;")
53.61 + public static Object fortyTwo() {
53.62 + return -42;
53.63 + }
53.64 +
53.65 + @JavaScriptBody(args = {"x", "y" }, body = "return x + y;")
53.66 + public static native int plus(int x, int y);
53.67 +
53.68 + @JavaScriptBody(args = {"x"}, body = "return x;")
53.69 + public static native int plus(int x);
53.70 +
53.71 + @JavaScriptBody(args = {}, body = "return this;")
53.72 + public static native Object staticThis();
53.73 +
53.74 + @JavaScriptBody(args = {}, body = "return this;")
53.75 + public native Object getThis();
53.76 + @JavaScriptBody(args = {"x"}, body = "return x;")
53.77 + public native int plusInst(int x);
53.78 +
53.79 + @JavaScriptBody(args = {}, body = "return true;")
53.80 + public static boolean truth() {
53.81 + return false;
53.82 + }
53.83 +
53.84 + @JavaScriptBody(args = { "r" }, javacall=true, body = "r.@java.lang.Runnable::run()();")
53.85 + public static native void callback(Runnable r);
53.86 +
53.87 + @JavaScriptBody(args = { "at", "arr" }, javacall = true, body =
53.88 + "var a = 0;\n"
53.89 + + "for (var i = 0; i < arr.length; i++) {\n"
53.90 + + " a = at.@org.netbeans.html.boot.impl.Arithm::sumTwo(II)(a, arr[i]);\n"
53.91 + + "}\n"
53.92 + + "return a;"
53.93 + )
53.94 + private static native int sumArr(Arithm at, int... arr);
53.95 +
53.96 + public static int sumArr(int... arr) {
53.97 + return sumArr(new Arithm(), arr);
53.98 + }
53.99 +
53.100 + @JavaScriptBody(args = { "x", "y" }, body = "return mul(x, y);")
53.101 + public static native int useExternalMul(int x, int y);
53.102 +
53.103 + @JavaScriptBody(args = { "m" }, javacall = true, body = "return m.@org.netbeans.html.boot.impl.JsMethods::getThis()();")
53.104 + public static native JsMethods returnYourSelf(JsMethods m);
53.105 +
53.106 + @JavaScriptBody(args = { "x", "y" }, javacall = true, body = "return @org.netbeans.html.boot.impl.JsMethods::useExternalMul(II)(x, y);")
53.107 + public static native int staticCallback(int x, int y);
53.108 +
53.109 + @JavaScriptBody(args = { "v" }, javacall = true, body = "return @java.lang.Integer::parseInt(Ljava/lang/String;)(v);")
53.110 + public static native int parseInt(String v);
53.111 +
53.112 + @JavaScriptBody(args = { "useA", "useB", "a", "b" }, body = "var l = 0;"
53.113 + + "if (useA) l += a;\n"
53.114 + + "if (useB) l += b;\n"
53.115 + + "return l;\n"
53.116 + )
53.117 + public static native long chooseLong(boolean useA, boolean useB, long a, long b);
53.118 +
53.119 + protected void onError(Object o) throws Exception {
53.120 + value = o;
53.121 + }
53.122 +
53.123 + Object getError() {
53.124 + return value;
53.125 + }
53.126 +
53.127 + @JavaScriptBody(args = { "err" }, javacall = true, body =
53.128 + "this.@org.netbeans.html.boot.impl.JsMethods::onError(Ljava/lang/Object;)(err);"
53.129 + + "return this.@org.netbeans.html.boot.impl.JsMethods::getError()();"
53.130 + )
53.131 + public native Object recordError(Object err);
53.132 +}
54.1 --- a/boot/src/test/resources/org/apidesign/html/boot/impl/jsmethods.js Mon Dec 16 15:48:09 2013 +0100
54.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
54.3 @@ -1,43 +0,0 @@
54.4 -/*
54.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
54.6 - *
54.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
54.8 - *
54.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
54.10 - * Other names may be trademarks of their respective owners.
54.11 - *
54.12 - * The contents of this file are subject to the terms of either the GNU
54.13 - * General Public License Version 2 only ("GPL") or the Common
54.14 - * Development and Distribution License("CDDL") (collectively, the
54.15 - * "License"). You may not use this file except in compliance with the
54.16 - * License. You can obtain a copy of the License at
54.17 - * http://www.netbeans.org/cddl-gplv2.html
54.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
54.19 - * specific language governing permissions and limitations under the
54.20 - * License. When distributing the software, include this License Header
54.21 - * Notice in each file and include the License file at
54.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
54.23 - * particular file as subject to the "Classpath" exception as provided
54.24 - * by Oracle in the GPL Version 2 section of the License file that
54.25 - * accompanied this code. If applicable, add the following below the
54.26 - * License Header, with the fields enclosed by brackets [] replaced by
54.27 - * your own identifying information:
54.28 - * "Portions Copyrighted [year] [name of copyright owner]"
54.29 - *
54.30 - * Contributor(s):
54.31 - *
54.32 - * The Original Software is NetBeans. The Initial Developer of the Original
54.33 - * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
54.34 - *
54.35 - * If you wish your version of this file to be governed by only the CDDL
54.36 - * or only the GPL Version 2, indicate your decision by adding
54.37 - * "[Contributor] elects to include this software in this distribution
54.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
54.39 - * single choice of license, a recipient has the option to distribute
54.40 - * your version of this file under either the CDDL, the GPL Version 2 or
54.41 - * to extend the choice of license to its licensees as provided above.
54.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
54.43 - * Version 2 license, then the option applies only if the new code is
54.44 - * made subject to such option by the copyright holder.
54.45 - */
54.46 -function mul(x, y) { return x * y; }
55.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
55.2 +++ b/boot/src/test/resources/org/netbeans/html/boot/impl/jsmethods.js Mon Dec 16 16:59:43 2013 +0100
55.3 @@ -0,0 +1,43 @@
55.4 +/*
55.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
55.6 + *
55.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
55.8 + *
55.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
55.10 + * Other names may be trademarks of their respective owners.
55.11 + *
55.12 + * The contents of this file are subject to the terms of either the GNU
55.13 + * General Public License Version 2 only ("GPL") or the Common
55.14 + * Development and Distribution License("CDDL") (collectively, the
55.15 + * "License"). You may not use this file except in compliance with the
55.16 + * License. You can obtain a copy of the License at
55.17 + * http://www.netbeans.org/cddl-gplv2.html
55.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
55.19 + * specific language governing permissions and limitations under the
55.20 + * License. When distributing the software, include this License Header
55.21 + * Notice in each file and include the License file at
55.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
55.23 + * particular file as subject to the "Classpath" exception as provided
55.24 + * by Oracle in the GPL Version 2 section of the License file that
55.25 + * accompanied this code. If applicable, add the following below the
55.26 + * License Header, with the fields enclosed by brackets [] replaced by
55.27 + * your own identifying information:
55.28 + * "Portions Copyrighted [year] [name of copyright owner]"
55.29 + *
55.30 + * Contributor(s):
55.31 + *
55.32 + * The Original Software is NetBeans. The Initial Developer of the Original
55.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
55.34 + *
55.35 + * If you wish your version of this file to be governed by only the CDDL
55.36 + * or only the GPL Version 2, indicate your decision by adding
55.37 + * "[Contributor] elects to include this software in this distribution
55.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
55.39 + * single choice of license, a recipient has the option to distribute
55.40 + * your version of this file under either the CDDL, the GPL Version 2 or
55.41 + * to extend the choice of license to its licensees as provided above.
55.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
55.43 + * Version 2 license, then the option applies only if the new code is
55.44 + * made subject to such option by the copyright holder.
55.45 + */
55.46 +function mul(x, y) { return x * y; }
56.1 --- a/context/src/main/java/net/java/html/BrwsrCtx.java Mon Dec 16 15:48:09 2013 +0100
56.2 +++ b/context/src/main/java/net/java/html/BrwsrCtx.java Mon Dec 16 16:59:43 2013 +0100
56.3 @@ -44,8 +44,8 @@
56.4
56.5 import java.util.ServiceLoader;
56.6 import java.util.logging.Logger;
56.7 -import org.apidesign.html.context.impl.CtxAccssr;
56.8 -import org.apidesign.html.context.impl.CtxImpl;
56.9 +import org.netbeans.html.context.impl.CtxAccssr;
56.10 +import org.netbeans.html.context.impl.CtxImpl;
56.11 import org.apidesign.html.context.spi.Contexts;
56.12
56.13 /** Represents context where the <code>net.java.html.json.Model</code>
57.1 --- a/context/src/main/java/org/apidesign/html/context/impl/CtxAccssr.java Mon Dec 16 15:48:09 2013 +0100
57.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
57.3 @@ -1,74 +0,0 @@
57.4 -/**
57.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
57.6 - *
57.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
57.8 - *
57.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
57.10 - * Other names may be trademarks of their respective owners.
57.11 - *
57.12 - * The contents of this file are subject to the terms of either the GNU
57.13 - * General Public License Version 2 only ("GPL") or the Common
57.14 - * Development and Distribution License("CDDL") (collectively, the
57.15 - * "License"). You may not use this file except in compliance with the
57.16 - * License. You can obtain a copy of the License at
57.17 - * http://www.netbeans.org/cddl-gplv2.html
57.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
57.19 - * specific language governing permissions and limitations under the
57.20 - * License. When distributing the software, include this License Header
57.21 - * Notice in each file and include the License file at
57.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
57.23 - * particular file as subject to the "Classpath" exception as provided
57.24 - * by Oracle in the GPL Version 2 section of the License file that
57.25 - * accompanied this code. If applicable, add the following below the
57.26 - * License Header, with the fields enclosed by brackets [] replaced by
57.27 - * your own identifying information:
57.28 - * "Portions Copyrighted [year] [name of copyright owner]"
57.29 - *
57.30 - * Contributor(s):
57.31 - *
57.32 - * The Original Software is NetBeans. The Initial Developer of the Original
57.33 - * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
57.34 - *
57.35 - * If you wish your version of this file to be governed by only the CDDL
57.36 - * or only the GPL Version 2, indicate your decision by adding
57.37 - * "[Contributor] elects to include this software in this distribution
57.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
57.39 - * single choice of license, a recipient has the option to distribute
57.40 - * your version of this file under either the CDDL, the GPL Version 2 or
57.41 - * to extend the choice of license to its licensees as provided above.
57.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
57.43 - * Version 2 license, then the option applies only if the new code is
57.44 - * made subject to such option by the copyright holder.
57.45 - */
57.46 -package org.apidesign.html.context.impl;
57.47 -
57.48 -import net.java.html.BrwsrCtx;
57.49 -
57.50 -/** Internal communication between API (e.g. {@link BrwsrCtx}), SPI
57.51 - * (e.g. {@link ContextBuilder}) and the implementation package.
57.52 - *
57.53 - * @author Jaroslav Tulach <jtulach@netbeans.org>
57.54 - */
57.55 -public abstract class CtxAccssr {
57.56 - private static CtxAccssr DEFAULT;
57.57 - static {
57.58 - // run initializers
57.59 - try {
57.60 - BrwsrCtx.EMPTY.getClass();
57.61 - } catch (NullPointerException ex) {
57.62 - // ignore
57.63 - }
57.64 - }
57.65 -
57.66 - protected CtxAccssr() {
57.67 - if (DEFAULT != null) throw new IllegalStateException();
57.68 - DEFAULT = this;
57.69 - }
57.70 -
57.71 - protected abstract BrwsrCtx newContext(CtxImpl impl);
57.72 - protected abstract CtxImpl find(BrwsrCtx context);
57.73 -
57.74 - static CtxAccssr getDefault() {
57.75 - return DEFAULT;
57.76 - }
57.77 -}
58.1 --- a/context/src/main/java/org/apidesign/html/context/impl/CtxImpl.java Mon Dec 16 15:48:09 2013 +0100
58.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
58.3 @@ -1,110 +0,0 @@
58.4 -/**
58.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
58.6 - *
58.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
58.8 - *
58.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
58.10 - * Other names may be trademarks of their respective owners.
58.11 - *
58.12 - * The contents of this file are subject to the terms of either the GNU
58.13 - * General Public License Version 2 only ("GPL") or the Common
58.14 - * Development and Distribution License("CDDL") (collectively, the
58.15 - * "License"). You may not use this file except in compliance with the
58.16 - * License. You can obtain a copy of the License at
58.17 - * http://www.netbeans.org/cddl-gplv2.html
58.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
58.19 - * specific language governing permissions and limitations under the
58.20 - * License. When distributing the software, include this License Header
58.21 - * Notice in each file and include the License file at
58.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
58.23 - * particular file as subject to the "Classpath" exception as provided
58.24 - * by Oracle in the GPL Version 2 section of the License file that
58.25 - * accompanied this code. If applicable, add the following below the
58.26 - * License Header, with the fields enclosed by brackets [] replaced by
58.27 - * your own identifying information:
58.28 - * "Portions Copyrighted [year] [name of copyright owner]"
58.29 - *
58.30 - * Contributor(s):
58.31 - *
58.32 - * The Original Software is NetBeans. The Initial Developer of the Original
58.33 - * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
58.34 - *
58.35 - * If you wish your version of this file to be governed by only the CDDL
58.36 - * or only the GPL Version 2, indicate your decision by adding
58.37 - * "[Contributor] elects to include this software in this distribution
58.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
58.39 - * single choice of license, a recipient has the option to distribute
58.40 - * your version of this file under either the CDDL, the GPL Version 2 or
58.41 - * to extend the choice of license to its licensees as provided above.
58.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
58.43 - * Version 2 license, then the option applies only if the new code is
58.44 - * made subject to such option by the copyright holder.
58.45 - */
58.46 -package org.apidesign.html.context.impl;
58.47 -
58.48 -import java.util.ArrayList;
58.49 -import java.util.Collections;
58.50 -import java.util.List;
58.51 -import net.java.html.BrwsrCtx;
58.52 -
58.53 -/** Implementation detail. Holds list of technologies for particular
58.54 - * {@link BrwsrCtx}.
58.55 - *
58.56 - * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
58.57 - */
58.58 -public final class CtxImpl {
58.59 - private final List<Bind<?>> techs;
58.60 -
58.61 - public CtxImpl() {
58.62 - techs = new ArrayList<Bind<?>>();
58.63 - }
58.64 -
58.65 - private CtxImpl(List<Bind<?>> techs) {
58.66 - this.techs = techs;
58.67 - }
58.68 -
58.69 - public static <Tech> Tech find(BrwsrCtx context, Class<Tech> technology) {
58.70 - CtxImpl impl = CtxAccssr.getDefault().find(context);
58.71 - for (Bind<?> bind : impl.techs) {
58.72 - if (technology == bind.clazz) {
58.73 - return technology.cast(bind.impl);
58.74 - }
58.75 - }
58.76 - return null;
58.77 - }
58.78 -
58.79 - public BrwsrCtx build() {
58.80 - Collections.sort(techs);
58.81 - CtxImpl impl = new CtxImpl(Collections.unmodifiableList(techs));
58.82 - return CtxAccssr.getDefault().newContext(impl);
58.83 - }
58.84 -
58.85 - public <Tech> void register(Class<Tech> type, Tech impl, int priority) {
58.86 - techs.add(new Bind<Tech>(type, impl, priority));
58.87 - }
58.88 -
58.89 - private static final class Bind<Tech> implements Comparable<Bind<?>> {
58.90 - private final Class<Tech> clazz;
58.91 - private final Tech impl;
58.92 - private final int priority;
58.93 -
58.94 - public Bind(Class<Tech> clazz, Tech impl, int priority) {
58.95 - this.clazz = clazz;
58.96 - this.impl = impl;
58.97 - this.priority = priority;
58.98 - }
58.99 -
58.100 - @Override
58.101 - public int compareTo(Bind<?> o) {
58.102 - if (priority != o.priority) {
58.103 - return priority - o.priority;
58.104 - }
58.105 - return clazz.getName().compareTo(o.clazz.getName());
58.106 - }
58.107 -
58.108 - @Override
58.109 - public String toString() {
58.110 - return "Bind{" + "clazz=" + clazz + "@" + clazz.getClassLoader() + ", impl=" + impl + ", priority=" + priority + '}';
58.111 - }
58.112 - }
58.113 -}
59.1 --- a/context/src/main/java/org/apidesign/html/context/spi/Contexts.java Mon Dec 16 15:48:09 2013 +0100
59.2 +++ b/context/src/main/java/org/apidesign/html/context/spi/Contexts.java Mon Dec 16 16:59:43 2013 +0100
59.3 @@ -43,7 +43,7 @@
59.4 package org.apidesign.html.context.spi;
59.5
59.6 import net.java.html.BrwsrCtx;
59.7 -import org.apidesign.html.context.impl.CtxImpl;
59.8 +import org.netbeans.html.context.impl.CtxImpl;
59.9
59.10 /**
59.11 *
60.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
60.2 +++ b/context/src/main/java/org/netbeans/html/context/impl/CtxAccssr.java Mon Dec 16 16:59:43 2013 +0100
60.3 @@ -0,0 +1,74 @@
60.4 +/**
60.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
60.6 + *
60.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
60.8 + *
60.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
60.10 + * Other names may be trademarks of their respective owners.
60.11 + *
60.12 + * The contents of this file are subject to the terms of either the GNU
60.13 + * General Public License Version 2 only ("GPL") or the Common
60.14 + * Development and Distribution License("CDDL") (collectively, the
60.15 + * "License"). You may not use this file except in compliance with the
60.16 + * License. You can obtain a copy of the License at
60.17 + * http://www.netbeans.org/cddl-gplv2.html
60.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
60.19 + * specific language governing permissions and limitations under the
60.20 + * License. When distributing the software, include this License Header
60.21 + * Notice in each file and include the License file at
60.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
60.23 + * particular file as subject to the "Classpath" exception as provided
60.24 + * by Oracle in the GPL Version 2 section of the License file that
60.25 + * accompanied this code. If applicable, add the following below the
60.26 + * License Header, with the fields enclosed by brackets [] replaced by
60.27 + * your own identifying information:
60.28 + * "Portions Copyrighted [year] [name of copyright owner]"
60.29 + *
60.30 + * Contributor(s):
60.31 + *
60.32 + * The Original Software is NetBeans. The Initial Developer of the Original
60.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
60.34 + *
60.35 + * If you wish your version of this file to be governed by only the CDDL
60.36 + * or only the GPL Version 2, indicate your decision by adding
60.37 + * "[Contributor] elects to include this software in this distribution
60.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
60.39 + * single choice of license, a recipient has the option to distribute
60.40 + * your version of this file under either the CDDL, the GPL Version 2 or
60.41 + * to extend the choice of license to its licensees as provided above.
60.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
60.43 + * Version 2 license, then the option applies only if the new code is
60.44 + * made subject to such option by the copyright holder.
60.45 + */
60.46 +package org.netbeans.html.context.impl;
60.47 +
60.48 +import net.java.html.BrwsrCtx;
60.49 +
60.50 +/** Internal communication between API (e.g. {@link BrwsrCtx}), SPI
60.51 + * (e.g. {@link ContextBuilder}) and the implementation package.
60.52 + *
60.53 + * @author Jaroslav Tulach <jtulach@netbeans.org>
60.54 + */
60.55 +public abstract class CtxAccssr {
60.56 + private static CtxAccssr DEFAULT;
60.57 + static {
60.58 + // run initializers
60.59 + try {
60.60 + BrwsrCtx.EMPTY.getClass();
60.61 + } catch (NullPointerException ex) {
60.62 + // ignore
60.63 + }
60.64 + }
60.65 +
60.66 + protected CtxAccssr() {
60.67 + if (DEFAULT != null) throw new IllegalStateException();
60.68 + DEFAULT = this;
60.69 + }
60.70 +
60.71 + protected abstract BrwsrCtx newContext(CtxImpl impl);
60.72 + protected abstract CtxImpl find(BrwsrCtx context);
60.73 +
60.74 + static CtxAccssr getDefault() {
60.75 + return DEFAULT;
60.76 + }
60.77 +}
61.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
61.2 +++ b/context/src/main/java/org/netbeans/html/context/impl/CtxImpl.java Mon Dec 16 16:59:43 2013 +0100
61.3 @@ -0,0 +1,110 @@
61.4 +/**
61.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
61.6 + *
61.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
61.8 + *
61.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
61.10 + * Other names may be trademarks of their respective owners.
61.11 + *
61.12 + * The contents of this file are subject to the terms of either the GNU
61.13 + * General Public License Version 2 only ("GPL") or the Common
61.14 + * Development and Distribution License("CDDL") (collectively, the
61.15 + * "License"). You may not use this file except in compliance with the
61.16 + * License. You can obtain a copy of the License at
61.17 + * http://www.netbeans.org/cddl-gplv2.html
61.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
61.19 + * specific language governing permissions and limitations under the
61.20 + * License. When distributing the software, include this License Header
61.21 + * Notice in each file and include the License file at
61.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
61.23 + * particular file as subject to the "Classpath" exception as provided
61.24 + * by Oracle in the GPL Version 2 section of the License file that
61.25 + * accompanied this code. If applicable, add the following below the
61.26 + * License Header, with the fields enclosed by brackets [] replaced by
61.27 + * your own identifying information:
61.28 + * "Portions Copyrighted [year] [name of copyright owner]"
61.29 + *
61.30 + * Contributor(s):
61.31 + *
61.32 + * The Original Software is NetBeans. The Initial Developer of the Original
61.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
61.34 + *
61.35 + * If you wish your version of this file to be governed by only the CDDL
61.36 + * or only the GPL Version 2, indicate your decision by adding
61.37 + * "[Contributor] elects to include this software in this distribution
61.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
61.39 + * single choice of license, a recipient has the option to distribute
61.40 + * your version of this file under either the CDDL, the GPL Version 2 or
61.41 + * to extend the choice of license to its licensees as provided above.
61.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
61.43 + * Version 2 license, then the option applies only if the new code is
61.44 + * made subject to such option by the copyright holder.
61.45 + */
61.46 +package org.netbeans.html.context.impl;
61.47 +
61.48 +import java.util.ArrayList;
61.49 +import java.util.Collections;
61.50 +import java.util.List;
61.51 +import net.java.html.BrwsrCtx;
61.52 +
61.53 +/** Implementation detail. Holds list of technologies for particular
61.54 + * {@link BrwsrCtx}.
61.55 + *
61.56 + * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
61.57 + */
61.58 +public final class CtxImpl {
61.59 + private final List<Bind<?>> techs;
61.60 +
61.61 + public CtxImpl() {
61.62 + techs = new ArrayList<Bind<?>>();
61.63 + }
61.64 +
61.65 + private CtxImpl(List<Bind<?>> techs) {
61.66 + this.techs = techs;
61.67 + }
61.68 +
61.69 + public static <Tech> Tech find(BrwsrCtx context, Class<Tech> technology) {
61.70 + CtxImpl impl = CtxAccssr.getDefault().find(context);
61.71 + for (Bind<?> bind : impl.techs) {
61.72 + if (technology == bind.clazz) {
61.73 + return technology.cast(bind.impl);
61.74 + }
61.75 + }
61.76 + return null;
61.77 + }
61.78 +
61.79 + public BrwsrCtx build() {
61.80 + Collections.sort(techs);
61.81 + CtxImpl impl = new CtxImpl(Collections.unmodifiableList(techs));
61.82 + return CtxAccssr.getDefault().newContext(impl);
61.83 + }
61.84 +
61.85 + public <Tech> void register(Class<Tech> type, Tech impl, int priority) {
61.86 + techs.add(new Bind<Tech>(type, impl, priority));
61.87 + }
61.88 +
61.89 + private static final class Bind<Tech> implements Comparable<Bind<?>> {
61.90 + private final Class<Tech> clazz;
61.91 + private final Tech impl;
61.92 + private final int priority;
61.93 +
61.94 + public Bind(Class<Tech> clazz, Tech impl, int priority) {
61.95 + this.clazz = clazz;
61.96 + this.impl = impl;
61.97 + this.priority = priority;
61.98 + }
61.99 +
61.100 + @Override
61.101 + public int compareTo(Bind<?> o) {
61.102 + if (priority != o.priority) {
61.103 + return priority - o.priority;
61.104 + }
61.105 + return clazz.getName().compareTo(o.clazz.getName());
61.106 + }
61.107 +
61.108 + @Override
61.109 + public String toString() {
61.110 + return "Bind{" + "clazz=" + clazz + "@" + clazz.getClassLoader() + ", impl=" + impl + ", priority=" + priority + '}';
61.111 + }
61.112 + }
61.113 +}
62.1 --- a/geo/src/main/java/net/java/html/geo/Position.java Mon Dec 16 15:48:09 2013 +0100
62.2 +++ b/geo/src/main/java/net/java/html/geo/Position.java Mon Dec 16 16:59:43 2013 +0100
62.3 @@ -44,7 +44,7 @@
62.4
62.5 import java.util.logging.Level;
62.6 import java.util.logging.Logger;
62.7 -import org.apidesign.html.geo.impl.JsG;
62.8 +import org.netbeans.html.geo.impl.JsG;
62.9
62.10 /** Class that represents a geolocation position provided as a callback
62.11 * to {@link Handle#onLocation(net.java.html.geo.Position)} method. The
63.1 --- a/geo/src/main/java/org/apidesign/html/geo/impl/GeoProcessor.java Mon Dec 16 15:48:09 2013 +0100
63.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
63.3 @@ -1,289 +0,0 @@
63.4 -/**
63.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
63.6 - *
63.7 - * Copyright 1997-2010 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.apidesign.html.geo.impl;
63.47 -
63.48 -import java.io.IOException;
63.49 -import java.io.Writer;
63.50 -import java.util.List;
63.51 -import java.util.Locale;
63.52 -import java.util.Set;
63.53 -import java.util.logging.Level;
63.54 -import java.util.logging.Logger;
63.55 -import javax.annotation.processing.AbstractProcessor;
63.56 -import javax.annotation.processing.Processor;
63.57 -import javax.annotation.processing.RoundEnvironment;
63.58 -import javax.annotation.processing.SupportedAnnotationTypes;
63.59 -import javax.annotation.processing.SupportedSourceVersion;
63.60 -import javax.lang.model.SourceVersion;
63.61 -import javax.lang.model.element.Element;
63.62 -import javax.lang.model.element.ElementKind;
63.63 -import javax.lang.model.element.ExecutableElement;
63.64 -import javax.lang.model.element.Modifier;
63.65 -import javax.lang.model.element.PackageElement;
63.66 -import javax.lang.model.element.TypeElement;
63.67 -import javax.lang.model.element.VariableElement;
63.68 -import javax.lang.model.type.TypeMirror;
63.69 -import javax.tools.Diagnostic;
63.70 -import javax.tools.JavaFileObject;
63.71 -import net.java.html.geo.OnLocation;
63.72 -import net.java.html.geo.Position;
63.73 -import org.openide.util.lookup.ServiceProvider;
63.74 -
63.75 -/** Annotation processor to generate callbacks from {@link GeoHandle} class.
63.76 - *
63.77 - * @author Jaroslav Tulach <jtulach@netbeans.org>
63.78 - */
63.79 -@ServiceProvider(service=Processor.class)
63.80 -@SupportedSourceVersion(SourceVersion.RELEASE_6)
63.81 -@SupportedAnnotationTypes({
63.82 - "net.java.html.geo.OnLocation"
63.83 -})
63.84 -public final class GeoProcessor extends AbstractProcessor {
63.85 - private static final Logger LOG = Logger.getLogger(GeoProcessor.class.getName());
63.86 - @Override
63.87 - public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
63.88 - boolean ok = true;
63.89 - for (Element e : roundEnv.getElementsAnnotatedWith(OnLocation.class)) {
63.90 - if (!processLocation(e)) {
63.91 - ok = false;
63.92 - }
63.93 - }
63.94 - return ok;
63.95 - }
63.96 -
63.97 - private void error(String msg, Element e) {
63.98 - processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, msg, e);
63.99 - }
63.100 -
63.101 - private boolean processLocation(Element e) {
63.102 - if (e.getKind() != ElementKind.METHOD) {
63.103 - return false;
63.104 - }
63.105 - ExecutableElement me = (ExecutableElement) e;
63.106 - OnLocation ol = e.getAnnotation(OnLocation.class);
63.107 - if (ol == null) {
63.108 - return true;
63.109 - }
63.110 - if (me.getModifiers().contains(Modifier.PRIVATE)) {
63.111 - error("Method annotated by @OnLocation cannot be private", e);
63.112 - return false;
63.113 - }
63.114 - TypeMirror positionClass = processingEnv.getElementUtils().getTypeElement(Position.class.getName()).asType();
63.115 - final List<? extends VariableElement> params = me.getParameters();
63.116 - if (params.size() < 1 || !params.get(0).asType().equals(positionClass)) {
63.117 - error("Method annotated by @OnLocation first argument must be net.java.html.geo.Position!", e);
63.118 - return false;
63.119 - }
63.120 - String className = ol.className();
63.121 - if (className.isEmpty()) {
63.122 - String n = e.getSimpleName().toString();
63.123 - if (n.isEmpty()) {
63.124 - error("Empty method name", e);
63.125 - return false;
63.126 - }
63.127 - final String firstLetter = n.substring(0, 1).toUpperCase(Locale.ENGLISH);
63.128 - className = firstLetter + n.substring(1) + "Handle";
63.129 - }
63.130 - TypeElement te = (TypeElement)e.getEnclosingElement();
63.131 - PackageElement pe = (PackageElement) te.getEnclosingElement();
63.132 - final String pkg = pe.getQualifiedName().toString();
63.133 - final String fqn = pkg + "." + className;
63.134 - final boolean isStatic = me.getModifiers().contains(Modifier.STATIC);
63.135 - String sep;
63.136 - try {
63.137 - JavaFileObject fo = processingEnv.getFiler().createSourceFile(fqn, e);
63.138 - Writer w = fo.openWriter();
63.139 - w.append("package ").append(pkg).append(";\n");
63.140 - w.append("class ").append(className).append(" extends net.java.html.geo.Position.Handle {\n");
63.141 - if (!isStatic) {
63.142 - w.append(" private final ").append(te.getSimpleName()).append(" $i;\n");
63.143 - }
63.144 - for (int i = 1; i < params.size(); i++) {
63.145 - final VariableElement p = params.get(i);
63.146 - w.append(" private final ").append(p.asType().toString()).append(" ").append(p.getSimpleName()).append(";\n");
63.147 - }
63.148 - w.append(" private ").append(className).append("(boolean oneTime");
63.149 - w.append(", ").append(te.getSimpleName()).append(" i");
63.150 - for (int i = 1; i < params.size(); i++) {
63.151 - final VariableElement p = params.get(i);
63.152 - w.append(", ").append(p.asType().toString()).append(" ").append(p.getSimpleName());
63.153 - }
63.154 - w.append(") {\n super(oneTime);\n");
63.155 - if (!isStatic) {
63.156 - w.append(" this.$i = i;\n");
63.157 - }
63.158 - for (int i = 1; i < params.size(); i++) {
63.159 - final VariableElement p = params.get(i);
63.160 - w.append(" this.").append(p.getSimpleName()).append(" = ").append(p.getSimpleName()).append(";\n");
63.161 - }
63.162 - w.append("}\n");
63.163 - w.append(" static net.java.html.geo.Position.Handle createQuery(");
63.164 - String inst;
63.165 - if (!isStatic) {
63.166 - w.append(te.getSimpleName()).append(" instance");
63.167 - inst = "instance";
63.168 - sep = ", ";
63.169 - } else {
63.170 - inst = "null";
63.171 - sep = "";
63.172 - }
63.173 - for (int i = 1; i < params.size(); i++) {
63.174 - final VariableElement p = params.get(i);
63.175 - w.append(sep).append(p.asType().toString()).append(" ").append(p.getSimpleName());
63.176 - sep = ", ";
63.177 - }
63.178 - w.append(") { return new ").append(className).append("(true, ").append(inst);
63.179 - for (int i = 1; i < params.size(); i++) {
63.180 - final VariableElement p = params.get(i);
63.181 - w.append(", ").append(p.getSimpleName());
63.182 - }
63.183 - w.append("); }\n");
63.184 - w.append(" static net.java.html.geo.Position.Handle createWatch(");
63.185 - if (!isStatic) {
63.186 - w.append(te.getSimpleName()).append(" instance");
63.187 - sep = ", ";
63.188 - } else {
63.189 - sep = "";
63.190 - }
63.191 - for (int i = 1; i < params.size(); i++) {
63.192 - final VariableElement p = params.get(i);
63.193 - w.append(sep).append(p.asType().toString()).append(" ").append(p.getSimpleName());
63.194 - }
63.195 - w.append(") { return new ").append(className).append("(false, ").append(inst);
63.196 - for (int i = 1; i < params.size(); i++) {
63.197 - final VariableElement p = params.get(i);
63.198 - w.append(", ").append(p.getSimpleName());
63.199 - }
63.200 - w.append("); }\n");
63.201 - w.append(" @Override protected void onError(Exception t) throws Throwable {\n");
63.202 - if (ol.onError().isEmpty()) {
63.203 - w.append(" t.printStackTrace();");
63.204 - } else {
63.205 - if (!findOnError(me, te, ol.onError(), isStatic)) {
63.206 - return false;
63.207 - }
63.208 - if (isStatic) {
63.209 - w.append(" ").append(te.getSimpleName()).append(".");
63.210 - } else {
63.211 - w.append(" $i.");
63.212 - }
63.213 - w.append(ol.onError()).append("(t");
63.214 - for (int i = 1; i < params.size(); i++) {
63.215 - final VariableElement p = params.get(i);
63.216 - w.append(", ").append(p.getSimpleName());
63.217 - }
63.218 - w.append(");\n");
63.219 - }
63.220 - w.append(" }\n");
63.221 - w.append(" @Override protected void onLocation(net.java.html.geo.Position p) throws Throwable {\n");
63.222 - if (isStatic) {
63.223 - w.append(" ").append(te.getSimpleName()).append(".");
63.224 - } else {
63.225 - w.append(" $i.");
63.226 - }
63.227 - w.append(me.getSimpleName()).append("(p");
63.228 - for (int i = 1; i < params.size(); i++) {
63.229 - final VariableElement p = params.get(i);
63.230 - w.append(", ").append(p.getSimpleName());
63.231 - }
63.232 - w.append(");\n");
63.233 - w.append(" }\n");
63.234 - w.append("}\n");
63.235 - w.close();
63.236 - } catch (IOException ex) {
63.237 - Logger.getLogger(GeoProcessor.class.getName()).log(Level.SEVERE, null, ex);
63.238 - error("Can't write handler class: " + ex.getMessage(), e);
63.239 - return false;
63.240 - }
63.241 -
63.242 - return true;
63.243 - }
63.244 -
63.245 - private boolean findOnError(ExecutableElement errElem, TypeElement te, String name, boolean onlyStatic) {
63.246 - String err = null;
63.247 - METHODS: for (Element e : te.getEnclosedElements()) {
63.248 - if (e.getKind() != ElementKind.METHOD) {
63.249 - continue;
63.250 - }
63.251 - if (!e.getSimpleName().contentEquals(name)) {
63.252 - continue;
63.253 - }
63.254 - if (onlyStatic && !e.getModifiers().contains(Modifier.STATIC)) {
63.255 - errElem = (ExecutableElement) e;
63.256 - err = "Would have to be static";
63.257 - continue;
63.258 - }
63.259 - ExecutableElement ee = (ExecutableElement) e;
63.260 - TypeMirror excType = processingEnv.getElementUtils().getTypeElement(Exception.class.getName()).asType();
63.261 - final List<? extends VariableElement> params = ee.getParameters();
63.262 - if (params.size() < 1 ||
63.263 - !processingEnv.getTypeUtils().isAssignable(excType, ee.getParameters().get(0).asType())
63.264 - ) {
63.265 - errElem = (ExecutableElement) e;
63.266 - err = "Error method first argument needs to be Exception";
63.267 - continue;
63.268 - }
63.269 - final List<? extends Element> origParams = errElem.getParameters();
63.270 - if (params.size() != origParams.size()) {
63.271 - errElem = (ExecutableElement) e;
63.272 - err = "Error method must have the same parameters as @OnLocation one";
63.273 - continue;
63.274 - }
63.275 - for (int i = 1; i < origParams.size(); i++) {
63.276 - final TypeMirror t1 = params.get(i).asType();
63.277 - final TypeMirror t2 = origParams.get(i).asType();
63.278 - if (!processingEnv.getTypeUtils().isSameType(t1, t2)) {
63.279 - errElem = (ExecutableElement) e;
63.280 - err = "Error method must have the same parameters as @OnLocation one";
63.281 - continue METHODS;
63.282 - }
63.283 - }
63.284 - return true;
63.285 - }
63.286 - if (err == null) {
63.287 - err = "Cannot find " + name + "(Exception) method in this class";
63.288 - }
63.289 - error(err, errElem);
63.290 - return false;
63.291 - }
63.292 -}
64.1 --- a/geo/src/main/java/org/apidesign/html/geo/impl/JsG.java Mon Dec 16 15:48:09 2013 +0100
64.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
64.3 @@ -1,107 +0,0 @@
64.4 -/**
64.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
64.6 - *
64.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
64.8 - *
64.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
64.10 - * Other names may be trademarks of their respective owners.
64.11 - *
64.12 - * The contents of this file are subject to the terms of either the GNU
64.13 - * General Public License Version 2 only ("GPL") or the Common
64.14 - * Development and Distribution License("CDDL") (collectively, the
64.15 - * "License"). You may not use this file except in compliance with the
64.16 - * License. You can obtain a copy of the License at
64.17 - * http://www.netbeans.org/cddl-gplv2.html
64.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
64.19 - * specific language governing permissions and limitations under the
64.20 - * License. When distributing the software, include this License Header
64.21 - * Notice in each file and include the License file at
64.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
64.23 - * particular file as subject to the "Classpath" exception as provided
64.24 - * by Oracle in the GPL Version 2 section of the License file that
64.25 - * accompanied this code. If applicable, add the following below the
64.26 - * License Header, with the fields enclosed by brackets [] replaced by
64.27 - * your own identifying information:
64.28 - * "Portions Copyrighted [year] [name of copyright owner]"
64.29 - *
64.30 - * Contributor(s):
64.31 - *
64.32 - * The Original Software is NetBeans. The Initial Developer of the Original
64.33 - * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
64.34 - *
64.35 - * If you wish your version of this file to be governed by only the CDDL
64.36 - * or only the GPL Version 2, indicate your decision by adding
64.37 - * "[Contributor] elects to include this software in this distribution
64.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
64.39 - * single choice of license, a recipient has the option to distribute
64.40 - * your version of this file under either the CDDL, the GPL Version 2 or
64.41 - * to extend the choice of license to its licensees as provided above.
64.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
64.43 - * Version 2 license, then the option applies only if the new code is
64.44 - * made subject to such option by the copyright holder.
64.45 - */
64.46 -package org.apidesign.html.geo.impl;
64.47 -
64.48 -import net.java.html.js.JavaScriptBody;
64.49 -
64.50 -/** Implementation class to deal with browser's <code>navigator.geolocation</code>
64.51 - * object.
64.52 - *
64.53 - * @author Jaroslav Tulach <jtulach@netbeans.org>
64.54 - */
64.55 -public abstract class JsG {
64.56 - protected JsG() {
64.57 - if (!getClass().getName().equals("net.java.html.geo.Position$Handle$JsH")) {
64.58 - throw new IllegalStateException();
64.59 - }
64.60 - }
64.61 -
64.62 - public abstract void onLocation(Object position);
64.63 - public abstract void onError(Object error);
64.64 -
64.65 - @JavaScriptBody(args = {}, body = "return !!navigator.geolocation;")
64.66 - public static boolean hasGeolocation() {
64.67 - return false;
64.68 - }
64.69 -
64.70 - @JavaScriptBody(
64.71 - args = { "onlyOnce", "enableHighAccuracy", "timeout", "maximumAge" },
64.72 - javacall = true,
64.73 - body =
64.74 - "var self = this;\n" +
64.75 - "var ok = function (position) {\n" +
64.76 - " self.@org.apidesign.html.geo.impl.JsG::onLocation(Ljava/lang/Object;)(position);\n" +
64.77 - "};\n" +
64.78 - "var fail = function (error) {\n" +
64.79 - " self.@org.apidesign.html.geo.impl.JsG::onError(Ljava/lang/Object;)(error);\n" +
64.80 - "};\n" +
64.81 - "var options = {};\n" +
64.82 - "options.enableHighAccuracy = enableHighAccuracy;\n" +
64.83 - "if (timeout >= 0) options.timeout = timeout;\n" +
64.84 - "if (maximumAge >= 0) options.maximumAge = maximumAge;\n" +
64.85 - "if (onlyOnce) {\n" +
64.86 - " navigator.geolocation.getCurrentPosition(ok, fail);\n" +
64.87 - " return 0;\n" +
64.88 - "} else {\n" +
64.89 - " return navigator.geolocation.watchPosition(ok, fail);\n" +
64.90 - "}\n"
64.91 - )
64.92 - protected long start(
64.93 - boolean onlyOnce,
64.94 - boolean enableHighAccuracy,
64.95 - long timeout,
64.96 - long maximumAge
64.97 - ) {
64.98 - return -1;
64.99 - }
64.100 -
64.101 - @JavaScriptBody(args = { "watch" }, body = "navigator.geolocation.clearWatch(watch);")
64.102 - protected void stop(long watch) {
64.103 - }
64.104 -
64.105 - @JavaScriptBody(args = { "self", "property" }, body = "return self[property];")
64.106 - public static Object get(Object self, String property) {
64.107 - return null;
64.108 - }
64.109 -
64.110 -}
65.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
65.2 +++ b/geo/src/main/java/org/netbeans/html/geo/impl/GeoProcessor.java Mon Dec 16 16:59:43 2013 +0100
65.3 @@ -0,0 +1,289 @@
65.4 +/**
65.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
65.6 + *
65.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
65.8 + *
65.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
65.10 + * Other names may be trademarks of their respective owners.
65.11 + *
65.12 + * The contents of this file are subject to the terms of either the GNU
65.13 + * General Public License Version 2 only ("GPL") or the Common
65.14 + * Development and Distribution License("CDDL") (collectively, the
65.15 + * "License"). You may not use this file except in compliance with the
65.16 + * License. You can obtain a copy of the License at
65.17 + * http://www.netbeans.org/cddl-gplv2.html
65.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
65.19 + * specific language governing permissions and limitations under the
65.20 + * License. When distributing the software, include this License Header
65.21 + * Notice in each file and include the License file at
65.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
65.23 + * particular file as subject to the "Classpath" exception as provided
65.24 + * by Oracle in the GPL Version 2 section of the License file that
65.25 + * accompanied this code. If applicable, add the following below the
65.26 + * License Header, with the fields enclosed by brackets [] replaced by
65.27 + * your own identifying information:
65.28 + * "Portions Copyrighted [year] [name of copyright owner]"
65.29 + *
65.30 + * Contributor(s):
65.31 + *
65.32 + * The Original Software is NetBeans. The Initial Developer of the Original
65.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
65.34 + *
65.35 + * If you wish your version of this file to be governed by only the CDDL
65.36 + * or only the GPL Version 2, indicate your decision by adding
65.37 + * "[Contributor] elects to include this software in this distribution
65.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
65.39 + * single choice of license, a recipient has the option to distribute
65.40 + * your version of this file under either the CDDL, the GPL Version 2 or
65.41 + * to extend the choice of license to its licensees as provided above.
65.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
65.43 + * Version 2 license, then the option applies only if the new code is
65.44 + * made subject to such option by the copyright holder.
65.45 + */
65.46 +package org.netbeans.html.geo.impl;
65.47 +
65.48 +import java.io.IOException;
65.49 +import java.io.Writer;
65.50 +import java.util.List;
65.51 +import java.util.Locale;
65.52 +import java.util.Set;
65.53 +import java.util.logging.Level;
65.54 +import java.util.logging.Logger;
65.55 +import javax.annotation.processing.AbstractProcessor;
65.56 +import javax.annotation.processing.Processor;
65.57 +import javax.annotation.processing.RoundEnvironment;
65.58 +import javax.annotation.processing.SupportedAnnotationTypes;
65.59 +import javax.annotation.processing.SupportedSourceVersion;
65.60 +import javax.lang.model.SourceVersion;
65.61 +import javax.lang.model.element.Element;
65.62 +import javax.lang.model.element.ElementKind;
65.63 +import javax.lang.model.element.ExecutableElement;
65.64 +import javax.lang.model.element.Modifier;
65.65 +import javax.lang.model.element.PackageElement;
65.66 +import javax.lang.model.element.TypeElement;
65.67 +import javax.lang.model.element.VariableElement;
65.68 +import javax.lang.model.type.TypeMirror;
65.69 +import javax.tools.Diagnostic;
65.70 +import javax.tools.JavaFileObject;
65.71 +import net.java.html.geo.OnLocation;
65.72 +import net.java.html.geo.Position;
65.73 +import org.openide.util.lookup.ServiceProvider;
65.74 +
65.75 +/** Annotation processor to generate callbacks from {@link GeoHandle} class.
65.76 + *
65.77 + * @author Jaroslav Tulach <jtulach@netbeans.org>
65.78 + */
65.79 +@ServiceProvider(service=Processor.class)
65.80 +@SupportedSourceVersion(SourceVersion.RELEASE_6)
65.81 +@SupportedAnnotationTypes({
65.82 + "net.java.html.geo.OnLocation"
65.83 +})
65.84 +public final class GeoProcessor extends AbstractProcessor {
65.85 + private static final Logger LOG = Logger.getLogger(GeoProcessor.class.getName());
65.86 + @Override
65.87 + public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
65.88 + boolean ok = true;
65.89 + for (Element e : roundEnv.getElementsAnnotatedWith(OnLocation.class)) {
65.90 + if (!processLocation(e)) {
65.91 + ok = false;
65.92 + }
65.93 + }
65.94 + return ok;
65.95 + }
65.96 +
65.97 + private void error(String msg, Element e) {
65.98 + processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, msg, e);
65.99 + }
65.100 +
65.101 + private boolean processLocation(Element e) {
65.102 + if (e.getKind() != ElementKind.METHOD) {
65.103 + return false;
65.104 + }
65.105 + ExecutableElement me = (ExecutableElement) e;
65.106 + OnLocation ol = e.getAnnotation(OnLocation.class);
65.107 + if (ol == null) {
65.108 + return true;
65.109 + }
65.110 + if (me.getModifiers().contains(Modifier.PRIVATE)) {
65.111 + error("Method annotated by @OnLocation cannot be private", e);
65.112 + return false;
65.113 + }
65.114 + TypeMirror positionClass = processingEnv.getElementUtils().getTypeElement(Position.class.getName()).asType();
65.115 + final List<? extends VariableElement> params = me.getParameters();
65.116 + if (params.size() < 1 || !params.get(0).asType().equals(positionClass)) {
65.117 + error("Method annotated by @OnLocation first argument must be net.java.html.geo.Position!", e);
65.118 + return false;
65.119 + }
65.120 + String className = ol.className();
65.121 + if (className.isEmpty()) {
65.122 + String n = e.getSimpleName().toString();
65.123 + if (n.isEmpty()) {
65.124 + error("Empty method name", e);
65.125 + return false;
65.126 + }
65.127 + final String firstLetter = n.substring(0, 1).toUpperCase(Locale.ENGLISH);
65.128 + className = firstLetter + n.substring(1) + "Handle";
65.129 + }
65.130 + TypeElement te = (TypeElement)e.getEnclosingElement();
65.131 + PackageElement pe = (PackageElement) te.getEnclosingElement();
65.132 + final String pkg = pe.getQualifiedName().toString();
65.133 + final String fqn = pkg + "." + className;
65.134 + final boolean isStatic = me.getModifiers().contains(Modifier.STATIC);
65.135 + String sep;
65.136 + try {
65.137 + JavaFileObject fo = processingEnv.getFiler().createSourceFile(fqn, e);
65.138 + Writer w = fo.openWriter();
65.139 + w.append("package ").append(pkg).append(";\n");
65.140 + w.append("class ").append(className).append(" extends net.java.html.geo.Position.Handle {\n");
65.141 + if (!isStatic) {
65.142 + w.append(" private final ").append(te.getSimpleName()).append(" $i;\n");
65.143 + }
65.144 + for (int i = 1; i < params.size(); i++) {
65.145 + final VariableElement p = params.get(i);
65.146 + w.append(" private final ").append(p.asType().toString()).append(" ").append(p.getSimpleName()).append(";\n");
65.147 + }
65.148 + w.append(" private ").append(className).append("(boolean oneTime");
65.149 + w.append(", ").append(te.getSimpleName()).append(" i");
65.150 + for (int i = 1; i < params.size(); i++) {
65.151 + final VariableElement p = params.get(i);
65.152 + w.append(", ").append(p.asType().toString()).append(" ").append(p.getSimpleName());
65.153 + }
65.154 + w.append(") {\n super(oneTime);\n");
65.155 + if (!isStatic) {
65.156 + w.append(" this.$i = i;\n");
65.157 + }
65.158 + for (int i = 1; i < params.size(); i++) {
65.159 + final VariableElement p = params.get(i);
65.160 + w.append(" this.").append(p.getSimpleName()).append(" = ").append(p.getSimpleName()).append(";\n");
65.161 + }
65.162 + w.append("}\n");
65.163 + w.append(" static net.java.html.geo.Position.Handle createQuery(");
65.164 + String inst;
65.165 + if (!isStatic) {
65.166 + w.append(te.getSimpleName()).append(" instance");
65.167 + inst = "instance";
65.168 + sep = ", ";
65.169 + } else {
65.170 + inst = "null";
65.171 + sep = "";
65.172 + }
65.173 + for (int i = 1; i < params.size(); i++) {
65.174 + final VariableElement p = params.get(i);
65.175 + w.append(sep).append(p.asType().toString()).append(" ").append(p.getSimpleName());
65.176 + sep = ", ";
65.177 + }
65.178 + w.append(") { return new ").append(className).append("(true, ").append(inst);
65.179 + for (int i = 1; i < params.size(); i++) {
65.180 + final VariableElement p = params.get(i);
65.181 + w.append(", ").append(p.getSimpleName());
65.182 + }
65.183 + w.append("); }\n");
65.184 + w.append(" static net.java.html.geo.Position.Handle createWatch(");
65.185 + if (!isStatic) {
65.186 + w.append(te.getSimpleName()).append(" instance");
65.187 + sep = ", ";
65.188 + } else {
65.189 + sep = "";
65.190 + }
65.191 + for (int i = 1; i < params.size(); i++) {
65.192 + final VariableElement p = params.get(i);
65.193 + w.append(sep).append(p.asType().toString()).append(" ").append(p.getSimpleName());
65.194 + }
65.195 + w.append(") { return new ").append(className).append("(false, ").append(inst);
65.196 + for (int i = 1; i < params.size(); i++) {
65.197 + final VariableElement p = params.get(i);
65.198 + w.append(", ").append(p.getSimpleName());
65.199 + }
65.200 + w.append("); }\n");
65.201 + w.append(" @Override protected void onError(Exception t) throws Throwable {\n");
65.202 + if (ol.onError().isEmpty()) {
65.203 + w.append(" t.printStackTrace();");
65.204 + } else {
65.205 + if (!findOnError(me, te, ol.onError(), isStatic)) {
65.206 + return false;
65.207 + }
65.208 + if (isStatic) {
65.209 + w.append(" ").append(te.getSimpleName()).append(".");
65.210 + } else {
65.211 + w.append(" $i.");
65.212 + }
65.213 + w.append(ol.onError()).append("(t");
65.214 + for (int i = 1; i < params.size(); i++) {
65.215 + final VariableElement p = params.get(i);
65.216 + w.append(", ").append(p.getSimpleName());
65.217 + }
65.218 + w.append(");\n");
65.219 + }
65.220 + w.append(" }\n");
65.221 + w.append(" @Override protected void onLocation(net.java.html.geo.Position p) throws Throwable {\n");
65.222 + if (isStatic) {
65.223 + w.append(" ").append(te.getSimpleName()).append(".");
65.224 + } else {
65.225 + w.append(" $i.");
65.226 + }
65.227 + w.append(me.getSimpleName()).append("(p");
65.228 + for (int i = 1; i < params.size(); i++) {
65.229 + final VariableElement p = params.get(i);
65.230 + w.append(", ").append(p.getSimpleName());
65.231 + }
65.232 + w.append(");\n");
65.233 + w.append(" }\n");
65.234 + w.append("}\n");
65.235 + w.close();
65.236 + } catch (IOException ex) {
65.237 + Logger.getLogger(GeoProcessor.class.getName()).log(Level.SEVERE, null, ex);
65.238 + error("Can't write handler class: " + ex.getMessage(), e);
65.239 + return false;
65.240 + }
65.241 +
65.242 + return true;
65.243 + }
65.244 +
65.245 + private boolean findOnError(ExecutableElement errElem, TypeElement te, String name, boolean onlyStatic) {
65.246 + String err = null;
65.247 + METHODS: for (Element e : te.getEnclosedElements()) {
65.248 + if (e.getKind() != ElementKind.METHOD) {
65.249 + continue;
65.250 + }
65.251 + if (!e.getSimpleName().contentEquals(name)) {
65.252 + continue;
65.253 + }
65.254 + if (onlyStatic && !e.getModifiers().contains(Modifier.STATIC)) {
65.255 + errElem = (ExecutableElement) e;
65.256 + err = "Would have to be static";
65.257 + continue;
65.258 + }
65.259 + ExecutableElement ee = (ExecutableElement) e;
65.260 + TypeMirror excType = processingEnv.getElementUtils().getTypeElement(Exception.class.getName()).asType();
65.261 + final List<? extends VariableElement> params = ee.getParameters();
65.262 + if (params.size() < 1 ||
65.263 + !processingEnv.getTypeUtils().isAssignable(excType, ee.getParameters().get(0).asType())
65.264 + ) {
65.265 + errElem = (ExecutableElement) e;
65.266 + err = "Error method first argument needs to be Exception";
65.267 + continue;
65.268 + }
65.269 + final List<? extends Element> origParams = errElem.getParameters();
65.270 + if (params.size() != origParams.size()) {
65.271 + errElem = (ExecutableElement) e;
65.272 + err = "Error method must have the same parameters as @OnLocation one";
65.273 + continue;
65.274 + }
65.275 + for (int i = 1; i < origParams.size(); i++) {
65.276 + final TypeMirror t1 = params.get(i).asType();
65.277 + final TypeMirror t2 = origParams.get(i).asType();
65.278 + if (!processingEnv.getTypeUtils().isSameType(t1, t2)) {
65.279 + errElem = (ExecutableElement) e;
65.280 + err = "Error method must have the same parameters as @OnLocation one";
65.281 + continue METHODS;
65.282 + }
65.283 + }
65.284 + return true;
65.285 + }
65.286 + if (err == null) {
65.287 + err = "Cannot find " + name + "(Exception) method in this class";
65.288 + }
65.289 + error(err, errElem);
65.290 + return false;
65.291 + }
65.292 +}
66.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
66.2 +++ b/geo/src/main/java/org/netbeans/html/geo/impl/JsG.java Mon Dec 16 16:59:43 2013 +0100
66.3 @@ -0,0 +1,107 @@
66.4 +/**
66.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
66.6 + *
66.7 + * Copyright 1997-2010 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 +package org.netbeans.html.geo.impl;
66.47 +
66.48 +import net.java.html.js.JavaScriptBody;
66.49 +
66.50 +/** Implementation class to deal with browser's <code>navigator.geolocation</code>
66.51 + * object.
66.52 + *
66.53 + * @author Jaroslav Tulach <jtulach@netbeans.org>
66.54 + */
66.55 +public abstract class JsG {
66.56 + protected JsG() {
66.57 + if (!getClass().getName().equals("net.java.html.geo.Position$Handle$JsH")) {
66.58 + throw new IllegalStateException();
66.59 + }
66.60 + }
66.61 +
66.62 + public abstract void onLocation(Object position);
66.63 + public abstract void onError(Object error);
66.64 +
66.65 + @JavaScriptBody(args = {}, body = "return !!navigator.geolocation;")
66.66 + public static boolean hasGeolocation() {
66.67 + return false;
66.68 + }
66.69 +
66.70 + @JavaScriptBody(
66.71 + args = { "onlyOnce", "enableHighAccuracy", "timeout", "maximumAge" },
66.72 + javacall = true,
66.73 + body =
66.74 + "var self = this;\n" +
66.75 + "var ok = function (position) {\n" +
66.76 + " self.@org.netbeans.html.geo.impl.JsG::onLocation(Ljava/lang/Object;)(position);\n" +
66.77 + "};\n" +
66.78 + "var fail = function (error) {\n" +
66.79 + " self.@org.netbeans.html.geo.impl.JsG::onError(Ljava/lang/Object;)(error);\n" +
66.80 + "};\n" +
66.81 + "var options = {};\n" +
66.82 + "options.enableHighAccuracy = enableHighAccuracy;\n" +
66.83 + "if (timeout >= 0) options.timeout = timeout;\n" +
66.84 + "if (maximumAge >= 0) options.maximumAge = maximumAge;\n" +
66.85 + "if (onlyOnce) {\n" +
66.86 + " navigator.geolocation.getCurrentPosition(ok, fail);\n" +
66.87 + " return 0;\n" +
66.88 + "} else {\n" +
66.89 + " return navigator.geolocation.watchPosition(ok, fail);\n" +
66.90 + "}\n"
66.91 + )
66.92 + protected long start(
66.93 + boolean onlyOnce,
66.94 + boolean enableHighAccuracy,
66.95 + long timeout,
66.96 + long maximumAge
66.97 + ) {
66.98 + return -1;
66.99 + }
66.100 +
66.101 + @JavaScriptBody(args = { "watch" }, body = "navigator.geolocation.clearWatch(watch);")
66.102 + protected void stop(long watch) {
66.103 + }
66.104 +
66.105 + @JavaScriptBody(args = { "self", "property" }, body = "return self[property];")
66.106 + public static Object get(Object self, String property) {
66.107 + return null;
66.108 + }
66.109 +
66.110 +}
67.1 --- a/geo/src/test/java/org/apidesign/html/geo/impl/Compile.java Mon Dec 16 15:48:09 2013 +0100
67.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
67.3 @@ -1,286 +0,0 @@
67.4 -/**
67.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
67.6 - *
67.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
67.8 - *
67.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
67.10 - * Other names may be trademarks of their respective owners.
67.11 - *
67.12 - * The contents of this file are subject to the terms of either the GNU
67.13 - * General Public License Version 2 only ("GPL") or the Common
67.14 - * Development and Distribution License("CDDL") (collectively, the
67.15 - * "License"). You may not use this file except in compliance with the
67.16 - * License. You can obtain a copy of the License at
67.17 - * http://www.netbeans.org/cddl-gplv2.html
67.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
67.19 - * specific language governing permissions and limitations under the
67.20 - * License. When distributing the software, include this License Header
67.21 - * Notice in each file and include the License file at
67.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
67.23 - * particular file as subject to the "Classpath" exception as provided
67.24 - * by Oracle in the GPL Version 2 section of the License file that
67.25 - * accompanied this code. If applicable, add the following below the
67.26 - * License Header, with the fields enclosed by brackets [] replaced by
67.27 - * your own identifying information:
67.28 - * "Portions Copyrighted [year] [name of copyright owner]"
67.29 - *
67.30 - * Contributor(s):
67.31 - *
67.32 - * The Original Software is NetBeans. The Initial Developer of the Original
67.33 - * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
67.34 - *
67.35 - * If you wish your version of this file to be governed by only the CDDL
67.36 - * or only the GPL Version 2, indicate your decision by adding
67.37 - * "[Contributor] elects to include this software in this distribution
67.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
67.39 - * single choice of license, a recipient has the option to distribute
67.40 - * your version of this file under either the CDDL, the GPL Version 2 or
67.41 - * to extend the choice of license to its licensees as provided above.
67.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
67.43 - * Version 2 license, then the option applies only if the new code is
67.44 - * made subject to such option by the copyright holder.
67.45 - */
67.46 -package org.apidesign.html.geo.impl;
67.47 -
67.48 -import java.io.ByteArrayInputStream;
67.49 -import java.io.ByteArrayOutputStream;
67.50 -import java.io.IOException;
67.51 -import java.io.InputStream;
67.52 -import java.io.OutputStream;
67.53 -import java.net.URI;
67.54 -import java.net.URISyntaxException;
67.55 -import java.util.ArrayList;
67.56 -import java.util.Arrays;
67.57 -import java.util.HashMap;
67.58 -import java.util.List;
67.59 -import java.util.Locale;
67.60 -import java.util.Map;
67.61 -import java.util.regex.Matcher;
67.62 -import java.util.regex.Pattern;
67.63 -import javax.tools.Diagnostic;
67.64 -import javax.tools.DiagnosticListener;
67.65 -import javax.tools.FileObject;
67.66 -import javax.tools.ForwardingJavaFileManager;
67.67 -import javax.tools.JavaFileManager;
67.68 -import javax.tools.JavaFileObject;
67.69 -import javax.tools.JavaFileObject.Kind;
67.70 -import javax.tools.SimpleJavaFileObject;
67.71 -import javax.tools.StandardJavaFileManager;
67.72 -import javax.tools.StandardLocation;
67.73 -import javax.tools.ToolProvider;
67.74 -import static org.testng.Assert.*;
67.75 -
67.76 -/**
67.77 - *
67.78 - * @author Jaroslav Tulach <jtulach@netbeans.org>
67.79 - */
67.80 -final class Compile implements DiagnosticListener<JavaFileObject> {
67.81 - private final List<Diagnostic<? extends JavaFileObject>> errors =
67.82 - new ArrayList<Diagnostic<? extends JavaFileObject>>();
67.83 - private final Map<String, byte[]> classes;
67.84 - private final String pkg;
67.85 - private final String cls;
67.86 - private final String html;
67.87 - private final String sourceLevel;
67.88 -
67.89 - private Compile(String html, String code, String sl) throws IOException {
67.90 - this.pkg = findPkg(code);
67.91 - this.cls = findCls(code);
67.92 - this.html = html;
67.93 - this.sourceLevel = sl;
67.94 - classes = compile(html, code);
67.95 - }
67.96 -
67.97 - /** Performs compilation of given HTML page and associated Java code
67.98 - */
67.99 - public static Compile create(String html, String code) throws IOException {
67.100 - return create(html, code, "1.7");
67.101 - }
67.102 - static Compile create(String html, String code, String sourceLevel) throws IOException {
67.103 - return new Compile(html, code, sourceLevel);
67.104 - }
67.105 -
67.106 - /** Checks for given class among compiled resources */
67.107 - public byte[] get(String res) {
67.108 - return classes.get(res);
67.109 - }
67.110 -
67.111 - /** Obtains errors created during compilation.
67.112 - */
67.113 - public List<Diagnostic<? extends JavaFileObject>> getErrors() {
67.114 - List<Diagnostic<? extends JavaFileObject>> err;
67.115 - err = new ArrayList<Diagnostic<? extends JavaFileObject>>();
67.116 - for (Diagnostic<? extends JavaFileObject> diagnostic : errors) {
67.117 - if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
67.118 - err.add(diagnostic);
67.119 - }
67.120 - }
67.121 - return err;
67.122 - }
67.123 -
67.124 - private Map<String, byte[]> compile(final String html, final String code) throws IOException {
67.125 - StandardJavaFileManager sjfm = ToolProvider.getSystemJavaCompiler().getStandardFileManager(this, null, null);
67.126 -
67.127 - final Map<String, ByteArrayOutputStream> class2BAOS;
67.128 - class2BAOS = new HashMap<String, ByteArrayOutputStream>();
67.129 -
67.130 - JavaFileObject file = new SimpleJavaFileObject(URI.create("mem://mem"), Kind.SOURCE) {
67.131 - @Override
67.132 - public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
67.133 - return code;
67.134 - }
67.135 - };
67.136 - final JavaFileObject htmlFile = new SimpleJavaFileObject(URI.create("mem://mem2"), Kind.OTHER) {
67.137 - @Override
67.138 - public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
67.139 - return html;
67.140 - }
67.141 -
67.142 - @Override
67.143 - public InputStream openInputStream() throws IOException {
67.144 - return new ByteArrayInputStream(html.getBytes());
67.145 - }
67.146 - };
67.147 -
67.148 - final URI scratch;
67.149 - try {
67.150 - scratch = new URI("mem://mem3");
67.151 - } catch (URISyntaxException ex) {
67.152 - throw new IOException(ex);
67.153 - }
67.154 -
67.155 - JavaFileManager jfm = new ForwardingJavaFileManager<JavaFileManager>(sjfm) {
67.156 - @Override
67.157 - public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) throws IOException {
67.158 - if (kind == Kind.CLASS) {
67.159 - final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
67.160 -
67.161 - class2BAOS.put(className.replace('.', '/') + ".class", buffer);
67.162 - return new SimpleJavaFileObject(sibling.toUri(), kind) {
67.163 - @Override
67.164 - public OutputStream openOutputStream() throws IOException {
67.165 - return buffer;
67.166 - }
67.167 - };
67.168 - }
67.169 -
67.170 - if (kind == Kind.SOURCE) {
67.171 - final String n = className.replace('.', '/') + ".java";
67.172 - final URI un;
67.173 - try {
67.174 - un = new URI("mem://" + n);
67.175 - } catch (URISyntaxException ex) {
67.176 - throw new IOException(ex);
67.177 - }
67.178 - return new VirtFO(un/*sibling.toUri()*/, kind, n);
67.179 - }
67.180 -
67.181 - throw new IllegalStateException();
67.182 - }
67.183 -
67.184 - @Override
67.185 - public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException {
67.186 - if (location == StandardLocation.SOURCE_PATH) {
67.187 - if (packageName.equals(pkg)) {
67.188 - return htmlFile;
67.189 - }
67.190 - }
67.191 -
67.192 - return null;
67.193 - }
67.194 -
67.195 - @Override
67.196 - public boolean isSameFile(FileObject a, FileObject b) {
67.197 - if (a instanceof VirtFO && b instanceof VirtFO) {
67.198 - return ((VirtFO)a).getName().equals(((VirtFO)b).getName());
67.199 - }
67.200 -
67.201 - return super.isSameFile(a, b);
67.202 - }
67.203 -
67.204 - class VirtFO extends SimpleJavaFileObject {
67.205 -
67.206 - private final String n;
67.207 -
67.208 - public VirtFO(URI uri, Kind kind, String n) {
67.209 - super(uri, kind);
67.210 - this.n = n;
67.211 - }
67.212 - private final ByteArrayOutputStream data = new ByteArrayOutputStream();
67.213 -
67.214 - @Override
67.215 - public OutputStream openOutputStream() throws IOException {
67.216 - return data;
67.217 - }
67.218 -
67.219 - @Override
67.220 - public String getName() {
67.221 - return n;
67.222 - }
67.223 -
67.224 - @Override
67.225 - public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
67.226 - data.close();
67.227 - return new String(data.toByteArray());
67.228 - }
67.229 - }
67.230 - };
67.231 -
67.232 - ToolProvider.getSystemJavaCompiler().getTask(null, jfm, this, /*XXX:*/Arrays.asList("-source", sourceLevel, "-target", "1.7"), null, Arrays.asList(file)).call();
67.233 -
67.234 - Map<String, byte[]> result = new HashMap<String, byte[]>();
67.235 -
67.236 - for (Map.Entry<String, ByteArrayOutputStream> e : class2BAOS.entrySet()) {
67.237 - result.put(e.getKey(), e.getValue().toByteArray());
67.238 - }
67.239 -
67.240 - return result;
67.241 - }
67.242 -
67.243 -
67.244 - @Override
67.245 - public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
67.246 - errors.add(diagnostic);
67.247 - }
67.248 - private static String findPkg(String java) throws IOException {
67.249 - Pattern p = Pattern.compile("package\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}*;", Pattern.MULTILINE);
67.250 - Matcher m = p.matcher(java);
67.251 - if (!m.find()) {
67.252 - throw new IOException("Can't find package declaration in the java file");
67.253 - }
67.254 - String pkg = m.group(1);
67.255 - return pkg;
67.256 - }
67.257 - private static String findCls(String java) throws IOException {
67.258 - Pattern p = Pattern.compile("class\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}", Pattern.MULTILINE);
67.259 - Matcher m = p.matcher(java);
67.260 - if (!m.find()) {
67.261 - throw new IOException("Can't find package declaration in the java file");
67.262 - }
67.263 - String cls = m.group(1);
67.264 - return cls;
67.265 - }
67.266 -
67.267 - String getHtml() {
67.268 - String fqn = "'" + pkg + '.' + cls + "'";
67.269 - return html.replace("'${fqn}'", fqn);
67.270 - }
67.271 -
67.272 - void assertErrors() {
67.273 - assertFalse(getErrors().isEmpty(), "There are supposed to be some errors");
67.274 - }
67.275 -
67.276 - void assertError(String expMsg) {
67.277 - StringBuilder sb = new StringBuilder();
67.278 - sb.append("Can't find ").append(expMsg).append(" among:");
67.279 - for (Diagnostic<? extends JavaFileObject> e : errors) {
67.280 - String msg = e.getMessage(Locale.US);
67.281 - if (msg.contains(expMsg)) {
67.282 - return;
67.283 - }
67.284 - sb.append("\n");
67.285 - sb.append(msg);
67.286 - }
67.287 - fail(sb.toString());
67.288 - }
67.289 -}
68.1 --- a/geo/src/test/java/org/apidesign/html/geo/impl/GeoProcessorTest.java Mon Dec 16 15:48:09 2013 +0100
68.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
68.3 @@ -1,114 +0,0 @@
68.4 -/**
68.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
68.6 - *
68.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
68.8 - *
68.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
68.10 - * Other names may be trademarks of their respective owners.
68.11 - *
68.12 - * The contents of this file are subject to the terms of either the GNU
68.13 - * General Public License Version 2 only ("GPL") or the Common
68.14 - * Development and Distribution License("CDDL") (collectively, the
68.15 - * "License"). You may not use this file except in compliance with the
68.16 - * License. You can obtain a copy of the License at
68.17 - * http://www.netbeans.org/cddl-gplv2.html
68.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
68.19 - * specific language governing permissions and limitations under the
68.20 - * License. When distributing the software, include this License Header
68.21 - * Notice in each file and include the License file at
68.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
68.23 - * particular file as subject to the "Classpath" exception as provided
68.24 - * by Oracle in the GPL Version 2 section of the License file that
68.25 - * accompanied this code. If applicable, add the following below the
68.26 - * License Header, with the fields enclosed by brackets [] replaced by
68.27 - * your own identifying information:
68.28 - * "Portions Copyrighted [year] [name of copyright owner]"
68.29 - *
68.30 - * Contributor(s):
68.31 - *
68.32 - * The Original Software is NetBeans. The Initial Developer of the Original
68.33 - * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
68.34 - *
68.35 - * If you wish your version of this file to be governed by only the CDDL
68.36 - * or only the GPL Version 2, indicate your decision by adding
68.37 - * "[Contributor] elects to include this software in this distribution
68.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
68.39 - * single choice of license, a recipient has the option to distribute
68.40 - * your version of this file under either the CDDL, the GPL Version 2 or
68.41 - * to extend the choice of license to its licensees as provided above.
68.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
68.43 - * Version 2 license, then the option applies only if the new code is
68.44 - * made subject to such option by the copyright holder.
68.45 - */
68.46 -package org.apidesign.html.geo.impl;
68.47 -
68.48 -import java.io.IOException;
68.49 -import org.testng.annotations.Test;
68.50 -
68.51 -/** Test whether the annotation processor detects errors correctly.
68.52 - *
68.53 - * @author Jaroslav Tulach <jtulach@netbeans.org>
68.54 - */
68.55 -public class GeoProcessorTest {
68.56 -
68.57 - public GeoProcessorTest() {
68.58 - }
68.59 -
68.60 - @Test public void onLocationMethodHasToTakePositionParameter() throws IOException {
68.61 - Compile res = Compile.create("", "package x;\n"
68.62 - + "class UseOnLocation {\n"
68.63 - + " @net.java.html.geo.OnLocation\n"
68.64 - + " public static void cantCallMe() {}\n"
68.65 - + "}\n"
68.66 - );
68.67 - res.assertErrors();
68.68 - res.assertError("first argument must be net.java.html.geo.Position");
68.69 - }
68.70 -
68.71 - @Test public void onLocationMethodCannotBePrivate() throws IOException {
68.72 - Compile res = Compile.create("", "package x;\n"
68.73 - + "class UseOnLocation {\n"
68.74 - + " @net.java.html.geo.OnLocation\n"
68.75 - + " private static void cantCallMe(net.java.html.geo.Position p) {}\n"
68.76 - + "}\n"
68.77 - );
68.78 - res.assertErrors();
68.79 - res.assertError("cannot be private");
68.80 - }
68.81 -
68.82 - @Test public void onErrorHasToExist() throws IOException {
68.83 - Compile res = Compile.create("", "package x;\n"
68.84 - + "class UseOnLocation {\n"
68.85 - + " @net.java.html.geo.OnLocation(onError=\"doesNotExist\")\n"
68.86 - + " static void cantCallMe(net.java.html.geo.Position p) {}\n"
68.87 - + "}\n"
68.88 - );
68.89 - res.assertErrors();
68.90 - res.assertError("not find doesNotExist");
68.91 - }
68.92 -
68.93 - @Test public void onErrorWouldHaveToBeStatic() throws IOException {
68.94 - Compile res = Compile.create("", "package x;\n"
68.95 - + "class UseOnLocation {\n"
68.96 - + " @net.java.html.geo.OnLocation(onError=\"notStatic\")\n"
68.97 - + " static void cantCallMe(net.java.html.geo.Position p) {}\n"
68.98 - + " void notStatic(Exception e) {}\n"
68.99 - + "}\n"
68.100 - );
68.101 - res.assertErrors();
68.102 - res.assertError("have to be static");
68.103 - }
68.104 -
68.105 - @Test public void onErrorMustAcceptExceptionArgument() throws IOException {
68.106 - Compile res = Compile.create("", "package x;\n"
68.107 - + "class UseOnLocation {\n"
68.108 - + " @net.java.html.geo.OnLocation(onError=\"notStatic\")\n"
68.109 - + " static void cantCallMe(net.java.html.geo.Position p) {}\n"
68.110 - + " static void notStatic(java.io.IOException e) {}\n"
68.111 - + "}\n"
68.112 - );
68.113 - res.assertErrors();
68.114 - res.assertError("Error method first argument needs to be Exception");
68.115 - }
68.116 -
68.117 -}
69.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
69.2 +++ b/geo/src/test/java/org/netbeans/html/geo/impl/Compile.java Mon Dec 16 16:59:43 2013 +0100
69.3 @@ -0,0 +1,286 @@
69.4 +/**
69.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
69.6 + *
69.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
69.8 + *
69.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
69.10 + * Other names may be trademarks of their respective owners.
69.11 + *
69.12 + * The contents of this file are subject to the terms of either the GNU
69.13 + * General Public License Version 2 only ("GPL") or the Common
69.14 + * Development and Distribution License("CDDL") (collectively, the
69.15 + * "License"). You may not use this file except in compliance with the
69.16 + * License. You can obtain a copy of the License at
69.17 + * http://www.netbeans.org/cddl-gplv2.html
69.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
69.19 + * specific language governing permissions and limitations under the
69.20 + * License. When distributing the software, include this License Header
69.21 + * Notice in each file and include the License file at
69.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
69.23 + * particular file as subject to the "Classpath" exception as provided
69.24 + * by Oracle in the GPL Version 2 section of the License file that
69.25 + * accompanied this code. If applicable, add the following below the
69.26 + * License Header, with the fields enclosed by brackets [] replaced by
69.27 + * your own identifying information:
69.28 + * "Portions Copyrighted [year] [name of copyright owner]"
69.29 + *
69.30 + * Contributor(s):
69.31 + *
69.32 + * The Original Software is NetBeans. The Initial Developer of the Original
69.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
69.34 + *
69.35 + * If you wish your version of this file to be governed by only the CDDL
69.36 + * or only the GPL Version 2, indicate your decision by adding
69.37 + * "[Contributor] elects to include this software in this distribution
69.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
69.39 + * single choice of license, a recipient has the option to distribute
69.40 + * your version of this file under either the CDDL, the GPL Version 2 or
69.41 + * to extend the choice of license to its licensees as provided above.
69.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
69.43 + * Version 2 license, then the option applies only if the new code is
69.44 + * made subject to such option by the copyright holder.
69.45 + */
69.46 +package org.netbeans.html.geo.impl;
69.47 +
69.48 +import java.io.ByteArrayInputStream;
69.49 +import java.io.ByteArrayOutputStream;
69.50 +import java.io.IOException;
69.51 +import java.io.InputStream;
69.52 +import java.io.OutputStream;
69.53 +import java.net.URI;
69.54 +import java.net.URISyntaxException;
69.55 +import java.util.ArrayList;
69.56 +import java.util.Arrays;
69.57 +import java.util.HashMap;
69.58 +import java.util.List;
69.59 +import java.util.Locale;
69.60 +import java.util.Map;
69.61 +import java.util.regex.Matcher;
69.62 +import java.util.regex.Pattern;
69.63 +import javax.tools.Diagnostic;
69.64 +import javax.tools.DiagnosticListener;
69.65 +import javax.tools.FileObject;
69.66 +import javax.tools.ForwardingJavaFileManager;
69.67 +import javax.tools.JavaFileManager;
69.68 +import javax.tools.JavaFileObject;
69.69 +import javax.tools.JavaFileObject.Kind;
69.70 +import javax.tools.SimpleJavaFileObject;
69.71 +import javax.tools.StandardJavaFileManager;
69.72 +import javax.tools.StandardLocation;
69.73 +import javax.tools.ToolProvider;
69.74 +import static org.testng.Assert.*;
69.75 +
69.76 +/**
69.77 + *
69.78 + * @author Jaroslav Tulach <jtulach@netbeans.org>
69.79 + */
69.80 +final class Compile implements DiagnosticListener<JavaFileObject> {
69.81 + private final List<Diagnostic<? extends JavaFileObject>> errors =
69.82 + new ArrayList<Diagnostic<? extends JavaFileObject>>();
69.83 + private final Map<String, byte[]> classes;
69.84 + private final String pkg;
69.85 + private final String cls;
69.86 + private final String html;
69.87 + private final String sourceLevel;
69.88 +
69.89 + private Compile(String html, String code, String sl) throws IOException {
69.90 + this.pkg = findPkg(code);
69.91 + this.cls = findCls(code);
69.92 + this.html = html;
69.93 + this.sourceLevel = sl;
69.94 + classes = compile(html, code);
69.95 + }
69.96 +
69.97 + /** Performs compilation of given HTML page and associated Java code
69.98 + */
69.99 + public static Compile create(String html, String code) throws IOException {
69.100 + return create(html, code, "1.7");
69.101 + }
69.102 + static Compile create(String html, String code, String sourceLevel) throws IOException {
69.103 + return new Compile(html, code, sourceLevel);
69.104 + }
69.105 +
69.106 + /** Checks for given class among compiled resources */
69.107 + public byte[] get(String res) {
69.108 + return classes.get(res);
69.109 + }
69.110 +
69.111 + /** Obtains errors created during compilation.
69.112 + */
69.113 + public List<Diagnostic<? extends JavaFileObject>> getErrors() {
69.114 + List<Diagnostic<? extends JavaFileObject>> err;
69.115 + err = new ArrayList<Diagnostic<? extends JavaFileObject>>();
69.116 + for (Diagnostic<? extends JavaFileObject> diagnostic : errors) {
69.117 + if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
69.118 + err.add(diagnostic);
69.119 + }
69.120 + }
69.121 + return err;
69.122 + }
69.123 +
69.124 + private Map<String, byte[]> compile(final String html, final String code) throws IOException {
69.125 + StandardJavaFileManager sjfm = ToolProvider.getSystemJavaCompiler().getStandardFileManager(this, null, null);
69.126 +
69.127 + final Map<String, ByteArrayOutputStream> class2BAOS;
69.128 + class2BAOS = new HashMap<String, ByteArrayOutputStream>();
69.129 +
69.130 + JavaFileObject file = new SimpleJavaFileObject(URI.create("mem://mem"), Kind.SOURCE) {
69.131 + @Override
69.132 + public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
69.133 + return code;
69.134 + }
69.135 + };
69.136 + final JavaFileObject htmlFile = new SimpleJavaFileObject(URI.create("mem://mem2"), Kind.OTHER) {
69.137 + @Override
69.138 + public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
69.139 + return html;
69.140 + }
69.141 +
69.142 + @Override
69.143 + public InputStream openInputStream() throws IOException {
69.144 + return new ByteArrayInputStream(html.getBytes());
69.145 + }
69.146 + };
69.147 +
69.148 + final URI scratch;
69.149 + try {
69.150 + scratch = new URI("mem://mem3");
69.151 + } catch (URISyntaxException ex) {
69.152 + throw new IOException(ex);
69.153 + }
69.154 +
69.155 + JavaFileManager jfm = new ForwardingJavaFileManager<JavaFileManager>(sjfm) {
69.156 + @Override
69.157 + public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) throws IOException {
69.158 + if (kind == Kind.CLASS) {
69.159 + final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
69.160 +
69.161 + class2BAOS.put(className.replace('.', '/') + ".class", buffer);
69.162 + return new SimpleJavaFileObject(sibling.toUri(), kind) {
69.163 + @Override
69.164 + public OutputStream openOutputStream() throws IOException {
69.165 + return buffer;
69.166 + }
69.167 + };
69.168 + }
69.169 +
69.170 + if (kind == Kind.SOURCE) {
69.171 + final String n = className.replace('.', '/') + ".java";
69.172 + final URI un;
69.173 + try {
69.174 + un = new URI("mem://" + n);
69.175 + } catch (URISyntaxException ex) {
69.176 + throw new IOException(ex);
69.177 + }
69.178 + return new VirtFO(un/*sibling.toUri()*/, kind, n);
69.179 + }
69.180 +
69.181 + throw new IllegalStateException();
69.182 + }
69.183 +
69.184 + @Override
69.185 + public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException {
69.186 + if (location == StandardLocation.SOURCE_PATH) {
69.187 + if (packageName.equals(pkg)) {
69.188 + return htmlFile;
69.189 + }
69.190 + }
69.191 +
69.192 + return null;
69.193 + }
69.194 +
69.195 + @Override
69.196 + public boolean isSameFile(FileObject a, FileObject b) {
69.197 + if (a instanceof VirtFO && b instanceof VirtFO) {
69.198 + return ((VirtFO)a).getName().equals(((VirtFO)b).getName());
69.199 + }
69.200 +
69.201 + return super.isSameFile(a, b);
69.202 + }
69.203 +
69.204 + class VirtFO extends SimpleJavaFileObject {
69.205 +
69.206 + private final String n;
69.207 +
69.208 + public VirtFO(URI uri, Kind kind, String n) {
69.209 + super(uri, kind);
69.210 + this.n = n;
69.211 + }
69.212 + private final ByteArrayOutputStream data = new ByteArrayOutputStream();
69.213 +
69.214 + @Override
69.215 + public OutputStream openOutputStream() throws IOException {
69.216 + return data;
69.217 + }
69.218 +
69.219 + @Override
69.220 + public String getName() {
69.221 + return n;
69.222 + }
69.223 +
69.224 + @Override
69.225 + public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
69.226 + data.close();
69.227 + return new String(data.toByteArray());
69.228 + }
69.229 + }
69.230 + };
69.231 +
69.232 + ToolProvider.getSystemJavaCompiler().getTask(null, jfm, this, /*XXX:*/Arrays.asList("-source", sourceLevel, "-target", "1.7"), null, Arrays.asList(file)).call();
69.233 +
69.234 + Map<String, byte[]> result = new HashMap<String, byte[]>();
69.235 +
69.236 + for (Map.Entry<String, ByteArrayOutputStream> e : class2BAOS.entrySet()) {
69.237 + result.put(e.getKey(), e.getValue().toByteArray());
69.238 + }
69.239 +
69.240 + return result;
69.241 + }
69.242 +
69.243 +
69.244 + @Override
69.245 + public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
69.246 + errors.add(diagnostic);
69.247 + }
69.248 + private static String findPkg(String java) throws IOException {
69.249 + Pattern p = Pattern.compile("package\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}*;", Pattern.MULTILINE);
69.250 + Matcher m = p.matcher(java);
69.251 + if (!m.find()) {
69.252 + throw new IOException("Can't find package declaration in the java file");
69.253 + }
69.254 + String pkg = m.group(1);
69.255 + return pkg;
69.256 + }
69.257 + private static String findCls(String java) throws IOException {
69.258 + Pattern p = Pattern.compile("class\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}", Pattern.MULTILINE);
69.259 + Matcher m = p.matcher(java);
69.260 + if (!m.find()) {
69.261 + throw new IOException("Can't find package declaration in the java file");
69.262 + }
69.263 + String cls = m.group(1);
69.264 + return cls;
69.265 + }
69.266 +
69.267 + String getHtml() {
69.268 + String fqn = "'" + pkg + '.' + cls + "'";
69.269 + return html.replace("'${fqn}'", fqn);
69.270 + }
69.271 +
69.272 + void assertErrors() {
69.273 + assertFalse(getErrors().isEmpty(), "There are supposed to be some errors");
69.274 + }
69.275 +
69.276 + void assertError(String expMsg) {
69.277 + StringBuilder sb = new StringBuilder();
69.278 + sb.append("Can't find ").append(expMsg).append(" among:");
69.279 + for (Diagnostic<? extends JavaFileObject> e : errors) {
69.280 + String msg = e.getMessage(Locale.US);
69.281 + if (msg.contains(expMsg)) {
69.282 + return;
69.283 + }
69.284 + sb.append("\n");
69.285 + sb.append(msg);
69.286 + }
69.287 + fail(sb.toString());
69.288 + }
69.289 +}
70.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
70.2 +++ b/geo/src/test/java/org/netbeans/html/geo/impl/GeoProcessorTest.java Mon Dec 16 16:59:43 2013 +0100
70.3 @@ -0,0 +1,114 @@
70.4 +/**
70.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
70.6 + *
70.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
70.8 + *
70.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
70.10 + * Other names may be trademarks of their respective owners.
70.11 + *
70.12 + * The contents of this file are subject to the terms of either the GNU
70.13 + * General Public License Version 2 only ("GPL") or the Common
70.14 + * Development and Distribution License("CDDL") (collectively, the
70.15 + * "License"). You may not use this file except in compliance with the
70.16 + * License. You can obtain a copy of the License at
70.17 + * http://www.netbeans.org/cddl-gplv2.html
70.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
70.19 + * specific language governing permissions and limitations under the
70.20 + * License. When distributing the software, include this License Header
70.21 + * Notice in each file and include the License file at
70.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
70.23 + * particular file as subject to the "Classpath" exception as provided
70.24 + * by Oracle in the GPL Version 2 section of the License file that
70.25 + * accompanied this code. If applicable, add the following below the
70.26 + * License Header, with the fields enclosed by brackets [] replaced by
70.27 + * your own identifying information:
70.28 + * "Portions Copyrighted [year] [name of copyright owner]"
70.29 + *
70.30 + * Contributor(s):
70.31 + *
70.32 + * The Original Software is NetBeans. The Initial Developer of the Original
70.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
70.34 + *
70.35 + * If you wish your version of this file to be governed by only the CDDL
70.36 + * or only the GPL Version 2, indicate your decision by adding
70.37 + * "[Contributor] elects to include this software in this distribution
70.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
70.39 + * single choice of license, a recipient has the option to distribute
70.40 + * your version of this file under either the CDDL, the GPL Version 2 or
70.41 + * to extend the choice of license to its licensees as provided above.
70.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
70.43 + * Version 2 license, then the option applies only if the new code is
70.44 + * made subject to such option by the copyright holder.
70.45 + */
70.46 +package org.netbeans.html.geo.impl;
70.47 +
70.48 +import java.io.IOException;
70.49 +import org.testng.annotations.Test;
70.50 +
70.51 +/** Test whether the annotation processor detects errors correctly.
70.52 + *
70.53 + * @author Jaroslav Tulach <jtulach@netbeans.org>
70.54 + */
70.55 +public class GeoProcessorTest {
70.56 +
70.57 + public GeoProcessorTest() {
70.58 + }
70.59 +
70.60 + @Test public void onLocationMethodHasToTakePositionParameter() throws IOException {
70.61 + Compile res = Compile.create("", "package x;\n"
70.62 + + "class UseOnLocation {\n"
70.63 + + " @net.java.html.geo.OnLocation\n"
70.64 + + " public static void cantCallMe() {}\n"
70.65 + + "}\n"
70.66 + );
70.67 + res.assertErrors();
70.68 + res.assertError("first argument must be net.java.html.geo.Position");
70.69 + }
70.70 +
70.71 + @Test public void onLocationMethodCannotBePrivate() throws IOException {
70.72 + Compile res = Compile.create("", "package x;\n"
70.73 + + "class UseOnLocation {\n"
70.74 + + " @net.java.html.geo.OnLocation\n"
70.75 + + " private static void cantCallMe(net.java.html.geo.Position p) {}\n"
70.76 + + "}\n"
70.77 + );
70.78 + res.assertErrors();
70.79 + res.assertError("cannot be private");
70.80 + }
70.81 +
70.82 + @Test public void onErrorHasToExist() throws IOException {
70.83 + Compile res = Compile.create("", "package x;\n"
70.84 + + "class UseOnLocation {\n"
70.85 + + " @net.java.html.geo.OnLocation(onError=\"doesNotExist\")\n"
70.86 + + " static void cantCallMe(net.java.html.geo.Position p) {}\n"
70.87 + + "}\n"
70.88 + );
70.89 + res.assertErrors();
70.90 + res.assertError("not find doesNotExist");
70.91 + }
70.92 +
70.93 + @Test public void onErrorWouldHaveToBeStatic() throws IOException {
70.94 + Compile res = Compile.create("", "package x;\n"
70.95 + + "class UseOnLocation {\n"
70.96 + + " @net.java.html.geo.OnLocation(onError=\"notStatic\")\n"
70.97 + + " static void cantCallMe(net.java.html.geo.Position p) {}\n"
70.98 + + " void notStatic(Exception e) {}\n"
70.99 + + "}\n"
70.100 + );
70.101 + res.assertErrors();
70.102 + res.assertError("have to be static");
70.103 + }
70.104 +
70.105 + @Test public void onErrorMustAcceptExceptionArgument() throws IOException {
70.106 + Compile res = Compile.create("", "package x;\n"
70.107 + + "class UseOnLocation {\n"
70.108 + + " @net.java.html.geo.OnLocation(onError=\"notStatic\")\n"
70.109 + + " static void cantCallMe(net.java.html.geo.Position p) {}\n"
70.110 + + " static void notStatic(java.io.IOException e) {}\n"
70.111 + + "}\n"
70.112 + );
70.113 + res.assertErrors();
70.114 + res.assertError("Error method first argument needs to be Exception");
70.115 + }
70.116 +
70.117 +}
71.1 --- a/json-tck/src/main/java/net/java/html/json/tests/ConvertTypesTest.java Mon Dec 16 15:48:09 2013 +0100
71.2 +++ b/json-tck/src/main/java/net/java/html/json/tests/ConvertTypesTest.java Mon Dec 16 16:59:43 2013 +0100
71.3 @@ -49,7 +49,7 @@
71.4 import java.util.Map;
71.5 import net.java.html.BrwsrCtx;
71.6 import net.java.html.json.Models;
71.7 -import org.apidesign.html.json.impl.JSON;
71.8 +import org.netbeans.html.json.impl.JSON;
71.9 import org.apidesign.html.json.tck.KOTest;
71.10
71.11 /**
72.1 --- a/json-tck/src/main/java/net/java/html/json/tests/JSONTest.java Mon Dec 16 15:48:09 2013 +0100
72.2 +++ b/json-tck/src/main/java/net/java/html/json/tests/JSONTest.java Mon Dec 16 16:59:43 2013 +0100
72.3 @@ -49,7 +49,7 @@
72.4 import net.java.html.json.Models;
72.5 import net.java.html.json.OnReceive;
72.6 import net.java.html.json.Property;
72.7 -import org.apidesign.html.json.impl.JSON;
72.8 +import org.netbeans.html.json.impl.JSON;
72.9 import org.apidesign.html.json.tck.KOTest;
72.10
72.11 /** Need to verify that models produce reasonable JSON objects.
73.1 --- a/json/src/main/java/net/java/html/json/Models.java Mon Dec 16 15:48:09 2013 +0100
73.2 +++ b/json/src/main/java/net/java/html/json/Models.java Mon Dec 16 16:59:43 2013 +0100
73.3 @@ -45,7 +45,7 @@
73.4 import net.java.html.BrwsrCtx;
73.5 import java.io.IOException;
73.6 import java.io.InputStream;
73.7 -import org.apidesign.html.json.impl.JSON;
73.8 +import org.netbeans.html.json.impl.JSON;
73.9
73.10 /** Information about and
73.11 * operations for classes generated by the {@link Model @Model}
74.1 --- a/json/src/main/java/org/apidesign/html/json/impl/Bindings.java Mon Dec 16 15:48:09 2013 +0100
74.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
74.3 @@ -1,113 +0,0 @@
74.4 -/**
74.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
74.6 - *
74.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
74.8 - *
74.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
74.10 - * Other names may be trademarks of their respective owners.
74.11 - *
74.12 - * The contents of this file are subject to the terms of either the GNU
74.13 - * General Public License Version 2 only ("GPL") or the Common
74.14 - * Development and Distribution License("CDDL") (collectively, the
74.15 - * "License"). You may not use this file except in compliance with the
74.16 - * License. You can obtain a copy of the License at
74.17 - * http://www.netbeans.org/cddl-gplv2.html
74.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
74.19 - * specific language governing permissions and limitations under the
74.20 - * License. When distributing the software, include this License Header
74.21 - * Notice in each file and include the License file at
74.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
74.23 - * particular file as subject to the "Classpath" exception as provided
74.24 - * by Oracle in the GPL Version 2 section of the License file that
74.25 - * accompanied this code. If applicable, add the following below the
74.26 - * License Header, with the fields enclosed by brackets [] replaced by
74.27 - * your own identifying information:
74.28 - * "Portions Copyrighted [year] [name of copyright owner]"
74.29 - *
74.30 - * Contributor(s):
74.31 - *
74.32 - * The Original Software is NetBeans. The Initial Developer of the Original
74.33 - * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
74.34 - *
74.35 - * If you wish your version of this file to be governed by only the CDDL
74.36 - * or only the GPL Version 2, indicate your decision by adding
74.37 - * "[Contributor] elects to include this software in this distribution
74.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
74.39 - * single choice of license, a recipient has the option to distribute
74.40 - * your version of this file under either the CDDL, the GPL Version 2 or
74.41 - * to extend the choice of license to its licensees as provided above.
74.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
74.43 - * Version 2 license, then the option applies only if the new code is
74.44 - * made subject to such option by the copyright holder.
74.45 - */
74.46 -package org.apidesign.html.json.impl;
74.47 -
74.48 -import org.apidesign.html.json.spi.PropertyBinding;
74.49 -import net.java.html.BrwsrCtx;
74.50 -import org.apidesign.html.json.impl.PropertyBindingAccessor.FBData;
74.51 -import org.apidesign.html.json.impl.PropertyBindingAccessor.PBData;
74.52 -import org.apidesign.html.json.spi.FunctionBinding;
74.53 -import org.apidesign.html.json.spi.Technology;
74.54 -
74.55 -/**
74.56 - *
74.57 - * @author Jaroslav Tulach <jtulach@netbeans.org>
74.58 - */
74.59 -public final class Bindings<Data> {
74.60 - private Data data;
74.61 - private final Technology<Data> bp;
74.62 -
74.63 - private Bindings(Technology<Data> bp) {
74.64 - this.bp = bp;
74.65 - }
74.66 -
74.67 - public <M> PropertyBinding registerProperty(String propName, M model, SetAndGet<M> access, boolean readOnly) {
74.68 - return PropertyBindingAccessor.create(new PBData<M>(this, propName, model, access, readOnly));
74.69 - }
74.70 -
74.71 - public <M> FunctionBinding registerFunction(String name, M model, Callback<M> access) {
74.72 - return PropertyBindingAccessor.createFunction(new FBData<M>(name, model, access));
74.73 - }
74.74 -
74.75 - public static Bindings<?> apply(BrwsrCtx c, Object model) {
74.76 - Technology<?> bp = JSON.findTechnology(c);
74.77 - return apply(bp);
74.78 - }
74.79 -
74.80 - private static <Data> Bindings<Data> apply(Technology<Data> bp) {
74.81 - return new Bindings<Data>(bp);
74.82 - }
74.83 -
74.84 - public final void finish(Object model, PropertyBinding[] propArr, FunctionBinding[] funcArr) {
74.85 - assert data == null;
74.86 - if (bp instanceof Technology.BatchInit) {
74.87 - Technology.BatchInit<Data> bi = (Technology.BatchInit<Data>)bp;
74.88 - data = bi.wrapModel(model, propArr, funcArr);
74.89 - } else {
74.90 - data = bp.wrapModel(model);
74.91 - for (PropertyBinding b : propArr) {
74.92 - bp.bind(b, model, data);
74.93 - }
74.94 - for (FunctionBinding b : funcArr) {
74.95 - bp.expose(b, model, data);
74.96 - }
74.97 - }
74.98 - }
74.99 -
74.100 -
74.101 - public Data koData() {
74.102 - return data;
74.103 - }
74.104 -
74.105 - public void valueHasMutated(String firstName) {
74.106 - bp.valueHasMutated(data, firstName);
74.107 - }
74.108 -
74.109 - public void applyBindings() {
74.110 - bp.applyBindings(data);
74.111 - }
74.112 -
74.113 - Object wrapArray(Object[] arr) {
74.114 - return bp.wrapArray(arr);
74.115 - }
74.116 -}
75.1 --- a/json/src/main/java/org/apidesign/html/json/impl/Callback.java Mon Dec 16 15:48:09 2013 +0100
75.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
75.3 @@ -1,51 +0,0 @@
75.4 -/**
75.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
75.6 - *
75.7 - * Copyright 1997-2010 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.apidesign.html.json.impl;
75.47 -
75.48 -/**
75.49 - *
75.50 - * @author Jaroslav Tulach <jtulach@netbeans.org>
75.51 - */
75.52 -public interface Callback<Data> {
75.53 - public void call(Data model, Object data, Object ev);
75.54 -}
76.1 --- a/json/src/main/java/org/apidesign/html/json/impl/FromJSON.java Mon Dec 16 15:48:09 2013 +0100
76.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
76.3 @@ -1,55 +0,0 @@
76.4 -/**
76.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
76.6 - *
76.7 - * Copyright 1997-2010 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 -package org.apidesign.html.json.impl;
76.47 -
76.48 -import net.java.html.BrwsrCtx;
76.49 -
76.50 -/**
76.51 - *
76.52 - * @author Jaroslav Tulach <jtulach@netbeans.org>
76.53 - */
76.54 -public interface FromJSON<Data> {
76.55 - public Class<Data> factoryFor();
76.56 - public Data read(BrwsrCtx c, Object d);
76.57 - public Data cloneTo(Object d, BrwsrCtx c);
76.58 -}
77.1 --- a/json/src/main/java/org/apidesign/html/json/impl/JSON.java Mon Dec 16 15:48:09 2013 +0100
77.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
77.3 @@ -1,474 +0,0 @@
77.4 -/**
77.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
77.6 - *
77.7 - * Copyright 1997-2010 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 -package org.apidesign.html.json.impl;
77.47 -
77.48 -import java.io.IOException;
77.49 -import java.io.InputStream;
77.50 -import java.util.HashMap;
77.51 -import java.util.Map;
77.52 -import net.java.html.BrwsrCtx;
77.53 -import org.apidesign.html.context.spi.Contexts;
77.54 -import org.apidesign.html.json.spi.FunctionBinding;
77.55 -import org.apidesign.html.json.spi.JSONCall;
77.56 -import org.apidesign.html.json.spi.PropertyBinding;
77.57 -import org.apidesign.html.json.spi.Technology;
77.58 -import org.apidesign.html.json.spi.Transfer;
77.59 -import org.apidesign.html.json.spi.WSTransfer;
77.60 -
77.61 -/**
77.62 - *
77.63 - * @author Jaroslav Tulach <jtulach@netbeans.org>
77.64 - */
77.65 -public final class JSON {
77.66 - private JSON() {
77.67 - }
77.68 -
77.69 - static Technology<?> findTechnology(BrwsrCtx c) {
77.70 - Technology<?> t = Contexts.find(c, Technology.class);
77.71 - return t == null ? EmptyTech.EMPTY : t;
77.72 - }
77.73 -
77.74 - static Transfer findTransfer(BrwsrCtx c) {
77.75 - Transfer t = Contexts.find(c, Transfer.class);
77.76 - return t == null ? EmptyTech.EMPTY : t;
77.77 - }
77.78 -
77.79 - static WSTransfer<?> findWSTransfer(BrwsrCtx c) {
77.80 - WSTransfer<?> t = Contexts.find(c, WSTransfer.class);
77.81 - return t == null ? EmptyTech.EMPTY : t;
77.82 - }
77.83 -
77.84 - public static void runInBrowser(BrwsrCtx c, Runnable runnable) {
77.85 - findTechnology(c).runSafe(runnable);
77.86 - }
77.87 -
77.88 - public static void extract(BrwsrCtx c, Object value, String[] props, Object[] values) {
77.89 - Transfer t = findTransfer(c);
77.90 - t.extract(value, props, values);
77.91 - }
77.92 -
77.93 - private static Object getProperty(BrwsrCtx c, Object obj, String prop) {
77.94 - if (prop == null) return obj;
77.95 -
77.96 - String[] arr = { prop };
77.97 - Object[] val = { null };
77.98 - extract(c, obj, arr, val);
77.99 - return val[0];
77.100 - }
77.101 -
77.102 - public static Object toJSON(Object value) {
77.103 - if (value == null) {
77.104 - return "null";
77.105 - }
77.106 - if (value instanceof Enum) {
77.107 - value = value.toString();
77.108 - }
77.109 - if (value instanceof String) {
77.110 - String s = (String)value;
77.111 - int len = s.length();
77.112 - StringBuilder sb = new StringBuilder(len + 10);
77.113 - sb.append('"');
77.114 - for (int i = 0; i < len; i++) {
77.115 - char ch = s.charAt(i);
77.116 - switch (ch) {
77.117 - case '\"': sb.append("\\\""); break;
77.118 - case '\n': sb.append("\\n"); break;
77.119 - case '\r': sb.append("\\r"); break;
77.120 - case '\t': sb.append("\\t"); break;
77.121 - case '\\': sb.append("\\\\"); break;
77.122 - default: sb.append(ch);
77.123 - }
77.124 - }
77.125 - sb.append('"');
77.126 - return sb.toString();
77.127 - }
77.128 - return value.toString();
77.129 - }
77.130 -
77.131 - public static String toString(BrwsrCtx c, Object obj, String prop) {
77.132 - obj = getProperty(c, obj, prop);
77.133 - return obj instanceof String ? (String)obj : null;
77.134 - }
77.135 - public static Number toNumber(BrwsrCtx c, Object obj, String prop) {
77.136 - obj = getProperty(c, obj, prop);
77.137 - if (!(obj instanceof Number)) {
77.138 - obj = Double.NaN;
77.139 - }
77.140 - return (Number)obj;
77.141 - }
77.142 - public static <M> M toModel(BrwsrCtx c, Class<M> aClass, Object data, Object object) {
77.143 - Technology<?> t = findTechnology(c);
77.144 - Object o = t.toModel(aClass, data);
77.145 - return aClass.cast(o);
77.146 - }
77.147 -
77.148 - public static boolean isSame(int a, int b) {
77.149 - return a == b;
77.150 - }
77.151 -
77.152 - public static boolean isSame(double a, double b) {
77.153 - return a == b;
77.154 - }
77.155 -
77.156 - public static boolean isSame(Object a, Object b) {
77.157 - if (a == b) {
77.158 - return true;
77.159 - }
77.160 - if (a == null || b == null) {
77.161 - return false;
77.162 - }
77.163 - return a.equals(b);
77.164 - }
77.165 -
77.166 - public static int hashPlus(Object o, int h) {
77.167 - return o == null ? h : h ^ o.hashCode();
77.168 - }
77.169 -
77.170 - public static <T> T extractValue(Class<T> type, Object val) {
77.171 - if (Number.class.isAssignableFrom(type)) {
77.172 - val = numberValue(val);
77.173 - }
77.174 - if (Boolean.class == type) {
77.175 - val = boolValue(val);
77.176 - }
77.177 - if (String.class == type) {
77.178 - val = stringValue(val);
77.179 - }
77.180 - if (Character.class == type) {
77.181 - val = charValue(val);
77.182 - }
77.183 - if (Integer.class == type) {
77.184 - val = val instanceof Number ? ((Number)val).intValue() : 0;
77.185 - }
77.186 - if (Long.class == type) {
77.187 - val = val instanceof Number ? ((Number)val).longValue() : 0;
77.188 - }
77.189 - if (Short.class == type) {
77.190 - val = val instanceof Number ? ((Number)val).shortValue() : 0;
77.191 - }
77.192 - if (Byte.class == type) {
77.193 - val = val instanceof Number ? ((Number)val).byteValue() : 0;
77.194 - }
77.195 - if (Double.class == type) {
77.196 - val = val instanceof Number ? ((Number)val).doubleValue() : Double.NaN;
77.197 - }
77.198 - if (Float.class == type) {
77.199 - val = val instanceof Number ? ((Number)val).floatValue() : Float.NaN;
77.200 - }
77.201 - return type.cast(val);
77.202 - }
77.203 -
77.204 - protected static boolean isNumeric(Object val) {
77.205 - return ((val instanceof Integer) || (val instanceof Long) || (val instanceof Short) || (val instanceof Byte));
77.206 - }
77.207 -
77.208 - public static String stringValue(Object val) {
77.209 - if (val instanceof Boolean) {
77.210 - return ((Boolean)val ? "true" : "false");
77.211 - }
77.212 - if (isNumeric(val)) {
77.213 - return Long.toString(((Number)val).longValue());
77.214 - }
77.215 - if (val instanceof Float) {
77.216 - return Float.toString((Float)val);
77.217 - }
77.218 - if (val instanceof Double) {
77.219 - return Double.toString((Double)val);
77.220 - }
77.221 - return (String)val;
77.222 - }
77.223 -
77.224 - public static Number numberValue(Object val) {
77.225 - if (val instanceof String) {
77.226 - try {
77.227 - return Double.valueOf((String)val);
77.228 - } catch (NumberFormatException ex) {
77.229 - return Double.NaN;
77.230 - }
77.231 - }
77.232 - if (val instanceof Boolean) {
77.233 - return (Boolean)val ? 1 : 0;
77.234 - }
77.235 - return (Number)val;
77.236 - }
77.237 -
77.238 - public static Character charValue(Object val) {
77.239 - if (val instanceof Number) {
77.240 - return Character.toChars(numberValue(val).intValue())[0];
77.241 - }
77.242 - if (val instanceof Boolean) {
77.243 - return (Boolean)val ? (char)1 : (char)0;
77.244 - }
77.245 - if (val instanceof String) {
77.246 - String s = (String)val;
77.247 - return s.isEmpty() ? (char)0 : s.charAt(0);
77.248 - }
77.249 - return (Character)val;
77.250 - }
77.251 -
77.252 - public static Boolean boolValue(Object val) {
77.253 - if (val instanceof String) {
77.254 - return Boolean.parseBoolean((String)val);
77.255 - }
77.256 - if (val instanceof Number) {
77.257 - return numberValue(val).doubleValue() != 0.0;
77.258 - }
77.259 -
77.260 - return Boolean.TRUE.equals(val);
77.261 - }
77.262 -
77.263 - public static void loadJSON(
77.264 - BrwsrCtx c, RcvrJSON callback,
77.265 - String urlBefore, String urlAfter, String method,
77.266 - Object data
77.267 - ) {
77.268 - JSONCall call = PropertyBindingAccessor.createCall(c, callback, urlBefore, urlAfter, method, data);
77.269 - Transfer t = findTransfer(c);
77.270 - t.loadJSON(call);
77.271 - }
77.272 - public static WS openWS(
77.273 - BrwsrCtx c, RcvrJSON r, String url, Object data
77.274 - ) {
77.275 - WS ws = WSImpl.create(findWSTransfer(c), r);
77.276 - ws.send(c, url, data);
77.277 - return ws;
77.278 - }
77.279 -
77.280 - public static abstract class WS {
77.281 - private WS() {
77.282 - }
77.283 -
77.284 - public abstract void send(BrwsrCtx ctx, String url, Object model);
77.285 - }
77.286 -
77.287 - private static final class WSImpl<Socket> extends WS {
77.288 -
77.289 - private final WSTransfer<Socket> trans;
77.290 - private final RcvrJSON rcvr;
77.291 - private Socket socket;
77.292 - private String prevURL;
77.293 -
77.294 - private WSImpl(WSTransfer<Socket> trans, RcvrJSON rcvr) {
77.295 - this.trans = trans;
77.296 - this.rcvr = rcvr;
77.297 - }
77.298 -
77.299 - static <Socket> WS create(WSTransfer<Socket> t, RcvrJSON r) {
77.300 - return new WSImpl<Socket>(t, r);
77.301 - }
77.302 -
77.303 - @Override
77.304 - public void send(BrwsrCtx ctx, String url, Object data) {
77.305 - Socket s = socket;
77.306 - if (s == null) {
77.307 - if (data != null) {
77.308 - throw new IllegalStateException("WebSocket is not opened yet. Call with null data, was: " + data);
77.309 - }
77.310 - JSONCall call = PropertyBindingAccessor.createCall(ctx, rcvr, url, null, "WebSocket", null);
77.311 - socket = trans.open(url, call);
77.312 - prevURL = url;
77.313 - return;
77.314 - }
77.315 - if (data == null) {
77.316 - trans.close(s);
77.317 - socket = null;
77.318 - return;
77.319 - }
77.320 - if (!prevURL.equals(url)) {
77.321 - throw new IllegalStateException(
77.322 - "Can't call to different URL " + url + " was: " + prevURL + "!"
77.323 - + " Close the socket by calling it will null data first!"
77.324 - );
77.325 - }
77.326 - JSONCall call = PropertyBindingAccessor.createCall(ctx, rcvr, prevURL, null, "WebSocket", data);
77.327 - trans.send(s, call);
77.328 - }
77.329 -
77.330 - }
77.331 -
77.332 - private static final Map<Class,FromJSON<?>> froms;
77.333 - static {
77.334 - Map<Class,FromJSON<?>> m = new HashMap<Class,FromJSON<?>>();
77.335 - froms = m;
77.336 - }
77.337 - public static void register(FromJSON<?> from) {
77.338 - froms.put(from.factoryFor(), from);
77.339 - }
77.340 -
77.341 - public static boolean isModel(Class<?> clazz) {
77.342 - return findFrom(clazz) != null;
77.343 - }
77.344 -
77.345 - private static FromJSON<?> findFrom(Class<?> clazz) {
77.346 - for (int i = 0; i < 2; i++) {
77.347 - FromJSON<?> from = froms.get(clazz);
77.348 - if (from == null) {
77.349 - initClass(clazz);
77.350 - } else {
77.351 - return from;
77.352 - }
77.353 - }
77.354 - return null;
77.355 - }
77.356 -
77.357 - public static <Model> Model bindTo(Model model, BrwsrCtx c) {
77.358 - FromJSON<?> from = findFrom(model.getClass());
77.359 - if (from == null) {
77.360 - throw new IllegalArgumentException();
77.361 - }
77.362 - return (Model) from.cloneTo(model, c);
77.363 - }
77.364 -
77.365 - public static <T> T readStream(BrwsrCtx c, Class<T> modelClazz, InputStream data)
77.366 - throws IOException {
77.367 - Transfer tr = findTransfer(c);
77.368 - return read(c, modelClazz, tr.toJSON((InputStream)data));
77.369 - }
77.370 - public static <T> T read(BrwsrCtx c, Class<T> modelClazz, Object data) {
77.371 - if (data == null) {
77.372 - return null;
77.373 - }
77.374 - if (modelClazz == String.class) {
77.375 - return modelClazz.cast(data.toString());
77.376 - }
77.377 - for (int i = 0; i < 2; i++) {
77.378 - FromJSON<?> from = froms.get(modelClazz);
77.379 - if (from == null) {
77.380 - initClass(modelClazz);
77.381 - } else {
77.382 - return modelClazz.cast(from.read(c, data));
77.383 - }
77.384 - }
77.385 - throw new NullPointerException();
77.386 - }
77.387 - static void initClass(Class<?> modelClazz) {
77.388 - try {
77.389 - // try to resolve the class
77.390 - ClassLoader l;
77.391 - try {
77.392 - l = modelClazz.getClassLoader();
77.393 - } catch (SecurityException ex) {
77.394 - l = null;
77.395 - }
77.396 - if (l != null) {
77.397 - Class.forName(modelClazz.getName(), true, l);
77.398 - }
77.399 - modelClazz.newInstance();
77.400 - } catch (Exception ex) {
77.401 - // ignore and try again
77.402 - }
77.403 - }
77.404 -
77.405 - private static final class EmptyTech
77.406 - implements Technology<Object>, Transfer, WSTransfer<Void> {
77.407 - private static final EmptyTech EMPTY = new EmptyTech();
77.408 -
77.409 - @Override
77.410 - public Object wrapModel(Object model) {
77.411 - return model;
77.412 - }
77.413 -
77.414 - @Override
77.415 - public void valueHasMutated(Object data, String propertyName) {
77.416 - }
77.417 -
77.418 - @Override
77.419 - public void bind(PropertyBinding b, Object model, Object data) {
77.420 - }
77.421 -
77.422 - @Override
77.423 - public void expose(FunctionBinding fb, Object model, Object d) {
77.424 - }
77.425 -
77.426 - @Override
77.427 - public void applyBindings(Object data) {
77.428 - }
77.429 -
77.430 - @Override
77.431 - public Object wrapArray(Object[] arr) {
77.432 - return arr;
77.433 - }
77.434 -
77.435 - @Override
77.436 - public void extract(Object obj, String[] props, Object[] values) {
77.437 - for (int i = 0; i < values.length; i++) {
77.438 - values[i] = null;
77.439 - }
77.440 - }
77.441 -
77.442 - @Override
77.443 - public void loadJSON(JSONCall call) {
77.444 - call.notifyError(new UnsupportedOperationException());
77.445 - }
77.446 -
77.447 - @Override
77.448 - public <M> M toModel(Class<M> modelClass, Object data) {
77.449 - return modelClass.cast(data);
77.450 - }
77.451 -
77.452 - @Override
77.453 - public Object toJSON(InputStream is) throws IOException {
77.454 - throw new IOException("Not supported");
77.455 - }
77.456 -
77.457 - @Override
77.458 - public synchronized void runSafe(Runnable r) {
77.459 - r.run();
77.460 - }
77.461 -
77.462 - @Override
77.463 - public Void open(String url, JSONCall onReply) {
77.464 - onReply.notifyError(new UnsupportedOperationException("WebSockets not supported!"));
77.465 - return null;
77.466 - }
77.467 -
77.468 - @Override
77.469 - public void send(Void socket, JSONCall data) {
77.470 - }
77.471 -
77.472 - @Override
77.473 - public void close(Void socket) {
77.474 - }
77.475 - }
77.476 -
77.477 -}
78.1 --- a/json/src/main/java/org/apidesign/html/json/impl/JSONList.java Mon Dec 16 15:48:09 2013 +0100
78.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
78.3 @@ -1,236 +0,0 @@
78.4 -/**
78.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
78.6 - *
78.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
78.8 - *
78.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
78.10 - * Other names may be trademarks of their respective owners.
78.11 - *
78.12 - * The contents of this file are subject to the terms of either the GNU
78.13 - * General Public License Version 2 only ("GPL") or the Common
78.14 - * Development and Distribution License("CDDL") (collectively, the
78.15 - * "License"). You may not use this file except in compliance with the
78.16 - * License. You can obtain a copy of the License at
78.17 - * http://www.netbeans.org/cddl-gplv2.html
78.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
78.19 - * specific language governing permissions and limitations under the
78.20 - * License. When distributing the software, include this License Header
78.21 - * Notice in each file and include the License file at
78.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
78.23 - * particular file as subject to the "Classpath" exception as provided
78.24 - * by Oracle in the GPL Version 2 section of the License file that
78.25 - * accompanied this code. If applicable, add the following below the
78.26 - * License Header, with the fields enclosed by brackets [] replaced by
78.27 - * your own identifying information:
78.28 - * "Portions Copyrighted [year] [name of copyright owner]"
78.29 - *
78.30 - * Contributor(s):
78.31 - *
78.32 - * The Original Software is NetBeans. The Initial Developer of the Original
78.33 - * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
78.34 - *
78.35 - * If you wish your version of this file to be governed by only the CDDL
78.36 - * or only the GPL Version 2, indicate your decision by adding
78.37 - * "[Contributor] elects to include this software in this distribution
78.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
78.39 - * single choice of license, a recipient has the option to distribute
78.40 - * your version of this file under either the CDDL, the GPL Version 2 or
78.41 - * to extend the choice of license to its licensees as provided above.
78.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
78.43 - * Version 2 license, then the option applies only if the new code is
78.44 - * made subject to such option by the copyright holder.
78.45 - */
78.46 -package org.apidesign.html.json.impl;
78.47 -
78.48 -import java.lang.reflect.Array;
78.49 -import java.util.ArrayList;
78.50 -import java.util.Arrays;
78.51 -import java.util.Collection;
78.52 -import java.util.Iterator;
78.53 -import java.util.List;
78.54 -import net.java.html.BrwsrCtx;
78.55 -
78.56 -/**
78.57 - *
78.58 - * @author Jaroslav Tulach <jtulach@netbeans.org>
78.59 - */
78.60 -public final class JSONList<T> extends ArrayList<T> {
78.61 - private final String name;
78.62 - private final String[] deps;
78.63 - private Bindings[] model;
78.64 - private Runnable onchange;
78.65 -
78.66 - public JSONList(Bindings[] model, String name, String... deps) {
78.67 - assert model.length == 1;
78.68 - this.model = model;
78.69 - this.name = name;
78.70 - this.deps = deps;
78.71 - }
78.72 -
78.73 - public void init(T... values) {
78.74 - if (values == null || values.length == 0) {
78.75 - return;
78.76 - }
78.77 - if (this.model[0] != null || !isEmpty()) {
78.78 - throw new IllegalStateException();
78.79 - }
78.80 - super.addAll(Arrays.asList(values));
78.81 - }
78.82 -
78.83 - public void init(Object values) {
78.84 - int len;
78.85 - if (values == null || (len = Array.getLength(values)) == 0) {
78.86 - return;
78.87 - }
78.88 - if (this.model[0] != null || !isEmpty()) {
78.89 - throw new IllegalStateException();
78.90 - }
78.91 - for (int i = 0; i < len; i++) {
78.92 - Object data = Array.get(values, i);
78.93 - super.add((T)data);
78.94 - }
78.95 - }
78.96 -
78.97 - public JSONList<T> onChange(Runnable r) {
78.98 - if (this.onchange != null) {
78.99 - throw new IllegalStateException();
78.100 - }
78.101 - this.onchange = r;
78.102 - return this;
78.103 - }
78.104 -
78.105 - @Override
78.106 - public boolean add(T e) {
78.107 - boolean ret = super.add(e);
78.108 - notifyChange();
78.109 - return ret;
78.110 - }
78.111 -
78.112 - @Override
78.113 - public boolean addAll(Collection<? extends T> c) {
78.114 - boolean ret = super.addAll(c);
78.115 - notifyChange();
78.116 - return ret;
78.117 - }
78.118 -
78.119 - @Override
78.120 - public boolean addAll(int index, Collection<? extends T> c) {
78.121 - boolean ret = super.addAll(index, c);
78.122 - notifyChange();
78.123 - return ret;
78.124 - }
78.125 -
78.126 - @Override
78.127 - public boolean remove(Object o) {
78.128 - boolean ret = super.remove(o);
78.129 - notifyChange();
78.130 - return ret;
78.131 - }
78.132 -
78.133 - @Override
78.134 - public void clear() {
78.135 - super.clear();
78.136 - notifyChange();
78.137 - }
78.138 -
78.139 - @Override
78.140 - public boolean removeAll(Collection<?> c) {
78.141 - boolean ret = super.removeAll(c);
78.142 - notifyChange();
78.143 - return ret;
78.144 - }
78.145 -
78.146 - @Override
78.147 - public boolean retainAll(Collection<?> c) {
78.148 - boolean ret = super.retainAll(c);
78.149 - notifyChange();
78.150 - return ret;
78.151 - }
78.152 -
78.153 - @Override
78.154 - public T set(int index, T element) {
78.155 - T ret = super.set(index, element);
78.156 - notifyChange();
78.157 - return ret;
78.158 - }
78.159 -
78.160 - @Override
78.161 - public void add(int index, T element) {
78.162 - super.add(index, element);
78.163 - notifyChange();
78.164 - }
78.165 -
78.166 - @Override
78.167 - public T remove(int index) {
78.168 - T ret = super.remove(index);
78.169 - notifyChange();
78.170 - return ret;
78.171 - }
78.172 -
78.173 - @Override
78.174 - public String toString() {
78.175 - Iterator<T> it = iterator();
78.176 - if (!it.hasNext()) {
78.177 - return "[]";
78.178 - }
78.179 - String sep = "";
78.180 - StringBuilder sb = new StringBuilder();
78.181 - sb.append('[');
78.182 - while (it.hasNext()) {
78.183 - T t = it.next();
78.184 - sb.append(sep);
78.185 - sb.append(JSON.toJSON(t));
78.186 - sep = ",";
78.187 - }
78.188 - sb.append(']');
78.189 - return sb.toString();
78.190 - }
78.191 -
78.192 - private void notifyChange() {
78.193 - Bindings m = model[0];
78.194 - if (m != null) {
78.195 - m.valueHasMutated(name);
78.196 - for (String dependant : deps) {
78.197 - m.valueHasMutated(dependant);
78.198 - }
78.199 - Runnable r = onchange;
78.200 - if (r != null) {
78.201 - r.run();
78.202 - }
78.203 - }
78.204 - }
78.205 -
78.206 - public void cloneAll(BrwsrCtx c, Collection<T> other) {
78.207 - Boolean isModel = null;
78.208 - for (T t : other) {
78.209 - if (isModel == null) {
78.210 - isModel = JSON.isModel(t.getClass());
78.211 - }
78.212 - if (isModel) {
78.213 - add(JSON.bindTo(t, c));
78.214 - } else {
78.215 - add(t);
78.216 - }
78.217 - }
78.218 - }
78.219 -
78.220 - @Override
78.221 - public JSONList clone() {
78.222 - throw new UnsupportedOperationException();
78.223 - }
78.224 -
78.225 - static final Object koData(Collection<?> c, Bindings m) {
78.226 - Object[] arr = c.toArray(new Object[c.size()]);
78.227 - for (int i = 0; i < arr.length; i++) {
78.228 - Object r = WrapperObject.find(arr[i], m);
78.229 - if (r != null) {
78.230 - arr[i] = r;
78.231 - }
78.232 - }
78.233 - return m.wrapArray(arr);
78.234 - }
78.235 -
78.236 - final Object koData() {
78.237 - return koData(this, model[0]);
78.238 - }
78.239 -}
79.1 --- a/json/src/main/java/org/apidesign/html/json/impl/ModelProcessor.java Mon Dec 16 15:48:09 2013 +0100
79.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
79.3 @@ -1,1767 +0,0 @@
79.4 -/**
79.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
79.6 - *
79.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
79.8 - *
79.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
79.10 - * Other names may be trademarks of their respective owners.
79.11 - *
79.12 - * The contents of this file are subject to the terms of either the GNU
79.13 - * General Public License Version 2 only ("GPL") or the Common
79.14 - * Development and Distribution License("CDDL") (collectively, the
79.15 - * "License"). You may not use this file except in compliance with the
79.16 - * License. You can obtain a copy of the License at
79.17 - * http://www.netbeans.org/cddl-gplv2.html
79.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
79.19 - * specific language governing permissions and limitations under the
79.20 - * License. When distributing the software, include this License Header
79.21 - * Notice in each file and include the License file at
79.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
79.23 - * particular file as subject to the "Classpath" exception as provided
79.24 - * by Oracle in the GPL Version 2 section of the License file that
79.25 - * accompanied this code. If applicable, add the following below the
79.26 - * License Header, with the fields enclosed by brackets [] replaced by
79.27 - * your own identifying information:
79.28 - * "Portions Copyrighted [year] [name of copyright owner]"
79.29 - *
79.30 - * Contributor(s):
79.31 - *
79.32 - * The Original Software is NetBeans. The Initial Developer of the Original
79.33 - * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
79.34 - *
79.35 - * If you wish your version of this file to be governed by only the CDDL
79.36 - * or only the GPL Version 2, indicate your decision by adding
79.37 - * "[Contributor] elects to include this software in this distribution
79.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
79.39 - * single choice of license, a recipient has the option to distribute
79.40 - * your version of this file under either the CDDL, the GPL Version 2 or
79.41 - * to extend the choice of license to its licensees as provided above.
79.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
79.43 - * Version 2 license, then the option applies only if the new code is
79.44 - * made subject to such option by the copyright holder.
79.45 - */
79.46 -package org.apidesign.html.json.impl;
79.47 -
79.48 -import java.io.IOException;
79.49 -import java.io.OutputStreamWriter;
79.50 -import java.io.StringWriter;
79.51 -import java.io.Writer;
79.52 -import java.lang.annotation.AnnotationTypeMismatchException;
79.53 -import java.lang.annotation.IncompleteAnnotationException;
79.54 -import java.lang.reflect.Method;
79.55 -import java.util.ArrayList;
79.56 -import java.util.Arrays;
79.57 -import java.util.Collection;
79.58 -import java.util.Collections;
79.59 -import java.util.HashMap;
79.60 -import java.util.HashSet;
79.61 -import java.util.LinkedHashSet;
79.62 -import java.util.List;
79.63 -import java.util.Map;
79.64 -import java.util.ResourceBundle;
79.65 -import java.util.Set;
79.66 -import java.util.WeakHashMap;
79.67 -import java.util.logging.Level;
79.68 -import java.util.logging.Logger;
79.69 -import javax.annotation.processing.AbstractProcessor;
79.70 -import javax.annotation.processing.Completion;
79.71 -import javax.annotation.processing.Completions;
79.72 -import javax.annotation.processing.ProcessingEnvironment;
79.73 -import javax.annotation.processing.Processor;
79.74 -import javax.annotation.processing.RoundEnvironment;
79.75 -import javax.annotation.processing.SupportedAnnotationTypes;
79.76 -import javax.annotation.processing.SupportedSourceVersion;
79.77 -import javax.lang.model.SourceVersion;
79.78 -import javax.lang.model.element.AnnotationMirror;
79.79 -import javax.lang.model.element.AnnotationValue;
79.80 -import javax.lang.model.element.Element;
79.81 -import javax.lang.model.element.ElementKind;
79.82 -import javax.lang.model.element.ExecutableElement;
79.83 -import javax.lang.model.element.Modifier;
79.84 -import javax.lang.model.element.PackageElement;
79.85 -import javax.lang.model.element.TypeElement;
79.86 -import javax.lang.model.element.VariableElement;
79.87 -import javax.lang.model.type.ArrayType;
79.88 -import javax.lang.model.type.DeclaredType;
79.89 -import javax.lang.model.type.MirroredTypeException;
79.90 -import javax.lang.model.type.TypeKind;
79.91 -import javax.lang.model.type.TypeMirror;
79.92 -import javax.lang.model.util.Elements;
79.93 -import javax.lang.model.util.Types;
79.94 -import javax.tools.Diagnostic;
79.95 -import javax.tools.FileObject;
79.96 -import net.java.html.json.ComputedProperty;
79.97 -import net.java.html.json.Model;
79.98 -import net.java.html.json.Function;
79.99 -import net.java.html.json.ModelOperation;
79.100 -import net.java.html.json.OnPropertyChange;
79.101 -import net.java.html.json.OnReceive;
79.102 -import net.java.html.json.Property;
79.103 -import org.openide.util.lookup.ServiceProvider;
79.104 -
79.105 -/** Annotation processor to process {@link Model @Model} annotations and
79.106 - * generate appropriate model classes.
79.107 - *
79.108 - * @author Jaroslav Tulach <jtulach@netbeans.org>
79.109 - */
79.110 -@ServiceProvider(service=Processor.class)
79.111 -@SupportedSourceVersion(SourceVersion.RELEASE_6)
79.112 -@SupportedAnnotationTypes({
79.113 - "net.java.html.json.Model",
79.114 - "net.java.html.json.ModelOperation",
79.115 - "net.java.html.json.Function",
79.116 - "net.java.html.json.OnReceive",
79.117 - "net.java.html.json.OnPropertyChange",
79.118 - "net.java.html.json.ComputedProperty",
79.119 - "net.java.html.json.Property"
79.120 -})
79.121 -public final class ModelProcessor extends AbstractProcessor {
79.122 - private static final Logger LOG = Logger.getLogger(ModelProcessor.class.getName());
79.123 - private final Map<Element,String> models = new WeakHashMap<Element,String>();
79.124 - private final Map<Element,Prprt[]> verify = new WeakHashMap<Element,Prprt[]>();
79.125 - @Override
79.126 - public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
79.127 - boolean ok = true;
79.128 - for (Element e : roundEnv.getElementsAnnotatedWith(Model.class)) {
79.129 - if (!processModel(e)) {
79.130 - ok = false;
79.131 - }
79.132 - }
79.133 - if (roundEnv.processingOver()) {
79.134 - models.clear();
79.135 - for (Map.Entry<Element, Prprt[]> entry : verify.entrySet()) {
79.136 - TypeElement te = (TypeElement)entry.getKey();
79.137 - String fqn = processingEnv.getElementUtils().getBinaryName(te).toString();
79.138 - Element finalElem = processingEnv.getElementUtils().getTypeElement(fqn);
79.139 - if (finalElem == null) {
79.140 - continue;
79.141 - }
79.142 - Prprt[] props;
79.143 - Model m = finalElem.getAnnotation(Model.class);
79.144 - if (m == null) {
79.145 - continue;
79.146 - }
79.147 - props = Prprt.wrap(processingEnv, finalElem, m.properties());
79.148 - for (Prprt p : props) {
79.149 - boolean[] isModel = { false };
79.150 - boolean[] isEnum = { false };
79.151 - boolean[] isPrimitive = { false };
79.152 - String t = checkType(p, isModel, isEnum, isPrimitive);
79.153 - if (isEnum[0]) {
79.154 - continue;
79.155 - }
79.156 - if (isPrimitive[0]) {
79.157 - continue;
79.158 - }
79.159 - if (isModel[0]) {
79.160 - continue;
79.161 - }
79.162 - if ("java.lang.String".equals(t)) {
79.163 - continue;
79.164 - }
79.165 - error("The type " + t + " should be defined by @Model annotation", entry.getKey());
79.166 - }
79.167 - }
79.168 - verify.clear();
79.169 - }
79.170 - return ok;
79.171 - }
79.172 -
79.173 - private void error(String msg, Element e) {
79.174 - processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, msg, e);
79.175 - }
79.176 -
79.177 - private boolean processModel(Element e) {
79.178 - boolean ok = true;
79.179 - Model m = e.getAnnotation(Model.class);
79.180 - if (m == null) {
79.181 - return true;
79.182 - }
79.183 - String pkg = findPkgName(e);
79.184 - Writer w;
79.185 - String className = m.className();
79.186 - models.put(e, className);
79.187 - try {
79.188 - StringWriter body = new StringWriter();
79.189 - List<String> propsGetSet = new ArrayList<String>();
79.190 - List<String> functions = new ArrayList<String>();
79.191 - Map<String, Collection<String>> propsDeps = new HashMap<String, Collection<String>>();
79.192 - Map<String, Collection<String>> functionDeps = new HashMap<String, Collection<String>>();
79.193 - Prprt[] props = createProps(e, m.properties());
79.194 -
79.195 - if (!generateComputedProperties(body, props, e.getEnclosedElements(), propsGetSet, propsDeps)) {
79.196 - ok = false;
79.197 - }
79.198 - if (!generateOnChange(e, propsDeps, props, className, functionDeps)) {
79.199 - ok = false;
79.200 - }
79.201 - if (!generateProperties(e, body, props, propsGetSet, propsDeps, functionDeps)) {
79.202 - ok = false;
79.203 - }
79.204 - if (!generateFunctions(e, body, className, e.getEnclosedElements(), functions)) {
79.205 - ok = false;
79.206 - }
79.207 - if (!generateReceive(e, body, className, e.getEnclosedElements(), functions)) {
79.208 - ok = false;
79.209 - }
79.210 - if (!generateOperation(e, body, className, e.getEnclosedElements())) {
79.211 - ok = false;
79.212 - }
79.213 - FileObject java = processingEnv.getFiler().createSourceFile(pkg + '.' + className, e);
79.214 - w = new OutputStreamWriter(java.openOutputStream());
79.215 - try {
79.216 - w.append("package " + pkg + ";\n");
79.217 - w.append("import net.java.html.json.*;\n");
79.218 - w.append("public final class ").append(className).append(" implements Cloneable {\n");
79.219 - w.append(" private boolean locked;\n");
79.220 - w.append(" private net.java.html.BrwsrCtx context;\n");
79.221 - w.append(" private org.apidesign.html.json.impl.Bindings[] ko = { null };\n");
79.222 - w.append(body.toString());
79.223 - w.append(" private static Class<" + inPckName(e) + "> modelFor() { return null; }\n");
79.224 - w.append(" private ").append(className).append("(net.java.html.BrwsrCtx context) {\n");
79.225 - w.append(" this.context = context;\n");
79.226 - w.append(" };\n");
79.227 - w.append(" public ").append(className).append("() {\n");
79.228 - w.append(" this(net.java.html.BrwsrCtx.findDefault(").append(className).append(".class));\n");
79.229 - for (Prprt p : props) {
79.230 - if (p.array()) {
79.231 - continue;
79.232 - }
79.233 - boolean[] isModel = {false};
79.234 - boolean[] isEnum = {false};
79.235 - boolean isPrimitive[] = {false};
79.236 - String tn = checkType(p, isModel, isEnum, isPrimitive);
79.237 - if (isModel[0]) {
79.238 - w.write(" prop_" + p.name() + " = new " + tn + "();\n");
79.239 - }
79.240 - }
79.241 - w.append(" };\n");
79.242 - if (props.length > 0) {
79.243 - w.append(" public ").append(className).append("(");
79.244 - Prprt firstArray = null;
79.245 - String sep = "";
79.246 - for (Prprt p : props) {
79.247 - if (p.array()) {
79.248 - if (firstArray == null) {
79.249 - firstArray = p;
79.250 - }
79.251 - continue;
79.252 - }
79.253 - String tn = typeName(e, p);
79.254 - w.write(sep);
79.255 - w.write(tn);
79.256 - w.write(" " + p.name());
79.257 - sep = ", ";
79.258 - }
79.259 - if (firstArray != null) {
79.260 - String tn;
79.261 - boolean[] isModel = {false};
79.262 - boolean[] isEnum = {false};
79.263 - boolean isPrimitive[] = {false};
79.264 - tn = checkType(firstArray, isModel, isEnum, isPrimitive);
79.265 - w.write(sep);
79.266 - w.write(tn);
79.267 - w.write("... " + firstArray.name());
79.268 - }
79.269 - w.append(") {\n");
79.270 - w.append(" this(net.java.html.BrwsrCtx.findDefault(").append(className).append(".class));\n");
79.271 - for (Prprt p : props) {
79.272 - if (p.array()) {
79.273 - continue;
79.274 - }
79.275 - w.write(" this.prop_" + p.name() + " = " + p.name() + ";\n");
79.276 - }
79.277 - if (firstArray != null) {
79.278 - w.write(" this.prop_" + firstArray.name() + ".init(" + firstArray.name() + ");\n");
79.279 - }
79.280 - w.append(" };\n");
79.281 - }
79.282 - w.append(" private org.apidesign.html.json.impl.Bindings intKnckt() {\n");
79.283 - w.append(" if (ko[0] != null) return ko[0];\n");
79.284 - w.append(" ko[0] = org.apidesign.html.json.impl.Bindings.apply(context, this);\n");
79.285 - {
79.286 - w.append(" org.apidesign.html.json.spi.PropertyBinding[] propArr = {\n");
79.287 - for (int i = 0; i < propsGetSet.size(); i += 5) {
79.288 - w.append(" ko[0].registerProperty(\"").append(propsGetSet.get(i)).append("\", this, new P(");
79.289 - w.append((i / 5) + "), " + (propsGetSet.get(i + 2) == null) + "),\n");
79.290 - }
79.291 - w.append(" };\n");
79.292 - }
79.293 - {
79.294 - w.append(" org.apidesign.html.json.spi.FunctionBinding[] funcArr = {\n");
79.295 - for (int i = 0; i < functions.size(); i += 2) {
79.296 - w.append(" ko[0].registerFunction(\"").append(functions.get(i)).append("\", this, new P(");
79.297 - w.append((i / 2) + ")),\n");
79.298 - }
79.299 - w.append(" };\n");
79.300 - }
79.301 - w.append(" ko[0].finish(this, propArr, funcArr);\n");
79.302 - w.append(" return ko[0];\n");
79.303 - w.append(" };\n");
79.304 - w.append(" private static final class P implements org.apidesign.html.json.impl.SetAndGet<" + className + ">,\n");
79.305 - w.append(" org.apidesign.html.json.impl.Callback<" + className + ">,\n");
79.306 - w.append(" org.apidesign.html.json.impl.FromJSON<" + className + "> {\n");
79.307 - w.append(" private final int type;\n");
79.308 - w.append(" P(int t) { type = t; };\n");
79.309 - w.append(" public void setValue(" + className + " data, Object value) {\n");
79.310 - w.append(" switch (type) {\n");
79.311 - for (int i = 0; i < propsGetSet.size(); i += 5) {
79.312 - final String set = propsGetSet.get(i + 2);
79.313 - String tn = propsGetSet.get(i + 4);
79.314 - String btn = findBoxedType(tn);
79.315 - if (btn != null) {
79.316 - tn = btn;
79.317 - }
79.318 - if (set != null) {
79.319 - w.append(" case " + (i / 5) + ": data." + strip(set) + "(org.apidesign.html.json.impl.JSON.extractValue(" + tn + ".class, value)); return;\n");
79.320 - }
79.321 - }
79.322 - w.append(" }\n");
79.323 - w.append(" }\n");
79.324 - w.append(" public Object getValue(" + className + " data) {\n");
79.325 - w.append(" switch (type) {\n");
79.326 - for (int i = 0; i < propsGetSet.size(); i += 5) {
79.327 - final String get = propsGetSet.get(i + 1);
79.328 - if (get != null) {
79.329 - w.append(" case " + (i / 5) + ": return data." + strip(get) + "();\n");
79.330 - }
79.331 - }
79.332 - w.append(" }\n");
79.333 - w.append(" throw new UnsupportedOperationException();\n");
79.334 - w.append(" }\n");
79.335 - w.append(" public void call(" + className + " model, Object data, Object ev) {\n");
79.336 - w.append(" switch (type) {\n");
79.337 - for (int i = 0; i < functions.size(); i += 2) {
79.338 - final String name = functions.get(i);
79.339 - w.append(" case " + (i / 2) + ": model." + name + "(data, ev); return;\n");
79.340 - }
79.341 - w.append(" }\n");
79.342 - w.append(" throw new UnsupportedOperationException();\n");
79.343 - w.append(" }\n");
79.344 - w.append(" public Class<" + className + "> factoryFor() { return " + className + ".class; }\n");
79.345 - w.append(" public " + className + " read(net.java.html.BrwsrCtx c, Object json) { return new " + className + "(c, json); }\n");
79.346 - w.append(" public " + className + " cloneTo(Object o, net.java.html.BrwsrCtx c) { return ((" + className + ")o).clone(c); }\n");
79.347 - w.append(" }\n");
79.348 - w.append(" static { org.apidesign.html.json.impl.JSON.register(new P(0)); }\n");
79.349 - w.append(" private ").append(className).append("(net.java.html.BrwsrCtx c, Object json) {\n");
79.350 - w.append(" this.context = c;\n");
79.351 - int values = 0;
79.352 - for (int i = 0; i < propsGetSet.size(); i += 5) {
79.353 - Prprt p = findPrprt(props, propsGetSet.get(i));
79.354 - if (p == null) {
79.355 - continue;
79.356 - }
79.357 - values++;
79.358 - }
79.359 - w.append(" Object[] ret = new Object[" + values + "];\n");
79.360 - w.append(" org.apidesign.html.json.impl.JSON.extract(context, json, new String[] {\n");
79.361 - for (int i = 0; i < propsGetSet.size(); i += 5) {
79.362 - Prprt p = findPrprt(props, propsGetSet.get(i));
79.363 - if (p == null) {
79.364 - continue;
79.365 - }
79.366 - w.append(" \"").append(propsGetSet.get(i)).append("\",\n");
79.367 - }
79.368 - w.append(" }, ret);\n");
79.369 - for (int i = 0, cnt = 0, prop = 0; i < propsGetSet.size(); i += 5) {
79.370 - final String pn = propsGetSet.get(i);
79.371 - Prprt p = findPrprt(props, pn);
79.372 - if (p == null) {
79.373 - continue;
79.374 - }
79.375 - boolean[] isModel = { false };
79.376 - boolean[] isEnum = { false };
79.377 - boolean isPrimitive[] = { false };
79.378 - String type = checkType(props[prop++], isModel, isEnum, isPrimitive);
79.379 - if (p.array()) {
79.380 - w.append(" if (ret[" + cnt + "] instanceof Object[]) {\n");
79.381 - w.append(" for (Object e : ((Object[])ret[" + cnt + "])) {\n");
79.382 - if (isModel[0]) {
79.383 - w.append(" this.prop_").append(pn).append(".add(org.apidesign.html.json.impl.JSON.read");
79.384 - w.append("(c, " + type + ".class, e));\n");
79.385 - } else if (isEnum[0]) {
79.386 - w.append(" this.prop_").append(pn);
79.387 - w.append(".add(e == null ? null : ");
79.388 - w.append(type).append(".valueOf(org.apidesign.html.json.impl.JSON.stringValue(e)));\n");
79.389 - } else {
79.390 - if (isPrimitive(type)) {
79.391 - w.append(" this.prop_").append(pn).append(".add(org.apidesign.html.json.impl.JSON.numberValue(e).");
79.392 - w.append(type).append("Value());\n");
79.393 - } else {
79.394 - w.append(" this.prop_").append(pn).append(".add((");
79.395 - w.append(type).append(")e);\n");
79.396 - }
79.397 - }
79.398 - w.append(" }\n");
79.399 - w.append(" }\n");
79.400 - } else {
79.401 - if (isEnum[0]) {
79.402 - w.append(" try {\n");
79.403 - w.append(" this.prop_").append(pn);
79.404 - w.append(" = ret[" + cnt + "] == null ? null : ");
79.405 - w.append(type).append(".valueOf(org.apidesign.html.json.impl.JSON.stringValue(ret[" + cnt + "]));\n");
79.406 - w.append(" } catch (IllegalArgumentException ex) {\n");
79.407 - w.append(" ex.printStackTrace();\n");
79.408 - w.append(" }\n");
79.409 - } else if (isPrimitive(type)) {
79.410 - w.append(" this.prop_").append(pn);
79.411 - w.append(" = ret[" + cnt + "] == null ? ");
79.412 - if ("char".equals(type)) {
79.413 - w.append("0 : (org.apidesign.html.json.impl.JSON.charValue(");
79.414 - } else if ("boolean".equals(type)) {
79.415 - w.append("false : (org.apidesign.html.json.impl.JSON.boolValue(");
79.416 - } else {
79.417 - w.append("0 : (org.apidesign.html.json.impl.JSON.numberValue(");
79.418 - }
79.419 - w.append("ret[" + cnt + "])).");
79.420 - w.append(type).append("Value();\n");
79.421 - } else if (isModel[0]) {
79.422 - w.append(" this.prop_").append(pn).append(" = org.apidesign.html.json.impl.JSON.read");
79.423 - w.append("(c, " + type + ".class, ");
79.424 - w.append("ret[" + cnt + "]);\n");
79.425 - }else {
79.426 - w.append(" this.prop_").append(pn);
79.427 - w.append(" = (").append(type).append(')');
79.428 - w.append("ret[" + cnt + "];\n");
79.429 - }
79.430 - }
79.431 - cnt++;
79.432 - }
79.433 - w.append(" };\n");
79.434 - writeToString(props, w);
79.435 - writeClone(className, props, w);
79.436 - w.write(" /** Activates this model instance in the current {@link \n"
79.437 - + "net.java.html.json.Models#bind(java.lang.Object, net.java.html.BrwsrCtx) browser context}. \n"
79.438 - + "In case of using Knockout technology, this means to \n"
79.439 - + "bind JSON like data in this model instance with Knockout tags in \n"
79.440 - + "the surrounding HTML page.\n"
79.441 - + "*/\n"
79.442 - );
79.443 - w.write(" public " + className + " applyBindings() {\n");
79.444 - w.write(" intKnckt().applyBindings();\n");
79.445 - w.write(" return this;\n");
79.446 - w.write(" }\n");
79.447 - w.write(" public boolean equals(Object o) {\n");
79.448 - w.write(" if (o == this) return true;\n");
79.449 - w.write(" if (o instanceof org.apidesign.html.json.impl.WrapperObject) {\n");
79.450 - w.write(" ((org.apidesign.html.json.impl.WrapperObject)o).setRealObject(intKnckt().koData());\n");
79.451 - w.write(" return false;\n");
79.452 - w.write(" }\n");
79.453 - w.write(" if (!(o instanceof " + className + ")) return false;\n");
79.454 - w.write(" " + className + " p = (" + className + ")o;\n");
79.455 - for (Prprt p : props) {
79.456 - w.write(" if (!org.apidesign.html.json.impl.JSON.isSame(prop_" + p.name() + ", p.prop_" + p.name() + ")) return false;\n");
79.457 - }
79.458 - w.write(" return true;\n");
79.459 - w.write(" }\n");
79.460 - w.write(" public int hashCode() {\n");
79.461 - w.write(" int h = " + className + ".class.getName().hashCode();\n");
79.462 - for (Prprt p : props) {
79.463 - w.write(" h = org.apidesign.html.json.impl.JSON.hashPlus(prop_" + p.name() + ", h);\n");
79.464 - }
79.465 - w.write(" return h;\n");
79.466 - w.write(" }\n");
79.467 - w.write("}\n");
79.468 - } finally {
79.469 - w.close();
79.470 - }
79.471 - } catch (IOException ex) {
79.472 - error("Can't create " + className + ".java", e);
79.473 - return false;
79.474 - }
79.475 - return ok;
79.476 - }
79.477 -
79.478 - private boolean generateProperties(
79.479 - Element where,
79.480 - Writer w, Prprt[] properties,
79.481 - Collection<String> props,
79.482 - Map<String,Collection<String>> deps,
79.483 - Map<String,Collection<String>> functionDeps
79.484 - ) throws IOException {
79.485 - boolean ok = true;
79.486 - for (Prprt p : properties) {
79.487 - final String tn;
79.488 - tn = typeName(where, p);
79.489 - String[] gs = toGetSet(p.name(), tn, p.array());
79.490 - String castTo;
79.491 -
79.492 - if (p.array()) {
79.493 - w.write(" private org.apidesign.html.json.impl.JSONList<" + tn + "> prop_" + p.name() + " = new org.apidesign.html.json.impl.JSONList<" + tn + ">(ko, \""
79.494 - + p.name() + "\"");
79.495 - Collection<String> dependants = deps.get(p.name());
79.496 - if (dependants != null) {
79.497 - for (String depProp : dependants) {
79.498 - w.write(", ");
79.499 - w.write('\"');
79.500 - w.write(depProp);
79.501 - w.write('\"');
79.502 - }
79.503 - }
79.504 - w.write(")");
79.505 -
79.506 - dependants = functionDeps.get(p.name());
79.507 - if (dependants != null) {
79.508 - w.write(".onChange(new Runnable() { public void run() {\n");
79.509 - for (String call : dependants) {
79.510 - w.append(" ").append(call);
79.511 - }
79.512 - w.write(" }})");
79.513 - }
79.514 - w.write(";\n");
79.515 -
79.516 - castTo = "java.util.List";
79.517 - w.write(" public java.util.List<" + tn + "> " + gs[0] + "() {\n");
79.518 - w.write(" if (locked) throw new IllegalStateException();\n");
79.519 - w.write(" return prop_" + p.name() + ";\n");
79.520 - w.write(" }\n");
79.521 - } else {
79.522 - castTo = tn;
79.523 - w.write(" private " + tn + " prop_" + p.name() + ";\n");
79.524 - w.write(" public " + tn + " " + gs[0] + "() {\n");
79.525 - w.write(" if (locked) throw new IllegalStateException();\n");
79.526 - w.write(" return prop_" + p.name() + ";\n");
79.527 - w.write(" }\n");
79.528 - w.write(" public void " + gs[1] + "(" + tn + " v) {\n");
79.529 - w.write(" if (locked) throw new IllegalStateException();\n");
79.530 - w.write(" if (org.apidesign.html.json.impl.JSON.isSame(prop_" + p.name() + ", v)) return;\n");
79.531 - w.write(" prop_" + p.name() + " = v;\n");
79.532 - w.write(" org.apidesign.html.json.impl.Bindings b = ko[0];\n");
79.533 - w.write(" if (b != null) {\n");
79.534 - w.write(" b.valueHasMutated(\"" + p.name() + "\");\n");
79.535 - Collection<String> dependants = deps.get(p.name());
79.536 - if (dependants != null) {
79.537 - for (String depProp : dependants) {
79.538 - w.write(" b.valueHasMutated(\"" + depProp + "\");\n");
79.539 - }
79.540 - }
79.541 - w.write(" }\n");
79.542 - dependants = functionDeps.get(p.name());
79.543 - if (dependants != null) {
79.544 - for (String call : dependants) {
79.545 - w.append(" ").append(call);
79.546 - }
79.547 - }
79.548 - w.write(" }\n");
79.549 - }
79.550 -
79.551 - props.add(p.name());
79.552 - props.add(gs[2]);
79.553 - props.add(gs[3]);
79.554 - props.add(gs[0]);
79.555 - props.add(castTo);
79.556 - }
79.557 - return ok;
79.558 - }
79.559 -
79.560 - private boolean generateComputedProperties(
79.561 - Writer w, Prprt[] fixedProps,
79.562 - Collection<? extends Element> arr, Collection<String> props,
79.563 - Map<String,Collection<String>> deps
79.564 - ) throws IOException {
79.565 - boolean ok = true;
79.566 - for (Element e : arr) {
79.567 - if (e.getKind() != ElementKind.METHOD) {
79.568 - continue;
79.569 - }
79.570 - if (e.getAnnotation(ComputedProperty.class) == null) {
79.571 - continue;
79.572 - }
79.573 - if (!e.getModifiers().contains(Modifier.STATIC)) {
79.574 - error("Method " + e.getSimpleName() + " has to be static when annotated by @ComputedProperty", e);
79.575 - ok = false;
79.576 - continue;
79.577 - }
79.578 - ExecutableElement ee = (ExecutableElement)e;
79.579 - final TypeMirror rt = ee.getReturnType();
79.580 - final Types tu = processingEnv.getTypeUtils();
79.581 - TypeMirror ert = tu.erasure(rt);
79.582 - String tn = fqn(ert, ee);
79.583 - boolean array = false;
79.584 - final TypeMirror toCheck;
79.585 - if (tn.equals("java.util.List")) {
79.586 - array = true;
79.587 - toCheck = ((DeclaredType)rt).getTypeArguments().get(0);
79.588 - } else {
79.589 - toCheck = rt;
79.590 - }
79.591 -
79.592 - final String sn = ee.getSimpleName().toString();
79.593 -
79.594 - if (toCheck.getKind().isPrimitive()) {
79.595 - // OK
79.596 - } else {
79.597 - TypeMirror stringType = processingEnv.getElementUtils().getTypeElement("java.lang.String").asType();
79.598 - TypeMirror enumType = processingEnv.getElementUtils().getTypeElement("java.lang.Enum").asType();
79.599 -
79.600 - if (tu.isSubtype(toCheck, stringType)) {
79.601 - // OK
79.602 - } else if (tu.isSubtype(tu.erasure(toCheck), tu.erasure(enumType))) {
79.603 - // OK
79.604 - } else if (isModel(toCheck)) {
79.605 - // OK
79.606 - } else {
79.607 - ok = false;
79.608 - error(sn + " cannot return " + toCheck, e);
79.609 - }
79.610 - }
79.611 -
79.612 - String[] gs = toGetSet(sn, tn, array);
79.613 -
79.614 - w.write(" public " + tn + " " + gs[0] + "() {\n");
79.615 - w.write(" if (locked) throw new IllegalStateException();\n");
79.616 - int arg = 0;
79.617 - for (VariableElement pe : ee.getParameters()) {
79.618 - final String dn = pe.getSimpleName().toString();
79.619 -
79.620 - if (!verifyPropName(pe, dn, fixedProps)) {
79.621 - ok = false;
79.622 - }
79.623 -
79.624 - final String dt = fqn(pe.asType(), ee);
79.625 - String[] call = toGetSet(dn, dt, false);
79.626 - w.write(" " + dt + " arg" + (++arg) + " = ");
79.627 - w.write(call[0] + "();\n");
79.628 -
79.629 - Collection<String> depends = deps.get(dn);
79.630 - if (depends == null) {
79.631 - depends = new LinkedHashSet<String>();
79.632 - deps.put(dn, depends);
79.633 - }
79.634 - depends.add(sn);
79.635 - }
79.636 - w.write(" try {\n");
79.637 - w.write(" locked = true;\n");
79.638 - w.write(" return " + fqn(ee.getEnclosingElement().asType(), ee) + '.' + e.getSimpleName() + "(");
79.639 - String sep = "";
79.640 - for (int i = 1; i <= arg; i++) {
79.641 - w.write(sep);
79.642 - w.write("arg" + i);
79.643 - sep = ", ";
79.644 - }
79.645 - w.write(");\n");
79.646 - w.write(" } finally {\n");
79.647 - w.write(" locked = false;\n");
79.648 - w.write(" }\n");
79.649 - w.write(" }\n");
79.650 -
79.651 - props.add(e.getSimpleName().toString());
79.652 - props.add(gs[2]);
79.653 - props.add(null);
79.654 - props.add(gs[0]);
79.655 - props.add(tn);
79.656 - }
79.657 -
79.658 - return ok;
79.659 - }
79.660 -
79.661 - private static String[] toGetSet(String name, String type, boolean array) {
79.662 - String n = Character.toUpperCase(name.charAt(0)) + name.substring(1);
79.663 - String bck2brwsrType = "L" + type.replace('.', '_') + "_2";
79.664 - if ("int".equals(type)) {
79.665 - bck2brwsrType = "I";
79.666 - }
79.667 - if ("double".equals(type)) {
79.668 - bck2brwsrType = "D";
79.669 - }
79.670 - String pref = "get";
79.671 - if ("boolean".equals(type)) {
79.672 - pref = "is";
79.673 - bck2brwsrType = "Z";
79.674 - }
79.675 - final String nu = n.replace('.', '_');
79.676 - if (array) {
79.677 - return new String[] {
79.678 - "get" + n,
79.679 - null,
79.680 - "get" + nu + "__Ljava_util_List_2",
79.681 - null
79.682 - };
79.683 - }
79.684 - return new String[]{
79.685 - pref + n,
79.686 - "set" + n,
79.687 - pref + nu + "__" + bck2brwsrType,
79.688 - "set" + nu + "__V" + bck2brwsrType
79.689 - };
79.690 - }
79.691 -
79.692 - private String typeName(Element where, Prprt p) {
79.693 - String ret;
79.694 - boolean[] isModel = { false };
79.695 - boolean[] isEnum = { false };
79.696 - boolean isPrimitive[] = { false };
79.697 - ret = checkType(p, isModel, isEnum, isPrimitive);
79.698 - if (p.array()) {
79.699 - String bt = findBoxedType(ret);
79.700 - if (bt != null) {
79.701 - return bt;
79.702 - }
79.703 - }
79.704 - return ret;
79.705 - }
79.706 -
79.707 - private static String findBoxedType(String ret) {
79.708 - if (ret.equals("boolean")) {
79.709 - return Boolean.class.getName();
79.710 - }
79.711 - if (ret.equals("byte")) {
79.712 - return Byte.class.getName();
79.713 - }
79.714 - if (ret.equals("short")) {
79.715 - return Short.class.getName();
79.716 - }
79.717 - if (ret.equals("char")) {
79.718 - return Character.class.getName();
79.719 - }
79.720 - if (ret.equals("int")) {
79.721 - return Integer.class.getName();
79.722 - }
79.723 - if (ret.equals("long")) {
79.724 - return Long.class.getName();
79.725 - }
79.726 - if (ret.equals("float")) {
79.727 - return Float.class.getName();
79.728 - }
79.729 - if (ret.equals("double")) {
79.730 - return Double.class.getName();
79.731 - }
79.732 - return null;
79.733 - }
79.734 -
79.735 - private boolean verifyPropName(Element e, String propName, Prprt[] existingProps) {
79.736 - StringBuilder sb = new StringBuilder();
79.737 - String sep = "";
79.738 - for (Prprt Prprt : existingProps) {
79.739 - if (Prprt.name().equals(propName)) {
79.740 - return true;
79.741 - }
79.742 - sb.append(sep);
79.743 - sb.append('"');
79.744 - sb.append(Prprt.name());
79.745 - sb.append('"');
79.746 - sep = ", ";
79.747 - }
79.748 - error(
79.749 - propName + " is not one of known properties: " + sb
79.750 - , e
79.751 - );
79.752 - return false;
79.753 - }
79.754 -
79.755 - private static String findPkgName(Element e) {
79.756 - for (;;) {
79.757 - if (e.getKind() == ElementKind.PACKAGE) {
79.758 - return ((PackageElement)e).getQualifiedName().toString();
79.759 - }
79.760 - e = e.getEnclosingElement();
79.761 - }
79.762 - }
79.763 -
79.764 - private boolean generateFunctions(
79.765 - Element clazz, StringWriter body, String className,
79.766 - List<? extends Element> enclosedElements, List<String> functions
79.767 - ) {
79.768 - for (Element m : enclosedElements) {
79.769 - if (m.getKind() != ElementKind.METHOD) {
79.770 - continue;
79.771 - }
79.772 - ExecutableElement e = (ExecutableElement)m;
79.773 - Function onF = e.getAnnotation(Function.class);
79.774 - if (onF == null) {
79.775 - continue;
79.776 - }
79.777 - if (!e.getModifiers().contains(Modifier.STATIC)) {
79.778 - error("@OnFunction method needs to be static", e);
79.779 - return false;
79.780 - }
79.781 - if (e.getModifiers().contains(Modifier.PRIVATE)) {
79.782 - error("@OnFunction method cannot be private", e);
79.783 - return false;
79.784 - }
79.785 - if (e.getReturnType().getKind() != TypeKind.VOID) {
79.786 - error("@OnFunction method should return void", e);
79.787 - return false;
79.788 - }
79.789 - String n = e.getSimpleName().toString();
79.790 - body.append(" private void ").append(n).append("(Object data, Object ev) {\n");
79.791 - body.append(" ").append(((TypeElement)clazz).getQualifiedName()).append(".").append(n).append("(");
79.792 - body.append(wrapParams(e, null, className, "ev", "data"));
79.793 - body.append(");\n");
79.794 - body.append(" }\n");
79.795 -
79.796 - functions.add(n);
79.797 - functions.add(n + "__VLjava_lang_Object_2Ljava_lang_Object_2");
79.798 - }
79.799 - return true;
79.800 - }
79.801 -
79.802 - private boolean generateOnChange(Element clazz, Map<String,Collection<String>> propDeps,
79.803 - Prprt[] properties, String className,
79.804 - Map<String, Collection<String>> functionDeps
79.805 - ) {
79.806 - for (Element m : clazz.getEnclosedElements()) {
79.807 - if (m.getKind() != ElementKind.METHOD) {
79.808 - continue;
79.809 - }
79.810 - ExecutableElement e = (ExecutableElement) m;
79.811 - OnPropertyChange onPC = e.getAnnotation(OnPropertyChange.class);
79.812 - if (onPC == null) {
79.813 - continue;
79.814 - }
79.815 - for (String pn : onPC.value()) {
79.816 - if (findPrprt(properties, pn) == null && findDerivedFrom(propDeps, pn).isEmpty()) {
79.817 - error("No Prprt named '" + pn + "' in the model", clazz);
79.818 - return false;
79.819 - }
79.820 - }
79.821 - if (!e.getModifiers().contains(Modifier.STATIC)) {
79.822 - error("@OnPrprtChange method needs to be static", e);
79.823 - return false;
79.824 - }
79.825 - if (e.getModifiers().contains(Modifier.PRIVATE)) {
79.826 - error("@OnPrprtChange method cannot be private", e);
79.827 - return false;
79.828 - }
79.829 - if (e.getReturnType().getKind() != TypeKind.VOID) {
79.830 - error("@OnPrprtChange method should return void", e);
79.831 - return false;
79.832 - }
79.833 - String n = e.getSimpleName().toString();
79.834 -
79.835 -
79.836 - for (String pn : onPC.value()) {
79.837 - StringBuilder call = new StringBuilder();
79.838 - call.append(" ").append(clazz.getSimpleName()).append(".").append(n).append("(");
79.839 - call.append(wrapPropName(e, className, "name", pn));
79.840 - call.append(");\n");
79.841 -
79.842 - Collection<String> change = functionDeps.get(pn);
79.843 - if (change == null) {
79.844 - change = new ArrayList<String>();
79.845 - functionDeps.put(pn, change);
79.846 - }
79.847 - change.add(call.toString());
79.848 - for (String dpn : findDerivedFrom(propDeps, pn)) {
79.849 - change = functionDeps.get(dpn);
79.850 - if (change == null) {
79.851 - change = new ArrayList<String>();
79.852 - functionDeps.put(dpn, change);
79.853 - }
79.854 - change.add(call.toString());
79.855 - }
79.856 - }
79.857 - }
79.858 - return true;
79.859 - }
79.860 -
79.861 - private boolean generateOperation(Element clazz,
79.862 - StringWriter body, String className,
79.863 - List<? extends Element> enclosedElements
79.864 - ) {
79.865 - for (Element m : enclosedElements) {
79.866 - if (m.getKind() != ElementKind.METHOD) {
79.867 - continue;
79.868 - }
79.869 - ExecutableElement e = (ExecutableElement)m;
79.870 - ModelOperation mO = e.getAnnotation(ModelOperation.class);
79.871 - if (mO == null) {
79.872 - continue;
79.873 - }
79.874 - if (!e.getModifiers().contains(Modifier.STATIC)) {
79.875 - error("@ModelOperation method needs to be static", e);
79.876 - return false;
79.877 - }
79.878 - if (e.getModifiers().contains(Modifier.PRIVATE)) {
79.879 - error("@ModelOperation method cannot be private", e);
79.880 - return false;
79.881 - }
79.882 - if (e.getReturnType().getKind() != TypeKind.VOID) {
79.883 - error("@ModelOperation method should return void", e);
79.884 - return false;
79.885 - }
79.886 - List<String> args = new ArrayList<String>();
79.887 - {
79.888 - body.append(" public void ").append(m.getSimpleName()).append("(");
79.889 - String sep = "";
79.890 - boolean checkFirst = true;
79.891 - for (VariableElement ve : e.getParameters()) {
79.892 - final TypeMirror type = ve.asType();
79.893 - CharSequence simpleName;
79.894 - if (type.getKind() == TypeKind.DECLARED) {
79.895 - simpleName = ((DeclaredType)type).asElement().getSimpleName();
79.896 - } else {
79.897 - simpleName = type.toString();
79.898 - }
79.899 - if (simpleName.toString().equals(className)) {
79.900 - checkFirst = false;
79.901 - } else {
79.902 - if (checkFirst) {
79.903 - error("First parameter of @ModelOperation method must be " + className, m);
79.904 - return false;
79.905 - }
79.906 - args.add(ve.getSimpleName().toString());
79.907 - body.append(sep).append("final ");
79.908 - body.append(ve.asType().toString()).append(" ");
79.909 - body.append(ve.toString());
79.910 - sep = ", ";
79.911 - }
79.912 - }
79.913 - body.append(") {\n");
79.914 - body.append(" org.apidesign.html.json.impl.JSON.runInBrowser(this.context, new Runnable() { public void run() {\n");
79.915 - body.append(" ").append(clazz.getSimpleName()).append(".").append(m.getSimpleName()).append("(");
79.916 - body.append(className).append(".this");
79.917 - for (String s : args) {
79.918 - body.append(", ").append(s);
79.919 - }
79.920 - body.append(");\n");
79.921 - body.append(" }});\n");
79.922 - body.append(" }\n");
79.923 - }
79.924 -
79.925 - }
79.926 - return true;
79.927 - }
79.928 -
79.929 -
79.930 - private boolean generateReceive(
79.931 - Element clazz, StringWriter body, String className,
79.932 - List<? extends Element> enclosedElements, List<String> functions
79.933 - ) {
79.934 - for (Element m : enclosedElements) {
79.935 - if (m.getKind() != ElementKind.METHOD) {
79.936 - continue;
79.937 - }
79.938 - ExecutableElement e = (ExecutableElement)m;
79.939 - OnReceive onR = e.getAnnotation(OnReceive.class);
79.940 - if (onR == null) {
79.941 - continue;
79.942 - }
79.943 - if (!e.getModifiers().contains(Modifier.STATIC)) {
79.944 - error("@OnReceive method needs to be static", e);
79.945 - return false;
79.946 - }
79.947 - if (e.getModifiers().contains(Modifier.PRIVATE)) {
79.948 - error("@OnReceive method cannot be private", e);
79.949 - return false;
79.950 - }
79.951 - if (e.getReturnType().getKind() != TypeKind.VOID) {
79.952 - error("@OnReceive method should return void", e);
79.953 - return false;
79.954 - }
79.955 - if (!onR.jsonp().isEmpty() && !"GET".equals(onR.method())) {
79.956 - error("JSONP works only with GET transport method", e);
79.957 - }
79.958 - String dataMirror = findDataSpecified(e, onR);
79.959 - if ("PUT".equals(onR.method()) && dataMirror == null) {
79.960 - error("PUT method needs to specify a data() class", e);
79.961 - return false;
79.962 - }
79.963 - if ("POST".equals(onR.method()) && dataMirror == null) {
79.964 - error("POST method needs to specify a data() class", e);
79.965 - return false;
79.966 - }
79.967 - String modelClass = null;
79.968 - boolean expectsList = false;
79.969 - List<String> args = new ArrayList<String>();
79.970 - {
79.971 - for (VariableElement ve : e.getParameters()) {
79.972 - TypeMirror modelType = null;
79.973 - final TypeMirror type = ve.asType();
79.974 - CharSequence simpleName;
79.975 - if (type.getKind() == TypeKind.DECLARED) {
79.976 - simpleName = ((DeclaredType)type).asElement().getSimpleName();
79.977 - } else {
79.978 - simpleName = type.toString();
79.979 - }
79.980 - if (simpleName.toString().equals(className)) {
79.981 - args.add(className + ".this");
79.982 - } else if (isModel(ve.asType())) {
79.983 - modelType = ve.asType();
79.984 - } else if (ve.asType().getKind() == TypeKind.ARRAY) {
79.985 - modelType = ((ArrayType)ve.asType()).getComponentType();
79.986 - expectsList = true;
79.987 - } else if (ve.asType().toString().equals("java.lang.String")) {
79.988 - modelType = ve.asType();
79.989 - }
79.990 - if (modelType != null) {
79.991 - if (modelClass != null) {
79.992 - error("There can be only one model class among arguments", e);
79.993 - } else {
79.994 - modelClass = modelType.toString();
79.995 - if (expectsList) {
79.996 - args.add("arr");
79.997 - } else {
79.998 - args.add("arr[0]");
79.999 - }
79.1000 - }
79.1001 - }
79.1002 - }
79.1003 - }
79.1004 - if (modelClass == null) {
79.1005 - error("The method needs to have one @Model class as parameter", e);
79.1006 - }
79.1007 - String n = e.getSimpleName().toString();
79.1008 - if ("WebSocket".equals(onR.method())) {
79.1009 - body.append(" /** Performs WebSocket communication. Call with <code>null</code> data parameter\n");
79.1010 - body.append(" * to open the connection (even if not required). Call with non-null data to\n");
79.1011 - body.append(" * send messages to server. Call again with <code>null</code> data to close the socket.\n");
79.1012 - body.append(" */\n");
79.1013 - }
79.1014 - body.append(" public void ").append(n).append("(");
79.1015 - StringBuilder urlBefore = new StringBuilder();
79.1016 - StringBuilder urlAfter = new StringBuilder();
79.1017 - String jsonpVarName = null;
79.1018 - {
79.1019 - String sep = "";
79.1020 - boolean skipJSONP = onR.jsonp().isEmpty();
79.1021 - for (String p : findParamNames(e, onR.url(), onR.jsonp(), urlBefore, urlAfter)) {
79.1022 - if (!skipJSONP && p.equals(onR.jsonp())) {
79.1023 - skipJSONP = true;
79.1024 - jsonpVarName = p;
79.1025 - continue;
79.1026 - }
79.1027 - body.append(sep);
79.1028 - body.append("String ").append(p);
79.1029 - sep = ", ";
79.1030 - }
79.1031 - if (!skipJSONP) {
79.1032 - error(
79.1033 - "Name of jsonp attribute ('" + onR.jsonp() +
79.1034 - "') is not used in url attribute '" + onR.url() + "'", e
79.1035 - );
79.1036 - }
79.1037 - if (dataMirror != null) {
79.1038 - body.append(sep).append(dataMirror.toString()).append(" data");
79.1039 - }
79.1040 - }
79.1041 - body.append(") {\n");
79.1042 - boolean webSocket = onR.method().equals("WebSocket");
79.1043 - if (webSocket) {
79.1044 - if (generateWSReceiveBody(body, onR, e, clazz, className, expectsList, modelClass, n, args, urlBefore, jsonpVarName, urlAfter, dataMirror)) {
79.1045 - return false;
79.1046 - }
79.1047 - body.append(" }\n");
79.1048 - body.append(" private org.apidesign.html.json.impl.JSON.WS ws_" + e.getSimpleName() + ";\n");
79.1049 - } else {
79.1050 - if (generateJSONReceiveBody(body, onR, e, clazz, className, expectsList, modelClass, n, args, urlBefore, jsonpVarName, urlAfter, dataMirror)) {
79.1051 - return false;
79.1052 - }
79.1053 - body.append(" }\n");
79.1054 - }
79.1055 - }
79.1056 - return true;
79.1057 - }
79.1058 -
79.1059 - private boolean generateJSONReceiveBody(StringWriter body, OnReceive onR, ExecutableElement e, Element clazz, String className, boolean expectsList, String modelClass, String n, List<String> args, StringBuilder urlBefore, String jsonpVarName, StringBuilder urlAfter, String dataMirror) {
79.1060 - body.append(
79.1061 - " class ProcessResult extends org.apidesign.html.json.impl.RcvrJSON {\n" +
79.1062 - " @Override\n" +
79.1063 - " public void onError(org.apidesign.html.json.impl.RcvrJSON.MsgEvnt ev) {\n" +
79.1064 - " Exception value = ev.getException();\n"
79.1065 - );
79.1066 - if (onR.onError().isEmpty()) {
79.1067 - body.append(
79.1068 - " value.printStackTrace();\n"
79.1069 - );
79.1070 - } else {
79.1071 - if (!findOnError(e, ((TypeElement)clazz), onR.onError(), className)) {
79.1072 - return true;
79.1073 - }
79.1074 - body.append(" ").append(clazz.getSimpleName()).append(".").append(onR.onError()).append("(");
79.1075 - body.append(className).append(".this, value);\n");
79.1076 - }
79.1077 - body.append(
79.1078 - " }\n" +
79.1079 - " @Override\n" +
79.1080 - " public void onMessage(org.apidesign.html.json.impl.RcvrJSON.MsgEvnt ev) {\n"
79.1081 - );
79.1082 - if (expectsList) {
79.1083 - body.append(
79.1084 - " " + modelClass + "[] arr = new " + modelClass + "[ev.dataSize()];\n"
79.1085 - );
79.1086 - } else {
79.1087 - body.append(
79.1088 - " " + modelClass + "[] arr = { null };\n"
79.1089 - );
79.1090 - }
79.1091 - body.append(
79.1092 - " ev.dataRead(context, " + modelClass + ".class, arr);\n"
79.1093 - );
79.1094 - {
79.1095 - body.append(" ").append(clazz.getSimpleName()).append(".").append(n).append("(");
79.1096 - String sep = "";
79.1097 - for (String arg : args) {
79.1098 - body.append(sep);
79.1099 - body.append(arg);
79.1100 - sep = ", ";
79.1101 - }
79.1102 - body.append(");\n");
79.1103 - }
79.1104 - body.append(
79.1105 - " }\n" +
79.1106 - " }\n"
79.1107 - );
79.1108 - body.append(" ProcessResult pr = new ProcessResult();\n");
79.1109 - body.append(" org.apidesign.html.json.impl.JSON.loadJSON(context, pr,\n ");
79.1110 - body.append(urlBefore).append(", ");
79.1111 - if (jsonpVarName != null) {
79.1112 - body.append(urlAfter);
79.1113 - } else {
79.1114 - body.append("null");
79.1115 - }
79.1116 - if (!"GET".equals(onR.method()) || dataMirror != null) {
79.1117 - body.append(", \"").append(onR.method()).append('"');
79.1118 - if (dataMirror != null) {
79.1119 - body.append(", data");
79.1120 - } else {
79.1121 - body.append(", null");
79.1122 - }
79.1123 - } else {
79.1124 - body.append(", null, null");
79.1125 - }
79.1126 - body.append(");\n");
79.1127 - return false;
79.1128 - }
79.1129 -
79.1130 - private boolean generateWSReceiveBody(StringWriter body, OnReceive onR, ExecutableElement e, Element clazz, String className, boolean expectsList, String modelClass, String n, List<String> args, StringBuilder urlBefore, String jsonpVarName, StringBuilder urlAfter, String dataMirror) {
79.1131 - body.append(
79.1132 - " class ProcessResult extends org.apidesign.html.json.impl.RcvrJSON {\n" +
79.1133 - " @Override\n" +
79.1134 - " public void onOpen(org.apidesign.html.json.impl.RcvrJSON.MsgEvnt ev) {\n"
79.1135 - );
79.1136 - body.append(" ").append(clazz.getSimpleName()).append(".").append(n).append("(");
79.1137 - {
79.1138 - String sep = "";
79.1139 - for (String arg : args) {
79.1140 - body.append(sep);
79.1141 - if (arg.startsWith("arr")) {
79.1142 - body.append("null");
79.1143 - } else {
79.1144 - body.append(arg);
79.1145 - }
79.1146 - sep = ", ";
79.1147 - }
79.1148 - }
79.1149 - body.append(");\n");
79.1150 - body.append(
79.1151 - " }\n" +
79.1152 - " @Override\n" +
79.1153 - " public void onError(org.apidesign.html.json.impl.RcvrJSON.MsgEvnt ev) {\n" +
79.1154 - " Exception value = ev.getException();\n"
79.1155 - );
79.1156 - if (onR.onError().isEmpty()) {
79.1157 - body.append(
79.1158 - " value.printStackTrace();\n"
79.1159 - );
79.1160 - } else {
79.1161 - if (!findOnError(e, ((TypeElement)clazz), onR.onError(), className)) {
79.1162 - return true;
79.1163 - }
79.1164 - body.append(" ").append(clazz.getSimpleName()).append(".").append(onR.onError()).append("(");
79.1165 - body.append(className).append(".this, value);\n");
79.1166 - }
79.1167 - body.append(
79.1168 - " }\n" +
79.1169 - " @Override\n" +
79.1170 - " public void onMessage(org.apidesign.html.json.impl.RcvrJSON.MsgEvnt ev) {\n"
79.1171 - );
79.1172 - if (expectsList) {
79.1173 - body.append(
79.1174 - " " + modelClass + "[] arr = new " + modelClass + "[ev.dataSize()];\n"
79.1175 - );
79.1176 - } else {
79.1177 - body.append(
79.1178 - " " + modelClass + "[] arr = { null };\n"
79.1179 - );
79.1180 - }
79.1181 - body.append(
79.1182 - " ev.dataRead(context, " + modelClass + ".class, arr);\n"
79.1183 - );
79.1184 - {
79.1185 - body.append(" ").append(clazz.getSimpleName()).append(".").append(n).append("(");
79.1186 - String sep = "";
79.1187 - for (String arg : args) {
79.1188 - body.append(sep);
79.1189 - body.append(arg);
79.1190 - sep = ", ";
79.1191 - }
79.1192 - body.append(");\n");
79.1193 - }
79.1194 - body.append(
79.1195 - " }\n"
79.1196 - );
79.1197 - if (!onR.onError().isEmpty()) {
79.1198 - body.append(
79.1199 - " @Override\n"
79.1200 - + " public void onClose(org.apidesign.html.json.impl.RcvrJSON.MsgEvnt ev) {\n"
79.1201 - );
79.1202 - body.append(" ").append(clazz.getSimpleName()).append(".").append(onR.onError()).append("(");
79.1203 - body.append(className).append(".this, null);\n");
79.1204 - body.append(
79.1205 - " }\n"
79.1206 - );
79.1207 - }
79.1208 - body.append(" }\n");
79.1209 - body.append(" if (this.ws_").append(e.getSimpleName()).append(" == null) {\n");
79.1210 - body.append(" ProcessResult pr = new ProcessResult();\n");
79.1211 - body.append(" this.ws_").append(e.getSimpleName());
79.1212 - body.append("= org.apidesign.html.json.impl.JSON.openWS(context, pr,\n ");
79.1213 - body.append(urlBefore).append(", data);\n");
79.1214 - body.append(" } else {\n");
79.1215 - body.append(" this.ws_").append(e.getSimpleName()).append(".send(context, ").append(urlBefore).append(", data);\n");
79.1216 - body.append(" }\n");
79.1217 - return false;
79.1218 - }
79.1219 -
79.1220 - private CharSequence wrapParams(
79.1221 - ExecutableElement ee, String id, String className, String evName, String dataName
79.1222 - ) {
79.1223 - TypeMirror stringType = processingEnv.getElementUtils().getTypeElement("java.lang.String").asType();
79.1224 - StringBuilder params = new StringBuilder();
79.1225 - boolean first = true;
79.1226 - for (VariableElement ve : ee.getParameters()) {
79.1227 - if (!first) {
79.1228 - params.append(", ");
79.1229 - }
79.1230 - first = false;
79.1231 - String toCall = null;
79.1232 - String toFinish = null;
79.1233 - if (ve.asType() == stringType) {
79.1234 - if (ve.getSimpleName().contentEquals("id")) {
79.1235 - params.append('"').append(id).append('"');
79.1236 - continue;
79.1237 - }
79.1238 - toCall = "org.apidesign.html.json.impl.JSON.toString(context, ";
79.1239 - }
79.1240 - if (ve.asType().getKind() == TypeKind.DOUBLE) {
79.1241 - toCall = "org.apidesign.html.json.impl.JSON.toNumber(context, ";
79.1242 - toFinish = ".doubleValue()";
79.1243 - }
79.1244 - if (ve.asType().getKind() == TypeKind.INT) {
79.1245 - toCall = "org.apidesign.html.json.impl.JSON.toNumber(context, ";
79.1246 - toFinish = ".intValue()";
79.1247 - }
79.1248 - if (dataName != null && ve.getSimpleName().contentEquals(dataName) && isModel(ve.asType())) {
79.1249 - toCall = "org.apidesign.html.json.impl.JSON.toModel(context, " + ve.asType() + ".class, ";
79.1250 - }
79.1251 -
79.1252 - if (toCall != null) {
79.1253 - params.append(toCall);
79.1254 - if (dataName != null && ve.getSimpleName().contentEquals(dataName)) {
79.1255 - params.append(dataName);
79.1256 - params.append(", null");
79.1257 - } else {
79.1258 - if (evName == null) {
79.1259 - final StringBuilder sb = new StringBuilder();
79.1260 - sb.append("Unexpected string parameter name.");
79.1261 - if (dataName != null) {
79.1262 - sb.append(" Try \"").append(dataName).append("\"");
79.1263 - }
79.1264 - error(sb.toString(), ee);
79.1265 - }
79.1266 - params.append(evName);
79.1267 - params.append(", \"");
79.1268 - params.append(ve.getSimpleName().toString());
79.1269 - params.append("\"");
79.1270 - }
79.1271 - params.append(")");
79.1272 - if (toFinish != null) {
79.1273 - params.append(toFinish);
79.1274 - }
79.1275 - continue;
79.1276 - }
79.1277 - String rn = fqn(ve.asType(), ee);
79.1278 - int last = rn.lastIndexOf('.');
79.1279 - if (last >= 0) {
79.1280 - rn = rn.substring(last + 1);
79.1281 - }
79.1282 - if (rn.equals(className)) {
79.1283 - params.append(className).append(".this");
79.1284 - continue;
79.1285 - }
79.1286 - error(
79.1287 - "The annotated method can only accept " + className + " argument or argument named 'data'",
79.1288 - ee
79.1289 - );
79.1290 - }
79.1291 - return params;
79.1292 - }
79.1293 -
79.1294 -
79.1295 - private CharSequence wrapPropName(
79.1296 - ExecutableElement ee, String className, String propName, String propValue
79.1297 - ) {
79.1298 - TypeMirror stringType = processingEnv.getElementUtils().getTypeElement("java.lang.String").asType();
79.1299 - StringBuilder params = new StringBuilder();
79.1300 - boolean first = true;
79.1301 - for (VariableElement ve : ee.getParameters()) {
79.1302 - if (!first) {
79.1303 - params.append(", ");
79.1304 - }
79.1305 - first = false;
79.1306 - if (ve.asType() == stringType) {
79.1307 - if (propName != null && ve.getSimpleName().contentEquals(propName)) {
79.1308 - params.append('"').append(propValue).append('"');
79.1309 - } else {
79.1310 - error("Unexpected string parameter name. Try \"" + propName + "\".", ee);
79.1311 - }
79.1312 - continue;
79.1313 - }
79.1314 - String rn = fqn(ve.asType(), ee);
79.1315 - int last = rn.lastIndexOf('.');
79.1316 - if (last >= 0) {
79.1317 - rn = rn.substring(last + 1);
79.1318 - }
79.1319 - if (rn.equals(className)) {
79.1320 - params.append(className).append(".this");
79.1321 - continue;
79.1322 - }
79.1323 - error(
79.1324 - "@OnPrprtChange method can only accept String or " + className + " arguments",
79.1325 - ee);
79.1326 - }
79.1327 - return params;
79.1328 - }
79.1329 -
79.1330 - private boolean isModel(TypeMirror tm) {
79.1331 - if (tm.getKind() == TypeKind.ERROR) {
79.1332 - return true;
79.1333 - }
79.1334 - final Element e = processingEnv.getTypeUtils().asElement(tm);
79.1335 - if (e == null) {
79.1336 - return false;
79.1337 - }
79.1338 - for (Element ch : e.getEnclosedElements()) {
79.1339 - if (ch.getKind() == ElementKind.METHOD) {
79.1340 - ExecutableElement ee = (ExecutableElement)ch;
79.1341 - if (ee.getParameters().isEmpty() && ee.getSimpleName().contentEquals("modelFor")) {
79.1342 - return true;
79.1343 - }
79.1344 - }
79.1345 - }
79.1346 - return models.values().contains(e.getSimpleName().toString());
79.1347 - }
79.1348 -
79.1349 - private void writeToString(Prprt[] props, Writer w) throws IOException {
79.1350 - w.write(" public String toString() {\n");
79.1351 - w.write(" StringBuilder sb = new StringBuilder();\n");
79.1352 - w.write(" sb.append('{');\n");
79.1353 - String sep = "";
79.1354 - for (Prprt p : props) {
79.1355 - w.write(sep);
79.1356 - w.append(" sb.append('\"').append(\"" + p.name() + "\")");
79.1357 - w.append(".append('\"').append(\":\");\n");
79.1358 - w.append(" sb.append(org.apidesign.html.json.impl.JSON.toJSON(prop_");
79.1359 - w.append(p.name()).append("));\n");
79.1360 - sep = " sb.append(',');\n";
79.1361 - }
79.1362 - w.write(" sb.append('}');\n");
79.1363 - w.write(" return sb.toString();\n");
79.1364 - w.write(" }\n");
79.1365 - }
79.1366 - private void writeClone(String className, Prprt[] props, Writer w) throws IOException {
79.1367 - w.write(" public " + className + " clone() {\n");
79.1368 - w.write(" return clone(context);\n");
79.1369 - w.write(" }\n");
79.1370 - w.write(" private " + className + " clone(net.java.html.BrwsrCtx ctx) {\n");
79.1371 - w.write(" " + className + " ret = new " + className + "(ctx);\n");
79.1372 - for (Prprt p : props) {
79.1373 - if (!p.array()) {
79.1374 - boolean isModel[] = { false };
79.1375 - boolean isEnum[] = { false };
79.1376 - boolean isPrimitive[] = { false };
79.1377 - checkType(p, isModel, isEnum, isPrimitive);
79.1378 - if (!isModel[0]) {
79.1379 - w.write(" ret.prop_" + p.name() + " = prop_" + p.name() + ";\n");
79.1380 - continue;
79.1381 - }
79.1382 - w.write(" ret.prop_" + p.name() + " = prop_" + p.name() + " == null ? null : prop_" + p.name() + ".clone();\n");
79.1383 - } else {
79.1384 - w.write(" ret.prop_" + p.name() + ".cloneAll(ctx, prop_" + p.name() + ");\n");
79.1385 - }
79.1386 - }
79.1387 -
79.1388 - w.write(" return ret;\n");
79.1389 - w.write(" }\n");
79.1390 - }
79.1391 -
79.1392 - private String inPckName(Element e) {
79.1393 - StringBuilder sb = new StringBuilder();
79.1394 - while (e.getKind() != ElementKind.PACKAGE) {
79.1395 - if (sb.length() == 0) {
79.1396 - sb.append(e.getSimpleName());
79.1397 - } else {
79.1398 - sb.insert(0, '.');
79.1399 - sb.insert(0, e.getSimpleName());
79.1400 - }
79.1401 - e = e.getEnclosingElement();
79.1402 - }
79.1403 - return sb.toString();
79.1404 - }
79.1405 -
79.1406 - private String fqn(TypeMirror pt, Element relative) {
79.1407 - if (pt.getKind() == TypeKind.ERROR) {
79.1408 - final Elements eu = processingEnv.getElementUtils();
79.1409 - PackageElement pckg = eu.getPackageOf(relative);
79.1410 - return pckg.getQualifiedName() + "." + pt.toString();
79.1411 - }
79.1412 - return pt.toString();
79.1413 - }
79.1414 -
79.1415 - private String checkType(Prprt p, boolean[] isModel, boolean[] isEnum, boolean[] isPrimitive) {
79.1416 - TypeMirror tm;
79.1417 - try {
79.1418 - String ret = p.typeName(processingEnv);
79.1419 - TypeElement e = processingEnv.getElementUtils().getTypeElement(ret);
79.1420 - if (e == null) {
79.1421 - isModel[0] = true;
79.1422 - isEnum[0] = false;
79.1423 - isPrimitive[0] = false;
79.1424 - return ret;
79.1425 - }
79.1426 - tm = e.asType();
79.1427 - } catch (MirroredTypeException ex) {
79.1428 - tm = ex.getTypeMirror();
79.1429 - }
79.1430 - tm = processingEnv.getTypeUtils().erasure(tm);
79.1431 - if (isPrimitive[0] = tm.getKind().isPrimitive()) {
79.1432 - isEnum[0] = false;
79.1433 - isModel[0] = false;
79.1434 - return tm.toString();
79.1435 - }
79.1436 - final Element e = processingEnv.getTypeUtils().asElement(tm);
79.1437 - if (e.getKind() == ElementKind.CLASS && tm.getKind() == TypeKind.ERROR) {
79.1438 - isModel[0] = true;
79.1439 - isEnum[0] = false;
79.1440 - return e.getSimpleName().toString();
79.1441 - }
79.1442 -
79.1443 - final Model m = e == null ? null : e.getAnnotation(Model.class);
79.1444 - String ret;
79.1445 - if (m != null) {
79.1446 - ret = findPkgName(e) + '.' + m.className();
79.1447 - isModel[0] = true;
79.1448 - models.put(e, m.className());
79.1449 - } else if (findModelForMthd(e)) {
79.1450 - ret = ((TypeElement)e).getQualifiedName().toString();
79.1451 - isModel[0] = true;
79.1452 - } else {
79.1453 - ret = tm.toString();
79.1454 - }
79.1455 - TypeMirror enm = processingEnv.getElementUtils().getTypeElement("java.lang.Enum").asType();
79.1456 - enm = processingEnv.getTypeUtils().erasure(enm);
79.1457 - isEnum[0] = processingEnv.getTypeUtils().isSubtype(tm, enm);
79.1458 - return ret;
79.1459 - }
79.1460 -
79.1461 - private static boolean findModelForMthd(Element clazz) {
79.1462 - if (clazz == null) {
79.1463 - return false;
79.1464 - }
79.1465 - for (Element e : clazz.getEnclosedElements()) {
79.1466 - if (e.getKind() == ElementKind.METHOD) {
79.1467 - ExecutableElement ee = (ExecutableElement)e;
79.1468 - if (
79.1469 - ee.getSimpleName().contentEquals("modelFor") &&
79.1470 - ee.getParameters().isEmpty()
79.1471 - ) {
79.1472 - return true;
79.1473 - }
79.1474 - }
79.1475 - }
79.1476 - return false;
79.1477 - }
79.1478 -
79.1479 - private Iterable<String> findParamNames(
79.1480 - Element e, String url, String jsonParam, StringBuilder... both
79.1481 - ) {
79.1482 - List<String> params = new ArrayList<String>();
79.1483 - int wasJSON = 0;
79.1484 -
79.1485 - for (int pos = 0; ;) {
79.1486 - int next = url.indexOf('{', pos);
79.1487 - if (next == -1) {
79.1488 - both[wasJSON].append('"')
79.1489 - .append(url.substring(pos))
79.1490 - .append('"');
79.1491 - return params;
79.1492 - }
79.1493 - int close = url.indexOf('}', next);
79.1494 - if (close == -1) {
79.1495 - error("Unbalanced '{' and '}' in " + url, e);
79.1496 - return params;
79.1497 - }
79.1498 - final String paramName = url.substring(next + 1, close);
79.1499 - params.add(paramName);
79.1500 - if (paramName.equals(jsonParam) && !jsonParam.isEmpty()) {
79.1501 - both[wasJSON].append('"')
79.1502 - .append(url.substring(pos, next))
79.1503 - .append('"');
79.1504 - wasJSON = 1;
79.1505 - } else {
79.1506 - both[wasJSON].append('"')
79.1507 - .append(url.substring(pos, next))
79.1508 - .append("\" + ").append(paramName).append(" + ");
79.1509 - }
79.1510 - pos = close + 1;
79.1511 - }
79.1512 - }
79.1513 -
79.1514 - private static Prprt findPrprt(Prprt[] properties, String propName) {
79.1515 - for (Prprt p : properties) {
79.1516 - if (propName.equals(p.name())) {
79.1517 - return p;
79.1518 - }
79.1519 - }
79.1520 - return null;
79.1521 - }
79.1522 -
79.1523 - private boolean isPrimitive(String type) {
79.1524 - return
79.1525 - "int".equals(type) ||
79.1526 - "double".equals(type) ||
79.1527 - "long".equals(type) ||
79.1528 - "short".equals(type) ||
79.1529 - "byte".equals(type) ||
79.1530 - "char".equals(type) ||
79.1531 - "boolean".equals(type) ||
79.1532 - "float".equals(type);
79.1533 - }
79.1534 -
79.1535 - private static Collection<String> findDerivedFrom(Map<String, Collection<String>> propsDeps, String derivedProp) {
79.1536 - Set<String> names = new HashSet<String>();
79.1537 - for (Map.Entry<String, Collection<String>> e : propsDeps.entrySet()) {
79.1538 - if (e.getValue().contains(derivedProp)) {
79.1539 - names.add(e.getKey());
79.1540 - }
79.1541 - }
79.1542 - return names;
79.1543 - }
79.1544 -
79.1545 - private Prprt[] createProps(Element e, Property[] arr) {
79.1546 - Prprt[] ret = Prprt.wrap(processingEnv, e, arr);
79.1547 - Prprt[] prev = verify.put(e, ret);
79.1548 - if (prev != null) {
79.1549 - error("Two sets of properties for ", e);
79.1550 - }
79.1551 - return ret;
79.1552 - }
79.1553 -
79.1554 - private static String strip(String s) {
79.1555 - int indx = s.indexOf("__");
79.1556 - if (indx >= 0) {
79.1557 - return s.substring(0, indx);
79.1558 - } else {
79.1559 - return s;
79.1560 - }
79.1561 - }
79.1562 -
79.1563 - private String findDataSpecified(ExecutableElement e, OnReceive onR) {
79.1564 - try {
79.1565 - return onR.data().getName();
79.1566 - } catch (MirroredTypeException ex) {
79.1567 - final TypeMirror tm = ex.getTypeMirror();
79.1568 - String name;
79.1569 - final Element te = processingEnv.getTypeUtils().asElement(tm);
79.1570 - if (te.getKind() == ElementKind.CLASS && tm.getKind() == TypeKind.ERROR) {
79.1571 - name = te.getSimpleName().toString();
79.1572 - } else {
79.1573 - name = tm.toString();
79.1574 - }
79.1575 - return "java.lang.Object".equals(name) ? null : name;
79.1576 - } catch (Exception ex) {
79.1577 - // fallback
79.1578 - }
79.1579 -
79.1580 - AnnotationMirror found = null;
79.1581 - for (AnnotationMirror am : e.getAnnotationMirrors()) {
79.1582 - if (am.getAnnotationType().toString().equals(OnReceive.class.getName())) {
79.1583 - found = am;
79.1584 - }
79.1585 - }
79.1586 - if (found == null) {
79.1587 - return null;
79.1588 - }
79.1589 -
79.1590 - for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : found.getElementValues().entrySet()) {
79.1591 - ExecutableElement ee = entry.getKey();
79.1592 - AnnotationValue av = entry.getValue();
79.1593 - if (ee.getSimpleName().contentEquals("data")) {
79.1594 - List<? extends Object> values = getAnnoValues(processingEnv, e, found);
79.1595 - for (Object v : values) {
79.1596 - String sv = v.toString();
79.1597 - if (sv.startsWith("data = ") && sv.endsWith(".class")) {
79.1598 - return sv.substring(7, sv.length() - 6);
79.1599 - }
79.1600 - }
79.1601 - return "error";
79.1602 - }
79.1603 - }
79.1604 - return null;
79.1605 - }
79.1606 -
79.1607 - static List<? extends Object> getAnnoValues(ProcessingEnvironment pe, Element e, AnnotationMirror am) {
79.1608 - try {
79.1609 - Class<?> trees = Class.forName("com.sun.tools.javac.api.JavacTrees");
79.1610 - Method m = trees.getMethod("instance", ProcessingEnvironment.class);
79.1611 - Object instance = m.invoke(null, pe);
79.1612 - m = instance.getClass().getMethod("getPath", Element.class, AnnotationMirror.class);
79.1613 - Object path = m.invoke(instance, e, am);
79.1614 - m = path.getClass().getMethod("getLeaf");
79.1615 - Object leaf = m.invoke(path);
79.1616 - m = leaf.getClass().getMethod("getArguments");
79.1617 - return (List) m.invoke(leaf);
79.1618 - } catch (Exception ex) {
79.1619 - return Collections.emptyList();
79.1620 - }
79.1621 - }
79.1622 -
79.1623 - private static class Prprt {
79.1624 - private final Element e;
79.1625 - private final AnnotationMirror tm;
79.1626 - private final Property p;
79.1627 -
79.1628 - public Prprt(Element e, AnnotationMirror tm, Property p) {
79.1629 - this.e = e;
79.1630 - this.tm = tm;
79.1631 - this.p = p;
79.1632 - }
79.1633 -
79.1634 - String name() {
79.1635 - return p.name();
79.1636 - }
79.1637 -
79.1638 - boolean array() {
79.1639 - return p.array();
79.1640 - }
79.1641 -
79.1642 - String typeName(ProcessingEnvironment env) {
79.1643 - RuntimeException ex;
79.1644 - try {
79.1645 - return p.type().getName();
79.1646 - } catch (IncompleteAnnotationException e) {
79.1647 - ex = e;
79.1648 - } catch (AnnotationTypeMismatchException e) {
79.1649 - ex = e;
79.1650 - }
79.1651 - for (Object v : getAnnoValues(env, e, tm)) {
79.1652 - String s = v.toString().replace(" ", "");
79.1653 - if (s.startsWith("type=") && s.endsWith(".class")) {
79.1654 - return s.substring(5, s.length() - 6);
79.1655 - }
79.1656 - }
79.1657 - throw ex;
79.1658 - }
79.1659 -
79.1660 -
79.1661 - static Prprt[] wrap(ProcessingEnvironment pe, Element e, Property[] arr) {
79.1662 - if (arr.length == 0) {
79.1663 - return new Prprt[0];
79.1664 - }
79.1665 -
79.1666 - if (e.getKind() != ElementKind.CLASS) {
79.1667 - throw new IllegalStateException("" + e.getKind());
79.1668 - }
79.1669 - TypeElement te = (TypeElement)e;
79.1670 - List<? extends AnnotationValue> val = null;
79.1671 - for (AnnotationMirror an : te.getAnnotationMirrors()) {
79.1672 - for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : an.getElementValues().entrySet()) {
79.1673 - if (entry.getKey().getSimpleName().contentEquals("properties")) {
79.1674 - val = (List)entry.getValue().getValue();
79.1675 - break;
79.1676 - }
79.1677 - }
79.1678 - }
79.1679 - if (val == null || val.size() != arr.length) {
79.1680 - pe.getMessager().printMessage(Diagnostic.Kind.ERROR, "" + val, e);
79.1681 - return new Prprt[0];
79.1682 - }
79.1683 - Prprt[] ret = new Prprt[arr.length];
79.1684 - BIG: for (int i = 0; i < ret.length; i++) {
79.1685 - AnnotationMirror am = (AnnotationMirror)val.get(i).getValue();
79.1686 - ret[i] = new Prprt(e, am, arr[i]);
79.1687 -
79.1688 - }
79.1689 - return ret;
79.1690 - }
79.1691 - }
79.1692 -
79.1693 - @Override
79.1694 - public Iterable<? extends Completion> getCompletions(Element element, AnnotationMirror annotation, ExecutableElement member, String userText) {
79.1695 - final Level l = Level.FINE;
79.1696 - LOG.log(l, " element: {0}", element);
79.1697 - LOG.log(l, " annotation: {0}", annotation);
79.1698 - LOG.log(l, " member: {0}", member);
79.1699 - LOG.log(l, " userText: {0}", userText);
79.1700 - LOG.log(l, "str: {0}", annotation.getAnnotationType().toString());
79.1701 - if (annotation.getAnnotationType().toString().equals(OnReceive.class.getName())) {
79.1702 - if (member.getSimpleName().contentEquals("method")) {
79.1703 - return Arrays.asList(
79.1704 - methodOf("GET"),
79.1705 - methodOf("POST"),
79.1706 - methodOf("PUT"),
79.1707 - methodOf("DELETE"),
79.1708 - methodOf("HEAD"),
79.1709 - methodOf("WebSocket")
79.1710 - );
79.1711 - }
79.1712 - }
79.1713 -
79.1714 - return super.getCompletions(element, annotation, member, userText);
79.1715 - }
79.1716 -
79.1717 - private static final Completion methodOf(String method) {
79.1718 - ResourceBundle rb = ResourceBundle.getBundle("org.apidesign.html.json.impl.Bundle");
79.1719 - return Completions.of('"' + method + '"', rb.getString("MSG_Completion_" + method));
79.1720 - }
79.1721 -
79.1722 - private boolean findOnError(ExecutableElement errElem, TypeElement te, String name, String className) {
79.1723 - String err = null;
79.1724 - METHODS:
79.1725 - for (Element e : te.getEnclosedElements()) {
79.1726 - if (e.getKind() != ElementKind.METHOD) {
79.1727 - continue;
79.1728 - }
79.1729 - if (!e.getSimpleName().contentEquals(name)) {
79.1730 - continue;
79.1731 - }
79.1732 - if (!e.getModifiers().contains(Modifier.STATIC)) {
79.1733 - errElem = (ExecutableElement) e;
79.1734 - err = "Would have to be static";
79.1735 - continue;
79.1736 - }
79.1737 - ExecutableElement ee = (ExecutableElement) e;
79.1738 - TypeMirror excType = processingEnv.getElementUtils().getTypeElement(Exception.class.getName()).asType();
79.1739 - final List<? extends VariableElement> params = ee.getParameters();
79.1740 - boolean error = false;
79.1741 - if (params.size() != 2) {
79.1742 - error = true;
79.1743 - } else {
79.1744 - String firstType = params.get(0).asType().toString();
79.1745 - int lastDot = firstType.lastIndexOf('.');
79.1746 - if (lastDot != -1) {
79.1747 - firstType = firstType.substring(lastDot + 1);
79.1748 - }
79.1749 - if (!firstType.equals(className)) {
79.1750 - error = true;
79.1751 - }
79.1752 - if (!processingEnv.getTypeUtils().isAssignable(excType, params.get(1).asType())) {
79.1753 - error = true;
79.1754 - }
79.1755 - }
79.1756 - if (error) {
79.1757 - errElem = (ExecutableElement) e;
79.1758 - err = "Error method first argument needs to be " + className + " and second Exception";
79.1759 - continue;
79.1760 - }
79.1761 - return true;
79.1762 - }
79.1763 - if (err == null) {
79.1764 - err = "Cannot find " + name + "(" + className + ", Exception) method in this class";
79.1765 - }
79.1766 - error(err, errElem);
79.1767 - return false;
79.1768 - }
79.1769 -
79.1770 -}
80.1 --- a/json/src/main/java/org/apidesign/html/json/impl/PropertyBindingAccessor.java Mon Dec 16 15:48:09 2013 +0100
80.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
80.3 @@ -1,135 +0,0 @@
80.4 -/**
80.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
80.6 - *
80.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
80.8 - *
80.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
80.10 - * Other names may be trademarks of their respective owners.
80.11 - *
80.12 - * The contents of this file are subject to the terms of either the GNU
80.13 - * General Public License Version 2 only ("GPL") or the Common
80.14 - * Development and Distribution License("CDDL") (collectively, the
80.15 - * "License"). You may not use this file except in compliance with the
80.16 - * License. You can obtain a copy of the License at
80.17 - * http://www.netbeans.org/cddl-gplv2.html
80.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
80.19 - * specific language governing permissions and limitations under the
80.20 - * License. When distributing the software, include this License Header
80.21 - * Notice in each file and include the License file at
80.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
80.23 - * particular file as subject to the "Classpath" exception as provided
80.24 - * by Oracle in the GPL Version 2 section of the License file that
80.25 - * accompanied this code. If applicable, add the following below the
80.26 - * License Header, with the fields enclosed by brackets [] replaced by
80.27 - * your own identifying information:
80.28 - * "Portions Copyrighted [year] [name of copyright owner]"
80.29 - *
80.30 - * Contributor(s):
80.31 - *
80.32 - * The Original Software is NetBeans. The Initial Developer of the Original
80.33 - * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
80.34 - *
80.35 - * If you wish your version of this file to be governed by only the CDDL
80.36 - * or only the GPL Version 2, indicate your decision by adding
80.37 - * "[Contributor] elects to include this software in this distribution
80.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
80.39 - * single choice of license, a recipient has the option to distribute
80.40 - * your version of this file under either the CDDL, the GPL Version 2 or
80.41 - * to extend the choice of license to its licensees as provided above.
80.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
80.43 - * Version 2 license, then the option applies only if the new code is
80.44 - * made subject to such option by the copyright holder.
80.45 - */
80.46 -package org.apidesign.html.json.impl;
80.47 -
80.48 -import net.java.html.BrwsrCtx;
80.49 -import org.apidesign.html.json.spi.FunctionBinding;
80.50 -import org.apidesign.html.json.spi.JSONCall;
80.51 -import org.apidesign.html.json.spi.PropertyBinding;
80.52 -
80.53 -/**
80.54 - *
80.55 - * @author Jaroslav Tulach <jtulach@netbeans.org>
80.56 - */
80.57 -public abstract class PropertyBindingAccessor {
80.58 - private static PropertyBindingAccessor DEFAULT;
80.59 -
80.60 - protected PropertyBindingAccessor() {
80.61 - if (DEFAULT != null) throw new IllegalStateException();
80.62 - DEFAULT = this;
80.63 - }
80.64 -
80.65 - static {
80.66 - JSON.initClass(PropertyBinding.class);
80.67 - }
80.68 -
80.69 - protected abstract <M> PropertyBinding newBinding(PBData<M> d);
80.70 - protected abstract <M> FunctionBinding newFunction(FBData<M> d);
80.71 - protected abstract JSONCall newCall(
80.72 - BrwsrCtx ctx, RcvrJSON callback, String urlBefore, String urlAfter,
80.73 - String method, Object data
80.74 - );
80.75 -
80.76 -
80.77 - static <M> PropertyBinding create(PBData<M> d) {
80.78 - return DEFAULT.newBinding(d);
80.79 - }
80.80 - static <M> FunctionBinding createFunction(FBData<M> d) {
80.81 - return DEFAULT.newFunction(d);
80.82 - }
80.83 - static JSONCall createCall(
80.84 - BrwsrCtx ctx, RcvrJSON callback, String urlBefore, String urlAfter,
80.85 - String method, Object data
80.86 - ) {
80.87 - return DEFAULT.newCall(ctx, callback, urlBefore, urlAfter, method, data);
80.88 - }
80.89 -
80.90 - public static final class PBData<M> {
80.91 - public final String name;
80.92 - public final boolean readOnly;
80.93 - private final M model;
80.94 - private final SetAndGet<M> access;
80.95 - private final Bindings<?> bindings;
80.96 -
80.97 - public PBData(Bindings<?> bindings, String name, M model, SetAndGet<M> access, boolean readOnly) {
80.98 - this.bindings = bindings;
80.99 - this.name = name;
80.100 - this.model = model;
80.101 - this.access = access;
80.102 - this.readOnly = readOnly;
80.103 - }
80.104 -
80.105 - public void setValue(Object v) {
80.106 - access.setValue(model, v);
80.107 - }
80.108 -
80.109 - public Object getValue() {
80.110 - return access.getValue(model);
80.111 - }
80.112 -
80.113 - public boolean isReadOnly() {
80.114 - return readOnly;
80.115 - }
80.116 -
80.117 - public Bindings getBindings() {
80.118 - return bindings;
80.119 - }
80.120 - } // end of PBData
80.121 -
80.122 - public static final class FBData<M> {
80.123 - public final String name;
80.124 - private final M model;
80.125 - private final Callback<M> access;
80.126 -
80.127 - public FBData(String name, M model, Callback<M> access) {
80.128 - this.name = name;
80.129 - this.model = model;
80.130 - this.access = access;
80.131 - }
80.132 -
80.133 -
80.134 - public void call(Object data, Object ev) {
80.135 - access.call(model, data, ev);
80.136 - }
80.137 - } // end of FBData
80.138 -}
81.1 --- a/json/src/main/java/org/apidesign/html/json/impl/RcvrJSON.java Mon Dec 16 15:48:09 2013 +0100
81.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
81.3 @@ -1,149 +0,0 @@
81.4 -/**
81.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
81.6 - *
81.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
81.8 - *
81.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
81.10 - * Other names may be trademarks of their respective owners.
81.11 - *
81.12 - * The contents of this file are subject to the terms of either the GNU
81.13 - * General Public License Version 2 only ("GPL") or the Common
81.14 - * Development and Distribution License("CDDL") (collectively, the
81.15 - * "License"). You may not use this file except in compliance with the
81.16 - * License. You can obtain a copy of the License at
81.17 - * http://www.netbeans.org/cddl-gplv2.html
81.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
81.19 - * specific language governing permissions and limitations under the
81.20 - * License. When distributing the software, include this License Header
81.21 - * Notice in each file and include the License file at
81.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
81.23 - * particular file as subject to the "Classpath" exception as provided
81.24 - * by Oracle in the GPL Version 2 section of the License file that
81.25 - * accompanied this code. If applicable, add the following below the
81.26 - * License Header, with the fields enclosed by brackets [] replaced by
81.27 - * your own identifying information:
81.28 - * "Portions Copyrighted [year] [name of copyright owner]"
81.29 - *
81.30 - * Contributor(s):
81.31 - *
81.32 - * The Original Software is NetBeans. The Initial Developer of the Original
81.33 - * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
81.34 - *
81.35 - * If you wish your version of this file to be governed by only the CDDL
81.36 - * or only the GPL Version 2, indicate your decision by adding
81.37 - * "[Contributor] elects to include this software in this distribution
81.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
81.39 - * single choice of license, a recipient has the option to distribute
81.40 - * your version of this file under either the CDDL, the GPL Version 2 or
81.41 - * to extend the choice of license to its licensees as provided above.
81.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
81.43 - * Version 2 license, then the option applies only if the new code is
81.44 - * made subject to such option by the copyright holder.
81.45 - */
81.46 -package org.apidesign.html.json.impl;
81.47 -
81.48 -import net.java.html.BrwsrCtx;
81.49 -
81.50 -/** Super type for those who wish to receive JSON messages.
81.51 - *
81.52 - * @author Jaroslav Tulach <jtulach@netbeans.org>
81.53 - */
81.54 -public abstract class RcvrJSON {
81.55 - protected void onOpen(MsgEvnt msg) {}
81.56 - protected abstract void onMessage(MsgEvnt msg);
81.57 - protected void onClose(MsgEvnt msg) {}
81.58 - protected abstract void onError(MsgEvnt msg);
81.59 -
81.60 - public abstract static class MsgEvnt {
81.61 - MsgEvnt() {
81.62 - }
81.63 -
81.64 - public Throwable getError() {
81.65 - return null;
81.66 - }
81.67 -
81.68 - public final Exception getException() {
81.69 - Throwable t = getError();
81.70 - if (t instanceof Exception) {
81.71 - return (Exception)t;
81.72 - }
81.73 - if (t == null) {
81.74 - return null;
81.75 - }
81.76 - return new Exception(t);
81.77 - }
81.78 -
81.79 - public int dataSize() {
81.80 - return -1;
81.81 - }
81.82 -
81.83 - public <Data> void dataRead(BrwsrCtx ctx, Class<? extends Data> type, Data[] fillTheArray) {
81.84 - }
81.85 -
81.86 - public abstract void dispatch(RcvrJSON r);
81.87 -
81.88 - public static MsgEvnt createError(final Throwable t) {
81.89 - return new MsgEvnt() {
81.90 - @Override
81.91 - public Throwable getError() {
81.92 - return t;
81.93 - }
81.94 -
81.95 - @Override
81.96 - public void dispatch(RcvrJSON r) {
81.97 - r.onError(this);
81.98 - }
81.99 - };
81.100 - }
81.101 -
81.102 - public static MsgEvnt createMessage(final Object value) {
81.103 - return new MsgEvnt() {
81.104 - @Override
81.105 - public int dataSize() {
81.106 - if (value instanceof Object[]) {
81.107 - return ((Object[])value).length;
81.108 - } else {
81.109 - return 1;
81.110 - }
81.111 - }
81.112 -
81.113 - @Override
81.114 - public <Data> void dataRead(BrwsrCtx context, Class<? extends Data> type, Data[] arr) {
81.115 - if (value instanceof Object[]) {
81.116 - Object[] data = ((Object[]) value);
81.117 - for (int i = 0; i < data.length && i < arr.length; i++) {
81.118 - arr[i] = org.apidesign.html.json.impl.JSON.read(context, type, data[i]);
81.119 - }
81.120 - } else {
81.121 - if (arr.length > 0) {
81.122 - arr[0] = org.apidesign.html.json.impl.JSON.read(context, type, value);
81.123 - }
81.124 - }
81.125 - }
81.126 -
81.127 - @Override
81.128 - public void dispatch(RcvrJSON r) {
81.129 - r.onMessage(this);
81.130 - }
81.131 - };
81.132 - }
81.133 -
81.134 - public static MsgEvnt createOpen() {
81.135 - return new MsgEvnt() {
81.136 - @Override
81.137 - public void dispatch(RcvrJSON r) {
81.138 - r.onOpen(this);
81.139 - }
81.140 - };
81.141 - }
81.142 -
81.143 - public static MsgEvnt createClose() {
81.144 - return new MsgEvnt() {
81.145 - @Override
81.146 - public void dispatch(RcvrJSON r) {
81.147 - r.onClose(this);
81.148 - }
81.149 - };
81.150 - }
81.151 - } // end MsgEvnt
81.152 -}
82.1 --- a/json/src/main/java/org/apidesign/html/json/impl/SetAndGet.java Mon Dec 16 15:48:09 2013 +0100
82.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
82.3 @@ -1,54 +0,0 @@
82.4 -/**
82.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
82.6 - *
82.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
82.8 - *
82.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
82.10 - * Other names may be trademarks of their respective owners.
82.11 - *
82.12 - * The contents of this file are subject to the terms of either the GNU
82.13 - * General Public License Version 2 only ("GPL") or the Common
82.14 - * Development and Distribution License("CDDL") (collectively, the
82.15 - * "License"). You may not use this file except in compliance with the
82.16 - * License. You can obtain a copy of the License at
82.17 - * http://www.netbeans.org/cddl-gplv2.html
82.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
82.19 - * specific language governing permissions and limitations under the
82.20 - * License. When distributing the software, include this License Header
82.21 - * Notice in each file and include the License file at
82.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
82.23 - * particular file as subject to the "Classpath" exception as provided
82.24 - * by Oracle in the GPL Version 2 section of the License file that
82.25 - * accompanied this code. If applicable, add the following below the
82.26 - * License Header, with the fields enclosed by brackets [] replaced by
82.27 - * your own identifying information:
82.28 - * "Portions Copyrighted [year] [name of copyright owner]"
82.29 - *
82.30 - * Contributor(s):
82.31 - *
82.32 - * The Original Software is NetBeans. The Initial Developer of the Original
82.33 - * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
82.34 - *
82.35 - * If you wish your version of this file to be governed by only the CDDL
82.36 - * or only the GPL Version 2, indicate your decision by adding
82.37 - * "[Contributor] elects to include this software in this distribution
82.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
82.39 - * single choice of license, a recipient has the option to distribute
82.40 - * your version of this file under either the CDDL, the GPL Version 2 or
82.41 - * to extend the choice of license to its licensees as provided above.
82.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
82.43 - * Version 2 license, then the option applies only if the new code is
82.44 - * made subject to such option by the copyright holder.
82.45 - */
82.46 -package org.apidesign.html.json.impl;
82.47 -
82.48 -import org.apidesign.html.json.spi.PropertyBinding;
82.49 -
82.50 -/** A way to implement a {@link PropertyBinding}.
82.51 - *
82.52 - * @author Jaroslav Tulach <jtulach@netbeans.org>
82.53 - */
82.54 -public interface SetAndGet<Data> {
82.55 - public void setValue(Data data, Object value);
82.56 - public Object getValue(Data data);
82.57 -}
83.1 --- a/json/src/main/java/org/apidesign/html/json/impl/WrapperObject.java Mon Dec 16 15:48:09 2013 +0100
83.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
83.3 @@ -1,82 +0,0 @@
83.4 -/**
83.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
83.6 - *
83.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
83.8 - *
83.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
83.10 - * Other names may be trademarks of their respective owners.
83.11 - *
83.12 - * The contents of this file are subject to the terms of either the GNU
83.13 - * General Public License Version 2 only ("GPL") or the Common
83.14 - * Development and Distribution License("CDDL") (collectively, the
83.15 - * "License"). You may not use this file except in compliance with the
83.16 - * License. You can obtain a copy of the License at
83.17 - * http://www.netbeans.org/cddl-gplv2.html
83.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
83.19 - * specific language governing permissions and limitations under the
83.20 - * License. When distributing the software, include this License Header
83.21 - * Notice in each file and include the License file at
83.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
83.23 - * particular file as subject to the "Classpath" exception as provided
83.24 - * by Oracle in the GPL Version 2 section of the License file that
83.25 - * accompanied this code. If applicable, add the following below the
83.26 - * License Header, with the fields enclosed by brackets [] replaced by
83.27 - * your own identifying information:
83.28 - * "Portions Copyrighted [year] [name of copyright owner]"
83.29 - *
83.30 - * Contributor(s):
83.31 - *
83.32 - * The Original Software is NetBeans. The Initial Developer of the Original
83.33 - * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
83.34 - *
83.35 - * If you wish your version of this file to be governed by only the CDDL
83.36 - * or only the GPL Version 2, indicate your decision by adding
83.37 - * "[Contributor] elects to include this software in this distribution
83.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
83.39 - * single choice of license, a recipient has the option to distribute
83.40 - * your version of this file under either the CDDL, the GPL Version 2 or
83.41 - * to extend the choice of license to its licensees as provided above.
83.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
83.43 - * Version 2 license, then the option applies only if the new code is
83.44 - * made subject to such option by the copyright holder.
83.45 - */
83.46 -package org.apidesign.html.json.impl;
83.47 -
83.48 -import java.util.Collection;
83.49 -import org.apidesign.html.json.impl.PropertyBindingAccessor.PBData;
83.50 -
83.51 -/** A way to extract real object from a model classes.
83.52 - *
83.53 - * @author Jaroslav Tulach <jtulach@netbeans.org>
83.54 - */
83.55 -public final class WrapperObject {
83.56 - private Object ko;
83.57 -
83.58 - private WrapperObject() {
83.59 - }
83.60 -
83.61 - public void setRealObject(Object ko) {
83.62 - this.ko = ko;
83.63 - }
83.64 -
83.65 - public static Object find(Object object) {
83.66 - return find(object, null);
83.67 - }
83.68 -
83.69 - public static Object find(Object object, Bindings model) {
83.70 - if (object == null) {
83.71 - return null;
83.72 - }
83.73 -
83.74 - if (object instanceof JSONList) {
83.75 - return ((JSONList<?>)object).koData();
83.76 - }
83.77 - if (object instanceof Collection) {
83.78 - return JSONList.koData((Collection<?>)object, model);
83.79 - }
83.80 -
83.81 - WrapperObject ro = new WrapperObject();
83.82 - object.equals(ro);
83.83 - return ro.ko;
83.84 - }
83.85 -}
84.1 --- a/json/src/main/java/org/apidesign/html/json/spi/FunctionBinding.java Mon Dec 16 15:48:09 2013 +0100
84.2 +++ b/json/src/main/java/org/apidesign/html/json/spi/FunctionBinding.java Mon Dec 16 16:59:43 2013 +0100
84.3 @@ -44,7 +44,7 @@
84.4
84.5 import net.java.html.json.Function;
84.6 import net.java.html.json.Model;
84.7 -import org.apidesign.html.json.impl.PropertyBindingAccessor.FBData;
84.8 +import org.netbeans.html.json.impl.PropertyBindingAccessor.FBData;
84.9
84.10 /** Describes a function provided by the {@link Model} and
84.11 * annotated by {@link Function} annotation.
85.1 --- a/json/src/main/java/org/apidesign/html/json/spi/JSONCall.java Mon Dec 16 15:48:09 2013 +0100
85.2 +++ b/json/src/main/java/org/apidesign/html/json/spi/JSONCall.java Mon Dec 16 16:59:43 2013 +0100
85.3 @@ -45,8 +45,8 @@
85.4 import java.io.IOException;
85.5 import java.io.OutputStream;
85.6 import net.java.html.BrwsrCtx;
85.7 -import org.apidesign.html.json.impl.JSON;
85.8 -import org.apidesign.html.json.impl.RcvrJSON;
85.9 +import org.netbeans.html.json.impl.JSON;
85.10 +import org.netbeans.html.json.impl.RcvrJSON;
85.11
85.12 /** Description of a JSON call request that is supposed to be processed
85.13 * by {@link Transfer#loadJSON(org.apidesign.html.json.spi.JSONCall)} implementors.
86.1 --- a/json/src/main/java/org/apidesign/html/json/spi/PropertyBinding.java Mon Dec 16 15:48:09 2013 +0100
86.2 +++ b/json/src/main/java/org/apidesign/html/json/spi/PropertyBinding.java Mon Dec 16 16:59:43 2013 +0100
86.3 @@ -43,10 +43,10 @@
86.4 package org.apidesign.html.json.spi;
86.5
86.6 import net.java.html.BrwsrCtx;
86.7 -import org.apidesign.html.json.impl.PropertyBindingAccessor;
86.8 -import org.apidesign.html.json.impl.PropertyBindingAccessor.PBData;
86.9 -import org.apidesign.html.json.impl.RcvrJSON;
86.10 -import org.apidesign.html.json.impl.WrapperObject;
86.11 +import org.netbeans.html.json.impl.PropertyBindingAccessor;
86.12 +import org.netbeans.html.json.impl.PropertyBindingAccessor.PBData;
86.13 +import org.netbeans.html.json.impl.RcvrJSON;
86.14 +import org.netbeans.html.json.impl.WrapperObject;
86.15
86.16 /** Describes a property when one is asked to
86.17 * bind it
87.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
87.2 +++ b/json/src/main/java/org/netbeans/html/json/impl/Bindings.java Mon Dec 16 16:59:43 2013 +0100
87.3 @@ -0,0 +1,113 @@
87.4 +/**
87.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
87.6 + *
87.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
87.8 + *
87.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
87.10 + * Other names may be trademarks of their respective owners.
87.11 + *
87.12 + * The contents of this file are subject to the terms of either the GNU
87.13 + * General Public License Version 2 only ("GPL") or the Common
87.14 + * Development and Distribution License("CDDL") (collectively, the
87.15 + * "License"). You may not use this file except in compliance with the
87.16 + * License. You can obtain a copy of the License at
87.17 + * http://www.netbeans.org/cddl-gplv2.html
87.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
87.19 + * specific language governing permissions and limitations under the
87.20 + * License. When distributing the software, include this License Header
87.21 + * Notice in each file and include the License file at
87.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
87.23 + * particular file as subject to the "Classpath" exception as provided
87.24 + * by Oracle in the GPL Version 2 section of the License file that
87.25 + * accompanied this code. If applicable, add the following below the
87.26 + * License Header, with the fields enclosed by brackets [] replaced by
87.27 + * your own identifying information:
87.28 + * "Portions Copyrighted [year] [name of copyright owner]"
87.29 + *
87.30 + * Contributor(s):
87.31 + *
87.32 + * The Original Software is NetBeans. The Initial Developer of the Original
87.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
87.34 + *
87.35 + * If you wish your version of this file to be governed by only the CDDL
87.36 + * or only the GPL Version 2, indicate your decision by adding
87.37 + * "[Contributor] elects to include this software in this distribution
87.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
87.39 + * single choice of license, a recipient has the option to distribute
87.40 + * your version of this file under either the CDDL, the GPL Version 2 or
87.41 + * to extend the choice of license to its licensees as provided above.
87.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
87.43 + * Version 2 license, then the option applies only if the new code is
87.44 + * made subject to such option by the copyright holder.
87.45 + */
87.46 +package org.netbeans.html.json.impl;
87.47 +
87.48 +import org.apidesign.html.json.spi.PropertyBinding;
87.49 +import net.java.html.BrwsrCtx;
87.50 +import org.netbeans.html.json.impl.PropertyBindingAccessor.FBData;
87.51 +import org.netbeans.html.json.impl.PropertyBindingAccessor.PBData;
87.52 +import org.apidesign.html.json.spi.FunctionBinding;
87.53 +import org.apidesign.html.json.spi.Technology;
87.54 +
87.55 +/**
87.56 + *
87.57 + * @author Jaroslav Tulach <jtulach@netbeans.org>
87.58 + */
87.59 +public final class Bindings<Data> {
87.60 + private Data data;
87.61 + private final Technology<Data> bp;
87.62 +
87.63 + private Bindings(Technology<Data> bp) {
87.64 + this.bp = bp;
87.65 + }
87.66 +
87.67 + public <M> PropertyBinding registerProperty(String propName, M model, SetAndGet<M> access, boolean readOnly) {
87.68 + return PropertyBindingAccessor.create(new PBData<M>(this, propName, model, access, readOnly));
87.69 + }
87.70 +
87.71 + public <M> FunctionBinding registerFunction(String name, M model, Callback<M> access) {
87.72 + return PropertyBindingAccessor.createFunction(new FBData<M>(name, model, access));
87.73 + }
87.74 +
87.75 + public static Bindings<?> apply(BrwsrCtx c, Object model) {
87.76 + Technology<?> bp = JSON.findTechnology(c);
87.77 + return apply(bp);
87.78 + }
87.79 +
87.80 + private static <Data> Bindings<Data> apply(Technology<Data> bp) {
87.81 + return new Bindings<Data>(bp);
87.82 + }
87.83 +
87.84 + public final void finish(Object model, PropertyBinding[] propArr, FunctionBinding[] funcArr) {
87.85 + assert data == null;
87.86 + if (bp instanceof Technology.BatchInit) {
87.87 + Technology.BatchInit<Data> bi = (Technology.BatchInit<Data>)bp;
87.88 + data = bi.wrapModel(model, propArr, funcArr);
87.89 + } else {
87.90 + data = bp.wrapModel(model);
87.91 + for (PropertyBinding b : propArr) {
87.92 + bp.bind(b, model, data);
87.93 + }
87.94 + for (FunctionBinding b : funcArr) {
87.95 + bp.expose(b, model, data);
87.96 + }
87.97 + }
87.98 + }
87.99 +
87.100 +
87.101 + public Data koData() {
87.102 + return data;
87.103 + }
87.104 +
87.105 + public void valueHasMutated(String firstName) {
87.106 + bp.valueHasMutated(data, firstName);
87.107 + }
87.108 +
87.109 + public void applyBindings() {
87.110 + bp.applyBindings(data);
87.111 + }
87.112 +
87.113 + Object wrapArray(Object[] arr) {
87.114 + return bp.wrapArray(arr);
87.115 + }
87.116 +}
88.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
88.2 +++ b/json/src/main/java/org/netbeans/html/json/impl/Callback.java Mon Dec 16 16:59:43 2013 +0100
88.3 @@ -0,0 +1,51 @@
88.4 +/**
88.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
88.6 + *
88.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
88.8 + *
88.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
88.10 + * Other names may be trademarks of their respective owners.
88.11 + *
88.12 + * The contents of this file are subject to the terms of either the GNU
88.13 + * General Public License Version 2 only ("GPL") or the Common
88.14 + * Development and Distribution License("CDDL") (collectively, the
88.15 + * "License"). You may not use this file except in compliance with the
88.16 + * License. You can obtain a copy of the License at
88.17 + * http://www.netbeans.org/cddl-gplv2.html
88.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
88.19 + * specific language governing permissions and limitations under the
88.20 + * License. When distributing the software, include this License Header
88.21 + * Notice in each file and include the License file at
88.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
88.23 + * particular file as subject to the "Classpath" exception as provided
88.24 + * by Oracle in the GPL Version 2 section of the License file that
88.25 + * accompanied this code. If applicable, add the following below the
88.26 + * License Header, with the fields enclosed by brackets [] replaced by
88.27 + * your own identifying information:
88.28 + * "Portions Copyrighted [year] [name of copyright owner]"
88.29 + *
88.30 + * Contributor(s):
88.31 + *
88.32 + * The Original Software is NetBeans. The Initial Developer of the Original
88.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
88.34 + *
88.35 + * If you wish your version of this file to be governed by only the CDDL
88.36 + * or only the GPL Version 2, indicate your decision by adding
88.37 + * "[Contributor] elects to include this software in this distribution
88.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
88.39 + * single choice of license, a recipient has the option to distribute
88.40 + * your version of this file under either the CDDL, the GPL Version 2 or
88.41 + * to extend the choice of license to its licensees as provided above.
88.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
88.43 + * Version 2 license, then the option applies only if the new code is
88.44 + * made subject to such option by the copyright holder.
88.45 + */
88.46 +package org.netbeans.html.json.impl;
88.47 +
88.48 +/**
88.49 + *
88.50 + * @author Jaroslav Tulach <jtulach@netbeans.org>
88.51 + */
88.52 +public interface Callback<Data> {
88.53 + public void call(Data model, Object data, Object ev);
88.54 +}
89.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
89.2 +++ b/json/src/main/java/org/netbeans/html/json/impl/FromJSON.java Mon Dec 16 16:59:43 2013 +0100
89.3 @@ -0,0 +1,55 @@
89.4 +/**
89.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
89.6 + *
89.7 + * Copyright 1997-2010 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.json.impl;
89.47 +
89.48 +import net.java.html.BrwsrCtx;
89.49 +
89.50 +/**
89.51 + *
89.52 + * @author Jaroslav Tulach <jtulach@netbeans.org>
89.53 + */
89.54 +public interface FromJSON<Data> {
89.55 + public Class<Data> factoryFor();
89.56 + public Data read(BrwsrCtx c, Object d);
89.57 + public Data cloneTo(Object d, BrwsrCtx c);
89.58 +}
90.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
90.2 +++ b/json/src/main/java/org/netbeans/html/json/impl/JSON.java Mon Dec 16 16:59:43 2013 +0100
90.3 @@ -0,0 +1,474 @@
90.4 +/**
90.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
90.6 + *
90.7 + * Copyright 1997-2010 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.json.impl;
90.47 +
90.48 +import java.io.IOException;
90.49 +import java.io.InputStream;
90.50 +import java.util.HashMap;
90.51 +import java.util.Map;
90.52 +import net.java.html.BrwsrCtx;
90.53 +import org.apidesign.html.context.spi.Contexts;
90.54 +import org.apidesign.html.json.spi.FunctionBinding;
90.55 +import org.apidesign.html.json.spi.JSONCall;
90.56 +import org.apidesign.html.json.spi.PropertyBinding;
90.57 +import org.apidesign.html.json.spi.Technology;
90.58 +import org.apidesign.html.json.spi.Transfer;
90.59 +import org.apidesign.html.json.spi.WSTransfer;
90.60 +
90.61 +/**
90.62 + *
90.63 + * @author Jaroslav Tulach <jtulach@netbeans.org>
90.64 + */
90.65 +public final class JSON {
90.66 + private JSON() {
90.67 + }
90.68 +
90.69 + static Technology<?> findTechnology(BrwsrCtx c) {
90.70 + Technology<?> t = Contexts.find(c, Technology.class);
90.71 + return t == null ? EmptyTech.EMPTY : t;
90.72 + }
90.73 +
90.74 + static Transfer findTransfer(BrwsrCtx c) {
90.75 + Transfer t = Contexts.find(c, Transfer.class);
90.76 + return t == null ? EmptyTech.EMPTY : t;
90.77 + }
90.78 +
90.79 + static WSTransfer<?> findWSTransfer(BrwsrCtx c) {
90.80 + WSTransfer<?> t = Contexts.find(c, WSTransfer.class);
90.81 + return t == null ? EmptyTech.EMPTY : t;
90.82 + }
90.83 +
90.84 + public static void runInBrowser(BrwsrCtx c, Runnable runnable) {
90.85 + findTechnology(c).runSafe(runnable);
90.86 + }
90.87 +
90.88 + public static void extract(BrwsrCtx c, Object value, String[] props, Object[] values) {
90.89 + Transfer t = findTransfer(c);
90.90 + t.extract(value, props, values);
90.91 + }
90.92 +
90.93 + private static Object getProperty(BrwsrCtx c, Object obj, String prop) {
90.94 + if (prop == null) return obj;
90.95 +
90.96 + String[] arr = { prop };
90.97 + Object[] val = { null };
90.98 + extract(c, obj, arr, val);
90.99 + return val[0];
90.100 + }
90.101 +
90.102 + public static Object toJSON(Object value) {
90.103 + if (value == null) {
90.104 + return "null";
90.105 + }
90.106 + if (value instanceof Enum) {
90.107 + value = value.toString();
90.108 + }
90.109 + if (value instanceof String) {
90.110 + String s = (String)value;
90.111 + int len = s.length();
90.112 + StringBuilder sb = new StringBuilder(len + 10);
90.113 + sb.append('"');
90.114 + for (int i = 0; i < len; i++) {
90.115 + char ch = s.charAt(i);
90.116 + switch (ch) {
90.117 + case '\"': sb.append("\\\""); break;
90.118 + case '\n': sb.append("\\n"); break;
90.119 + case '\r': sb.append("\\r"); break;
90.120 + case '\t': sb.append("\\t"); break;
90.121 + case '\\': sb.append("\\\\"); break;
90.122 + default: sb.append(ch);
90.123 + }
90.124 + }
90.125 + sb.append('"');
90.126 + return sb.toString();
90.127 + }
90.128 + return value.toString();
90.129 + }
90.130 +
90.131 + public static String toString(BrwsrCtx c, Object obj, String prop) {
90.132 + obj = getProperty(c, obj, prop);
90.133 + return obj instanceof String ? (String)obj : null;
90.134 + }
90.135 + public static Number toNumber(BrwsrCtx c, Object obj, String prop) {
90.136 + obj = getProperty(c, obj, prop);
90.137 + if (!(obj instanceof Number)) {
90.138 + obj = Double.NaN;
90.139 + }
90.140 + return (Number)obj;
90.141 + }
90.142 + public static <M> M toModel(BrwsrCtx c, Class<M> aClass, Object data, Object object) {
90.143 + Technology<?> t = findTechnology(c);
90.144 + Object o = t.toModel(aClass, data);
90.145 + return aClass.cast(o);
90.146 + }
90.147 +
90.148 + public static boolean isSame(int a, int b) {
90.149 + return a == b;
90.150 + }
90.151 +
90.152 + public static boolean isSame(double a, double b) {
90.153 + return a == b;
90.154 + }
90.155 +
90.156 + public static boolean isSame(Object a, Object b) {
90.157 + if (a == b) {
90.158 + return true;
90.159 + }
90.160 + if (a == null || b == null) {
90.161 + return false;
90.162 + }
90.163 + return a.equals(b);
90.164 + }
90.165 +
90.166 + public static int hashPlus(Object o, int h) {
90.167 + return o == null ? h : h ^ o.hashCode();
90.168 + }
90.169 +
90.170 + public static <T> T extractValue(Class<T> type, Object val) {
90.171 + if (Number.class.isAssignableFrom(type)) {
90.172 + val = numberValue(val);
90.173 + }
90.174 + if (Boolean.class == type) {
90.175 + val = boolValue(val);
90.176 + }
90.177 + if (String.class == type) {
90.178 + val = stringValue(val);
90.179 + }
90.180 + if (Character.class == type) {
90.181 + val = charValue(val);
90.182 + }
90.183 + if (Integer.class == type) {
90.184 + val = val instanceof Number ? ((Number)val).intValue() : 0;
90.185 + }
90.186 + if (Long.class == type) {
90.187 + val = val instanceof Number ? ((Number)val).longValue() : 0;
90.188 + }
90.189 + if (Short.class == type) {
90.190 + val = val instanceof Number ? ((Number)val).shortValue() : 0;
90.191 + }
90.192 + if (Byte.class == type) {
90.193 + val = val instanceof Number ? ((Number)val).byteValue() : 0;
90.194 + }
90.195 + if (Double.class == type) {
90.196 + val = val instanceof Number ? ((Number)val).doubleValue() : Double.NaN;
90.197 + }
90.198 + if (Float.class == type) {
90.199 + val = val instanceof Number ? ((Number)val).floatValue() : Float.NaN;
90.200 + }
90.201 + return type.cast(val);
90.202 + }
90.203 +
90.204 + protected static boolean isNumeric(Object val) {
90.205 + return ((val instanceof Integer) || (val instanceof Long) || (val instanceof Short) || (val instanceof Byte));
90.206 + }
90.207 +
90.208 + public static String stringValue(Object val) {
90.209 + if (val instanceof Boolean) {
90.210 + return ((Boolean)val ? "true" : "false");
90.211 + }
90.212 + if (isNumeric(val)) {
90.213 + return Long.toString(((Number)val).longValue());
90.214 + }
90.215 + if (val instanceof Float) {
90.216 + return Float.toString((Float)val);
90.217 + }
90.218 + if (val instanceof Double) {
90.219 + return Double.toString((Double)val);
90.220 + }
90.221 + return (String)val;
90.222 + }
90.223 +
90.224 + public static Number numberValue(Object val) {
90.225 + if (val instanceof String) {
90.226 + try {
90.227 + return Double.valueOf((String)val);
90.228 + } catch (NumberFormatException ex) {
90.229 + return Double.NaN;
90.230 + }
90.231 + }
90.232 + if (val instanceof Boolean) {
90.233 + return (Boolean)val ? 1 : 0;
90.234 + }
90.235 + return (Number)val;
90.236 + }
90.237 +
90.238 + public static Character charValue(Object val) {
90.239 + if (val instanceof Number) {
90.240 + return Character.toChars(numberValue(val).intValue())[0];
90.241 + }
90.242 + if (val instanceof Boolean) {
90.243 + return (Boolean)val ? (char)1 : (char)0;
90.244 + }
90.245 + if (val instanceof String) {
90.246 + String s = (String)val;
90.247 + return s.isEmpty() ? (char)0 : s.charAt(0);
90.248 + }
90.249 + return (Character)val;
90.250 + }
90.251 +
90.252 + public static Boolean boolValue(Object val) {
90.253 + if (val instanceof String) {
90.254 + return Boolean.parseBoolean((String)val);
90.255 + }
90.256 + if (val instanceof Number) {
90.257 + return numberValue(val).doubleValue() != 0.0;
90.258 + }
90.259 +
90.260 + return Boolean.TRUE.equals(val);
90.261 + }
90.262 +
90.263 + public static void loadJSON(
90.264 + BrwsrCtx c, RcvrJSON callback,
90.265 + String urlBefore, String urlAfter, String method,
90.266 + Object data
90.267 + ) {
90.268 + JSONCall call = PropertyBindingAccessor.createCall(c, callback, urlBefore, urlAfter, method, data);
90.269 + Transfer t = findTransfer(c);
90.270 + t.loadJSON(call);
90.271 + }
90.272 + public static WS openWS(
90.273 + BrwsrCtx c, RcvrJSON r, String url, Object data
90.274 + ) {
90.275 + WS ws = WSImpl.create(findWSTransfer(c), r);
90.276 + ws.send(c, url, data);
90.277 + return ws;
90.278 + }
90.279 +
90.280 + public static abstract class WS {
90.281 + private WS() {
90.282 + }
90.283 +
90.284 + public abstract void send(BrwsrCtx ctx, String url, Object model);
90.285 + }
90.286 +
90.287 + private static final class WSImpl<Socket> extends WS {
90.288 +
90.289 + private final WSTransfer<Socket> trans;
90.290 + private final RcvrJSON rcvr;
90.291 + private Socket socket;
90.292 + private String prevURL;
90.293 +
90.294 + private WSImpl(WSTransfer<Socket> trans, RcvrJSON rcvr) {
90.295 + this.trans = trans;
90.296 + this.rcvr = rcvr;
90.297 + }
90.298 +
90.299 + static <Socket> WS create(WSTransfer<Socket> t, RcvrJSON r) {
90.300 + return new WSImpl<Socket>(t, r);
90.301 + }
90.302 +
90.303 + @Override
90.304 + public void send(BrwsrCtx ctx, String url, Object data) {
90.305 + Socket s = socket;
90.306 + if (s == null) {
90.307 + if (data != null) {
90.308 + throw new IllegalStateException("WebSocket is not opened yet. Call with null data, was: " + data);
90.309 + }
90.310 + JSONCall call = PropertyBindingAccessor.createCall(ctx, rcvr, url, null, "WebSocket", null);
90.311 + socket = trans.open(url, call);
90.312 + prevURL = url;
90.313 + return;
90.314 + }
90.315 + if (data == null) {
90.316 + trans.close(s);
90.317 + socket = null;
90.318 + return;
90.319 + }
90.320 + if (!prevURL.equals(url)) {
90.321 + throw new IllegalStateException(
90.322 + "Can't call to different URL " + url + " was: " + prevURL + "!"
90.323 + + " Close the socket by calling it will null data first!"
90.324 + );
90.325 + }
90.326 + JSONCall call = PropertyBindingAccessor.createCall(ctx, rcvr, prevURL, null, "WebSocket", data);
90.327 + trans.send(s, call);
90.328 + }
90.329 +
90.330 + }
90.331 +
90.332 + private static final Map<Class,FromJSON<?>> froms;
90.333 + static {
90.334 + Map<Class,FromJSON<?>> m = new HashMap<Class,FromJSON<?>>();
90.335 + froms = m;
90.336 + }
90.337 + public static void register(FromJSON<?> from) {
90.338 + froms.put(from.factoryFor(), from);
90.339 + }
90.340 +
90.341 + public static boolean isModel(Class<?> clazz) {
90.342 + return findFrom(clazz) != null;
90.343 + }
90.344 +
90.345 + private static FromJSON<?> findFrom(Class<?> clazz) {
90.346 + for (int i = 0; i < 2; i++) {
90.347 + FromJSON<?> from = froms.get(clazz);
90.348 + if (from == null) {
90.349 + initClass(clazz);
90.350 + } else {
90.351 + return from;
90.352 + }
90.353 + }
90.354 + return null;
90.355 + }
90.356 +
90.357 + public static <Model> Model bindTo(Model model, BrwsrCtx c) {
90.358 + FromJSON<?> from = findFrom(model.getClass());
90.359 + if (from == null) {
90.360 + throw new IllegalArgumentException();
90.361 + }
90.362 + return (Model) from.cloneTo(model, c);
90.363 + }
90.364 +
90.365 + public static <T> T readStream(BrwsrCtx c, Class<T> modelClazz, InputStream data)
90.366 + throws IOException {
90.367 + Transfer tr = findTransfer(c);
90.368 + return read(c, modelClazz, tr.toJSON((InputStream)data));
90.369 + }
90.370 + public static <T> T read(BrwsrCtx c, Class<T> modelClazz, Object data) {
90.371 + if (data == null) {
90.372 + return null;
90.373 + }
90.374 + if (modelClazz == String.class) {
90.375 + return modelClazz.cast(data.toString());
90.376 + }
90.377 + for (int i = 0; i < 2; i++) {
90.378 + FromJSON<?> from = froms.get(modelClazz);
90.379 + if (from == null) {
90.380 + initClass(modelClazz);
90.381 + } else {
90.382 + return modelClazz.cast(from.read(c, data));
90.383 + }
90.384 + }
90.385 + throw new NullPointerException();
90.386 + }
90.387 + static void initClass(Class<?> modelClazz) {
90.388 + try {
90.389 + // try to resolve the class
90.390 + ClassLoader l;
90.391 + try {
90.392 + l = modelClazz.getClassLoader();
90.393 + } catch (SecurityException ex) {
90.394 + l = null;
90.395 + }
90.396 + if (l != null) {
90.397 + Class.forName(modelClazz.getName(), true, l);
90.398 + }
90.399 + modelClazz.newInstance();
90.400 + } catch (Exception ex) {
90.401 + // ignore and try again
90.402 + }
90.403 + }
90.404 +
90.405 + private static final class EmptyTech
90.406 + implements Technology<Object>, Transfer, WSTransfer<Void> {
90.407 + private static final EmptyTech EMPTY = new EmptyTech();
90.408 +
90.409 + @Override
90.410 + public Object wrapModel(Object model) {
90.411 + return model;
90.412 + }
90.413 +
90.414 + @Override
90.415 + public void valueHasMutated(Object data, String propertyName) {
90.416 + }
90.417 +
90.418 + @Override
90.419 + public void bind(PropertyBinding b, Object model, Object data) {
90.420 + }
90.421 +
90.422 + @Override
90.423 + public void expose(FunctionBinding fb, Object model, Object d) {
90.424 + }
90.425 +
90.426 + @Override
90.427 + public void applyBindings(Object data) {
90.428 + }
90.429 +
90.430 + @Override
90.431 + public Object wrapArray(Object[] arr) {
90.432 + return arr;
90.433 + }
90.434 +
90.435 + @Override
90.436 + public void extract(Object obj, String[] props, Object[] values) {
90.437 + for (int i = 0; i < values.length; i++) {
90.438 + values[i] = null;
90.439 + }
90.440 + }
90.441 +
90.442 + @Override
90.443 + public void loadJSON(JSONCall call) {
90.444 + call.notifyError(new UnsupportedOperationException());
90.445 + }
90.446 +
90.447 + @Override
90.448 + public <M> M toModel(Class<M> modelClass, Object data) {
90.449 + return modelClass.cast(data);
90.450 + }
90.451 +
90.452 + @Override
90.453 + public Object toJSON(InputStream is) throws IOException {
90.454 + throw new IOException("Not supported");
90.455 + }
90.456 +
90.457 + @Override
90.458 + public synchronized void runSafe(Runnable r) {
90.459 + r.run();
90.460 + }
90.461 +
90.462 + @Override
90.463 + public Void open(String url, JSONCall onReply) {
90.464 + onReply.notifyError(new UnsupportedOperationException("WebSockets not supported!"));
90.465 + return null;
90.466 + }
90.467 +
90.468 + @Override
90.469 + public void send(Void socket, JSONCall data) {
90.470 + }
90.471 +
90.472 + @Override
90.473 + public void close(Void socket) {
90.474 + }
90.475 + }
90.476 +
90.477 +}
91.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
91.2 +++ b/json/src/main/java/org/netbeans/html/json/impl/JSONList.java Mon Dec 16 16:59:43 2013 +0100
91.3 @@ -0,0 +1,236 @@
91.4 +/**
91.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
91.6 + *
91.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
91.8 + *
91.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
91.10 + * Other names may be trademarks of their respective owners.
91.11 + *
91.12 + * The contents of this file are subject to the terms of either the GNU
91.13 + * General Public License Version 2 only ("GPL") or the Common
91.14 + * Development and Distribution License("CDDL") (collectively, the
91.15 + * "License"). You may not use this file except in compliance with the
91.16 + * License. You can obtain a copy of the License at
91.17 + * http://www.netbeans.org/cddl-gplv2.html
91.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
91.19 + * specific language governing permissions and limitations under the
91.20 + * License. When distributing the software, include this License Header
91.21 + * Notice in each file and include the License file at
91.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
91.23 + * particular file as subject to the "Classpath" exception as provided
91.24 + * by Oracle in the GPL Version 2 section of the License file that
91.25 + * accompanied this code. If applicable, add the following below the
91.26 + * License Header, with the fields enclosed by brackets [] replaced by
91.27 + * your own identifying information:
91.28 + * "Portions Copyrighted [year] [name of copyright owner]"
91.29 + *
91.30 + * Contributor(s):
91.31 + *
91.32 + * The Original Software is NetBeans. The Initial Developer of the Original
91.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
91.34 + *
91.35 + * If you wish your version of this file to be governed by only the CDDL
91.36 + * or only the GPL Version 2, indicate your decision by adding
91.37 + * "[Contributor] elects to include this software in this distribution
91.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
91.39 + * single choice of license, a recipient has the option to distribute
91.40 + * your version of this file under either the CDDL, the GPL Version 2 or
91.41 + * to extend the choice of license to its licensees as provided above.
91.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
91.43 + * Version 2 license, then the option applies only if the new code is
91.44 + * made subject to such option by the copyright holder.
91.45 + */
91.46 +package org.netbeans.html.json.impl;
91.47 +
91.48 +import java.lang.reflect.Array;
91.49 +import java.util.ArrayList;
91.50 +import java.util.Arrays;
91.51 +import java.util.Collection;
91.52 +import java.util.Iterator;
91.53 +import java.util.List;
91.54 +import net.java.html.BrwsrCtx;
91.55 +
91.56 +/**
91.57 + *
91.58 + * @author Jaroslav Tulach <jtulach@netbeans.org>
91.59 + */
91.60 +public final class JSONList<T> extends ArrayList<T> {
91.61 + private final String name;
91.62 + private final String[] deps;
91.63 + private Bindings[] model;
91.64 + private Runnable onchange;
91.65 +
91.66 + public JSONList(Bindings[] model, String name, String... deps) {
91.67 + assert model.length == 1;
91.68 + this.model = model;
91.69 + this.name = name;
91.70 + this.deps = deps;
91.71 + }
91.72 +
91.73 + public void init(T... values) {
91.74 + if (values == null || values.length == 0) {
91.75 + return;
91.76 + }
91.77 + if (this.model[0] != null || !isEmpty()) {
91.78 + throw new IllegalStateException();
91.79 + }
91.80 + super.addAll(Arrays.asList(values));
91.81 + }
91.82 +
91.83 + public void init(Object values) {
91.84 + int len;
91.85 + if (values == null || (len = Array.getLength(values)) == 0) {
91.86 + return;
91.87 + }
91.88 + if (this.model[0] != null || !isEmpty()) {
91.89 + throw new IllegalStateException();
91.90 + }
91.91 + for (int i = 0; i < len; i++) {
91.92 + Object data = Array.get(values, i);
91.93 + super.add((T)data);
91.94 + }
91.95 + }
91.96 +
91.97 + public JSONList<T> onChange(Runnable r) {
91.98 + if (this.onchange != null) {
91.99 + throw new IllegalStateException();
91.100 + }
91.101 + this.onchange = r;
91.102 + return this;
91.103 + }
91.104 +
91.105 + @Override
91.106 + public boolean add(T e) {
91.107 + boolean ret = super.add(e);
91.108 + notifyChange();
91.109 + return ret;
91.110 + }
91.111 +
91.112 + @Override
91.113 + public boolean addAll(Collection<? extends T> c) {
91.114 + boolean ret = super.addAll(c);
91.115 + notifyChange();
91.116 + return ret;
91.117 + }
91.118 +
91.119 + @Override
91.120 + public boolean addAll(int index, Collection<? extends T> c) {
91.121 + boolean ret = super.addAll(index, c);
91.122 + notifyChange();
91.123 + return ret;
91.124 + }
91.125 +
91.126 + @Override
91.127 + public boolean remove(Object o) {
91.128 + boolean ret = super.remove(o);
91.129 + notifyChange();
91.130 + return ret;
91.131 + }
91.132 +
91.133 + @Override
91.134 + public void clear() {
91.135 + super.clear();
91.136 + notifyChange();
91.137 + }
91.138 +
91.139 + @Override
91.140 + public boolean removeAll(Collection<?> c) {
91.141 + boolean ret = super.removeAll(c);
91.142 + notifyChange();
91.143 + return ret;
91.144 + }
91.145 +
91.146 + @Override
91.147 + public boolean retainAll(Collection<?> c) {
91.148 + boolean ret = super.retainAll(c);
91.149 + notifyChange();
91.150 + return ret;
91.151 + }
91.152 +
91.153 + @Override
91.154 + public T set(int index, T element) {
91.155 + T ret = super.set(index, element);
91.156 + notifyChange();
91.157 + return ret;
91.158 + }
91.159 +
91.160 + @Override
91.161 + public void add(int index, T element) {
91.162 + super.add(index, element);
91.163 + notifyChange();
91.164 + }
91.165 +
91.166 + @Override
91.167 + public T remove(int index) {
91.168 + T ret = super.remove(index);
91.169 + notifyChange();
91.170 + return ret;
91.171 + }
91.172 +
91.173 + @Override
91.174 + public String toString() {
91.175 + Iterator<T> it = iterator();
91.176 + if (!it.hasNext()) {
91.177 + return "[]";
91.178 + }
91.179 + String sep = "";
91.180 + StringBuilder sb = new StringBuilder();
91.181 + sb.append('[');
91.182 + while (it.hasNext()) {
91.183 + T t = it.next();
91.184 + sb.append(sep);
91.185 + sb.append(JSON.toJSON(t));
91.186 + sep = ",";
91.187 + }
91.188 + sb.append(']');
91.189 + return sb.toString();
91.190 + }
91.191 +
91.192 + private void notifyChange() {
91.193 + Bindings m = model[0];
91.194 + if (m != null) {
91.195 + m.valueHasMutated(name);
91.196 + for (String dependant : deps) {
91.197 + m.valueHasMutated(dependant);
91.198 + }
91.199 + Runnable r = onchange;
91.200 + if (r != null) {
91.201 + r.run();
91.202 + }
91.203 + }
91.204 + }
91.205 +
91.206 + public void cloneAll(BrwsrCtx c, Collection<T> other) {
91.207 + Boolean isModel = null;
91.208 + for (T t : other) {
91.209 + if (isModel == null) {
91.210 + isModel = JSON.isModel(t.getClass());
91.211 + }
91.212 + if (isModel) {
91.213 + add(JSON.bindTo(t, c));
91.214 + } else {
91.215 + add(t);
91.216 + }
91.217 + }
91.218 + }
91.219 +
91.220 + @Override
91.221 + public JSONList clone() {
91.222 + throw new UnsupportedOperationException();
91.223 + }
91.224 +
91.225 + static final Object koData(Collection<?> c, Bindings m) {
91.226 + Object[] arr = c.toArray(new Object[c.size()]);
91.227 + for (int i = 0; i < arr.length; i++) {
91.228 + Object r = WrapperObject.find(arr[i], m);
91.229 + if (r != null) {
91.230 + arr[i] = r;
91.231 + }
91.232 + }
91.233 + return m.wrapArray(arr);
91.234 + }
91.235 +
91.236 + final Object koData() {
91.237 + return koData(this, model[0]);
91.238 + }
91.239 +}
92.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
92.2 +++ b/json/src/main/java/org/netbeans/html/json/impl/ModelProcessor.java Mon Dec 16 16:59:43 2013 +0100
92.3 @@ -0,0 +1,1767 @@
92.4 +/**
92.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
92.6 + *
92.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
92.8 + *
92.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
92.10 + * Other names may be trademarks of their respective owners.
92.11 + *
92.12 + * The contents of this file are subject to the terms of either the GNU
92.13 + * General Public License Version 2 only ("GPL") or the Common
92.14 + * Development and Distribution License("CDDL") (collectively, the
92.15 + * "License"). You may not use this file except in compliance with the
92.16 + * License. You can obtain a copy of the License at
92.17 + * http://www.netbeans.org/cddl-gplv2.html
92.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
92.19 + * specific language governing permissions and limitations under the
92.20 + * License. When distributing the software, include this License Header
92.21 + * Notice in each file and include the License file at
92.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
92.23 + * particular file as subject to the "Classpath" exception as provided
92.24 + * by Oracle in the GPL Version 2 section of the License file that
92.25 + * accompanied this code. If applicable, add the following below the
92.26 + * License Header, with the fields enclosed by brackets [] replaced by
92.27 + * your own identifying information:
92.28 + * "Portions Copyrighted [year] [name of copyright owner]"
92.29 + *
92.30 + * Contributor(s):
92.31 + *
92.32 + * The Original Software is NetBeans. The Initial Developer of the Original
92.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
92.34 + *
92.35 + * If you wish your version of this file to be governed by only the CDDL
92.36 + * or only the GPL Version 2, indicate your decision by adding
92.37 + * "[Contributor] elects to include this software in this distribution
92.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
92.39 + * single choice of license, a recipient has the option to distribute
92.40 + * your version of this file under either the CDDL, the GPL Version 2 or
92.41 + * to extend the choice of license to its licensees as provided above.
92.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
92.43 + * Version 2 license, then the option applies only if the new code is
92.44 + * made subject to such option by the copyright holder.
92.45 + */
92.46 +package org.netbeans.html.json.impl;
92.47 +
92.48 +import java.io.IOException;
92.49 +import java.io.OutputStreamWriter;
92.50 +import java.io.StringWriter;
92.51 +import java.io.Writer;
92.52 +import java.lang.annotation.AnnotationTypeMismatchException;
92.53 +import java.lang.annotation.IncompleteAnnotationException;
92.54 +import java.lang.reflect.Method;
92.55 +import java.util.ArrayList;
92.56 +import java.util.Arrays;
92.57 +import java.util.Collection;
92.58 +import java.util.Collections;
92.59 +import java.util.HashMap;
92.60 +import java.util.HashSet;
92.61 +import java.util.LinkedHashSet;
92.62 +import java.util.List;
92.63 +import java.util.Map;
92.64 +import java.util.ResourceBundle;
92.65 +import java.util.Set;
92.66 +import java.util.WeakHashMap;
92.67 +import java.util.logging.Level;
92.68 +import java.util.logging.Logger;
92.69 +import javax.annotation.processing.AbstractProcessor;
92.70 +import javax.annotation.processing.Completion;
92.71 +import javax.annotation.processing.Completions;
92.72 +import javax.annotation.processing.ProcessingEnvironment;
92.73 +import javax.annotation.processing.Processor;
92.74 +import javax.annotation.processing.RoundEnvironment;
92.75 +import javax.annotation.processing.SupportedAnnotationTypes;
92.76 +import javax.annotation.processing.SupportedSourceVersion;
92.77 +import javax.lang.model.SourceVersion;
92.78 +import javax.lang.model.element.AnnotationMirror;
92.79 +import javax.lang.model.element.AnnotationValue;
92.80 +import javax.lang.model.element.Element;
92.81 +import javax.lang.model.element.ElementKind;
92.82 +import javax.lang.model.element.ExecutableElement;
92.83 +import javax.lang.model.element.Modifier;
92.84 +import javax.lang.model.element.PackageElement;
92.85 +import javax.lang.model.element.TypeElement;
92.86 +import javax.lang.model.element.VariableElement;
92.87 +import javax.lang.model.type.ArrayType;
92.88 +import javax.lang.model.type.DeclaredType;
92.89 +import javax.lang.model.type.MirroredTypeException;
92.90 +import javax.lang.model.type.TypeKind;
92.91 +import javax.lang.model.type.TypeMirror;
92.92 +import javax.lang.model.util.Elements;
92.93 +import javax.lang.model.util.Types;
92.94 +import javax.tools.Diagnostic;
92.95 +import javax.tools.FileObject;
92.96 +import net.java.html.json.ComputedProperty;
92.97 +import net.java.html.json.Model;
92.98 +import net.java.html.json.Function;
92.99 +import net.java.html.json.ModelOperation;
92.100 +import net.java.html.json.OnPropertyChange;
92.101 +import net.java.html.json.OnReceive;
92.102 +import net.java.html.json.Property;
92.103 +import org.openide.util.lookup.ServiceProvider;
92.104 +
92.105 +/** Annotation processor to process {@link Model @Model} annotations and
92.106 + * generate appropriate model classes.
92.107 + *
92.108 + * @author Jaroslav Tulach <jtulach@netbeans.org>
92.109 + */
92.110 +@ServiceProvider(service=Processor.class)
92.111 +@SupportedSourceVersion(SourceVersion.RELEASE_6)
92.112 +@SupportedAnnotationTypes({
92.113 + "net.java.html.json.Model",
92.114 + "net.java.html.json.ModelOperation",
92.115 + "net.java.html.json.Function",
92.116 + "net.java.html.json.OnReceive",
92.117 + "net.java.html.json.OnPropertyChange",
92.118 + "net.java.html.json.ComputedProperty",
92.119 + "net.java.html.json.Property"
92.120 +})
92.121 +public final class ModelProcessor extends AbstractProcessor {
92.122 + private static final Logger LOG = Logger.getLogger(ModelProcessor.class.getName());
92.123 + private final Map<Element,String> models = new WeakHashMap<Element,String>();
92.124 + private final Map<Element,Prprt[]> verify = new WeakHashMap<Element,Prprt[]>();
92.125 + @Override
92.126 + public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
92.127 + boolean ok = true;
92.128 + for (Element e : roundEnv.getElementsAnnotatedWith(Model.class)) {
92.129 + if (!processModel(e)) {
92.130 + ok = false;
92.131 + }
92.132 + }
92.133 + if (roundEnv.processingOver()) {
92.134 + models.clear();
92.135 + for (Map.Entry<Element, Prprt[]> entry : verify.entrySet()) {
92.136 + TypeElement te = (TypeElement)entry.getKey();
92.137 + String fqn = processingEnv.getElementUtils().getBinaryName(te).toString();
92.138 + Element finalElem = processingEnv.getElementUtils().getTypeElement(fqn);
92.139 + if (finalElem == null) {
92.140 + continue;
92.141 + }
92.142 + Prprt[] props;
92.143 + Model m = finalElem.getAnnotation(Model.class);
92.144 + if (m == null) {
92.145 + continue;
92.146 + }
92.147 + props = Prprt.wrap(processingEnv, finalElem, m.properties());
92.148 + for (Prprt p : props) {
92.149 + boolean[] isModel = { false };
92.150 + boolean[] isEnum = { false };
92.151 + boolean[] isPrimitive = { false };
92.152 + String t = checkType(p, isModel, isEnum, isPrimitive);
92.153 + if (isEnum[0]) {
92.154 + continue;
92.155 + }
92.156 + if (isPrimitive[0]) {
92.157 + continue;
92.158 + }
92.159 + if (isModel[0]) {
92.160 + continue;
92.161 + }
92.162 + if ("java.lang.String".equals(t)) {
92.163 + continue;
92.164 + }
92.165 + error("The type " + t + " should be defined by @Model annotation", entry.getKey());
92.166 + }
92.167 + }
92.168 + verify.clear();
92.169 + }
92.170 + return ok;
92.171 + }
92.172 +
92.173 + private void error(String msg, Element e) {
92.174 + processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, msg, e);
92.175 + }
92.176 +
92.177 + private boolean processModel(Element e) {
92.178 + boolean ok = true;
92.179 + Model m = e.getAnnotation(Model.class);
92.180 + if (m == null) {
92.181 + return true;
92.182 + }
92.183 + String pkg = findPkgName(e);
92.184 + Writer w;
92.185 + String className = m.className();
92.186 + models.put(e, className);
92.187 + try {
92.188 + StringWriter body = new StringWriter();
92.189 + List<String> propsGetSet = new ArrayList<String>();
92.190 + List<String> functions = new ArrayList<String>();
92.191 + Map<String, Collection<String>> propsDeps = new HashMap<String, Collection<String>>();
92.192 + Map<String, Collection<String>> functionDeps = new HashMap<String, Collection<String>>();
92.193 + Prprt[] props = createProps(e, m.properties());
92.194 +
92.195 + if (!generateComputedProperties(body, props, e.getEnclosedElements(), propsGetSet, propsDeps)) {
92.196 + ok = false;
92.197 + }
92.198 + if (!generateOnChange(e, propsDeps, props, className, functionDeps)) {
92.199 + ok = false;
92.200 + }
92.201 + if (!generateProperties(e, body, props, propsGetSet, propsDeps, functionDeps)) {
92.202 + ok = false;
92.203 + }
92.204 + if (!generateFunctions(e, body, className, e.getEnclosedElements(), functions)) {
92.205 + ok = false;
92.206 + }
92.207 + if (!generateReceive(e, body, className, e.getEnclosedElements(), functions)) {
92.208 + ok = false;
92.209 + }
92.210 + if (!generateOperation(e, body, className, e.getEnclosedElements())) {
92.211 + ok = false;
92.212 + }
92.213 + FileObject java = processingEnv.getFiler().createSourceFile(pkg + '.' + className, e);
92.214 + w = new OutputStreamWriter(java.openOutputStream());
92.215 + try {
92.216 + w.append("package " + pkg + ";\n");
92.217 + w.append("import net.java.html.json.*;\n");
92.218 + w.append("public final class ").append(className).append(" implements Cloneable {\n");
92.219 + w.append(" private boolean locked;\n");
92.220 + w.append(" private net.java.html.BrwsrCtx context;\n");
92.221 + w.append(" private org.netbeans.html.json.impl.Bindings[] ko = { null };\n");
92.222 + w.append(body.toString());
92.223 + w.append(" private static Class<" + inPckName(e) + "> modelFor() { return null; }\n");
92.224 + w.append(" private ").append(className).append("(net.java.html.BrwsrCtx context) {\n");
92.225 + w.append(" this.context = context;\n");
92.226 + w.append(" };\n");
92.227 + w.append(" public ").append(className).append("() {\n");
92.228 + w.append(" this(net.java.html.BrwsrCtx.findDefault(").append(className).append(".class));\n");
92.229 + for (Prprt p : props) {
92.230 + if (p.array()) {
92.231 + continue;
92.232 + }
92.233 + boolean[] isModel = {false};
92.234 + boolean[] isEnum = {false};
92.235 + boolean isPrimitive[] = {false};
92.236 + String tn = checkType(p, isModel, isEnum, isPrimitive);
92.237 + if (isModel[0]) {
92.238 + w.write(" prop_" + p.name() + " = new " + tn + "();\n");
92.239 + }
92.240 + }
92.241 + w.append(" };\n");
92.242 + if (props.length > 0) {
92.243 + w.append(" public ").append(className).append("(");
92.244 + Prprt firstArray = null;
92.245 + String sep = "";
92.246 + for (Prprt p : props) {
92.247 + if (p.array()) {
92.248 + if (firstArray == null) {
92.249 + firstArray = p;
92.250 + }
92.251 + continue;
92.252 + }
92.253 + String tn = typeName(e, p);
92.254 + w.write(sep);
92.255 + w.write(tn);
92.256 + w.write(" " + p.name());
92.257 + sep = ", ";
92.258 + }
92.259 + if (firstArray != null) {
92.260 + String tn;
92.261 + boolean[] isModel = {false};
92.262 + boolean[] isEnum = {false};
92.263 + boolean isPrimitive[] = {false};
92.264 + tn = checkType(firstArray, isModel, isEnum, isPrimitive);
92.265 + w.write(sep);
92.266 + w.write(tn);
92.267 + w.write("... " + firstArray.name());
92.268 + }
92.269 + w.append(") {\n");
92.270 + w.append(" this(net.java.html.BrwsrCtx.findDefault(").append(className).append(".class));\n");
92.271 + for (Prprt p : props) {
92.272 + if (p.array()) {
92.273 + continue;
92.274 + }
92.275 + w.write(" this.prop_" + p.name() + " = " + p.name() + ";\n");
92.276 + }
92.277 + if (firstArray != null) {
92.278 + w.write(" this.prop_" + firstArray.name() + ".init(" + firstArray.name() + ");\n");
92.279 + }
92.280 + w.append(" };\n");
92.281 + }
92.282 + w.append(" private org.netbeans.html.json.impl.Bindings intKnckt() {\n");
92.283 + w.append(" if (ko[0] != null) return ko[0];\n");
92.284 + w.append(" ko[0] = org.netbeans.html.json.impl.Bindings.apply(context, this);\n");
92.285 + {
92.286 + w.append(" org.apidesign.html.json.spi.PropertyBinding[] propArr = {\n");
92.287 + for (int i = 0; i < propsGetSet.size(); i += 5) {
92.288 + w.append(" ko[0].registerProperty(\"").append(propsGetSet.get(i)).append("\", this, new P(");
92.289 + w.append((i / 5) + "), " + (propsGetSet.get(i + 2) == null) + "),\n");
92.290 + }
92.291 + w.append(" };\n");
92.292 + }
92.293 + {
92.294 + w.append(" org.apidesign.html.json.spi.FunctionBinding[] funcArr = {\n");
92.295 + for (int i = 0; i < functions.size(); i += 2) {
92.296 + w.append(" ko[0].registerFunction(\"").append(functions.get(i)).append("\", this, new P(");
92.297 + w.append((i / 2) + ")),\n");
92.298 + }
92.299 + w.append(" };\n");
92.300 + }
92.301 + w.append(" ko[0].finish(this, propArr, funcArr);\n");
92.302 + w.append(" return ko[0];\n");
92.303 + w.append(" };\n");
92.304 + w.append(" private static final class P implements org.netbeans.html.json.impl.SetAndGet<" + className + ">,\n");
92.305 + w.append(" org.netbeans.html.json.impl.Callback<" + className + ">,\n");
92.306 + w.append(" org.netbeans.html.json.impl.FromJSON<" + className + "> {\n");
92.307 + w.append(" private final int type;\n");
92.308 + w.append(" P(int t) { type = t; };\n");
92.309 + w.append(" public void setValue(" + className + " data, Object value) {\n");
92.310 + w.append(" switch (type) {\n");
92.311 + for (int i = 0; i < propsGetSet.size(); i += 5) {
92.312 + final String set = propsGetSet.get(i + 2);
92.313 + String tn = propsGetSet.get(i + 4);
92.314 + String btn = findBoxedType(tn);
92.315 + if (btn != null) {
92.316 + tn = btn;
92.317 + }
92.318 + if (set != null) {
92.319 + w.append(" case " + (i / 5) + ": data." + strip(set) + "(org.netbeans.html.json.impl.JSON.extractValue(" + tn + ".class, value)); return;\n");
92.320 + }
92.321 + }
92.322 + w.append(" }\n");
92.323 + w.append(" }\n");
92.324 + w.append(" public Object getValue(" + className + " data) {\n");
92.325 + w.append(" switch (type) {\n");
92.326 + for (int i = 0; i < propsGetSet.size(); i += 5) {
92.327 + final String get = propsGetSet.get(i + 1);
92.328 + if (get != null) {
92.329 + w.append(" case " + (i / 5) + ": return data." + strip(get) + "();\n");
92.330 + }
92.331 + }
92.332 + w.append(" }\n");
92.333 + w.append(" throw new UnsupportedOperationException();\n");
92.334 + w.append(" }\n");
92.335 + w.append(" public void call(" + className + " model, Object data, Object ev) {\n");
92.336 + w.append(" switch (type) {\n");
92.337 + for (int i = 0; i < functions.size(); i += 2) {
92.338 + final String name = functions.get(i);
92.339 + w.append(" case " + (i / 2) + ": model." + name + "(data, ev); return;\n");
92.340 + }
92.341 + w.append(" }\n");
92.342 + w.append(" throw new UnsupportedOperationException();\n");
92.343 + w.append(" }\n");
92.344 + w.append(" public Class<" + className + "> factoryFor() { return " + className + ".class; }\n");
92.345 + w.append(" public " + className + " read(net.java.html.BrwsrCtx c, Object json) { return new " + className + "(c, json); }\n");
92.346 + w.append(" public " + className + " cloneTo(Object o, net.java.html.BrwsrCtx c) { return ((" + className + ")o).clone(c); }\n");
92.347 + w.append(" }\n");
92.348 + w.append(" static { org.netbeans.html.json.impl.JSON.register(new P(0)); }\n");
92.349 + w.append(" private ").append(className).append("(net.java.html.BrwsrCtx c, Object json) {\n");
92.350 + w.append(" this.context = c;\n");
92.351 + int values = 0;
92.352 + for (int i = 0; i < propsGetSet.size(); i += 5) {
92.353 + Prprt p = findPrprt(props, propsGetSet.get(i));
92.354 + if (p == null) {
92.355 + continue;
92.356 + }
92.357 + values++;
92.358 + }
92.359 + w.append(" Object[] ret = new Object[" + values + "];\n");
92.360 + w.append(" org.netbeans.html.json.impl.JSON.extract(context, json, new String[] {\n");
92.361 + for (int i = 0; i < propsGetSet.size(); i += 5) {
92.362 + Prprt p = findPrprt(props, propsGetSet.get(i));
92.363 + if (p == null) {
92.364 + continue;
92.365 + }
92.366 + w.append(" \"").append(propsGetSet.get(i)).append("\",\n");
92.367 + }
92.368 + w.append(" }, ret);\n");
92.369 + for (int i = 0, cnt = 0, prop = 0; i < propsGetSet.size(); i += 5) {
92.370 + final String pn = propsGetSet.get(i);
92.371 + Prprt p = findPrprt(props, pn);
92.372 + if (p == null) {
92.373 + continue;
92.374 + }
92.375 + boolean[] isModel = { false };
92.376 + boolean[] isEnum = { false };
92.377 + boolean isPrimitive[] = { false };
92.378 + String type = checkType(props[prop++], isModel, isEnum, isPrimitive);
92.379 + if (p.array()) {
92.380 + w.append(" if (ret[" + cnt + "] instanceof Object[]) {\n");
92.381 + w.append(" for (Object e : ((Object[])ret[" + cnt + "])) {\n");
92.382 + if (isModel[0]) {
92.383 + w.append(" this.prop_").append(pn).append(".add(org.netbeans.html.json.impl.JSON.read");
92.384 + w.append("(c, " + type + ".class, e));\n");
92.385 + } else if (isEnum[0]) {
92.386 + w.append(" this.prop_").append(pn);
92.387 + w.append(".add(e == null ? null : ");
92.388 + w.append(type).append(".valueOf(org.netbeans.html.json.impl.JSON.stringValue(e)));\n");
92.389 + } else {
92.390 + if (isPrimitive(type)) {
92.391 + w.append(" this.prop_").append(pn).append(".add(org.netbeans.html.json.impl.JSON.numberValue(e).");
92.392 + w.append(type).append("Value());\n");
92.393 + } else {
92.394 + w.append(" this.prop_").append(pn).append(".add((");
92.395 + w.append(type).append(")e);\n");
92.396 + }
92.397 + }
92.398 + w.append(" }\n");
92.399 + w.append(" }\n");
92.400 + } else {
92.401 + if (isEnum[0]) {
92.402 + w.append(" try {\n");
92.403 + w.append(" this.prop_").append(pn);
92.404 + w.append(" = ret[" + cnt + "] == null ? null : ");
92.405 + w.append(type).append(".valueOf(org.netbeans.html.json.impl.JSON.stringValue(ret[" + cnt + "]));\n");
92.406 + w.append(" } catch (IllegalArgumentException ex) {\n");
92.407 + w.append(" ex.printStackTrace();\n");
92.408 + w.append(" }\n");
92.409 + } else if (isPrimitive(type)) {
92.410 + w.append(" this.prop_").append(pn);
92.411 + w.append(" = ret[" + cnt + "] == null ? ");
92.412 + if ("char".equals(type)) {
92.413 + w.append("0 : (org.netbeans.html.json.impl.JSON.charValue(");
92.414 + } else if ("boolean".equals(type)) {
92.415 + w.append("false : (org.netbeans.html.json.impl.JSON.boolValue(");
92.416 + } else {
92.417 + w.append("0 : (org.netbeans.html.json.impl.JSON.numberValue(");
92.418 + }
92.419 + w.append("ret[" + cnt + "])).");
92.420 + w.append(type).append("Value();\n");
92.421 + } else if (isModel[0]) {
92.422 + w.append(" this.prop_").append(pn).append(" = org.netbeans.html.json.impl.JSON.read");
92.423 + w.append("(c, " + type + ".class, ");
92.424 + w.append("ret[" + cnt + "]);\n");
92.425 + }else {
92.426 + w.append(" this.prop_").append(pn);
92.427 + w.append(" = (").append(type).append(')');
92.428 + w.append("ret[" + cnt + "];\n");
92.429 + }
92.430 + }
92.431 + cnt++;
92.432 + }
92.433 + w.append(" };\n");
92.434 + writeToString(props, w);
92.435 + writeClone(className, props, w);
92.436 + w.write(" /** Activates this model instance in the current {@link \n"
92.437 + + "net.java.html.json.Models#bind(java.lang.Object, net.java.html.BrwsrCtx) browser context}. \n"
92.438 + + "In case of using Knockout technology, this means to \n"
92.439 + + "bind JSON like data in this model instance with Knockout tags in \n"
92.440 + + "the surrounding HTML page.\n"
92.441 + + "*/\n"
92.442 + );
92.443 + w.write(" public " + className + " applyBindings() {\n");
92.444 + w.write(" intKnckt().applyBindings();\n");
92.445 + w.write(" return this;\n");
92.446 + w.write(" }\n");
92.447 + w.write(" public boolean equals(Object o) {\n");
92.448 + w.write(" if (o == this) return true;\n");
92.449 + w.write(" if (o instanceof org.netbeans.html.json.impl.WrapperObject) {\n");
92.450 + w.write(" ((org.netbeans.html.json.impl.WrapperObject)o).setRealObject(intKnckt().koData());\n");
92.451 + w.write(" return false;\n");
92.452 + w.write(" }\n");
92.453 + w.write(" if (!(o instanceof " + className + ")) return false;\n");
92.454 + w.write(" " + className + " p = (" + className + ")o;\n");
92.455 + for (Prprt p : props) {
92.456 + w.write(" if (!org.netbeans.html.json.impl.JSON.isSame(prop_" + p.name() + ", p.prop_" + p.name() + ")) return false;\n");
92.457 + }
92.458 + w.write(" return true;\n");
92.459 + w.write(" }\n");
92.460 + w.write(" public int hashCode() {\n");
92.461 + w.write(" int h = " + className + ".class.getName().hashCode();\n");
92.462 + for (Prprt p : props) {
92.463 + w.write(" h = org.netbeans.html.json.impl.JSON.hashPlus(prop_" + p.name() + ", h);\n");
92.464 + }
92.465 + w.write(" return h;\n");
92.466 + w.write(" }\n");
92.467 + w.write("}\n");
92.468 + } finally {
92.469 + w.close();
92.470 + }
92.471 + } catch (IOException ex) {
92.472 + error("Can't create " + className + ".java", e);
92.473 + return false;
92.474 + }
92.475 + return ok;
92.476 + }
92.477 +
92.478 + private boolean generateProperties(
92.479 + Element where,
92.480 + Writer w, Prprt[] properties,
92.481 + Collection<String> props,
92.482 + Map<String,Collection<String>> deps,
92.483 + Map<String,Collection<String>> functionDeps
92.484 + ) throws IOException {
92.485 + boolean ok = true;
92.486 + for (Prprt p : properties) {
92.487 + final String tn;
92.488 + tn = typeName(where, p);
92.489 + String[] gs = toGetSet(p.name(), tn, p.array());
92.490 + String castTo;
92.491 +
92.492 + if (p.array()) {
92.493 + w.write(" private org.netbeans.html.json.impl.JSONList<" + tn + "> prop_" + p.name() + " = new org.netbeans.html.json.impl.JSONList<" + tn + ">(ko, \""
92.494 + + p.name() + "\"");
92.495 + Collection<String> dependants = deps.get(p.name());
92.496 + if (dependants != null) {
92.497 + for (String depProp : dependants) {
92.498 + w.write(", ");
92.499 + w.write('\"');
92.500 + w.write(depProp);
92.501 + w.write('\"');
92.502 + }
92.503 + }
92.504 + w.write(")");
92.505 +
92.506 + dependants = functionDeps.get(p.name());
92.507 + if (dependants != null) {
92.508 + w.write(".onChange(new Runnable() { public void run() {\n");
92.509 + for (String call : dependants) {
92.510 + w.append(" ").append(call);
92.511 + }
92.512 + w.write(" }})");
92.513 + }
92.514 + w.write(";\n");
92.515 +
92.516 + castTo = "java.util.List";
92.517 + w.write(" public java.util.List<" + tn + "> " + gs[0] + "() {\n");
92.518 + w.write(" if (locked) throw new IllegalStateException();\n");
92.519 + w.write(" return prop_" + p.name() + ";\n");
92.520 + w.write(" }\n");
92.521 + } else {
92.522 + castTo = tn;
92.523 + w.write(" private " + tn + " prop_" + p.name() + ";\n");
92.524 + w.write(" public " + tn + " " + gs[0] + "() {\n");
92.525 + w.write(" if (locked) throw new IllegalStateException();\n");
92.526 + w.write(" return prop_" + p.name() + ";\n");
92.527 + w.write(" }\n");
92.528 + w.write(" public void " + gs[1] + "(" + tn + " v) {\n");
92.529 + w.write(" if (locked) throw new IllegalStateException();\n");
92.530 + w.write(" if (org.netbeans.html.json.impl.JSON.isSame(prop_" + p.name() + ", v)) return;\n");
92.531 + w.write(" prop_" + p.name() + " = v;\n");
92.532 + w.write(" org.netbeans.html.json.impl.Bindings b = ko[0];\n");
92.533 + w.write(" if (b != null) {\n");
92.534 + w.write(" b.valueHasMutated(\"" + p.name() + "\");\n");
92.535 + Collection<String> dependants = deps.get(p.name());
92.536 + if (dependants != null) {
92.537 + for (String depProp : dependants) {
92.538 + w.write(" b.valueHasMutated(\"" + depProp + "\");\n");
92.539 + }
92.540 + }
92.541 + w.write(" }\n");
92.542 + dependants = functionDeps.get(p.name());
92.543 + if (dependants != null) {
92.544 + for (String call : dependants) {
92.545 + w.append(" ").append(call);
92.546 + }
92.547 + }
92.548 + w.write(" }\n");
92.549 + }
92.550 +
92.551 + props.add(p.name());
92.552 + props.add(gs[2]);
92.553 + props.add(gs[3]);
92.554 + props.add(gs[0]);
92.555 + props.add(castTo);
92.556 + }
92.557 + return ok;
92.558 + }
92.559 +
92.560 + private boolean generateComputedProperties(
92.561 + Writer w, Prprt[] fixedProps,
92.562 + Collection<? extends Element> arr, Collection<String> props,
92.563 + Map<String,Collection<String>> deps
92.564 + ) throws IOException {
92.565 + boolean ok = true;
92.566 + for (Element e : arr) {
92.567 + if (e.getKind() != ElementKind.METHOD) {
92.568 + continue;
92.569 + }
92.570 + if (e.getAnnotation(ComputedProperty.class) == null) {
92.571 + continue;
92.572 + }
92.573 + if (!e.getModifiers().contains(Modifier.STATIC)) {
92.574 + error("Method " + e.getSimpleName() + " has to be static when annotated by @ComputedProperty", e);
92.575 + ok = false;
92.576 + continue;
92.577 + }
92.578 + ExecutableElement ee = (ExecutableElement)e;
92.579 + final TypeMirror rt = ee.getReturnType();
92.580 + final Types tu = processingEnv.getTypeUtils();
92.581 + TypeMirror ert = tu.erasure(rt);
92.582 + String tn = fqn(ert, ee);
92.583 + boolean array = false;
92.584 + final TypeMirror toCheck;
92.585 + if (tn.equals("java.util.List")) {
92.586 + array = true;
92.587 + toCheck = ((DeclaredType)rt).getTypeArguments().get(0);
92.588 + } else {
92.589 + toCheck = rt;
92.590 + }
92.591 +
92.592 + final String sn = ee.getSimpleName().toString();
92.593 +
92.594 + if (toCheck.getKind().isPrimitive()) {
92.595 + // OK
92.596 + } else {
92.597 + TypeMirror stringType = processingEnv.getElementUtils().getTypeElement("java.lang.String").asType();
92.598 + TypeMirror enumType = processingEnv.getElementUtils().getTypeElement("java.lang.Enum").asType();
92.599 +
92.600 + if (tu.isSubtype(toCheck, stringType)) {
92.601 + // OK
92.602 + } else if (tu.isSubtype(tu.erasure(toCheck), tu.erasure(enumType))) {
92.603 + // OK
92.604 + } else if (isModel(toCheck)) {
92.605 + // OK
92.606 + } else {
92.607 + ok = false;
92.608 + error(sn + " cannot return " + toCheck, e);
92.609 + }
92.610 + }
92.611 +
92.612 + String[] gs = toGetSet(sn, tn, array);
92.613 +
92.614 + w.write(" public " + tn + " " + gs[0] + "() {\n");
92.615 + w.write(" if (locked) throw new IllegalStateException();\n");
92.616 + int arg = 0;
92.617 + for (VariableElement pe : ee.getParameters()) {
92.618 + final String dn = pe.getSimpleName().toString();
92.619 +
92.620 + if (!verifyPropName(pe, dn, fixedProps)) {
92.621 + ok = false;
92.622 + }
92.623 +
92.624 + final String dt = fqn(pe.asType(), ee);
92.625 + String[] call = toGetSet(dn, dt, false);
92.626 + w.write(" " + dt + " arg" + (++arg) + " = ");
92.627 + w.write(call[0] + "();\n");
92.628 +
92.629 + Collection<String> depends = deps.get(dn);
92.630 + if (depends == null) {
92.631 + depends = new LinkedHashSet<String>();
92.632 + deps.put(dn, depends);
92.633 + }
92.634 + depends.add(sn);
92.635 + }
92.636 + w.write(" try {\n");
92.637 + w.write(" locked = true;\n");
92.638 + w.write(" return " + fqn(ee.getEnclosingElement().asType(), ee) + '.' + e.getSimpleName() + "(");
92.639 + String sep = "";
92.640 + for (int i = 1; i <= arg; i++) {
92.641 + w.write(sep);
92.642 + w.write("arg" + i);
92.643 + sep = ", ";
92.644 + }
92.645 + w.write(");\n");
92.646 + w.write(" } finally {\n");
92.647 + w.write(" locked = false;\n");
92.648 + w.write(" }\n");
92.649 + w.write(" }\n");
92.650 +
92.651 + props.add(e.getSimpleName().toString());
92.652 + props.add(gs[2]);
92.653 + props.add(null);
92.654 + props.add(gs[0]);
92.655 + props.add(tn);
92.656 + }
92.657 +
92.658 + return ok;
92.659 + }
92.660 +
92.661 + private static String[] toGetSet(String name, String type, boolean array) {
92.662 + String n = Character.toUpperCase(name.charAt(0)) + name.substring(1);
92.663 + String bck2brwsrType = "L" + type.replace('.', '_') + "_2";
92.664 + if ("int".equals(type)) {
92.665 + bck2brwsrType = "I";
92.666 + }
92.667 + if ("double".equals(type)) {
92.668 + bck2brwsrType = "D";
92.669 + }
92.670 + String pref = "get";
92.671 + if ("boolean".equals(type)) {
92.672 + pref = "is";
92.673 + bck2brwsrType = "Z";
92.674 + }
92.675 + final String nu = n.replace('.', '_');
92.676 + if (array) {
92.677 + return new String[] {
92.678 + "get" + n,
92.679 + null,
92.680 + "get" + nu + "__Ljava_util_List_2",
92.681 + null
92.682 + };
92.683 + }
92.684 + return new String[]{
92.685 + pref + n,
92.686 + "set" + n,
92.687 + pref + nu + "__" + bck2brwsrType,
92.688 + "set" + nu + "__V" + bck2brwsrType
92.689 + };
92.690 + }
92.691 +
92.692 + private String typeName(Element where, Prprt p) {
92.693 + String ret;
92.694 + boolean[] isModel = { false };
92.695 + boolean[] isEnum = { false };
92.696 + boolean isPrimitive[] = { false };
92.697 + ret = checkType(p, isModel, isEnum, isPrimitive);
92.698 + if (p.array()) {
92.699 + String bt = findBoxedType(ret);
92.700 + if (bt != null) {
92.701 + return bt;
92.702 + }
92.703 + }
92.704 + return ret;
92.705 + }
92.706 +
92.707 + private static String findBoxedType(String ret) {
92.708 + if (ret.equals("boolean")) {
92.709 + return Boolean.class.getName();
92.710 + }
92.711 + if (ret.equals("byte")) {
92.712 + return Byte.class.getName();
92.713 + }
92.714 + if (ret.equals("short")) {
92.715 + return Short.class.getName();
92.716 + }
92.717 + if (ret.equals("char")) {
92.718 + return Character.class.getName();
92.719 + }
92.720 + if (ret.equals("int")) {
92.721 + return Integer.class.getName();
92.722 + }
92.723 + if (ret.equals("long")) {
92.724 + return Long.class.getName();
92.725 + }
92.726 + if (ret.equals("float")) {
92.727 + return Float.class.getName();
92.728 + }
92.729 + if (ret.equals("double")) {
92.730 + return Double.class.getName();
92.731 + }
92.732 + return null;
92.733 + }
92.734 +
92.735 + private boolean verifyPropName(Element e, String propName, Prprt[] existingProps) {
92.736 + StringBuilder sb = new StringBuilder();
92.737 + String sep = "";
92.738 + for (Prprt Prprt : existingProps) {
92.739 + if (Prprt.name().equals(propName)) {
92.740 + return true;
92.741 + }
92.742 + sb.append(sep);
92.743 + sb.append('"');
92.744 + sb.append(Prprt.name());
92.745 + sb.append('"');
92.746 + sep = ", ";
92.747 + }
92.748 + error(
92.749 + propName + " is not one of known properties: " + sb
92.750 + , e
92.751 + );
92.752 + return false;
92.753 + }
92.754 +
92.755 + private static String findPkgName(Element e) {
92.756 + for (;;) {
92.757 + if (e.getKind() == ElementKind.PACKAGE) {
92.758 + return ((PackageElement)e).getQualifiedName().toString();
92.759 + }
92.760 + e = e.getEnclosingElement();
92.761 + }
92.762 + }
92.763 +
92.764 + private boolean generateFunctions(
92.765 + Element clazz, StringWriter body, String className,
92.766 + List<? extends Element> enclosedElements, List<String> functions
92.767 + ) {
92.768 + for (Element m : enclosedElements) {
92.769 + if (m.getKind() != ElementKind.METHOD) {
92.770 + continue;
92.771 + }
92.772 + ExecutableElement e = (ExecutableElement)m;
92.773 + Function onF = e.getAnnotation(Function.class);
92.774 + if (onF == null) {
92.775 + continue;
92.776 + }
92.777 + if (!e.getModifiers().contains(Modifier.STATIC)) {
92.778 + error("@OnFunction method needs to be static", e);
92.779 + return false;
92.780 + }
92.781 + if (e.getModifiers().contains(Modifier.PRIVATE)) {
92.782 + error("@OnFunction method cannot be private", e);
92.783 + return false;
92.784 + }
92.785 + if (e.getReturnType().getKind() != TypeKind.VOID) {
92.786 + error("@OnFunction method should return void", e);
92.787 + return false;
92.788 + }
92.789 + String n = e.getSimpleName().toString();
92.790 + body.append(" private void ").append(n).append("(Object data, Object ev) {\n");
92.791 + body.append(" ").append(((TypeElement)clazz).getQualifiedName()).append(".").append(n).append("(");
92.792 + body.append(wrapParams(e, null, className, "ev", "data"));
92.793 + body.append(");\n");
92.794 + body.append(" }\n");
92.795 +
92.796 + functions.add(n);
92.797 + functions.add(n + "__VLjava_lang_Object_2Ljava_lang_Object_2");
92.798 + }
92.799 + return true;
92.800 + }
92.801 +
92.802 + private boolean generateOnChange(Element clazz, Map<String,Collection<String>> propDeps,
92.803 + Prprt[] properties, String className,
92.804 + Map<String, Collection<String>> functionDeps
92.805 + ) {
92.806 + for (Element m : clazz.getEnclosedElements()) {
92.807 + if (m.getKind() != ElementKind.METHOD) {
92.808 + continue;
92.809 + }
92.810 + ExecutableElement e = (ExecutableElement) m;
92.811 + OnPropertyChange onPC = e.getAnnotation(OnPropertyChange.class);
92.812 + if (onPC == null) {
92.813 + continue;
92.814 + }
92.815 + for (String pn : onPC.value()) {
92.816 + if (findPrprt(properties, pn) == null && findDerivedFrom(propDeps, pn).isEmpty()) {
92.817 + error("No Prprt named '" + pn + "' in the model", clazz);
92.818 + return false;
92.819 + }
92.820 + }
92.821 + if (!e.getModifiers().contains(Modifier.STATIC)) {
92.822 + error("@OnPrprtChange method needs to be static", e);
92.823 + return false;
92.824 + }
92.825 + if (e.getModifiers().contains(Modifier.PRIVATE)) {
92.826 + error("@OnPrprtChange method cannot be private", e);
92.827 + return false;
92.828 + }
92.829 + if (e.getReturnType().getKind() != TypeKind.VOID) {
92.830 + error("@OnPrprtChange method should return void", e);
92.831 + return false;
92.832 + }
92.833 + String n = e.getSimpleName().toString();
92.834 +
92.835 +
92.836 + for (String pn : onPC.value()) {
92.837 + StringBuilder call = new StringBuilder();
92.838 + call.append(" ").append(clazz.getSimpleName()).append(".").append(n).append("(");
92.839 + call.append(wrapPropName(e, className, "name", pn));
92.840 + call.append(");\n");
92.841 +
92.842 + Collection<String> change = functionDeps.get(pn);
92.843 + if (change == null) {
92.844 + change = new ArrayList<String>();
92.845 + functionDeps.put(pn, change);
92.846 + }
92.847 + change.add(call.toString());
92.848 + for (String dpn : findDerivedFrom(propDeps, pn)) {
92.849 + change = functionDeps.get(dpn);
92.850 + if (change == null) {
92.851 + change = new ArrayList<String>();
92.852 + functionDeps.put(dpn, change);
92.853 + }
92.854 + change.add(call.toString());
92.855 + }
92.856 + }
92.857 + }
92.858 + return true;
92.859 + }
92.860 +
92.861 + private boolean generateOperation(Element clazz,
92.862 + StringWriter body, String className,
92.863 + List<? extends Element> enclosedElements
92.864 + ) {
92.865 + for (Element m : enclosedElements) {
92.866 + if (m.getKind() != ElementKind.METHOD) {
92.867 + continue;
92.868 + }
92.869 + ExecutableElement e = (ExecutableElement)m;
92.870 + ModelOperation mO = e.getAnnotation(ModelOperation.class);
92.871 + if (mO == null) {
92.872 + continue;
92.873 + }
92.874 + if (!e.getModifiers().contains(Modifier.STATIC)) {
92.875 + error("@ModelOperation method needs to be static", e);
92.876 + return false;
92.877 + }
92.878 + if (e.getModifiers().contains(Modifier.PRIVATE)) {
92.879 + error("@ModelOperation method cannot be private", e);
92.880 + return false;
92.881 + }
92.882 + if (e.getReturnType().getKind() != TypeKind.VOID) {
92.883 + error("@ModelOperation method should return void", e);
92.884 + return false;
92.885 + }
92.886 + List<String> args = new ArrayList<String>();
92.887 + {
92.888 + body.append(" public void ").append(m.getSimpleName()).append("(");
92.889 + String sep = "";
92.890 + boolean checkFirst = true;
92.891 + for (VariableElement ve : e.getParameters()) {
92.892 + final TypeMirror type = ve.asType();
92.893 + CharSequence simpleName;
92.894 + if (type.getKind() == TypeKind.DECLARED) {
92.895 + simpleName = ((DeclaredType)type).asElement().getSimpleName();
92.896 + } else {
92.897 + simpleName = type.toString();
92.898 + }
92.899 + if (simpleName.toString().equals(className)) {
92.900 + checkFirst = false;
92.901 + } else {
92.902 + if (checkFirst) {
92.903 + error("First parameter of @ModelOperation method must be " + className, m);
92.904 + return false;
92.905 + }
92.906 + args.add(ve.getSimpleName().toString());
92.907 + body.append(sep).append("final ");
92.908 + body.append(ve.asType().toString()).append(" ");
92.909 + body.append(ve.toString());
92.910 + sep = ", ";
92.911 + }
92.912 + }
92.913 + body.append(") {\n");
92.914 + body.append(" org.netbeans.html.json.impl.JSON.runInBrowser(this.context, new Runnable() { public void run() {\n");
92.915 + body.append(" ").append(clazz.getSimpleName()).append(".").append(m.getSimpleName()).append("(");
92.916 + body.append(className).append(".this");
92.917 + for (String s : args) {
92.918 + body.append(", ").append(s);
92.919 + }
92.920 + body.append(");\n");
92.921 + body.append(" }});\n");
92.922 + body.append(" }\n");
92.923 + }
92.924 +
92.925 + }
92.926 + return true;
92.927 + }
92.928 +
92.929 +
92.930 + private boolean generateReceive(
92.931 + Element clazz, StringWriter body, String className,
92.932 + List<? extends Element> enclosedElements, List<String> functions
92.933 + ) {
92.934 + for (Element m : enclosedElements) {
92.935 + if (m.getKind() != ElementKind.METHOD) {
92.936 + continue;
92.937 + }
92.938 + ExecutableElement e = (ExecutableElement)m;
92.939 + OnReceive onR = e.getAnnotation(OnReceive.class);
92.940 + if (onR == null) {
92.941 + continue;
92.942 + }
92.943 + if (!e.getModifiers().contains(Modifier.STATIC)) {
92.944 + error("@OnReceive method needs to be static", e);
92.945 + return false;
92.946 + }
92.947 + if (e.getModifiers().contains(Modifier.PRIVATE)) {
92.948 + error("@OnReceive method cannot be private", e);
92.949 + return false;
92.950 + }
92.951 + if (e.getReturnType().getKind() != TypeKind.VOID) {
92.952 + error("@OnReceive method should return void", e);
92.953 + return false;
92.954 + }
92.955 + if (!onR.jsonp().isEmpty() && !"GET".equals(onR.method())) {
92.956 + error("JSONP works only with GET transport method", e);
92.957 + }
92.958 + String dataMirror = findDataSpecified(e, onR);
92.959 + if ("PUT".equals(onR.method()) && dataMirror == null) {
92.960 + error("PUT method needs to specify a data() class", e);
92.961 + return false;
92.962 + }
92.963 + if ("POST".equals(onR.method()) && dataMirror == null) {
92.964 + error("POST method needs to specify a data() class", e);
92.965 + return false;
92.966 + }
92.967 + String modelClass = null;
92.968 + boolean expectsList = false;
92.969 + List<String> args = new ArrayList<String>();
92.970 + {
92.971 + for (VariableElement ve : e.getParameters()) {
92.972 + TypeMirror modelType = null;
92.973 + final TypeMirror type = ve.asType();
92.974 + CharSequence simpleName;
92.975 + if (type.getKind() == TypeKind.DECLARED) {
92.976 + simpleName = ((DeclaredType)type).asElement().getSimpleName();
92.977 + } else {
92.978 + simpleName = type.toString();
92.979 + }
92.980 + if (simpleName.toString().equals(className)) {
92.981 + args.add(className + ".this");
92.982 + } else if (isModel(ve.asType())) {
92.983 + modelType = ve.asType();
92.984 + } else if (ve.asType().getKind() == TypeKind.ARRAY) {
92.985 + modelType = ((ArrayType)ve.asType()).getComponentType();
92.986 + expectsList = true;
92.987 + } else if (ve.asType().toString().equals("java.lang.String")) {
92.988 + modelType = ve.asType();
92.989 + }
92.990 + if (modelType != null) {
92.991 + if (modelClass != null) {
92.992 + error("There can be only one model class among arguments", e);
92.993 + } else {
92.994 + modelClass = modelType.toString();
92.995 + if (expectsList) {
92.996 + args.add("arr");
92.997 + } else {
92.998 + args.add("arr[0]");
92.999 + }
92.1000 + }
92.1001 + }
92.1002 + }
92.1003 + }
92.1004 + if (modelClass == null) {
92.1005 + error("The method needs to have one @Model class as parameter", e);
92.1006 + }
92.1007 + String n = e.getSimpleName().toString();
92.1008 + if ("WebSocket".equals(onR.method())) {
92.1009 + body.append(" /** Performs WebSocket communication. Call with <code>null</code> data parameter\n");
92.1010 + body.append(" * to open the connection (even if not required). Call with non-null data to\n");
92.1011 + body.append(" * send messages to server. Call again with <code>null</code> data to close the socket.\n");
92.1012 + body.append(" */\n");
92.1013 + }
92.1014 + body.append(" public void ").append(n).append("(");
92.1015 + StringBuilder urlBefore = new StringBuilder();
92.1016 + StringBuilder urlAfter = new StringBuilder();
92.1017 + String jsonpVarName = null;
92.1018 + {
92.1019 + String sep = "";
92.1020 + boolean skipJSONP = onR.jsonp().isEmpty();
92.1021 + for (String p : findParamNames(e, onR.url(), onR.jsonp(), urlBefore, urlAfter)) {
92.1022 + if (!skipJSONP && p.equals(onR.jsonp())) {
92.1023 + skipJSONP = true;
92.1024 + jsonpVarName = p;
92.1025 + continue;
92.1026 + }
92.1027 + body.append(sep);
92.1028 + body.append("String ").append(p);
92.1029 + sep = ", ";
92.1030 + }
92.1031 + if (!skipJSONP) {
92.1032 + error(
92.1033 + "Name of jsonp attribute ('" + onR.jsonp() +
92.1034 + "') is not used in url attribute '" + onR.url() + "'", e
92.1035 + );
92.1036 + }
92.1037 + if (dataMirror != null) {
92.1038 + body.append(sep).append(dataMirror.toString()).append(" data");
92.1039 + }
92.1040 + }
92.1041 + body.append(") {\n");
92.1042 + boolean webSocket = onR.method().equals("WebSocket");
92.1043 + if (webSocket) {
92.1044 + if (generateWSReceiveBody(body, onR, e, clazz, className, expectsList, modelClass, n, args, urlBefore, jsonpVarName, urlAfter, dataMirror)) {
92.1045 + return false;
92.1046 + }
92.1047 + body.append(" }\n");
92.1048 + body.append(" private org.netbeans.html.json.impl.JSON.WS ws_" + e.getSimpleName() + ";\n");
92.1049 + } else {
92.1050 + if (generateJSONReceiveBody(body, onR, e, clazz, className, expectsList, modelClass, n, args, urlBefore, jsonpVarName, urlAfter, dataMirror)) {
92.1051 + return false;
92.1052 + }
92.1053 + body.append(" }\n");
92.1054 + }
92.1055 + }
92.1056 + return true;
92.1057 + }
92.1058 +
92.1059 + private boolean generateJSONReceiveBody(StringWriter body, OnReceive onR, ExecutableElement e, Element clazz, String className, boolean expectsList, String modelClass, String n, List<String> args, StringBuilder urlBefore, String jsonpVarName, StringBuilder urlAfter, String dataMirror) {
92.1060 + body.append(
92.1061 + " class ProcessResult extends org.netbeans.html.json.impl.RcvrJSON {\n" +
92.1062 + " @Override\n" +
92.1063 + " public void onError(org.netbeans.html.json.impl.RcvrJSON.MsgEvnt ev) {\n" +
92.1064 + " Exception value = ev.getException();\n"
92.1065 + );
92.1066 + if (onR.onError().isEmpty()) {
92.1067 + body.append(
92.1068 + " value.printStackTrace();\n"
92.1069 + );
92.1070 + } else {
92.1071 + if (!findOnError(e, ((TypeElement)clazz), onR.onError(), className)) {
92.1072 + return true;
92.1073 + }
92.1074 + body.append(" ").append(clazz.getSimpleName()).append(".").append(onR.onError()).append("(");
92.1075 + body.append(className).append(".this, value);\n");
92.1076 + }
92.1077 + body.append(
92.1078 + " }\n" +
92.1079 + " @Override\n" +
92.1080 + " public void onMessage(org.netbeans.html.json.impl.RcvrJSON.MsgEvnt ev) {\n"
92.1081 + );
92.1082 + if (expectsList) {
92.1083 + body.append(
92.1084 + " " + modelClass + "[] arr = new " + modelClass + "[ev.dataSize()];\n"
92.1085 + );
92.1086 + } else {
92.1087 + body.append(
92.1088 + " " + modelClass + "[] arr = { null };\n"
92.1089 + );
92.1090 + }
92.1091 + body.append(
92.1092 + " ev.dataRead(context, " + modelClass + ".class, arr);\n"
92.1093 + );
92.1094 + {
92.1095 + body.append(" ").append(clazz.getSimpleName()).append(".").append(n).append("(");
92.1096 + String sep = "";
92.1097 + for (String arg : args) {
92.1098 + body.append(sep);
92.1099 + body.append(arg);
92.1100 + sep = ", ";
92.1101 + }
92.1102 + body.append(");\n");
92.1103 + }
92.1104 + body.append(
92.1105 + " }\n" +
92.1106 + " }\n"
92.1107 + );
92.1108 + body.append(" ProcessResult pr = new ProcessResult();\n");
92.1109 + body.append(" org.netbeans.html.json.impl.JSON.loadJSON(context, pr,\n ");
92.1110 + body.append(urlBefore).append(", ");
92.1111 + if (jsonpVarName != null) {
92.1112 + body.append(urlAfter);
92.1113 + } else {
92.1114 + body.append("null");
92.1115 + }
92.1116 + if (!"GET".equals(onR.method()) || dataMirror != null) {
92.1117 + body.append(", \"").append(onR.method()).append('"');
92.1118 + if (dataMirror != null) {
92.1119 + body.append(", data");
92.1120 + } else {
92.1121 + body.append(", null");
92.1122 + }
92.1123 + } else {
92.1124 + body.append(", null, null");
92.1125 + }
92.1126 + body.append(");\n");
92.1127 + return false;
92.1128 + }
92.1129 +
92.1130 + private boolean generateWSReceiveBody(StringWriter body, OnReceive onR, ExecutableElement e, Element clazz, String className, boolean expectsList, String modelClass, String n, List<String> args, StringBuilder urlBefore, String jsonpVarName, StringBuilder urlAfter, String dataMirror) {
92.1131 + body.append(
92.1132 + " class ProcessResult extends org.netbeans.html.json.impl.RcvrJSON {\n" +
92.1133 + " @Override\n" +
92.1134 + " public void onOpen(org.netbeans.html.json.impl.RcvrJSON.MsgEvnt ev) {\n"
92.1135 + );
92.1136 + body.append(" ").append(clazz.getSimpleName()).append(".").append(n).append("(");
92.1137 + {
92.1138 + String sep = "";
92.1139 + for (String arg : args) {
92.1140 + body.append(sep);
92.1141 + if (arg.startsWith("arr")) {
92.1142 + body.append("null");
92.1143 + } else {
92.1144 + body.append(arg);
92.1145 + }
92.1146 + sep = ", ";
92.1147 + }
92.1148 + }
92.1149 + body.append(");\n");
92.1150 + body.append(
92.1151 + " }\n" +
92.1152 + " @Override\n" +
92.1153 + " public void onError(org.netbeans.html.json.impl.RcvrJSON.MsgEvnt ev) {\n" +
92.1154 + " Exception value = ev.getException();\n"
92.1155 + );
92.1156 + if (onR.onError().isEmpty()) {
92.1157 + body.append(
92.1158 + " value.printStackTrace();\n"
92.1159 + );
92.1160 + } else {
92.1161 + if (!findOnError(e, ((TypeElement)clazz), onR.onError(), className)) {
92.1162 + return true;
92.1163 + }
92.1164 + body.append(" ").append(clazz.getSimpleName()).append(".").append(onR.onError()).append("(");
92.1165 + body.append(className).append(".this, value);\n");
92.1166 + }
92.1167 + body.append(
92.1168 + " }\n" +
92.1169 + " @Override\n" +
92.1170 + " public void onMessage(org.netbeans.html.json.impl.RcvrJSON.MsgEvnt ev) {\n"
92.1171 + );
92.1172 + if (expectsList) {
92.1173 + body.append(
92.1174 + " " + modelClass + "[] arr = new " + modelClass + "[ev.dataSize()];\n"
92.1175 + );
92.1176 + } else {
92.1177 + body.append(
92.1178 + " " + modelClass + "[] arr = { null };\n"
92.1179 + );
92.1180 + }
92.1181 + body.append(
92.1182 + " ev.dataRead(context, " + modelClass + ".class, arr);\n"
92.1183 + );
92.1184 + {
92.1185 + body.append(" ").append(clazz.getSimpleName()).append(".").append(n).append("(");
92.1186 + String sep = "";
92.1187 + for (String arg : args) {
92.1188 + body.append(sep);
92.1189 + body.append(arg);
92.1190 + sep = ", ";
92.1191 + }
92.1192 + body.append(");\n");
92.1193 + }
92.1194 + body.append(
92.1195 + " }\n"
92.1196 + );
92.1197 + if (!onR.onError().isEmpty()) {
92.1198 + body.append(
92.1199 + " @Override\n"
92.1200 + + " public void onClose(org.netbeans.html.json.impl.RcvrJSON.MsgEvnt ev) {\n"
92.1201 + );
92.1202 + body.append(" ").append(clazz.getSimpleName()).append(".").append(onR.onError()).append("(");
92.1203 + body.append(className).append(".this, null);\n");
92.1204 + body.append(
92.1205 + " }\n"
92.1206 + );
92.1207 + }
92.1208 + body.append(" }\n");
92.1209 + body.append(" if (this.ws_").append(e.getSimpleName()).append(" == null) {\n");
92.1210 + body.append(" ProcessResult pr = new ProcessResult();\n");
92.1211 + body.append(" this.ws_").append(e.getSimpleName());
92.1212 + body.append("= org.netbeans.html.json.impl.JSON.openWS(context, pr,\n ");
92.1213 + body.append(urlBefore).append(", data);\n");
92.1214 + body.append(" } else {\n");
92.1215 + body.append(" this.ws_").append(e.getSimpleName()).append(".send(context, ").append(urlBefore).append(", data);\n");
92.1216 + body.append(" }\n");
92.1217 + return false;
92.1218 + }
92.1219 +
92.1220 + private CharSequence wrapParams(
92.1221 + ExecutableElement ee, String id, String className, String evName, String dataName
92.1222 + ) {
92.1223 + TypeMirror stringType = processingEnv.getElementUtils().getTypeElement("java.lang.String").asType();
92.1224 + StringBuilder params = new StringBuilder();
92.1225 + boolean first = true;
92.1226 + for (VariableElement ve : ee.getParameters()) {
92.1227 + if (!first) {
92.1228 + params.append(", ");
92.1229 + }
92.1230 + first = false;
92.1231 + String toCall = null;
92.1232 + String toFinish = null;
92.1233 + if (ve.asType() == stringType) {
92.1234 + if (ve.getSimpleName().contentEquals("id")) {
92.1235 + params.append('"').append(id).append('"');
92.1236 + continue;
92.1237 + }
92.1238 + toCall = "org.netbeans.html.json.impl.JSON.toString(context, ";
92.1239 + }
92.1240 + if (ve.asType().getKind() == TypeKind.DOUBLE) {
92.1241 + toCall = "org.netbeans.html.json.impl.JSON.toNumber(context, ";
92.1242 + toFinish = ".doubleValue()";
92.1243 + }
92.1244 + if (ve.asType().getKind() == TypeKind.INT) {
92.1245 + toCall = "org.netbeans.html.json.impl.JSON.toNumber(context, ";
92.1246 + toFinish = ".intValue()";
92.1247 + }
92.1248 + if (dataName != null && ve.getSimpleName().contentEquals(dataName) && isModel(ve.asType())) {
92.1249 + toCall = "org.netbeans.html.json.impl.JSON.toModel(context, " + ve.asType() + ".class, ";
92.1250 + }
92.1251 +
92.1252 + if (toCall != null) {
92.1253 + params.append(toCall);
92.1254 + if (dataName != null && ve.getSimpleName().contentEquals(dataName)) {
92.1255 + params.append(dataName);
92.1256 + params.append(", null");
92.1257 + } else {
92.1258 + if (evName == null) {
92.1259 + final StringBuilder sb = new StringBuilder();
92.1260 + sb.append("Unexpected string parameter name.");
92.1261 + if (dataName != null) {
92.1262 + sb.append(" Try \"").append(dataName).append("\"");
92.1263 + }
92.1264 + error(sb.toString(), ee);
92.1265 + }
92.1266 + params.append(evName);
92.1267 + params.append(", \"");
92.1268 + params.append(ve.getSimpleName().toString());
92.1269 + params.append("\"");
92.1270 + }
92.1271 + params.append(")");
92.1272 + if (toFinish != null) {
92.1273 + params.append(toFinish);
92.1274 + }
92.1275 + continue;
92.1276 + }
92.1277 + String rn = fqn(ve.asType(), ee);
92.1278 + int last = rn.lastIndexOf('.');
92.1279 + if (last >= 0) {
92.1280 + rn = rn.substring(last + 1);
92.1281 + }
92.1282 + if (rn.equals(className)) {
92.1283 + params.append(className).append(".this");
92.1284 + continue;
92.1285 + }
92.1286 + error(
92.1287 + "The annotated method can only accept " + className + " argument or argument named 'data'",
92.1288 + ee
92.1289 + );
92.1290 + }
92.1291 + return params;
92.1292 + }
92.1293 +
92.1294 +
92.1295 + private CharSequence wrapPropName(
92.1296 + ExecutableElement ee, String className, String propName, String propValue
92.1297 + ) {
92.1298 + TypeMirror stringType = processingEnv.getElementUtils().getTypeElement("java.lang.String").asType();
92.1299 + StringBuilder params = new StringBuilder();
92.1300 + boolean first = true;
92.1301 + for (VariableElement ve : ee.getParameters()) {
92.1302 + if (!first) {
92.1303 + params.append(", ");
92.1304 + }
92.1305 + first = false;
92.1306 + if (ve.asType() == stringType) {
92.1307 + if (propName != null && ve.getSimpleName().contentEquals(propName)) {
92.1308 + params.append('"').append(propValue).append('"');
92.1309 + } else {
92.1310 + error("Unexpected string parameter name. Try \"" + propName + "\".", ee);
92.1311 + }
92.1312 + continue;
92.1313 + }
92.1314 + String rn = fqn(ve.asType(), ee);
92.1315 + int last = rn.lastIndexOf('.');
92.1316 + if (last >= 0) {
92.1317 + rn = rn.substring(last + 1);
92.1318 + }
92.1319 + if (rn.equals(className)) {
92.1320 + params.append(className).append(".this");
92.1321 + continue;
92.1322 + }
92.1323 + error(
92.1324 + "@OnPrprtChange method can only accept String or " + className + " arguments",
92.1325 + ee);
92.1326 + }
92.1327 + return params;
92.1328 + }
92.1329 +
92.1330 + private boolean isModel(TypeMirror tm) {
92.1331 + if (tm.getKind() == TypeKind.ERROR) {
92.1332 + return true;
92.1333 + }
92.1334 + final Element e = processingEnv.getTypeUtils().asElement(tm);
92.1335 + if (e == null) {
92.1336 + return false;
92.1337 + }
92.1338 + for (Element ch : e.getEnclosedElements()) {
92.1339 + if (ch.getKind() == ElementKind.METHOD) {
92.1340 + ExecutableElement ee = (ExecutableElement)ch;
92.1341 + if (ee.getParameters().isEmpty() && ee.getSimpleName().contentEquals("modelFor")) {
92.1342 + return true;
92.1343 + }
92.1344 + }
92.1345 + }
92.1346 + return models.values().contains(e.getSimpleName().toString());
92.1347 + }
92.1348 +
92.1349 + private void writeToString(Prprt[] props, Writer w) throws IOException {
92.1350 + w.write(" public String toString() {\n");
92.1351 + w.write(" StringBuilder sb = new StringBuilder();\n");
92.1352 + w.write(" sb.append('{');\n");
92.1353 + String sep = "";
92.1354 + for (Prprt p : props) {
92.1355 + w.write(sep);
92.1356 + w.append(" sb.append('\"').append(\"" + p.name() + "\")");
92.1357 + w.append(".append('\"').append(\":\");\n");
92.1358 + w.append(" sb.append(org.netbeans.html.json.impl.JSON.toJSON(prop_");
92.1359 + w.append(p.name()).append("));\n");
92.1360 + sep = " sb.append(',');\n";
92.1361 + }
92.1362 + w.write(" sb.append('}');\n");
92.1363 + w.write(" return sb.toString();\n");
92.1364 + w.write(" }\n");
92.1365 + }
92.1366 + private void writeClone(String className, Prprt[] props, Writer w) throws IOException {
92.1367 + w.write(" public " + className + " clone() {\n");
92.1368 + w.write(" return clone(context);\n");
92.1369 + w.write(" }\n");
92.1370 + w.write(" private " + className + " clone(net.java.html.BrwsrCtx ctx) {\n");
92.1371 + w.write(" " + className + " ret = new " + className + "(ctx);\n");
92.1372 + for (Prprt p : props) {
92.1373 + if (!p.array()) {
92.1374 + boolean isModel[] = { false };
92.1375 + boolean isEnum[] = { false };
92.1376 + boolean isPrimitive[] = { false };
92.1377 + checkType(p, isModel, isEnum, isPrimitive);
92.1378 + if (!isModel[0]) {
92.1379 + w.write(" ret.prop_" + p.name() + " = prop_" + p.name() + ";\n");
92.1380 + continue;
92.1381 + }
92.1382 + w.write(" ret.prop_" + p.name() + " = prop_" + p.name() + " == null ? null : prop_" + p.name() + ".clone();\n");
92.1383 + } else {
92.1384 + w.write(" ret.prop_" + p.name() + ".cloneAll(ctx, prop_" + p.name() + ");\n");
92.1385 + }
92.1386 + }
92.1387 +
92.1388 + w.write(" return ret;\n");
92.1389 + w.write(" }\n");
92.1390 + }
92.1391 +
92.1392 + private String inPckName(Element e) {
92.1393 + StringBuilder sb = new StringBuilder();
92.1394 + while (e.getKind() != ElementKind.PACKAGE) {
92.1395 + if (sb.length() == 0) {
92.1396 + sb.append(e.getSimpleName());
92.1397 + } else {
92.1398 + sb.insert(0, '.');
92.1399 + sb.insert(0, e.getSimpleName());
92.1400 + }
92.1401 + e = e.getEnclosingElement();
92.1402 + }
92.1403 + return sb.toString();
92.1404 + }
92.1405 +
92.1406 + private String fqn(TypeMirror pt, Element relative) {
92.1407 + if (pt.getKind() == TypeKind.ERROR) {
92.1408 + final Elements eu = processingEnv.getElementUtils();
92.1409 + PackageElement pckg = eu.getPackageOf(relative);
92.1410 + return pckg.getQualifiedName() + "." + pt.toString();
92.1411 + }
92.1412 + return pt.toString();
92.1413 + }
92.1414 +
92.1415 + private String checkType(Prprt p, boolean[] isModel, boolean[] isEnum, boolean[] isPrimitive) {
92.1416 + TypeMirror tm;
92.1417 + try {
92.1418 + String ret = p.typeName(processingEnv);
92.1419 + TypeElement e = processingEnv.getElementUtils().getTypeElement(ret);
92.1420 + if (e == null) {
92.1421 + isModel[0] = true;
92.1422 + isEnum[0] = false;
92.1423 + isPrimitive[0] = false;
92.1424 + return ret;
92.1425 + }
92.1426 + tm = e.asType();
92.1427 + } catch (MirroredTypeException ex) {
92.1428 + tm = ex.getTypeMirror();
92.1429 + }
92.1430 + tm = processingEnv.getTypeUtils().erasure(tm);
92.1431 + if (isPrimitive[0] = tm.getKind().isPrimitive()) {
92.1432 + isEnum[0] = false;
92.1433 + isModel[0] = false;
92.1434 + return tm.toString();
92.1435 + }
92.1436 + final Element e = processingEnv.getTypeUtils().asElement(tm);
92.1437 + if (e.getKind() == ElementKind.CLASS && tm.getKind() == TypeKind.ERROR) {
92.1438 + isModel[0] = true;
92.1439 + isEnum[0] = false;
92.1440 + return e.getSimpleName().toString();
92.1441 + }
92.1442 +
92.1443 + final Model m = e == null ? null : e.getAnnotation(Model.class);
92.1444 + String ret;
92.1445 + if (m != null) {
92.1446 + ret = findPkgName(e) + '.' + m.className();
92.1447 + isModel[0] = true;
92.1448 + models.put(e, m.className());
92.1449 + } else if (findModelForMthd(e)) {
92.1450 + ret = ((TypeElement)e).getQualifiedName().toString();
92.1451 + isModel[0] = true;
92.1452 + } else {
92.1453 + ret = tm.toString();
92.1454 + }
92.1455 + TypeMirror enm = processingEnv.getElementUtils().getTypeElement("java.lang.Enum").asType();
92.1456 + enm = processingEnv.getTypeUtils().erasure(enm);
92.1457 + isEnum[0] = processingEnv.getTypeUtils().isSubtype(tm, enm);
92.1458 + return ret;
92.1459 + }
92.1460 +
92.1461 + private static boolean findModelForMthd(Element clazz) {
92.1462 + if (clazz == null) {
92.1463 + return false;
92.1464 + }
92.1465 + for (Element e : clazz.getEnclosedElements()) {
92.1466 + if (e.getKind() == ElementKind.METHOD) {
92.1467 + ExecutableElement ee = (ExecutableElement)e;
92.1468 + if (
92.1469 + ee.getSimpleName().contentEquals("modelFor") &&
92.1470 + ee.getParameters().isEmpty()
92.1471 + ) {
92.1472 + return true;
92.1473 + }
92.1474 + }
92.1475 + }
92.1476 + return false;
92.1477 + }
92.1478 +
92.1479 + private Iterable<String> findParamNames(
92.1480 + Element e, String url, String jsonParam, StringBuilder... both
92.1481 + ) {
92.1482 + List<String> params = new ArrayList<String>();
92.1483 + int wasJSON = 0;
92.1484 +
92.1485 + for (int pos = 0; ;) {
92.1486 + int next = url.indexOf('{', pos);
92.1487 + if (next == -1) {
92.1488 + both[wasJSON].append('"')
92.1489 + .append(url.substring(pos))
92.1490 + .append('"');
92.1491 + return params;
92.1492 + }
92.1493 + int close = url.indexOf('}', next);
92.1494 + if (close == -1) {
92.1495 + error("Unbalanced '{' and '}' in " + url, e);
92.1496 + return params;
92.1497 + }
92.1498 + final String paramName = url.substring(next + 1, close);
92.1499 + params.add(paramName);
92.1500 + if (paramName.equals(jsonParam) && !jsonParam.isEmpty()) {
92.1501 + both[wasJSON].append('"')
92.1502 + .append(url.substring(pos, next))
92.1503 + .append('"');
92.1504 + wasJSON = 1;
92.1505 + } else {
92.1506 + both[wasJSON].append('"')
92.1507 + .append(url.substring(pos, next))
92.1508 + .append("\" + ").append(paramName).append(" + ");
92.1509 + }
92.1510 + pos = close + 1;
92.1511 + }
92.1512 + }
92.1513 +
92.1514 + private static Prprt findPrprt(Prprt[] properties, String propName) {
92.1515 + for (Prprt p : properties) {
92.1516 + if (propName.equals(p.name())) {
92.1517 + return p;
92.1518 + }
92.1519 + }
92.1520 + return null;
92.1521 + }
92.1522 +
92.1523 + private boolean isPrimitive(String type) {
92.1524 + return
92.1525 + "int".equals(type) ||
92.1526 + "double".equals(type) ||
92.1527 + "long".equals(type) ||
92.1528 + "short".equals(type) ||
92.1529 + "byte".equals(type) ||
92.1530 + "char".equals(type) ||
92.1531 + "boolean".equals(type) ||
92.1532 + "float".equals(type);
92.1533 + }
92.1534 +
92.1535 + private static Collection<String> findDerivedFrom(Map<String, Collection<String>> propsDeps, String derivedProp) {
92.1536 + Set<String> names = new HashSet<String>();
92.1537 + for (Map.Entry<String, Collection<String>> e : propsDeps.entrySet()) {
92.1538 + if (e.getValue().contains(derivedProp)) {
92.1539 + names.add(e.getKey());
92.1540 + }
92.1541 + }
92.1542 + return names;
92.1543 + }
92.1544 +
92.1545 + private Prprt[] createProps(Element e, Property[] arr) {
92.1546 + Prprt[] ret = Prprt.wrap(processingEnv, e, arr);
92.1547 + Prprt[] prev = verify.put(e, ret);
92.1548 + if (prev != null) {
92.1549 + error("Two sets of properties for ", e);
92.1550 + }
92.1551 + return ret;
92.1552 + }
92.1553 +
92.1554 + private static String strip(String s) {
92.1555 + int indx = s.indexOf("__");
92.1556 + if (indx >= 0) {
92.1557 + return s.substring(0, indx);
92.1558 + } else {
92.1559 + return s;
92.1560 + }
92.1561 + }
92.1562 +
92.1563 + private String findDataSpecified(ExecutableElement e, OnReceive onR) {
92.1564 + try {
92.1565 + return onR.data().getName();
92.1566 + } catch (MirroredTypeException ex) {
92.1567 + final TypeMirror tm = ex.getTypeMirror();
92.1568 + String name;
92.1569 + final Element te = processingEnv.getTypeUtils().asElement(tm);
92.1570 + if (te.getKind() == ElementKind.CLASS && tm.getKind() == TypeKind.ERROR) {
92.1571 + name = te.getSimpleName().toString();
92.1572 + } else {
92.1573 + name = tm.toString();
92.1574 + }
92.1575 + return "java.lang.Object".equals(name) ? null : name;
92.1576 + } catch (Exception ex) {
92.1577 + // fallback
92.1578 + }
92.1579 +
92.1580 + AnnotationMirror found = null;
92.1581 + for (AnnotationMirror am : e.getAnnotationMirrors()) {
92.1582 + if (am.getAnnotationType().toString().equals(OnReceive.class.getName())) {
92.1583 + found = am;
92.1584 + }
92.1585 + }
92.1586 + if (found == null) {
92.1587 + return null;
92.1588 + }
92.1589 +
92.1590 + for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : found.getElementValues().entrySet()) {
92.1591 + ExecutableElement ee = entry.getKey();
92.1592 + AnnotationValue av = entry.getValue();
92.1593 + if (ee.getSimpleName().contentEquals("data")) {
92.1594 + List<? extends Object> values = getAnnoValues(processingEnv, e, found);
92.1595 + for (Object v : values) {
92.1596 + String sv = v.toString();
92.1597 + if (sv.startsWith("data = ") && sv.endsWith(".class")) {
92.1598 + return sv.substring(7, sv.length() - 6);
92.1599 + }
92.1600 + }
92.1601 + return "error";
92.1602 + }
92.1603 + }
92.1604 + return null;
92.1605 + }
92.1606 +
92.1607 + static List<? extends Object> getAnnoValues(ProcessingEnvironment pe, Element e, AnnotationMirror am) {
92.1608 + try {
92.1609 + Class<?> trees = Class.forName("com.sun.tools.javac.api.JavacTrees");
92.1610 + Method m = trees.getMethod("instance", ProcessingEnvironment.class);
92.1611 + Object instance = m.invoke(null, pe);
92.1612 + m = instance.getClass().getMethod("getPath", Element.class, AnnotationMirror.class);
92.1613 + Object path = m.invoke(instance, e, am);
92.1614 + m = path.getClass().getMethod("getLeaf");
92.1615 + Object leaf = m.invoke(path);
92.1616 + m = leaf.getClass().getMethod("getArguments");
92.1617 + return (List) m.invoke(leaf);
92.1618 + } catch (Exception ex) {
92.1619 + return Collections.emptyList();
92.1620 + }
92.1621 + }
92.1622 +
92.1623 + private static class Prprt {
92.1624 + private final Element e;
92.1625 + private final AnnotationMirror tm;
92.1626 + private final Property p;
92.1627 +
92.1628 + public Prprt(Element e, AnnotationMirror tm, Property p) {
92.1629 + this.e = e;
92.1630 + this.tm = tm;
92.1631 + this.p = p;
92.1632 + }
92.1633 +
92.1634 + String name() {
92.1635 + return p.name();
92.1636 + }
92.1637 +
92.1638 + boolean array() {
92.1639 + return p.array();
92.1640 + }
92.1641 +
92.1642 + String typeName(ProcessingEnvironment env) {
92.1643 + RuntimeException ex;
92.1644 + try {
92.1645 + return p.type().getName();
92.1646 + } catch (IncompleteAnnotationException e) {
92.1647 + ex = e;
92.1648 + } catch (AnnotationTypeMismatchException e) {
92.1649 + ex = e;
92.1650 + }
92.1651 + for (Object v : getAnnoValues(env, e, tm)) {
92.1652 + String s = v.toString().replace(" ", "");
92.1653 + if (s.startsWith("type=") && s.endsWith(".class")) {
92.1654 + return s.substring(5, s.length() - 6);
92.1655 + }
92.1656 + }
92.1657 + throw ex;
92.1658 + }
92.1659 +
92.1660 +
92.1661 + static Prprt[] wrap(ProcessingEnvironment pe, Element e, Property[] arr) {
92.1662 + if (arr.length == 0) {
92.1663 + return new Prprt[0];
92.1664 + }
92.1665 +
92.1666 + if (e.getKind() != ElementKind.CLASS) {
92.1667 + throw new IllegalStateException("" + e.getKind());
92.1668 + }
92.1669 + TypeElement te = (TypeElement)e;
92.1670 + List<? extends AnnotationValue> val = null;
92.1671 + for (AnnotationMirror an : te.getAnnotationMirrors()) {
92.1672 + for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : an.getElementValues().entrySet()) {
92.1673 + if (entry.getKey().getSimpleName().contentEquals("properties")) {
92.1674 + val = (List)entry.getValue().getValue();
92.1675 + break;
92.1676 + }
92.1677 + }
92.1678 + }
92.1679 + if (val == null || val.size() != arr.length) {
92.1680 + pe.getMessager().printMessage(Diagnostic.Kind.ERROR, "" + val, e);
92.1681 + return new Prprt[0];
92.1682 + }
92.1683 + Prprt[] ret = new Prprt[arr.length];
92.1684 + BIG: for (int i = 0; i < ret.length; i++) {
92.1685 + AnnotationMirror am = (AnnotationMirror)val.get(i).getValue();
92.1686 + ret[i] = new Prprt(e, am, arr[i]);
92.1687 +
92.1688 + }
92.1689 + return ret;
92.1690 + }
92.1691 + }
92.1692 +
92.1693 + @Override
92.1694 + public Iterable<? extends Completion> getCompletions(Element element, AnnotationMirror annotation, ExecutableElement member, String userText) {
92.1695 + final Level l = Level.FINE;
92.1696 + LOG.log(l, " element: {0}", element);
92.1697 + LOG.log(l, " annotation: {0}", annotation);
92.1698 + LOG.log(l, " member: {0}", member);
92.1699 + LOG.log(l, " userText: {0}", userText);
92.1700 + LOG.log(l, "str: {0}", annotation.getAnnotationType().toString());
92.1701 + if (annotation.getAnnotationType().toString().equals(OnReceive.class.getName())) {
92.1702 + if (member.getSimpleName().contentEquals("method")) {
92.1703 + return Arrays.asList(
92.1704 + methodOf("GET"),
92.1705 + methodOf("POST"),
92.1706 + methodOf("PUT"),
92.1707 + methodOf("DELETE"),
92.1708 + methodOf("HEAD"),
92.1709 + methodOf("WebSocket")
92.1710 + );
92.1711 + }
92.1712 + }
92.1713 +
92.1714 + return super.getCompletions(element, annotation, member, userText);
92.1715 + }
92.1716 +
92.1717 + private static final Completion methodOf(String method) {
92.1718 + ResourceBundle rb = ResourceBundle.getBundle("org.netbeans.html.json.impl.Bundle");
92.1719 + return Completions.of('"' + method + '"', rb.getString("MSG_Completion_" + method));
92.1720 + }
92.1721 +
92.1722 + private boolean findOnError(ExecutableElement errElem, TypeElement te, String name, String className) {
92.1723 + String err = null;
92.1724 + METHODS:
92.1725 + for (Element e : te.getEnclosedElements()) {
92.1726 + if (e.getKind() != ElementKind.METHOD) {
92.1727 + continue;
92.1728 + }
92.1729 + if (!e.getSimpleName().contentEquals(name)) {
92.1730 + continue;
92.1731 + }
92.1732 + if (!e.getModifiers().contains(Modifier.STATIC)) {
92.1733 + errElem = (ExecutableElement) e;
92.1734 + err = "Would have to be static";
92.1735 + continue;
92.1736 + }
92.1737 + ExecutableElement ee = (ExecutableElement) e;
92.1738 + TypeMirror excType = processingEnv.getElementUtils().getTypeElement(Exception.class.getName()).asType();
92.1739 + final List<? extends VariableElement> params = ee.getParameters();
92.1740 + boolean error = false;
92.1741 + if (params.size() != 2) {
92.1742 + error = true;
92.1743 + } else {
92.1744 + String firstType = params.get(0).asType().toString();
92.1745 + int lastDot = firstType.lastIndexOf('.');
92.1746 + if (lastDot != -1) {
92.1747 + firstType = firstType.substring(lastDot + 1);
92.1748 + }
92.1749 + if (!firstType.equals(className)) {
92.1750 + error = true;
92.1751 + }
92.1752 + if (!processingEnv.getTypeUtils().isAssignable(excType, params.get(1).asType())) {
92.1753 + error = true;
92.1754 + }
92.1755 + }
92.1756 + if (error) {
92.1757 + errElem = (ExecutableElement) e;
92.1758 + err = "Error method first argument needs to be " + className + " and second Exception";
92.1759 + continue;
92.1760 + }
92.1761 + return true;
92.1762 + }
92.1763 + if (err == null) {
92.1764 + err = "Cannot find " + name + "(" + className + ", Exception) method in this class";
92.1765 + }
92.1766 + error(err, errElem);
92.1767 + return false;
92.1768 + }
92.1769 +
92.1770 +}
93.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
93.2 +++ b/json/src/main/java/org/netbeans/html/json/impl/PropertyBindingAccessor.java Mon Dec 16 16:59:43 2013 +0100
93.3 @@ -0,0 +1,135 @@
93.4 +/**
93.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
93.6 + *
93.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
93.8 + *
93.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
93.10 + * Other names may be trademarks of their respective owners.
93.11 + *
93.12 + * The contents of this file are subject to the terms of either the GNU
93.13 + * General Public License Version 2 only ("GPL") or the Common
93.14 + * Development and Distribution License("CDDL") (collectively, the
93.15 + * "License"). You may not use this file except in compliance with the
93.16 + * License. You can obtain a copy of the License at
93.17 + * http://www.netbeans.org/cddl-gplv2.html
93.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
93.19 + * specific language governing permissions and limitations under the
93.20 + * License. When distributing the software, include this License Header
93.21 + * Notice in each file and include the License file at
93.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
93.23 + * particular file as subject to the "Classpath" exception as provided
93.24 + * by Oracle in the GPL Version 2 section of the License file that
93.25 + * accompanied this code. If applicable, add the following below the
93.26 + * License Header, with the fields enclosed by brackets [] replaced by
93.27 + * your own identifying information:
93.28 + * "Portions Copyrighted [year] [name of copyright owner]"
93.29 + *
93.30 + * Contributor(s):
93.31 + *
93.32 + * The Original Software is NetBeans. The Initial Developer of the Original
93.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
93.34 + *
93.35 + * If you wish your version of this file to be governed by only the CDDL
93.36 + * or only the GPL Version 2, indicate your decision by adding
93.37 + * "[Contributor] elects to include this software in this distribution
93.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
93.39 + * single choice of license, a recipient has the option to distribute
93.40 + * your version of this file under either the CDDL, the GPL Version 2 or
93.41 + * to extend the choice of license to its licensees as provided above.
93.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
93.43 + * Version 2 license, then the option applies only if the new code is
93.44 + * made subject to such option by the copyright holder.
93.45 + */
93.46 +package org.netbeans.html.json.impl;
93.47 +
93.48 +import net.java.html.BrwsrCtx;
93.49 +import org.apidesign.html.json.spi.FunctionBinding;
93.50 +import org.apidesign.html.json.spi.JSONCall;
93.51 +import org.apidesign.html.json.spi.PropertyBinding;
93.52 +
93.53 +/**
93.54 + *
93.55 + * @author Jaroslav Tulach <jtulach@netbeans.org>
93.56 + */
93.57 +public abstract class PropertyBindingAccessor {
93.58 + private static PropertyBindingAccessor DEFAULT;
93.59 +
93.60 + protected PropertyBindingAccessor() {
93.61 + if (DEFAULT != null) throw new IllegalStateException();
93.62 + DEFAULT = this;
93.63 + }
93.64 +
93.65 + static {
93.66 + JSON.initClass(PropertyBinding.class);
93.67 + }
93.68 +
93.69 + protected abstract <M> PropertyBinding newBinding(PBData<M> d);
93.70 + protected abstract <M> FunctionBinding newFunction(FBData<M> d);
93.71 + protected abstract JSONCall newCall(
93.72 + BrwsrCtx ctx, RcvrJSON callback, String urlBefore, String urlAfter,
93.73 + String method, Object data
93.74 + );
93.75 +
93.76 +
93.77 + static <M> PropertyBinding create(PBData<M> d) {
93.78 + return DEFAULT.newBinding(d);
93.79 + }
93.80 + static <M> FunctionBinding createFunction(FBData<M> d) {
93.81 + return DEFAULT.newFunction(d);
93.82 + }
93.83 + static JSONCall createCall(
93.84 + BrwsrCtx ctx, RcvrJSON callback, String urlBefore, String urlAfter,
93.85 + String method, Object data
93.86 + ) {
93.87 + return DEFAULT.newCall(ctx, callback, urlBefore, urlAfter, method, data);
93.88 + }
93.89 +
93.90 + public static final class PBData<M> {
93.91 + public final String name;
93.92 + public final boolean readOnly;
93.93 + private final M model;
93.94 + private final SetAndGet<M> access;
93.95 + private final Bindings<?> bindings;
93.96 +
93.97 + public PBData(Bindings<?> bindings, String name, M model, SetAndGet<M> access, boolean readOnly) {
93.98 + this.bindings = bindings;
93.99 + this.name = name;
93.100 + this.model = model;
93.101 + this.access = access;
93.102 + this.readOnly = readOnly;
93.103 + }
93.104 +
93.105 + public void setValue(Object v) {
93.106 + access.setValue(model, v);
93.107 + }
93.108 +
93.109 + public Object getValue() {
93.110 + return access.getValue(model);
93.111 + }
93.112 +
93.113 + public boolean isReadOnly() {
93.114 + return readOnly;
93.115 + }
93.116 +
93.117 + public Bindings getBindings() {
93.118 + return bindings;
93.119 + }
93.120 + } // end of PBData
93.121 +
93.122 + public static final class FBData<M> {
93.123 + public final String name;
93.124 + private final M model;
93.125 + private final Callback<M> access;
93.126 +
93.127 + public FBData(String name, M model, Callback<M> access) {
93.128 + this.name = name;
93.129 + this.model = model;
93.130 + this.access = access;
93.131 + }
93.132 +
93.133 +
93.134 + public void call(Object data, Object ev) {
93.135 + access.call(model, data, ev);
93.136 + }
93.137 + } // end of FBData
93.138 +}
94.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
94.2 +++ b/json/src/main/java/org/netbeans/html/json/impl/RcvrJSON.java Mon Dec 16 16:59:43 2013 +0100
94.3 @@ -0,0 +1,149 @@
94.4 +/**
94.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
94.6 + *
94.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
94.8 + *
94.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
94.10 + * Other names may be trademarks of their respective owners.
94.11 + *
94.12 + * The contents of this file are subject to the terms of either the GNU
94.13 + * General Public License Version 2 only ("GPL") or the Common
94.14 + * Development and Distribution License("CDDL") (collectively, the
94.15 + * "License"). You may not use this file except in compliance with the
94.16 + * License. You can obtain a copy of the License at
94.17 + * http://www.netbeans.org/cddl-gplv2.html
94.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
94.19 + * specific language governing permissions and limitations under the
94.20 + * License. When distributing the software, include this License Header
94.21 + * Notice in each file and include the License file at
94.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
94.23 + * particular file as subject to the "Classpath" exception as provided
94.24 + * by Oracle in the GPL Version 2 section of the License file that
94.25 + * accompanied this code. If applicable, add the following below the
94.26 + * License Header, with the fields enclosed by brackets [] replaced by
94.27 + * your own identifying information:
94.28 + * "Portions Copyrighted [year] [name of copyright owner]"
94.29 + *
94.30 + * Contributor(s):
94.31 + *
94.32 + * The Original Software is NetBeans. The Initial Developer of the Original
94.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
94.34 + *
94.35 + * If you wish your version of this file to be governed by only the CDDL
94.36 + * or only the GPL Version 2, indicate your decision by adding
94.37 + * "[Contributor] elects to include this software in this distribution
94.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
94.39 + * single choice of license, a recipient has the option to distribute
94.40 + * your version of this file under either the CDDL, the GPL Version 2 or
94.41 + * to extend the choice of license to its licensees as provided above.
94.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
94.43 + * Version 2 license, then the option applies only if the new code is
94.44 + * made subject to such option by the copyright holder.
94.45 + */
94.46 +package org.netbeans.html.json.impl;
94.47 +
94.48 +import net.java.html.BrwsrCtx;
94.49 +
94.50 +/** Super type for those who wish to receive JSON messages.
94.51 + *
94.52 + * @author Jaroslav Tulach <jtulach@netbeans.org>
94.53 + */
94.54 +public abstract class RcvrJSON {
94.55 + protected void onOpen(MsgEvnt msg) {}
94.56 + protected abstract void onMessage(MsgEvnt msg);
94.57 + protected void onClose(MsgEvnt msg) {}
94.58 + protected abstract void onError(MsgEvnt msg);
94.59 +
94.60 + public abstract static class MsgEvnt {
94.61 + MsgEvnt() {
94.62 + }
94.63 +
94.64 + public Throwable getError() {
94.65 + return null;
94.66 + }
94.67 +
94.68 + public final Exception getException() {
94.69 + Throwable t = getError();
94.70 + if (t instanceof Exception) {
94.71 + return (Exception)t;
94.72 + }
94.73 + if (t == null) {
94.74 + return null;
94.75 + }
94.76 + return new Exception(t);
94.77 + }
94.78 +
94.79 + public int dataSize() {
94.80 + return -1;
94.81 + }
94.82 +
94.83 + public <Data> void dataRead(BrwsrCtx ctx, Class<? extends Data> type, Data[] fillTheArray) {
94.84 + }
94.85 +
94.86 + public abstract void dispatch(RcvrJSON r);
94.87 +
94.88 + public static MsgEvnt createError(final Throwable t) {
94.89 + return new MsgEvnt() {
94.90 + @Override
94.91 + public Throwable getError() {
94.92 + return t;
94.93 + }
94.94 +
94.95 + @Override
94.96 + public void dispatch(RcvrJSON r) {
94.97 + r.onError(this);
94.98 + }
94.99 + };
94.100 + }
94.101 +
94.102 + public static MsgEvnt createMessage(final Object value) {
94.103 + return new MsgEvnt() {
94.104 + @Override
94.105 + public int dataSize() {
94.106 + if (value instanceof Object[]) {
94.107 + return ((Object[])value).length;
94.108 + } else {
94.109 + return 1;
94.110 + }
94.111 + }
94.112 +
94.113 + @Override
94.114 + public <Data> void dataRead(BrwsrCtx context, Class<? extends Data> type, Data[] arr) {
94.115 + if (value instanceof Object[]) {
94.116 + Object[] data = ((Object[]) value);
94.117 + for (int i = 0; i < data.length && i < arr.length; i++) {
94.118 + arr[i] = org.netbeans.html.json.impl.JSON.read(context, type, data[i]);
94.119 + }
94.120 + } else {
94.121 + if (arr.length > 0) {
94.122 + arr[0] = org.netbeans.html.json.impl.JSON.read(context, type, value);
94.123 + }
94.124 + }
94.125 + }
94.126 +
94.127 + @Override
94.128 + public void dispatch(RcvrJSON r) {
94.129 + r.onMessage(this);
94.130 + }
94.131 + };
94.132 + }
94.133 +
94.134 + public static MsgEvnt createOpen() {
94.135 + return new MsgEvnt() {
94.136 + @Override
94.137 + public void dispatch(RcvrJSON r) {
94.138 + r.onOpen(this);
94.139 + }
94.140 + };
94.141 + }
94.142 +
94.143 + public static MsgEvnt createClose() {
94.144 + return new MsgEvnt() {
94.145 + @Override
94.146 + public void dispatch(RcvrJSON r) {
94.147 + r.onClose(this);
94.148 + }
94.149 + };
94.150 + }
94.151 + } // end MsgEvnt
94.152 +}
95.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
95.2 +++ b/json/src/main/java/org/netbeans/html/json/impl/SetAndGet.java Mon Dec 16 16:59:43 2013 +0100
95.3 @@ -0,0 +1,54 @@
95.4 +/**
95.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
95.6 + *
95.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
95.8 + *
95.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
95.10 + * Other names may be trademarks of their respective owners.
95.11 + *
95.12 + * The contents of this file are subject to the terms of either the GNU
95.13 + * General Public License Version 2 only ("GPL") or the Common
95.14 + * Development and Distribution License("CDDL") (collectively, the
95.15 + * "License"). You may not use this file except in compliance with the
95.16 + * License. You can obtain a copy of the License at
95.17 + * http://www.netbeans.org/cddl-gplv2.html
95.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
95.19 + * specific language governing permissions and limitations under the
95.20 + * License. When distributing the software, include this License Header
95.21 + * Notice in each file and include the License file at
95.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
95.23 + * particular file as subject to the "Classpath" exception as provided
95.24 + * by Oracle in the GPL Version 2 section of the License file that
95.25 + * accompanied this code. If applicable, add the following below the
95.26 + * License Header, with the fields enclosed by brackets [] replaced by
95.27 + * your own identifying information:
95.28 + * "Portions Copyrighted [year] [name of copyright owner]"
95.29 + *
95.30 + * Contributor(s):
95.31 + *
95.32 + * The Original Software is NetBeans. The Initial Developer of the Original
95.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
95.34 + *
95.35 + * If you wish your version of this file to be governed by only the CDDL
95.36 + * or only the GPL Version 2, indicate your decision by adding
95.37 + * "[Contributor] elects to include this software in this distribution
95.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
95.39 + * single choice of license, a recipient has the option to distribute
95.40 + * your version of this file under either the CDDL, the GPL Version 2 or
95.41 + * to extend the choice of license to its licensees as provided above.
95.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
95.43 + * Version 2 license, then the option applies only if the new code is
95.44 + * made subject to such option by the copyright holder.
95.45 + */
95.46 +package org.netbeans.html.json.impl;
95.47 +
95.48 +import org.apidesign.html.json.spi.PropertyBinding;
95.49 +
95.50 +/** A way to implement a {@link PropertyBinding}.
95.51 + *
95.52 + * @author Jaroslav Tulach <jtulach@netbeans.org>
95.53 + */
95.54 +public interface SetAndGet<Data> {
95.55 + public void setValue(Data data, Object value);
95.56 + public Object getValue(Data data);
95.57 +}
96.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
96.2 +++ b/json/src/main/java/org/netbeans/html/json/impl/WrapperObject.java Mon Dec 16 16:59:43 2013 +0100
96.3 @@ -0,0 +1,82 @@
96.4 +/**
96.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
96.6 + *
96.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
96.8 + *
96.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
96.10 + * Other names may be trademarks of their respective owners.
96.11 + *
96.12 + * The contents of this file are subject to the terms of either the GNU
96.13 + * General Public License Version 2 only ("GPL") or the Common
96.14 + * Development and Distribution License("CDDL") (collectively, the
96.15 + * "License"). You may not use this file except in compliance with the
96.16 + * License. You can obtain a copy of the License at
96.17 + * http://www.netbeans.org/cddl-gplv2.html
96.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
96.19 + * specific language governing permissions and limitations under the
96.20 + * License. When distributing the software, include this License Header
96.21 + * Notice in each file and include the License file at
96.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
96.23 + * particular file as subject to the "Classpath" exception as provided
96.24 + * by Oracle in the GPL Version 2 section of the License file that
96.25 + * accompanied this code. If applicable, add the following below the
96.26 + * License Header, with the fields enclosed by brackets [] replaced by
96.27 + * your own identifying information:
96.28 + * "Portions Copyrighted [year] [name of copyright owner]"
96.29 + *
96.30 + * Contributor(s):
96.31 + *
96.32 + * The Original Software is NetBeans. The Initial Developer of the Original
96.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
96.34 + *
96.35 + * If you wish your version of this file to be governed by only the CDDL
96.36 + * or only the GPL Version 2, indicate your decision by adding
96.37 + * "[Contributor] elects to include this software in this distribution
96.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
96.39 + * single choice of license, a recipient has the option to distribute
96.40 + * your version of this file under either the CDDL, the GPL Version 2 or
96.41 + * to extend the choice of license to its licensees as provided above.
96.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
96.43 + * Version 2 license, then the option applies only if the new code is
96.44 + * made subject to such option by the copyright holder.
96.45 + */
96.46 +package org.netbeans.html.json.impl;
96.47 +
96.48 +import java.util.Collection;
96.49 +import org.netbeans.html.json.impl.PropertyBindingAccessor.PBData;
96.50 +
96.51 +/** A way to extract real object from a model classes.
96.52 + *
96.53 + * @author Jaroslav Tulach <jtulach@netbeans.org>
96.54 + */
96.55 +public final class WrapperObject {
96.56 + private Object ko;
96.57 +
96.58 + private WrapperObject() {
96.59 + }
96.60 +
96.61 + public void setRealObject(Object ko) {
96.62 + this.ko = ko;
96.63 + }
96.64 +
96.65 + public static Object find(Object object) {
96.66 + return find(object, null);
96.67 + }
96.68 +
96.69 + public static Object find(Object object, Bindings model) {
96.70 + if (object == null) {
96.71 + return null;
96.72 + }
96.73 +
96.74 + if (object instanceof JSONList) {
96.75 + return ((JSONList<?>)object).koData();
96.76 + }
96.77 + if (object instanceof Collection) {
96.78 + return JSONList.koData((Collection<?>)object, model);
96.79 + }
96.80 +
96.81 + WrapperObject ro = new WrapperObject();
96.82 + object.equals(ro);
96.83 + return ro.ko;
96.84 + }
96.85 +}
97.1 --- a/json/src/main/resources/org/apidesign/html/json/impl/Bundle.properties Mon Dec 16 15:48:09 2013 +0100
97.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
97.3 @@ -1,97 +0,0 @@
97.4 -#
97.5 -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
97.6 -#
97.7 -# Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
97.8 -#
97.9 -# Oracle and Java are registered trademarks of Oracle and/or its affiliates.
97.10 -# Other names may be trademarks of their respective owners.
97.11 -#
97.12 -# The contents of this file are subject to the terms of either the GNU
97.13 -# General Public License Version 2 only ("GPL") or the Common
97.14 -# Development and Distribution License("CDDL") (collectively, the
97.15 -# "License"). You may not use this file except in compliance with the
97.16 -# License. You can obtain a copy of the License at
97.17 -# http://www.netbeans.org/cddl-gplv2.html
97.18 -# or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
97.19 -# specific language governing permissions and limitations under the
97.20 -# License. When distributing the software, include this License Header
97.21 -# Notice in each file and include the License file at
97.22 -# nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
97.23 -# particular file as subject to the "Classpath" exception as provided
97.24 -# by Oracle in the GPL Version 2 section of the License file that
97.25 -# accompanied this code. If applicable, add the following below the
97.26 -# License Header, with the fields enclosed by brackets [] replaced by
97.27 -# your own identifying information:
97.28 -# "Portions Copyrighted [year] [name of copyright owner]"
97.29 -#
97.30 -# Contributor(s):
97.31 -#
97.32 -# The Original Software is NetBeans. The Initial Developer of the Original
97.33 -# Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
97.34 -#
97.35 -# If you wish your version of this file to be governed by only the CDDL
97.36 -# or only the GPL Version 2, indicate your decision by adding
97.37 -# "[Contributor] elects to include this software in this distribution
97.38 -# under the [CDDL or GPL Version 2] license." If you do not indicate a
97.39 -# single choice of license, a recipient has the option to distribute
97.40 -# your version of this file under either the CDDL, the GPL Version 2 or
97.41 -# to extend the choice of license to its licensees as provided above.
97.42 -# However, if you add GPL Version 2 code and therefore, elected the GPL
97.43 -# Version 2 license, then the option applies only if the new code is
97.44 -# made subject to such option by the copyright holder.
97.45 -#
97.46 -
97.47 -MSG_Completion_GET=The GET method means retrieve whatever information \
97.48 - (in the form of an entity) is identified by the Request-URI. \
97.49 - If the Request-URI refers to a data-producing process, \
97.50 - it is the produced data which shall be returned as the entity in \
97.51 - the response and not the source text of the process, \
97.52 - unless that text happens to be the output of the process.
97.53 -
97.54 -MSG_Completion_HEAD=The HEAD method is identical to GET except that the server \
97.55 - MUST NOT return a message-body in the response. The metainformation \
97.56 - contained in the HTTP headers in response to a HEAD request SHOULD be \
97.57 - identical to the information sent in response to a GET request. \
97.58 - This method can be used for obtaining metainformation about the entity implied \
97.59 - by the request without transferring the entity-body itself. \
97.60 - This method is often used for testing hypertext links for validity, \
97.61 - accessibility, and recent modification.
97.62 -
97.63 -MSG_Completion_POST=The POST method is used to request that the origin server \
97.64 - accept the entity enclosed in the request as a new subordinate of the resource \
97.65 - identified by the Request-URI in the Request-Line. POST is designed to allow \
97.66 - a uniform method to cover annotation of existing resources,\
97.67 - posting a message to a bulletin board, newsgroup, mailing list, or similar \
97.68 - group of articles, providing a block of data, such as the result of submitting a \
97.69 - form, to a data-handling process or extending a database through an append operation. \
97.70 - The actual function performed by the POST method is determined by the server \
97.71 - and is usually dependent on the Request-URI. The posted entity is subordinate \
97.72 - to that URI in the same way that a file is subordinate to a directory containing it, \
97.73 - a news article is subordinate to a newsgroup to which it is posted, \
97.74 - or a record is subordinate to a database.
97.75 -
97.76 -MSG_Completion_PUT=The PUT method requests that the enclosed entity be stored \
97.77 - under the supplied Request-URI. If the Request-URI refers to an already \
97.78 - existing resource, the enclosed entity SHOULD be considered as a modified \
97.79 - version of the one residing on the origin server. If the Request-URI does \
97.80 - not point to an existing resource, and that URI is capable of being defined \
97.81 - as a new resource by the requesting user agent, the origin server can \
97.82 - create the resource with that URI. If a new resource is created, the origin \
97.83 - server MUST inform the user agent via the 201 (Created) response. \
97.84 - If an existing resource is modified, either the 200 (OK) or 204 (No Content) \
97.85 - response codes SHOULD be sent to indicate successful completion of the request. \
97.86 - If the resource could not be created or modified with the Request-URI, an \
97.87 - appropriate error response SHOULD be given that reflects the nature of the problem. \
97.88 - The recipient of the entity MUST NOT ignore any Content-* (e.g. Content-Range) \
97.89 - headers that it does not understand or implement and MUST return \
97.90 - a 501 (Not Implemented) response in such cases.
97.91 -
97.92 -MSG_Completion_DELETE=The DELETE method requests that the origin server delete \
97.93 - the resource identified by the Request-URI. This method MAY be overridden \
97.94 - by human intervention (or other means) on the origin server. The client \
97.95 - cannot be guaranteed that the operation has been carried out, even if \
97.96 - the status code returned from the origin server indicates that the action \
97.97 - has been completed successfully. However, the server SHOULD NOT indicate \
97.98 - success unless, at the time the response is given, it intends to delete \
97.99 - the resource or move it to an inaccessible location.
97.100 -
98.1 --- a/json/src/main/resources/org/apidesign/html/json/spi/package.html Mon Dec 16 15:48:09 2013 +0100
98.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
98.3 @@ -1,59 +0,0 @@
98.4 -<!--
98.5 -
98.6 - DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
98.7 -
98.8 - Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
98.9 -
98.10 - Oracle and Java are registered trademarks of Oracle and/or its affiliates.
98.11 - Other names may be trademarks of their respective owners.
98.12 -
98.13 - The contents of this file are subject to the terms of either the GNU
98.14 - General Public License Version 2 only ("GPL") or the Common
98.15 - Development and Distribution License("CDDL") (collectively, the
98.16 - "License"). You may not use this file except in compliance with the
98.17 - License. You can obtain a copy of the License at
98.18 - http://www.netbeans.org/cddl-gplv2.html
98.19 - or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
98.20 - specific language governing permissions and limitations under the
98.21 - License. When distributing the software, include this License Header
98.22 - Notice in each file and include the License file at
98.23 - nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
98.24 - particular file as subject to the "Classpath" exception as provided
98.25 - by Oracle in the GPL Version 2 section of the License file that
98.26 - accompanied this code. If applicable, add the following below the
98.27 - License Header, with the fields enclosed by brackets [] replaced by
98.28 - your own identifying information:
98.29 - "Portions Copyrighted [year] [name of copyright owner]"
98.30 -
98.31 - Contributor(s):
98.32 -
98.33 - The Original Software is NetBeans. The Initial Developer of the Original
98.34 - Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
98.35 -
98.36 - If you wish your version of this file to be governed by only the CDDL
98.37 - or only the GPL Version 2, indicate your decision by adding
98.38 - "[Contributor] elects to include this software in this distribution
98.39 - under the [CDDL or GPL Version 2] license." If you do not indicate a
98.40 - single choice of license, a recipient has the option to distribute
98.41 - your version of this file under either the CDDL, the GPL Version 2 or
98.42 - to extend the choice of license to its licensees as provided above.
98.43 - However, if you add GPL Version 2 code and therefore, elected the GPL
98.44 - Version 2 license, then the option applies only if the new code is
98.45 - made subject to such option by the copyright holder.
98.46 -
98.47 --->
98.48 -<!DOCTYPE html>
98.49 -<html>
98.50 - <head>
98.51 - <title></title>
98.52 - <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
98.53 - </head>
98.54 - <body>
98.55 - <div>Implement
98.56 - <a href="Technology.html">Technology</a> and
98.57 - <a href="Transfer.html">Transfer</a> and use
98.58 - <a href="ContextBuilder.html">ContextBuilder</a> to create an instance
98.59 - of <code>Context</code> representing your technology.
98.60 - </div>
98.61 - </body>
98.62 -</html>
99.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
99.2 +++ b/json/src/main/resources/org/netbeans/html/json/impl/Bundle.properties Mon Dec 16 16:59:43 2013 +0100
99.3 @@ -0,0 +1,97 @@
99.4 +#
99.5 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
99.6 +#
99.7 +# Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
99.8 +#
99.9 +# Oracle and Java are registered trademarks of Oracle and/or its affiliates.
99.10 +# Other names may be trademarks of their respective owners.
99.11 +#
99.12 +# The contents of this file are subject to the terms of either the GNU
99.13 +# General Public License Version 2 only ("GPL") or the Common
99.14 +# Development and Distribution License("CDDL") (collectively, the
99.15 +# "License"). You may not use this file except in compliance with the
99.16 +# License. You can obtain a copy of the License at
99.17 +# http://www.netbeans.org/cddl-gplv2.html
99.18 +# or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
99.19 +# specific language governing permissions and limitations under the
99.20 +# License. When distributing the software, include this License Header
99.21 +# Notice in each file and include the License file at
99.22 +# nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
99.23 +# particular file as subject to the "Classpath" exception as provided
99.24 +# by Oracle in the GPL Version 2 section of the License file that
99.25 +# accompanied this code. If applicable, add the following below the
99.26 +# License Header, with the fields enclosed by brackets [] replaced by
99.27 +# your own identifying information:
99.28 +# "Portions Copyrighted [year] [name of copyright owner]"
99.29 +#
99.30 +# Contributor(s):
99.31 +#
99.32 +# The Original Software is NetBeans. The Initial Developer of the Original
99.33 +# Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
99.34 +#
99.35 +# If you wish your version of this file to be governed by only the CDDL
99.36 +# or only the GPL Version 2, indicate your decision by adding
99.37 +# "[Contributor] elects to include this software in this distribution
99.38 +# under the [CDDL or GPL Version 2] license." If you do not indicate a
99.39 +# single choice of license, a recipient has the option to distribute
99.40 +# your version of this file under either the CDDL, the GPL Version 2 or
99.41 +# to extend the choice of license to its licensees as provided above.
99.42 +# However, if you add GPL Version 2 code and therefore, elected the GPL
99.43 +# Version 2 license, then the option applies only if the new code is
99.44 +# made subject to such option by the copyright holder.
99.45 +#
99.46 +
99.47 +MSG_Completion_GET=The GET method means retrieve whatever information \
99.48 + (in the form of an entity) is identified by the Request-URI. \
99.49 + If the Request-URI refers to a data-producing process, \
99.50 + it is the produced data which shall be returned as the entity in \
99.51 + the response and not the source text of the process, \
99.52 + unless that text happens to be the output of the process.
99.53 +
99.54 +MSG_Completion_HEAD=The HEAD method is identical to GET except that the server \
99.55 + MUST NOT return a message-body in the response. The metainformation \
99.56 + contained in the HTTP headers in response to a HEAD request SHOULD be \
99.57 + identical to the information sent in response to a GET request. \
99.58 + This method can be used for obtaining metainformation about the entity implied \
99.59 + by the request without transferring the entity-body itself. \
99.60 + This method is often used for testing hypertext links for validity, \
99.61 + accessibility, and recent modification.
99.62 +
99.63 +MSG_Completion_POST=The POST method is used to request that the origin server \
99.64 + accept the entity enclosed in the request as a new subordinate of the resource \
99.65 + identified by the Request-URI in the Request-Line. POST is designed to allow \
99.66 + a uniform method to cover annotation of existing resources,\
99.67 + posting a message to a bulletin board, newsgroup, mailing list, or similar \
99.68 + group of articles, providing a block of data, such as the result of submitting a \
99.69 + form, to a data-handling process or extending a database through an append operation. \
99.70 + The actual function performed by the POST method is determined by the server \
99.71 + and is usually dependent on the Request-URI. The posted entity is subordinate \
99.72 + to that URI in the same way that a file is subordinate to a directory containing it, \
99.73 + a news article is subordinate to a newsgroup to which it is posted, \
99.74 + or a record is subordinate to a database.
99.75 +
99.76 +MSG_Completion_PUT=The PUT method requests that the enclosed entity be stored \
99.77 + under the supplied Request-URI. If the Request-URI refers to an already \
99.78 + existing resource, the enclosed entity SHOULD be considered as a modified \
99.79 + version of the one residing on the origin server. If the Request-URI does \
99.80 + not point to an existing resource, and that URI is capable of being defined \
99.81 + as a new resource by the requesting user agent, the origin server can \
99.82 + create the resource with that URI. If a new resource is created, the origin \
99.83 + server MUST inform the user agent via the 201 (Created) response. \
99.84 + If an existing resource is modified, either the 200 (OK) or 204 (No Content) \
99.85 + response codes SHOULD be sent to indicate successful completion of the request. \
99.86 + If the resource could not be created or modified with the Request-URI, an \
99.87 + appropriate error response SHOULD be given that reflects the nature of the problem. \
99.88 + The recipient of the entity MUST NOT ignore any Content-* (e.g. Content-Range) \
99.89 + headers that it does not understand or implement and MUST return \
99.90 + a 501 (Not Implemented) response in such cases.
99.91 +
99.92 +MSG_Completion_DELETE=The DELETE method requests that the origin server delete \
99.93 + the resource identified by the Request-URI. This method MAY be overridden \
99.94 + by human intervention (or other means) on the origin server. The client \
99.95 + cannot be guaranteed that the operation has been carried out, even if \
99.96 + the status code returned from the origin server indicates that the action \
99.97 + has been completed successfully. However, the server SHOULD NOT indicate \
99.98 + success unless, at the time the response is given, it intends to delete \
99.99 + the resource or move it to an inaccessible location.
99.100 +
100.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
100.2 +++ b/json/src/main/resources/org/netbeans/html/json/spi/package.html Mon Dec 16 16:59:43 2013 +0100
100.3 @@ -0,0 +1,59 @@
100.4 +<!--
100.5 +
100.6 + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
100.7 +
100.8 + Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
100.9 +
100.10 + Oracle and Java are registered trademarks of Oracle and/or its affiliates.
100.11 + Other names may be trademarks of their respective owners.
100.12 +
100.13 + The contents of this file are subject to the terms of either the GNU
100.14 + General Public License Version 2 only ("GPL") or the Common
100.15 + Development and Distribution License("CDDL") (collectively, the
100.16 + "License"). You may not use this file except in compliance with the
100.17 + License. You can obtain a copy of the License at
100.18 + http://www.netbeans.org/cddl-gplv2.html
100.19 + or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
100.20 + specific language governing permissions and limitations under the
100.21 + License. When distributing the software, include this License Header
100.22 + Notice in each file and include the License file at
100.23 + nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
100.24 + particular file as subject to the "Classpath" exception as provided
100.25 + by Oracle in the GPL Version 2 section of the License file that
100.26 + accompanied this code. If applicable, add the following below the
100.27 + License Header, with the fields enclosed by brackets [] replaced by
100.28 + your own identifying information:
100.29 + "Portions Copyrighted [year] [name of copyright owner]"
100.30 +
100.31 + Contributor(s):
100.32 +
100.33 + The Original Software is NetBeans. The Initial Developer of the Original
100.34 + Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
100.35 +
100.36 + If you wish your version of this file to be governed by only the CDDL
100.37 + or only the GPL Version 2, indicate your decision by adding
100.38 + "[Contributor] elects to include this software in this distribution
100.39 + under the [CDDL or GPL Version 2] license." If you do not indicate a
100.40 + single choice of license, a recipient has the option to distribute
100.41 + your version of this file under either the CDDL, the GPL Version 2 or
100.42 + to extend the choice of license to its licensees as provided above.
100.43 + However, if you add GPL Version 2 code and therefore, elected the GPL
100.44 + Version 2 license, then the option applies only if the new code is
100.45 + made subject to such option by the copyright holder.
100.46 +
100.47 +-->
100.48 +<!DOCTYPE html>
100.49 +<html>
100.50 + <head>
100.51 + <title></title>
100.52 + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
100.53 + </head>
100.54 + <body>
100.55 + <div>Implement
100.56 + <a href="Technology.html">Technology</a> and
100.57 + <a href="Transfer.html">Transfer</a> and use
100.58 + <a href="ContextBuilder.html">ContextBuilder</a> to create an instance
100.59 + of <code>Context</code> representing your technology.
100.60 + </div>
100.61 + </body>
100.62 +</html>
101.1 --- a/json/src/test/java/net/java/html/json/MapModelTest.java Mon Dec 16 15:48:09 2013 +0100
101.2 +++ b/json/src/test/java/net/java/html/json/MapModelTest.java Mon Dec 16 16:59:43 2013 +0100
101.3 @@ -49,7 +49,7 @@
101.4 import java.util.HashMap;
101.5 import java.util.Map;
101.6 import org.apidesign.html.context.spi.Contexts;
101.7 -import org.apidesign.html.json.impl.WrapperObject;
101.8 +import org.netbeans.html.json.impl.WrapperObject;
101.9 import org.apidesign.html.json.spi.FunctionBinding;
101.10 import org.apidesign.html.json.spi.JSONCall;
101.11 import org.apidesign.html.json.spi.PropertyBinding;
102.1 --- a/json/src/test/java/net/java/html/json/TypesTest.java Mon Dec 16 15:48:09 2013 +0100
102.2 +++ b/json/src/test/java/net/java/html/json/TypesTest.java Mon Dec 16 16:59:43 2013 +0100
102.3 @@ -46,7 +46,7 @@
102.4 import java.util.Map;
102.5 import net.java.html.json.MapModelTest.One;
102.6 import org.apidesign.html.context.spi.Contexts;
102.7 -import org.apidesign.html.json.impl.WrapperObject;
102.8 +import org.netbeans.html.json.impl.WrapperObject;
102.9 import org.apidesign.html.json.spi.Technology;
102.10 import org.apidesign.html.json.spi.Transfer;
102.11 import org.testng.annotations.BeforeMethod;
103.1 --- a/json/src/test/java/org/apidesign/html/json/impl/ConstructorTest.java Mon Dec 16 15:48:09 2013 +0100
103.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
103.3 @@ -1,80 +0,0 @@
103.4 -/**
103.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
103.6 - *
103.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
103.8 - *
103.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
103.10 - * Other names may be trademarks of their respective owners.
103.11 - *
103.12 - * The contents of this file are subject to the terms of either the GNU
103.13 - * General Public License Version 2 only ("GPL") or the Common
103.14 - * Development and Distribution License("CDDL") (collectively, the
103.15 - * "License"). You may not use this file except in compliance with the
103.16 - * License. You can obtain a copy of the License at
103.17 - * http://www.netbeans.org/cddl-gplv2.html
103.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
103.19 - * specific language governing permissions and limitations under the
103.20 - * License. When distributing the software, include this License Header
103.21 - * Notice in each file and include the License file at
103.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
103.23 - * particular file as subject to the "Classpath" exception as provided
103.24 - * by Oracle in the GPL Version 2 section of the License file that
103.25 - * accompanied this code. If applicable, add the following below the
103.26 - * License Header, with the fields enclosed by brackets [] replaced by
103.27 - * your own identifying information:
103.28 - * "Portions Copyrighted [year] [name of copyright owner]"
103.29 - *
103.30 - * Contributor(s):
103.31 - *
103.32 - * The Original Software is NetBeans. The Initial Developer of the Original
103.33 - * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
103.34 - *
103.35 - * If you wish your version of this file to be governed by only the CDDL
103.36 - * or only the GPL Version 2, indicate your decision by adding
103.37 - * "[Contributor] elects to include this software in this distribution
103.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
103.39 - * single choice of license, a recipient has the option to distribute
103.40 - * your version of this file under either the CDDL, the GPL Version 2 or
103.41 - * to extend the choice of license to its licensees as provided above.
103.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
103.43 - * Version 2 license, then the option applies only if the new code is
103.44 - * made subject to such option by the copyright holder.
103.45 - */
103.46 -package org.apidesign.html.json.impl;
103.47 -
103.48 -import net.java.html.json.Model;
103.49 -import net.java.html.json.Property;
103.50 -import static org.testng.Assert.assertNotNull;
103.51 -import static org.testng.Assert.assertEquals;
103.52 -import org.testng.annotations.Test;
103.53 -
103.54 -/**
103.55 - *
103.56 - * @author Jaroslav Tulach <jtulach@netbeans.org>
103.57 - */
103.58 -@Model(className="Man", properties={
103.59 - @Property(name = "name", type = String.class),
103.60 - @Property(name = "other", type = Address.class, array = true),
103.61 - @Property(name = "primary", type = Address.class),
103.62 - @Property(name = "childrenNames", type = String.class, array = true)
103.63 -})
103.64 -public class ConstructorTest {
103.65 - @Model(className = "Address", properties = {
103.66 - @Property(name = "place", type = String.class)
103.67 - })
103.68 - static final class AddressModel {
103.69 - }
103.70 -
103.71 - @Test public void initializedByDefault() {
103.72 - Man m = new Man();
103.73 - assertNotNull(m.getPrimary(), "Single subobjects are initialized");
103.74 - }
103.75 -
103.76 - @Test public void hasRichConstructor() {
103.77 - Man m = new Man("Jarda", new Address("home"), new Address("work"), new Address("hotel"));
103.78 - assertEquals(m.getName(), "Jarda");
103.79 - assertNotNull(m.getPrimary(), "Primary address specified");
103.80 - assertNotNull(m.getPrimary().getPlace(), "home");
103.81 - assertEquals(m.getOther().size(), 2, "Two other addresses");
103.82 - }
103.83 -}
104.1 --- a/json/src/test/java/org/apidesign/html/json/impl/EmployeeImpl.java Mon Dec 16 15:48:09 2013 +0100
104.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
104.3 @@ -1,63 +0,0 @@
104.4 -/**
104.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
104.6 - *
104.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
104.8 - *
104.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
104.10 - * Other names may be trademarks of their respective owners.
104.11 - *
104.12 - * The contents of this file are subject to the terms of either the GNU
104.13 - * General Public License Version 2 only ("GPL") or the Common
104.14 - * Development and Distribution License("CDDL") (collectively, the
104.15 - * "License"). You may not use this file except in compliance with the
104.16 - * License. You can obtain a copy of the License at
104.17 - * http://www.netbeans.org/cddl-gplv2.html
104.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
104.19 - * specific language governing permissions and limitations under the
104.20 - * License. When distributing the software, include this License Header
104.21 - * Notice in each file and include the License file at
104.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
104.23 - * particular file as subject to the "Classpath" exception as provided
104.24 - * by Oracle in the GPL Version 2 section of the License file that
104.25 - * accompanied this code. If applicable, add the following below the
104.26 - * License Header, with the fields enclosed by brackets [] replaced by
104.27 - * your own identifying information:
104.28 - * "Portions Copyrighted [year] [name of copyright owner]"
104.29 - *
104.30 - * Contributor(s):
104.31 - *
104.32 - * The Original Software is NetBeans. The Initial Developer of the Original
104.33 - * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
104.34 - *
104.35 - * If you wish your version of this file to be governed by only the CDDL
104.36 - * or only the GPL Version 2, indicate your decision by adding
104.37 - * "[Contributor] elects to include this software in this distribution
104.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
104.39 - * single choice of license, a recipient has the option to distribute
104.40 - * your version of this file under either the CDDL, the GPL Version 2 or
104.41 - * to extend the choice of license to its licensees as provided above.
104.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
104.43 - * Version 2 license, then the option applies only if the new code is
104.44 - * made subject to such option by the copyright holder.
104.45 - */
104.46 -package org.apidesign.html.json.impl;
104.47 -
104.48 -import net.java.html.json.Model;
104.49 -import net.java.html.json.OnReceive;
104.50 -import net.java.html.json.Person;
104.51 -import net.java.html.json.Property;
104.52 -
104.53 -/**
104.54 - *
104.55 - * @author Jaroslav Tulach <jtulach@netbeans.org>
104.56 - */
104.57 -@Model(className = "Employee", properties = {
104.58 - @Property(name = "person", type = Person.class),
104.59 - @Property(name = "employer", type = Employer.class)
104.60 -})
104.61 -public class EmployeeImpl {
104.62 - @OnReceive(url = "some/url")
104.63 - static void changePersonality(Employee e, Person p) {
104.64 - e.setPerson(p);
104.65 - }
104.66 -}
105.1 --- a/json/src/test/java/org/apidesign/html/json/impl/EmployerTest.java Mon Dec 16 15:48:09 2013 +0100
105.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
105.3 @@ -1,65 +0,0 @@
105.4 -/**
105.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
105.6 - *
105.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
105.8 - *
105.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
105.10 - * Other names may be trademarks of their respective owners.
105.11 - *
105.12 - * The contents of this file are subject to the terms of either the GNU
105.13 - * General Public License Version 2 only ("GPL") or the Common
105.14 - * Development and Distribution License("CDDL") (collectively, the
105.15 - * "License"). You may not use this file except in compliance with the
105.16 - * License. You can obtain a copy of the License at
105.17 - * http://www.netbeans.org/cddl-gplv2.html
105.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
105.19 - * specific language governing permissions and limitations under the
105.20 - * License. When distributing the software, include this License Header
105.21 - * Notice in each file and include the License file at
105.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
105.23 - * particular file as subject to the "Classpath" exception as provided
105.24 - * by Oracle in the GPL Version 2 section of the License file that
105.25 - * accompanied this code. If applicable, add the following below the
105.26 - * License Header, with the fields enclosed by brackets [] replaced by
105.27 - * your own identifying information:
105.28 - * "Portions Copyrighted [year] [name of copyright owner]"
105.29 - *
105.30 - * Contributor(s):
105.31 - *
105.32 - * The Original Software is NetBeans. The Initial Developer of the Original
105.33 - * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
105.34 - *
105.35 - * If you wish your version of this file to be governed by only the CDDL
105.36 - * or only the GPL Version 2, indicate your decision by adding
105.37 - * "[Contributor] elects to include this software in this distribution
105.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
105.39 - * single choice of license, a recipient has the option to distribute
105.40 - * your version of this file under either the CDDL, the GPL Version 2 or
105.41 - * to extend the choice of license to its licensees as provided above.
105.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
105.43 - * Version 2 license, then the option applies only if the new code is
105.44 - * made subject to such option by the copyright holder.
105.45 - */
105.46 -package org.apidesign.html.json.impl;
105.47 -
105.48 -import net.java.html.BrwsrCtx;
105.49 -import net.java.html.json.Model;
105.50 -import net.java.html.json.Models;
105.51 -import net.java.html.json.Property;
105.52 -import org.testng.Assert;
105.53 -import org.testng.annotations.Test;
105.54 -
105.55 -/**
105.56 - *
105.57 - * @author Jaroslav Tulach <jtulach@netbeans.org>
105.58 - */
105.59 -@Model(className = "Employer", properties = {
105.60 - @Property(name = "name", type = String.class)
105.61 -})
105.62 -public class EmployerTest {
105.63 - @Test public void preLoadsTheClass() {
105.64 - Employer em = Models.fromRaw(BrwsrCtx.EMPTY, Employer.class, this);
105.65 - Assert.assertNotNull(em, "Class loaded");
105.66 - em.applyBindings();
105.67 - }
105.68 -}
106.1 --- a/json/src/test/java/org/apidesign/html/json/impl/JSONListTest.java Mon Dec 16 15:48:09 2013 +0100
106.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
106.3 @@ -1,192 +0,0 @@
106.4 -/**
106.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
106.6 - *
106.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
106.8 - *
106.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
106.10 - * Other names may be trademarks of their respective owners.
106.11 - *
106.12 - * The contents of this file are subject to the terms of either the GNU
106.13 - * General Public License Version 2 only ("GPL") or the Common
106.14 - * Development and Distribution License("CDDL") (collectively, the
106.15 - * "License"). You may not use this file except in compliance with the
106.16 - * License. You can obtain a copy of the License at
106.17 - * http://www.netbeans.org/cddl-gplv2.html
106.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
106.19 - * specific language governing permissions and limitations under the
106.20 - * License. When distributing the software, include this License Header
106.21 - * Notice in each file and include the License file at
106.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
106.23 - * particular file as subject to the "Classpath" exception as provided
106.24 - * by Oracle in the GPL Version 2 section of the License file that
106.25 - * accompanied this code. If applicable, add the following below the
106.26 - * License Header, with the fields enclosed by brackets [] replaced by
106.27 - * your own identifying information:
106.28 - * "Portions Copyrighted [year] [name of copyright owner]"
106.29 - *
106.30 - * Contributor(s):
106.31 - *
106.32 - * The Original Software is NetBeans. The Initial Developer of the Original
106.33 - * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
106.34 - *
106.35 - * If you wish your version of this file to be governed by only the CDDL
106.36 - * or only the GPL Version 2, indicate your decision by adding
106.37 - * "[Contributor] elects to include this software in this distribution
106.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
106.39 - * single choice of license, a recipient has the option to distribute
106.40 - * your version of this file under either the CDDL, the GPL Version 2 or
106.41 - * to extend the choice of license to its licensees as provided above.
106.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
106.43 - * Version 2 license, then the option applies only if the new code is
106.44 - * made subject to such option by the copyright holder.
106.45 - */
106.46 -package org.apidesign.html.json.impl;
106.47 -
106.48 -import java.util.HashMap;
106.49 -import java.util.Map;
106.50 -import net.java.html.BrwsrCtx;
106.51 -import net.java.html.json.Models;
106.52 -import net.java.html.json.People;
106.53 -import net.java.html.json.Person;
106.54 -import net.java.html.json.Sex;
106.55 -import org.apidesign.html.context.spi.Contexts;
106.56 -import org.apidesign.html.json.spi.FunctionBinding;
106.57 -import org.apidesign.html.json.spi.PropertyBinding;
106.58 -import org.apidesign.html.json.spi.Technology;
106.59 -import static org.testng.Assert.*;
106.60 -import org.testng.annotations.BeforeMethod;
106.61 -import org.testng.annotations.Test;
106.62 -
106.63 -/**
106.64 - *
106.65 - * @author Jaroslav Tulach <jtulach@netbeans.org>
106.66 - */
106.67 -public class JSONListTest implements Technology<Object> {
106.68 - private boolean replaceArray;
106.69 - private final Map<String,PropertyBinding> bindings = new HashMap<String,PropertyBinding>();
106.70 -
106.71 - public JSONListTest() {
106.72 - }
106.73 -
106.74 - @BeforeMethod public void clear() {
106.75 - replaceArray = false;
106.76 - }
106.77 -
106.78 - @Test public void testConvertorOnAnObject() {
106.79 - BrwsrCtx c = Contexts.newBuilder().register(Technology.class, this, 1).build();
106.80 -
106.81 - Person p = Models.bind(new Person(), c);
106.82 - p.setFirstName("1");
106.83 - p.setLastName("2");
106.84 - p.setSex(Sex.MALE);
106.85 -
106.86 - Object real = WrapperObject.find(p);
106.87 - assertEquals(this, real, "I am the right model");
106.88 - }
106.89 -
106.90 - @Test public void testConvertorOnAnArray() {
106.91 - BrwsrCtx c = Contexts.newBuilder().register(Technology.class, this, 1).build();
106.92 -
106.93 - Person p = Models.bind(new Person(), c);
106.94 - p.setFirstName("1");
106.95 - p.setLastName("2");
106.96 - p.setSex(Sex.MALE);
106.97 -
106.98 - People people = Models.bind(new People(p), c).applyBindings();
106.99 - assertEquals(people.getInfo().toString(), "[{\"firstName\":\"1\",\"lastName\":\"2\",\"sex\":\"MALE\"}]", "Converted to real JSON");
106.100 -
106.101 - PropertyBinding pb = bindings.get("info");
106.102 - assertNotNull(pb, "Binding for info found");
106.103 -
106.104 - Object real = pb.getValue();
106.105 - assertTrue(real instanceof Object[], "It is an array: " + real);
106.106 - Object[] arr = (Object[])real;
106.107 - assertEquals(arr.length, 1, "Size is one");
106.108 - assertEquals(this, arr[0], "I am the right model");
106.109 - }
106.110 -
106.111 - @Test public void testNicknames() {
106.112 - BrwsrCtx c = Contexts.newBuilder().register(Technology.class, this, 1).build();
106.113 -
106.114 - People people = Models.bind(new People(), c).applyBindings();
106.115 - people.getNicknames().add("One");
106.116 - people.getNicknames().add("Two");
106.117 -
106.118 - PropertyBinding pb = bindings.get("nicknames");
106.119 - assertNotNull(pb, "Binding for info found");
106.120 -
106.121 - Object real = pb.getValue();
106.122 - assertTrue(real instanceof Object[], "It is an array: " + real);
106.123 - Object[] arr = (Object[])real;
106.124 - assertEquals(arr.length, 2, "Length two");
106.125 - assertEquals(arr[0], "One", "Text should be in the model");
106.126 - assertEquals(arr[1], "Two", "2nd text in the model");
106.127 - }
106.128 -
106.129 - @Test public void testConvertorOnAnArrayWithWrapper() {
106.130 - this.replaceArray = true;
106.131 - BrwsrCtx c = Contexts.newBuilder().register(Technology.class, this, 1).build();
106.132 -
106.133 - Person p = Models.bind(new Person(), c);
106.134 - p.setFirstName("1");
106.135 - p.setLastName("2");
106.136 - p.setSex(Sex.MALE);
106.137 -
106.138 - People people = Models.bind(new People(), c).applyBindings();
106.139 - people.getInfo().add(p);
106.140 -
106.141 - Object real = WrapperObject.find(people.getInfo());
106.142 - assertEquals(real, this, "I am the model of the array");
106.143 - }
106.144 -
106.145 - @Test public void bindingsOnArray() {
106.146 - this.replaceArray = true;
106.147 - BrwsrCtx c = Contexts.newBuilder().register(Technology.class, this, 1).build();
106.148 -
106.149 - People p = Models.bind(new People(), c).applyBindings();
106.150 - p.getAge().add(30);
106.151 -
106.152 - PropertyBinding pb = bindings.get("age");
106.153 - assertNotNull(pb, "There is a binding for age list");
106.154 -
106.155 - assertEquals(pb.getValue(), this, "I am the model of the array");
106.156 - }
106.157 -
106.158 - @Override
106.159 - public Object wrapModel(Object model) {
106.160 - return this;
106.161 - }
106.162 -
106.163 - @Override
106.164 - public void bind(PropertyBinding b, Object model, Object data) {
106.165 - bindings.put(b.getPropertyName(), b);
106.166 - }
106.167 -
106.168 - @Override
106.169 - public void valueHasMutated(Object data, String propertyName) {
106.170 - }
106.171 -
106.172 - @Override
106.173 - public void expose(FunctionBinding fb, Object model, Object d) {
106.174 - }
106.175 -
106.176 - @Override
106.177 - public void applyBindings(Object data) {
106.178 - }
106.179 -
106.180 - @Override
106.181 - public Object wrapArray(Object[] arr) {
106.182 - return replaceArray ? this : arr;
106.183 - }
106.184 -
106.185 - @Override
106.186 - public <M> M toModel(Class<M> modelClass, Object data) {
106.187 - return modelClass.cast(data);
106.188 - }
106.189 -
106.190 - @Override
106.191 - public void runSafe(Runnable r) {
106.192 - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
106.193 - }
106.194 -
106.195 -}
107.1 --- a/json/src/test/java/org/apidesign/html/json/impl/JSONTest.java Mon Dec 16 15:48:09 2013 +0100
107.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
107.3 @@ -1,84 +0,0 @@
107.4 -/**
107.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
107.6 - *
107.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
107.8 - *
107.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
107.10 - * Other names may be trademarks of their respective owners.
107.11 - *
107.12 - * The contents of this file are subject to the terms of either the GNU
107.13 - * General Public License Version 2 only ("GPL") or the Common
107.14 - * Development and Distribution License("CDDL") (collectively, the
107.15 - * "License"). You may not use this file except in compliance with the
107.16 - * License. You can obtain a copy of the License at
107.17 - * http://www.netbeans.org/cddl-gplv2.html
107.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
107.19 - * specific language governing permissions and limitations under the
107.20 - * License. When distributing the software, include this License Header
107.21 - * Notice in each file and include the License file at
107.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
107.23 - * particular file as subject to the "Classpath" exception as provided
107.24 - * by Oracle in the GPL Version 2 section of the License file that
107.25 - * accompanied this code. If applicable, add the following below the
107.26 - * License Header, with the fields enclosed by brackets [] replaced by
107.27 - * your own identifying information:
107.28 - * "Portions Copyrighted [year] [name of copyright owner]"
107.29 - *
107.30 - * Contributor(s):
107.31 - *
107.32 - * The Original Software is NetBeans. The Initial Developer of the Original
107.33 - * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
107.34 - *
107.35 - * If you wish your version of this file to be governed by only the CDDL
107.36 - * or only the GPL Version 2, indicate your decision by adding
107.37 - * "[Contributor] elects to include this software in this distribution
107.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
107.39 - * single choice of license, a recipient has the option to distribute
107.40 - * your version of this file under either the CDDL, the GPL Version 2 or
107.41 - * to extend the choice of license to its licensees as provided above.
107.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
107.43 - * Version 2 license, then the option applies only if the new code is
107.44 - * made subject to such option by the copyright holder.
107.45 - */
107.46 -package org.apidesign.html.json.impl;
107.47 -
107.48 -import static org.testng.Assert.*;
107.49 -import org.testng.annotations.Test;
107.50 -
107.51 -/**
107.52 - *
107.53 - * @author Jaroslav Tulach <jtulach@netbeans.org>
107.54 - */
107.55 -public class JSONTest {
107.56 -
107.57 - public JSONTest() {
107.58 - }
107.59 -
107.60 - @Test public void longToStringValue() {
107.61 - assertEquals(JSON.stringValue(Long.valueOf(1)), "1");
107.62 - }
107.63 -
107.64 - @Test public void booleanIsSortOfNumber() {
107.65 - assertEquals(JSON.numberValue(Boolean.TRUE), Integer.valueOf(1));
107.66 - assertEquals(JSON.numberValue(Boolean.FALSE), Integer.valueOf(0));
107.67 - }
107.68 -
107.69 - @Test public void numberToChar() {
107.70 - assertEquals(JSON.charValue(65), Character.valueOf('A'));
107.71 - }
107.72 - @Test public void booleanToChar() {
107.73 - assertEquals(JSON.charValue(false), Character.valueOf((char)0));
107.74 - assertEquals(JSON.charValue(true), Character.valueOf((char)1));
107.75 - }
107.76 - @Test public void stringToChar() {
107.77 - assertEquals(JSON.charValue("Ahoj"), Character.valueOf('A'));
107.78 - }
107.79 - @Test public void stringToBoolean() {
107.80 - assertEquals(JSON.boolValue("false"), Boolean.FALSE);
107.81 - assertEquals(JSON.boolValue("True"), Boolean.TRUE);
107.82 - }
107.83 - @Test public void numberToBoolean() {
107.84 - assertEquals(JSON.boolValue(0), Boolean.FALSE);
107.85 - assertEquals(JSON.boolValue(1), Boolean.TRUE);
107.86 - }
107.87 -}
108.1 --- a/json/src/test/java/org/apidesign/html/json/impl/NoPropertiesTest.java Mon Dec 16 15:48:09 2013 +0100
108.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
108.3 @@ -1,55 +0,0 @@
108.4 -/**
108.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
108.6 - *
108.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
108.8 - *
108.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
108.10 - * Other names may be trademarks of their respective owners.
108.11 - *
108.12 - * The contents of this file are subject to the terms of either the GNU
108.13 - * General Public License Version 2 only ("GPL") or the Common
108.14 - * Development and Distribution License("CDDL") (collectively, the
108.15 - * "License"). You may not use this file except in compliance with the
108.16 - * License. You can obtain a copy of the License at
108.17 - * http://www.netbeans.org/cddl-gplv2.html
108.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
108.19 - * specific language governing permissions and limitations under the
108.20 - * License. When distributing the software, include this License Header
108.21 - * Notice in each file and include the License file at
108.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
108.23 - * particular file as subject to the "Classpath" exception as provided
108.24 - * by Oracle in the GPL Version 2 section of the License file that
108.25 - * accompanied this code. If applicable, add the following below the
108.26 - * License Header, with the fields enclosed by brackets [] replaced by
108.27 - * your own identifying information:
108.28 - * "Portions Copyrighted [year] [name of copyright owner]"
108.29 - *
108.30 - * Contributor(s):
108.31 - *
108.32 - * The Original Software is NetBeans. The Initial Developer of the Original
108.33 - * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
108.34 - *
108.35 - * If you wish your version of this file to be governed by only the CDDL
108.36 - * or only the GPL Version 2, indicate your decision by adding
108.37 - * "[Contributor] elects to include this software in this distribution
108.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
108.39 - * single choice of license, a recipient has the option to distribute
108.40 - * your version of this file under either the CDDL, the GPL Version 2 or
108.41 - * to extend the choice of license to its licensees as provided above.
108.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
108.43 - * Version 2 license, then the option applies only if the new code is
108.44 - * made subject to such option by the copyright holder.
108.45 - */
108.46 -package org.apidesign.html.json.impl;
108.47 -
108.48 -import net.java.html.json.Model;
108.49 -
108.50 -/** Originally could not compile.
108.51 - *
108.52 - * @author Jaroslav Tulach <jtulach@netbeans.org>
108.53 - */
108.54 -@Model(className="NoProperties", properties = {
108.55 -})
108.56 -public class NoPropertiesTest {
108.57 -
108.58 -}
109.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
109.2 +++ b/json/src/test/java/org/netbeans/html/json/impl/ConstructorTest.java Mon Dec 16 16:59:43 2013 +0100
109.3 @@ -0,0 +1,80 @@
109.4 +/**
109.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
109.6 + *
109.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
109.8 + *
109.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
109.10 + * Other names may be trademarks of their respective owners.
109.11 + *
109.12 + * The contents of this file are subject to the terms of either the GNU
109.13 + * General Public License Version 2 only ("GPL") or the Common
109.14 + * Development and Distribution License("CDDL") (collectively, the
109.15 + * "License"). You may not use this file except in compliance with the
109.16 + * License. You can obtain a copy of the License at
109.17 + * http://www.netbeans.org/cddl-gplv2.html
109.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
109.19 + * specific language governing permissions and limitations under the
109.20 + * License. When distributing the software, include this License Header
109.21 + * Notice in each file and include the License file at
109.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
109.23 + * particular file as subject to the "Classpath" exception as provided
109.24 + * by Oracle in the GPL Version 2 section of the License file that
109.25 + * accompanied this code. If applicable, add the following below the
109.26 + * License Header, with the fields enclosed by brackets [] replaced by
109.27 + * your own identifying information:
109.28 + * "Portions Copyrighted [year] [name of copyright owner]"
109.29 + *
109.30 + * Contributor(s):
109.31 + *
109.32 + * The Original Software is NetBeans. The Initial Developer of the Original
109.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
109.34 + *
109.35 + * If you wish your version of this file to be governed by only the CDDL
109.36 + * or only the GPL Version 2, indicate your decision by adding
109.37 + * "[Contributor] elects to include this software in this distribution
109.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
109.39 + * single choice of license, a recipient has the option to distribute
109.40 + * your version of this file under either the CDDL, the GPL Version 2 or
109.41 + * to extend the choice of license to its licensees as provided above.
109.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
109.43 + * Version 2 license, then the option applies only if the new code is
109.44 + * made subject to such option by the copyright holder.
109.45 + */
109.46 +package org.netbeans.html.json.impl;
109.47 +
109.48 +import net.java.html.json.Model;
109.49 +import net.java.html.json.Property;
109.50 +import static org.testng.Assert.assertNotNull;
109.51 +import static org.testng.Assert.assertEquals;
109.52 +import org.testng.annotations.Test;
109.53 +
109.54 +/**
109.55 + *
109.56 + * @author Jaroslav Tulach <jtulach@netbeans.org>
109.57 + */
109.58 +@Model(className="Man", properties={
109.59 + @Property(name = "name", type = String.class),
109.60 + @Property(name = "other", type = Address.class, array = true),
109.61 + @Property(name = "primary", type = Address.class),
109.62 + @Property(name = "childrenNames", type = String.class, array = true)
109.63 +})
109.64 +public class ConstructorTest {
109.65 + @Model(className = "Address", properties = {
109.66 + @Property(name = "place", type = String.class)
109.67 + })
109.68 + static final class AddressModel {
109.69 + }
109.70 +
109.71 + @Test public void initializedByDefault() {
109.72 + Man m = new Man();
109.73 + assertNotNull(m.getPrimary(), "Single subobjects are initialized");
109.74 + }
109.75 +
109.76 + @Test public void hasRichConstructor() {
109.77 + Man m = new Man("Jarda", new Address("home"), new Address("work"), new Address("hotel"));
109.78 + assertEquals(m.getName(), "Jarda");
109.79 + assertNotNull(m.getPrimary(), "Primary address specified");
109.80 + assertNotNull(m.getPrimary().getPlace(), "home");
109.81 + assertEquals(m.getOther().size(), 2, "Two other addresses");
109.82 + }
109.83 +}
110.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
110.2 +++ b/json/src/test/java/org/netbeans/html/json/impl/EmployeeImpl.java Mon Dec 16 16:59:43 2013 +0100
110.3 @@ -0,0 +1,63 @@
110.4 +/**
110.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
110.6 + *
110.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
110.8 + *
110.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
110.10 + * Other names may be trademarks of their respective owners.
110.11 + *
110.12 + * The contents of this file are subject to the terms of either the GNU
110.13 + * General Public License Version 2 only ("GPL") or the Common
110.14 + * Development and Distribution License("CDDL") (collectively, the
110.15 + * "License"). You may not use this file except in compliance with the
110.16 + * License. You can obtain a copy of the License at
110.17 + * http://www.netbeans.org/cddl-gplv2.html
110.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
110.19 + * specific language governing permissions and limitations under the
110.20 + * License. When distributing the software, include this License Header
110.21 + * Notice in each file and include the License file at
110.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
110.23 + * particular file as subject to the "Classpath" exception as provided
110.24 + * by Oracle in the GPL Version 2 section of the License file that
110.25 + * accompanied this code. If applicable, add the following below the
110.26 + * License Header, with the fields enclosed by brackets [] replaced by
110.27 + * your own identifying information:
110.28 + * "Portions Copyrighted [year] [name of copyright owner]"
110.29 + *
110.30 + * Contributor(s):
110.31 + *
110.32 + * The Original Software is NetBeans. The Initial Developer of the Original
110.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
110.34 + *
110.35 + * If you wish your version of this file to be governed by only the CDDL
110.36 + * or only the GPL Version 2, indicate your decision by adding
110.37 + * "[Contributor] elects to include this software in this distribution
110.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
110.39 + * single choice of license, a recipient has the option to distribute
110.40 + * your version of this file under either the CDDL, the GPL Version 2 or
110.41 + * to extend the choice of license to its licensees as provided above.
110.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
110.43 + * Version 2 license, then the option applies only if the new code is
110.44 + * made subject to such option by the copyright holder.
110.45 + */
110.46 +package org.netbeans.html.json.impl;
110.47 +
110.48 +import net.java.html.json.Model;
110.49 +import net.java.html.json.OnReceive;
110.50 +import net.java.html.json.Person;
110.51 +import net.java.html.json.Property;
110.52 +
110.53 +/**
110.54 + *
110.55 + * @author Jaroslav Tulach <jtulach@netbeans.org>
110.56 + */
110.57 +@Model(className = "Employee", properties = {
110.58 + @Property(name = "person", type = Person.class),
110.59 + @Property(name = "employer", type = Employer.class)
110.60 +})
110.61 +public class EmployeeImpl {
110.62 + @OnReceive(url = "some/url")
110.63 + static void changePersonality(Employee e, Person p) {
110.64 + e.setPerson(p);
110.65 + }
110.66 +}
111.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
111.2 +++ b/json/src/test/java/org/netbeans/html/json/impl/EmployerTest.java Mon Dec 16 16:59:43 2013 +0100
111.3 @@ -0,0 +1,65 @@
111.4 +/**
111.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
111.6 + *
111.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
111.8 + *
111.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
111.10 + * Other names may be trademarks of their respective owners.
111.11 + *
111.12 + * The contents of this file are subject to the terms of either the GNU
111.13 + * General Public License Version 2 only ("GPL") or the Common
111.14 + * Development and Distribution License("CDDL") (collectively, the
111.15 + * "License"). You may not use this file except in compliance with the
111.16 + * License. You can obtain a copy of the License at
111.17 + * http://www.netbeans.org/cddl-gplv2.html
111.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
111.19 + * specific language governing permissions and limitations under the
111.20 + * License. When distributing the software, include this License Header
111.21 + * Notice in each file and include the License file at
111.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
111.23 + * particular file as subject to the "Classpath" exception as provided
111.24 + * by Oracle in the GPL Version 2 section of the License file that
111.25 + * accompanied this code. If applicable, add the following below the
111.26 + * License Header, with the fields enclosed by brackets [] replaced by
111.27 + * your own identifying information:
111.28 + * "Portions Copyrighted [year] [name of copyright owner]"
111.29 + *
111.30 + * Contributor(s):
111.31 + *
111.32 + * The Original Software is NetBeans. The Initial Developer of the Original
111.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
111.34 + *
111.35 + * If you wish your version of this file to be governed by only the CDDL
111.36 + * or only the GPL Version 2, indicate your decision by adding
111.37 + * "[Contributor] elects to include this software in this distribution
111.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
111.39 + * single choice of license, a recipient has the option to distribute
111.40 + * your version of this file under either the CDDL, the GPL Version 2 or
111.41 + * to extend the choice of license to its licensees as provided above.
111.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
111.43 + * Version 2 license, then the option applies only if the new code is
111.44 + * made subject to such option by the copyright holder.
111.45 + */
111.46 +package org.netbeans.html.json.impl;
111.47 +
111.48 +import net.java.html.BrwsrCtx;
111.49 +import net.java.html.json.Model;
111.50 +import net.java.html.json.Models;
111.51 +import net.java.html.json.Property;
111.52 +import org.testng.Assert;
111.53 +import org.testng.annotations.Test;
111.54 +
111.55 +/**
111.56 + *
111.57 + * @author Jaroslav Tulach <jtulach@netbeans.org>
111.58 + */
111.59 +@Model(className = "Employer", properties = {
111.60 + @Property(name = "name", type = String.class)
111.61 +})
111.62 +public class EmployerTest {
111.63 + @Test public void preLoadsTheClass() {
111.64 + Employer em = Models.fromRaw(BrwsrCtx.EMPTY, Employer.class, this);
111.65 + Assert.assertNotNull(em, "Class loaded");
111.66 + em.applyBindings();
111.67 + }
111.68 +}
112.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
112.2 +++ b/json/src/test/java/org/netbeans/html/json/impl/JSONListTest.java Mon Dec 16 16:59:43 2013 +0100
112.3 @@ -0,0 +1,192 @@
112.4 +/**
112.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
112.6 + *
112.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
112.8 + *
112.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
112.10 + * Other names may be trademarks of their respective owners.
112.11 + *
112.12 + * The contents of this file are subject to the terms of either the GNU
112.13 + * General Public License Version 2 only ("GPL") or the Common
112.14 + * Development and Distribution License("CDDL") (collectively, the
112.15 + * "License"). You may not use this file except in compliance with the
112.16 + * License. You can obtain a copy of the License at
112.17 + * http://www.netbeans.org/cddl-gplv2.html
112.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
112.19 + * specific language governing permissions and limitations under the
112.20 + * License. When distributing the software, include this License Header
112.21 + * Notice in each file and include the License file at
112.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
112.23 + * particular file as subject to the "Classpath" exception as provided
112.24 + * by Oracle in the GPL Version 2 section of the License file that
112.25 + * accompanied this code. If applicable, add the following below the
112.26 + * License Header, with the fields enclosed by brackets [] replaced by
112.27 + * your own identifying information:
112.28 + * "Portions Copyrighted [year] [name of copyright owner]"
112.29 + *
112.30 + * Contributor(s):
112.31 + *
112.32 + * The Original Software is NetBeans. The Initial Developer of the Original
112.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
112.34 + *
112.35 + * If you wish your version of this file to be governed by only the CDDL
112.36 + * or only the GPL Version 2, indicate your decision by adding
112.37 + * "[Contributor] elects to include this software in this distribution
112.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
112.39 + * single choice of license, a recipient has the option to distribute
112.40 + * your version of this file under either the CDDL, the GPL Version 2 or
112.41 + * to extend the choice of license to its licensees as provided above.
112.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
112.43 + * Version 2 license, then the option applies only if the new code is
112.44 + * made subject to such option by the copyright holder.
112.45 + */
112.46 +package org.netbeans.html.json.impl;
112.47 +
112.48 +import java.util.HashMap;
112.49 +import java.util.Map;
112.50 +import net.java.html.BrwsrCtx;
112.51 +import net.java.html.json.Models;
112.52 +import net.java.html.json.People;
112.53 +import net.java.html.json.Person;
112.54 +import net.java.html.json.Sex;
112.55 +import org.apidesign.html.context.spi.Contexts;
112.56 +import org.apidesign.html.json.spi.FunctionBinding;
112.57 +import org.apidesign.html.json.spi.PropertyBinding;
112.58 +import org.apidesign.html.json.spi.Technology;
112.59 +import static org.testng.Assert.*;
112.60 +import org.testng.annotations.BeforeMethod;
112.61 +import org.testng.annotations.Test;
112.62 +
112.63 +/**
112.64 + *
112.65 + * @author Jaroslav Tulach <jtulach@netbeans.org>
112.66 + */
112.67 +public class JSONListTest implements Technology<Object> {
112.68 + private boolean replaceArray;
112.69 + private final Map<String,PropertyBinding> bindings = new HashMap<String,PropertyBinding>();
112.70 +
112.71 + public JSONListTest() {
112.72 + }
112.73 +
112.74 + @BeforeMethod public void clear() {
112.75 + replaceArray = false;
112.76 + }
112.77 +
112.78 + @Test public void testConvertorOnAnObject() {
112.79 + BrwsrCtx c = Contexts.newBuilder().register(Technology.class, this, 1).build();
112.80 +
112.81 + Person p = Models.bind(new Person(), c);
112.82 + p.setFirstName("1");
112.83 + p.setLastName("2");
112.84 + p.setSex(Sex.MALE);
112.85 +
112.86 + Object real = WrapperObject.find(p);
112.87 + assertEquals(this, real, "I am the right model");
112.88 + }
112.89 +
112.90 + @Test public void testConvertorOnAnArray() {
112.91 + BrwsrCtx c = Contexts.newBuilder().register(Technology.class, this, 1).build();
112.92 +
112.93 + Person p = Models.bind(new Person(), c);
112.94 + p.setFirstName("1");
112.95 + p.setLastName("2");
112.96 + p.setSex(Sex.MALE);
112.97 +
112.98 + People people = Models.bind(new People(p), c).applyBindings();
112.99 + assertEquals(people.getInfo().toString(), "[{\"firstName\":\"1\",\"lastName\":\"2\",\"sex\":\"MALE\"}]", "Converted to real JSON");
112.100 +
112.101 + PropertyBinding pb = bindings.get("info");
112.102 + assertNotNull(pb, "Binding for info found");
112.103 +
112.104 + Object real = pb.getValue();
112.105 + assertTrue(real instanceof Object[], "It is an array: " + real);
112.106 + Object[] arr = (Object[])real;
112.107 + assertEquals(arr.length, 1, "Size is one");
112.108 + assertEquals(this, arr[0], "I am the right model");
112.109 + }
112.110 +
112.111 + @Test public void testNicknames() {
112.112 + BrwsrCtx c = Contexts.newBuilder().register(Technology.class, this, 1).build();
112.113 +
112.114 + People people = Models.bind(new People(), c).applyBindings();
112.115 + people.getNicknames().add("One");
112.116 + people.getNicknames().add("Two");
112.117 +
112.118 + PropertyBinding pb = bindings.get("nicknames");
112.119 + assertNotNull(pb, "Binding for info found");
112.120 +
112.121 + Object real = pb.getValue();
112.122 + assertTrue(real instanceof Object[], "It is an array: " + real);
112.123 + Object[] arr = (Object[])real;
112.124 + assertEquals(arr.length, 2, "Length two");
112.125 + assertEquals(arr[0], "One", "Text should be in the model");
112.126 + assertEquals(arr[1], "Two", "2nd text in the model");
112.127 + }
112.128 +
112.129 + @Test public void testConvertorOnAnArrayWithWrapper() {
112.130 + this.replaceArray = true;
112.131 + BrwsrCtx c = Contexts.newBuilder().register(Technology.class, this, 1).build();
112.132 +
112.133 + Person p = Models.bind(new Person(), c);
112.134 + p.setFirstName("1");
112.135 + p.setLastName("2");
112.136 + p.setSex(Sex.MALE);
112.137 +
112.138 + People people = Models.bind(new People(), c).applyBindings();
112.139 + people.getInfo().add(p);
112.140 +
112.141 + Object real = WrapperObject.find(people.getInfo());
112.142 + assertEquals(real, this, "I am the model of the array");
112.143 + }
112.144 +
112.145 + @Test public void bindingsOnArray() {
112.146 + this.replaceArray = true;
112.147 + BrwsrCtx c = Contexts.newBuilder().register(Technology.class, this, 1).build();
112.148 +
112.149 + People p = Models.bind(new People(), c).applyBindings();
112.150 + p.getAge().add(30);
112.151 +
112.152 + PropertyBinding pb = bindings.get("age");
112.153 + assertNotNull(pb, "There is a binding for age list");
112.154 +
112.155 + assertEquals(pb.getValue(), this, "I am the model of the array");
112.156 + }
112.157 +
112.158 + @Override
112.159 + public Object wrapModel(Object model) {
112.160 + return this;
112.161 + }
112.162 +
112.163 + @Override
112.164 + public void bind(PropertyBinding b, Object model, Object data) {
112.165 + bindings.put(b.getPropertyName(), b);
112.166 + }
112.167 +
112.168 + @Override
112.169 + public void valueHasMutated(Object data, String propertyName) {
112.170 + }
112.171 +
112.172 + @Override
112.173 + public void expose(FunctionBinding fb, Object model, Object d) {
112.174 + }
112.175 +
112.176 + @Override
112.177 + public void applyBindings(Object data) {
112.178 + }
112.179 +
112.180 + @Override
112.181 + public Object wrapArray(Object[] arr) {
112.182 + return replaceArray ? this : arr;
112.183 + }
112.184 +
112.185 + @Override
112.186 + public <M> M toModel(Class<M> modelClass, Object data) {
112.187 + return modelClass.cast(data);
112.188 + }
112.189 +
112.190 + @Override
112.191 + public void runSafe(Runnable r) {
112.192 + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
112.193 + }
112.194 +
112.195 +}
113.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
113.2 +++ b/json/src/test/java/org/netbeans/html/json/impl/JSONTest.java Mon Dec 16 16:59:43 2013 +0100
113.3 @@ -0,0 +1,85 @@
113.4 +/**
113.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
113.6 + *
113.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
113.8 + *
113.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
113.10 + * Other names may be trademarks of their respective owners.
113.11 + *
113.12 + * The contents of this file are subject to the terms of either the GNU
113.13 + * General Public License Version 2 only ("GPL") or the Common
113.14 + * Development and Distribution License("CDDL") (collectively, the
113.15 + * "License"). You may not use this file except in compliance with the
113.16 + * License. You can obtain a copy of the License at
113.17 + * http://www.netbeans.org/cddl-gplv2.html
113.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
113.19 + * specific language governing permissions and limitations under the
113.20 + * License. When distributing the software, include this License Header
113.21 + * Notice in each file and include the License file at
113.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
113.23 + * particular file as subject to the "Classpath" exception as provided
113.24 + * by Oracle in the GPL Version 2 section of the License file that
113.25 + * accompanied this code. If applicable, add the following below the
113.26 + * License Header, with the fields enclosed by brackets [] replaced by
113.27 + * your own identifying information:
113.28 + * "Portions Copyrighted [year] [name of copyright owner]"
113.29 + *
113.30 + * Contributor(s):
113.31 + *
113.32 + * The Original Software is NetBeans. The Initial Developer of the Original
113.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
113.34 + *
113.35 + * If you wish your version of this file to be governed by only the CDDL
113.36 + * or only the GPL Version 2, indicate your decision by adding
113.37 + * "[Contributor] elects to include this software in this distribution
113.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
113.39 + * single choice of license, a recipient has the option to distribute
113.40 + * your version of this file under either the CDDL, the GPL Version 2 or
113.41 + * to extend the choice of license to its licensees as provided above.
113.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
113.43 + * Version 2 license, then the option applies only if the new code is
113.44 + * made subject to such option by the copyright holder.
113.45 + */
113.46 +package org.netbeans.html.json.impl;
113.47 +
113.48 +import org.netbeans.html.json.impl.JSON;
113.49 +import static org.testng.Assert.*;
113.50 +import org.testng.annotations.Test;
113.51 +
113.52 +/**
113.53 + *
113.54 + * @author Jaroslav Tulach <jtulach@netbeans.org>
113.55 + */
113.56 +public class JSONTest {
113.57 +
113.58 + public JSONTest() {
113.59 + }
113.60 +
113.61 + @Test public void longToStringValue() {
113.62 + assertEquals(JSON.stringValue(Long.valueOf(1)), "1");
113.63 + }
113.64 +
113.65 + @Test public void booleanIsSortOfNumber() {
113.66 + assertEquals(JSON.numberValue(Boolean.TRUE), Integer.valueOf(1));
113.67 + assertEquals(JSON.numberValue(Boolean.FALSE), Integer.valueOf(0));
113.68 + }
113.69 +
113.70 + @Test public void numberToChar() {
113.71 + assertEquals(JSON.charValue(65), Character.valueOf('A'));
113.72 + }
113.73 + @Test public void booleanToChar() {
113.74 + assertEquals(JSON.charValue(false), Character.valueOf((char)0));
113.75 + assertEquals(JSON.charValue(true), Character.valueOf((char)1));
113.76 + }
113.77 + @Test public void stringToChar() {
113.78 + assertEquals(JSON.charValue("Ahoj"), Character.valueOf('A'));
113.79 + }
113.80 + @Test public void stringToBoolean() {
113.81 + assertEquals(JSON.boolValue("false"), Boolean.FALSE);
113.82 + assertEquals(JSON.boolValue("True"), Boolean.TRUE);
113.83 + }
113.84 + @Test public void numberToBoolean() {
113.85 + assertEquals(JSON.boolValue(0), Boolean.FALSE);
113.86 + assertEquals(JSON.boolValue(1), Boolean.TRUE);
113.87 + }
113.88 +}
114.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
114.2 +++ b/json/src/test/java/org/netbeans/html/json/impl/NoPropertiesTest.java Mon Dec 16 16:59:43 2013 +0100
114.3 @@ -0,0 +1,55 @@
114.4 +/**
114.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
114.6 + *
114.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
114.8 + *
114.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
114.10 + * Other names may be trademarks of their respective owners.
114.11 + *
114.12 + * The contents of this file are subject to the terms of either the GNU
114.13 + * General Public License Version 2 only ("GPL") or the Common
114.14 + * Development and Distribution License("CDDL") (collectively, the
114.15 + * "License"). You may not use this file except in compliance with the
114.16 + * License. You can obtain a copy of the License at
114.17 + * http://www.netbeans.org/cddl-gplv2.html
114.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
114.19 + * specific language governing permissions and limitations under the
114.20 + * License. When distributing the software, include this License Header
114.21 + * Notice in each file and include the License file at
114.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
114.23 + * particular file as subject to the "Classpath" exception as provided
114.24 + * by Oracle in the GPL Version 2 section of the License file that
114.25 + * accompanied this code. If applicable, add the following below the
114.26 + * License Header, with the fields enclosed by brackets [] replaced by
114.27 + * your own identifying information:
114.28 + * "Portions Copyrighted [year] [name of copyright owner]"
114.29 + *
114.30 + * Contributor(s):
114.31 + *
114.32 + * The Original Software is NetBeans. The Initial Developer of the Original
114.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
114.34 + *
114.35 + * If you wish your version of this file to be governed by only the CDDL
114.36 + * or only the GPL Version 2, indicate your decision by adding
114.37 + * "[Contributor] elects to include this software in this distribution
114.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
114.39 + * single choice of license, a recipient has the option to distribute
114.40 + * your version of this file under either the CDDL, the GPL Version 2 or
114.41 + * to extend the choice of license to its licensees as provided above.
114.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
114.43 + * Version 2 license, then the option applies only if the new code is
114.44 + * made subject to such option by the copyright holder.
114.45 + */
114.46 +package org.netbeans.html.json.impl;
114.47 +
114.48 +import net.java.html.json.Model;
114.49 +
114.50 +/** Originally could not compile.
114.51 + *
114.52 + * @author Jaroslav Tulach <jtulach@netbeans.org>
114.53 + */
114.54 +@Model(className="NoProperties", properties = {
114.55 +})
114.56 +public class NoPropertiesTest {
114.57 +
114.58 +}
115.1 --- a/ko-archetype-test/src/test/java/org/apidesign/html/archetype/test/ArchetypeVersionTest.java Mon Dec 16 15:48:09 2013 +0100
115.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
115.3 @@ -1,128 +0,0 @@
115.4 -/**
115.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
115.6 - *
115.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
115.8 - *
115.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
115.10 - * Other names may be trademarks of their respective owners.
115.11 - *
115.12 - * The contents of this file are subject to the terms of either the GNU
115.13 - * General Public License Version 2 only ("GPL") or the Common
115.14 - * Development and Distribution License("CDDL") (collectively, the
115.15 - * "License"). You may not use this file except in compliance with the
115.16 - * License. You can obtain a copy of the License at
115.17 - * http://www.netbeans.org/cddl-gplv2.html
115.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
115.19 - * specific language governing permissions and limitations under the
115.20 - * License. When distributing the software, include this License Header
115.21 - * Notice in each file and include the License file at
115.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
115.23 - * particular file as subject to the "Classpath" exception as provided
115.24 - * by Oracle in the GPL Version 2 section of the License file that
115.25 - * accompanied this code. If applicable, add the following below the
115.26 - * License Header, with the fields enclosed by brackets [] replaced by
115.27 - * your own identifying information:
115.28 - * "Portions Copyrighted [year] [name of copyright owner]"
115.29 - *
115.30 - * Contributor(s):
115.31 - *
115.32 - * The Original Software is NetBeans. The Initial Developer of the Original
115.33 - * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
115.34 - *
115.35 - * If you wish your version of this file to be governed by only the CDDL
115.36 - * or only the GPL Version 2, indicate your decision by adding
115.37 - * "[Contributor] elects to include this software in this distribution
115.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
115.39 - * single choice of license, a recipient has the option to distribute
115.40 - * your version of this file under either the CDDL, the GPL Version 2 or
115.41 - * to extend the choice of license to its licensees as provided above.
115.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
115.43 - * Version 2 license, then the option applies only if the new code is
115.44 - * made subject to such option by the copyright holder.
115.45 - */
115.46 -package org.apidesign.html.archetype.test;
115.47 -
115.48 -import java.io.IOException;
115.49 -import java.net.URL;
115.50 -import javax.xml.XMLConstants;
115.51 -import javax.xml.parsers.DocumentBuilderFactory;
115.52 -import javax.xml.parsers.ParserConfigurationException;
115.53 -import javax.xml.xpath.XPathConstants;
115.54 -import javax.xml.xpath.XPathExpression;
115.55 -import javax.xml.xpath.XPathExpressionException;
115.56 -import javax.xml.xpath.XPathFactory;
115.57 -import javax.xml.xpath.XPathFactoryConfigurationException;
115.58 -import org.testng.annotations.Test;
115.59 -import static org.testng.Assert.*;
115.60 -import org.testng.annotations.BeforeClass;
115.61 -import org.w3c.dom.Document;
115.62 -import org.w3c.dom.NodeList;
115.63 -import org.xml.sax.SAXException;
115.64 -
115.65 -/**
115.66 - *
115.67 - * @author Jaroslav Tulach <jtulach@netbeans.org>
115.68 - */
115.69 -public class ArchetypeVersionTest {
115.70 - private String version;
115.71 -
115.72 - public ArchetypeVersionTest() {
115.73 - }
115.74 -
115.75 - @BeforeClass public void readCurrentVersion() throws Exception {
115.76 - version = findCurrentVersion();
115.77 - assertFalse(version.isEmpty(), "There should be some version string");
115.78 - }
115.79 -
115.80 -
115.81 - @Test public void testComparePomDepsVersions() throws Exception {
115.82 - final ClassLoader l = ArchetypeVersionTest.class.getClassLoader();
115.83 - URL r = l.getResource("archetype-resources/pom.xml");
115.84 - assertNotNull(r, "Archetype pom found");
115.85 -
115.86 - final XPathFactory fact = XPathFactory.newInstance();
115.87 - XPathExpression xp2 = fact.newXPath().compile(
115.88 - "//properties/net.java.html.version/text()"
115.89 - );
115.90 -
115.91 - Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(r.openStream());
115.92 - String arch = (String) xp2.evaluate(dom, XPathConstants.STRING);
115.93 -
115.94 - assertEquals(arch, version, "net.java.html.json dependency needs to be on latest version");
115.95 - }
115.96 -
115.97 - @Test public void testNbActions() throws Exception {
115.98 - final ClassLoader l = ArchetypeVersionTest.class.getClassLoader();
115.99 - URL r = l.getResource("archetype-resources/nbactions.xml");
115.100 - assertNotNull(r, "Archetype nb file found");
115.101 -
115.102 - final XPathFactory fact = XPathFactory.newInstance();
115.103 - XPathExpression xp2 = fact.newXPath().compile(
115.104 - "//goal/text()"
115.105 - );
115.106 -
115.107 - Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(r.openStream());
115.108 - NodeList goals = (NodeList) xp2.evaluate(dom, XPathConstants.NODESET);
115.109 -
115.110 - for (int i = 0; i < goals.getLength(); i++) {
115.111 - String s = goals.item(i).getTextContent();
115.112 - if (s.contains("apidesign")) {
115.113 - assertFalse(s.matches(".*apidesign.*[0-9].*"), "No numbers: " + s);
115.114 - }
115.115 - }
115.116 - }
115.117 -
115.118 - static String findCurrentVersion() throws XPathExpressionException, IOException, ParserConfigurationException, SAXException, XPathFactoryConfigurationException {
115.119 - final ClassLoader l = ArchetypeVersionTest.class.getClassLoader();
115.120 - URL u = l.getResource("META-INF/maven/org.netbeans.html/knockout4j-archetype/pom.xml");
115.121 - assertNotNull(u, "Own pom found: " + System.getProperty("java.class.path"));
115.122 -
115.123 - final XPathFactory fact = XPathFactory.newInstance();
115.124 - fact.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
115.125 -
115.126 - XPathExpression xp = fact.newXPath().compile("project/version/text()");
115.127 -
115.128 - Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(u.openStream());
115.129 - return xp.evaluate(dom);
115.130 - }
115.131 -}
116.1 --- a/ko-archetype-test/src/test/java/org/apidesign/html/archetype/test/VerifyArchetypeTest.java Mon Dec 16 15:48:09 2013 +0100
116.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
116.3 @@ -1,99 +0,0 @@
116.4 -/**
116.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
116.6 - *
116.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
116.8 - *
116.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
116.10 - * Other names may be trademarks of their respective owners.
116.11 - *
116.12 - * The contents of this file are subject to the terms of either the GNU
116.13 - * General Public License Version 2 only ("GPL") or the Common
116.14 - * Development and Distribution License("CDDL") (collectively, the
116.15 - * "License"). You may not use this file except in compliance with the
116.16 - * License. You can obtain a copy of the License at
116.17 - * http://www.netbeans.org/cddl-gplv2.html
116.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
116.19 - * specific language governing permissions and limitations under the
116.20 - * License. When distributing the software, include this License Header
116.21 - * Notice in each file and include the License file at
116.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
116.23 - * particular file as subject to the "Classpath" exception as provided
116.24 - * by Oracle in the GPL Version 2 section of the License file that
116.25 - * accompanied this code. If applicable, add the following below the
116.26 - * License Header, with the fields enclosed by brackets [] replaced by
116.27 - * your own identifying information:
116.28 - * "Portions Copyrighted [year] [name of copyright owner]"
116.29 - *
116.30 - * Contributor(s):
116.31 - *
116.32 - * The Original Software is NetBeans. The Initial Developer of the Original
116.33 - * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
116.34 - *
116.35 - * If you wish your version of this file to be governed by only the CDDL
116.36 - * or only the GPL Version 2, indicate your decision by adding
116.37 - * "[Contributor] elects to include this software in this distribution
116.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
116.39 - * single choice of license, a recipient has the option to distribute
116.40 - * your version of this file under either the CDDL, the GPL Version 2 or
116.41 - * to extend the choice of license to its licensees as provided above.
116.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
116.43 - * Version 2 license, then the option applies only if the new code is
116.44 - * made subject to such option by the copyright holder.
116.45 - */
116.46 -package org.apidesign.html.archetype.test;
116.47 -
116.48 -import java.io.File;
116.49 -import java.util.Properties;
116.50 -import org.apache.maven.it.Verifier;
116.51 -import org.testng.annotations.Test;
116.52 -import static org.testng.Assert.*;
116.53 -
116.54 -/**
116.55 - *
116.56 - * @author Jaroslav Tulach <jtulach@netbeans.org>
116.57 - */
116.58 -public class VerifyArchetypeTest {
116.59 - @Test public void projectCompiles() throws Exception {
116.60 - final File dir = new File("target/tests/fxcompile/").getAbsoluteFile();
116.61 - generateFromArchetype(dir);
116.62 -
116.63 - File created = new File(dir, "o-a-test");
116.64 - assertTrue(created.isDirectory(), "Project created");
116.65 - assertTrue(new File(created, "pom.xml").isFile(), "Pom file is in there");
116.66 -
116.67 - Verifier v = new Verifier(created.getAbsolutePath());
116.68 - v.executeGoal("verify");
116.69 -
116.70 - v.verifyErrorFreeLog();
116.71 -
116.72 - for (String l : v.loadFile(v.getBasedir(), v.getLogFileName(), false)) {
116.73 - if (l.contains("j2js")) {
116.74 - fail("No pre-compilaton:\n" + l);
116.75 - }
116.76 - }
116.77 -
116.78 - v.verifyTextInLog("fxcompile/o-a-test/target/o-a-test-1.0-SNAPSHOT-html.java.net.zip");
116.79 - }
116.80 -
116.81 - private Verifier generateFromArchetype(final File dir, String... params) throws Exception {
116.82 - Verifier v = new Verifier(dir.getAbsolutePath());
116.83 - v.setAutoclean(false);
116.84 - v.setLogFileName("generate.log");
116.85 - v.deleteDirectory("");
116.86 - dir.mkdirs();
116.87 - Properties sysProp = v.getSystemProperties();
116.88 - sysProp.put("groupId", "org.apidesign.test");
116.89 - sysProp.put("artifactId", "o-a-test");
116.90 - sysProp.put("package", "org.apidesign.test.oat");
116.91 - sysProp.put("archetypeGroupId", "org.apidesign.html");
116.92 - sysProp.put("archetypeArtifactId", "knockout4j-archetype");
116.93 - sysProp.put("archetypeVersion", ArchetypeVersionTest.findCurrentVersion());
116.94 -
116.95 - for (String p : params) {
116.96 - v.addCliOption(p);
116.97 - }
116.98 - v.executeGoal("archetype:generate");
116.99 - v.verifyErrorFreeLog();
116.100 - return v;
116.101 - }
116.102 -}
117.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
117.2 +++ b/ko-archetype-test/src/test/java/org/netbeans/html/archetype/test/ArchetypeVersionTest.java Mon Dec 16 16:59:43 2013 +0100
117.3 @@ -0,0 +1,128 @@
117.4 +/**
117.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
117.6 + *
117.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
117.8 + *
117.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
117.10 + * Other names may be trademarks of their respective owners.
117.11 + *
117.12 + * The contents of this file are subject to the terms of either the GNU
117.13 + * General Public License Version 2 only ("GPL") or the Common
117.14 + * Development and Distribution License("CDDL") (collectively, the
117.15 + * "License"). You may not use this file except in compliance with the
117.16 + * License. You can obtain a copy of the License at
117.17 + * http://www.netbeans.org/cddl-gplv2.html
117.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
117.19 + * specific language governing permissions and limitations under the
117.20 + * License. When distributing the software, include this License Header
117.21 + * Notice in each file and include the License file at
117.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
117.23 + * particular file as subject to the "Classpath" exception as provided
117.24 + * by Oracle in the GPL Version 2 section of the License file that
117.25 + * accompanied this code. If applicable, add the following below the
117.26 + * License Header, with the fields enclosed by brackets [] replaced by
117.27 + * your own identifying information:
117.28 + * "Portions Copyrighted [year] [name of copyright owner]"
117.29 + *
117.30 + * Contributor(s):
117.31 + *
117.32 + * The Original Software is NetBeans. The Initial Developer of the Original
117.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
117.34 + *
117.35 + * If you wish your version of this file to be governed by only the CDDL
117.36 + * or only the GPL Version 2, indicate your decision by adding
117.37 + * "[Contributor] elects to include this software in this distribution
117.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
117.39 + * single choice of license, a recipient has the option to distribute
117.40 + * your version of this file under either the CDDL, the GPL Version 2 or
117.41 + * to extend the choice of license to its licensees as provided above.
117.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
117.43 + * Version 2 license, then the option applies only if the new code is
117.44 + * made subject to such option by the copyright holder.
117.45 + */
117.46 +package org.netbeans.html.archetype.test;
117.47 +
117.48 +import java.io.IOException;
117.49 +import java.net.URL;
117.50 +import javax.xml.XMLConstants;
117.51 +import javax.xml.parsers.DocumentBuilderFactory;
117.52 +import javax.xml.parsers.ParserConfigurationException;
117.53 +import javax.xml.xpath.XPathConstants;
117.54 +import javax.xml.xpath.XPathExpression;
117.55 +import javax.xml.xpath.XPathExpressionException;
117.56 +import javax.xml.xpath.XPathFactory;
117.57 +import javax.xml.xpath.XPathFactoryConfigurationException;
117.58 +import org.testng.annotations.Test;
117.59 +import static org.testng.Assert.*;
117.60 +import org.testng.annotations.BeforeClass;
117.61 +import org.w3c.dom.Document;
117.62 +import org.w3c.dom.NodeList;
117.63 +import org.xml.sax.SAXException;
117.64 +
117.65 +/**
117.66 + *
117.67 + * @author Jaroslav Tulach <jtulach@netbeans.org>
117.68 + */
117.69 +public class ArchetypeVersionTest {
117.70 + private String version;
117.71 +
117.72 + public ArchetypeVersionTest() {
117.73 + }
117.74 +
117.75 + @BeforeClass public void readCurrentVersion() throws Exception {
117.76 + version = findCurrentVersion();
117.77 + assertFalse(version.isEmpty(), "There should be some version string");
117.78 + }
117.79 +
117.80 +
117.81 + @Test public void testComparePomDepsVersions() throws Exception {
117.82 + final ClassLoader l = ArchetypeVersionTest.class.getClassLoader();
117.83 + URL r = l.getResource("archetype-resources/pom.xml");
117.84 + assertNotNull(r, "Archetype pom found");
117.85 +
117.86 + final XPathFactory fact = XPathFactory.newInstance();
117.87 + XPathExpression xp2 = fact.newXPath().compile(
117.88 + "//properties/net.java.html.version/text()"
117.89 + );
117.90 +
117.91 + Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(r.openStream());
117.92 + String arch = (String) xp2.evaluate(dom, XPathConstants.STRING);
117.93 +
117.94 + assertEquals(arch, version, "net.java.html.json dependency needs to be on latest version");
117.95 + }
117.96 +
117.97 + @Test public void testNbActions() throws Exception {
117.98 + final ClassLoader l = ArchetypeVersionTest.class.getClassLoader();
117.99 + URL r = l.getResource("archetype-resources/nbactions.xml");
117.100 + assertNotNull(r, "Archetype nb file found");
117.101 +
117.102 + final XPathFactory fact = XPathFactory.newInstance();
117.103 + XPathExpression xp2 = fact.newXPath().compile(
117.104 + "//goal/text()"
117.105 + );
117.106 +
117.107 + Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(r.openStream());
117.108 + NodeList goals = (NodeList) xp2.evaluate(dom, XPathConstants.NODESET);
117.109 +
117.110 + for (int i = 0; i < goals.getLength(); i++) {
117.111 + String s = goals.item(i).getTextContent();
117.112 + if (s.contains("apidesign")) {
117.113 + assertFalse(s.matches(".*apidesign.*[0-9].*"), "No numbers: " + s);
117.114 + }
117.115 + }
117.116 + }
117.117 +
117.118 + static String findCurrentVersion() throws XPathExpressionException, IOException, ParserConfigurationException, SAXException, XPathFactoryConfigurationException {
117.119 + final ClassLoader l = ArchetypeVersionTest.class.getClassLoader();
117.120 + URL u = l.getResource("META-INF/maven/org.netbeans.html/knockout4j-archetype/pom.xml");
117.121 + assertNotNull(u, "Own pom found: " + System.getProperty("java.class.path"));
117.122 +
117.123 + final XPathFactory fact = XPathFactory.newInstance();
117.124 + fact.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
117.125 +
117.126 + XPathExpression xp = fact.newXPath().compile("project/version/text()");
117.127 +
117.128 + Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(u.openStream());
117.129 + return xp.evaluate(dom);
117.130 + }
117.131 +}
118.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
118.2 +++ b/ko-archetype-test/src/test/java/org/netbeans/html/archetype/test/VerifyArchetypeTest.java Mon Dec 16 16:59:43 2013 +0100
118.3 @@ -0,0 +1,99 @@
118.4 +/**
118.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
118.6 + *
118.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
118.8 + *
118.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
118.10 + * Other names may be trademarks of their respective owners.
118.11 + *
118.12 + * The contents of this file are subject to the terms of either the GNU
118.13 + * General Public License Version 2 only ("GPL") or the Common
118.14 + * Development and Distribution License("CDDL") (collectively, the
118.15 + * "License"). You may not use this file except in compliance with the
118.16 + * License. You can obtain a copy of the License at
118.17 + * http://www.netbeans.org/cddl-gplv2.html
118.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
118.19 + * specific language governing permissions and limitations under the
118.20 + * License. When distributing the software, include this License Header
118.21 + * Notice in each file and include the License file at
118.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
118.23 + * particular file as subject to the "Classpath" exception as provided
118.24 + * by Oracle in the GPL Version 2 section of the License file that
118.25 + * accompanied this code. If applicable, add the following below the
118.26 + * License Header, with the fields enclosed by brackets [] replaced by
118.27 + * your own identifying information:
118.28 + * "Portions Copyrighted [year] [name of copyright owner]"
118.29 + *
118.30 + * Contributor(s):
118.31 + *
118.32 + * The Original Software is NetBeans. The Initial Developer of the Original
118.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
118.34 + *
118.35 + * If you wish your version of this file to be governed by only the CDDL
118.36 + * or only the GPL Version 2, indicate your decision by adding
118.37 + * "[Contributor] elects to include this software in this distribution
118.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
118.39 + * single choice of license, a recipient has the option to distribute
118.40 + * your version of this file under either the CDDL, the GPL Version 2 or
118.41 + * to extend the choice of license to its licensees as provided above.
118.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
118.43 + * Version 2 license, then the option applies only if the new code is
118.44 + * made subject to such option by the copyright holder.
118.45 + */
118.46 +package org.netbeans.html.archetype.test;
118.47 +
118.48 +import java.io.File;
118.49 +import java.util.Properties;
118.50 +import org.apache.maven.it.Verifier;
118.51 +import org.testng.annotations.Test;
118.52 +import static org.testng.Assert.*;
118.53 +
118.54 +/**
118.55 + *
118.56 + * @author Jaroslav Tulach <jtulach@netbeans.org>
118.57 + */
118.58 +public class VerifyArchetypeTest {
118.59 + @Test public void projectCompiles() throws Exception {
118.60 + final File dir = new File("target/tests/fxcompile/").getAbsoluteFile();
118.61 + generateFromArchetype(dir);
118.62 +
118.63 + File created = new File(dir, "o-a-test");
118.64 + assertTrue(created.isDirectory(), "Project created");
118.65 + assertTrue(new File(created, "pom.xml").isFile(), "Pom file is in there");
118.66 +
118.67 + Verifier v = new Verifier(created.getAbsolutePath());
118.68 + v.executeGoal("verify");
118.69 +
118.70 + v.verifyErrorFreeLog();
118.71 +
118.72 + for (String l : v.loadFile(v.getBasedir(), v.getLogFileName(), false)) {
118.73 + if (l.contains("j2js")) {
118.74 + fail("No pre-compilaton:\n" + l);
118.75 + }
118.76 + }
118.77 +
118.78 + v.verifyTextInLog("fxcompile/o-a-test/target/o-a-test-1.0-SNAPSHOT-html.java.net.zip");
118.79 + }
118.80 +
118.81 + private Verifier generateFromArchetype(final File dir, String... params) throws Exception {
118.82 + Verifier v = new Verifier(dir.getAbsolutePath());
118.83 + v.setAutoclean(false);
118.84 + v.setLogFileName("generate.log");
118.85 + v.deleteDirectory("");
118.86 + dir.mkdirs();
118.87 + Properties sysProp = v.getSystemProperties();
118.88 + sysProp.put("groupId", "org.apidesign.test");
118.89 + sysProp.put("artifactId", "o-a-test");
118.90 + sysProp.put("package", "org.apidesign.test.oat");
118.91 + sysProp.put("archetypeGroupId", "org.apidesign.html");
118.92 + sysProp.put("archetypeArtifactId", "knockout4j-archetype");
118.93 + sysProp.put("archetypeVersion", ArchetypeVersionTest.findCurrentVersion());
118.94 +
118.95 + for (String p : params) {
118.96 + v.addCliOption(p);
118.97 + }
118.98 + v.executeGoal("archetype:generate");
118.99 + v.verifyErrorFreeLog();
118.100 + return v;
118.101 + }
118.102 +}
119.1 --- a/ko-archetype/src/main/java/org/apidesign/html/archetype/package-info.java Mon Dec 16 15:48:09 2013 +0100
119.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
119.3 @@ -1,43 +0,0 @@
119.4 -/**
119.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
119.6 - *
119.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
119.8 - *
119.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
119.10 - * Other names may be trademarks of their respective owners.
119.11 - *
119.12 - * The contents of this file are subject to the terms of either the GNU
119.13 - * General Public License Version 2 only ("GPL") or the Common
119.14 - * Development and Distribution License("CDDL") (collectively, the
119.15 - * "License"). You may not use this file except in compliance with the
119.16 - * License. You can obtain a copy of the License at
119.17 - * http://www.netbeans.org/cddl-gplv2.html
119.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
119.19 - * specific language governing permissions and limitations under the
119.20 - * License. When distributing the software, include this License Header
119.21 - * Notice in each file and include the License file at
119.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
119.23 - * particular file as subject to the "Classpath" exception as provided
119.24 - * by Oracle in the GPL Version 2 section of the License file that
119.25 - * accompanied this code. If applicable, add the following below the
119.26 - * License Header, with the fields enclosed by brackets [] replaced by
119.27 - * your own identifying information:
119.28 - * "Portions Copyrighted [year] [name of copyright owner]"
119.29 - *
119.30 - * Contributor(s):
119.31 - *
119.32 - * The Original Software is NetBeans. The Initial Developer of the Original
119.33 - * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
119.34 - *
119.35 - * If you wish your version of this file to be governed by only the CDDL
119.36 - * or only the GPL Version 2, indicate your decision by adding
119.37 - * "[Contributor] elects to include this software in this distribution
119.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
119.39 - * single choice of license, a recipient has the option to distribute
119.40 - * your version of this file under either the CDDL, the GPL Version 2 or
119.41 - * to extend the choice of license to its licensees as provided above.
119.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
119.43 - * Version 2 license, then the option applies only if the new code is
119.44 - * made subject to such option by the copyright holder.
119.45 - */
119.46 -package org.apidesign.html.archetype;
120.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
120.2 +++ b/ko-archetype/src/main/java/org/netbeans/html/archetype/package-info.java Mon Dec 16 16:59:43 2013 +0100
120.3 @@ -0,0 +1,43 @@
120.4 +/**
120.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
120.6 + *
120.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
120.8 + *
120.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
120.10 + * Other names may be trademarks of their respective owners.
120.11 + *
120.12 + * The contents of this file are subject to the terms of either the GNU
120.13 + * General Public License Version 2 only ("GPL") or the Common
120.14 + * Development and Distribution License("CDDL") (collectively, the
120.15 + * "License"). You may not use this file except in compliance with the
120.16 + * License. You can obtain a copy of the License at
120.17 + * http://www.netbeans.org/cddl-gplv2.html
120.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
120.19 + * specific language governing permissions and limitations under the
120.20 + * License. When distributing the software, include this License Header
120.21 + * Notice in each file and include the License file at
120.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
120.23 + * particular file as subject to the "Classpath" exception as provided
120.24 + * by Oracle in the GPL Version 2 section of the License file that
120.25 + * accompanied this code. If applicable, add the following below the
120.26 + * License Header, with the fields enclosed by brackets [] replaced by
120.27 + * your own identifying information:
120.28 + * "Portions Copyrighted [year] [name of copyright owner]"
120.29 + *
120.30 + * Contributor(s):
120.31 + *
120.32 + * The Original Software is NetBeans. The Initial Developer of the Original
120.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
120.34 + *
120.35 + * If you wish your version of this file to be governed by only the CDDL
120.36 + * or only the GPL Version 2, indicate your decision by adding
120.37 + * "[Contributor] elects to include this software in this distribution
120.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
120.39 + * single choice of license, a recipient has the option to distribute
120.40 + * your version of this file under either the CDDL, the GPL Version 2 or
120.41 + * to extend the choice of license to its licensees as provided above.
120.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
120.43 + * Version 2 license, then the option applies only if the new code is
120.44 + * made subject to such option by the copyright holder.
120.45 + */
120.46 +package org.netbeans.html.archetype;
121.1 --- a/ko-fx/src/main/java/org/apidesign/html/kofx/Console.java Mon Dec 16 15:48:09 2013 +0100
121.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
121.3 @@ -1,81 +0,0 @@
121.4 -/**
121.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
121.6 - *
121.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
121.8 - *
121.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
121.10 - * Other names may be trademarks of their respective owners.
121.11 - *
121.12 - * The contents of this file are subject to the terms of either the GNU
121.13 - * General Public License Version 2 only ("GPL") or the Common
121.14 - * Development and Distribution License("CDDL") (collectively, the
121.15 - * "License"). You may not use this file except in compliance with the
121.16 - * License. You can obtain a copy of the License at
121.17 - * http://www.netbeans.org/cddl-gplv2.html
121.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
121.19 - * specific language governing permissions and limitations under the
121.20 - * License. When distributing the software, include this License Header
121.21 - * Notice in each file and include the License file at
121.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
121.23 - * particular file as subject to the "Classpath" exception as provided
121.24 - * by Oracle in the GPL Version 2 section of the License file that
121.25 - * accompanied this code. If applicable, add the following below the
121.26 - * License Header, with the fields enclosed by brackets [] replaced by
121.27 - * your own identifying information:
121.28 - * "Portions Copyrighted [year] [name of copyright owner]"
121.29 - *
121.30 - * Contributor(s):
121.31 - *
121.32 - * The Original Software is NetBeans. The Initial Developer of the Original
121.33 - * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
121.34 - *
121.35 - * If you wish your version of this file to be governed by only the CDDL
121.36 - * or only the GPL Version 2, indicate your decision by adding
121.37 - * "[Contributor] elects to include this software in this distribution
121.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
121.39 - * single choice of license, a recipient has the option to distribute
121.40 - * your version of this file under either the CDDL, the GPL Version 2 or
121.41 - * to extend the choice of license to its licensees as provided above.
121.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
121.43 - * Version 2 license, then the option applies only if the new code is
121.44 - * made subject to such option by the copyright holder.
121.45 - */
121.46 -package org.apidesign.html.kofx;
121.47 -
121.48 -import java.util.logging.Level;
121.49 -import java.util.logging.Logger;
121.50 -import net.java.html.js.JavaScriptBody;
121.51 -
121.52 -/** This is an implementation package - just
121.53 - * include its JAR on classpath and use official {@link Context} API
121.54 - * to access the functionality.
121.55 - * <p>
121.56 - * Redirects JavaScript's messages to Java's {@link Logger}.
121.57 - *
121.58 - * @author Jaroslav Tulach <jtulach@netbeans.org>
121.59 - */
121.60 -final class Console {
121.61 - private static final Logger LOG = Logger.getLogger(Console.class.getName());
121.62 -
121.63 - private Console() {
121.64 - }
121.65 -
121.66 - static void register() {
121.67 - registerImpl("log", Level.INFO);
121.68 - registerImpl("info", Level.INFO);
121.69 - registerImpl("warn", Level.WARNING);
121.70 - registerImpl("error", Level.SEVERE);
121.71 - }
121.72 -
121.73 - @JavaScriptBody(args = { "attr", "l" },
121.74 - javacall = true, body =
121.75 - " window.console[attr] = function(m) {\n"
121.76 - + " @org.apidesign.html.kofx.Console::log(Ljava/util/logging/Level;Ljava/lang/String;)(l, m);\n"
121.77 - + " };\n"
121.78 - )
121.79 - private static native void registerImpl(String attr, Level l);
121.80 -
121.81 - static void log(Level l, String msg) {
121.82 - LOG.log(l, msg);
121.83 - }
121.84 -}
122.1 --- a/ko-fx/src/main/java/org/apidesign/html/kofx/FXContext.java Mon Dec 16 15:48:09 2013 +0100
122.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
122.3 @@ -1,222 +0,0 @@
122.4 -/**
122.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
122.6 - *
122.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
122.8 - *
122.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
122.10 - * Other names may be trademarks of their respective owners.
122.11 - *
122.12 - * The contents of this file are subject to the terms of either the GNU
122.13 - * General Public License Version 2 only ("GPL") or the Common
122.14 - * Development and Distribution License("CDDL") (collectively, the
122.15 - * "License"). You may not use this file except in compliance with the
122.16 - * License. You can obtain a copy of the License at
122.17 - * http://www.netbeans.org/cddl-gplv2.html
122.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
122.19 - * specific language governing permissions and limitations under the
122.20 - * License. When distributing the software, include this License Header
122.21 - * Notice in each file and include the License file at
122.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
122.23 - * particular file as subject to the "Classpath" exception as provided
122.24 - * by Oracle in the GPL Version 2 section of the License file that
122.25 - * accompanied this code. If applicable, add the following below the
122.26 - * License Header, with the fields enclosed by brackets [] replaced by
122.27 - * your own identifying information:
122.28 - * "Portions Copyrighted [year] [name of copyright owner]"
122.29 - *
122.30 - * Contributor(s):
122.31 - *
122.32 - * The Original Software is NetBeans. The Initial Developer of the Original
122.33 - * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
122.34 - *
122.35 - * If you wish your version of this file to be governed by only the CDDL
122.36 - * or only the GPL Version 2, indicate your decision by adding
122.37 - * "[Contributor] elects to include this software in this distribution
122.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
122.39 - * single choice of license, a recipient has the option to distribute
122.40 - * your version of this file under either the CDDL, the GPL Version 2 or
122.41 - * to extend the choice of license to its licensees as provided above.
122.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
122.43 - * Version 2 license, then the option applies only if the new code is
122.44 - * made subject to such option by the copyright holder.
122.45 - */
122.46 -package org.apidesign.html.kofx;
122.47 -
122.48 -import java.io.Closeable;
122.49 -import java.io.IOException;
122.50 -import java.io.InputStream;
122.51 -import java.util.ServiceLoader;
122.52 -import java.util.logging.Logger;
122.53 -import javafx.application.Platform;
122.54 -import net.java.html.js.JavaScriptBody;
122.55 -import netscape.javascript.JSObject;
122.56 -import org.apidesign.html.boot.spi.Fn;
122.57 -import org.apidesign.html.context.spi.Contexts;
122.58 -import org.apidesign.html.json.spi.FunctionBinding;
122.59 -import org.apidesign.html.json.spi.JSONCall;
122.60 -import org.apidesign.html.json.spi.PropertyBinding;
122.61 -import org.apidesign.html.json.spi.Technology;
122.62 -import org.apidesign.html.json.spi.Transfer;
122.63 -import org.apidesign.html.json.spi.WSTransfer;
122.64 -import org.openide.util.lookup.ServiceProvider;
122.65 -
122.66 -/** This is an implementation package - just
122.67 - * include its JAR on classpath and use official {@link Context} API
122.68 - * to access the functionality.
122.69 - * <p>
122.70 - * Registers {@link ContextProvider}, so {@link ServiceLoader} can find it.
122.71 - *
122.72 - * @author Jaroslav Tulach <jtulach@netbeans.org>
122.73 - */
122.74 -public final class FXContext
122.75 -implements Technology.BatchInit<JSObject>, Transfer, WSTransfer<LoadWS> {
122.76 - static final Logger LOG = Logger.getLogger(FXContext.class.getName());
122.77 - private static Boolean javaScriptEnabled;
122.78 - private final Fn.Presenter browserContext;
122.79 -
122.80 - public FXContext(Fn.Presenter browserContext) {
122.81 - this.browserContext = browserContext;
122.82 - }
122.83 -
122.84 - @JavaScriptBody(args = {}, body = "return true;")
122.85 - private static boolean isJavaScriptEnabledJs() {
122.86 - return false;
122.87 - }
122.88 -
122.89 - static boolean isJavaScriptEnabled() {
122.90 - if (javaScriptEnabled != null) {
122.91 - return javaScriptEnabled;
122.92 - }
122.93 - return javaScriptEnabled = isJavaScriptEnabledJs();
122.94 - }
122.95 -
122.96 - final boolean areWebSocketsSupported() {
122.97 - return LoadWS.isSupported();
122.98 - }
122.99 -
122.100 -
122.101 - @Override
122.102 - public JSObject wrapModel(Object model, PropertyBinding[] propArr, FunctionBinding[] funcArr) {
122.103 - String[] propNames = new String[propArr.length];
122.104 - boolean[] propReadOnly = new boolean[propArr.length];
122.105 - Object[] propValues = new Object[propArr.length];
122.106 - for (int i = 0; i < propNames.length; i++) {
122.107 - propNames[i] = propArr[i].getPropertyName();
122.108 - propReadOnly[i] = propArr[i].isReadOnly();
122.109 - propValues[i] = propArr[i].getValue();
122.110 - }
122.111 - String[] funcNames = new String[funcArr.length];
122.112 - for (int i = 0; i < funcNames.length; i++) {
122.113 - funcNames[i] = funcArr[i].getFunctionName();
122.114 - }
122.115 -
122.116 - return Knockout.wrapModel(model,
122.117 - propNames, propReadOnly, Knockout.toArray(propValues), propArr,
122.118 - funcNames, funcArr
122.119 - );
122.120 - }
122.121 -
122.122 - @Override
122.123 - public JSObject wrapModel(Object model) {
122.124 - throw new UnsupportedOperationException();
122.125 - }
122.126 -
122.127 - @Override
122.128 - public void bind(PropertyBinding b, Object model, JSObject data) {
122.129 - throw new UnsupportedOperationException();
122.130 - }
122.131 -
122.132 - @Override
122.133 - public void valueHasMutated(JSObject data, String propertyName) {
122.134 - Knockout.valueHasMutated(data, propertyName);
122.135 - }
122.136 -
122.137 - @Override
122.138 - public void expose(FunctionBinding fb, Object model, JSObject d) {
122.139 - throw new UnsupportedOperationException();
122.140 - }
122.141 -
122.142 - @Override
122.143 - public void applyBindings(JSObject data) {
122.144 - Knockout.applyBindings(data);
122.145 - }
122.146 -
122.147 - @Override
122.148 - public Object wrapArray(Object[] arr) {
122.149 - return Knockout.toArray(arr);
122.150 - }
122.151 -
122.152 - @Override
122.153 - public void extract(Object obj, String[] props, Object[] values) {
122.154 - LoadJSON.extractJSON(obj, props, values);
122.155 - }
122.156 -
122.157 - @Override
122.158 - public void loadJSON(final JSONCall call) {
122.159 - LoadJSON.loadJSON(call);
122.160 - }
122.161 -
122.162 - @Override
122.163 - public <M> M toModel(Class<M> modelClass, Object data) {
122.164 - if (data instanceof JSObject) {
122.165 - data = ((JSObject)data).getMember("ko-fx.model"); // NOI18N
122.166 - }
122.167 - return modelClass.cast(data);
122.168 - }
122.169 -
122.170 - @Override
122.171 - public Object toJSON(InputStream is) throws IOException {
122.172 - return LoadJSON.parse(is);
122.173 - }
122.174 -
122.175 - @Override
122.176 - public void runSafe(final Runnable r) {
122.177 - class Wrap implements Runnable {
122.178 - @Override public void run() {
122.179 - try (Closeable c = Fn.activate(browserContext)) {
122.180 - r.run();
122.181 - } catch (IOException ex) {
122.182 - // cannot be thrown
122.183 - }
122.184 - }
122.185 - }
122.186 - Wrap w = new Wrap();
122.187 -
122.188 - if (Platform.isFxApplicationThread()) {
122.189 - w.run();
122.190 - } else {
122.191 - Platform.runLater(w);
122.192 - }
122.193 - }
122.194 -
122.195 - @Override
122.196 - public LoadWS open(String url, JSONCall onReply) {
122.197 - return new LoadWS(onReply, url);
122.198 - }
122.199 -
122.200 - @Override
122.201 - public void send(LoadWS socket, JSONCall data) {
122.202 - socket.send(data);
122.203 - }
122.204 -
122.205 - @Override
122.206 - public void close(LoadWS socket) {
122.207 - socket.close();
122.208 - }
122.209 -
122.210 - @ServiceProvider(service = Contexts.Provider.class)
122.211 - public static final class Prvdr implements Contexts.Provider {
122.212 - @Override
122.213 - public void fillContext(Contexts.Builder context, Class<?> requestor) {
122.214 - if (isJavaScriptEnabled()) {
122.215 - FXContext c = new FXContext(Fn.activePresenter());
122.216 -
122.217 - context.register(Technology.class, c, 100);
122.218 - context.register(Transfer.class, c, 100);
122.219 - if (c.areWebSocketsSupported()) {
122.220 - context.register(WSTransfer.class, c, 100);
122.221 - }
122.222 - }
122.223 - }
122.224 - }
122.225 -}
123.1 --- a/ko-fx/src/main/java/org/apidesign/html/kofx/Knockout.java Mon Dec 16 15:48:09 2013 +0100
123.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
123.3 @@ -1,145 +0,0 @@
123.4 -/**
123.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
123.6 - *
123.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
123.8 - *
123.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
123.10 - * Other names may be trademarks of their respective owners.
123.11 - *
123.12 - * The contents of this file are subject to the terms of either the GNU
123.13 - * General Public License Version 2 only ("GPL") or the Common
123.14 - * Development and Distribution License("CDDL") (collectively, the
123.15 - * "License"). You may not use this file except in compliance with the
123.16 - * License. You can obtain a copy of the License at
123.17 - * http://www.netbeans.org/cddl-gplv2.html
123.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
123.19 - * specific language governing permissions and limitations under the
123.20 - * License. When distributing the software, include this License Header
123.21 - * Notice in each file and include the License file at
123.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
123.23 - * particular file as subject to the "Classpath" exception as provided
123.24 - * by Oracle in the GPL Version 2 section of the License file that
123.25 - * accompanied this code. If applicable, add the following below the
123.26 - * License Header, with the fields enclosed by brackets [] replaced by
123.27 - * your own identifying information:
123.28 - * "Portions Copyrighted [year] [name of copyright owner]"
123.29 - *
123.30 - * Contributor(s):
123.31 - *
123.32 - * The Original Software is NetBeans. The Initial Developer of the Original
123.33 - * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
123.34 - *
123.35 - * If you wish your version of this file to be governed by only the CDDL
123.36 - * or only the GPL Version 2, indicate your decision by adding
123.37 - * "[Contributor] elects to include this software in this distribution
123.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
123.39 - * single choice of license, a recipient has the option to distribute
123.40 - * your version of this file under either the CDDL, the GPL Version 2 or
123.41 - * to extend the choice of license to its licensees as provided above.
123.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
123.43 - * Version 2 license, then the option applies only if the new code is
123.44 - * made subject to such option by the copyright holder.
123.45 - */
123.46 -package org.apidesign.html.kofx;
123.47 -
123.48 -import net.java.html.js.JavaScriptBody;
123.49 -import net.java.html.js.JavaScriptResource;
123.50 -import net.java.html.json.Model;
123.51 -import netscape.javascript.JSObject;
123.52 -import org.apidesign.html.json.spi.FunctionBinding;
123.53 -import org.apidesign.html.json.spi.PropertyBinding;
123.54 -
123.55 -/** This is an implementation package - just
123.56 - * include its JAR on classpath and use official {@link Context} API
123.57 - * to access the functionality.
123.58 - * <p>
123.59 - * Provides binding between {@link Model models} and knockout.js running
123.60 - * inside a JavaFX WebView.
123.61 - *
123.62 - * @author Jaroslav Tulach <jtulach@netbeans.org>
123.63 - */
123.64 -@JavaScriptResource("knockout-2.2.1.js")
123.65 -final class Knockout {
123.66 - static final JSObject KObject;
123.67 - static {
123.68 - Console.register();
123.69 - KObject = (JSObject) kObj();
123.70 - }
123.71 -
123.72 - static Object toArray(Object[] arr) {
123.73 - return KObject.call("array", arr);
123.74 - }
123.75 -
123.76 - @JavaScriptBody(args = { "model", "prop" }, body =
123.77 - "if (model) {\n"
123.78 - + " var koProp = model[prop];\n"
123.79 - + " if (koProp && koProp['valueHasMutated']) {\n"
123.80 - + " koProp['valueHasMutated']();\n"
123.81 - + " }\n"
123.82 - + "}\n"
123.83 - )
123.84 - public native static void valueHasMutated(JSObject model, String prop);
123.85 -
123.86 - @JavaScriptBody(args = { "bindings" }, body = "ko.applyBindings(bindings);")
123.87 - native static void applyBindings(Object bindings);
123.88 -
123.89 - @JavaScriptBody(args = {}, body =
123.90 - " var k = {};"
123.91 - + " k.array= function() {"
123.92 - + " return Array.prototype.slice.call(arguments);"
123.93 - + " };"
123.94 - + " return k;"
123.95 - )
123.96 - private static native Object kObj();
123.97 -
123.98 -
123.99 - @JavaScriptBody(
123.100 - javacall = true,
123.101 - args = {"model", "propNames", "propReadOnly", "propValues", "propArr", "funcNames", "funcArr"},
123.102 - body
123.103 - = "var ret = {};\n"
123.104 - + "ret['ko-fx.model'] = model;\n"
123.105 - + "function koComputed(name, readOnly, value, prop) {\n"
123.106 - + " function realGetter() {\n"
123.107 - + " try {"
123.108 - + " var v = prop.@org.apidesign.html.json.spi.PropertyBinding::getValue()();"
123.109 - + " return v;"
123.110 - + " } catch (e) {"
123.111 - + " alert(\"Cannot call getValue on \" + model + \" prop: \" + name + \" error: \" + e);"
123.112 - + " }"
123.113 - + " }\n"
123.114 - + " var activeGetter = function() { return value; };\n"
123.115 - + " var bnd = {"
123.116 - + " read: function() {"
123.117 - + " var r = activeGetter();"
123.118 - + " activeGetter = realGetter;"
123.119 - + " return r;"
123.120 - + " },"
123.121 - + " owner: ret\n"
123.122 - + " };\n"
123.123 - + " if (!readOnly) {\n"
123.124 - + " bnd.write = function(val) {\n"
123.125 - + " prop.@org.apidesign.html.json.spi.PropertyBinding::setValue(Ljava/lang/Object;)(val);\n"
123.126 - + " };"
123.127 - + " };"
123.128 - + " ret[name] = ko.computed(bnd);"
123.129 - + "}\n"
123.130 - + "for (var i = 0; i < propNames.length; i++) {\n"
123.131 - + " koComputed(propNames[i], propReadOnly[i], propValues[i], propArr[i]);\n"
123.132 - + "}\n"
123.133 - + "function koExpose(name, func) {\n"
123.134 - + " ret[name] = function(data, ev) {\n"
123.135 - + " func.@org.apidesign.html.json.spi.FunctionBinding::call(Ljava/lang/Object;Ljava/lang/Object;)(data, ev);\n"
123.136 - + " };\n"
123.137 - + "}\n"
123.138 - + "for (var i = 0; i < funcNames.length; i++) {\n"
123.139 - + " koExpose(funcNames[i], funcArr[i]);\n"
123.140 - + "}\n"
123.141 - + "return ret;\n"
123.142 - )
123.143 - static native JSObject wrapModel(
123.144 - Object model,
123.145 - String[] propNames, boolean[] propReadOnly, Object propValues, PropertyBinding[] propArr,
123.146 - String[] funcNames, FunctionBinding[] funcArr
123.147 - );
123.148 -}
124.1 --- a/ko-fx/src/main/java/org/apidesign/html/kofx/LoadJSON.java Mon Dec 16 15:48:09 2013 +0100
124.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
124.3 @@ -1,267 +0,0 @@
124.4 -/**
124.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
124.6 - *
124.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
124.8 - *
124.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
124.10 - * Other names may be trademarks of their respective owners.
124.11 - *
124.12 - * The contents of this file are subject to the terms of either the GNU
124.13 - * General Public License Version 2 only ("GPL") or the Common
124.14 - * Development and Distribution License("CDDL") (collectively, the
124.15 - * "License"). You may not use this file except in compliance with the
124.16 - * License. You can obtain a copy of the License at
124.17 - * http://www.netbeans.org/cddl-gplv2.html
124.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
124.19 - * specific language governing permissions and limitations under the
124.20 - * License. When distributing the software, include this License Header
124.21 - * Notice in each file and include the License file at
124.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
124.23 - * particular file as subject to the "Classpath" exception as provided
124.24 - * by Oracle in the GPL Version 2 section of the License file that
124.25 - * accompanied this code. If applicable, add the following below the
124.26 - * License Header, with the fields enclosed by brackets [] replaced by
124.27 - * your own identifying information:
124.28 - * "Portions Copyrighted [year] [name of copyright owner]"
124.29 - *
124.30 - * Contributor(s):
124.31 - *
124.32 - * The Original Software is NetBeans. The Initial Developer of the Original
124.33 - * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
124.34 - *
124.35 - * If you wish your version of this file to be governed by only the CDDL
124.36 - * or only the GPL Version 2, indicate your decision by adding
124.37 - * "[Contributor] elects to include this software in this distribution
124.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
124.39 - * single choice of license, a recipient has the option to distribute
124.40 - * your version of this file under either the CDDL, the GPL Version 2 or
124.41 - * to extend the choice of license to its licensees as provided above.
124.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
124.43 - * Version 2 license, then the option applies only if the new code is
124.44 - * made subject to such option by the copyright holder.
124.45 - */
124.46 -package org.apidesign.html.kofx;
124.47 -
124.48 -import java.io.IOException;
124.49 -import java.io.InputStream;
124.50 -import java.io.InputStreamReader;
124.51 -import java.io.OutputStream;
124.52 -import java.io.PushbackInputStream;
124.53 -import java.io.Reader;
124.54 -import java.net.HttpURLConnection;
124.55 -import java.net.MalformedURLException;
124.56 -import java.net.URL;
124.57 -import java.net.URLConnection;
124.58 -import java.util.Iterator;
124.59 -import java.util.concurrent.Executor;
124.60 -import java.util.concurrent.Executors;
124.61 -import java.util.concurrent.ThreadFactory;
124.62 -import java.util.logging.Level;
124.63 -import java.util.logging.Logger;
124.64 -import javafx.application.Platform;
124.65 -import net.java.html.js.JavaScriptBody;
124.66 -import netscape.javascript.JSObject;
124.67 -import org.apidesign.html.json.spi.JSONCall;
124.68 -import org.json.JSONArray;
124.69 -import org.json.JSONException;
124.70 -import org.json.JSONObject;
124.71 -import org.json.JSONTokener;
124.72 -
124.73 -/** This is an implementation package - just
124.74 - * include its JAR on classpath and use official {@link Context} API
124.75 - * to access the functionality.
124.76 - *
124.77 - * @author Jaroslav Tulach <jtulach@netbeans.org>
124.78 - */
124.79 -final class LoadJSON implements Runnable {
124.80 - private static final Logger LOG = FXContext.LOG;
124.81 - private static final Executor REQ = Executors.newCachedThreadPool(new ThreadFactory() {
124.82 - @Override
124.83 - public Thread newThread(Runnable runnable) {
124.84 - Thread thread = Executors.defaultThreadFactory().newThread(runnable);
124.85 - thread.setDaemon(true);
124.86 - return thread;
124.87 - }
124.88 - });
124.89 -
124.90 - private final JSONCall call;
124.91 - private final URL base;
124.92 - private Throwable error;
124.93 - private Object json;
124.94 -
124.95 -
124.96 - private LoadJSON(JSONCall call) {
124.97 - this.call = call;
124.98 - URL b;
124.99 - try {
124.100 - b = new URL(findBaseURL());
124.101 - } catch (MalformedURLException ex) {
124.102 - LOG.log(Level.SEVERE, "Can't find base url for " + call.composeURL("dummy"), ex);
124.103 - b = null;
124.104 - }
124.105 - this.base = b;
124.106 - }
124.107 -
124.108 - public static void loadJSON(JSONCall call) {
124.109 - assert !"WebSocket".equals(call.getMethod());
124.110 - REQ.execute(new LoadJSON((call)));
124.111 - }
124.112 -
124.113 - @Override
124.114 - public void run() {
124.115 - if (Platform.isFxApplicationThread()) {
124.116 - if (error != null) {
124.117 - call.notifyError(error);
124.118 - } else {
124.119 - call.notifySuccess(json);
124.120 - }
124.121 - return;
124.122 - }
124.123 - final String url;
124.124 - if (call.isJSONP()) {
124.125 - url = call.composeURL("dummy");
124.126 - } else {
124.127 - url = call.composeURL(null);
124.128 - }
124.129 - try {
124.130 - final URL u = new URL(base, url.replace(" ", "%20"));
124.131 - URLConnection conn = u.openConnection();
124.132 - if (conn instanceof HttpURLConnection) {
124.133 - HttpURLConnection huc = (HttpURLConnection) conn;
124.134 - if (call.getMethod() != null) {
124.135 - huc.setRequestMethod(call.getMethod());
124.136 - }
124.137 - if (call.isDoOutput()) {
124.138 - huc.setDoOutput(true);
124.139 - final OutputStream os = huc.getOutputStream();
124.140 - call.writeData(os);
124.141 - os.flush();
124.142 - }
124.143 - }
124.144 - final PushbackInputStream is = new PushbackInputStream(
124.145 - conn.getInputStream(), 1
124.146 - );
124.147 - boolean array = false;
124.148 - boolean string = false;
124.149 - if (call.isJSONP()) {
124.150 - for (;;) {
124.151 - int ch = is.read();
124.152 - if (ch == -1) {
124.153 - break;
124.154 - }
124.155 - if (ch == '[') {
124.156 - is.unread(ch);
124.157 - array = true;
124.158 - break;
124.159 - }
124.160 - if (ch == '{') {
124.161 - is.unread(ch);
124.162 - break;
124.163 - }
124.164 - }
124.165 - } else {
124.166 - int ch = is.read();
124.167 - if (ch == -1) {
124.168 - string = true;
124.169 - } else {
124.170 - array = ch == '[';
124.171 - is.unread(ch);
124.172 - if (!array && ch != '{') {
124.173 - string = true;
124.174 - }
124.175 - }
124.176 - }
124.177 - try {
124.178 - if (string) {
124.179 - throw new JSONException("");
124.180 - }
124.181 - Reader r = new InputStreamReader(is, "UTF-8");
124.182 -
124.183 - JSONTokener tok = new JSONTokener(r);
124.184 - Object obj;
124.185 - obj = array ? new JSONArray(tok) : new JSONObject(tok);
124.186 - json = convertToArray(obj);
124.187 - } catch (JSONException ex) {
124.188 - Reader r = new InputStreamReader(is, "UTF-8");
124.189 - StringBuilder sb = new StringBuilder();
124.190 - for (;;) {
124.191 - int ch = r.read();
124.192 - if (ch == -1) {
124.193 - break;
124.194 - }
124.195 - sb.append((char)ch);
124.196 - }
124.197 - json = sb.toString();
124.198 - }
124.199 - } catch (IOException ex) {
124.200 - error = ex;
124.201 - } finally {
124.202 - Platform.runLater(this);
124.203 - }
124.204 - }
124.205 -
124.206 - static Object convertToArray(Object o) throws JSONException {
124.207 - if (o instanceof JSONArray) {
124.208 - JSONArray ja = (JSONArray)o;
124.209 - Object[] arr = new Object[ja.length()];
124.210 - for (int i = 0; i < arr.length; i++) {
124.211 - arr[i] = convertToArray(ja.get(i));
124.212 - }
124.213 - return arr;
124.214 - } else if (o instanceof JSONObject) {
124.215 - JSONObject obj = (JSONObject)o;
124.216 - Iterator it = obj.keys();
124.217 - while (it.hasNext()) {
124.218 - String key = (String)it.next();
124.219 - obj.put(key, convertToArray(obj.get(key)));
124.220 - }
124.221 - return obj;
124.222 - } else {
124.223 - return o;
124.224 - }
124.225 - }
124.226 -
124.227 - public static void extractJSON(Object jsonObject, String[] props, Object[] values) {
124.228 - if (jsonObject instanceof JSONObject) {
124.229 - JSONObject obj = (JSONObject)jsonObject;
124.230 - for (int i = 0; i < props.length; i++) {
124.231 - try {
124.232 - values[i] = obj.has(props[i]) ? obj.get(props[i]) : null;
124.233 - } catch (JSONException ex) {
124.234 - LoadJSON.LOG.log(Level.SEVERE, "Can't read " + props[i] + " from " + jsonObject, ex);
124.235 - }
124.236 - }
124.237 - }
124.238 - if (jsonObject instanceof JSObject) {
124.239 - JSObject obj = (JSObject)jsonObject;
124.240 - for (int i = 0; i < props.length; i++) {
124.241 - Object val = obj.getMember(props[i]);
124.242 - values[i] = isDefined(val) ? val : null;
124.243 - }
124.244 - }
124.245 - }
124.246 -
124.247 - public static Object parse(InputStream is) throws IOException {
124.248 - try {
124.249 - InputStreamReader r = new InputStreamReader(is, "UTF-8");
124.250 - JSONTokener t = new JSONTokener(r);
124.251 - return new JSONObject(t);
124.252 - } catch (JSONException ex) {
124.253 - throw new IOException(ex);
124.254 - }
124.255 - }
124.256 -
124.257 - @JavaScriptBody(args = { }, body =
124.258 - "var h;"
124.259 - + "if (!!window && !!window.location && !!window.location.href)\n"
124.260 - + " h = window.location.href;\n"
124.261 - + "else "
124.262 - + " h = null;"
124.263 - + "return h;\n"
124.264 - )
124.265 - private static native String findBaseURL();
124.266 -
124.267 - private static boolean isDefined(Object val) {
124.268 - return !"undefined".equals(val);
124.269 - }
124.270 -}
125.1 --- a/ko-fx/src/main/java/org/apidesign/html/kofx/LoadWS.java Mon Dec 16 15:48:09 2013 +0100
125.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
125.3 @@ -1,149 +0,0 @@
125.4 -/**
125.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
125.6 - *
125.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
125.8 - *
125.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
125.10 - * Other names may be trademarks of their respective owners.
125.11 - *
125.12 - * The contents of this file are subject to the terms of either the GNU
125.13 - * General Public License Version 2 only ("GPL") or the Common
125.14 - * Development and Distribution License("CDDL") (collectively, the
125.15 - * "License"). You may not use this file except in compliance with the
125.16 - * License. You can obtain a copy of the License at
125.17 - * http://www.netbeans.org/cddl-gplv2.html
125.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
125.19 - * specific language governing permissions and limitations under the
125.20 - * License. When distributing the software, include this License Header
125.21 - * Notice in each file and include the License file at
125.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
125.23 - * particular file as subject to the "Classpath" exception as provided
125.24 - * by Oracle in the GPL Version 2 section of the License file that
125.25 - * accompanied this code. If applicable, add the following below the
125.26 - * License Header, with the fields enclosed by brackets [] replaced by
125.27 - * your own identifying information:
125.28 - * "Portions Copyrighted [year] [name of copyright owner]"
125.29 - *
125.30 - * Contributor(s):
125.31 - *
125.32 - * The Original Software is NetBeans. The Initial Developer of the Original
125.33 - * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
125.34 - *
125.35 - * If you wish your version of this file to be governed by only the CDDL
125.36 - * or only the GPL Version 2, indicate your decision by adding
125.37 - * "[Contributor] elects to include this software in this distribution
125.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
125.39 - * single choice of license, a recipient has the option to distribute
125.40 - * your version of this file under either the CDDL, the GPL Version 2 or
125.41 - * to extend the choice of license to its licensees as provided above.
125.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
125.43 - * Version 2 license, then the option applies only if the new code is
125.44 - * made subject to such option by the copyright holder.
125.45 - */
125.46 -package org.apidesign.html.kofx;
125.47 -
125.48 -import net.java.html.js.JavaScriptBody;
125.49 -import org.apidesign.html.json.spi.JSONCall;
125.50 -import org.json.JSONArray;
125.51 -import org.json.JSONException;
125.52 -import org.json.JSONObject;
125.53 -import org.json.JSONTokener;
125.54 -
125.55 -/** Communication with WebSockets for WebView 1.8.
125.56 - *
125.57 - * @author Jaroslav Tulach <jtulach@netbeans.org>
125.58 - */
125.59 -final class LoadWS {
125.60 - private static final boolean SUPPORTED = isWebSocket();
125.61 - private final Object ws;
125.62 - private final JSONCall call;
125.63 -
125.64 - LoadWS(JSONCall first, String url) {
125.65 - call = first;
125.66 - ws = initWebSocket(this, url);
125.67 - if (ws == null) {
125.68 - first.notifyError(new IllegalArgumentException("Wrong URL: " + url));
125.69 - }
125.70 - }
125.71 -
125.72 - static boolean isSupported() {
125.73 - return SUPPORTED;
125.74 - }
125.75 -
125.76 - void send(JSONCall call) {
125.77 - push(call);
125.78 - }
125.79 -
125.80 - private synchronized void push(JSONCall call) {
125.81 - send(ws, call.getMessage());
125.82 - }
125.83 -
125.84 - void onOpen(Object ev) {
125.85 - if (!call.isDoOutput()) {
125.86 - call.notifySuccess(null);
125.87 - }
125.88 - }
125.89 -
125.90 - void onMessage(Object ev, String data) {
125.91 - Object json;
125.92 - try {
125.93 - data = data.trim();
125.94 -
125.95 - JSONTokener tok = new JSONTokener(data);
125.96 - Object obj;
125.97 - obj = data.startsWith("[") ? new JSONArray(tok) : new JSONObject(tok);
125.98 - json = LoadJSON.convertToArray(obj);
125.99 - } catch (JSONException ex) {
125.100 - json = data;
125.101 - }
125.102 - call.notifySuccess(json);
125.103 - }
125.104 -
125.105 - void onError(Object ev) {
125.106 - call.notifyError(new Exception(ev.toString()));
125.107 - }
125.108 -
125.109 - void onClose(boolean wasClean, int code, String reason) {
125.110 - call.notifyError(null);
125.111 - }
125.112 -
125.113 - @JavaScriptBody(args = {}, body = "if (window.WebSocket) return true; else return false;")
125.114 - private static boolean isWebSocket() {
125.115 - return false;
125.116 - }
125.117 -
125.118 - @JavaScriptBody(args = { "back", "url" }, javacall = true, body = ""
125.119 - + "if (window.WebSocket) {"
125.120 - + " try {"
125.121 - + " var ws = new window.WebSocket(url);"
125.122 - + " ws.onopen = function(ev) { back.@org.apidesign.html.kofx.LoadWS::onOpen(Ljava/lang/Object;)(ev); };"
125.123 - + " ws.onmessage = function(ev) { back.@org.apidesign.html.kofx.LoadWS::onMessage(Ljava/lang/Object;Ljava/lang/String;)(ev, ev.data); };"
125.124 - + " ws.onerror = function(ev) { back.@org.apidesign.html.kofx.LoadWS::onError(Ljava/lang/Object;)(ev); };"
125.125 - + " ws.onclose = function(ev) { back.@org.apidesign.html.kofx.LoadWS::onClose(ZILjava/lang/String;)(ev.wasClean, ev.code, ev.reason); };"
125.126 - + " return ws;"
125.127 - + " } catch (ex) {"
125.128 - + " return null;"
125.129 - + " }"
125.130 - + "} else {"
125.131 - + " return null;"
125.132 - + "}"
125.133 - )
125.134 - private static Object initWebSocket(Object back, String url) {
125.135 - return null;
125.136 - }
125.137 -
125.138 -
125.139 - @JavaScriptBody(args = { "ws", "msg" }, body = ""
125.140 - + "ws.send(msg);"
125.141 - )
125.142 - private void send(Object ws, String msg) {
125.143 - }
125.144 -
125.145 - @JavaScriptBody(args = { "ws" }, body = "ws.close();")
125.146 - private static void close(Object ws) {
125.147 - }
125.148 -
125.149 - void close() {
125.150 - close(ws);
125.151 - }
125.152 -}
126.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
126.2 +++ b/ko-fx/src/main/java/org/netbeans/html/kofx/Console.java Mon Dec 16 16:59:43 2013 +0100
126.3 @@ -0,0 +1,81 @@
126.4 +/**
126.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
126.6 + *
126.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
126.8 + *
126.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
126.10 + * Other names may be trademarks of their respective owners.
126.11 + *
126.12 + * The contents of this file are subject to the terms of either the GNU
126.13 + * General Public License Version 2 only ("GPL") or the Common
126.14 + * Development and Distribution License("CDDL") (collectively, the
126.15 + * "License"). You may not use this file except in compliance with the
126.16 + * License. You can obtain a copy of the License at
126.17 + * http://www.netbeans.org/cddl-gplv2.html
126.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
126.19 + * specific language governing permissions and limitations under the
126.20 + * License. When distributing the software, include this License Header
126.21 + * Notice in each file and include the License file at
126.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
126.23 + * particular file as subject to the "Classpath" exception as provided
126.24 + * by Oracle in the GPL Version 2 section of the License file that
126.25 + * accompanied this code. If applicable, add the following below the
126.26 + * License Header, with the fields enclosed by brackets [] replaced by
126.27 + * your own identifying information:
126.28 + * "Portions Copyrighted [year] [name of copyright owner]"
126.29 + *
126.30 + * Contributor(s):
126.31 + *
126.32 + * The Original Software is NetBeans. The Initial Developer of the Original
126.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
126.34 + *
126.35 + * If you wish your version of this file to be governed by only the CDDL
126.36 + * or only the GPL Version 2, indicate your decision by adding
126.37 + * "[Contributor] elects to include this software in this distribution
126.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
126.39 + * single choice of license, a recipient has the option to distribute
126.40 + * your version of this file under either the CDDL, the GPL Version 2 or
126.41 + * to extend the choice of license to its licensees as provided above.
126.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
126.43 + * Version 2 license, then the option applies only if the new code is
126.44 + * made subject to such option by the copyright holder.
126.45 + */
126.46 +package org.netbeans.html.kofx;
126.47 +
126.48 +import java.util.logging.Level;
126.49 +import java.util.logging.Logger;
126.50 +import net.java.html.js.JavaScriptBody;
126.51 +
126.52 +/** This is an implementation package - just
126.53 + * include its JAR on classpath and use official {@link Context} API
126.54 + * to access the functionality.
126.55 + * <p>
126.56 + * Redirects JavaScript's messages to Java's {@link Logger}.
126.57 + *
126.58 + * @author Jaroslav Tulach <jtulach@netbeans.org>
126.59 + */
126.60 +final class Console {
126.61 + private static final Logger LOG = Logger.getLogger(Console.class.getName());
126.62 +
126.63 + private Console() {
126.64 + }
126.65 +
126.66 + static void register() {
126.67 + registerImpl("log", Level.INFO);
126.68 + registerImpl("info", Level.INFO);
126.69 + registerImpl("warn", Level.WARNING);
126.70 + registerImpl("error", Level.SEVERE);
126.71 + }
126.72 +
126.73 + @JavaScriptBody(args = { "attr", "l" },
126.74 + javacall = true, body =
126.75 + " window.console[attr] = function(m) {\n"
126.76 + + " @org.netbeans.html.kofx.Console::log(Ljava/util/logging/Level;Ljava/lang/String;)(l, m);\n"
126.77 + + " };\n"
126.78 + )
126.79 + private static native void registerImpl(String attr, Level l);
126.80 +
126.81 + static void log(Level l, String msg) {
126.82 + LOG.log(l, msg);
126.83 + }
126.84 +}
127.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
127.2 +++ b/ko-fx/src/main/java/org/netbeans/html/kofx/FXContext.java Mon Dec 16 16:59:43 2013 +0100
127.3 @@ -0,0 +1,222 @@
127.4 +/**
127.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
127.6 + *
127.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
127.8 + *
127.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
127.10 + * Other names may be trademarks of their respective owners.
127.11 + *
127.12 + * The contents of this file are subject to the terms of either the GNU
127.13 + * General Public License Version 2 only ("GPL") or the Common
127.14 + * Development and Distribution License("CDDL") (collectively, the
127.15 + * "License"). You may not use this file except in compliance with the
127.16 + * License. You can obtain a copy of the License at
127.17 + * http://www.netbeans.org/cddl-gplv2.html
127.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
127.19 + * specific language governing permissions and limitations under the
127.20 + * License. When distributing the software, include this License Header
127.21 + * Notice in each file and include the License file at
127.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
127.23 + * particular file as subject to the "Classpath" exception as provided
127.24 + * by Oracle in the GPL Version 2 section of the License file that
127.25 + * accompanied this code. If applicable, add the following below the
127.26 + * License Header, with the fields enclosed by brackets [] replaced by
127.27 + * your own identifying information:
127.28 + * "Portions Copyrighted [year] [name of copyright owner]"
127.29 + *
127.30 + * Contributor(s):
127.31 + *
127.32 + * The Original Software is NetBeans. The Initial Developer of the Original
127.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
127.34 + *
127.35 + * If you wish your version of this file to be governed by only the CDDL
127.36 + * or only the GPL Version 2, indicate your decision by adding
127.37 + * "[Contributor] elects to include this software in this distribution
127.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
127.39 + * single choice of license, a recipient has the option to distribute
127.40 + * your version of this file under either the CDDL, the GPL Version 2 or
127.41 + * to extend the choice of license to its licensees as provided above.
127.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
127.43 + * Version 2 license, then the option applies only if the new code is
127.44 + * made subject to such option by the copyright holder.
127.45 + */
127.46 +package org.netbeans.html.kofx;
127.47 +
127.48 +import java.io.Closeable;
127.49 +import java.io.IOException;
127.50 +import java.io.InputStream;
127.51 +import java.util.ServiceLoader;
127.52 +import java.util.logging.Logger;
127.53 +import javafx.application.Platform;
127.54 +import net.java.html.js.JavaScriptBody;
127.55 +import netscape.javascript.JSObject;
127.56 +import org.apidesign.html.boot.spi.Fn;
127.57 +import org.apidesign.html.context.spi.Contexts;
127.58 +import org.apidesign.html.json.spi.FunctionBinding;
127.59 +import org.apidesign.html.json.spi.JSONCall;
127.60 +import org.apidesign.html.json.spi.PropertyBinding;
127.61 +import org.apidesign.html.json.spi.Technology;
127.62 +import org.apidesign.html.json.spi.Transfer;
127.63 +import org.apidesign.html.json.spi.WSTransfer;
127.64 +import org.openide.util.lookup.ServiceProvider;
127.65 +
127.66 +/** This is an implementation package - just
127.67 + * include its JAR on classpath and use official {@link Context} API
127.68 + * to access the functionality.
127.69 + * <p>
127.70 + * Registers {@link ContextProvider}, so {@link ServiceLoader} can find it.
127.71 + *
127.72 + * @author Jaroslav Tulach <jtulach@netbeans.org>
127.73 + */
127.74 +public final class FXContext
127.75 +implements Technology.BatchInit<JSObject>, Transfer, WSTransfer<LoadWS> {
127.76 + static final Logger LOG = Logger.getLogger(FXContext.class.getName());
127.77 + private static Boolean javaScriptEnabled;
127.78 + private final Fn.Presenter browserContext;
127.79 +
127.80 + public FXContext(Fn.Presenter browserContext) {
127.81 + this.browserContext = browserContext;
127.82 + }
127.83 +
127.84 + @JavaScriptBody(args = {}, body = "return true;")
127.85 + private static boolean isJavaScriptEnabledJs() {
127.86 + return false;
127.87 + }
127.88 +
127.89 + static boolean isJavaScriptEnabled() {
127.90 + if (javaScriptEnabled != null) {
127.91 + return javaScriptEnabled;
127.92 + }
127.93 + return javaScriptEnabled = isJavaScriptEnabledJs();
127.94 + }
127.95 +
127.96 + final boolean areWebSocketsSupported() {
127.97 + return LoadWS.isSupported();
127.98 + }
127.99 +
127.100 +
127.101 + @Override
127.102 + public JSObject wrapModel(Object model, PropertyBinding[] propArr, FunctionBinding[] funcArr) {
127.103 + String[] propNames = new String[propArr.length];
127.104 + boolean[] propReadOnly = new boolean[propArr.length];
127.105 + Object[] propValues = new Object[propArr.length];
127.106 + for (int i = 0; i < propNames.length; i++) {
127.107 + propNames[i] = propArr[i].getPropertyName();
127.108 + propReadOnly[i] = propArr[i].isReadOnly();
127.109 + propValues[i] = propArr[i].getValue();
127.110 + }
127.111 + String[] funcNames = new String[funcArr.length];
127.112 + for (int i = 0; i < funcNames.length; i++) {
127.113 + funcNames[i] = funcArr[i].getFunctionName();
127.114 + }
127.115 +
127.116 + return Knockout.wrapModel(model,
127.117 + propNames, propReadOnly, Knockout.toArray(propValues), propArr,
127.118 + funcNames, funcArr
127.119 + );
127.120 + }
127.121 +
127.122 + @Override
127.123 + public JSObject wrapModel(Object model) {
127.124 + throw new UnsupportedOperationException();
127.125 + }
127.126 +
127.127 + @Override
127.128 + public void bind(PropertyBinding b, Object model, JSObject data) {
127.129 + throw new UnsupportedOperationException();
127.130 + }
127.131 +
127.132 + @Override
127.133 + public void valueHasMutated(JSObject data, String propertyName) {
127.134 + Knockout.valueHasMutated(data, propertyName);
127.135 + }
127.136 +
127.137 + @Override
127.138 + public void expose(FunctionBinding fb, Object model, JSObject d) {
127.139 + throw new UnsupportedOperationException();
127.140 + }
127.141 +
127.142 + @Override
127.143 + public void applyBindings(JSObject data) {
127.144 + Knockout.applyBindings(data);
127.145 + }
127.146 +
127.147 + @Override
127.148 + public Object wrapArray(Object[] arr) {
127.149 + return Knockout.toArray(arr);
127.150 + }
127.151 +
127.152 + @Override
127.153 + public void extract(Object obj, String[] props, Object[] values) {
127.154 + LoadJSON.extractJSON(obj, props, values);
127.155 + }
127.156 +
127.157 + @Override
127.158 + public void loadJSON(final JSONCall call) {
127.159 + LoadJSON.loadJSON(call);
127.160 + }
127.161 +
127.162 + @Override
127.163 + public <M> M toModel(Class<M> modelClass, Object data) {
127.164 + if (data instanceof JSObject) {
127.165 + data = ((JSObject)data).getMember("ko-fx.model"); // NOI18N
127.166 + }
127.167 + return modelClass.cast(data);
127.168 + }
127.169 +
127.170 + @Override
127.171 + public Object toJSON(InputStream is) throws IOException {
127.172 + return LoadJSON.parse(is);
127.173 + }
127.174 +
127.175 + @Override
127.176 + public void runSafe(final Runnable r) {
127.177 + class Wrap implements Runnable {
127.178 + @Override public void run() {
127.179 + try (Closeable c = Fn.activate(browserContext)) {
127.180 + r.run();
127.181 + } catch (IOException ex) {
127.182 + // cannot be thrown
127.183 + }
127.184 + }
127.185 + }
127.186 + Wrap w = new Wrap();
127.187 +
127.188 + if (Platform.isFxApplicationThread()) {
127.189 + w.run();
127.190 + } else {
127.191 + Platform.runLater(w);
127.192 + }
127.193 + }
127.194 +
127.195 + @Override
127.196 + public LoadWS open(String url, JSONCall onReply) {
127.197 + return new LoadWS(onReply, url);
127.198 + }
127.199 +
127.200 + @Override
127.201 + public void send(LoadWS socket, JSONCall data) {
127.202 + socket.send(data);
127.203 + }
127.204 +
127.205 + @Override
127.206 + public void close(LoadWS socket) {
127.207 + socket.close();
127.208 + }
127.209 +
127.210 + @ServiceProvider(service = Contexts.Provider.class)
127.211 + public static final class Prvdr implements Contexts.Provider {
127.212 + @Override
127.213 + public void fillContext(Contexts.Builder context, Class<?> requestor) {
127.214 + if (isJavaScriptEnabled()) {
127.215 + FXContext c = new FXContext(Fn.activePresenter());
127.216 +
127.217 + context.register(Technology.class, c, 100);
127.218 + context.register(Transfer.class, c, 100);
127.219 + if (c.areWebSocketsSupported()) {
127.220 + context.register(WSTransfer.class, c, 100);
127.221 + }
127.222 + }
127.223 + }
127.224 + }
127.225 +}
128.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
128.2 +++ b/ko-fx/src/main/java/org/netbeans/html/kofx/Knockout.java Mon Dec 16 16:59:43 2013 +0100
128.3 @@ -0,0 +1,145 @@
128.4 +/**
128.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
128.6 + *
128.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
128.8 + *
128.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
128.10 + * Other names may be trademarks of their respective owners.
128.11 + *
128.12 + * The contents of this file are subject to the terms of either the GNU
128.13 + * General Public License Version 2 only ("GPL") or the Common
128.14 + * Development and Distribution License("CDDL") (collectively, the
128.15 + * "License"). You may not use this file except in compliance with the
128.16 + * License. You can obtain a copy of the License at
128.17 + * http://www.netbeans.org/cddl-gplv2.html
128.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
128.19 + * specific language governing permissions and limitations under the
128.20 + * License. When distributing the software, include this License Header
128.21 + * Notice in each file and include the License file at
128.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
128.23 + * particular file as subject to the "Classpath" exception as provided
128.24 + * by Oracle in the GPL Version 2 section of the License file that
128.25 + * accompanied this code. If applicable, add the following below the
128.26 + * License Header, with the fields enclosed by brackets [] replaced by
128.27 + * your own identifying information:
128.28 + * "Portions Copyrighted [year] [name of copyright owner]"
128.29 + *
128.30 + * Contributor(s):
128.31 + *
128.32 + * The Original Software is NetBeans. The Initial Developer of the Original
128.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
128.34 + *
128.35 + * If you wish your version of this file to be governed by only the CDDL
128.36 + * or only the GPL Version 2, indicate your decision by adding
128.37 + * "[Contributor] elects to include this software in this distribution
128.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
128.39 + * single choice of license, a recipient has the option to distribute
128.40 + * your version of this file under either the CDDL, the GPL Version 2 or
128.41 + * to extend the choice of license to its licensees as provided above.
128.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
128.43 + * Version 2 license, then the option applies only if the new code is
128.44 + * made subject to such option by the copyright holder.
128.45 + */
128.46 +package org.netbeans.html.kofx;
128.47 +
128.48 +import net.java.html.js.JavaScriptBody;
128.49 +import net.java.html.js.JavaScriptResource;
128.50 +import net.java.html.json.Model;
128.51 +import netscape.javascript.JSObject;
128.52 +import org.apidesign.html.json.spi.FunctionBinding;
128.53 +import org.apidesign.html.json.spi.PropertyBinding;
128.54 +
128.55 +/** This is an implementation package - just
128.56 + * include its JAR on classpath and use official {@link Context} API
128.57 + * to access the functionality.
128.58 + * <p>
128.59 + * Provides binding between {@link Model models} and knockout.js running
128.60 + * inside a JavaFX WebView.
128.61 + *
128.62 + * @author Jaroslav Tulach <jtulach@netbeans.org>
128.63 + */
128.64 +@JavaScriptResource("knockout-2.2.1.js")
128.65 +final class Knockout {
128.66 + static final JSObject KObject;
128.67 + static {
128.68 + Console.register();
128.69 + KObject = (JSObject) kObj();
128.70 + }
128.71 +
128.72 + static Object toArray(Object[] arr) {
128.73 + return KObject.call("array", arr);
128.74 + }
128.75 +
128.76 + @JavaScriptBody(args = { "model", "prop" }, body =
128.77 + "if (model) {\n"
128.78 + + " var koProp = model[prop];\n"
128.79 + + " if (koProp && koProp['valueHasMutated']) {\n"
128.80 + + " koProp['valueHasMutated']();\n"
128.81 + + " }\n"
128.82 + + "}\n"
128.83 + )
128.84 + public native static void valueHasMutated(JSObject model, String prop);
128.85 +
128.86 + @JavaScriptBody(args = { "bindings" }, body = "ko.applyBindings(bindings);")
128.87 + native static void applyBindings(Object bindings);
128.88 +
128.89 + @JavaScriptBody(args = {}, body =
128.90 + " var k = {};"
128.91 + + " k.array= function() {"
128.92 + + " return Array.prototype.slice.call(arguments);"
128.93 + + " };"
128.94 + + " return k;"
128.95 + )
128.96 + private static native Object kObj();
128.97 +
128.98 +
128.99 + @JavaScriptBody(
128.100 + javacall = true,
128.101 + args = {"model", "propNames", "propReadOnly", "propValues", "propArr", "funcNames", "funcArr"},
128.102 + body
128.103 + = "var ret = {};\n"
128.104 + + "ret['ko-fx.model'] = model;\n"
128.105 + + "function koComputed(name, readOnly, value, prop) {\n"
128.106 + + " function realGetter() {\n"
128.107 + + " try {"
128.108 + + " var v = prop.@org.apidesign.html.json.spi.PropertyBinding::getValue()();"
128.109 + + " return v;"
128.110 + + " } catch (e) {"
128.111 + + " alert(\"Cannot call getValue on \" + model + \" prop: \" + name + \" error: \" + e);"
128.112 + + " }"
128.113 + + " }\n"
128.114 + + " var activeGetter = function() { return value; };\n"
128.115 + + " var bnd = {"
128.116 + + " read: function() {"
128.117 + + " var r = activeGetter();"
128.118 + + " activeGetter = realGetter;"
128.119 + + " return r;"
128.120 + + " },"
128.121 + + " owner: ret\n"
128.122 + + " };\n"
128.123 + + " if (!readOnly) {\n"
128.124 + + " bnd.write = function(val) {\n"
128.125 + + " prop.@org.apidesign.html.json.spi.PropertyBinding::setValue(Ljava/lang/Object;)(val);\n"
128.126 + + " };"
128.127 + + " };"
128.128 + + " ret[name] = ko.computed(bnd);"
128.129 + + "}\n"
128.130 + + "for (var i = 0; i < propNames.length; i++) {\n"
128.131 + + " koComputed(propNames[i], propReadOnly[i], propValues[i], propArr[i]);\n"
128.132 + + "}\n"
128.133 + + "function koExpose(name, func) {\n"
128.134 + + " ret[name] = function(data, ev) {\n"
128.135 + + " func.@org.apidesign.html.json.spi.FunctionBinding::call(Ljava/lang/Object;Ljava/lang/Object;)(data, ev);\n"
128.136 + + " };\n"
128.137 + + "}\n"
128.138 + + "for (var i = 0; i < funcNames.length; i++) {\n"
128.139 + + " koExpose(funcNames[i], funcArr[i]);\n"
128.140 + + "}\n"
128.141 + + "return ret;\n"
128.142 + )
128.143 + static native JSObject wrapModel(
128.144 + Object model,
128.145 + String[] propNames, boolean[] propReadOnly, Object propValues, PropertyBinding[] propArr,
128.146 + String[] funcNames, FunctionBinding[] funcArr
128.147 + );
128.148 +}
129.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
129.2 +++ b/ko-fx/src/main/java/org/netbeans/html/kofx/LoadJSON.java Mon Dec 16 16:59:43 2013 +0100
129.3 @@ -0,0 +1,267 @@
129.4 +/**
129.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
129.6 + *
129.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
129.8 + *
129.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
129.10 + * Other names may be trademarks of their respective owners.
129.11 + *
129.12 + * The contents of this file are subject to the terms of either the GNU
129.13 + * General Public License Version 2 only ("GPL") or the Common
129.14 + * Development and Distribution License("CDDL") (collectively, the
129.15 + * "License"). You may not use this file except in compliance with the
129.16 + * License. You can obtain a copy of the License at
129.17 + * http://www.netbeans.org/cddl-gplv2.html
129.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
129.19 + * specific language governing permissions and limitations under the
129.20 + * License. When distributing the software, include this License Header
129.21 + * Notice in each file and include the License file at
129.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
129.23 + * particular file as subject to the "Classpath" exception as provided
129.24 + * by Oracle in the GPL Version 2 section of the License file that
129.25 + * accompanied this code. If applicable, add the following below the
129.26 + * License Header, with the fields enclosed by brackets [] replaced by
129.27 + * your own identifying information:
129.28 + * "Portions Copyrighted [year] [name of copyright owner]"
129.29 + *
129.30 + * Contributor(s):
129.31 + *
129.32 + * The Original Software is NetBeans. The Initial Developer of the Original
129.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
129.34 + *
129.35 + * If you wish your version of this file to be governed by only the CDDL
129.36 + * or only the GPL Version 2, indicate your decision by adding
129.37 + * "[Contributor] elects to include this software in this distribution
129.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
129.39 + * single choice of license, a recipient has the option to distribute
129.40 + * your version of this file under either the CDDL, the GPL Version 2 or
129.41 + * to extend the choice of license to its licensees as provided above.
129.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
129.43 + * Version 2 license, then the option applies only if the new code is
129.44 + * made subject to such option by the copyright holder.
129.45 + */
129.46 +package org.netbeans.html.kofx;
129.47 +
129.48 +import java.io.IOException;
129.49 +import java.io.InputStream;
129.50 +import java.io.InputStreamReader;
129.51 +import java.io.OutputStream;
129.52 +import java.io.PushbackInputStream;
129.53 +import java.io.Reader;
129.54 +import java.net.HttpURLConnection;
129.55 +import java.net.MalformedURLException;
129.56 +import java.net.URL;
129.57 +import java.net.URLConnection;
129.58 +import java.util.Iterator;
129.59 +import java.util.concurrent.Executor;
129.60 +import java.util.concurrent.Executors;
129.61 +import java.util.concurrent.ThreadFactory;
129.62 +import java.util.logging.Level;
129.63 +import java.util.logging.Logger;
129.64 +import javafx.application.Platform;
129.65 +import net.java.html.js.JavaScriptBody;
129.66 +import netscape.javascript.JSObject;
129.67 +import org.apidesign.html.json.spi.JSONCall;
129.68 +import org.json.JSONArray;
129.69 +import org.json.JSONException;
129.70 +import org.json.JSONObject;
129.71 +import org.json.JSONTokener;
129.72 +
129.73 +/** This is an implementation package - just
129.74 + * include its JAR on classpath and use official {@link Context} API
129.75 + * to access the functionality.
129.76 + *
129.77 + * @author Jaroslav Tulach <jtulach@netbeans.org>
129.78 + */
129.79 +final class LoadJSON implements Runnable {
129.80 + private static final Logger LOG = FXContext.LOG;
129.81 + private static final Executor REQ = Executors.newCachedThreadPool(new ThreadFactory() {
129.82 + @Override
129.83 + public Thread newThread(Runnable runnable) {
129.84 + Thread thread = Executors.defaultThreadFactory().newThread(runnable);
129.85 + thread.setDaemon(true);
129.86 + return thread;
129.87 + }
129.88 + });
129.89 +
129.90 + private final JSONCall call;
129.91 + private final URL base;
129.92 + private Throwable error;
129.93 + private Object json;
129.94 +
129.95 +
129.96 + private LoadJSON(JSONCall call) {
129.97 + this.call = call;
129.98 + URL b;
129.99 + try {
129.100 + b = new URL(findBaseURL());
129.101 + } catch (MalformedURLException ex) {
129.102 + LOG.log(Level.SEVERE, "Can't find base url for " + call.composeURL("dummy"), ex);
129.103 + b = null;
129.104 + }
129.105 + this.base = b;
129.106 + }
129.107 +
129.108 + public static void loadJSON(JSONCall call) {
129.109 + assert !"WebSocket".equals(call.getMethod());
129.110 + REQ.execute(new LoadJSON((call)));
129.111 + }
129.112 +
129.113 + @Override
129.114 + public void run() {
129.115 + if (Platform.isFxApplicationThread()) {
129.116 + if (error != null) {
129.117 + call.notifyError(error);
129.118 + } else {
129.119 + call.notifySuccess(json);
129.120 + }
129.121 + return;
129.122 + }
129.123 + final String url;
129.124 + if (call.isJSONP()) {
129.125 + url = call.composeURL("dummy");
129.126 + } else {
129.127 + url = call.composeURL(null);
129.128 + }
129.129 + try {
129.130 + final URL u = new URL(base, url.replace(" ", "%20"));
129.131 + URLConnection conn = u.openConnection();
129.132 + if (conn instanceof HttpURLConnection) {
129.133 + HttpURLConnection huc = (HttpURLConnection) conn;
129.134 + if (call.getMethod() != null) {
129.135 + huc.setRequestMethod(call.getMethod());
129.136 + }
129.137 + if (call.isDoOutput()) {
129.138 + huc.setDoOutput(true);
129.139 + final OutputStream os = huc.getOutputStream();
129.140 + call.writeData(os);
129.141 + os.flush();
129.142 + }
129.143 + }
129.144 + final PushbackInputStream is = new PushbackInputStream(
129.145 + conn.getInputStream(), 1
129.146 + );
129.147 + boolean array = false;
129.148 + boolean string = false;
129.149 + if (call.isJSONP()) {
129.150 + for (;;) {
129.151 + int ch = is.read();
129.152 + if (ch == -1) {
129.153 + break;
129.154 + }
129.155 + if (ch == '[') {
129.156 + is.unread(ch);
129.157 + array = true;
129.158 + break;
129.159 + }
129.160 + if (ch == '{') {
129.161 + is.unread(ch);
129.162 + break;
129.163 + }
129.164 + }
129.165 + } else {
129.166 + int ch = is.read();
129.167 + if (ch == -1) {
129.168 + string = true;
129.169 + } else {
129.170 + array = ch == '[';
129.171 + is.unread(ch);
129.172 + if (!array && ch != '{') {
129.173 + string = true;
129.174 + }
129.175 + }
129.176 + }
129.177 + try {
129.178 + if (string) {
129.179 + throw new JSONException("");
129.180 + }
129.181 + Reader r = new InputStreamReader(is, "UTF-8");
129.182 +
129.183 + JSONTokener tok = new JSONTokener(r);
129.184 + Object obj;
129.185 + obj = array ? new JSONArray(tok) : new JSONObject(tok);
129.186 + json = convertToArray(obj);
129.187 + } catch (JSONException ex) {
129.188 + Reader r = new InputStreamReader(is, "UTF-8");
129.189 + StringBuilder sb = new StringBuilder();
129.190 + for (;;) {
129.191 + int ch = r.read();
129.192 + if (ch == -1) {
129.193 + break;
129.194 + }
129.195 + sb.append((char)ch);
129.196 + }
129.197 + json = sb.toString();
129.198 + }
129.199 + } catch (IOException ex) {
129.200 + error = ex;
129.201 + } finally {
129.202 + Platform.runLater(this);
129.203 + }
129.204 + }
129.205 +
129.206 + static Object convertToArray(Object o) throws JSONException {
129.207 + if (o instanceof JSONArray) {
129.208 + JSONArray ja = (JSONArray)o;
129.209 + Object[] arr = new Object[ja.length()];
129.210 + for (int i = 0; i < arr.length; i++) {
129.211 + arr[i] = convertToArray(ja.get(i));
129.212 + }
129.213 + return arr;
129.214 + } else if (o instanceof JSONObject) {
129.215 + JSONObject obj = (JSONObject)o;
129.216 + Iterator it = obj.keys();
129.217 + while (it.hasNext()) {
129.218 + String key = (String)it.next();
129.219 + obj.put(key, convertToArray(obj.get(key)));
129.220 + }
129.221 + return obj;
129.222 + } else {
129.223 + return o;
129.224 + }
129.225 + }
129.226 +
129.227 + public static void extractJSON(Object jsonObject, String[] props, Object[] values) {
129.228 + if (jsonObject instanceof JSONObject) {
129.229 + JSONObject obj = (JSONObject)jsonObject;
129.230 + for (int i = 0; i < props.length; i++) {
129.231 + try {
129.232 + values[i] = obj.has(props[i]) ? obj.get(props[i]) : null;
129.233 + } catch (JSONException ex) {
129.234 + LoadJSON.LOG.log(Level.SEVERE, "Can't read " + props[i] + " from " + jsonObject, ex);
129.235 + }
129.236 + }
129.237 + }
129.238 + if (jsonObject instanceof JSObject) {
129.239 + JSObject obj = (JSObject)jsonObject;
129.240 + for (int i = 0; i < props.length; i++) {
129.241 + Object val = obj.getMember(props[i]);
129.242 + values[i] = isDefined(val) ? val : null;
129.243 + }
129.244 + }
129.245 + }
129.246 +
129.247 + public static Object parse(InputStream is) throws IOException {
129.248 + try {
129.249 + InputStreamReader r = new InputStreamReader(is, "UTF-8");
129.250 + JSONTokener t = new JSONTokener(r);
129.251 + return new JSONObject(t);
129.252 + } catch (JSONException ex) {
129.253 + throw new IOException(ex);
129.254 + }
129.255 + }
129.256 +
129.257 + @JavaScriptBody(args = { }, body =
129.258 + "var h;"
129.259 + + "if (!!window && !!window.location && !!window.location.href)\n"
129.260 + + " h = window.location.href;\n"
129.261 + + "else "
129.262 + + " h = null;"
129.263 + + "return h;\n"
129.264 + )
129.265 + private static native String findBaseURL();
129.266 +
129.267 + private static boolean isDefined(Object val) {
129.268 + return !"undefined".equals(val);
129.269 + }
129.270 +}
130.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
130.2 +++ b/ko-fx/src/main/java/org/netbeans/html/kofx/LoadWS.java Mon Dec 16 16:59:43 2013 +0100
130.3 @@ -0,0 +1,149 @@
130.4 +/**
130.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
130.6 + *
130.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
130.8 + *
130.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
130.10 + * Other names may be trademarks of their respective owners.
130.11 + *
130.12 + * The contents of this file are subject to the terms of either the GNU
130.13 + * General Public License Version 2 only ("GPL") or the Common
130.14 + * Development and Distribution License("CDDL") (collectively, the
130.15 + * "License"). You may not use this file except in compliance with the
130.16 + * License. You can obtain a copy of the License at
130.17 + * http://www.netbeans.org/cddl-gplv2.html
130.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
130.19 + * specific language governing permissions and limitations under the
130.20 + * License. When distributing the software, include this License Header
130.21 + * Notice in each file and include the License file at
130.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
130.23 + * particular file as subject to the "Classpath" exception as provided
130.24 + * by Oracle in the GPL Version 2 section of the License file that
130.25 + * accompanied this code. If applicable, add the following below the
130.26 + * License Header, with the fields enclosed by brackets [] replaced by
130.27 + * your own identifying information:
130.28 + * "Portions Copyrighted [year] [name of copyright owner]"
130.29 + *
130.30 + * Contributor(s):
130.31 + *
130.32 + * The Original Software is NetBeans. The Initial Developer of the Original
130.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
130.34 + *
130.35 + * If you wish your version of this file to be governed by only the CDDL
130.36 + * or only the GPL Version 2, indicate your decision by adding
130.37 + * "[Contributor] elects to include this software in this distribution
130.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
130.39 + * single choice of license, a recipient has the option to distribute
130.40 + * your version of this file under either the CDDL, the GPL Version 2 or
130.41 + * to extend the choice of license to its licensees as provided above.
130.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
130.43 + * Version 2 license, then the option applies only if the new code is
130.44 + * made subject to such option by the copyright holder.
130.45 + */
130.46 +package org.netbeans.html.kofx;
130.47 +
130.48 +import net.java.html.js.JavaScriptBody;
130.49 +import org.apidesign.html.json.spi.JSONCall;
130.50 +import org.json.JSONArray;
130.51 +import org.json.JSONException;
130.52 +import org.json.JSONObject;
130.53 +import org.json.JSONTokener;
130.54 +
130.55 +/** Communication with WebSockets for WebView 1.8.
130.56 + *
130.57 + * @author Jaroslav Tulach <jtulach@netbeans.org>
130.58 + */
130.59 +final class LoadWS {
130.60 + private static final boolean SUPPORTED = isWebSocket();
130.61 + private final Object ws;
130.62 + private final JSONCall call;
130.63 +
130.64 + LoadWS(JSONCall first, String url) {
130.65 + call = first;
130.66 + ws = initWebSocket(this, url);
130.67 + if (ws == null) {
130.68 + first.notifyError(new IllegalArgumentException("Wrong URL: " + url));
130.69 + }
130.70 + }
130.71 +
130.72 + static boolean isSupported() {
130.73 + return SUPPORTED;
130.74 + }
130.75 +
130.76 + void send(JSONCall call) {
130.77 + push(call);
130.78 + }
130.79 +
130.80 + private synchronized void push(JSONCall call) {
130.81 + send(ws, call.getMessage());
130.82 + }
130.83 +
130.84 + void onOpen(Object ev) {
130.85 + if (!call.isDoOutput()) {
130.86 + call.notifySuccess(null);
130.87 + }
130.88 + }
130.89 +
130.90 + void onMessage(Object ev, String data) {
130.91 + Object json;
130.92 + try {
130.93 + data = data.trim();
130.94 +
130.95 + JSONTokener tok = new JSONTokener(data);
130.96 + Object obj;
130.97 + obj = data.startsWith("[") ? new JSONArray(tok) : new JSONObject(tok);
130.98 + json = LoadJSON.convertToArray(obj);
130.99 + } catch (JSONException ex) {
130.100 + json = data;
130.101 + }
130.102 + call.notifySuccess(json);
130.103 + }
130.104 +
130.105 + void onError(Object ev) {
130.106 + call.notifyError(new Exception(ev.toString()));
130.107 + }
130.108 +
130.109 + void onClose(boolean wasClean, int code, String reason) {
130.110 + call.notifyError(null);
130.111 + }
130.112 +
130.113 + @JavaScriptBody(args = {}, body = "if (window.WebSocket) return true; else return false;")
130.114 + private static boolean isWebSocket() {
130.115 + return false;
130.116 + }
130.117 +
130.118 + @JavaScriptBody(args = { "back", "url" }, javacall = true, body = ""
130.119 + + "if (window.WebSocket) {"
130.120 + + " try {"
130.121 + + " var ws = new window.WebSocket(url);"
130.122 + + " ws.onopen = function(ev) { back.@org.netbeans.html.kofx.LoadWS::onOpen(Ljava/lang/Object;)(ev); };"
130.123 + + " ws.onmessage = function(ev) { back.@org.netbeans.html.kofx.LoadWS::onMessage(Ljava/lang/Object;Ljava/lang/String;)(ev, ev.data); };"
130.124 + + " ws.onerror = function(ev) { back.@org.netbeans.html.kofx.LoadWS::onError(Ljava/lang/Object;)(ev); };"
130.125 + + " ws.onclose = function(ev) { back.@org.netbeans.html.kofx.LoadWS::onClose(ZILjava/lang/String;)(ev.wasClean, ev.code, ev.reason); };"
130.126 + + " return ws;"
130.127 + + " } catch (ex) {"
130.128 + + " return null;"
130.129 + + " }"
130.130 + + "} else {"
130.131 + + " return null;"
130.132 + + "}"
130.133 + )
130.134 + private static Object initWebSocket(Object back, String url) {
130.135 + return null;
130.136 + }
130.137 +
130.138 +
130.139 + @JavaScriptBody(args = { "ws", "msg" }, body = ""
130.140 + + "ws.send(msg);"
130.141 + )
130.142 + private void send(Object ws, String msg) {
130.143 + }
130.144 +
130.145 + @JavaScriptBody(args = { "ws" }, body = "ws.close();")
130.146 + private static void close(Object ws) {
130.147 + }
130.148 +
130.149 + void close() {
130.150 + close(ws);
130.151 + }
130.152 +}
131.1 --- a/ko-fx/src/main/resources/org/apidesign/html/kofx/knockout-2.2.1.js Mon Dec 16 15:48:09 2013 +0100
131.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
131.3 @@ -1,3594 +0,0 @@
131.4 -// Knockout JavaScript library v2.2.1
131.5 -// (c) Steven Sanderson - http://knockoutjs.com/
131.6 -// License: MIT (http://www.opensource.org/licenses/mit-license.php)
131.7 -
131.8 -(function(){
131.9 -var DEBUG=true;
131.10 -(function(window,document,navigator,jQuery,undefined){
131.11 -!function(factory) {
131.12 - // Support three module loading scenarios
131.13 - if (typeof require === 'function' && typeof exports === 'object' && typeof module === 'object') {
131.14 - // [1] CommonJS/Node.js
131.15 - var target = module['exports'] || exports; // module.exports is for Node.js
131.16 - factory(target);
131.17 - } else if (typeof define === 'function' && define['amd']) {
131.18 - // [2] AMD anonymous module
131.19 - define(['exports'], factory);
131.20 - } else {
131.21 - // [3] No module loader (plain <script> tag) - put directly in global namespace
131.22 - factory(window['ko'] = {});
131.23 - }
131.24 -}(function(koExports){
131.25 -// Internally, all KO objects are attached to koExports (even the non-exported ones whose names will be minified by the closure compiler).
131.26 -// In the future, the following "ko" variable may be made distinct from "koExports" so that private objects are not externally reachable.
131.27 -var ko = typeof koExports !== 'undefined' ? koExports : {};
131.28 -// Google Closure Compiler helpers (used only to make the minified file smaller)
131.29 -ko.exportSymbol = function(koPath, object) {
131.30 - var tokens = koPath.split(".");
131.31 -
131.32 - // In the future, "ko" may become distinct from "koExports" (so that non-exported objects are not reachable)
131.33 - // At that point, "target" would be set to: (typeof koExports !== "undefined" ? koExports : ko)
131.34 - var target = ko;
131.35 -
131.36 - for (var i = 0; i < tokens.length - 1; i++)
131.37 - target = target[tokens[i]];
131.38 - target[tokens[tokens.length - 1]] = object;
131.39 -};
131.40 -ko.exportProperty = function(owner, publicName, object) {
131.41 - owner[publicName] = object;
131.42 -};
131.43 -ko.version = "2.2.1";
131.44 -
131.45 -ko.exportSymbol('version', ko.version);
131.46 -ko.utils = new (function () {
131.47 - var stringTrimRegex = /^(\s|\u00A0)+|(\s|\u00A0)+$/g;
131.48 -
131.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)
131.50 - var knownEvents = {}, knownEventTypesByEventName = {};
131.51 - var keyEventTypeName = /Firefox\/2/i.test(navigator.userAgent) ? 'KeyboardEvent' : 'UIEvents';
131.52 - knownEvents[keyEventTypeName] = ['keyup', 'keydown', 'keypress'];
131.53 - knownEvents['MouseEvents'] = ['click', 'dblclick', 'mousedown', 'mouseup', 'mousemove', 'mouseover', 'mouseout', 'mouseenter', 'mouseleave'];
131.54 - for (var eventType in knownEvents) {
131.55 - var knownEventsForType = knownEvents[eventType];
131.56 - if (knownEventsForType.length) {
131.57 - for (var i = 0, j = knownEventsForType.length; i < j; i++)
131.58 - knownEventTypesByEventName[knownEventsForType[i]] = eventType;
131.59 - }
131.60 - }
131.61 - var eventsThatMustBeRegisteredUsingAttachEvent = { 'propertychange': true }; // Workaround for an IE9 issue - https://github.com/SteveSanderson/knockout/issues/406
131.62 -
131.63 - // Detect IE versions for bug workarounds (uses IE conditionals, not UA string, for robustness)
131.64 - // Note that, since IE 10 does not support conditional comments, the following logic only detects IE < 10.
131.65 - // Currently this is by design, since IE 10+ behaves correctly when treated as a standard browser.
131.66 - // If there is a future need to detect specific versions of IE10+, we will amend this.
131.67 - var ieVersion = (function() {
131.68 - var version = 3, div = document.createElement('div'), iElems = div.getElementsByTagName('i');
131.69 -
131.70 - // Keep constructing conditional HTML blocks until we hit one that resolves to an empty fragment
131.71 - while (
131.72 - div.innerHTML = '<!--[if gt IE ' + (++version) + ']><i></i><![endif]-->',
131.73 - iElems[0]
131.74 - );
131.75 - return version > 4 ? version : undefined;
131.76 - }());
131.77 - var isIe6 = ieVersion === 6,
131.78 - isIe7 = ieVersion === 7;
131.79 -
131.80 - function isClickOnCheckableElement(element, eventType) {
131.81 - if ((ko.utils.tagNameLower(element) !== "input") || !element.type) return false;
131.82 - if (eventType.toLowerCase() != "click") return false;
131.83 - var inputType = element.type;
131.84 - return (inputType == "checkbox") || (inputType == "radio");
131.85 - }
131.86 -
131.87 - return {
131.88 - fieldsIncludedWithJsonPost: ['authenticity_token', /^__RequestVerificationToken(_.*)?$/],
131.89 -
131.90 - arrayForEach: function (array, action) {
131.91 - for (var i = 0, j = array.length; i < j; i++)
131.92 - action(array[i]);
131.93 - },
131.94 -
131.95 - arrayIndexOf: function (array, item) {
131.96 - if (typeof Array.prototype.indexOf == "function")
131.97 - return Array.prototype.indexOf.call(array, item);
131.98 - for (var i = 0, j = array.length; i < j; i++)
131.99 - if (array[i] === item)
131.100 - return i;
131.101 - return -1;
131.102 - },
131.103 -
131.104 - arrayFirst: function (array, predicate, predicateOwner) {
131.105 - for (var i = 0, j = array.length; i < j; i++)
131.106 - if (predicate.call(predicateOwner, array[i]))
131.107 - return array[i];
131.108 - return null;
131.109 - },
131.110 -
131.111 - arrayRemoveItem: function (array, itemToRemove) {
131.112 - var index = ko.utils.arrayIndexOf(array, itemToRemove);
131.113 - if (index >= 0)
131.114 - array.splice(index, 1);
131.115 - },
131.116 -
131.117 - arrayGetDistinctValues: function (array) {
131.118 - array = array || [];
131.119 - var result = [];
131.120 - for (var i = 0, j = array.length; i < j; i++) {
131.121 - if (ko.utils.arrayIndexOf(result, array[i]) < 0)
131.122 - result.push(array[i]);
131.123 - }
131.124 - return result;
131.125 - },
131.126 -
131.127 - arrayMap: function (array, mapping) {
131.128 - array = array || [];
131.129 - var result = [];
131.130 - for (var i = 0, j = array.length; i < j; i++)
131.131 - result.push(mapping(array[i]));
131.132 - return result;
131.133 - },
131.134 -
131.135 - arrayFilter: function (array, predicate) {
131.136 - array = array || [];
131.137 - var result = [];
131.138 - for (var i = 0, j = array.length; i < j; i++)
131.139 - if (predicate(array[i]))
131.140 - result.push(array[i]);
131.141 - return result;
131.142 - },
131.143 -
131.144 - arrayPushAll: function (array, valuesToPush) {
131.145 - if (valuesToPush instanceof Array)
131.146 - array.push.apply(array, valuesToPush);
131.147 - else
131.148 - for (var i = 0, j = valuesToPush.length; i < j; i++)
131.149 - array.push(valuesToPush[i]);
131.150 - return array;
131.151 - },
131.152 -
131.153 - extend: function (target, source) {
131.154 - if (source) {
131.155 - for(var prop in source) {
131.156 - if(source.hasOwnProperty(prop)) {
131.157 - target[prop] = source[prop];
131.158 - }
131.159 - }
131.160 - }
131.161 - return target;
131.162 - },
131.163 -
131.164 - emptyDomNode: function (domNode) {
131.165 - while (domNode.firstChild) {
131.166 - ko.removeNode(domNode.firstChild);
131.167 - }
131.168 - },
131.169 -
131.170 - moveCleanedNodesToContainerElement: function(nodes) {
131.171 - // Ensure it's a real array, as we're about to reparent the nodes and
131.172 - // we don't want the underlying collection to change while we're doing that.
131.173 - var nodesArray = ko.utils.makeArray(nodes);
131.174 -
131.175 - var container = document.createElement('div');
131.176 - for (var i = 0, j = nodesArray.length; i < j; i++) {
131.177 - container.appendChild(ko.cleanNode(nodesArray[i]));
131.178 - }
131.179 - return container;
131.180 - },
131.181 -
131.182 - cloneNodes: function (nodesArray, shouldCleanNodes) {
131.183 - for (var i = 0, j = nodesArray.length, newNodesArray = []; i < j; i++) {
131.184 - var clonedNode = nodesArray[i].cloneNode(true);
131.185 - newNodesArray.push(shouldCleanNodes ? ko.cleanNode(clonedNode) : clonedNode);
131.186 - }
131.187 - return newNodesArray;
131.188 - },
131.189 -
131.190 - setDomNodeChildren: function (domNode, childNodes) {
131.191 - ko.utils.emptyDomNode(domNode);
131.192 - if (childNodes) {
131.193 - for (var i = 0, j = childNodes.length; i < j; i++)
131.194 - domNode.appendChild(childNodes[i]);
131.195 - }
131.196 - },
131.197 -
131.198 - replaceDomNodes: function (nodeToReplaceOrNodeArray, newNodesArray) {
131.199 - var nodesToReplaceArray = nodeToReplaceOrNodeArray.nodeType ? [nodeToReplaceOrNodeArray] : nodeToReplaceOrNodeArray;
131.200 - if (nodesToReplaceArray.length > 0) {
131.201 - var insertionPoint = nodesToReplaceArray[0];
131.202 - var parent = insertionPoint.parentNode;
131.203 - for (var i = 0, j = newNodesArray.length; i < j; i++)
131.204 - parent.insertBefore(newNodesArray[i], insertionPoint);
131.205 - for (var i = 0, j = nodesToReplaceArray.length; i < j; i++) {
131.206 - ko.removeNode(nodesToReplaceArray[i]);
131.207 - }
131.208 - }
131.209 - },
131.210 -
131.211 - setOptionNodeSelectionState: function (optionNode, isSelected) {
131.212 - // IE6 sometimes throws "unknown error" if you try to write to .selected directly, whereas Firefox struggles with setAttribute. Pick one based on browser.
131.213 - if (ieVersion < 7)
131.214 - optionNode.setAttribute("selected", isSelected);
131.215 - else
131.216 - optionNode.selected = isSelected;
131.217 - },
131.218 -
131.219 - stringTrim: function (string) {
131.220 - return (string || "").replace(stringTrimRegex, "");
131.221 - },
131.222 -
131.223 - stringTokenize: function (string, delimiter) {
131.224 - var result = [];
131.225 - var tokens = (string || "").split(delimiter);
131.226 - for (var i = 0, j = tokens.length; i < j; i++) {
131.227 - var trimmed = ko.utils.stringTrim(tokens[i]);
131.228 - if (trimmed !== "")
131.229 - result.push(trimmed);
131.230 - }
131.231 - return result;
131.232 - },
131.233 -
131.234 - stringStartsWith: function (string, startsWith) {
131.235 - string = string || "";
131.236 - if (startsWith.length > string.length)
131.237 - return false;
131.238 - return string.substring(0, startsWith.length) === startsWith;
131.239 - },
131.240 -
131.241 - domNodeIsContainedBy: function (node, containedByNode) {
131.242 - if (containedByNode.compareDocumentPosition)
131.243 - return (containedByNode.compareDocumentPosition(node) & 16) == 16;
131.244 - while (node != null) {
131.245 - if (node == containedByNode)
131.246 - return true;
131.247 - node = node.parentNode;
131.248 - }
131.249 - return false;
131.250 - },
131.251 -
131.252 - domNodeIsAttachedToDocument: function (node) {
131.253 - return ko.utils.domNodeIsContainedBy(node, node.ownerDocument);
131.254 - },
131.255 -
131.256 - tagNameLower: function(element) {
131.257 - // For HTML elements, tagName will always be upper case; for XHTML elements, it'll be lower case.
131.258 - // Possible future optimization: If we know it's an element from an XHTML document (not HTML),
131.259 - // we don't need to do the .toLowerCase() as it will always be lower case anyway.
131.260 - return element && element.tagName && element.tagName.toLowerCase();
131.261 - },
131.262 -
131.263 - registerEventHandler: function (element, eventType, handler) {
131.264 - var mustUseAttachEvent = ieVersion && eventsThatMustBeRegisteredUsingAttachEvent[eventType];
131.265 - if (!mustUseAttachEvent && typeof jQuery != "undefined") {
131.266 - if (isClickOnCheckableElement(element, eventType)) {
131.267 - // For click events on checkboxes, jQuery interferes with the event handling in an awkward way:
131.268 - // it toggles the element checked state *after* the click event handlers run, whereas native
131.269 - // click events toggle the checked state *before* the event handler.
131.270 - // Fix this by intecepting the handler and applying the correct checkedness before it runs.
131.271 - var originalHandler = handler;
131.272 - handler = function(event, eventData) {
131.273 - var jQuerySuppliedCheckedState = this.checked;
131.274 - if (eventData)
131.275 - this.checked = eventData.checkedStateBeforeEvent !== true;
131.276 - originalHandler.call(this, event);
131.277 - this.checked = jQuerySuppliedCheckedState; // Restore the state jQuery applied
131.278 - };
131.279 - }
131.280 - jQuery(element)['bind'](eventType, handler);
131.281 - } else if (!mustUseAttachEvent && typeof element.addEventListener == "function")
131.282 - element.addEventListener(eventType, handler, false);
131.283 - else if (typeof element.attachEvent != "undefined")
131.284 - element.attachEvent("on" + eventType, function (event) {
131.285 - handler.call(element, event);
131.286 - });
131.287 - else
131.288 - throw new Error("Browser doesn't support addEventListener or attachEvent");
131.289 - },
131.290 -
131.291 - triggerEvent: function (element, eventType) {
131.292 - if (!(element && element.nodeType))
131.293 - throw new Error("element must be a DOM node when calling triggerEvent");
131.294 -
131.295 - if (typeof jQuery != "undefined") {
131.296 - var eventData = [];
131.297 - if (isClickOnCheckableElement(element, eventType)) {
131.298 - // Work around the jQuery "click events on checkboxes" issue described above by storing the original checked state before triggering the handler
131.299 - eventData.push({ checkedStateBeforeEvent: element.checked });
131.300 - }
131.301 - jQuery(element)['trigger'](eventType, eventData);
131.302 - } else if (typeof document.createEvent == "function") {
131.303 - if (typeof element.dispatchEvent == "function") {
131.304 - var eventCategory = knownEventTypesByEventName[eventType] || "HTMLEvents";
131.305 - var event = document.createEvent(eventCategory);
131.306 - event.initEvent(eventType, true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, element);
131.307 - element.dispatchEvent(event);
131.308 - }
131.309 - else
131.310 - throw new Error("The supplied element doesn't support dispatchEvent");
131.311 - } else if (typeof element.fireEvent != "undefined") {
131.312 - // Unlike other browsers, IE doesn't change the checked state of checkboxes/radiobuttons when you trigger their "click" event
131.313 - // so to make it consistent, we'll do it manually here
131.314 - if (isClickOnCheckableElement(element, eventType))
131.315 - element.checked = element.checked !== true;
131.316 - element.fireEvent("on" + eventType);
131.317 - }
131.318 - else
131.319 - throw new Error("Browser doesn't support triggering events");
131.320 - },
131.321 -
131.322 - unwrapObservable: function (value) {
131.323 - return ko.isObservable(value) ? value() : value;
131.324 - },
131.325 -
131.326 - peekObservable: function (value) {
131.327 - return ko.isObservable(value) ? value.peek() : value;
131.328 - },
131.329 -
131.330 - toggleDomNodeCssClass: function (node, classNames, shouldHaveClass) {
131.331 - if (classNames) {
131.332 - var cssClassNameRegex = /[\w-]+/g,
131.333 - currentClassNames = node.className.match(cssClassNameRegex) || [];
131.334 - ko.utils.arrayForEach(classNames.match(cssClassNameRegex), function(className) {
131.335 - var indexOfClass = ko.utils.arrayIndexOf(currentClassNames, className);
131.336 - if (indexOfClass >= 0) {
131.337 - if (!shouldHaveClass)
131.338 - currentClassNames.splice(indexOfClass, 1);
131.339 - } else {
131.340 - if (shouldHaveClass)
131.341 - currentClassNames.push(className);
131.342 - }
131.343 - });
131.344 - node.className = currentClassNames.join(" ");
131.345 - }
131.346 - },
131.347 -
131.348 - setTextContent: function(element, textContent) {
131.349 - var value = ko.utils.unwrapObservable(textContent);
131.350 - if ((value === null) || (value === undefined))
131.351 - value = "";
131.352 -
131.353 - if (element.nodeType === 3) {
131.354 - element.data = value;
131.355 - } else {
131.356 - // We need there to be exactly one child: a text node.
131.357 - // If there are no children, more than one, or if it's not a text node,
131.358 - // we'll clear everything and create a single text node.
131.359 - var innerTextNode = ko.virtualElements.firstChild(element);
131.360 - if (!innerTextNode || innerTextNode.nodeType != 3 || ko.virtualElements.nextSibling(innerTextNode)) {
131.361 - ko.virtualElements.setDomNodeChildren(element, [document.createTextNode(value)]);
131.362 - } else {
131.363 - innerTextNode.data = value;
131.364 - }
131.365 -
131.366 - ko.utils.forceRefresh(element);
131.367 - }
131.368 - },
131.369 -
131.370 - setElementName: function(element, name) {
131.371 - element.name = name;
131.372 -
131.373 - // Workaround IE 6/7 issue
131.374 - // - https://github.com/SteveSanderson/knockout/issues/197
131.375 - // - http://www.matts411.com/post/setting_the_name_attribute_in_ie_dom/
131.376 - if (ieVersion <= 7) {
131.377 - try {
131.378 - element.mergeAttributes(document.createElement("<input name='" + element.name + "'/>"), false);
131.379 - }
131.380 - catch(e) {} // For IE9 with doc mode "IE9 Standards" and browser mode "IE9 Compatibility View"
131.381 - }
131.382 - },
131.383 -
131.384 - forceRefresh: function(node) {
131.385 - // Workaround for an IE9 rendering bug - https://github.com/SteveSanderson/knockout/issues/209
131.386 - if (ieVersion >= 9) {
131.387 - // For text nodes and comment nodes (most likely virtual elements), we will have to refresh the container
131.388 - var elem = node.nodeType == 1 ? node : node.parentNode;
131.389 - if (elem.style)
131.390 - elem.style.zoom = elem.style.zoom;
131.391 - }
131.392 - },
131.393 -
131.394 - ensureSelectElementIsRenderedCorrectly: function(selectElement) {
131.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.
131.396 - // (See https://github.com/SteveSanderson/knockout/issues/312, http://stackoverflow.com/questions/5908494/select-only-shows-first-char-of-selected-option)
131.397 - if (ieVersion >= 9) {
131.398 - var originalWidth = selectElement.style.width;
131.399 - selectElement.style.width = 0;
131.400 - selectElement.style.width = originalWidth;
131.401 - }
131.402 - },
131.403 -
131.404 - range: function (min, max) {
131.405 - min = ko.utils.unwrapObservable(min);
131.406 - max = ko.utils.unwrapObservable(max);
131.407 - var result = [];
131.408 - for (var i = min; i <= max; i++)
131.409 - result.push(i);
131.410 - return result;
131.411 - },
131.412 -
131.413 - makeArray: function(arrayLikeObject) {
131.414 - var result = [];
131.415 - for (var i = 0, j = arrayLikeObject.length; i < j; i++) {
131.416 - result.push(arrayLikeObject[i]);
131.417 - };
131.418 - return result;
131.419 - },
131.420 -
131.421 - isIe6 : isIe6,
131.422 - isIe7 : isIe7,
131.423 - ieVersion : ieVersion,
131.424 -
131.425 - getFormFields: function(form, fieldName) {
131.426 - var fields = ko.utils.makeArray(form.getElementsByTagName("input")).concat(ko.utils.makeArray(form.getElementsByTagName("textarea")));
131.427 - var isMatchingField = (typeof fieldName == 'string')
131.428 - ? function(field) { return field.name === fieldName }
131.429 - : function(field) { return fieldName.test(field.name) }; // Treat fieldName as regex or object containing predicate
131.430 - var matches = [];
131.431 - for (var i = fields.length - 1; i >= 0; i--) {
131.432 - if (isMatchingField(fields[i]))
131.433 - matches.push(fields[i]);
131.434 - };
131.435 - return matches;
131.436 - },
131.437 -
131.438 - parseJson: function (jsonString) {
131.439 - if (typeof jsonString == "string") {
131.440 - jsonString = ko.utils.stringTrim(jsonString);
131.441 - if (jsonString) {
131.442 - if (window.JSON && window.JSON.parse) // Use native parsing where available
131.443 - return window.JSON.parse(jsonString);
131.444 - return (new Function("return " + jsonString))(); // Fallback on less safe parsing for older browsers
131.445 - }
131.446 - }
131.447 - return null;
131.448 - },
131.449 -
131.450 - stringifyJson: function (data, replacer, space) { // replacer and space are optional
131.451 - if ((typeof JSON == "undefined") || (typeof JSON.stringify == "undefined"))
131.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");
131.453 - return JSON.stringify(ko.utils.unwrapObservable(data), replacer, space);
131.454 - },
131.455 -
131.456 - postJson: function (urlOrForm, data, options) {
131.457 - options = options || {};
131.458 - var params = options['params'] || {};
131.459 - var includeFields = options['includeFields'] || this.fieldsIncludedWithJsonPost;
131.460 - var url = urlOrForm;
131.461 -
131.462 - // If we were given a form, use its 'action' URL and pick out any requested field values
131.463 - if((typeof urlOrForm == 'object') && (ko.utils.tagNameLower(urlOrForm) === "form")) {
131.464 - var originalForm = urlOrForm;
131.465 - url = originalForm.action;
131.466 - for (var i = includeFields.length - 1; i >= 0; i--) {
131.467 - var fields = ko.utils.getFormFields(originalForm, includeFields[i]);
131.468 - for (var j = fields.length - 1; j >= 0; j--)
131.469 - params[fields[j].name] = fields[j].value;
131.470 - }
131.471 - }
131.472 -
131.473 - data = ko.utils.unwrapObservable(data);
131.474 - var form = document.createElement("form");
131.475 - form.style.display = "none";
131.476 - form.action = url;
131.477 - form.method = "post";
131.478 - for (var key in data) {
131.479 - var input = document.createElement("input");
131.480 - input.name = key;
131.481 - input.value = ko.utils.stringifyJson(ko.utils.unwrapObservable(data[key]));
131.482 - form.appendChild(input);
131.483 - }
131.484 - for (var key in params) {
131.485 - var input = document.createElement("input");
131.486 - input.name = key;
131.487 - input.value = params[key];
131.488 - form.appendChild(input);
131.489 - }
131.490 - document.body.appendChild(form);
131.491 - options['submitter'] ? options['submitter'](form) : form.submit();
131.492 - setTimeout(function () { form.parentNode.removeChild(form); }, 0);
131.493 - }
131.494 - }
131.495 -})();
131.496 -
131.497 -ko.exportSymbol('utils', ko.utils);
131.498 -ko.exportSymbol('utils.arrayForEach', ko.utils.arrayForEach);
131.499 -ko.exportSymbol('utils.arrayFirst', ko.utils.arrayFirst);
131.500 -ko.exportSymbol('utils.arrayFilter', ko.utils.arrayFilter);
131.501 -ko.exportSymbol('utils.arrayGetDistinctValues', ko.utils.arrayGetDistinctValues);
131.502 -ko.exportSymbol('utils.arrayIndexOf', ko.utils.arrayIndexOf);
131.503 -ko.exportSymbol('utils.arrayMap', ko.utils.arrayMap);
131.504 -ko.exportSymbol('utils.arrayPushAll', ko.utils.arrayPushAll);
131.505 -ko.exportSymbol('utils.arrayRemoveItem', ko.utils.arrayRemoveItem);
131.506 -ko.exportSymbol('utils.extend', ko.utils.extend);
131.507 -ko.exportSymbol('utils.fieldsIncludedWithJsonPost', ko.utils.fieldsIncludedWithJsonPost);
131.508 -ko.exportSymbol('utils.getFormFields', ko.utils.getFormFields);
131.509 -ko.exportSymbol('utils.peekObservable', ko.utils.peekObservable);
131.510 -ko.exportSymbol('utils.postJson', ko.utils.postJson);
131.511 -ko.exportSymbol('utils.parseJson', ko.utils.parseJson);
131.512 -ko.exportSymbol('utils.registerEventHandler', ko.utils.registerEventHandler);
131.513 -ko.exportSymbol('utils.stringifyJson', ko.utils.stringifyJson);
131.514 -ko.exportSymbol('utils.range', ko.utils.range);
131.515 -ko.exportSymbol('utils.toggleDomNodeCssClass', ko.utils.toggleDomNodeCssClass);
131.516 -ko.exportSymbol('utils.triggerEvent', ko.utils.triggerEvent);
131.517 -ko.exportSymbol('utils.unwrapObservable', ko.utils.unwrapObservable);
131.518 -
131.519 -if (!Function.prototype['bind']) {
131.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)
131.521 - // In case the browser doesn't implement it natively, provide a JavaScript implementation. This implementation is based on the one in prototype.js
131.522 - Function.prototype['bind'] = function (object) {
131.523 - var originalFunction = this, args = Array.prototype.slice.call(arguments), object = args.shift();
131.524 - return function () {
131.525 - return originalFunction.apply(object, args.concat(Array.prototype.slice.call(arguments)));
131.526 - };
131.527 - };
131.528 -}
131.529 -
131.530 -ko.utils.domData = new (function () {
131.531 - var uniqueId = 0;
131.532 - var dataStoreKeyExpandoPropertyName = "__ko__" + (new Date).getTime();
131.533 - var dataStore = {};
131.534 - return {
131.535 - get: function (node, key) {
131.536 - var allDataForNode = ko.utils.domData.getAll(node, false);
131.537 - return allDataForNode === undefined ? undefined : allDataForNode[key];
131.538 - },
131.539 - set: function (node, key, value) {
131.540 - if (value === undefined) {
131.541 - // Make sure we don't actually create a new domData key if we are actually deleting a value
131.542 - if (ko.utils.domData.getAll(node, false) === undefined)
131.543 - return;
131.544 - }
131.545 - var allDataForNode = ko.utils.domData.getAll(node, true);
131.546 - allDataForNode[key] = value;
131.547 - },
131.548 - getAll: function (node, createIfNotFound) {
131.549 - var dataStoreKey = node[dataStoreKeyExpandoPropertyName];
131.550 - var hasExistingDataStore = dataStoreKey && (dataStoreKey !== "null") && dataStore[dataStoreKey];
131.551 - if (!hasExistingDataStore) {
131.552 - if (!createIfNotFound)
131.553 - return undefined;
131.554 - dataStoreKey = node[dataStoreKeyExpandoPropertyName] = "ko" + uniqueId++;
131.555 - dataStore[dataStoreKey] = {};
131.556 - }
131.557 - return dataStore[dataStoreKey];
131.558 - },
131.559 - clear: function (node) {
131.560 - var dataStoreKey = node[dataStoreKeyExpandoPropertyName];
131.561 - if (dataStoreKey) {
131.562 - delete dataStore[dataStoreKey];
131.563 - node[dataStoreKeyExpandoPropertyName] = null;
131.564 - return true; // Exposing "did clean" flag purely so specs can infer whether things have been cleaned up as intended
131.565 - }
131.566 - return false;
131.567 - }
131.568 - }
131.569 -})();
131.570 -
131.571 -ko.exportSymbol('utils.domData', ko.utils.domData);
131.572 -ko.exportSymbol('utils.domData.clear', ko.utils.domData.clear); // Exporting only so specs can clear up after themselves fully
131.573 -
131.574 -ko.utils.domNodeDisposal = new (function () {
131.575 - var domDataKey = "__ko_domNodeDisposal__" + (new Date).getTime();
131.576 - var cleanableNodeTypes = { 1: true, 8: true, 9: true }; // Element, Comment, Document
131.577 - var cleanableNodeTypesWithDescendants = { 1: true, 9: true }; // Element, Document
131.578 -
131.579 - function getDisposeCallbacksCollection(node, createIfNotFound) {
131.580 - var allDisposeCallbacks = ko.utils.domData.get(node, domDataKey);
131.581 - if ((allDisposeCallbacks === undefined) && createIfNotFound) {
131.582 - allDisposeCallbacks = [];
131.583 - ko.utils.domData.set(node, domDataKey, allDisposeCallbacks);
131.584 - }
131.585 - return allDisposeCallbacks;
131.586 - }
131.587 - function destroyCallbacksCollection(node) {
131.588 - ko.utils.domData.set(node, domDataKey, undefined);
131.589 - }
131.590 -
131.591 - function cleanSingleNode(node) {
131.592 - // Run all the dispose callbacks
131.593 - var callbacks = getDisposeCallbacksCollection(node, false);
131.594 - if (callbacks) {
131.595 - callbacks = callbacks.slice(0); // Clone, as the array may be modified during iteration (typically, callbacks will remove themselves)
131.596 - for (var i = 0; i < callbacks.length; i++)
131.597 - callbacks[i](node);
131.598 - }
131.599 -
131.600 - // Also erase the DOM data
131.601 - ko.utils.domData.clear(node);
131.602 -
131.603 - // Special support for jQuery here because it's so commonly used.
131.604 - // Many jQuery plugins (including jquery.tmpl) store data using jQuery's equivalent of domData
131.605 - // so notify it to tear down any resources associated with the node & descendants here.
131.606 - if ((typeof jQuery == "function") && (typeof jQuery['cleanData'] == "function"))
131.607 - jQuery['cleanData']([node]);
131.608 -
131.609 - // Also clear any immediate-child comment nodes, as these wouldn't have been found by
131.610 - // node.getElementsByTagName("*") in cleanNode() (comment nodes aren't elements)
131.611 - if (cleanableNodeTypesWithDescendants[node.nodeType])
131.612 - cleanImmediateCommentTypeChildren(node);
131.613 - }
131.614 -
131.615 - function cleanImmediateCommentTypeChildren(nodeWithChildren) {
131.616 - var child, nextChild = nodeWithChildren.firstChild;
131.617 - while (child = nextChild) {
131.618 - nextChild = child.nextSibling;
131.619 - if (child.nodeType === 8)
131.620 - cleanSingleNode(child);
131.621 - }
131.622 - }
131.623 -
131.624 - return {
131.625 - addDisposeCallback : function(node, callback) {
131.626 - if (typeof callback != "function")
131.627 - throw new Error("Callback must be a function");
131.628 - getDisposeCallbacksCollection(node, true).push(callback);
131.629 - },
131.630 -
131.631 - removeDisposeCallback : function(node, callback) {
131.632 - var callbacksCollection = getDisposeCallbacksCollection(node, false);
131.633 - if (callbacksCollection) {
131.634 - ko.utils.arrayRemoveItem(callbacksCollection, callback);
131.635 - if (callbacksCollection.length == 0)
131.636 - destroyCallbacksCollection(node);
131.637 - }
131.638 - },
131.639 -
131.640 - cleanNode : function(node) {
131.641 - // First clean this node, where applicable
131.642 - if (cleanableNodeTypes[node.nodeType]) {
131.643 - cleanSingleNode(node);
131.644 -
131.645 - // ... then its descendants, where applicable
131.646 - if (cleanableNodeTypesWithDescendants[node.nodeType]) {
131.647 - // Clone the descendants list in case it changes during iteration
131.648 - var descendants = [];
131.649 - ko.utils.arrayPushAll(descendants, node.getElementsByTagName("*"));
131.650 - for (var i = 0, j = descendants.length; i < j; i++)
131.651 - cleanSingleNode(descendants[i]);
131.652 - }
131.653 - }
131.654 - return node;
131.655 - },
131.656 -
131.657 - removeNode : function(node) {
131.658 - ko.cleanNode(node);
131.659 - if (node.parentNode)
131.660 - node.parentNode.removeChild(node);
131.661 - }
131.662 - }
131.663 -})();
131.664 -ko.cleanNode = ko.utils.domNodeDisposal.cleanNode; // Shorthand name for convenience
131.665 -ko.removeNode = ko.utils.domNodeDisposal.removeNode; // Shorthand name for convenience
131.666 -ko.exportSymbol('cleanNode', ko.cleanNode);
131.667 -ko.exportSymbol('removeNode', ko.removeNode);
131.668 -ko.exportSymbol('utils.domNodeDisposal', ko.utils.domNodeDisposal);
131.669 -ko.exportSymbol('utils.domNodeDisposal.addDisposeCallback', ko.utils.domNodeDisposal.addDisposeCallback);
131.670 -ko.exportSymbol('utils.domNodeDisposal.removeDisposeCallback', ko.utils.domNodeDisposal.removeDisposeCallback);
131.671 -(function () {
131.672 - var leadingCommentRegex = /^(\s*)<!--(.*?)-->/;
131.673 -
131.674 - function simpleHtmlParse(html) {
131.675 - // Based on jQuery's "clean" function, but only accounting for table-related elements.
131.676 - // If you have referenced jQuery, this won't be used anyway - KO will use jQuery's "clean" function directly
131.677 -
131.678 - // Note that there's still an issue in IE < 9 whereby it will discard comment nodes that are the first child of
131.679 - // a descendant node. For example: "<div><!-- mycomment -->abc</div>" will get parsed as "<div>abc</div>"
131.680 - // This won't affect anyone who has referenced jQuery, and there's always the workaround of inserting a dummy node
131.681 - // (possibly a text node) in front of the comment. So, KO does not attempt to workaround this IE issue automatically at present.
131.682 -
131.683 - // Trim whitespace, otherwise indexOf won't work as expected
131.684 - var tags = ko.utils.stringTrim(html).toLowerCase(), div = document.createElement("div");
131.685 -
131.686 - // Finds the first match from the left column, and returns the corresponding "wrap" data from the right column
131.687 - var wrap = tags.match(/^<(thead|tbody|tfoot)/) && [1, "<table>", "</table>"] ||
131.688 - !tags.indexOf("<tr") && [2, "<table><tbody>", "</tbody></table>"] ||
131.689 - (!tags.indexOf("<td") || !tags.indexOf("<th")) && [3, "<table><tbody><tr>", "</tr></tbody></table>"] ||
131.690 - /* anything else */ [0, "", ""];
131.691 -
131.692 - // Go to html and back, then peel off extra wrappers
131.693 - // Note that we always prefix with some dummy text, because otherwise, IE<9 will strip out leading comment nodes in descendants. Total madness.
131.694 - var markup = "ignored<div>" + wrap[1] + html + wrap[2] + "</div>";
131.695 - if (typeof window['innerShiv'] == "function") {
131.696 - div.appendChild(window['innerShiv'](markup));
131.697 - } else {
131.698 - div.innerHTML = markup;
131.699 - }
131.700 -
131.701 - // Move to the right depth
131.702 - while (wrap[0]--)
131.703 - div = div.lastChild;
131.704 -
131.705 - return ko.utils.makeArray(div.lastChild.childNodes);
131.706 - }
131.707 -
131.708 - function jQueryHtmlParse(html) {
131.709 - // jQuery's "parseHTML" function was introduced in jQuery 1.8.0 and is a documented public API.
131.710 - if (jQuery['parseHTML']) {
131.711 - return jQuery['parseHTML'](html);
131.712 - } else {
131.713 - // For jQuery < 1.8.0, we fall back on the undocumented internal "clean" function.
131.714 - var elems = jQuery['clean']([html]);
131.715 -
131.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.
131.717 - // Unfortunately, it never clears the dummy parent nodes from the document fragment, so it leaks memory over time.
131.718 - // Fix this by finding the top-most dummy parent element, and detaching it from its owner fragment.
131.719 - if (elems && elems[0]) {
131.720 - // Find the top-most parent element that's a direct child of a document fragment
131.721 - var elem = elems[0];
131.722 - while (elem.parentNode && elem.parentNode.nodeType !== 11 /* i.e., DocumentFragment */)
131.723 - elem = elem.parentNode;
131.724 - // ... then detach it
131.725 - if (elem.parentNode)
131.726 - elem.parentNode.removeChild(elem);
131.727 - }
131.728 -
131.729 - return elems;
131.730 - }
131.731 - }
131.732 -
131.733 - ko.utils.parseHtmlFragment = function(html) {
131.734 - return typeof jQuery != 'undefined' ? jQueryHtmlParse(html) // As below, benefit from jQuery's optimisations where possible
131.735 - : simpleHtmlParse(html); // ... otherwise, this simple logic will do in most common cases.
131.736 - };
131.737 -
131.738 - ko.utils.setHtml = function(node, html) {
131.739 - ko.utils.emptyDomNode(node);
131.740 -
131.741 - // There's no legitimate reason to display a stringified observable without unwrapping it, so we'll unwrap it
131.742 - html = ko.utils.unwrapObservable(html);
131.743 -
131.744 - if ((html !== null) && (html !== undefined)) {
131.745 - if (typeof html != 'string')
131.746 - html = html.toString();
131.747 -
131.748 - // jQuery contains a lot of sophisticated code to parse arbitrary HTML fragments,
131.749 - // for example <tr> elements which are not normally allowed to exist on their own.
131.750 - // If you've referenced jQuery we'll use that rather than duplicating its code.
131.751 - if (typeof jQuery != 'undefined') {
131.752 - jQuery(node)['html'](html);
131.753 - } else {
131.754 - // ... otherwise, use KO's own parsing logic.
131.755 - var parsedNodes = ko.utils.parseHtmlFragment(html);
131.756 - for (var i = 0; i < parsedNodes.length; i++)
131.757 - node.appendChild(parsedNodes[i]);
131.758 - }
131.759 - }
131.760 - };
131.761 -})();
131.762 -
131.763 -ko.exportSymbol('utils.parseHtmlFragment', ko.utils.parseHtmlFragment);
131.764 -ko.exportSymbol('utils.setHtml', ko.utils.setHtml);
131.765 -
131.766 -ko.memoization = (function () {
131.767 - var memos = {};
131.768 -
131.769 - function randomMax8HexChars() {
131.770 - return (((1 + Math.random()) * 0x100000000) | 0).toString(16).substring(1);
131.771 - }
131.772 - function generateRandomId() {
131.773 - return randomMax8HexChars() + randomMax8HexChars();
131.774 - }
131.775 - function findMemoNodes(rootNode, appendToArray) {
131.776 - if (!rootNode)
131.777 - return;
131.778 - if (rootNode.nodeType == 8) {
131.779 - var memoId = ko.memoization.parseMemoText(rootNode.nodeValue);
131.780 - if (memoId != null)
131.781 - appendToArray.push({ domNode: rootNode, memoId: memoId });
131.782 - } else if (rootNode.nodeType == 1) {
131.783 - for (var i = 0, childNodes = rootNode.childNodes, j = childNodes.length; i < j; i++)
131.784 - findMemoNodes(childNodes[i], appendToArray);
131.785 - }
131.786 - }
131.787 -
131.788 - return {
131.789 - memoize: function (callback) {
131.790 - if (typeof callback != "function")
131.791 - throw new Error("You can only pass a function to ko.memoization.memoize()");
131.792 - var memoId = generateRandomId();
131.793 - memos[memoId] = callback;
131.794 - return "<!--[ko_memo:" + memoId + "]-->";
131.795 - },
131.796 -
131.797 - unmemoize: function (memoId, callbackParams) {
131.798 - var callback = memos[memoId];
131.799 - if (callback === undefined)
131.800 - throw new Error("Couldn't find any memo with ID " + memoId + ". Perhaps it's already been unmemoized.");
131.801 - try {
131.802 - callback.apply(null, callbackParams || []);
131.803 - return true;
131.804 - }
131.805 - finally { delete memos[memoId]; }
131.806 - },
131.807 -
131.808 - unmemoizeDomNodeAndDescendants: function (domNode, extraCallbackParamsArray) {
131.809 - var memos = [];
131.810 - findMemoNodes(domNode, memos);
131.811 - for (var i = 0, j = memos.length; i < j; i++) {
131.812 - var node = memos[i].domNode;
131.813 - var combinedParams = [node];
131.814 - if (extraCallbackParamsArray)
131.815 - ko.utils.arrayPushAll(combinedParams, extraCallbackParamsArray);
131.816 - ko.memoization.unmemoize(memos[i].memoId, combinedParams);
131.817 - node.nodeValue = ""; // Neuter this node so we don't try to unmemoize it again
131.818 - if (node.parentNode)
131.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)
131.820 - }
131.821 - },
131.822 -
131.823 - parseMemoText: function (memoText) {
131.824 - var match = memoText.match(/^\[ko_memo\:(.*?)\]$/);
131.825 - return match ? match[1] : null;
131.826 - }
131.827 - };
131.828 -})();
131.829 -
131.830 -ko.exportSymbol('memoization', ko.memoization);
131.831 -ko.exportSymbol('memoization.memoize', ko.memoization.memoize);
131.832 -ko.exportSymbol('memoization.unmemoize', ko.memoization.unmemoize);
131.833 -ko.exportSymbol('memoization.parseMemoText', ko.memoization.parseMemoText);
131.834 -ko.exportSymbol('memoization.unmemoizeDomNodeAndDescendants', ko.memoization.unmemoizeDomNodeAndDescendants);
131.835 -ko.extenders = {
131.836 - 'throttle': function(target, timeout) {
131.837 - // Throttling means two things:
131.838 -
131.839 - // (1) For dependent observables, we throttle *evaluations* so that, no matter how fast its dependencies
131.840 - // notify updates, the target doesn't re-evaluate (and hence doesn't notify) faster than a certain rate
131.841 - target['throttleEvaluation'] = timeout;
131.842 -
131.843 - // (2) For writable targets (observables, or writable dependent observables), we throttle *writes*
131.844 - // so the target cannot change value synchronously or faster than a certain rate
131.845 - var writeTimeoutInstance = null;
131.846 - return ko.dependentObservable({
131.847 - 'read': target,
131.848 - 'write': function(value) {
131.849 - clearTimeout(writeTimeoutInstance);
131.850 - writeTimeoutInstance = setTimeout(function() {
131.851 - target(value);
131.852 - }, timeout);
131.853 - }
131.854 - });
131.855 - },
131.856 -
131.857 - 'notify': function(target, notifyWhen) {
131.858 - target["equalityComparer"] = notifyWhen == "always"
131.859 - ? function() { return false } // Treat all values as not equal
131.860 - : ko.observable["fn"]["equalityComparer"];
131.861 - return target;
131.862 - }
131.863 -};
131.864 -
131.865 -function applyExtenders(requestedExtenders) {
131.866 - var target = this;
131.867 - if (requestedExtenders) {
131.868 - for (var key in requestedExtenders) {
131.869 - var extenderHandler = ko.extenders[key];
131.870 - if (typeof extenderHandler == 'function') {
131.871 - target = extenderHandler(target, requestedExtenders[key]);
131.872 - }
131.873 - }
131.874 - }
131.875 - return target;
131.876 -}
131.877 -
131.878 -ko.exportSymbol('extenders', ko.extenders);
131.879 -
131.880 -ko.subscription = function (target, callback, disposeCallback) {
131.881 - this.target = target;
131.882 - this.callback = callback;
131.883 - this.disposeCallback = disposeCallback;
131.884 - ko.exportProperty(this, 'dispose', this.dispose);
131.885 -};
131.886 -ko.subscription.prototype.dispose = function () {
131.887 - this.isDisposed = true;
131.888 - this.disposeCallback();
131.889 -};
131.890 -
131.891 -ko.subscribable = function () {
131.892 - this._subscriptions = {};
131.893 -
131.894 - ko.utils.extend(this, ko.subscribable['fn']);
131.895 - ko.exportProperty(this, 'subscribe', this.subscribe);
131.896 - ko.exportProperty(this, 'extend', this.extend);
131.897 - ko.exportProperty(this, 'getSubscriptionsCount', this.getSubscriptionsCount);
131.898 -}
131.899 -
131.900 -var defaultEvent = "change";
131.901 -
131.902 -ko.subscribable['fn'] = {
131.903 - subscribe: function (callback, callbackTarget, event) {
131.904 - event = event || defaultEvent;
131.905 - var boundCallback = callbackTarget ? callback.bind(callbackTarget) : callback;
131.906 -
131.907 - var subscription = new ko.subscription(this, boundCallback, function () {
131.908 - ko.utils.arrayRemoveItem(this._subscriptions[event], subscription);
131.909 - }.bind(this));
131.910 -
131.911 - if (!this._subscriptions[event])
131.912 - this._subscriptions[event] = [];
131.913 - this._subscriptions[event].push(subscription);
131.914 - return subscription;
131.915 - },
131.916 -
131.917 - "notifySubscribers": function (valueToNotify, event) {
131.918 - event = event || defaultEvent;
131.919 - if (this._subscriptions[event]) {
131.920 - ko.dependencyDetection.ignore(function() {
131.921 - ko.utils.arrayForEach(this._subscriptions[event].slice(0), function (subscription) {
131.922 - // In case a subscription was disposed during the arrayForEach cycle, check
131.923 - // for isDisposed on each subscription before invoking its callback
131.924 - if (subscription && (subscription.isDisposed !== true))
131.925 - subscription.callback(valueToNotify);
131.926 - });
131.927 - }, this);
131.928 - }
131.929 - },
131.930 -
131.931 - getSubscriptionsCount: function () {
131.932 - var total = 0;
131.933 - for (var eventName in this._subscriptions) {
131.934 - if (this._subscriptions.hasOwnProperty(eventName))
131.935 - total += this._subscriptions[eventName].length;
131.936 - }
131.937 - return total;
131.938 - },
131.939 -
131.940 - extend: applyExtenders
131.941 -};
131.942 -
131.943 -
131.944 -ko.isSubscribable = function (instance) {
131.945 - return typeof instance.subscribe == "function" && typeof instance["notifySubscribers"] == "function";
131.946 -};
131.947 -
131.948 -ko.exportSymbol('subscribable', ko.subscribable);
131.949 -ko.exportSymbol('isSubscribable', ko.isSubscribable);
131.950 -
131.951 -ko.dependencyDetection = (function () {
131.952 - var _frames = [];
131.953 -
131.954 - return {
131.955 - begin: function (callback) {
131.956 - _frames.push({ callback: callback, distinctDependencies:[] });
131.957 - },
131.958 -
131.959 - end: function () {
131.960 - _frames.pop();
131.961 - },
131.962 -
131.963 - registerDependency: function (subscribable) {
131.964 - if (!ko.isSubscribable(subscribable))
131.965 - throw new Error("Only subscribable things can act as dependencies");
131.966 - if (_frames.length > 0) {
131.967 - var topFrame = _frames[_frames.length - 1];
131.968 - if (!topFrame || ko.utils.arrayIndexOf(topFrame.distinctDependencies, subscribable) >= 0)
131.969 - return;
131.970 - topFrame.distinctDependencies.push(subscribable);
131.971 - topFrame.callback(subscribable);
131.972 - }
131.973 - },
131.974 -
131.975 - ignore: function(callback, callbackTarget, callbackArgs) {
131.976 - try {
131.977 - _frames.push(null);
131.978 - return callback.apply(callbackTarget, callbackArgs || []);
131.979 - } finally {
131.980 - _frames.pop();
131.981 - }
131.982 - }
131.983 - };
131.984 -})();
131.985 -var primitiveTypes = { 'undefined':true, 'boolean':true, 'number':true, 'string':true };
131.986 -
131.987 -ko.observable = function (initialValue) {
131.988 - var _latestValue = initialValue;
131.989 -
131.990 - function observable() {
131.991 - if (arguments.length > 0) {
131.992 - // Write
131.993 -
131.994 - // Ignore writes if the value hasn't changed
131.995 - if ((!observable['equalityComparer']) || !observable['equalityComparer'](_latestValue, arguments[0])) {
131.996 - observable.valueWillMutate();
131.997 - _latestValue = arguments[0];
131.998 - if (DEBUG) observable._latestValue = _latestValue;
131.999 - observable.valueHasMutated();
131.1000 - }
131.1001 - return this; // Permits chained assignments
131.1002 - }
131.1003 - else {
131.1004 - // Read
131.1005 - ko.dependencyDetection.registerDependency(observable); // The caller only needs to be notified of changes if they did a "read" operation
131.1006 - return _latestValue;
131.1007 - }
131.1008 - }
131.1009 - if (DEBUG) observable._latestValue = _latestValue;
131.1010 - ko.subscribable.call(observable);
131.1011 - observable.peek = function() { return _latestValue };
131.1012 - observable.valueHasMutated = function () { observable["notifySubscribers"](_latestValue); }
131.1013 - observable.valueWillMutate = function () { observable["notifySubscribers"](_latestValue, "beforeChange"); }
131.1014 - ko.utils.extend(observable, ko.observable['fn']);
131.1015 -
131.1016 - ko.exportProperty(observable, 'peek', observable.peek);
131.1017 - ko.exportProperty(observable, "valueHasMutated", observable.valueHasMutated);
131.1018 - ko.exportProperty(observable, "valueWillMutate", observable.valueWillMutate);
131.1019 -
131.1020 - return observable;
131.1021 -}
131.1022 -
131.1023 -ko.observable['fn'] = {
131.1024 - "equalityComparer": function valuesArePrimitiveAndEqual(a, b) {
131.1025 - var oldValueIsPrimitive = (a === null) || (typeof(a) in primitiveTypes);
131.1026 - return oldValueIsPrimitive ? (a === b) : false;
131.1027 - }
131.1028 -};
131.1029 -
131.1030 -var protoProperty = ko.observable.protoProperty = "__ko_proto__";
131.1031 -ko.observable['fn'][protoProperty] = ko.observable;
131.1032 -
131.1033 -ko.hasPrototype = function(instance, prototype) {
131.1034 - if ((instance === null) || (instance === undefined) || (instance[protoProperty] === undefined)) return false;
131.1035 - if (instance[protoProperty] === prototype) return true;
131.1036 - return ko.hasPrototype(instance[protoProperty], prototype); // Walk the prototype chain
131.1037 -};
131.1038 -
131.1039 -ko.isObservable = function (instance) {
131.1040 - return ko.hasPrototype(instance, ko.observable);
131.1041 -}
131.1042 -ko.isWriteableObservable = function (instance) {
131.1043 - // Observable
131.1044 - if ((typeof instance == "function") && instance[protoProperty] === ko.observable)
131.1045 - return true;
131.1046 - // Writeable dependent observable
131.1047 - if ((typeof instance == "function") && (instance[protoProperty] === ko.dependentObservable) && (instance.hasWriteFunction))
131.1048 - return true;
131.1049 - // Anything else
131.1050 - return false;
131.1051 -}
131.1052 -
131.1053 -
131.1054 -ko.exportSymbol('observable', ko.observable);
131.1055 -ko.exportSymbol('isObservable', ko.isObservable);
131.1056 -ko.exportSymbol('isWriteableObservable', ko.isWriteableObservable);
131.1057 -ko.observableArray = function (initialValues) {
131.1058 - if (arguments.length == 0) {
131.1059 - // Zero-parameter constructor initializes to empty array
131.1060 - initialValues = [];
131.1061 - }
131.1062 - if ((initialValues !== null) && (initialValues !== undefined) && !('length' in initialValues))
131.1063 - throw new Error("The argument passed when initializing an observable array must be an array, or null, or undefined.");
131.1064 -
131.1065 - var result = ko.observable(initialValues);
131.1066 - ko.utils.extend(result, ko.observableArray['fn']);
131.1067 - return result;
131.1068 -}
131.1069 -
131.1070 -ko.observableArray['fn'] = {
131.1071 - 'remove': function (valueOrPredicate) {
131.1072 - var underlyingArray = this.peek();
131.1073 - var removedValues = [];
131.1074 - var predicate = typeof valueOrPredicate == "function" ? valueOrPredicate : function (value) { return value === valueOrPredicate; };
131.1075 - for (var i = 0; i < underlyingArray.length; i++) {
131.1076 - var value = underlyingArray[i];
131.1077 - if (predicate(value)) {
131.1078 - if (removedValues.length === 0) {
131.1079 - this.valueWillMutate();
131.1080 - }
131.1081 - removedValues.push(value);
131.1082 - underlyingArray.splice(i, 1);
131.1083 - i--;
131.1084 - }
131.1085 - }
131.1086 - if (removedValues.length) {
131.1087 - this.valueHasMutated();
131.1088 - }
131.1089 - return removedValues;
131.1090 - },
131.1091 -
131.1092 - 'removeAll': function (arrayOfValues) {
131.1093 - // If you passed zero args, we remove everything
131.1094 - if (arrayOfValues === undefined) {
131.1095 - var underlyingArray = this.peek();
131.1096 - var allValues = underlyingArray.slice(0);
131.1097 - this.valueWillMutate();
131.1098 - underlyingArray.splice(0, underlyingArray.length);
131.1099 - this.valueHasMutated();
131.1100 - return allValues;
131.1101 - }
131.1102 - // If you passed an arg, we interpret it as an array of entries to remove
131.1103 - if (!arrayOfValues)
131.1104 - return [];
131.1105 - return this['remove'](function (value) {
131.1106 - return ko.utils.arrayIndexOf(arrayOfValues, value) >= 0;
131.1107 - });
131.1108 - },
131.1109 -
131.1110 - 'destroy': function (valueOrPredicate) {
131.1111 - var underlyingArray = this.peek();
131.1112 - var predicate = typeof valueOrPredicate == "function" ? valueOrPredicate : function (value) { return value === valueOrPredicate; };
131.1113 - this.valueWillMutate();
131.1114 - for (var i = underlyingArray.length - 1; i >= 0; i--) {
131.1115 - var value = underlyingArray[i];
131.1116 - if (predicate(value))
131.1117 - underlyingArray[i]["_destroy"] = true;
131.1118 - }
131.1119 - this.valueHasMutated();
131.1120 - },
131.1121 -
131.1122 - 'destroyAll': function (arrayOfValues) {
131.1123 - // If you passed zero args, we destroy everything
131.1124 - if (arrayOfValues === undefined)
131.1125 - return this['destroy'](function() { return true });
131.1126 -
131.1127 - // If you passed an arg, we interpret it as an array of entries to destroy
131.1128 - if (!arrayOfValues)
131.1129 - return [];
131.1130 - return this['destroy'](function (value) {
131.1131 - return ko.utils.arrayIndexOf(arrayOfValues, value) >= 0;
131.1132 - });
131.1133 - },
131.1134 -
131.1135 - 'indexOf': function (item) {
131.1136 - var underlyingArray = this();
131.1137 - return ko.utils.arrayIndexOf(underlyingArray, item);
131.1138 - },
131.1139 -
131.1140 - 'replace': function(oldItem, newItem) {
131.1141 - var index = this['indexOf'](oldItem);
131.1142 - if (index >= 0) {
131.1143 - this.valueWillMutate();
131.1144 - this.peek()[index] = newItem;
131.1145 - this.valueHasMutated();
131.1146 - }
131.1147 - }
131.1148 -}
131.1149 -
131.1150 -// Populate ko.observableArray.fn with read/write functions from native arrays
131.1151 -// Important: Do not add any additional functions here that may reasonably be used to *read* data from the array
131.1152 -// because we'll eval them without causing subscriptions, so ko.computed output could end up getting stale
131.1153 -ko.utils.arrayForEach(["pop", "push", "reverse", "shift", "sort", "splice", "unshift"], function (methodName) {
131.1154 - ko.observableArray['fn'][methodName] = function () {
131.1155 - // Use "peek" to avoid creating a subscription in any computed that we're executing in the context of
131.1156 - // (for consistency with mutating regular observables)
131.1157 - var underlyingArray = this.peek();
131.1158 - this.valueWillMutate();
131.1159 - var methodCallResult = underlyingArray[methodName].apply(underlyingArray, arguments);
131.1160 - this.valueHasMutated();
131.1161 - return methodCallResult;
131.1162 - };
131.1163 -});
131.1164 -
131.1165 -// Populate ko.observableArray.fn with read-only functions from native arrays
131.1166 -ko.utils.arrayForEach(["slice"], function (methodName) {
131.1167 - ko.observableArray['fn'][methodName] = function () {
131.1168 - var underlyingArray = this();
131.1169 - return underlyingArray[methodName].apply(underlyingArray, arguments);
131.1170 - };
131.1171 -});
131.1172 -
131.1173 -ko.exportSymbol('observableArray', ko.observableArray);
131.1174 -ko.dependentObservable = function (evaluatorFunctionOrOptions, evaluatorFunctionTarget, options) {
131.1175 - var _latestValue,
131.1176 - _hasBeenEvaluated = false,
131.1177 - _isBeingEvaluated = false,
131.1178 - readFunction = evaluatorFunctionOrOptions;
131.1179 -
131.1180 - if (readFunction && typeof readFunction == "object") {
131.1181 - // Single-parameter syntax - everything is on this "options" param
131.1182 - options = readFunction;
131.1183 - readFunction = options["read"];
131.1184 - } else {
131.1185 - // Multi-parameter syntax - construct the options according to the params passed
131.1186 - options = options || {};
131.1187 - if (!readFunction)
131.1188 - readFunction = options["read"];
131.1189 - }
131.1190 - if (typeof readFunction != "function")
131.1191 - throw new Error("Pass a function that returns the value of the ko.computed");
131.1192 -
131.1193 - function addSubscriptionToDependency(subscribable) {
131.1194 - _subscriptionsToDependencies.push(subscribable.subscribe(evaluatePossiblyAsync));
131.1195 - }
131.1196 -
131.1197 - function disposeAllSubscriptionsToDependencies() {
131.1198 - ko.utils.arrayForEach(_subscriptionsToDependencies, function (subscription) {
131.1199 - subscription.dispose();
131.1200 - });
131.1201 - _subscriptionsToDependencies = [];
131.1202 - }
131.1203 -
131.1204 - function evaluatePossiblyAsync() {
131.1205 - var throttleEvaluationTimeout = dependentObservable['throttleEvaluation'];
131.1206 - if (throttleEvaluationTimeout && throttleEvaluationTimeout >= 0) {
131.1207 - clearTimeout(evaluationTimeoutInstance);
131.1208 - evaluationTimeoutInstance = setTimeout(evaluateImmediate, throttleEvaluationTimeout);
131.1209 - } else
131.1210 - evaluateImmediate();
131.1211 - }
131.1212 -
131.1213 - function evaluateImmediate() {
131.1214 - if (_isBeingEvaluated) {
131.1215 - // If the evaluation of a ko.computed causes side effects, it's possible that it will trigger its own re-evaluation.
131.1216 - // This is not desirable (it's hard for a developer to realise a chain of dependencies might cause this, and they almost
131.1217 - // certainly didn't intend infinite re-evaluations). So, for predictability, we simply prevent ko.computeds from causing
131.1218 - // their own re-evaluation. Further discussion at https://github.com/SteveSanderson/knockout/pull/387
131.1219 - return;
131.1220 - }
131.1221 -
131.1222 - // Don't dispose on first evaluation, because the "disposeWhen" callback might
131.1223 - // e.g., dispose when the associated DOM element isn't in the doc, and it's not
131.1224 - // going to be in the doc until *after* the first evaluation
131.1225 - if (_hasBeenEvaluated && disposeWhen()) {
131.1226 - dispose();
131.1227 - return;
131.1228 - }
131.1229 -
131.1230 - _isBeingEvaluated = true;
131.1231 - try {
131.1232 - // Initially, we assume that none of the subscriptions are still being used (i.e., all are candidates for disposal).
131.1233 - // Then, during evaluation, we cross off any that are in fact still being used.
131.1234 - var disposalCandidates = ko.utils.arrayMap(_subscriptionsToDependencies, function(item) {return item.target;});
131.1235 -
131.1236 - ko.dependencyDetection.begin(function(subscribable) {
131.1237 - var inOld;
131.1238 - if ((inOld = ko.utils.arrayIndexOf(disposalCandidates, subscribable)) >= 0)
131.1239 - disposalCandidates[inOld] = undefined; // Don't want to dispose this subscription, as it's still being used
131.1240 - else
131.1241 - addSubscriptionToDependency(subscribable); // Brand new subscription - add it
131.1242 - });
131.1243 -
131.1244 - var newValue = readFunction.call(evaluatorFunctionTarget);
131.1245 -
131.1246 - // For each subscription no longer being used, remove it from the active subscriptions list and dispose it
131.1247 - for (var i = disposalCandidates.length - 1; i >= 0; i--) {
131.1248 - if (disposalCandidates[i])
131.1249 - _subscriptionsToDependencies.splice(i, 1)[0].dispose();
131.1250 - }
131.1251 - _hasBeenEvaluated = true;
131.1252 -
131.1253 - dependentObservable["notifySubscribers"](_latestValue, "beforeChange");
131.1254 - _latestValue = newValue;
131.1255 - if (DEBUG) dependentObservable._latestValue = _latestValue;
131.1256 - } finally {
131.1257 - ko.dependencyDetection.end();
131.1258 - }
131.1259 -
131.1260 - dependentObservable["notifySubscribers"](_latestValue);
131.1261 - _isBeingEvaluated = false;
131.1262 - if (!_subscriptionsToDependencies.length)
131.1263 - dispose();
131.1264 - }
131.1265 -
131.1266 - function dependentObservable() {
131.1267 - if (arguments.length > 0) {
131.1268 - if (typeof writeFunction === "function") {
131.1269 - // Writing a value
131.1270 - writeFunction.apply(evaluatorFunctionTarget, arguments);
131.1271 - } else {
131.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.");
131.1273 - }
131.1274 - return this; // Permits chained assignments
131.1275 - } else {
131.1276 - // Reading the value
131.1277 - if (!_hasBeenEvaluated)
131.1278 - evaluateImmediate();
131.1279 - ko.dependencyDetection.registerDependency(dependentObservable);
131.1280 - return _latestValue;
131.1281 - }
131.1282 - }
131.1283 -
131.1284 - function peek() {
131.1285 - if (!_hasBeenEvaluated)
131.1286 - evaluateImmediate();
131.1287 - return _latestValue;
131.1288 - }
131.1289 -
131.1290 - function isActive() {
131.1291 - return !_hasBeenEvaluated || _subscriptionsToDependencies.length > 0;
131.1292 - }
131.1293 -
131.1294 - // By here, "options" is always non-null
131.1295 - var writeFunction = options["write"],
131.1296 - disposeWhenNodeIsRemoved = options["disposeWhenNodeIsRemoved"] || options.disposeWhenNodeIsRemoved || null,
131.1297 - disposeWhen = options["disposeWhen"] || options.disposeWhen || function() { return false; },
131.1298 - dispose = disposeAllSubscriptionsToDependencies,
131.1299 - _subscriptionsToDependencies = [],
131.1300 - evaluationTimeoutInstance = null;
131.1301 -
131.1302 - if (!evaluatorFunctionTarget)
131.1303 - evaluatorFunctionTarget = options["owner"];
131.1304 -
131.1305 - dependentObservable.peek = peek;
131.1306 - dependentObservable.getDependenciesCount = function () { return _subscriptionsToDependencies.length; };
131.1307 - dependentObservable.hasWriteFunction = typeof options["write"] === "function";
131.1308 - dependentObservable.dispose = function () { dispose(); };
131.1309 - dependentObservable.isActive = isActive;
131.1310 - dependentObservable.valueHasMutated = function() {
131.1311 - _hasBeenEvaluated = false;
131.1312 - evaluateImmediate();
131.1313 - };
131.1314 -
131.1315 - ko.subscribable.call(dependentObservable);
131.1316 - ko.utils.extend(dependentObservable, ko.dependentObservable['fn']);
131.1317 -
131.1318 - ko.exportProperty(dependentObservable, 'peek', dependentObservable.peek);
131.1319 - ko.exportProperty(dependentObservable, 'dispose', dependentObservable.dispose);
131.1320 - ko.exportProperty(dependentObservable, 'isActive', dependentObservable.isActive);
131.1321 - ko.exportProperty(dependentObservable, 'getDependenciesCount', dependentObservable.getDependenciesCount);
131.1322 -
131.1323 - // Evaluate, unless deferEvaluation is true
131.1324 - if (options['deferEvaluation'] !== true)
131.1325 - evaluateImmediate();
131.1326 -
131.1327 - // Build "disposeWhenNodeIsRemoved" and "disposeWhenNodeIsRemovedCallback" option values.
131.1328 - // But skip if isActive is false (there will never be any dependencies to dispose).
131.1329 - // (Note: "disposeWhenNodeIsRemoved" option both proactively disposes as soon as the node is removed using ko.removeNode(),
131.1330 - // plus adds a "disposeWhen" callback that, on each evaluation, disposes if the node was removed by some other means.)
131.1331 - if (disposeWhenNodeIsRemoved && isActive()) {
131.1332 - dispose = function() {
131.1333 - ko.utils.domNodeDisposal.removeDisposeCallback(disposeWhenNodeIsRemoved, arguments.callee);
131.1334 - disposeAllSubscriptionsToDependencies();
131.1335 - };
131.1336 - ko.utils.domNodeDisposal.addDisposeCallback(disposeWhenNodeIsRemoved, dispose);
131.1337 - var existingDisposeWhenFunction = disposeWhen;
131.1338 - disposeWhen = function () {
131.1339 - return !ko.utils.domNodeIsAttachedToDocument(disposeWhenNodeIsRemoved) || existingDisposeWhenFunction();
131.1340 - }
131.1341 - }
131.1342 -
131.1343 - return dependentObservable;
131.1344 -};
131.1345 -
131.1346 -ko.isComputed = function(instance) {
131.1347 - return ko.hasPrototype(instance, ko.dependentObservable);
131.1348 -};
131.1349 -
131.1350 -var protoProp = ko.observable.protoProperty; // == "__ko_proto__"
131.1351 -ko.dependentObservable[protoProp] = ko.observable;
131.1352 -
131.1353 -ko.dependentObservable['fn'] = {};
131.1354 -ko.dependentObservable['fn'][protoProp] = ko.dependentObservable;
131.1355 -
131.1356 -ko.exportSymbol('dependentObservable', ko.dependentObservable);
131.1357 -ko.exportSymbol('computed', ko.dependentObservable); // Make "ko.computed" an alias for "ko.dependentObservable"
131.1358 -ko.exportSymbol('isComputed', ko.isComputed);
131.1359 -
131.1360 -(function() {
131.1361 - var maxNestedObservableDepth = 10; // Escape the (unlikely) pathalogical case where an observable's current value is itself (or similar reference cycle)
131.1362 -
131.1363 - ko.toJS = function(rootObject) {
131.1364 - if (arguments.length == 0)
131.1365 - throw new Error("When calling ko.toJS, pass the object you want to convert.");
131.1366 -
131.1367 - // We just unwrap everything at every level in the object graph
131.1368 - return mapJsObjectGraph(rootObject, function(valueToMap) {
131.1369 - // Loop because an observable's value might in turn be another observable wrapper
131.1370 - for (var i = 0; ko.isObservable(valueToMap) && (i < maxNestedObservableDepth); i++)
131.1371 - valueToMap = valueToMap();
131.1372 - return valueToMap;
131.1373 - });
131.1374 - };
131.1375 -
131.1376 - ko.toJSON = function(rootObject, replacer, space) { // replacer and space are optional
131.1377 - var plainJavaScriptObject = ko.toJS(rootObject);
131.1378 - return ko.utils.stringifyJson(plainJavaScriptObject, replacer, space);
131.1379 - };
131.1380 -
131.1381 - function mapJsObjectGraph(rootObject, mapInputCallback, visitedObjects) {
131.1382 - visitedObjects = visitedObjects || new objectLookup();
131.1383 -
131.1384 - rootObject = mapInputCallback(rootObject);
131.1385 - var canHaveProperties = (typeof rootObject == "object") && (rootObject !== null) && (rootObject !== undefined) && (!(rootObject instanceof Date));
131.1386 - if (!canHaveProperties)
131.1387 - return rootObject;
131.1388 -
131.1389 - var outputProperties = rootObject instanceof Array ? [] : {};
131.1390 - visitedObjects.save(rootObject, outputProperties);
131.1391 -
131.1392 - visitPropertiesOrArrayEntries(rootObject, function(indexer) {
131.1393 - var propertyValue = mapInputCallback(rootObject[indexer]);
131.1394 -
131.1395 - switch (typeof propertyValue) {
131.1396 - case "boolean":
131.1397 - case "number":
131.1398 - case "string":
131.1399 - case "function":
131.1400 - outputProperties[indexer] = propertyValue;
131.1401 - break;
131.1402 - case "object":
131.1403 - case "undefined":
131.1404 - var previouslyMappedValue = visitedObjects.get(propertyValue);
131.1405 - outputProperties[indexer] = (previouslyMappedValue !== undefined)
131.1406 - ? previouslyMappedValue
131.1407 - : mapJsObjectGraph(propertyValue, mapInputCallback, visitedObjects);
131.1408 - break;
131.1409 - }
131.1410 - });
131.1411 -
131.1412 - return outputProperties;
131.1413 - }
131.1414 -
131.1415 - function visitPropertiesOrArrayEntries(rootObject, visitorCallback) {
131.1416 - if (rootObject instanceof Array) {
131.1417 - for (var i = 0; i < rootObject.length; i++)
131.1418 - visitorCallback(i);
131.1419 -
131.1420 - // For arrays, also respect toJSON property for custom mappings (fixes #278)
131.1421 - if (typeof rootObject['toJSON'] == 'function')
131.1422 - visitorCallback('toJSON');
131.1423 - } else {
131.1424 - for (var propertyName in rootObject)
131.1425 - visitorCallback(propertyName);
131.1426 - }
131.1427 - };
131.1428 -
131.1429 - function objectLookup() {
131.1430 - var keys = [];
131.1431 - var values = [];
131.1432 - this.save = function(key, value) {
131.1433 - var existingIndex = ko.utils.arrayIndexOf(keys, key);
131.1434 - if (existingIndex >= 0)
131.1435 - values[existingIndex] = value;
131.1436 - else {
131.1437 - keys.push(key);
131.1438 - values.push(value);
131.1439 - }
131.1440 - };
131.1441 - this.get = function(key) {
131.1442 - var existingIndex = ko.utils.arrayIndexOf(keys, key);
131.1443 - return (existingIndex >= 0) ? values[existingIndex] : undefined;
131.1444 - };
131.1445 - };
131.1446 -})();
131.1447 -
131.1448 -ko.exportSymbol('toJS', ko.toJS);
131.1449 -ko.exportSymbol('toJSON', ko.toJSON);
131.1450 -(function () {
131.1451 - var hasDomDataExpandoProperty = '__ko__hasDomDataOptionValue__';
131.1452 -
131.1453 - // Normally, SELECT elements and their OPTIONs can only take value of type 'string' (because the values
131.1454 - // are stored on DOM attributes). ko.selectExtensions provides a way for SELECTs/OPTIONs to have values
131.1455 - // that are arbitrary objects. This is very convenient when implementing things like cascading dropdowns.
131.1456 - ko.selectExtensions = {
131.1457 - readValue : function(element) {
131.1458 - switch (ko.utils.tagNameLower(element)) {
131.1459 - case 'option':
131.1460 - if (element[hasDomDataExpandoProperty] === true)
131.1461 - return ko.utils.domData.get(element, ko.bindingHandlers.options.optionValueDomDataKey);
131.1462 - return ko.utils.ieVersion <= 7
131.1463 - ? (element.getAttributeNode('value').specified ? element.value : element.text)
131.1464 - : element.value;
131.1465 - case 'select':
131.1466 - return element.selectedIndex >= 0 ? ko.selectExtensions.readValue(element.options[element.selectedIndex]) : undefined;
131.1467 - default:
131.1468 - return element.value;
131.1469 - }
131.1470 - },
131.1471 -
131.1472 - writeValue: function(element, value) {
131.1473 - switch (ko.utils.tagNameLower(element)) {
131.1474 - case 'option':
131.1475 - switch(typeof value) {
131.1476 - case "string":
131.1477 - ko.utils.domData.set(element, ko.bindingHandlers.options.optionValueDomDataKey, undefined);
131.1478 - if (hasDomDataExpandoProperty in element) { // IE <= 8 throws errors if you delete non-existent properties from a DOM node
131.1479 - delete element[hasDomDataExpandoProperty];
131.1480 - }
131.1481 - element.value = value;
131.1482 - break;
131.1483 - default:
131.1484 - // Store arbitrary object using DomData
131.1485 - ko.utils.domData.set(element, ko.bindingHandlers.options.optionValueDomDataKey, value);
131.1486 - element[hasDomDataExpandoProperty] = true;
131.1487 -
131.1488 - // Special treatment of numbers is just for backward compatibility. KO 1.2.1 wrote numerical values to element.value.
131.1489 - element.value = typeof value === "number" ? value : "";
131.1490 - break;
131.1491 - }
131.1492 - break;
131.1493 - case 'select':
131.1494 - for (var i = element.options.length - 1; i >= 0; i--) {
131.1495 - if (ko.selectExtensions.readValue(element.options[i]) == value) {
131.1496 - element.selectedIndex = i;
131.1497 - break;
131.1498 - }
131.1499 - }
131.1500 - break;
131.1501 - default:
131.1502 - if ((value === null) || (value === undefined))
131.1503 - value = "";
131.1504 - element.value = value;
131.1505 - break;
131.1506 - }
131.1507 - }
131.1508 - };
131.1509 -})();
131.1510 -
131.1511 -ko.exportSymbol('selectExtensions', ko.selectExtensions);
131.1512 -ko.exportSymbol('selectExtensions.readValue', ko.selectExtensions.readValue);
131.1513 -ko.exportSymbol('selectExtensions.writeValue', ko.selectExtensions.writeValue);
131.1514 -ko.expressionRewriting = (function () {
131.1515 - var restoreCapturedTokensRegex = /\@ko_token_(\d+)\@/g;
131.1516 - var javaScriptReservedWords = ["true", "false"];
131.1517 -
131.1518 - // Matches something that can be assigned to--either an isolated identifier or something ending with a property accessor
131.1519 - // This is designed to be simple and avoid false negatives, but could produce false positives (e.g., a+b.c).
131.1520 - var javaScriptAssignmentTarget = /^(?:[$_a-z][$\w]*|(.+)(\.\s*[$_a-z][$\w]*|\[.+\]))$/i;
131.1521 -
131.1522 - function restoreTokens(string, tokens) {
131.1523 - var prevValue = null;
131.1524 - while (string != prevValue) { // Keep restoring tokens until it no longer makes a difference (they may be nested)
131.1525 - prevValue = string;
131.1526 - string = string.replace(restoreCapturedTokensRegex, function (match, tokenIndex) {
131.1527 - return tokens[tokenIndex];
131.1528 - });
131.1529 - }
131.1530 - return string;
131.1531 - }
131.1532 -
131.1533 - function getWriteableValue(expression) {
131.1534 - if (ko.utils.arrayIndexOf(javaScriptReservedWords, ko.utils.stringTrim(expression).toLowerCase()) >= 0)
131.1535 - return false;
131.1536 - var match = expression.match(javaScriptAssignmentTarget);
131.1537 - return match === null ? false : match[1] ? ('Object(' + match[1] + ')' + match[2]) : expression;
131.1538 - }
131.1539 -
131.1540 - function ensureQuoted(key) {
131.1541 - var trimmedKey = ko.utils.stringTrim(key);
131.1542 - switch (trimmedKey.length && trimmedKey.charAt(0)) {
131.1543 - case "'":
131.1544 - case '"':
131.1545 - return key;
131.1546 - default:
131.1547 - return "'" + trimmedKey + "'";
131.1548 - }
131.1549 - }
131.1550 -
131.1551 - return {
131.1552 - bindingRewriteValidators: [],
131.1553 -
131.1554 - parseObjectLiteral: function(objectLiteralString) {
131.1555 - // A full tokeniser+lexer would add too much weight to this library, so here's a simple parser
131.1556 - // that is sufficient just to split an object literal string into a set of top-level key-value pairs
131.1557 -
131.1558 - var str = ko.utils.stringTrim(objectLiteralString);
131.1559 - if (str.length < 3)
131.1560 - return [];
131.1561 - if (str.charAt(0) === "{")// Ignore any braces surrounding the whole object literal
131.1562 - str = str.substring(1, str.length - 1);
131.1563 -
131.1564 - // Pull out any string literals and regex literals
131.1565 - var tokens = [];
131.1566 - var tokenStart = null, tokenEndChar;
131.1567 - for (var position = 0; position < str.length; position++) {
131.1568 - var c = str.charAt(position);
131.1569 - if (tokenStart === null) {
131.1570 - switch (c) {
131.1571 - case '"':
131.1572 - case "'":
131.1573 - case "/":
131.1574 - tokenStart = position;
131.1575 - tokenEndChar = c;
131.1576 - break;
131.1577 - }
131.1578 - } else if ((c == tokenEndChar) && (str.charAt(position - 1) !== "\\")) {
131.1579 - var token = str.substring(tokenStart, position + 1);
131.1580 - tokens.push(token);
131.1581 - var replacement = "@ko_token_" + (tokens.length - 1) + "@";
131.1582 - str = str.substring(0, tokenStart) + replacement + str.substring(position + 1);
131.1583 - position -= (token.length - replacement.length);
131.1584 - tokenStart = null;
131.1585 - }
131.1586 - }
131.1587 -
131.1588 - // Next pull out balanced paren, brace, and bracket blocks
131.1589 - tokenStart = null;
131.1590 - tokenEndChar = null;
131.1591 - var tokenDepth = 0, tokenStartChar = null;
131.1592 - for (var position = 0; position < str.length; position++) {
131.1593 - var c = str.charAt(position);
131.1594 - if (tokenStart === null) {
131.1595 - switch (c) {
131.1596 - case "{": tokenStart = position; tokenStartChar = c;
131.1597 - tokenEndChar = "}";
131.1598 - break;
131.1599 - case "(": tokenStart = position; tokenStartChar = c;
131.1600 - tokenEndChar = ")";
131.1601 - break;
131.1602 - case "[": tokenStart = position; tokenStartChar = c;
131.1603 - tokenEndChar = "]";
131.1604 - break;
131.1605 - }
131.1606 - }
131.1607 -
131.1608 - if (c === tokenStartChar)
131.1609 - tokenDepth++;
131.1610 - else if (c === tokenEndChar) {
131.1611 - tokenDepth--;
131.1612 - if (tokenDepth === 0) {
131.1613 - var token = str.substring(tokenStart, position + 1);
131.1614 - tokens.push(token);
131.1615 - var replacement = "@ko_token_" + (tokens.length - 1) + "@";
131.1616 - str = str.substring(0, tokenStart) + replacement + str.substring(position + 1);
131.1617 - position -= (token.length - replacement.length);
131.1618 - tokenStart = null;
131.1619 - }
131.1620 - }
131.1621 - }
131.1622 -
131.1623 - // Now we can safely split on commas to get the key/value pairs
131.1624 - var result = [];
131.1625 - var keyValuePairs = str.split(",");
131.1626 - for (var i = 0, j = keyValuePairs.length; i < j; i++) {
131.1627 - var pair = keyValuePairs[i];
131.1628 - var colonPos = pair.indexOf(":");
131.1629 - if ((colonPos > 0) && (colonPos < pair.length - 1)) {
131.1630 - var key = pair.substring(0, colonPos);
131.1631 - var value = pair.substring(colonPos + 1);
131.1632 - result.push({ 'key': restoreTokens(key, tokens), 'value': restoreTokens(value, tokens) });
131.1633 - } else {
131.1634 - result.push({ 'unknown': restoreTokens(pair, tokens) });
131.1635 - }
131.1636 - }
131.1637 - return result;
131.1638 - },
131.1639 -
131.1640 - preProcessBindings: function (objectLiteralStringOrKeyValueArray) {
131.1641 - var keyValueArray = typeof objectLiteralStringOrKeyValueArray === "string"
131.1642 - ? ko.expressionRewriting.parseObjectLiteral(objectLiteralStringOrKeyValueArray)
131.1643 - : objectLiteralStringOrKeyValueArray;
131.1644 - var resultStrings = [], propertyAccessorResultStrings = [];
131.1645 -
131.1646 - var keyValueEntry;
131.1647 - for (var i = 0; keyValueEntry = keyValueArray[i]; i++) {
131.1648 - if (resultStrings.length > 0)
131.1649 - resultStrings.push(",");
131.1650 -
131.1651 - if (keyValueEntry['key']) {
131.1652 - var quotedKey = ensureQuoted(keyValueEntry['key']), val = keyValueEntry['value'];
131.1653 - resultStrings.push(quotedKey);
131.1654 - resultStrings.push(":");
131.1655 - resultStrings.push(val);
131.1656 -
131.1657 - if (val = getWriteableValue(ko.utils.stringTrim(val))) {
131.1658 - if (propertyAccessorResultStrings.length > 0)
131.1659 - propertyAccessorResultStrings.push(", ");
131.1660 - propertyAccessorResultStrings.push(quotedKey + " : function(__ko_value) { " + val + " = __ko_value; }");
131.1661 - }
131.1662 - } else if (keyValueEntry['unknown']) {
131.1663 - resultStrings.push(keyValueEntry['unknown']);
131.1664 - }
131.1665 - }
131.1666 -
131.1667 - var combinedResult = resultStrings.join("");
131.1668 - if (propertyAccessorResultStrings.length > 0) {
131.1669 - var allPropertyAccessors = propertyAccessorResultStrings.join("");
131.1670 - combinedResult = combinedResult + ", '_ko_property_writers' : { " + allPropertyAccessors + " } ";
131.1671 - }
131.1672 -
131.1673 - return combinedResult;
131.1674 - },
131.1675 -
131.1676 - keyValueArrayContainsKey: function(keyValueArray, key) {
131.1677 - for (var i = 0; i < keyValueArray.length; i++)
131.1678 - if (ko.utils.stringTrim(keyValueArray[i]['key']) == key)
131.1679 - return true;
131.1680 - return false;
131.1681 - },
131.1682 -
131.1683 - // Internal, private KO utility for updating model properties from within bindings
131.1684 - // property: If the property being updated is (or might be) an observable, pass it here
131.1685 - // If it turns out to be a writable observable, it will be written to directly
131.1686 - // allBindingsAccessor: All bindings in the current execution context.
131.1687 - // This will be searched for a '_ko_property_writers' property in case you're writing to a non-observable
131.1688 - // key: The key identifying the property to be written. Example: for { hasFocus: myValue }, write to 'myValue' by specifying the key 'hasFocus'
131.1689 - // value: The value to be written
131.1690 - // checkIfDifferent: If true, and if the property being written is a writable observable, the value will only be written if
131.1691 - // it is !== existing value on that writable observable
131.1692 - writeValueToProperty: function(property, allBindingsAccessor, key, value, checkIfDifferent) {
131.1693 - if (!property || !ko.isWriteableObservable(property)) {
131.1694 - var propWriters = allBindingsAccessor()['_ko_property_writers'];
131.1695 - if (propWriters && propWriters[key])
131.1696 - propWriters[key](value);
131.1697 - } else if (!checkIfDifferent || property.peek() !== value) {
131.1698 - property(value);
131.1699 - }
131.1700 - }
131.1701 - };
131.1702 -})();
131.1703 -
131.1704 -ko.exportSymbol('expressionRewriting', ko.expressionRewriting);
131.1705 -ko.exportSymbol('expressionRewriting.bindingRewriteValidators', ko.expressionRewriting.bindingRewriteValidators);
131.1706 -ko.exportSymbol('expressionRewriting.parseObjectLiteral', ko.expressionRewriting.parseObjectLiteral);
131.1707 -ko.exportSymbol('expressionRewriting.preProcessBindings', ko.expressionRewriting.preProcessBindings);
131.1708 -
131.1709 -// For backward compatibility, define the following aliases. (Previously, these function names were misleading because
131.1710 -// they referred to JSON specifically, even though they actually work with arbitrary JavaScript object literal expressions.)
131.1711 -ko.exportSymbol('jsonExpressionRewriting', ko.expressionRewriting);
131.1712 -ko.exportSymbol('jsonExpressionRewriting.insertPropertyAccessorsIntoJson', ko.expressionRewriting.preProcessBindings);(function() {
131.1713 - // "Virtual elements" is an abstraction on top of the usual DOM API which understands the notion that comment nodes
131.1714 - // may be used to represent hierarchy (in addition to the DOM's natural hierarchy).
131.1715 - // If you call the DOM-manipulating functions on ko.virtualElements, you will be able to read and write the state
131.1716 - // of that virtual hierarchy
131.1717 - //
131.1718 - // The point of all this is to support containerless templates (e.g., <!-- ko foreach:someCollection -->blah<!-- /ko -->)
131.1719 - // without having to scatter special cases all over the binding and templating code.
131.1720 -
131.1721 - // IE 9 cannot reliably read the "nodeValue" property of a comment node (see https://github.com/SteveSanderson/knockout/issues/186)
131.1722 - // but it does give them a nonstandard alternative property called "text" that it can read reliably. Other browsers don't have that property.
131.1723 - // So, use node.text where available, and node.nodeValue elsewhere
131.1724 - var commentNodesHaveTextProperty = document.createComment("test").text === "<!--test-->";
131.1725 -
131.1726 - var startCommentRegex = commentNodesHaveTextProperty ? /^<!--\s*ko(?:\s+(.+\s*\:[\s\S]*))?\s*-->$/ : /^\s*ko(?:\s+(.+\s*\:[\s\S]*))?\s*$/;
131.1727 - var endCommentRegex = commentNodesHaveTextProperty ? /^<!--\s*\/ko\s*-->$/ : /^\s*\/ko\s*$/;
131.1728 - var htmlTagsWithOptionallyClosingChildren = { 'ul': true, 'ol': true };
131.1729 -
131.1730 - function isStartComment(node) {
131.1731 - return (node.nodeType == 8) && (commentNodesHaveTextProperty ? node.text : node.nodeValue).match(startCommentRegex);
131.1732 - }
131.1733 -
131.1734 - function isEndComment(node) {
131.1735 - return (node.nodeType == 8) && (commentNodesHaveTextProperty ? node.text : node.nodeValue).match(endCommentRegex);
131.1736 - }
131.1737 -
131.1738 - function getVirtualChildren(startComment, allowUnbalanced) {
131.1739 - var currentNode = startComment;
131.1740 - var depth = 1;
131.1741 - var children = [];
131.1742 - while (currentNode = currentNode.nextSibling) {
131.1743 - if (isEndComment(currentNode)) {
131.1744 - depth--;
131.1745 - if (depth === 0)
131.1746 - return children;
131.1747 - }
131.1748 -
131.1749 - children.push(currentNode);
131.1750 -
131.1751 - if (isStartComment(currentNode))
131.1752 - depth++;
131.1753 - }
131.1754 - if (!allowUnbalanced)
131.1755 - throw new Error("Cannot find closing comment tag to match: " + startComment.nodeValue);
131.1756 - return null;
131.1757 - }
131.1758 -
131.1759 - function getMatchingEndComment(startComment, allowUnbalanced) {
131.1760 - var allVirtualChildren = getVirtualChildren(startComment, allowUnbalanced);
131.1761 - if (allVirtualChildren) {
131.1762 - if (allVirtualChildren.length > 0)
131.1763 - return allVirtualChildren[allVirtualChildren.length - 1].nextSibling;
131.1764 - return startComment.nextSibling;
131.1765 - } else
131.1766 - return null; // Must have no matching end comment, and allowUnbalanced is true
131.1767 - }
131.1768 -
131.1769 - function getUnbalancedChildTags(node) {
131.1770 - // e.g., from <div>OK</div><!-- ko blah --><span>Another</span>, returns: <!-- ko blah --><span>Another</span>
131.1771 - // from <div>OK</div><!-- /ko --><!-- /ko -->, returns: <!-- /ko --><!-- /ko -->
131.1772 - var childNode = node.firstChild, captureRemaining = null;
131.1773 - if (childNode) {
131.1774 - do {
131.1775 - if (captureRemaining) // We already hit an unbalanced node and are now just scooping up all subsequent nodes
131.1776 - captureRemaining.push(childNode);
131.1777 - else if (isStartComment(childNode)) {
131.1778 - var matchingEndComment = getMatchingEndComment(childNode, /* allowUnbalanced: */ true);
131.1779 - if (matchingEndComment) // It's a balanced tag, so skip immediately to the end of this virtual set
131.1780 - childNode = matchingEndComment;
131.1781 - else
131.1782 - captureRemaining = [childNode]; // It's unbalanced, so start capturing from this point
131.1783 - } else if (isEndComment(childNode)) {
131.1784 - captureRemaining = [childNode]; // It's unbalanced (if it wasn't, we'd have skipped over it already), so start capturing
131.1785 - }
131.1786 - } while (childNode = childNode.nextSibling);
131.1787 - }
131.1788 - return captureRemaining;
131.1789 - }
131.1790 -
131.1791 - ko.virtualElements = {
131.1792 - allowedBindings: {},
131.1793 -
131.1794 - childNodes: function(node) {
131.1795 - return isStartComment(node) ? getVirtualChildren(node) : node.childNodes;
131.1796 - },
131.1797 -
131.1798 - emptyNode: function(node) {
131.1799 - if (!isStartComment(node))
131.1800 - ko.utils.emptyDomNode(node);
131.1801 - else {
131.1802 - var virtualChildren = ko.virtualElements.childNodes(node);
131.1803 - for (var i = 0, j = virtualChildren.length; i < j; i++)
131.1804 - ko.removeNode(virtualChildren[i]);
131.1805 - }
131.1806 - },
131.1807 -
131.1808 - setDomNodeChildren: function(node, childNodes) {
131.1809 - if (!isStartComment(node))
131.1810 - ko.utils.setDomNodeChildren(node, childNodes);
131.1811 - else {
131.1812 - ko.virtualElements.emptyNode(node);
131.1813 - var endCommentNode = node.nextSibling; // Must be the next sibling, as we just emptied the children
131.1814 - for (var i = 0, j = childNodes.length; i < j; i++)
131.1815 - endCommentNode.parentNode.insertBefore(childNodes[i], endCommentNode);
131.1816 - }
131.1817 - },
131.1818 -
131.1819 - prepend: function(containerNode, nodeToPrepend) {
131.1820 - if (!isStartComment(containerNode)) {
131.1821 - if (containerNode.firstChild)
131.1822 - containerNode.insertBefore(nodeToPrepend, containerNode.firstChild);
131.1823 - else
131.1824 - containerNode.appendChild(nodeToPrepend);
131.1825 - } else {
131.1826 - // Start comments must always have a parent and at least one following sibling (the end comment)
131.1827 - containerNode.parentNode.insertBefore(nodeToPrepend, containerNode.nextSibling);
131.1828 - }
131.1829 - },
131.1830 -
131.1831 - insertAfter: function(containerNode, nodeToInsert, insertAfterNode) {
131.1832 - if (!insertAfterNode) {
131.1833 - ko.virtualElements.prepend(containerNode, nodeToInsert);
131.1834 - } else if (!isStartComment(containerNode)) {
131.1835 - // Insert after insertion point
131.1836 - if (insertAfterNode.nextSibling)
131.1837 - containerNode.insertBefore(nodeToInsert, insertAfterNode.nextSibling);
131.1838 - else
131.1839 - containerNode.appendChild(nodeToInsert);
131.1840 - } else {
131.1841 - // Children of start comments must always have a parent and at least one following sibling (the end comment)
131.1842 - containerNode.parentNode.insertBefore(nodeToInsert, insertAfterNode.nextSibling);
131.1843 - }
131.1844 - },
131.1845 -
131.1846 - firstChild: function(node) {
131.1847 - if (!isStartComment(node))
131.1848 - return node.firstChild;
131.1849 - if (!node.nextSibling || isEndComment(node.nextSibling))
131.1850 - return null;
131.1851 - return node.nextSibling;
131.1852 - },
131.1853 -
131.1854 - nextSibling: function(node) {
131.1855 - if (isStartComment(node))
131.1856 - node = getMatchingEndComment(node);
131.1857 - if (node.nextSibling && isEndComment(node.nextSibling))
131.1858 - return null;
131.1859 - return node.nextSibling;
131.1860 - },
131.1861 -
131.1862 - virtualNodeBindingValue: function(node) {
131.1863 - var regexMatch = isStartComment(node);
131.1864 - return regexMatch ? regexMatch[1] : null;
131.1865 - },
131.1866 -
131.1867 - normaliseVirtualElementDomStructure: function(elementVerified) {
131.1868 - // Workaround for https://github.com/SteveSanderson/knockout/issues/155
131.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
131.1870 - // that are direct descendants of <ul> into the preceding <li>)
131.1871 - if (!htmlTagsWithOptionallyClosingChildren[ko.utils.tagNameLower(elementVerified)])
131.1872 - return;
131.1873 -
131.1874 - // Scan immediate children to see if they contain unbalanced comment tags. If they do, those comment tags
131.1875 - // must be intended to appear *after* that child, so move them there.
131.1876 - var childNode = elementVerified.firstChild;
131.1877 - if (childNode) {
131.1878 - do {
131.1879 - if (childNode.nodeType === 1) {
131.1880 - var unbalancedTags = getUnbalancedChildTags(childNode);
131.1881 - if (unbalancedTags) {
131.1882 - // Fix up the DOM by moving the unbalanced tags to where they most likely were intended to be placed - *after* the child
131.1883 - var nodeToInsertBefore = childNode.nextSibling;
131.1884 - for (var i = 0; i < unbalancedTags.length; i++) {
131.1885 - if (nodeToInsertBefore)
131.1886 - elementVerified.insertBefore(unbalancedTags[i], nodeToInsertBefore);
131.1887 - else
131.1888 - elementVerified.appendChild(unbalancedTags[i]);
131.1889 - }
131.1890 - }
131.1891 - }
131.1892 - } while (childNode = childNode.nextSibling);
131.1893 - }
131.1894 - }
131.1895 - };
131.1896 -})();
131.1897 -ko.exportSymbol('virtualElements', ko.virtualElements);
131.1898 -ko.exportSymbol('virtualElements.allowedBindings', ko.virtualElements.allowedBindings);
131.1899 -ko.exportSymbol('virtualElements.emptyNode', ko.virtualElements.emptyNode);
131.1900 -//ko.exportSymbol('virtualElements.firstChild', ko.virtualElements.firstChild); // firstChild is not minified
131.1901 -ko.exportSymbol('virtualElements.insertAfter', ko.virtualElements.insertAfter);
131.1902 -//ko.exportSymbol('virtualElements.nextSibling', ko.virtualElements.nextSibling); // nextSibling is not minified
131.1903 -ko.exportSymbol('virtualElements.prepend', ko.virtualElements.prepend);
131.1904 -ko.exportSymbol('virtualElements.setDomNodeChildren', ko.virtualElements.setDomNodeChildren);
131.1905 -(function() {
131.1906 - var defaultBindingAttributeName = "data-bind";
131.1907 -
131.1908 - ko.bindingProvider = function() {
131.1909 - this.bindingCache = {};
131.1910 - };
131.1911 -
131.1912 - ko.utils.extend(ko.bindingProvider.prototype, {
131.1913 - 'nodeHasBindings': function(node) {
131.1914 - switch (node.nodeType) {
131.1915 - case 1: return node.getAttribute(defaultBindingAttributeName) != null; // Element
131.1916 - case 8: return ko.virtualElements.virtualNodeBindingValue(node) != null; // Comment node
131.1917 - default: return false;
131.1918 - }
131.1919 - },
131.1920 -
131.1921 - 'getBindings': function(node, bindingContext) {
131.1922 - var bindingsString = this['getBindingsString'](node, bindingContext);
131.1923 - return bindingsString ? this['parseBindingsString'](bindingsString, bindingContext, node) : null;
131.1924 - },
131.1925 -
131.1926 - // The following function is only used internally by this default provider.
131.1927 - // It's not part of the interface definition for a general binding provider.
131.1928 - 'getBindingsString': function(node, bindingContext) {
131.1929 - switch (node.nodeType) {
131.1930 - case 1: return node.getAttribute(defaultBindingAttributeName); // Element
131.1931 - case 8: return ko.virtualElements.virtualNodeBindingValue(node); // Comment node
131.1932 - default: return null;
131.1933 - }
131.1934 - },
131.1935 -
131.1936 - // The following function is only used internally by this default provider.
131.1937 - // It's not part of the interface definition for a general binding provider.
131.1938 - 'parseBindingsString': function(bindingsString, bindingContext, node) {
131.1939 - try {
131.1940 - var bindingFunction = createBindingsStringEvaluatorViaCache(bindingsString, this.bindingCache);
131.1941 - return bindingFunction(bindingContext, node);
131.1942 - } catch (ex) {
131.1943 - throw new Error("Unable to parse bindings.\nMessage: " + ex + ";\nBindings value: " + bindingsString);
131.1944 - }
131.1945 - }
131.1946 - });
131.1947 -
131.1948 - ko.bindingProvider['instance'] = new ko.bindingProvider();
131.1949 -
131.1950 - function createBindingsStringEvaluatorViaCache(bindingsString, cache) {
131.1951 - var cacheKey = bindingsString;
131.1952 - return cache[cacheKey]
131.1953 - || (cache[cacheKey] = createBindingsStringEvaluator(bindingsString));
131.1954 - }
131.1955 -
131.1956 - function createBindingsStringEvaluator(bindingsString) {
131.1957 - // Build the source for a function that evaluates "expression"
131.1958 - // For each scope variable, add an extra level of "with" nesting
131.1959 - // Example result: with(sc1) { with(sc0) { return (expression) } }
131.1960 - var rewrittenBindings = ko.expressionRewriting.preProcessBindings(bindingsString),
131.1961 - functionBody = "with($context){with($data||{}){return{" + rewrittenBindings + "}}}";
131.1962 - return new Function("$context", "$element", functionBody);
131.1963 - }
131.1964 -})();
131.1965 -
131.1966 -ko.exportSymbol('bindingProvider', ko.bindingProvider);
131.1967 -(function () {
131.1968 - ko.bindingHandlers = {};
131.1969 -
131.1970 - ko.bindingContext = function(dataItem, parentBindingContext, dataItemAlias) {
131.1971 - if (parentBindingContext) {
131.1972 - ko.utils.extend(this, parentBindingContext); // Inherit $root and any custom properties
131.1973 - this['$parentContext'] = parentBindingContext;
131.1974 - this['$parent'] = parentBindingContext['$data'];
131.1975 - this['$parents'] = (parentBindingContext['$parents'] || []).slice(0);
131.1976 - this['$parents'].unshift(this['$parent']);
131.1977 - } else {
131.1978 - this['$parents'] = [];
131.1979 - this['$root'] = dataItem;
131.1980 - // Export 'ko' in the binding context so it will be available in bindings and templates
131.1981 - // even if 'ko' isn't exported as a global, such as when using an AMD loader.
131.1982 - // See https://github.com/SteveSanderson/knockout/issues/490
131.1983 - this['ko'] = ko;
131.1984 - }
131.1985 - this['$data'] = dataItem;
131.1986 - if (dataItemAlias)
131.1987 - this[dataItemAlias] = dataItem;
131.1988 - }
131.1989 - ko.bindingContext.prototype['createChildContext'] = function (dataItem, dataItemAlias) {
131.1990 - return new ko.bindingContext(dataItem, this, dataItemAlias);
131.1991 - };
131.1992 - ko.bindingContext.prototype['extend'] = function(properties) {
131.1993 - var clone = ko.utils.extend(new ko.bindingContext(), this);
131.1994 - return ko.utils.extend(clone, properties);
131.1995 - };
131.1996 -
131.1997 - function validateThatBindingIsAllowedForVirtualElements(bindingName) {
131.1998 - var validator = ko.virtualElements.allowedBindings[bindingName];
131.1999 - if (!validator)
131.2000 - throw new Error("The binding '" + bindingName + "' cannot be used with virtual elements")
131.2001 - }
131.2002 -
131.2003 - function applyBindingsToDescendantsInternal (viewModel, elementOrVirtualElement, bindingContextsMayDifferFromDomParentElement) {
131.2004 - var currentChild, nextInQueue = ko.virtualElements.firstChild(elementOrVirtualElement);
131.2005 - while (currentChild = nextInQueue) {
131.2006 - // Keep a record of the next child *before* applying bindings, in case the binding removes the current child from its position
131.2007 - nextInQueue = ko.virtualElements.nextSibling(currentChild);
131.2008 - applyBindingsToNodeAndDescendantsInternal(viewModel, currentChild, bindingContextsMayDifferFromDomParentElement);
131.2009 - }
131.2010 - }
131.2011 -
131.2012 - function applyBindingsToNodeAndDescendantsInternal (viewModel, nodeVerified, bindingContextMayDifferFromDomParentElement) {
131.2013 - var shouldBindDescendants = true;
131.2014 -
131.2015 - // Perf optimisation: Apply bindings only if...
131.2016 - // (1) We need to store the binding context on this node (because it may differ from the DOM parent node's binding context)
131.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
131.2018 - // (2) It might have bindings (e.g., it has a data-bind attribute, or it's a marker for a containerless template)
131.2019 - var isElement = (nodeVerified.nodeType === 1);
131.2020 - if (isElement) // Workaround IE <= 8 HTML parsing weirdness
131.2021 - ko.virtualElements.normaliseVirtualElementDomStructure(nodeVerified);
131.2022 -
131.2023 - var shouldApplyBindings = (isElement && bindingContextMayDifferFromDomParentElement) // Case (1)
131.2024 - || ko.bindingProvider['instance']['nodeHasBindings'](nodeVerified); // Case (2)
131.2025 - if (shouldApplyBindings)
131.2026 - shouldBindDescendants = applyBindingsToNodeInternal(nodeVerified, null, viewModel, bindingContextMayDifferFromDomParentElement).shouldBindDescendants;
131.2027 -
131.2028 - if (shouldBindDescendants) {
131.2029 - // We're recursing automatically into (real or virtual) child nodes without changing binding contexts. So,
131.2030 - // * For children of a *real* element, the binding context is certainly the same as on their DOM .parentNode,
131.2031 - // hence bindingContextsMayDifferFromDomParentElement is false
131.2032 - // * For children of a *virtual* element, we can't be sure. Evaluating .parentNode on those children may
131.2033 - // skip over any number of intermediate virtual elements, any of which might define a custom binding context,
131.2034 - // hence bindingContextsMayDifferFromDomParentElement is true
131.2035 - applyBindingsToDescendantsInternal(viewModel, nodeVerified, /* bindingContextsMayDifferFromDomParentElement: */ !isElement);
131.2036 - }
131.2037 - }
131.2038 -
131.2039 - function applyBindingsToNodeInternal (node, bindings, viewModelOrBindingContext, bindingContextMayDifferFromDomParentElement) {
131.2040 - // Need to be sure that inits are only run once, and updates never run until all the inits have been run
131.2041 - var initPhase = 0; // 0 = before all inits, 1 = during inits, 2 = after all inits
131.2042 -
131.2043 - // Each time the dependentObservable is evaluated (after data changes),
131.2044 - // the binding attribute is reparsed so that it can pick out the correct
131.2045 - // model properties in the context of the changed data.
131.2046 - // DOM event callbacks need to be able to access this changed data,
131.2047 - // so we need a single parsedBindings variable (shared by all callbacks
131.2048 - // associated with this node's bindings) that all the closures can access.
131.2049 - var parsedBindings;
131.2050 - function makeValueAccessor(bindingKey) {
131.2051 - return function () { return parsedBindings[bindingKey] }
131.2052 - }
131.2053 - function parsedBindingsAccessor() {
131.2054 - return parsedBindings;
131.2055 - }
131.2056 -
131.2057 - var bindingHandlerThatControlsDescendantBindings;
131.2058 - ko.dependentObservable(
131.2059 - function () {
131.2060 - // Ensure we have a nonnull binding context to work with
131.2061 - var bindingContextInstance = viewModelOrBindingContext && (viewModelOrBindingContext instanceof ko.bindingContext)
131.2062 - ? viewModelOrBindingContext
131.2063 - : new ko.bindingContext(ko.utils.unwrapObservable(viewModelOrBindingContext));
131.2064 - var viewModel = bindingContextInstance['$data'];
131.2065 -
131.2066 - // Optimization: Don't store the binding context on this node if it's definitely the same as on node.parentNode, because
131.2067 - // we can easily recover it just by scanning up the node's ancestors in the DOM
131.2068 - // (note: here, parent node means "real DOM parent" not "virtual parent", as there's no O(1) way to find the virtual parent)
131.2069 - if (bindingContextMayDifferFromDomParentElement)
131.2070 - ko.storedBindingContextForNode(node, bindingContextInstance);
131.2071 -
131.2072 - // Use evaluatedBindings if given, otherwise fall back on asking the bindings provider to give us some bindings
131.2073 - var evaluatedBindings = (typeof bindings == "function") ? bindings(bindingContextInstance, node) : bindings;
131.2074 - parsedBindings = evaluatedBindings || ko.bindingProvider['instance']['getBindings'](node, bindingContextInstance);
131.2075 -
131.2076 - if (parsedBindings) {
131.2077 - // First run all the inits, so bindings can register for notification on changes
131.2078 - if (initPhase === 0) {
131.2079 - initPhase = 1;
131.2080 - for (var bindingKey in parsedBindings) {
131.2081 - var binding = ko.bindingHandlers[bindingKey];
131.2082 - if (binding && node.nodeType === 8)
131.2083 - validateThatBindingIsAllowedForVirtualElements(bindingKey);
131.2084 -
131.2085 - if (binding && typeof binding["init"] == "function") {
131.2086 - var handlerInitFn = binding["init"];
131.2087 - var initResult = handlerInitFn(node, makeValueAccessor(bindingKey), parsedBindingsAccessor, viewModel, bindingContextInstance);
131.2088 -
131.2089 - // If this binding handler claims to control descendant bindings, make a note of this
131.2090 - if (initResult && initResult['controlsDescendantBindings']) {
131.2091 - if (bindingHandlerThatControlsDescendantBindings !== undefined)
131.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.");
131.2093 - bindingHandlerThatControlsDescendantBindings = bindingKey;
131.2094 - }
131.2095 - }
131.2096 - }
131.2097 - initPhase = 2;
131.2098 - }
131.2099 -
131.2100 - // ... then run all the updates, which might trigger changes even on the first evaluation
131.2101 - if (initPhase === 2) {
131.2102 - for (var bindingKey in parsedBindings) {
131.2103 - var binding = ko.bindingHandlers[bindingKey];
131.2104 - if (binding && typeof binding["update"] == "function") {
131.2105 - var handlerUpdateFn = binding["update"];
131.2106 - handlerUpdateFn(node, makeValueAccessor(bindingKey), parsedBindingsAccessor, viewModel, bindingContextInstance);
131.2107 - }
131.2108 - }
131.2109 - }
131.2110 - }
131.2111 - },
131.2112 - null,
131.2113 - { disposeWhenNodeIsRemoved : node }
131.2114 - );
131.2115 -
131.2116 - return {
131.2117 - shouldBindDescendants: bindingHandlerThatControlsDescendantBindings === undefined
131.2118 - };
131.2119 - };
131.2120 -
131.2121 - var storedBindingContextDomDataKey = "__ko_bindingContext__";
131.2122 - ko.storedBindingContextForNode = function (node, bindingContext) {
131.2123 - if (arguments.length == 2)
131.2124 - ko.utils.domData.set(node, storedBindingContextDomDataKey, bindingContext);
131.2125 - else
131.2126 - return ko.utils.domData.get(node, storedBindingContextDomDataKey);
131.2127 - }
131.2128 -
131.2129 - ko.applyBindingsToNode = function (node, bindings, viewModel) {
131.2130 - if (node.nodeType === 1) // If it's an element, workaround IE <= 8 HTML parsing weirdness
131.2131 - ko.virtualElements.normaliseVirtualElementDomStructure(node);
131.2132 - return applyBindingsToNodeInternal(node, bindings, viewModel, true);
131.2133 - };
131.2134 -
131.2135 - ko.applyBindingsToDescendants = function(viewModel, rootNode) {
131.2136 - if (rootNode.nodeType === 1 || rootNode.nodeType === 8)
131.2137 - applyBindingsToDescendantsInternal(viewModel, rootNode, true);
131.2138 - };
131.2139 -
131.2140 - ko.applyBindings = function (viewModel, rootNode) {
131.2141 - if (rootNode && (rootNode.nodeType !== 1) && (rootNode.nodeType !== 8))
131.2142 - throw new Error("ko.applyBindings: first parameter should be your view model; second parameter should be a DOM node");
131.2143 - rootNode = rootNode || window.document.body; // Make "rootNode" parameter optional
131.2144 -
131.2145 - applyBindingsToNodeAndDescendantsInternal(viewModel, rootNode, true);
131.2146 - };
131.2147 -
131.2148 - // Retrieving binding context from arbitrary nodes
131.2149 - ko.contextFor = function(node) {
131.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)
131.2151 - switch (node.nodeType) {
131.2152 - case 1:
131.2153 - case 8:
131.2154 - var context = ko.storedBindingContextForNode(node);
131.2155 - if (context) return context;
131.2156 - if (node.parentNode) return ko.contextFor(node.parentNode);
131.2157 - break;
131.2158 - }
131.2159 - return undefined;
131.2160 - };
131.2161 - ko.dataFor = function(node) {
131.2162 - var context = ko.contextFor(node);
131.2163 - return context ? context['$data'] : undefined;
131.2164 - };
131.2165 -
131.2166 - ko.exportSymbol('bindingHandlers', ko.bindingHandlers);
131.2167 - ko.exportSymbol('applyBindings', ko.applyBindings);
131.2168 - ko.exportSymbol('applyBindingsToDescendants', ko.applyBindingsToDescendants);
131.2169 - ko.exportSymbol('applyBindingsToNode', ko.applyBindingsToNode);
131.2170 - ko.exportSymbol('contextFor', ko.contextFor);
131.2171 - ko.exportSymbol('dataFor', ko.dataFor);
131.2172 -})();
131.2173 -var attrHtmlToJavascriptMap = { 'class': 'className', 'for': 'htmlFor' };
131.2174 -ko.bindingHandlers['attr'] = {
131.2175 - 'update': function(element, valueAccessor, allBindingsAccessor) {
131.2176 - var value = ko.utils.unwrapObservable(valueAccessor()) || {};
131.2177 - for (var attrName in value) {
131.2178 - if (typeof attrName == "string") {
131.2179 - var attrValue = ko.utils.unwrapObservable(value[attrName]);
131.2180 -
131.2181 - // To cover cases like "attr: { checked:someProp }", we want to remove the attribute entirely
131.2182 - // when someProp is a "no value"-like value (strictly null, false, or undefined)
131.2183 - // (because the absence of the "checked" attr is how to mark an element as not checked, etc.)
131.2184 - var toRemove = (attrValue === false) || (attrValue === null) || (attrValue === undefined);
131.2185 - if (toRemove)
131.2186 - element.removeAttribute(attrName);
131.2187 -
131.2188 - // In IE <= 7 and IE8 Quirks Mode, you have to use the Javascript property name instead of the
131.2189 - // HTML attribute name for certain attributes. IE8 Standards Mode supports the correct behavior,
131.2190 - // but instead of figuring out the mode, we'll just set the attribute through the Javascript
131.2191 - // property for IE <= 8.
131.2192 - if (ko.utils.ieVersion <= 8 && attrName in attrHtmlToJavascriptMap) {
131.2193 - attrName = attrHtmlToJavascriptMap[attrName];
131.2194 - if (toRemove)
131.2195 - element.removeAttribute(attrName);
131.2196 - else
131.2197 - element[attrName] = attrValue;
131.2198 - } else if (!toRemove) {
131.2199 - try {
131.2200 - element.setAttribute(attrName, attrValue.toString());
131.2201 - } catch (err) {
131.2202 - // ignore for now
131.2203 - if (console) {
131.2204 - console.log("Can't set attribute " + attrName + " to " + attrValue + " error: " + err);
131.2205 - }
131.2206 - }
131.2207 - }
131.2208 -
131.2209 - // Treat "name" specially - although you can think of it as an attribute, it also needs
131.2210 - // special handling on older versions of IE (https://github.com/SteveSanderson/knockout/pull/333)
131.2211 - // Deliberately being case-sensitive here because XHTML would regard "Name" as a different thing
131.2212 - // entirely, and there's no strong reason to allow for such casing in HTML.
131.2213 - if (attrName === "name") {
131.2214 - ko.utils.setElementName(element, toRemove ? "" : attrValue.toString());
131.2215 - }
131.2216 - }
131.2217 - }
131.2218 - }
131.2219 -};
131.2220 -ko.bindingHandlers['checked'] = {
131.2221 - 'init': function (element, valueAccessor, allBindingsAccessor) {
131.2222 - var updateHandler = function() {
131.2223 - var valueToWrite;
131.2224 - if (element.type == "checkbox") {
131.2225 - valueToWrite = element.checked;
131.2226 - } else if ((element.type == "radio") && (element.checked)) {
131.2227 - valueToWrite = element.value;
131.2228 - } else {
131.2229 - return; // "checked" binding only responds to checkboxes and selected radio buttons
131.2230 - }
131.2231 -
131.2232 - var modelValue = valueAccessor(), unwrappedValue = ko.utils.unwrapObservable(modelValue);
131.2233 - if ((element.type == "checkbox") && (unwrappedValue instanceof Array)) {
131.2234 - // For checkboxes bound to an array, we add/remove the checkbox value to that array
131.2235 - // This works for both observable and non-observable arrays
131.2236 - var existingEntryIndex = ko.utils.arrayIndexOf(unwrappedValue, element.value);
131.2237 - if (element.checked && (existingEntryIndex < 0))
131.2238 - modelValue.push(element.value);
131.2239 - else if ((!element.checked) && (existingEntryIndex >= 0))
131.2240 - modelValue.splice(existingEntryIndex, 1);
131.2241 - } else {
131.2242 - ko.expressionRewriting.writeValueToProperty(modelValue, allBindingsAccessor, 'checked', valueToWrite, true);
131.2243 - }
131.2244 - };
131.2245 - ko.utils.registerEventHandler(element, "click", updateHandler);
131.2246 -
131.2247 - // IE 6 won't allow radio buttons to be selected unless they have a name
131.2248 - if ((element.type == "radio") && !element.name)
131.2249 - ko.bindingHandlers['uniqueName']['init'](element, function() { return true });
131.2250 - },
131.2251 - 'update': function (element, valueAccessor) {
131.2252 - var value = ko.utils.unwrapObservable(valueAccessor());
131.2253 -
131.2254 - if (element.type == "checkbox") {
131.2255 - if (value instanceof Array) {
131.2256 - // When bound to an array, the checkbox being checked represents its value being present in that array
131.2257 - element.checked = ko.utils.arrayIndexOf(value, element.value) >= 0;
131.2258 - } else {
131.2259 - // When bound to anything other value (not an array), the checkbox being checked represents the value being trueish
131.2260 - element.checked = value;
131.2261 - }
131.2262 - } else if (element.type == "radio") {
131.2263 - element.checked = (element.value == value);
131.2264 - }
131.2265 - }
131.2266 -};
131.2267 -var classesWrittenByBindingKey = '__ko__cssValue';
131.2268 -ko.bindingHandlers['css'] = {
131.2269 - 'update': function (element, valueAccessor) {
131.2270 - var value = ko.utils.unwrapObservable(valueAccessor());
131.2271 - if (typeof value == "object") {
131.2272 - for (var className in value) {
131.2273 - var shouldHaveClass = ko.utils.unwrapObservable(value[className]);
131.2274 - ko.utils.toggleDomNodeCssClass(element, className, shouldHaveClass);
131.2275 - }
131.2276 - } else {
131.2277 - value = String(value || ''); // Make sure we don't try to store or set a non-string value
131.2278 - ko.utils.toggleDomNodeCssClass(element, element[classesWrittenByBindingKey], false);
131.2279 - element[classesWrittenByBindingKey] = value;
131.2280 - ko.utils.toggleDomNodeCssClass(element, value, true);
131.2281 - }
131.2282 - }
131.2283 -};
131.2284 -ko.bindingHandlers['enable'] = {
131.2285 - 'update': function (element, valueAccessor) {
131.2286 - var value = ko.utils.unwrapObservable(valueAccessor());
131.2287 - if (value && element.disabled)
131.2288 - element.removeAttribute("disabled");
131.2289 - else if ((!value) && (!element.disabled))
131.2290 - element.disabled = true;
131.2291 - }
131.2292 -};
131.2293 -
131.2294 -ko.bindingHandlers['disable'] = {
131.2295 - 'update': function (element, valueAccessor) {
131.2296 - ko.bindingHandlers['enable']['update'](element, function() { return !ko.utils.unwrapObservable(valueAccessor()) });
131.2297 - }
131.2298 -};
131.2299 -// For certain common events (currently just 'click'), allow a simplified data-binding syntax
131.2300 -// e.g. click:handler instead of the usual full-length event:{click:handler}
131.2301 -function makeEventHandlerShortcut(eventName) {
131.2302 - ko.bindingHandlers[eventName] = {
131.2303 - 'init': function(element, valueAccessor, allBindingsAccessor, viewModel) {
131.2304 - var newValueAccessor = function () {
131.2305 - var result = {};
131.2306 - result[eventName] = valueAccessor();
131.2307 - return result;
131.2308 - };
131.2309 - return ko.bindingHandlers['event']['init'].call(this, element, newValueAccessor, allBindingsAccessor, viewModel);
131.2310 - }
131.2311 - }
131.2312 -}
131.2313 -
131.2314 -ko.bindingHandlers['event'] = {
131.2315 - 'init' : function (element, valueAccessor, allBindingsAccessor, viewModel) {
131.2316 - var eventsToHandle = valueAccessor() || {};
131.2317 - for(var eventNameOutsideClosure in eventsToHandle) {
131.2318 - (function() {
131.2319 - var eventName = eventNameOutsideClosure; // Separate variable to be captured by event handler closure
131.2320 - if (typeof eventName == "string") {
131.2321 - ko.utils.registerEventHandler(element, eventName, function (event) {
131.2322 - var handlerReturnValue;
131.2323 - var handlerFunction = valueAccessor()[eventName];
131.2324 - if (!handlerFunction)
131.2325 - return;
131.2326 - var allBindings = allBindingsAccessor();
131.2327 -
131.2328 - try {
131.2329 - // Take all the event args, and prefix with the viewmodel
131.2330 - var argsForHandler = ko.utils.makeArray(arguments);
131.2331 - argsForHandler.unshift(viewModel);
131.2332 - handlerReturnValue = handlerFunction.apply(viewModel, argsForHandler);
131.2333 - } finally {
131.2334 - if (handlerReturnValue !== true) { // Normally we want to prevent default action. Developer can override this be explicitly returning true.
131.2335 - if (event.preventDefault)
131.2336 - event.preventDefault();
131.2337 - else
131.2338 - event.returnValue = false;
131.2339 - }
131.2340 - }
131.2341 -
131.2342 - var bubble = allBindings[eventName + 'Bubble'] !== false;
131.2343 - if (!bubble) {
131.2344 - event.cancelBubble = true;
131.2345 - if (event.stopPropagation)
131.2346 - event.stopPropagation();
131.2347 - }
131.2348 - });
131.2349 - }
131.2350 - })();
131.2351 - }
131.2352 - }
131.2353 -};
131.2354 -// "foreach: someExpression" is equivalent to "template: { foreach: someExpression }"
131.2355 -// "foreach: { data: someExpression, afterAdd: myfn }" is equivalent to "template: { foreach: someExpression, afterAdd: myfn }"
131.2356 -ko.bindingHandlers['foreach'] = {
131.2357 - makeTemplateValueAccessor: function(valueAccessor) {
131.2358 - return function() {
131.2359 - var modelValue = valueAccessor(),
131.2360 - unwrappedValue = ko.utils.peekObservable(modelValue); // Unwrap without setting a dependency here
131.2361 -
131.2362 - // If unwrappedValue is the array, pass in the wrapped value on its own
131.2363 - // The value will be unwrapped and tracked within the template binding
131.2364 - // (See https://github.com/SteveSanderson/knockout/issues/523)
131.2365 - if ((!unwrappedValue) || typeof unwrappedValue.length == "number")
131.2366 - return { 'foreach': modelValue, 'templateEngine': ko.nativeTemplateEngine.instance };
131.2367 -
131.2368 - // If unwrappedValue.data is the array, preserve all relevant options and unwrap again value so we get updates
131.2369 - ko.utils.unwrapObservable(modelValue);
131.2370 - return {
131.2371 - 'foreach': unwrappedValue['data'],
131.2372 - 'as': unwrappedValue['as'],
131.2373 - 'includeDestroyed': unwrappedValue['includeDestroyed'],
131.2374 - 'afterAdd': unwrappedValue['afterAdd'],
131.2375 - 'beforeRemove': unwrappedValue['beforeRemove'],
131.2376 - 'afterRender': unwrappedValue['afterRender'],
131.2377 - 'beforeMove': unwrappedValue['beforeMove'],
131.2378 - 'afterMove': unwrappedValue['afterMove'],
131.2379 - 'templateEngine': ko.nativeTemplateEngine.instance
131.2380 - };
131.2381 - };
131.2382 - },
131.2383 - 'init': function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
131.2384 - return ko.bindingHandlers['template']['init'](element, ko.bindingHandlers['foreach'].makeTemplateValueAccessor(valueAccessor));
131.2385 - },
131.2386 - 'update': function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
131.2387 - return ko.bindingHandlers['template']['update'](element, ko.bindingHandlers['foreach'].makeTemplateValueAccessor(valueAccessor), allBindingsAccessor, viewModel, bindingContext);
131.2388 - }
131.2389 -};
131.2390 -ko.expressionRewriting.bindingRewriteValidators['foreach'] = false; // Can't rewrite control flow bindings
131.2391 -ko.virtualElements.allowedBindings['foreach'] = true;
131.2392 -var hasfocusUpdatingProperty = '__ko_hasfocusUpdating';
131.2393 -ko.bindingHandlers['hasfocus'] = {
131.2394 - 'init': function(element, valueAccessor, allBindingsAccessor) {
131.2395 - var handleElementFocusChange = function(isFocused) {
131.2396 - // Where possible, ignore which event was raised and determine focus state using activeElement,
131.2397 - // as this avoids phantom focus/blur events raised when changing tabs in modern browsers.
131.2398 - // However, not all KO-targeted browsers (Firefox 2) support activeElement. For those browsers,
131.2399 - // prevent a loss of focus when changing tabs/windows by setting a flag that prevents hasfocus
131.2400 - // from calling 'blur()' on the element when it loses focus.
131.2401 - // Discussion at https://github.com/SteveSanderson/knockout/pull/352
131.2402 - element[hasfocusUpdatingProperty] = true;
131.2403 - var ownerDoc = element.ownerDocument;
131.2404 - if ("activeElement" in ownerDoc) {
131.2405 - isFocused = (ownerDoc.activeElement === element);
131.2406 - }
131.2407 - var modelValue = valueAccessor();
131.2408 - ko.expressionRewriting.writeValueToProperty(modelValue, allBindingsAccessor, 'hasfocus', isFocused, true);
131.2409 - element[hasfocusUpdatingProperty] = false;
131.2410 - };
131.2411 - var handleElementFocusIn = handleElementFocusChange.bind(null, true);
131.2412 - var handleElementFocusOut = handleElementFocusChange.bind(null, false);
131.2413 -
131.2414 - ko.utils.registerEventHandler(element, "focus", handleElementFocusIn);
131.2415 - ko.utils.registerEventHandler(element, "focusin", handleElementFocusIn); // For IE
131.2416 - ko.utils.registerEventHandler(element, "blur", handleElementFocusOut);
131.2417 - ko.utils.registerEventHandler(element, "focusout", handleElementFocusOut); // For IE
131.2418 - },
131.2419 - 'update': function(element, valueAccessor) {
131.2420 - var value = ko.utils.unwrapObservable(valueAccessor());
131.2421 - if (!element[hasfocusUpdatingProperty]) {
131.2422 - value ? element.focus() : element.blur();
131.2423 - ko.dependencyDetection.ignore(ko.utils.triggerEvent, null, [element, value ? "focusin" : "focusout"]); // For IE, which doesn't reliably fire "focus" or "blur" events synchronously
131.2424 - }
131.2425 - }
131.2426 -};
131.2427 -ko.bindingHandlers['html'] = {
131.2428 - 'init': function() {
131.2429 - // Prevent binding on the dynamically-injected HTML (as developers are unlikely to expect that, and it has security implications)
131.2430 - return { 'controlsDescendantBindings': true };
131.2431 - },
131.2432 - 'update': function (element, valueAccessor) {
131.2433 - // setHtml will unwrap the value if needed
131.2434 - ko.utils.setHtml(element, valueAccessor());
131.2435 - }
131.2436 -};
131.2437 -var withIfDomDataKey = '__ko_withIfBindingData';
131.2438 -// Makes a binding like with or if
131.2439 -function makeWithIfBinding(bindingKey, isWith, isNot, makeContextCallback) {
131.2440 - ko.bindingHandlers[bindingKey] = {
131.2441 - 'init': function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
131.2442 - ko.utils.domData.set(element, withIfDomDataKey, {});
131.2443 - return { 'controlsDescendantBindings': true };
131.2444 - },
131.2445 - 'update': function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
131.2446 - var withIfData = ko.utils.domData.get(element, withIfDomDataKey),
131.2447 - dataValue = ko.utils.unwrapObservable(valueAccessor()),
131.2448 - shouldDisplay = !isNot !== !dataValue, // equivalent to isNot ? !dataValue : !!dataValue
131.2449 - isFirstRender = !withIfData.savedNodes,
131.2450 - needsRefresh = isFirstRender || isWith || (shouldDisplay !== withIfData.didDisplayOnLastUpdate);
131.2451 -
131.2452 - if (needsRefresh) {
131.2453 - if (isFirstRender) {
131.2454 - withIfData.savedNodes = ko.utils.cloneNodes(ko.virtualElements.childNodes(element), true /* shouldCleanNodes */);
131.2455 - }
131.2456 -
131.2457 - if (shouldDisplay) {
131.2458 - if (!isFirstRender) {
131.2459 - ko.virtualElements.setDomNodeChildren(element, ko.utils.cloneNodes(withIfData.savedNodes));
131.2460 - }
131.2461 - ko.applyBindingsToDescendants(makeContextCallback ? makeContextCallback(bindingContext, dataValue) : bindingContext, element);
131.2462 - } else {
131.2463 - ko.virtualElements.emptyNode(element);
131.2464 - }
131.2465 -
131.2466 - withIfData.didDisplayOnLastUpdate = shouldDisplay;
131.2467 - }
131.2468 - }
131.2469 - };
131.2470 - ko.expressionRewriting.bindingRewriteValidators[bindingKey] = false; // Can't rewrite control flow bindings
131.2471 - ko.virtualElements.allowedBindings[bindingKey] = true;
131.2472 -}
131.2473 -
131.2474 -// Construct the actual binding handlers
131.2475 -makeWithIfBinding('if');
131.2476 -makeWithIfBinding('ifnot', false /* isWith */, true /* isNot */);
131.2477 -makeWithIfBinding('with', true /* isWith */, false /* isNot */,
131.2478 - function(bindingContext, dataValue) {
131.2479 - return bindingContext['createChildContext'](dataValue);
131.2480 - }
131.2481 -);
131.2482 -function ensureDropdownSelectionIsConsistentWithModelValue(element, modelValue, preferModelValue) {
131.2483 - if (preferModelValue) {
131.2484 - if (modelValue !== ko.selectExtensions.readValue(element))
131.2485 - ko.selectExtensions.writeValue(element, modelValue);
131.2486 - }
131.2487 -
131.2488 - // No matter which direction we're syncing in, we want the end result to be equality between dropdown value and model value.
131.2489 - // If they aren't equal, either we prefer the dropdown value, or the model value couldn't be represented, so either way,
131.2490 - // change the model value to match the dropdown.
131.2491 - if (modelValue !== ko.selectExtensions.readValue(element))
131.2492 - ko.dependencyDetection.ignore(ko.utils.triggerEvent, null, [element, "change"]);
131.2493 -};
131.2494 -
131.2495 -ko.bindingHandlers['options'] = {
131.2496 - 'update': function (element, valueAccessor, allBindingsAccessor) {
131.2497 - if (ko.utils.tagNameLower(element) !== "select")
131.2498 - throw new Error("options binding applies only to SELECT elements");
131.2499 -
131.2500 - var selectWasPreviouslyEmpty = element.length == 0;
131.2501 - var previousSelectedValues = ko.utils.arrayMap(ko.utils.arrayFilter(element.childNodes, function (node) {
131.2502 - return node.tagName && (ko.utils.tagNameLower(node) === "option") && node.selected;
131.2503 - }), function (node) {
131.2504 - return ko.selectExtensions.readValue(node) || node.innerText || node.textContent;
131.2505 - });
131.2506 - var previousScrollTop = element.scrollTop;
131.2507 -
131.2508 - var value = ko.utils.unwrapObservable(valueAccessor());
131.2509 - var selectedValue = element.value;
131.2510 -
131.2511 - // Remove all existing <option>s.
131.2512 - // Need to use .remove() rather than .removeChild() for <option>s otherwise IE behaves oddly (https://github.com/SteveSanderson/knockout/issues/134)
131.2513 - while (element.length > 0) {
131.2514 - ko.cleanNode(element.options[0]);
131.2515 - element.remove(0);
131.2516 - }
131.2517 -
131.2518 - if (value) {
131.2519 - var allBindings = allBindingsAccessor(),
131.2520 - includeDestroyed = allBindings['optionsIncludeDestroyed'];
131.2521 -
131.2522 - if (typeof value.length != "number")
131.2523 - value = [value];
131.2524 - if (allBindings['optionsCaption']) {
131.2525 - var option = document.createElement("option");
131.2526 - ko.utils.setHtml(option, allBindings['optionsCaption']);
131.2527 - ko.selectExtensions.writeValue(option, undefined);
131.2528 - element.appendChild(option);
131.2529 - }
131.2530 -
131.2531 - for (var i = 0, j = value.length; i < j; i++) {
131.2532 - // Skip destroyed items
131.2533 - var arrayEntry = value[i];
131.2534 - if (arrayEntry && arrayEntry['_destroy'] && !includeDestroyed)
131.2535 - continue;
131.2536 -
131.2537 - var option = document.createElement("option");
131.2538 -
131.2539 - function applyToObject(object, predicate, defaultValue) {
131.2540 - var predicateType = typeof predicate;
131.2541 - if (predicateType == "function") // Given a function; run it against the data value
131.2542 - return predicate(object);
131.2543 - else if (predicateType == "string") // Given a string; treat it as a property name on the data value
131.2544 - return object[predicate];
131.2545 - else // Given no optionsText arg; use the data value itself
131.2546 - return defaultValue;
131.2547 - }
131.2548 -
131.2549 - // Apply a value to the option element
131.2550 - var optionValue = applyToObject(arrayEntry, allBindings['optionsValue'], arrayEntry);
131.2551 - ko.selectExtensions.writeValue(option, ko.utils.unwrapObservable(optionValue));
131.2552 -
131.2553 - // Apply some text to the option element
131.2554 - var optionText = applyToObject(arrayEntry, allBindings['optionsText'], optionValue);
131.2555 - ko.utils.setTextContent(option, optionText);
131.2556 -
131.2557 - element.appendChild(option);
131.2558 - }
131.2559 -
131.2560 - // IE6 doesn't like us to assign selection to OPTION nodes before they're added to the document.
131.2561 - // That's why we first added them without selection. Now it's time to set the selection.
131.2562 - var newOptions = element.getElementsByTagName("option");
131.2563 - var countSelectionsRetained = 0;
131.2564 - for (var i = 0, j = newOptions.length; i < j; i++) {
131.2565 - if (ko.utils.arrayIndexOf(previousSelectedValues, ko.selectExtensions.readValue(newOptions[i])) >= 0) {
131.2566 - ko.utils.setOptionNodeSelectionState(newOptions[i], true);
131.2567 - countSelectionsRetained++;
131.2568 - }
131.2569 - }
131.2570 -
131.2571 - element.scrollTop = previousScrollTop;
131.2572 -
131.2573 - if (selectWasPreviouslyEmpty && ('value' in allBindings)) {
131.2574 - // Ensure consistency between model value and selected option.
131.2575 - // If the dropdown is being populated for the first time here (or was otherwise previously empty),
131.2576 - // the dropdown selection state is meaningless, so we preserve the model value.
131.2577 - ensureDropdownSelectionIsConsistentWithModelValue(element, ko.utils.peekObservable(allBindings['value']), /* preferModelValue */ true);
131.2578 - }
131.2579 -
131.2580 - // Workaround for IE9 bug
131.2581 - ko.utils.ensureSelectElementIsRenderedCorrectly(element);
131.2582 - }
131.2583 - }
131.2584 -};
131.2585 -ko.bindingHandlers['options'].optionValueDomDataKey = '__ko.optionValueDomData__';
131.2586 -ko.bindingHandlers['selectedOptions'] = {
131.2587 - 'init': function (element, valueAccessor, allBindingsAccessor) {
131.2588 - ko.utils.registerEventHandler(element, "change", function () {
131.2589 - var value = valueAccessor(), valueToWrite = [];
131.2590 - ko.utils.arrayForEach(element.getElementsByTagName("option"), function(node) {
131.2591 - if (node.selected)
131.2592 - valueToWrite.push(ko.selectExtensions.readValue(node));
131.2593 - });
131.2594 - ko.expressionRewriting.writeValueToProperty(value, allBindingsAccessor, 'value', valueToWrite);
131.2595 - });
131.2596 - },
131.2597 - 'update': function (element, valueAccessor) {
131.2598 - if (ko.utils.tagNameLower(element) != "select")
131.2599 - throw new Error("values binding applies only to SELECT elements");
131.2600 -
131.2601 - var newValue = ko.utils.unwrapObservable(valueAccessor());
131.2602 - if (newValue && typeof newValue.length == "number") {
131.2603 - ko.utils.arrayForEach(element.getElementsByTagName("option"), function(node) {
131.2604 - var isSelected = ko.utils.arrayIndexOf(newValue, ko.selectExtensions.readValue(node)) >= 0;
131.2605 - ko.utils.setOptionNodeSelectionState(node, isSelected);
131.2606 - });
131.2607 - }
131.2608 - }
131.2609 -};
131.2610 -ko.bindingHandlers['style'] = {
131.2611 - 'update': function (element, valueAccessor) {
131.2612 - var value = ko.utils.unwrapObservable(valueAccessor() || {});
131.2613 - for (var styleName in value) {
131.2614 - if (typeof styleName == "string") {
131.2615 - var styleValue = ko.utils.unwrapObservable(value[styleName]);
131.2616 - element.style[styleName] = styleValue || ""; // Empty string removes the value, whereas null/undefined have no effect
131.2617 - }
131.2618 - }
131.2619 - }
131.2620 -};
131.2621 -ko.bindingHandlers['submit'] = {
131.2622 - 'init': function (element, valueAccessor, allBindingsAccessor, viewModel) {
131.2623 - if (typeof valueAccessor() != "function")
131.2624 - throw new Error("The value for a submit binding must be a function");
131.2625 - ko.utils.registerEventHandler(element, "submit", function (event) {
131.2626 - var handlerReturnValue;
131.2627 - var value = valueAccessor();
131.2628 - try { handlerReturnValue = value.call(viewModel, element); }
131.2629 - finally {
131.2630 - if (handlerReturnValue !== true) { // Normally we want to prevent default action. Developer can override this be explicitly returning true.
131.2631 - if (event.preventDefault)
131.2632 - event.preventDefault();
131.2633 - else
131.2634 - event.returnValue = false;
131.2635 - }
131.2636 - }
131.2637 - });
131.2638 - }
131.2639 -};
131.2640 -ko.bindingHandlers['text'] = {
131.2641 - 'update': function (element, valueAccessor) {
131.2642 - ko.utils.setTextContent(element, valueAccessor());
131.2643 - }
131.2644 -};
131.2645 -ko.virtualElements.allowedBindings['text'] = true;
131.2646 -ko.bindingHandlers['uniqueName'] = {
131.2647 - 'init': function (element, valueAccessor) {
131.2648 - if (valueAccessor()) {
131.2649 - var name = "ko_unique_" + (++ko.bindingHandlers['uniqueName'].currentIndex);
131.2650 - ko.utils.setElementName(element, name);
131.2651 - }
131.2652 - }
131.2653 -};
131.2654 -ko.bindingHandlers['uniqueName'].currentIndex = 0;
131.2655 -ko.bindingHandlers['value'] = {
131.2656 - 'init': function (element, valueAccessor, allBindingsAccessor) {
131.2657 - // Always catch "change" event; possibly other events too if asked
131.2658 - var eventsToCatch = ["change"];
131.2659 - var requestedEventsToCatch = allBindingsAccessor()["valueUpdate"];
131.2660 - var propertyChangedFired = false;
131.2661 - if (requestedEventsToCatch) {
131.2662 - if (typeof requestedEventsToCatch == "string") // Allow both individual event names, and arrays of event names
131.2663 - requestedEventsToCatch = [requestedEventsToCatch];
131.2664 - ko.utils.arrayPushAll(eventsToCatch, requestedEventsToCatch);
131.2665 - eventsToCatch = ko.utils.arrayGetDistinctValues(eventsToCatch);
131.2666 - }
131.2667 -
131.2668 - var valueUpdateHandler = function() {
131.2669 - propertyChangedFired = false;
131.2670 - var modelValue = valueAccessor();
131.2671 - var elementValue = ko.selectExtensions.readValue(element);
131.2672 - ko.expressionRewriting.writeValueToProperty(modelValue, allBindingsAccessor, 'value', elementValue);
131.2673 - }
131.2674 -
131.2675 - // Workaround for https://github.com/SteveSanderson/knockout/issues/122
131.2676 - // IE doesn't fire "change" events on textboxes if the user selects a value from its autocomplete list
131.2677 - var ieAutoCompleteHackNeeded = ko.utils.ieVersion && element.tagName.toLowerCase() == "input" && element.type == "text"
131.2678 - && element.autocomplete != "off" && (!element.form || element.form.autocomplete != "off");
131.2679 - if (ieAutoCompleteHackNeeded && ko.utils.arrayIndexOf(eventsToCatch, "propertychange") == -1) {
131.2680 - ko.utils.registerEventHandler(element, "propertychange", function () { propertyChangedFired = true });
131.2681 - ko.utils.registerEventHandler(element, "blur", function() {
131.2682 - if (propertyChangedFired) {
131.2683 - valueUpdateHandler();
131.2684 - }
131.2685 - });
131.2686 - }
131.2687 -
131.2688 - ko.utils.arrayForEach(eventsToCatch, function(eventName) {
131.2689 - // The syntax "after<eventname>" means "run the handler asynchronously after the event"
131.2690 - // This is useful, for example, to catch "keydown" events after the browser has updated the control
131.2691 - // (otherwise, ko.selectExtensions.readValue(this) will receive the control's value *before* the key event)
131.2692 - var handler = valueUpdateHandler;
131.2693 - if (ko.utils.stringStartsWith(eventName, "after")) {
131.2694 - handler = function() { setTimeout(valueUpdateHandler, 0) };
131.2695 - eventName = eventName.substring("after".length);
131.2696 - }
131.2697 - ko.utils.registerEventHandler(element, eventName, handler);
131.2698 - });
131.2699 - },
131.2700 - 'update': function (element, valueAccessor) {
131.2701 - var valueIsSelectOption = ko.utils.tagNameLower(element) === "select";
131.2702 - var newValue = ko.utils.unwrapObservable(valueAccessor());
131.2703 - var elementValue = ko.selectExtensions.readValue(element);
131.2704 - var valueHasChanged = (newValue != elementValue);
131.2705 -
131.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).
131.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.
131.2708 - if ((newValue === 0) && (elementValue !== 0) && (elementValue !== "0"))
131.2709 - valueHasChanged = true;
131.2710 -
131.2711 - if (valueHasChanged) {
131.2712 - var applyValueAction = function () { ko.selectExtensions.writeValue(element, newValue); };
131.2713 - applyValueAction();
131.2714 -
131.2715 - // Workaround for IE6 bug: It won't reliably apply values to SELECT nodes during the same execution thread
131.2716 - // right after you've changed the set of OPTION nodes on it. So for that node type, we'll schedule a second thread
131.2717 - // to apply the value as well.
131.2718 - var alsoApplyAsynchronously = valueIsSelectOption;
131.2719 - if (alsoApplyAsynchronously)
131.2720 - setTimeout(applyValueAction, 0);
131.2721 - }
131.2722 -
131.2723 - // If you try to set a model value that can't be represented in an already-populated dropdown, reject that change,
131.2724 - // because you're not allowed to have a model value that disagrees with a visible UI selection.
131.2725 - if (valueIsSelectOption && (element.length > 0))
131.2726 - ensureDropdownSelectionIsConsistentWithModelValue(element, newValue, /* preferModelValue */ false);
131.2727 - }
131.2728 -};
131.2729 -ko.bindingHandlers['visible'] = {
131.2730 - 'update': function (element, valueAccessor) {
131.2731 - var value = ko.utils.unwrapObservable(valueAccessor());
131.2732 - var isCurrentlyVisible = !(element.style.display == "none");
131.2733 - if (value && !isCurrentlyVisible)
131.2734 - element.style.display = "";
131.2735 - else if ((!value) && isCurrentlyVisible)
131.2736 - element.style.display = "none";
131.2737 - }
131.2738 -};
131.2739 -// 'click' is just a shorthand for the usual full-length event:{click:handler}
131.2740 -makeEventHandlerShortcut('click');
131.2741 -// If you want to make a custom template engine,
131.2742 -//
131.2743 -// [1] Inherit from this class (like ko.nativeTemplateEngine does)
131.2744 -// [2] Override 'renderTemplateSource', supplying a function with this signature:
131.2745 -//
131.2746 -// function (templateSource, bindingContext, options) {
131.2747 -// // - templateSource.text() is the text of the template you should render
131.2748 -// // - bindingContext.$data is the data you should pass into the template
131.2749 -// // - you might also want to make bindingContext.$parent, bindingContext.$parents,
131.2750 -// // and bindingContext.$root available in the template too
131.2751 -// // - options gives you access to any other properties set on "data-bind: { template: options }"
131.2752 -// //
131.2753 -// // Return value: an array of DOM nodes
131.2754 -// }
131.2755 -//
131.2756 -// [3] Override 'createJavaScriptEvaluatorBlock', supplying a function with this signature:
131.2757 -//
131.2758 -// function (script) {
131.2759 -// // Return value: Whatever syntax means "Evaluate the JavaScript statement 'script' and output the result"
131.2760 -// // For example, the jquery.tmpl template engine converts 'someScript' to '${ someScript }'
131.2761 -// }
131.2762 -//
131.2763 -// This is only necessary if you want to allow data-bind attributes to reference arbitrary template variables.
131.2764 -// If you don't want to allow that, you can set the property 'allowTemplateRewriting' to false (like ko.nativeTemplateEngine does)
131.2765 -// and then you don't need to override 'createJavaScriptEvaluatorBlock'.
131.2766 -
131.2767 -ko.templateEngine = function () { };
131.2768 -
131.2769 -ko.templateEngine.prototype['renderTemplateSource'] = function (templateSource, bindingContext, options) {
131.2770 - throw new Error("Override renderTemplateSource");
131.2771 -};
131.2772 -
131.2773 -ko.templateEngine.prototype['createJavaScriptEvaluatorBlock'] = function (script) {
131.2774 - throw new Error("Override createJavaScriptEvaluatorBlock");
131.2775 -};
131.2776 -
131.2777 -ko.templateEngine.prototype['makeTemplateSource'] = function(template, templateDocument) {
131.2778 - // Named template
131.2779 - if (typeof template == "string") {
131.2780 - templateDocument = templateDocument || document;
131.2781 - var elem = templateDocument.getElementById(template);
131.2782 - if (!elem)
131.2783 - throw new Error("Cannot find template with ID " + template);
131.2784 - return new ko.templateSources.domElement(elem);
131.2785 - } else if ((template.nodeType == 1) || (template.nodeType == 8)) {
131.2786 - // Anonymous template
131.2787 - return new ko.templateSources.anonymousTemplate(template);
131.2788 - } else
131.2789 - throw new Error("Unknown template type: " + template);
131.2790 -};
131.2791 -
131.2792 -ko.templateEngine.prototype['renderTemplate'] = function (template, bindingContext, options, templateDocument) {
131.2793 - var templateSource = this['makeTemplateSource'](template, templateDocument);
131.2794 - return this['renderTemplateSource'](templateSource, bindingContext, options);
131.2795 -};
131.2796 -
131.2797 -ko.templateEngine.prototype['isTemplateRewritten'] = function (template, templateDocument) {
131.2798 - // Skip rewriting if requested
131.2799 - if (this['allowTemplateRewriting'] === false)
131.2800 - return true;
131.2801 - return this['makeTemplateSource'](template, templateDocument)['data']("isRewritten");
131.2802 -};
131.2803 -
131.2804 -ko.templateEngine.prototype['rewriteTemplate'] = function (template, rewriterCallback, templateDocument) {
131.2805 - var templateSource = this['makeTemplateSource'](template, templateDocument);
131.2806 - var rewritten = rewriterCallback(templateSource['text']());
131.2807 - templateSource['text'](rewritten);
131.2808 - templateSource['data']("isRewritten", true);
131.2809 -};
131.2810 -
131.2811 -ko.exportSymbol('templateEngine', ko.templateEngine);
131.2812 -
131.2813 -ko.templateRewriting = (function () {
131.2814 - var memoizeDataBindingAttributeSyntaxRegex = /(<[a-z]+\d*(\s+(?!data-bind=)[a-z0-9\-]+(=(\"[^\"]*\"|\'[^\']*\'))?)*\s+)data-bind=(["'])([\s\S]*?)\5/gi;
131.2815 - var memoizeVirtualContainerBindingSyntaxRegex = /<!--\s*ko\b\s*([\s\S]*?)\s*-->/g;
131.2816 -
131.2817 - function validateDataBindValuesForRewriting(keyValueArray) {
131.2818 - var allValidators = ko.expressionRewriting.bindingRewriteValidators;
131.2819 - for (var i = 0; i < keyValueArray.length; i++) {
131.2820 - var key = keyValueArray[i]['key'];
131.2821 - if (allValidators.hasOwnProperty(key)) {
131.2822 - var validator = allValidators[key];
131.2823 -
131.2824 - if (typeof validator === "function") {
131.2825 - var possibleErrorMessage = validator(keyValueArray[i]['value']);
131.2826 - if (possibleErrorMessage)
131.2827 - throw new Error(possibleErrorMessage);
131.2828 - } else if (!validator) {
131.2829 - throw new Error("This template engine does not support the '" + key + "' binding within its templates");
131.2830 - }
131.2831 - }
131.2832 - }
131.2833 - }
131.2834 -
131.2835 - function constructMemoizedTagReplacement(dataBindAttributeValue, tagToRetain, templateEngine) {
131.2836 - var dataBindKeyValueArray = ko.expressionRewriting.parseObjectLiteral(dataBindAttributeValue);
131.2837 - validateDataBindValuesForRewriting(dataBindKeyValueArray);
131.2838 - var rewrittenDataBindAttributeValue = ko.expressionRewriting.preProcessBindings(dataBindKeyValueArray);
131.2839 -
131.2840 - // For no obvious reason, Opera fails to evaluate rewrittenDataBindAttributeValue unless it's wrapped in an additional
131.2841 - // anonymous function, even though Opera's built-in debugger can evaluate it anyway. No other browser requires this
131.2842 - // extra indirection.
131.2843 - var applyBindingsToNextSiblingScript =
131.2844 - "ko.__tr_ambtns(function($context,$element){return(function(){return{ " + rewrittenDataBindAttributeValue + " } })()})";
131.2845 - return templateEngine['createJavaScriptEvaluatorBlock'](applyBindingsToNextSiblingScript) + tagToRetain;
131.2846 - }
131.2847 -
131.2848 - return {
131.2849 - ensureTemplateIsRewritten: function (template, templateEngine, templateDocument) {
131.2850 - if (!templateEngine['isTemplateRewritten'](template, templateDocument))
131.2851 - templateEngine['rewriteTemplate'](template, function (htmlString) {
131.2852 - return ko.templateRewriting.memoizeBindingAttributeSyntax(htmlString, templateEngine);
131.2853 - }, templateDocument);
131.2854 - },
131.2855 -
131.2856 - memoizeBindingAttributeSyntax: function (htmlString, templateEngine) {
131.2857 - return htmlString.replace(memoizeDataBindingAttributeSyntaxRegex, function () {
131.2858 - return constructMemoizedTagReplacement(/* dataBindAttributeValue: */ arguments[6], /* tagToRetain: */ arguments[1], templateEngine);
131.2859 - }).replace(memoizeVirtualContainerBindingSyntaxRegex, function() {
131.2860 - return constructMemoizedTagReplacement(/* dataBindAttributeValue: */ arguments[1], /* tagToRetain: */ "<!-- ko -->", templateEngine);
131.2861 - });
131.2862 - },
131.2863 -
131.2864 - applyMemoizedBindingsToNextSibling: function (bindings) {
131.2865 - return ko.memoization.memoize(function (domNode, bindingContext) {
131.2866 - if (domNode.nextSibling)
131.2867 - ko.applyBindingsToNode(domNode.nextSibling, bindings, bindingContext);
131.2868 - });
131.2869 - }
131.2870 - }
131.2871 -})();
131.2872 -
131.2873 -
131.2874 -// Exported only because it has to be referenced by string lookup from within rewritten template
131.2875 -ko.exportSymbol('__tr_ambtns', ko.templateRewriting.applyMemoizedBindingsToNextSibling);
131.2876 -(function() {
131.2877 - // A template source represents a read/write way of accessing a template. This is to eliminate the need for template loading/saving
131.2878 - // logic to be duplicated in every template engine (and means they can all work with anonymous templates, etc.)
131.2879 - //
131.2880 - // Two are provided by default:
131.2881 - // 1. ko.templateSources.domElement - reads/writes the text content of an arbitrary DOM element
131.2882 - // 2. ko.templateSources.anonymousElement - uses ko.utils.domData to read/write text *associated* with the DOM element, but
131.2883 - // without reading/writing the actual element text content, since it will be overwritten
131.2884 - // with the rendered template output.
131.2885 - // You can implement your own template source if you want to fetch/store templates somewhere other than in DOM elements.
131.2886 - // Template sources need to have the following functions:
131.2887 - // text() - returns the template text from your storage location
131.2888 - // text(value) - writes the supplied template text to your storage location
131.2889 - // data(key) - reads values stored using data(key, value) - see below
131.2890 - // data(key, value) - associates "value" with this template and the key "key". Is used to store information like "isRewritten".
131.2891 - //
131.2892 - // Optionally, template sources can also have the following functions:
131.2893 - // nodes() - returns a DOM element containing the nodes of this template, where available
131.2894 - // nodes(value) - writes the given DOM element to your storage location
131.2895 - // If a DOM element is available for a given template source, template engines are encouraged to use it in preference over text()
131.2896 - // for improved speed. However, all templateSources must supply text() even if they don't supply nodes().
131.2897 - //
131.2898 - // Once you've implemented a templateSource, make your template engine use it by subclassing whatever template engine you were
131.2899 - // using and overriding "makeTemplateSource" to return an instance of your custom template source.
131.2900 -
131.2901 - ko.templateSources = {};
131.2902 -
131.2903 - // ---- ko.templateSources.domElement -----
131.2904 -
131.2905 - ko.templateSources.domElement = function(element) {
131.2906 - this.domElement = element;
131.2907 - }
131.2908 -
131.2909 - ko.templateSources.domElement.prototype['text'] = function(/* valueToWrite */) {
131.2910 - var tagNameLower = ko.utils.tagNameLower(this.domElement),
131.2911 - elemContentsProperty = tagNameLower === "script" ? "text"
131.2912 - : tagNameLower === "textarea" ? "value"
131.2913 - : "innerHTML";
131.2914 -
131.2915 - if (arguments.length == 0) {
131.2916 - return this.domElement[elemContentsProperty];
131.2917 - } else {
131.2918 - var valueToWrite = arguments[0];
131.2919 - if (elemContentsProperty === "innerHTML")
131.2920 - ko.utils.setHtml(this.domElement, valueToWrite);
131.2921 - else
131.2922 - this.domElement[elemContentsProperty] = valueToWrite;
131.2923 - }
131.2924 - };
131.2925 -
131.2926 - ko.templateSources.domElement.prototype['data'] = function(key /*, valueToWrite */) {
131.2927 - if (arguments.length === 1) {
131.2928 - return ko.utils.domData.get(this.domElement, "templateSourceData_" + key);
131.2929 - } else {
131.2930 - ko.utils.domData.set(this.domElement, "templateSourceData_" + key, arguments[1]);
131.2931 - }
131.2932 - };
131.2933 -
131.2934 - // ---- ko.templateSources.anonymousTemplate -----
131.2935 - // Anonymous templates are normally saved/retrieved as DOM nodes through "nodes".
131.2936 - // For compatibility, you can also read "text"; it will be serialized from the nodes on demand.
131.2937 - // Writing to "text" is still supported, but then the template data will not be available as DOM nodes.
131.2938 -
131.2939 - var anonymousTemplatesDomDataKey = "__ko_anon_template__";
131.2940 - ko.templateSources.anonymousTemplate = function(element) {
131.2941 - this.domElement = element;
131.2942 - }
131.2943 - ko.templateSources.anonymousTemplate.prototype = new ko.templateSources.domElement();
131.2944 - ko.templateSources.anonymousTemplate.prototype['text'] = function(/* valueToWrite */) {
131.2945 - if (arguments.length == 0) {
131.2946 - var templateData = ko.utils.domData.get(this.domElement, anonymousTemplatesDomDataKey) || {};
131.2947 - if (templateData.textData === undefined && templateData.containerData)
131.2948 - templateData.textData = templateData.containerData.innerHTML;
131.2949 - return templateData.textData;
131.2950 - } else {
131.2951 - var valueToWrite = arguments[0];
131.2952 - ko.utils.domData.set(this.domElement, anonymousTemplatesDomDataKey, {textData: valueToWrite});
131.2953 - }
131.2954 - };
131.2955 - ko.templateSources.domElement.prototype['nodes'] = function(/* valueToWrite */) {
131.2956 - if (arguments.length == 0) {
131.2957 - var templateData = ko.utils.domData.get(this.domElement, anonymousTemplatesDomDataKey) || {};
131.2958 - return templateData.containerData;
131.2959 - } else {
131.2960 - var valueToWrite = arguments[0];
131.2961 - ko.utils.domData.set(this.domElement, anonymousTemplatesDomDataKey, {containerData: valueToWrite});
131.2962 - }
131.2963 - };
131.2964 -
131.2965 - ko.exportSymbol('templateSources', ko.templateSources);
131.2966 - ko.exportSymbol('templateSources.domElement', ko.templateSources.domElement);
131.2967 - ko.exportSymbol('templateSources.anonymousTemplate', ko.templateSources.anonymousTemplate);
131.2968 -})();
131.2969 -(function () {
131.2970 - var _templateEngine;
131.2971 - ko.setTemplateEngine = function (templateEngine) {
131.2972 - if ((templateEngine != undefined) && !(templateEngine instanceof ko.templateEngine))
131.2973 - throw new Error("templateEngine must inherit from ko.templateEngine");
131.2974 - _templateEngine = templateEngine;
131.2975 - }
131.2976 -
131.2977 - function invokeForEachNodeOrCommentInContinuousRange(firstNode, lastNode, action) {
131.2978 - var node, nextInQueue = firstNode, firstOutOfRangeNode = ko.virtualElements.nextSibling(lastNode);
131.2979 - while (nextInQueue && ((node = nextInQueue) !== firstOutOfRangeNode)) {
131.2980 - nextInQueue = ko.virtualElements.nextSibling(node);
131.2981 - if (node.nodeType === 1 || node.nodeType === 8)
131.2982 - action(node);
131.2983 - }
131.2984 - }
131.2985 -
131.2986 - function activateBindingsOnContinuousNodeArray(continuousNodeArray, bindingContext) {
131.2987 - // To be used on any nodes that have been rendered by a template and have been inserted into some parent element
131.2988 - // Walks through continuousNodeArray (which *must* be continuous, i.e., an uninterrupted sequence of sibling nodes, because
131.2989 - // the algorithm for walking them relies on this), and for each top-level item in the virtual-element sense,
131.2990 - // (1) Does a regular "applyBindings" to associate bindingContext with this node and to activate any non-memoized bindings
131.2991 - // (2) Unmemoizes any memos in the DOM subtree (e.g., to activate bindings that had been memoized during template rewriting)
131.2992 -
131.2993 - if (continuousNodeArray.length) {
131.2994 - var firstNode = continuousNodeArray[0], lastNode = continuousNodeArray[continuousNodeArray.length - 1];
131.2995 -
131.2996 - // Need to applyBindings *before* unmemoziation, because unmemoization might introduce extra nodes (that we don't want to re-bind)
131.2997 - // whereas a regular applyBindings won't introduce new memoized nodes
131.2998 - invokeForEachNodeOrCommentInContinuousRange(firstNode, lastNode, function(node) {
131.2999 - ko.applyBindings(bindingContext, node);
131.3000 - });
131.3001 - invokeForEachNodeOrCommentInContinuousRange(firstNode, lastNode, function(node) {
131.3002 - ko.memoization.unmemoizeDomNodeAndDescendants(node, [bindingContext]);
131.3003 - });
131.3004 - }
131.3005 - }
131.3006 -
131.3007 - function getFirstNodeFromPossibleArray(nodeOrNodeArray) {
131.3008 - return nodeOrNodeArray.nodeType ? nodeOrNodeArray
131.3009 - : nodeOrNodeArray.length > 0 ? nodeOrNodeArray[0]
131.3010 - : null;
131.3011 - }
131.3012 -
131.3013 - function executeTemplate(targetNodeOrNodeArray, renderMode, template, bindingContext, options) {
131.3014 - options = options || {};
131.3015 - var firstTargetNode = targetNodeOrNodeArray && getFirstNodeFromPossibleArray(targetNodeOrNodeArray);
131.3016 - var templateDocument = firstTargetNode && firstTargetNode.ownerDocument;
131.3017 - var templateEngineToUse = (options['templateEngine'] || _templateEngine);
131.3018 - ko.templateRewriting.ensureTemplateIsRewritten(template, templateEngineToUse, templateDocument);
131.3019 - var renderedNodesArray = templateEngineToUse['renderTemplate'](template, bindingContext, options, templateDocument);
131.3020 -
131.3021 - // Loosely check result is an array of DOM nodes
131.3022 - if ((typeof renderedNodesArray.length != "number") || (renderedNodesArray.length > 0 && typeof renderedNodesArray[0].nodeType != "number"))
131.3023 - throw new Error("Template engine must return an array of DOM nodes");
131.3024 -
131.3025 - var haveAddedNodesToParent = false;
131.3026 - switch (renderMode) {
131.3027 - case "replaceChildren":
131.3028 - ko.virtualElements.setDomNodeChildren(targetNodeOrNodeArray, renderedNodesArray);
131.3029 - haveAddedNodesToParent = true;
131.3030 - break;
131.3031 - case "replaceNode":
131.3032 - ko.utils.replaceDomNodes(targetNodeOrNodeArray, renderedNodesArray);
131.3033 - haveAddedNodesToParent = true;
131.3034 - break;
131.3035 - case "ignoreTargetNode": break;
131.3036 - default:
131.3037 - throw new Error("Unknown renderMode: " + renderMode);
131.3038 - }
131.3039 -
131.3040 - if (haveAddedNodesToParent) {
131.3041 - activateBindingsOnContinuousNodeArray(renderedNodesArray, bindingContext);
131.3042 - if (options['afterRender'])
131.3043 - ko.dependencyDetection.ignore(options['afterRender'], null, [renderedNodesArray, bindingContext['$data']]);
131.3044 - }
131.3045 -
131.3046 - return renderedNodesArray;
131.3047 - }
131.3048 -
131.3049 - ko.renderTemplate = function (template, dataOrBindingContext, options, targetNodeOrNodeArray, renderMode) {
131.3050 - options = options || {};
131.3051 - if ((options['templateEngine'] || _templateEngine) == undefined)
131.3052 - throw new Error("Set a template engine before calling renderTemplate");
131.3053 - renderMode = renderMode || "replaceChildren";
131.3054 -
131.3055 - if (targetNodeOrNodeArray) {
131.3056 - var firstTargetNode = getFirstNodeFromPossibleArray(targetNodeOrNodeArray);
131.3057 -
131.3058 - var whenToDispose = function () { return (!firstTargetNode) || !ko.utils.domNodeIsAttachedToDocument(firstTargetNode); }; // Passive disposal (on next evaluation)
131.3059 - var activelyDisposeWhenNodeIsRemoved = (firstTargetNode && renderMode == "replaceNode") ? firstTargetNode.parentNode : firstTargetNode;
131.3060 -
131.3061 - return ko.dependentObservable( // So the DOM is automatically updated when any dependency changes
131.3062 - function () {
131.3063 - // Ensure we've got a proper binding context to work with
131.3064 - var bindingContext = (dataOrBindingContext && (dataOrBindingContext instanceof ko.bindingContext))
131.3065 - ? dataOrBindingContext
131.3066 - : new ko.bindingContext(ko.utils.unwrapObservable(dataOrBindingContext));
131.3067 -
131.3068 - // Support selecting template as a function of the data being rendered
131.3069 - var templateName = typeof(template) == 'function' ? template(bindingContext['$data'], bindingContext) : template;
131.3070 -
131.3071 - var renderedNodesArray = executeTemplate(targetNodeOrNodeArray, renderMode, templateName, bindingContext, options);
131.3072 - if (renderMode == "replaceNode") {
131.3073 - targetNodeOrNodeArray = renderedNodesArray;
131.3074 - firstTargetNode = getFirstNodeFromPossibleArray(targetNodeOrNodeArray);
131.3075 - }
131.3076 - },
131.3077 - null,
131.3078 - { disposeWhen: whenToDispose, disposeWhenNodeIsRemoved: activelyDisposeWhenNodeIsRemoved }
131.3079 - );
131.3080 - } else {
131.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
131.3082 - return ko.memoization.memoize(function (domNode) {
131.3083 - ko.renderTemplate(template, dataOrBindingContext, options, domNode, "replaceNode");
131.3084 - });
131.3085 - }
131.3086 - };
131.3087 -
131.3088 - ko.renderTemplateForEach = function (template, arrayOrObservableArray, options, targetNode, parentBindingContext) {
131.3089 - // Since setDomNodeChildrenFromArrayMapping always calls executeTemplateForArrayItem and then
131.3090 - // activateBindingsCallback for added items, we can store the binding context in the former to use in the latter.
131.3091 - var arrayItemContext;
131.3092 -
131.3093 - // This will be called by setDomNodeChildrenFromArrayMapping to get the nodes to add to targetNode
131.3094 - var executeTemplateForArrayItem = function (arrayValue, index) {
131.3095 - // Support selecting template as a function of the data being rendered
131.3096 - arrayItemContext = parentBindingContext['createChildContext'](ko.utils.unwrapObservable(arrayValue), options['as']);
131.3097 - arrayItemContext['$index'] = index;
131.3098 - var templateName = typeof(template) == 'function' ? template(arrayValue, arrayItemContext) : template;
131.3099 - return executeTemplate(null, "ignoreTargetNode", templateName, arrayItemContext, options);
131.3100 - }
131.3101 -
131.3102 - // This will be called whenever setDomNodeChildrenFromArrayMapping has added nodes to targetNode
131.3103 - var activateBindingsCallback = function(arrayValue, addedNodesArray, index) {
131.3104 - activateBindingsOnContinuousNodeArray(addedNodesArray, arrayItemContext);
131.3105 - if (options['afterRender'])
131.3106 - options['afterRender'](addedNodesArray, arrayValue);
131.3107 - };
131.3108 -
131.3109 - return ko.dependentObservable(function () {
131.3110 - var unwrappedArray = ko.utils.unwrapObservable(arrayOrObservableArray) || [];
131.3111 - if (typeof unwrappedArray.length == "undefined") // Coerce single value into array
131.3112 - unwrappedArray = [unwrappedArray];
131.3113 -
131.3114 - // Filter out any entries marked as destroyed
131.3115 - var filteredArray = ko.utils.arrayFilter(unwrappedArray, function(item) {
131.3116 - return options['includeDestroyed'] || item === undefined || item === null || !ko.utils.unwrapObservable(item['_destroy']);
131.3117 - });
131.3118 -
131.3119 - // Call setDomNodeChildrenFromArrayMapping, ignoring any observables unwrapped within (most likely from a callback function).
131.3120 - // If the array items are observables, though, they will be unwrapped in executeTemplateForArrayItem and managed within setDomNodeChildrenFromArrayMapping.
131.3121 - ko.dependencyDetection.ignore(ko.utils.setDomNodeChildrenFromArrayMapping, null, [targetNode, filteredArray, executeTemplateForArrayItem, options, activateBindingsCallback]);
131.3122 -
131.3123 - }, null, { disposeWhenNodeIsRemoved: targetNode });
131.3124 - };
131.3125 -
131.3126 - var templateComputedDomDataKey = '__ko__templateComputedDomDataKey__';
131.3127 - function disposeOldComputedAndStoreNewOne(element, newComputed) {
131.3128 - var oldComputed = ko.utils.domData.get(element, templateComputedDomDataKey);
131.3129 - if (oldComputed && (typeof(oldComputed.dispose) == 'function'))
131.3130 - oldComputed.dispose();
131.3131 - ko.utils.domData.set(element, templateComputedDomDataKey, (newComputed && newComputed.isActive()) ? newComputed : undefined);
131.3132 - }
131.3133 -
131.3134 - ko.bindingHandlers['template'] = {
131.3135 - 'init': function(element, valueAccessor) {
131.3136 - // Support anonymous templates
131.3137 - var bindingValue = ko.utils.unwrapObservable(valueAccessor());
131.3138 - if ((typeof bindingValue != "string") && (!bindingValue['name']) && (element.nodeType == 1 || element.nodeType == 8)) {
131.3139 - // It's an anonymous template - store the element contents, then clear the element
131.3140 - var templateNodes = element.nodeType == 1 ? element.childNodes : ko.virtualElements.childNodes(element),
131.3141 - container = ko.utils.moveCleanedNodesToContainerElement(templateNodes); // This also removes the nodes from their current parent
131.3142 - new ko.templateSources.anonymousTemplate(element)['nodes'](container);
131.3143 - }
131.3144 - return { 'controlsDescendantBindings': true };
131.3145 - },
131.3146 - 'update': function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
131.3147 - var templateName = ko.utils.unwrapObservable(valueAccessor()),
131.3148 - options = {},
131.3149 - shouldDisplay = true,
131.3150 - dataValue,
131.3151 - templateComputed = null;
131.3152 -
131.3153 - if (typeof templateName != "string") {
131.3154 - options = templateName;
131.3155 - templateName = options['name'];
131.3156 -
131.3157 - // Support "if"/"ifnot" conditions
131.3158 - if ('if' in options)
131.3159 - shouldDisplay = ko.utils.unwrapObservable(options['if']);
131.3160 - if (shouldDisplay && 'ifnot' in options)
131.3161 - shouldDisplay = !ko.utils.unwrapObservable(options['ifnot']);
131.3162 -
131.3163 - dataValue = ko.utils.unwrapObservable(options['data']);
131.3164 - }
131.3165 -
131.3166 - if ('foreach' in options) {
131.3167 - // Render once for each data point (treating data set as empty if shouldDisplay==false)
131.3168 - var dataArray = (shouldDisplay && options['foreach']) || [];
131.3169 - templateComputed = ko.renderTemplateForEach(templateName || element, dataArray, options, element, bindingContext);
131.3170 - } else if (!shouldDisplay) {
131.3171 - ko.virtualElements.emptyNode(element);
131.3172 - } else {
131.3173 - // Render once for this single data point (or use the viewModel if no data was provided)
131.3174 - var innerBindingContext = ('data' in options) ?
131.3175 - bindingContext['createChildContext'](dataValue, options['as']) : // Given an explitit 'data' value, we create a child binding context for it
131.3176 - bindingContext; // Given no explicit 'data' value, we retain the same binding context
131.3177 - templateComputed = ko.renderTemplate(templateName || element, innerBindingContext, options, element);
131.3178 - }
131.3179 -
131.3180 - // It only makes sense to have a single template computed per element (otherwise which one should have its output displayed?)
131.3181 - disposeOldComputedAndStoreNewOne(element, templateComputed);
131.3182 - }
131.3183 - };
131.3184 -
131.3185 - // Anonymous templates can't be rewritten. Give a nice error message if you try to do it.
131.3186 - ko.expressionRewriting.bindingRewriteValidators['template'] = function(bindingValue) {
131.3187 - var parsedBindingValue = ko.expressionRewriting.parseObjectLiteral(bindingValue);
131.3188 -
131.3189 - if ((parsedBindingValue.length == 1) && parsedBindingValue[0]['unknown'])
131.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)
131.3191 -
131.3192 - if (ko.expressionRewriting.keyValueArrayContainsKey(parsedBindingValue, "name"))
131.3193 - return null; // Named templates can be rewritten, so return "no error"
131.3194 - return "This template engine does not support anonymous templates nested within its templates";
131.3195 - };
131.3196 -
131.3197 - ko.virtualElements.allowedBindings['template'] = true;
131.3198 -})();
131.3199 -
131.3200 -ko.exportSymbol('setTemplateEngine', ko.setTemplateEngine);
131.3201 -ko.exportSymbol('renderTemplate', ko.renderTemplate);
131.3202 -
131.3203 -ko.utils.compareArrays = (function () {
131.3204 - var statusNotInOld = 'added', statusNotInNew = 'deleted';
131.3205 -
131.3206 - // Simple calculation based on Levenshtein distance.
131.3207 - function compareArrays(oldArray, newArray, dontLimitMoves) {
131.3208 - oldArray = oldArray || [];
131.3209 - newArray = newArray || [];
131.3210 -
131.3211 - if (oldArray.length <= newArray.length)
131.3212 - return compareSmallArrayToBigArray(oldArray, newArray, statusNotInOld, statusNotInNew, dontLimitMoves);
131.3213 - else
131.3214 - return compareSmallArrayToBigArray(newArray, oldArray, statusNotInNew, statusNotInOld, dontLimitMoves);
131.3215 - }
131.3216 -
131.3217 - function compareSmallArrayToBigArray(smlArray, bigArray, statusNotInSml, statusNotInBig, dontLimitMoves) {
131.3218 - var myMin = Math.min,
131.3219 - myMax = Math.max,
131.3220 - editDistanceMatrix = [],
131.3221 - smlIndex, smlIndexMax = smlArray.length,
131.3222 - bigIndex, bigIndexMax = bigArray.length,
131.3223 - compareRange = (bigIndexMax - smlIndexMax) || 1,
131.3224 - maxDistance = smlIndexMax + bigIndexMax + 1,
131.3225 - thisRow, lastRow,
131.3226 - bigIndexMaxForRow, bigIndexMinForRow;
131.3227 -
131.3228 - for (smlIndex = 0; smlIndex <= smlIndexMax; smlIndex++) {
131.3229 - lastRow = thisRow;
131.3230 - editDistanceMatrix.push(thisRow = []);
131.3231 - bigIndexMaxForRow = myMin(bigIndexMax, smlIndex + compareRange);
131.3232 - bigIndexMinForRow = myMax(0, smlIndex - 1);
131.3233 - for (bigIndex = bigIndexMinForRow; bigIndex <= bigIndexMaxForRow; bigIndex++) {
131.3234 - if (!bigIndex)
131.3235 - thisRow[bigIndex] = smlIndex + 1;
131.3236 - else if (!smlIndex) // Top row - transform empty array into new array via additions
131.3237 - thisRow[bigIndex] = bigIndex + 1;
131.3238 - else if (smlArray[smlIndex - 1] === bigArray[bigIndex - 1])
131.3239 - thisRow[bigIndex] = lastRow[bigIndex - 1]; // copy value (no edit)
131.3240 - else {
131.3241 - var northDistance = lastRow[bigIndex] || maxDistance; // not in big (deletion)
131.3242 - var westDistance = thisRow[bigIndex - 1] || maxDistance; // not in small (addition)
131.3243 - thisRow[bigIndex] = myMin(northDistance, westDistance) + 1;
131.3244 - }
131.3245 - }
131.3246 - }
131.3247 -
131.3248 - var editScript = [], meMinusOne, notInSml = [], notInBig = [];
131.3249 - for (smlIndex = smlIndexMax, bigIndex = bigIndexMax; smlIndex || bigIndex;) {
131.3250 - meMinusOne = editDistanceMatrix[smlIndex][bigIndex] - 1;
131.3251 - if (bigIndex && meMinusOne === editDistanceMatrix[smlIndex][bigIndex-1]) {
131.3252 - notInSml.push(editScript[editScript.length] = { // added
131.3253 - 'status': statusNotInSml,
131.3254 - 'value': bigArray[--bigIndex],
131.3255 - 'index': bigIndex });
131.3256 - } else if (smlIndex && meMinusOne === editDistanceMatrix[smlIndex - 1][bigIndex]) {
131.3257 - notInBig.push(editScript[editScript.length] = { // deleted
131.3258 - 'status': statusNotInBig,
131.3259 - 'value': smlArray[--smlIndex],
131.3260 - 'index': smlIndex });
131.3261 - } else {
131.3262 - editScript.push({
131.3263 - 'status': "retained",
131.3264 - 'value': bigArray[--bigIndex] });
131.3265 - --smlIndex;
131.3266 - }
131.3267 - }
131.3268 -
131.3269 - if (notInSml.length && notInBig.length) {
131.3270 - // Set a limit on the number of consecutive non-matching comparisons; having it a multiple of
131.3271 - // smlIndexMax keeps the time complexity of this algorithm linear.
131.3272 - var limitFailedCompares = smlIndexMax * 10, failedCompares,
131.3273 - a, d, notInSmlItem, notInBigItem;
131.3274 - // Go through the items that have been added and deleted and try to find matches between them.
131.3275 - for (failedCompares = a = 0; (dontLimitMoves || failedCompares < limitFailedCompares) && (notInSmlItem = notInSml[a]); a++) {
131.3276 - for (d = 0; notInBigItem = notInBig[d]; d++) {
131.3277 - if (notInSmlItem['value'] === notInBigItem['value']) {
131.3278 - notInSmlItem['moved'] = notInBigItem['index'];
131.3279 - notInBigItem['moved'] = notInSmlItem['index'];
131.3280 - notInBig.splice(d,1); // This item is marked as moved; so remove it from notInBig list
131.3281 - failedCompares = d = 0; // Reset failed compares count because we're checking for consecutive failures
131.3282 - break;
131.3283 - }
131.3284 - }
131.3285 - failedCompares += d;
131.3286 - }
131.3287 - }
131.3288 - return editScript.reverse();
131.3289 - }
131.3290 -
131.3291 - return compareArrays;
131.3292 -})();
131.3293 -
131.3294 -ko.exportSymbol('utils.compareArrays', ko.utils.compareArrays);
131.3295 -
131.3296 -(function () {
131.3297 - // Objective:
131.3298 - // * Given an input array, a container DOM node, and a function from array elements to arrays of DOM nodes,
131.3299 - // map the array elements to arrays of DOM nodes, concatenate together all these arrays, and use them to populate the container DOM node
131.3300 - // * Next time we're given the same combination of things (with the array possibly having mutated), update the container DOM node
131.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
131.3302 - // previously mapped - retain those nodes, and just insert/delete other ones
131.3303 -
131.3304 - // "callbackAfterAddingNodes" will be invoked after any "mapping"-generated nodes are inserted into the container node
131.3305 - // You can use this, for example, to activate bindings on those nodes.
131.3306 -
131.3307 - function fixUpNodesToBeMovedOrRemoved(contiguousNodeArray) {
131.3308 - // Before moving, deleting, or replacing a set of nodes that were previously outputted by the "map" function, we have to reconcile
131.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,
131.3310 - // or that new nodes might have been inserted in the middle, for example by a binding. Also, there may previously have been
131.3311 - // leading comment nodes (created by rewritten string-based templates) that have since been removed during binding.
131.3312 - // So, this function translates the old "map" output array into its best guess of what set of current DOM nodes should be removed.
131.3313 - //
131.3314 - // Rules:
131.3315 - // [A] Any leading nodes that aren't in the document any more should be ignored
131.3316 - // These most likely correspond to memoization nodes that were already removed during binding
131.3317 - // See https://github.com/SteveSanderson/knockout/pull/440
131.3318 - // [B] We want to output a contiguous series of nodes that are still in the document. So, ignore any nodes that
131.3319 - // have already been removed, and include any nodes that have been inserted among the previous collection
131.3320 -
131.3321 - // Rule [A]
131.3322 - while (contiguousNodeArray.length && !ko.utils.domNodeIsAttachedToDocument(contiguousNodeArray[0]))
131.3323 - contiguousNodeArray.splice(0, 1);
131.3324 -
131.3325 - // Rule [B]
131.3326 - if (contiguousNodeArray.length > 1) {
131.3327 - // Build up the actual new contiguous node set
131.3328 - var current = contiguousNodeArray[0], last = contiguousNodeArray[contiguousNodeArray.length - 1], newContiguousSet = [current];
131.3329 - while (current !== last) {
131.3330 - current = current.nextSibling;
131.3331 - if (!current) // Won't happen, except if the developer has manually removed some DOM elements (then we're in an undefined scenario)
131.3332 - return;
131.3333 - newContiguousSet.push(current);
131.3334 - }
131.3335 -
131.3336 - // ... then mutate the input array to match this.
131.3337 - // (The following line replaces the contents of contiguousNodeArray with newContiguousSet)
131.3338 - Array.prototype.splice.apply(contiguousNodeArray, [0, contiguousNodeArray.length].concat(newContiguousSet));
131.3339 - }
131.3340 - return contiguousNodeArray;
131.3341 - }
131.3342 -
131.3343 - function mapNodeAndRefreshWhenChanged(containerNode, mapping, valueToMap, callbackAfterAddingNodes, index) {
131.3344 - // Map this array value inside a dependentObservable so we re-map when any dependency changes
131.3345 - var mappedNodes = [];
131.3346 - var dependentObservable = ko.dependentObservable(function() {
131.3347 - var newMappedNodes = mapping(valueToMap, index) || [];
131.3348 -
131.3349 - // On subsequent evaluations, just replace the previously-inserted DOM nodes
131.3350 - if (mappedNodes.length > 0) {
131.3351 - ko.utils.replaceDomNodes(fixUpNodesToBeMovedOrRemoved(mappedNodes), newMappedNodes);
131.3352 - if (callbackAfterAddingNodes)
131.3353 - ko.dependencyDetection.ignore(callbackAfterAddingNodes, null, [valueToMap, newMappedNodes, index]);
131.3354 - }
131.3355 -
131.3356 - // Replace the contents of the mappedNodes array, thereby updating the record
131.3357 - // of which nodes would be deleted if valueToMap was itself later removed
131.3358 - mappedNodes.splice(0, mappedNodes.length);
131.3359 - ko.utils.arrayPushAll(mappedNodes, newMappedNodes);
131.3360 - }, null, { disposeWhenNodeIsRemoved: containerNode, disposeWhen: function() { return (mappedNodes.length == 0) || !ko.utils.domNodeIsAttachedToDocument(mappedNodes[0]) } });
131.3361 - return { mappedNodes : mappedNodes, dependentObservable : (dependentObservable.isActive() ? dependentObservable : undefined) };
131.3362 - }
131.3363 -
131.3364 - var lastMappingResultDomDataKey = "setDomNodeChildrenFromArrayMapping_lastMappingResult";
131.3365 -
131.3366 - ko.utils.setDomNodeChildrenFromArrayMapping = function (domNode, array, mapping, options, callbackAfterAddingNodes) {
131.3367 - // Compare the provided array against the previous one
131.3368 - array = array || [];
131.3369 - options = options || {};
131.3370 - var isFirstExecution = ko.utils.domData.get(domNode, lastMappingResultDomDataKey) === undefined;
131.3371 - var lastMappingResult = ko.utils.domData.get(domNode, lastMappingResultDomDataKey) || [];
131.3372 - var lastArray = ko.utils.arrayMap(lastMappingResult, function (x) { return x.arrayEntry; });
131.3373 - var editScript = ko.utils.compareArrays(lastArray, array);
131.3374 -
131.3375 - // Build the new mapping result
131.3376 - var newMappingResult = [];
131.3377 - var lastMappingResultIndex = 0;
131.3378 - var newMappingResultIndex = 0;
131.3379 -
131.3380 - var nodesToDelete = [];
131.3381 - var itemsToProcess = [];
131.3382 - var itemsForBeforeRemoveCallbacks = [];
131.3383 - var itemsForMoveCallbacks = [];
131.3384 - var itemsForAfterAddCallbacks = [];
131.3385 - var mapData;
131.3386 -
131.3387 - function itemMovedOrRetained(editScriptIndex, oldPosition) {
131.3388 - mapData = lastMappingResult[oldPosition];
131.3389 - if (newMappingResultIndex !== oldPosition)
131.3390 - itemsForMoveCallbacks[editScriptIndex] = mapData;
131.3391 - // Since updating the index might change the nodes, do so before calling fixUpNodesToBeMovedOrRemoved
131.3392 - mapData.indexObservable(newMappingResultIndex++);
131.3393 - fixUpNodesToBeMovedOrRemoved(mapData.mappedNodes);
131.3394 - newMappingResult.push(mapData);
131.3395 - itemsToProcess.push(mapData);
131.3396 - }
131.3397 -
131.3398 - function callCallback(callback, items) {
131.3399 - if (callback) {
131.3400 - for (var i = 0, n = items.length; i < n; i++) {
131.3401 - if (items[i]) {
131.3402 - ko.utils.arrayForEach(items[i].mappedNodes, function(node) {
131.3403 - callback(node, i, items[i].arrayEntry);
131.3404 - });
131.3405 - }
131.3406 - }
131.3407 - }
131.3408 - }
131.3409 -
131.3410 - for (var i = 0, editScriptItem, movedIndex; editScriptItem = editScript[i]; i++) {
131.3411 - movedIndex = editScriptItem['moved'];
131.3412 - switch (editScriptItem['status']) {
131.3413 - case "deleted":
131.3414 - if (movedIndex === undefined) {
131.3415 - mapData = lastMappingResult[lastMappingResultIndex];
131.3416 -
131.3417 - // Stop tracking changes to the mapping for these nodes
131.3418 - if (mapData.dependentObservable)
131.3419 - mapData.dependentObservable.dispose();
131.3420 -
131.3421 - // Queue these nodes for later removal
131.3422 - nodesToDelete.push.apply(nodesToDelete, fixUpNodesToBeMovedOrRemoved(mapData.mappedNodes));
131.3423 - if (options['beforeRemove']) {
131.3424 - itemsForBeforeRemoveCallbacks[i] = mapData;
131.3425 - itemsToProcess.push(mapData);
131.3426 - }
131.3427 - }
131.3428 - lastMappingResultIndex++;
131.3429 - break;
131.3430 -
131.3431 - case "retained":
131.3432 - itemMovedOrRetained(i, lastMappingResultIndex++);
131.3433 - break;
131.3434 -
131.3435 - case "added":
131.3436 - if (movedIndex !== undefined) {
131.3437 - itemMovedOrRetained(i, movedIndex);
131.3438 - } else {
131.3439 - mapData = { arrayEntry: editScriptItem['value'], indexObservable: ko.observable(newMappingResultIndex++) };
131.3440 - newMappingResult.push(mapData);
131.3441 - itemsToProcess.push(mapData);
131.3442 - if (!isFirstExecution)
131.3443 - itemsForAfterAddCallbacks[i] = mapData;
131.3444 - }
131.3445 - break;
131.3446 - }
131.3447 - }
131.3448 -
131.3449 - // Call beforeMove first before any changes have been made to the DOM
131.3450 - callCallback(options['beforeMove'], itemsForMoveCallbacks);
131.3451 -
131.3452 - // Next remove nodes for deleted items (or just clean if there's a beforeRemove callback)
131.3453 - ko.utils.arrayForEach(nodesToDelete, options['beforeRemove'] ? ko.cleanNode : ko.removeNode);
131.3454 -
131.3455 - // Next add/reorder the remaining items (will include deleted items if there's a beforeRemove callback)
131.3456 - for (var i = 0, nextNode = ko.virtualElements.firstChild(domNode), lastNode, node; mapData = itemsToProcess[i]; i++) {
131.3457 - // Get nodes for newly added items
131.3458 - if (!mapData.mappedNodes)
131.3459 - ko.utils.extend(mapData, mapNodeAndRefreshWhenChanged(domNode, mapping, mapData.arrayEntry, callbackAfterAddingNodes, mapData.indexObservable));
131.3460 -
131.3461 - // Put nodes in the right place if they aren't there already
131.3462 - for (var j = 0; node = mapData.mappedNodes[j]; nextNode = node.nextSibling, lastNode = node, j++) {
131.3463 - if (node !== nextNode)
131.3464 - ko.virtualElements.insertAfter(domNode, node, lastNode);
131.3465 - }
131.3466 -
131.3467 - // Run the callbacks for newly added nodes (for example, to apply bindings, etc.)
131.3468 - if (!mapData.initialized && callbackAfterAddingNodes) {
131.3469 - callbackAfterAddingNodes(mapData.arrayEntry, mapData.mappedNodes, mapData.indexObservable);
131.3470 - mapData.initialized = true;
131.3471 - }
131.3472 - }
131.3473 -
131.3474 - // If there's a beforeRemove callback, call it after reordering.
131.3475 - // Note that we assume that the beforeRemove callback will usually be used to remove the nodes using
131.3476 - // some sort of animation, which is why we first reorder the nodes that will be removed. If the
131.3477 - // callback instead removes the nodes right away, it would be more efficient to skip reordering them.
131.3478 - // Perhaps we'll make that change in the future if this scenario becomes more common.
131.3479 - callCallback(options['beforeRemove'], itemsForBeforeRemoveCallbacks);
131.3480 -
131.3481 - // Finally call afterMove and afterAdd callbacks
131.3482 - callCallback(options['afterMove'], itemsForMoveCallbacks);
131.3483 - callCallback(options['afterAdd'], itemsForAfterAddCallbacks);
131.3484 -
131.3485 - // Store a copy of the array items we just considered so we can difference it next time
131.3486 - ko.utils.domData.set(domNode, lastMappingResultDomDataKey, newMappingResult);
131.3487 - }
131.3488 -})();
131.3489 -
131.3490 -ko.exportSymbol('utils.setDomNodeChildrenFromArrayMapping', ko.utils.setDomNodeChildrenFromArrayMapping);
131.3491 -ko.nativeTemplateEngine = function () {
131.3492 - this['allowTemplateRewriting'] = false;
131.3493 -}
131.3494 -
131.3495 -ko.nativeTemplateEngine.prototype = new ko.templateEngine();
131.3496 -ko.nativeTemplateEngine.prototype['renderTemplateSource'] = function (templateSource, bindingContext, options) {
131.3497 - var useNodesIfAvailable = !(ko.utils.ieVersion < 9), // IE<9 cloneNode doesn't work properly
131.3498 - templateNodesFunc = useNodesIfAvailable ? templateSource['nodes'] : null,
131.3499 - templateNodes = templateNodesFunc ? templateSource['nodes']() : null;
131.3500 -
131.3501 - if (templateNodes) {
131.3502 - return ko.utils.makeArray(templateNodes.cloneNode(true).childNodes);
131.3503 - } else {
131.3504 - var templateText = templateSource['text']();
131.3505 - return ko.utils.parseHtmlFragment(templateText);
131.3506 - }
131.3507 -};
131.3508 -
131.3509 -ko.nativeTemplateEngine.instance = new ko.nativeTemplateEngine();
131.3510 -ko.setTemplateEngine(ko.nativeTemplateEngine.instance);
131.3511 -
131.3512 -ko.exportSymbol('nativeTemplateEngine', ko.nativeTemplateEngine);
131.3513 -(function() {
131.3514 - ko.jqueryTmplTemplateEngine = function () {
131.3515 - // Detect which version of jquery-tmpl you're using. Unfortunately jquery-tmpl
131.3516 - // doesn't expose a version number, so we have to infer it.
131.3517 - // Note that as of Knockout 1.3, we only support jQuery.tmpl 1.0.0pre and later,
131.3518 - // which KO internally refers to as version "2", so older versions are no longer detected.
131.3519 - var jQueryTmplVersion = this.jQueryTmplVersion = (function() {
131.3520 - if ((typeof(jQuery) == "undefined") || !(jQuery['tmpl']))
131.3521 - return 0;
131.3522 - // Since it exposes no official version number, we use our own numbering system. To be updated as jquery-tmpl evolves.
131.3523 - try {
131.3524 - if (jQuery['tmpl']['tag']['tmpl']['open'].toString().indexOf('__') >= 0) {
131.3525 - // Since 1.0.0pre, custom tags should append markup to an array called "__"
131.3526 - return 2; // Final version of jquery.tmpl
131.3527 - }
131.3528 - } catch(ex) { /* Apparently not the version we were looking for */ }
131.3529 -
131.3530 - return 1; // Any older version that we don't support
131.3531 - })();
131.3532 -
131.3533 - function ensureHasReferencedJQueryTemplates() {
131.3534 - if (jQueryTmplVersion < 2)
131.3535 - throw new Error("Your version of jQuery.tmpl is too old. Please upgrade to jQuery.tmpl 1.0.0pre or later.");
131.3536 - }
131.3537 -
131.3538 - function executeTemplate(compiledTemplate, data, jQueryTemplateOptions) {
131.3539 - return jQuery['tmpl'](compiledTemplate, data, jQueryTemplateOptions);
131.3540 - }
131.3541 -
131.3542 - this['renderTemplateSource'] = function(templateSource, bindingContext, options) {
131.3543 - options = options || {};
131.3544 - ensureHasReferencedJQueryTemplates();
131.3545 -
131.3546 - // Ensure we have stored a precompiled version of this template (don't want to reparse on every render)
131.3547 - var precompiled = templateSource['data']('precompiled');
131.3548 - if (!precompiled) {
131.3549 - var templateText = templateSource['text']() || "";
131.3550 - // Wrap in "with($whatever.koBindingContext) { ... }"
131.3551 - templateText = "{{ko_with $item.koBindingContext}}" + templateText + "{{/ko_with}}";
131.3552 -
131.3553 - precompiled = jQuery['template'](null, templateText);
131.3554 - templateSource['data']('precompiled', precompiled);
131.3555 - }
131.3556 -
131.3557 - var data = [bindingContext['$data']]; // Prewrap the data in an array to stop jquery.tmpl from trying to unwrap any arrays
131.3558 - var jQueryTemplateOptions = jQuery['extend']({ 'koBindingContext': bindingContext }, options['templateOptions']);
131.3559 -
131.3560 - var resultNodes = executeTemplate(precompiled, data, jQueryTemplateOptions);
131.3561 - resultNodes['appendTo'](document.createElement("div")); // Using "appendTo" forces jQuery/jQuery.tmpl to perform necessary cleanup work
131.3562 -
131.3563 - jQuery['fragments'] = {}; // Clear jQuery's fragment cache to avoid a memory leak after a large number of template renders
131.3564 - return resultNodes;
131.3565 - };
131.3566 -
131.3567 - this['createJavaScriptEvaluatorBlock'] = function(script) {
131.3568 - return "{{ko_code ((function() { return " + script + " })()) }}";
131.3569 - };
131.3570 -
131.3571 - this['addTemplate'] = function(templateName, templateMarkup) {
131.3572 - document.write("<script type='text/html' id='" + templateName + "'>" + templateMarkup + "</script>");
131.3573 - };
131.3574 -
131.3575 - if (jQueryTmplVersion > 0) {
131.3576 - jQuery['tmpl']['tag']['ko_code'] = {
131.3577 - open: "__.push($1 || '');"
131.3578 - };
131.3579 - jQuery['tmpl']['tag']['ko_with'] = {
131.3580 - open: "with($1) {",
131.3581 - close: "} "
131.3582 - };
131.3583 - }
131.3584 - };
131.3585 -
131.3586 - ko.jqueryTmplTemplateEngine.prototype = new ko.templateEngine();
131.3587 -
131.3588 - // Use this one by default *only if jquery.tmpl is referenced*
131.3589 - var jqueryTmplTemplateEngineInstance = new ko.jqueryTmplTemplateEngine();
131.3590 - if (jqueryTmplTemplateEngineInstance.jQueryTmplVersion > 0)
131.3591 - ko.setTemplateEngine(jqueryTmplTemplateEngineInstance);
131.3592 -
131.3593 - ko.exportSymbol('jqueryTmplTemplateEngine', ko.jqueryTmplTemplateEngine);
131.3594 -})();
131.3595 -});
131.3596 -})(window,document,navigator,window["jQuery"]);
131.3597 -})();
131.3598 \ No newline at end of file
132.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
132.2 +++ b/ko-fx/src/main/resources/org/netbeans/html/kofx/knockout-2.2.1.js Mon Dec 16 16:59:43 2013 +0100
132.3 @@ -0,0 +1,3594 @@
132.4 +// Knockout JavaScript library v2.2.1
132.5 +// (c) Steven Sanderson - http://knockoutjs.com/
132.6 +// License: MIT (http://www.opensource.org/licenses/mit-license.php)
132.7 +
132.8 +(function(){
132.9 +var DEBUG=true;
132.10 +(function(window,document,navigator,jQuery,undefined){
132.11 +!function(factory) {
132.12 + // Support three module loading scenarios
132.13 + if (typeof require === 'function' && typeof exports === 'object' && typeof module === 'object') {
132.14 + // [1] CommonJS/Node.js
132.15 + var target = module['exports'] || exports; // module.exports is for Node.js
132.16 + factory(target);
132.17 + } else if (typeof define === 'function' && define['amd']) {
132.18 + // [2] AMD anonymous module
132.19 + define(['exports'], factory);
132.20 + } else {
132.21 + // [3] No module loader (plain <script> tag) - put directly in global namespace
132.22 + factory(window['ko'] = {});
132.23 + }
132.24 +}(function(koExports){
132.25 +// Internally, all KO objects are attached to koExports (even the non-exported ones whose names will be minified by the closure compiler).
132.26 +// In the future, the following "ko" variable may be made distinct from "koExports" so that private objects are not externally reachable.
132.27 +var ko = typeof koExports !== 'undefined' ? koExports : {};
132.28 +// Google Closure Compiler helpers (used only to make the minified file smaller)
132.29 +ko.exportSymbol = function(koPath, object) {
132.30 + var tokens = koPath.split(".");
132.31 +
132.32 + // In the future, "ko" may become distinct from "koExports" (so that non-exported objects are not reachable)
132.33 + // At that point, "target" would be set to: (typeof koExports !== "undefined" ? koExports : ko)
132.34 + var target = ko;
132.35 +
132.36 + for (var i = 0; i < tokens.length - 1; i++)
132.37 + target = target[tokens[i]];
132.38 + target[tokens[tokens.length - 1]] = object;
132.39 +};
132.40 +ko.exportProperty = function(owner, publicName, object) {
132.41 + owner[publicName] = object;
132.42 +};
132.43 +ko.version = "2.2.1";
132.44 +
132.45 +ko.exportSymbol('version', ko.version);
132.46 +ko.utils = new (function () {
132.47 + var stringTrimRegex = /^(\s|\u00A0)+|(\s|\u00A0)+$/g;
132.48 +
132.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)
132.50 + var knownEvents = {}, knownEventTypesByEventName = {};
132.51 + var keyEventTypeName = /Firefox\/2/i.test(navigator.userAgent) ? 'KeyboardEvent' : 'UIEvents';
132.52 + knownEvents[keyEventTypeName] = ['keyup', 'keydown', 'keypress'];
132.53 + knownEvents['MouseEvents'] = ['click', 'dblclick', 'mousedown', 'mouseup', 'mousemove', 'mouseover', 'mouseout', 'mouseenter', 'mouseleave'];
132.54 + for (var eventType in knownEvents) {
132.55 + var knownEventsForType = knownEvents[eventType];
132.56 + if (knownEventsForType.length) {
132.57 + for (var i = 0, j = knownEventsForType.length; i < j; i++)
132.58 + knownEventTypesByEventName[knownEventsForType[i]] = eventType;
132.59 + }
132.60 + }
132.61 + var eventsThatMustBeRegisteredUsingAttachEvent = { 'propertychange': true }; // Workaround for an IE9 issue - https://github.com/SteveSanderson/knockout/issues/406
132.62 +
132.63 + // Detect IE versions for bug workarounds (uses IE conditionals, not UA string, for robustness)
132.64 + // Note that, since IE 10 does not support conditional comments, the following logic only detects IE < 10.
132.65 + // Currently this is by design, since IE 10+ behaves correctly when treated as a standard browser.
132.66 + // If there is a future need to detect specific versions of IE10+, we will amend this.
132.67 + var ieVersion = (function() {
132.68 + var version = 3, div = document.createElement('div'), iElems = div.getElementsByTagName('i');
132.69 +
132.70 + // Keep constructing conditional HTML blocks until we hit one that resolves to an empty fragment
132.71 + while (
132.72 + div.innerHTML = '<!--[if gt IE ' + (++version) + ']><i></i><![endif]-->',
132.73 + iElems[0]
132.74 + );
132.75 + return version > 4 ? version : undefined;
132.76 + }());
132.77 + var isIe6 = ieVersion === 6,
132.78 + isIe7 = ieVersion === 7;
132.79 +
132.80 + function isClickOnCheckableElement(element, eventType) {
132.81 + if ((ko.utils.tagNameLower(element) !== "input") || !element.type) return false;
132.82 + if (eventType.toLowerCase() != "click") return false;
132.83 + var inputType = element.type;
132.84 + return (inputType == "checkbox") || (inputType == "radio");
132.85 + }
132.86 +
132.87 + return {
132.88 + fieldsIncludedWithJsonPost: ['authenticity_token', /^__RequestVerificationToken(_.*)?$/],
132.89 +
132.90 + arrayForEach: function (array, action) {
132.91 + for (var i = 0, j = array.length; i < j; i++)
132.92 + action(array[i]);
132.93 + },
132.94 +
132.95 + arrayIndexOf: function (array, item) {
132.96 + if (typeof Array.prototype.indexOf == "function")
132.97 + return Array.prototype.indexOf.call(array, item);
132.98 + for (var i = 0, j = array.length; i < j; i++)
132.99 + if (array[i] === item)
132.100 + return i;
132.101 + return -1;
132.102 + },
132.103 +
132.104 + arrayFirst: function (array, predicate, predicateOwner) {
132.105 + for (var i = 0, j = array.length; i < j; i++)
132.106 + if (predicate.call(predicateOwner, array[i]))
132.107 + return array[i];
132.108 + return null;
132.109 + },
132.110 +
132.111 + arrayRemoveItem: function (array, itemToRemove) {
132.112 + var index = ko.utils.arrayIndexOf(array, itemToRemove);
132.113 + if (index >= 0)
132.114 + array.splice(index, 1);
132.115 + },
132.116 +
132.117 + arrayGetDistinctValues: function (array) {
132.118 + array = array || [];
132.119 + var result = [];
132.120 + for (var i = 0, j = array.length; i < j; i++) {
132.121 + if (ko.utils.arrayIndexOf(result, array[i]) < 0)
132.122 + result.push(array[i]);
132.123 + }
132.124 + return result;
132.125 + },
132.126 +
132.127 + arrayMap: function (array, mapping) {
132.128 + array = array || [];
132.129 + var result = [];
132.130 + for (var i = 0, j = array.length; i < j; i++)
132.131 + result.push(mapping(array[i]));
132.132 + return result;
132.133 + },
132.134 +
132.135 + arrayFilter: function (array, predicate) {
132.136 + array = array || [];
132.137 + var result = [];
132.138 + for (var i = 0, j = array.length; i < j; i++)
132.139 + if (predicate(array[i]))
132.140 + result.push(array[i]);
132.141 + return result;
132.142 + },
132.143 +
132.144 + arrayPushAll: function (array, valuesToPush) {
132.145 + if (valuesToPush instanceof Array)
132.146 + array.push.apply(array, valuesToPush);
132.147 + else
132.148 + for (var i = 0, j = valuesToPush.length; i < j; i++)
132.149 + array.push(valuesToPush[i]);
132.150 + return array;
132.151 + },
132.152 +
132.153 + extend: function (target, source) {
132.154 + if (source) {
132.155 + for(var prop in source) {
132.156 + if(source.hasOwnProperty(prop)) {
132.157 + target[prop] = source[prop];
132.158 + }
132.159 + }
132.160 + }
132.161 + return target;
132.162 + },
132.163 +
132.164 + emptyDomNode: function (domNode) {
132.165 + while (domNode.firstChild) {
132.166 + ko.removeNode(domNode.firstChild);
132.167 + }
132.168 + },
132.169 +
132.170 + moveCleanedNodesToContainerElement: function(nodes) {
132.171 + // Ensure it's a real array, as we're about to reparent the nodes and
132.172 + // we don't want the underlying collection to change while we're doing that.
132.173 + var nodesArray = ko.utils.makeArray(nodes);
132.174 +
132.175 + var container = document.createElement('div');
132.176 + for (var i = 0, j = nodesArray.length; i < j; i++) {
132.177 + container.appendChild(ko.cleanNode(nodesArray[i]));
132.178 + }
132.179 + return container;
132.180 + },
132.181 +
132.182 + cloneNodes: function (nodesArray, shouldCleanNodes) {
132.183 + for (var i = 0, j = nodesArray.length, newNodesArray = []; i < j; i++) {
132.184 + var clonedNode = nodesArray[i].cloneNode(true);
132.185 + newNodesArray.push(shouldCleanNodes ? ko.cleanNode(clonedNode) : clonedNode);
132.186 + }
132.187 + return newNodesArray;
132.188 + },
132.189 +
132.190 + setDomNodeChildren: function (domNode, childNodes) {
132.191 + ko.utils.emptyDomNode(domNode);
132.192 + if (childNodes) {
132.193 + for (var i = 0, j = childNodes.length; i < j; i++)
132.194 + domNode.appendChild(childNodes[i]);
132.195 + }
132.196 + },
132.197 +
132.198 + replaceDomNodes: function (nodeToReplaceOrNodeArray, newNodesArray) {
132.199 + var nodesToReplaceArray = nodeToReplaceOrNodeArray.nodeType ? [nodeToReplaceOrNodeArray] : nodeToReplaceOrNodeArray;
132.200 + if (nodesToReplaceArray.length > 0) {
132.201 + var insertionPoint = nodesToReplaceArray[0];
132.202 + var parent = insertionPoint.parentNode;
132.203 + for (var i = 0, j = newNodesArray.length; i < j; i++)
132.204 + parent.insertBefore(newNodesArray[i], insertionPoint);
132.205 + for (var i = 0, j = nodesToReplaceArray.length; i < j; i++) {
132.206 + ko.removeNode(nodesToReplaceArray[i]);
132.207 + }
132.208 + }
132.209 + },
132.210 +
132.211 + setOptionNodeSelectionState: function (optionNode, isSelected) {
132.212 + // IE6 sometimes throws "unknown error" if you try to write to .selected directly, whereas Firefox struggles with setAttribute. Pick one based on browser.
132.213 + if (ieVersion < 7)
132.214 + optionNode.setAttribute("selected", isSelected);
132.215 + else
132.216 + optionNode.selected = isSelected;
132.217 + },
132.218 +
132.219 + stringTrim: function (string) {
132.220 + return (string || "").replace(stringTrimRegex, "");
132.221 + },
132.222 +
132.223 + stringTokenize: function (string, delimiter) {
132.224 + var result = [];
132.225 + var tokens = (string || "").split(delimiter);
132.226 + for (var i = 0, j = tokens.length; i < j; i++) {
132.227 + var trimmed = ko.utils.stringTrim(tokens[i]);
132.228 + if (trimmed !== "")
132.229 + result.push(trimmed);
132.230 + }
132.231 + return result;
132.232 + },
132.233 +
132.234 + stringStartsWith: function (string, startsWith) {
132.235 + string = string || "";
132.236 + if (startsWith.length > string.length)
132.237 + return false;
132.238 + return string.substring(0, startsWith.length) === startsWith;
132.239 + },
132.240 +
132.241 + domNodeIsContainedBy: function (node, containedByNode) {
132.242 + if (containedByNode.compareDocumentPosition)
132.243 + return (containedByNode.compareDocumentPosition(node) & 16) == 16;
132.244 + while (node != null) {
132.245 + if (node == containedByNode)
132.246 + return true;
132.247 + node = node.parentNode;
132.248 + }
132.249 + return false;
132.250 + },
132.251 +
132.252 + domNodeIsAttachedToDocument: function (node) {
132.253 + return ko.utils.domNodeIsContainedBy(node, node.ownerDocument);
132.254 + },
132.255 +
132.256 + tagNameLower: function(element) {
132.257 + // For HTML elements, tagName will always be upper case; for XHTML elements, it'll be lower case.
132.258 + // Possible future optimization: If we know it's an element from an XHTML document (not HTML),
132.259 + // we don't need to do the .toLowerCase() as it will always be lower case anyway.
132.260 + return element && element.tagName && element.tagName.toLowerCase();
132.261 + },
132.262 +
132.263 + registerEventHandler: function (element, eventType, handler) {
132.264 + var mustUseAttachEvent = ieVersion && eventsThatMustBeRegisteredUsingAttachEvent[eventType];
132.265 + if (!mustUseAttachEvent && typeof jQuery != "undefined") {
132.266 + if (isClickOnCheckableElement(element, eventType)) {
132.267 + // For click events on checkboxes, jQuery interferes with the event handling in an awkward way:
132.268 + // it toggles the element checked state *after* the click event handlers run, whereas native
132.269 + // click events toggle the checked state *before* the event handler.
132.270 + // Fix this by intecepting the handler and applying the correct checkedness before it runs.
132.271 + var originalHandler = handler;
132.272 + handler = function(event, eventData) {
132.273 + var jQuerySuppliedCheckedState = this.checked;
132.274 + if (eventData)
132.275 + this.checked = eventData.checkedStateBeforeEvent !== true;
132.276 + originalHandler.call(this, event);
132.277 + this.checked = jQuerySuppliedCheckedState; // Restore the state jQuery applied
132.278 + };
132.279 + }
132.280 + jQuery(element)['bind'](eventType, handler);
132.281 + } else if (!mustUseAttachEvent && typeof element.addEventListener == "function")
132.282 + element.addEventListener(eventType, handler, false);
132.283 + else if (typeof element.attachEvent != "undefined")
132.284 + element.attachEvent("on" + eventType, function (event) {
132.285 + handler.call(element, event);
132.286 + });
132.287 + else
132.288 + throw new Error("Browser doesn't support addEventListener or attachEvent");
132.289 + },
132.290 +
132.291 + triggerEvent: function (element, eventType) {
132.292 + if (!(element && element.nodeType))
132.293 + throw new Error("element must be a DOM node when calling triggerEvent");
132.294 +
132.295 + if (typeof jQuery != "undefined") {
132.296 + var eventData = [];
132.297 + if (isClickOnCheckableElement(element, eventType)) {
132.298 + // Work around the jQuery "click events on checkboxes" issue described above by storing the original checked state before triggering the handler
132.299 + eventData.push({ checkedStateBeforeEvent: element.checked });
132.300 + }
132.301 + jQuery(element)['trigger'](eventType, eventData);
132.302 + } else if (typeof document.createEvent == "function") {
132.303 + if (typeof element.dispatchEvent == "function") {
132.304 + var eventCategory = knownEventTypesByEventName[eventType] || "HTMLEvents";
132.305 + var event = document.createEvent(eventCategory);
132.306 + event.initEvent(eventType, true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, element);
132.307 + element.dispatchEvent(event);
132.308 + }
132.309 + else
132.310 + throw new Error("The supplied element doesn't support dispatchEvent");
132.311 + } else if (typeof element.fireEvent != "undefined") {
132.312 + // Unlike other browsers, IE doesn't change the checked state of checkboxes/radiobuttons when you trigger their "click" event
132.313 + // so to make it consistent, we'll do it manually here
132.314 + if (isClickOnCheckableElement(element, eventType))
132.315 + element.checked = element.checked !== true;
132.316 + element.fireEvent("on" + eventType);
132.317 + }
132.318 + else
132.319 + throw new Error("Browser doesn't support triggering events");
132.320 + },
132.321 +
132.322 + unwrapObservable: function (value) {
132.323 + return ko.isObservable(value) ? value() : value;
132.324 + },
132.325 +
132.326 + peekObservable: function (value) {
132.327 + return ko.isObservable(value) ? value.peek() : value;
132.328 + },
132.329 +
132.330 + toggleDomNodeCssClass: function (node, classNames, shouldHaveClass) {
132.331 + if (classNames) {
132.332 + var cssClassNameRegex = /[\w-]+/g,
132.333 + currentClassNames = node.className.match(cssClassNameRegex) || [];
132.334 + ko.utils.arrayForEach(classNames.match(cssClassNameRegex), function(className) {
132.335 + var indexOfClass = ko.utils.arrayIndexOf(currentClassNames, className);
132.336 + if (indexOfClass >= 0) {
132.337 + if (!shouldHaveClass)
132.338 + currentClassNames.splice(indexOfClass, 1);
132.339 + } else {
132.340 + if (shouldHaveClass)
132.341 + currentClassNames.push(className);
132.342 + }
132.343 + });
132.344 + node.className = currentClassNames.join(" ");
132.345 + }
132.346 + },
132.347 +
132.348 + setTextContent: function(element, textContent) {
132.349 + var value = ko.utils.unwrapObservable(textContent);
132.350 + if ((value === null) || (value === undefined))
132.351 + value = "";
132.352 +
132.353 + if (element.nodeType === 3) {
132.354 + element.data = value;
132.355 + } else {
132.356 + // We need there to be exactly one child: a text node.
132.357 + // If there are no children, more than one, or if it's not a text node,
132.358 + // we'll clear everything and create a single text node.
132.359 + var innerTextNode = ko.virtualElements.firstChild(element);
132.360 + if (!innerTextNode || innerTextNode.nodeType != 3 || ko.virtualElements.nextSibling(innerTextNode)) {
132.361 + ko.virtualElements.setDomNodeChildren(element, [document.createTextNode(value)]);
132.362 + } else {
132.363 + innerTextNode.data = value;
132.364 + }
132.365 +
132.366 + ko.utils.forceRefresh(element);
132.367 + }
132.368 + },
132.369 +
132.370 + setElementName: function(element, name) {
132.371 + element.name = name;
132.372 +
132.373 + // Workaround IE 6/7 issue
132.374 + // - https://github.com/SteveSanderson/knockout/issues/197
132.375 + // - http://www.matts411.com/post/setting_the_name_attribute_in_ie_dom/
132.376 + if (ieVersion <= 7) {
132.377 + try {
132.378 + element.mergeAttributes(document.createElement("<input name='" + element.name + "'/>"), false);
132.379 + }
132.380 + catch(e) {} // For IE9 with doc mode "IE9 Standards" and browser mode "IE9 Compatibility View"
132.381 + }
132.382 + },
132.383 +
132.384 + forceRefresh: function(node) {
132.385 + // Workaround for an IE9 rendering bug - https://github.com/SteveSanderson/knockout/issues/209
132.386 + if (ieVersion >= 9) {
132.387 + // For text nodes and comment nodes (most likely virtual elements), we will have to refresh the container
132.388 + var elem = node.nodeType == 1 ? node : node.parentNode;
132.389 + if (elem.style)
132.390 + elem.style.zoom = elem.style.zoom;
132.391 + }
132.392 + },
132.393 +
132.394 + ensureSelectElementIsRenderedCorrectly: function(selectElement) {
132.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.
132.396 + // (See https://github.com/SteveSanderson/knockout/issues/312, http://stackoverflow.com/questions/5908494/select-only-shows-first-char-of-selected-option)
132.397 + if (ieVersion >= 9) {
132.398 + var originalWidth = selectElement.style.width;
132.399 + selectElement.style.width = 0;
132.400 + selectElement.style.width = originalWidth;
132.401 + }
132.402 + },
132.403 +
132.404 + range: function (min, max) {
132.405 + min = ko.utils.unwrapObservable(min);
132.406 + max = ko.utils.unwrapObservable(max);
132.407 + var result = [];
132.408 + for (var i = min; i <= max; i++)
132.409 + result.push(i);
132.410 + return result;
132.411 + },
132.412 +
132.413 + makeArray: function(arrayLikeObject) {
132.414 + var result = [];
132.415 + for (var i = 0, j = arrayLikeObject.length; i < j; i++) {
132.416 + result.push(arrayLikeObject[i]);
132.417 + };
132.418 + return result;
132.419 + },
132.420 +
132.421 + isIe6 : isIe6,
132.422 + isIe7 : isIe7,
132.423 + ieVersion : ieVersion,
132.424 +
132.425 + getFormFields: function(form, fieldName) {
132.426 + var fields = ko.utils.makeArray(form.getElementsByTagName("input")).concat(ko.utils.makeArray(form.getElementsByTagName("textarea")));
132.427 + var isMatchingField = (typeof fieldName == 'string')
132.428 + ? function(field) { return field.name === fieldName }
132.429 + : function(field) { return fieldName.test(field.name) }; // Treat fieldName as regex or object containing predicate
132.430 + var matches = [];
132.431 + for (var i = fields.length - 1; i >= 0; i--) {
132.432 + if (isMatchingField(fields[i]))
132.433 + matches.push(fields[i]);
132.434 + };
132.435 + return matches;
132.436 + },
132.437 +
132.438 + parseJson: function (jsonString) {
132.439 + if (typeof jsonString == "string") {
132.440 + jsonString = ko.utils.stringTrim(jsonString);
132.441 + if (jsonString) {
132.442 + if (window.JSON && window.JSON.parse) // Use native parsing where available
132.443 + return window.JSON.parse(jsonString);
132.444 + return (new Function("return " + jsonString))(); // Fallback on less safe parsing for older browsers
132.445 + }
132.446 + }
132.447 + return null;
132.448 + },
132.449 +
132.450 + stringifyJson: function (data, replacer, space) { // replacer and space are optional
132.451 + if ((typeof JSON == "undefined") || (typeof JSON.stringify == "undefined"))
132.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");
132.453 + return JSON.stringify(ko.utils.unwrapObservable(data), replacer, space);
132.454 + },
132.455 +
132.456 + postJson: function (urlOrForm, data, options) {
132.457 + options = options || {};
132.458 + var params = options['params'] || {};
132.459 + var includeFields = options['includeFields'] || this.fieldsIncludedWithJsonPost;
132.460 + var url = urlOrForm;
132.461 +
132.462 + // If we were given a form, use its 'action' URL and pick out any requested field values
132.463 + if((typeof urlOrForm == 'object') && (ko.utils.tagNameLower(urlOrForm) === "form")) {
132.464 + var originalForm = urlOrForm;
132.465 + url = originalForm.action;
132.466 + for (var i = includeFields.length - 1; i >= 0; i--) {
132.467 + var fields = ko.utils.getFormFields(originalForm, includeFields[i]);
132.468 + for (var j = fields.length - 1; j >= 0; j--)
132.469 + params[fields[j].name] = fields[j].value;
132.470 + }
132.471 + }
132.472 +
132.473 + data = ko.utils.unwrapObservable(data);
132.474 + var form = document.createElement("form");
132.475 + form.style.display = "none";
132.476 + form.action = url;
132.477 + form.method = "post";
132.478 + for (var key in data) {
132.479 + var input = document.createElement("input");
132.480 + input.name = key;
132.481 + input.value = ko.utils.stringifyJson(ko.utils.unwrapObservable(data[key]));
132.482 + form.appendChild(input);
132.483 + }
132.484 + for (var key in params) {
132.485 + var input = document.createElement("input");
132.486 + input.name = key;
132.487 + input.value = params[key];
132.488 + form.appendChild(input);
132.489 + }
132.490 + document.body.appendChild(form);
132.491 + options['submitter'] ? options['submitter'](form) : form.submit();
132.492 + setTimeout(function () { form.parentNode.removeChild(form); }, 0);
132.493 + }
132.494 + }
132.495 +})();
132.496 +
132.497 +ko.exportSymbol('utils', ko.utils);
132.498 +ko.exportSymbol('utils.arrayForEach', ko.utils.arrayForEach);
132.499 +ko.exportSymbol('utils.arrayFirst', ko.utils.arrayFirst);
132.500 +ko.exportSymbol('utils.arrayFilter', ko.utils.arrayFilter);
132.501 +ko.exportSymbol('utils.arrayGetDistinctValues', ko.utils.arrayGetDistinctValues);
132.502 +ko.exportSymbol('utils.arrayIndexOf', ko.utils.arrayIndexOf);
132.503 +ko.exportSymbol('utils.arrayMap', ko.utils.arrayMap);
132.504 +ko.exportSymbol('utils.arrayPushAll', ko.utils.arrayPushAll);
132.505 +ko.exportSymbol('utils.arrayRemoveItem', ko.utils.arrayRemoveItem);
132.506 +ko.exportSymbol('utils.extend', ko.utils.extend);
132.507 +ko.exportSymbol('utils.fieldsIncludedWithJsonPost', ko.utils.fieldsIncludedWithJsonPost);
132.508 +ko.exportSymbol('utils.getFormFields', ko.utils.getFormFields);
132.509 +ko.exportSymbol('utils.peekObservable', ko.utils.peekObservable);
132.510 +ko.exportSymbol('utils.postJson', ko.utils.postJson);
132.511 +ko.exportSymbol('utils.parseJson', ko.utils.parseJson);
132.512 +ko.exportSymbol('utils.registerEventHandler', ko.utils.registerEventHandler);
132.513 +ko.exportSymbol('utils.stringifyJson', ko.utils.stringifyJson);
132.514 +ko.exportSymbol('utils.range', ko.utils.range);
132.515 +ko.exportSymbol('utils.toggleDomNodeCssClass', ko.utils.toggleDomNodeCssClass);
132.516 +ko.exportSymbol('utils.triggerEvent', ko.utils.triggerEvent);
132.517 +ko.exportSymbol('utils.unwrapObservable', ko.utils.unwrapObservable);
132.518 +
132.519 +if (!Function.prototype['bind']) {
132.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)
132.521 + // In case the browser doesn't implement it natively, provide a JavaScript implementation. This implementation is based on the one in prototype.js
132.522 + Function.prototype['bind'] = function (object) {
132.523 + var originalFunction = this, args = Array.prototype.slice.call(arguments), object = args.shift();
132.524 + return function () {
132.525 + return originalFunction.apply(object, args.concat(Array.prototype.slice.call(arguments)));
132.526 + };
132.527 + };
132.528 +}
132.529 +
132.530 +ko.utils.domData = new (function () {
132.531 + var uniqueId = 0;
132.532 + var dataStoreKeyExpandoPropertyName = "__ko__" + (new Date).getTime();
132.533 + var dataStore = {};
132.534 + return {
132.535 + get: function (node, key) {
132.536 + var allDataForNode = ko.utils.domData.getAll(node, false);
132.537 + return allDataForNode === undefined ? undefined : allDataForNode[key];
132.538 + },
132.539 + set: function (node, key, value) {
132.540 + if (value === undefined) {
132.541 + // Make sure we don't actually create a new domData key if we are actually deleting a value
132.542 + if (ko.utils.domData.getAll(node, false) === undefined)
132.543 + return;
132.544 + }
132.545 + var allDataForNode = ko.utils.domData.getAll(node, true);
132.546 + allDataForNode[key] = value;
132.547 + },
132.548 + getAll: function (node, createIfNotFound) {
132.549 + var dataStoreKey = node[dataStoreKeyExpandoPropertyName];
132.550 + var hasExistingDataStore = dataStoreKey && (dataStoreKey !== "null") && dataStore[dataStoreKey];
132.551 + if (!hasExistingDataStore) {
132.552 + if (!createIfNotFound)
132.553 + return undefined;
132.554 + dataStoreKey = node[dataStoreKeyExpandoPropertyName] = "ko" + uniqueId++;
132.555 + dataStore[dataStoreKey] = {};
132.556 + }
132.557 + return dataStore[dataStoreKey];
132.558 + },
132.559 + clear: function (node) {
132.560 + var dataStoreKey = node[dataStoreKeyExpandoPropertyName];
132.561 + if (dataStoreKey) {
132.562 + delete dataStore[dataStoreKey];
132.563 + node[dataStoreKeyExpandoPropertyName] = null;
132.564 + return true; // Exposing "did clean" flag purely so specs can infer whether things have been cleaned up as intended
132.565 + }
132.566 + return false;
132.567 + }
132.568 + }
132.569 +})();
132.570 +
132.571 +ko.exportSymbol('utils.domData', ko.utils.domData);
132.572 +ko.exportSymbol('utils.domData.clear', ko.utils.domData.clear); // Exporting only so specs can clear up after themselves fully
132.573 +
132.574 +ko.utils.domNodeDisposal = new (function () {
132.575 + var domDataKey = "__ko_domNodeDisposal__" + (new Date).getTime();
132.576 + var cleanableNodeTypes = { 1: true, 8: true, 9: true }; // Element, Comment, Document
132.577 + var cleanableNodeTypesWithDescendants = { 1: true, 9: true }; // Element, Document
132.578 +
132.579 + function getDisposeCallbacksCollection(node, createIfNotFound) {
132.580 + var allDisposeCallbacks = ko.utils.domData.get(node, domDataKey);
132.581 + if ((allDisposeCallbacks === undefined) && createIfNotFound) {
132.582 + allDisposeCallbacks = [];
132.583 + ko.utils.domData.set(node, domDataKey, allDisposeCallbacks);
132.584 + }
132.585 + return allDisposeCallbacks;
132.586 + }
132.587 + function destroyCallbacksCollection(node) {
132.588 + ko.utils.domData.set(node, domDataKey, undefined);
132.589 + }
132.590 +
132.591 + function cleanSingleNode(node) {
132.592 + // Run all the dispose callbacks
132.593 + var callbacks = getDisposeCallbacksCollection(node, false);
132.594 + if (callbacks) {
132.595 + callbacks = callbacks.slice(0); // Clone, as the array may be modified during iteration (typically, callbacks will remove themselves)
132.596 + for (var i = 0; i < callbacks.length; i++)
132.597 + callbacks[i](node);
132.598 + }
132.599 +
132.600 + // Also erase the DOM data
132.601 + ko.utils.domData.clear(node);
132.602 +
132.603 + // Special support for jQuery here because it's so commonly used.
132.604 + // Many jQuery plugins (including jquery.tmpl) store data using jQuery's equivalent of domData
132.605 + // so notify it to tear down any resources associated with the node & descendants here.
132.606 + if ((typeof jQuery == "function") && (typeof jQuery['cleanData'] == "function"))
132.607 + jQuery['cleanData']([node]);
132.608 +
132.609 + // Also clear any immediate-child comment nodes, as these wouldn't have been found by
132.610 + // node.getElementsByTagName("*") in cleanNode() (comment nodes aren't elements)
132.611 + if (cleanableNodeTypesWithDescendants[node.nodeType])
132.612 + cleanImmediateCommentTypeChildren(node);
132.613 + }
132.614 +
132.615 + function cleanImmediateCommentTypeChildren(nodeWithChildren) {
132.616 + var child, nextChild = nodeWithChildren.firstChild;
132.617 + while (child = nextChild) {
132.618 + nextChild = child.nextSibling;
132.619 + if (child.nodeType === 8)
132.620 + cleanSingleNode(child);
132.621 + }
132.622 + }
132.623 +
132.624 + return {
132.625 + addDisposeCallback : function(node, callback) {
132.626 + if (typeof callback != "function")
132.627 + throw new Error("Callback must be a function");
132.628 + getDisposeCallbacksCollection(node, true).push(callback);
132.629 + },
132.630 +
132.631 + removeDisposeCallback : function(node, callback) {
132.632 + var callbacksCollection = getDisposeCallbacksCollection(node, false);
132.633 + if (callbacksCollection) {
132.634 + ko.utils.arrayRemoveItem(callbacksCollection, callback);
132.635 + if (callbacksCollection.length == 0)
132.636 + destroyCallbacksCollection(node);
132.637 + }
132.638 + },
132.639 +
132.640 + cleanNode : function(node) {
132.641 + // First clean this node, where applicable
132.642 + if (cleanableNodeTypes[node.nodeType]) {
132.643 + cleanSingleNode(node);
132.644 +
132.645 + // ... then its descendants, where applicable
132.646 + if (cleanableNodeTypesWithDescendants[node.nodeType]) {
132.647 + // Clone the descendants list in case it changes during iteration
132.648 + var descendants = [];
132.649 + ko.utils.arrayPushAll(descendants, node.getElementsByTagName("*"));
132.650 + for (var i = 0, j = descendants.length; i < j; i++)
132.651 + cleanSingleNode(descendants[i]);
132.652 + }
132.653 + }
132.654 + return node;
132.655 + },
132.656 +
132.657 + removeNode : function(node) {
132.658 + ko.cleanNode(node);
132.659 + if (node.parentNode)
132.660 + node.parentNode.removeChild(node);
132.661 + }
132.662 + }
132.663 +})();
132.664 +ko.cleanNode = ko.utils.domNodeDisposal.cleanNode; // Shorthand name for convenience
132.665 +ko.removeNode = ko.utils.domNodeDisposal.removeNode; // Shorthand name for convenience
132.666 +ko.exportSymbol('cleanNode', ko.cleanNode);
132.667 +ko.exportSymbol('removeNode', ko.removeNode);
132.668 +ko.exportSymbol('utils.domNodeDisposal', ko.utils.domNodeDisposal);
132.669 +ko.exportSymbol('utils.domNodeDisposal.addDisposeCallback', ko.utils.domNodeDisposal.addDisposeCallback);
132.670 +ko.exportSymbol('utils.domNodeDisposal.removeDisposeCallback', ko.utils.domNodeDisposal.removeDisposeCallback);
132.671 +(function () {
132.672 + var leadingCommentRegex = /^(\s*)<!--(.*?)-->/;
132.673 +
132.674 + function simpleHtmlParse(html) {
132.675 + // Based on jQuery's "clean" function, but only accounting for table-related elements.
132.676 + // If you have referenced jQuery, this won't be used anyway - KO will use jQuery's "clean" function directly
132.677 +
132.678 + // Note that there's still an issue in IE < 9 whereby it will discard comment nodes that are the first child of
132.679 + // a descendant node. For example: "<div><!-- mycomment -->abc</div>" will get parsed as "<div>abc</div>"
132.680 + // This won't affect anyone who has referenced jQuery, and there's always the workaround of inserting a dummy node
132.681 + // (possibly a text node) in front of the comment. So, KO does not attempt to workaround this IE issue automatically at present.
132.682 +
132.683 + // Trim whitespace, otherwise indexOf won't work as expected
132.684 + var tags = ko.utils.stringTrim(html).toLowerCase(), div = document.createElement("div");
132.685 +
132.686 + // Finds the first match from the left column, and returns the corresponding "wrap" data from the right column
132.687 + var wrap = tags.match(/^<(thead|tbody|tfoot)/) && [1, "<table>", "</table>"] ||
132.688 + !tags.indexOf("<tr") && [2, "<table><tbody>", "</tbody></table>"] ||
132.689 + (!tags.indexOf("<td") || !tags.indexOf("<th")) && [3, "<table><tbody><tr>", "</tr></tbody></table>"] ||
132.690 + /* anything else */ [0, "", ""];
132.691 +
132.692 + // Go to html and back, then peel off extra wrappers
132.693 + // Note that we always prefix with some dummy text, because otherwise, IE<9 will strip out leading comment nodes in descendants. Total madness.
132.694 + var markup = "ignored<div>" + wrap[1] + html + wrap[2] + "</div>";
132.695 + if (typeof window['innerShiv'] == "function") {
132.696 + div.appendChild(window['innerShiv'](markup));
132.697 + } else {
132.698 + div.innerHTML = markup;
132.699 + }
132.700 +
132.701 + // Move to the right depth
132.702 + while (wrap[0]--)
132.703 + div = div.lastChild;
132.704 +
132.705 + return ko.utils.makeArray(div.lastChild.childNodes);
132.706 + }
132.707 +
132.708 + function jQueryHtmlParse(html) {
132.709 + // jQuery's "parseHTML" function was introduced in jQuery 1.8.0 and is a documented public API.
132.710 + if (jQuery['parseHTML']) {
132.711 + return jQuery['parseHTML'](html);
132.712 + } else {
132.713 + // For jQuery < 1.8.0, we fall back on the undocumented internal "clean" function.
132.714 + var elems = jQuery['clean']([html]);
132.715 +
132.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.
132.717 + // Unfortunately, it never clears the dummy parent nodes from the document fragment, so it leaks memory over time.
132.718 + // Fix this by finding the top-most dummy parent element, and detaching it from its owner fragment.
132.719 + if (elems && elems[0]) {
132.720 + // Find the top-most parent element that's a direct child of a document fragment
132.721 + var elem = elems[0];
132.722 + while (elem.parentNode && elem.parentNode.nodeType !== 11 /* i.e., DocumentFragment */)
132.723 + elem = elem.parentNode;
132.724 + // ... then detach it
132.725 + if (elem.parentNode)
132.726 + elem.parentNode.removeChild(elem);
132.727 + }
132.728 +
132.729 + return elems;
132.730 + }
132.731 + }
132.732 +
132.733 + ko.utils.parseHtmlFragment = function(html) {
132.734 + return typeof jQuery != 'undefined' ? jQueryHtmlParse(html) // As below, benefit from jQuery's optimisations where possible
132.735 + : simpleHtmlParse(html); // ... otherwise, this simple logic will do in most common cases.
132.736 + };
132.737 +
132.738 + ko.utils.setHtml = function(node, html) {
132.739 + ko.utils.emptyDomNode(node);
132.740 +
132.741 + // There's no legitimate reason to display a stringified observable without unwrapping it, so we'll unwrap it
132.742 + html = ko.utils.unwrapObservable(html);
132.743 +
132.744 + if ((html !== null) && (html !== undefined)) {
132.745 + if (typeof html != 'string')
132.746 + html = html.toString();
132.747 +
132.748 + // jQuery contains a lot of sophisticated code to parse arbitrary HTML fragments,
132.749 + // for example <tr> elements which are not normally allowed to exist on their own.
132.750 + // If you've referenced jQuery we'll use that rather than duplicating its code.
132.751 + if (typeof jQuery != 'undefined') {
132.752 + jQuery(node)['html'](html);
132.753 + } else {
132.754 + // ... otherwise, use KO's own parsing logic.
132.755 + var parsedNodes = ko.utils.parseHtmlFragment(html);
132.756 + for (var i = 0; i < parsedNodes.length; i++)
132.757 + node.appendChild(parsedNodes[i]);
132.758 + }
132.759 + }
132.760 + };
132.761 +})();
132.762 +
132.763 +ko.exportSymbol('utils.parseHtmlFragment', ko.utils.parseHtmlFragment);
132.764 +ko.exportSymbol('utils.setHtml', ko.utils.setHtml);
132.765 +
132.766 +ko.memoization = (function () {
132.767 + var memos = {};
132.768 +
132.769 + function randomMax8HexChars() {
132.770 + return (((1 + Math.random()) * 0x100000000) | 0).toString(16).substring(1);
132.771 + }
132.772 + function generateRandomId() {
132.773 + return randomMax8HexChars() + randomMax8HexChars();
132.774 + }
132.775 + function findMemoNodes(rootNode, appendToArray) {
132.776 + if (!rootNode)
132.777 + return;
132.778 + if (rootNode.nodeType == 8) {
132.779 + var memoId = ko.memoization.parseMemoText(rootNode.nodeValue);
132.780 + if (memoId != null)
132.781 + appendToArray.push({ domNode: rootNode, memoId: memoId });
132.782 + } else if (rootNode.nodeType == 1) {
132.783 + for (var i = 0, childNodes = rootNode.childNodes, j = childNodes.length; i < j; i++)
132.784 + findMemoNodes(childNodes[i], appendToArray);
132.785 + }
132.786 + }
132.787 +
132.788 + return {
132.789 + memoize: function (callback) {
132.790 + if (typeof callback != "function")
132.791 + throw new Error("You can only pass a function to ko.memoization.memoize()");
132.792 + var memoId = generateRandomId();
132.793 + memos[memoId] = callback;
132.794 + return "<!--[ko_memo:" + memoId + "]-->";
132.795 + },
132.796 +
132.797 + unmemoize: function (memoId, callbackParams) {
132.798 + var callback = memos[memoId];
132.799 + if (callback === undefined)
132.800 + throw new Error("Couldn't find any memo with ID " + memoId + ". Perhaps it's already been unmemoized.");
132.801 + try {
132.802 + callback.apply(null, callbackParams || []);
132.803 + return true;
132.804 + }
132.805 + finally { delete memos[memoId]; }
132.806 + },
132.807 +
132.808 + unmemoizeDomNodeAndDescendants: function (domNode, extraCallbackParamsArray) {
132.809 + var memos = [];
132.810 + findMemoNodes(domNode, memos);
132.811 + for (var i = 0, j = memos.length; i < j; i++) {
132.812 + var node = memos[i].domNode;
132.813 + var combinedParams = [node];
132.814 + if (extraCallbackParamsArray)
132.815 + ko.utils.arrayPushAll(combinedParams, extraCallbackParamsArray);
132.816 + ko.memoization.unmemoize(memos[i].memoId, combinedParams);
132.817 + node.nodeValue = ""; // Neuter this node so we don't try to unmemoize it again
132.818 + if (node.parentNode)
132.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)
132.820 + }
132.821 + },
132.822 +
132.823 + parseMemoText: function (memoText) {
132.824 + var match = memoText.match(/^\[ko_memo\:(.*?)\]$/);
132.825 + return match ? match[1] : null;
132.826 + }
132.827 + };
132.828 +})();
132.829 +
132.830 +ko.exportSymbol('memoization', ko.memoization);
132.831 +ko.exportSymbol('memoization.memoize', ko.memoization.memoize);
132.832 +ko.exportSymbol('memoization.unmemoize', ko.memoization.unmemoize);
132.833 +ko.exportSymbol('memoization.parseMemoText', ko.memoization.parseMemoText);
132.834 +ko.exportSymbol('memoization.unmemoizeDomNodeAndDescendants', ko.memoization.unmemoizeDomNodeAndDescendants);
132.835 +ko.extenders = {
132.836 + 'throttle': function(target, timeout) {
132.837 + // Throttling means two things:
132.838 +
132.839 + // (1) For dependent observables, we throttle *evaluations* so that, no matter how fast its dependencies
132.840 + // notify updates, the target doesn't re-evaluate (and hence doesn't notify) faster than a certain rate
132.841 + target['throttleEvaluation'] = timeout;
132.842 +
132.843 + // (2) For writable targets (observables, or writable dependent observables), we throttle *writes*
132.844 + // so the target cannot change value synchronously or faster than a certain rate
132.845 + var writeTimeoutInstance = null;
132.846 + return ko.dependentObservable({
132.847 + 'read': target,
132.848 + 'write': function(value) {
132.849 + clearTimeout(writeTimeoutInstance);
132.850 + writeTimeoutInstance = setTimeout(function() {
132.851 + target(value);
132.852 + }, timeout);
132.853 + }
132.854 + });
132.855 + },
132.856 +
132.857 + 'notify': function(target, notifyWhen) {
132.858 + target["equalityComparer"] = notifyWhen == "always"
132.859 + ? function() { return false } // Treat all values as not equal
132.860 + : ko.observable["fn"]["equalityComparer"];
132.861 + return target;
132.862 + }
132.863 +};
132.864 +
132.865 +function applyExtenders(requestedExtenders) {
132.866 + var target = this;
132.867 + if (requestedExtenders) {
132.868 + for (var key in requestedExtenders) {
132.869 + var extenderHandler = ko.extenders[key];
132.870 + if (typeof extenderHandler == 'function') {
132.871 + target = extenderHandler(target, requestedExtenders[key]);
132.872 + }
132.873 + }
132.874 + }
132.875 + return target;
132.876 +}
132.877 +
132.878 +ko.exportSymbol('extenders', ko.extenders);
132.879 +
132.880 +ko.subscription = function (target, callback, disposeCallback) {
132.881 + this.target = target;
132.882 + this.callback = callback;
132.883 + this.disposeCallback = disposeCallback;
132.884 + ko.exportProperty(this, 'dispose', this.dispose);
132.885 +};
132.886 +ko.subscription.prototype.dispose = function () {
132.887 + this.isDisposed = true;
132.888 + this.disposeCallback();
132.889 +};
132.890 +
132.891 +ko.subscribable = function () {
132.892 + this._subscriptions = {};
132.893 +
132.894 + ko.utils.extend(this, ko.subscribable['fn']);
132.895 + ko.exportProperty(this, 'subscribe', this.subscribe);
132.896 + ko.exportProperty(this, 'extend', this.extend);
132.897 + ko.exportProperty(this, 'getSubscriptionsCount', this.getSubscriptionsCount);
132.898 +}
132.899 +
132.900 +var defaultEvent = "change";
132.901 +
132.902 +ko.subscribable['fn'] = {
132.903 + subscribe: function (callback, callbackTarget, event) {
132.904 + event = event || defaultEvent;
132.905 + var boundCallback = callbackTarget ? callback.bind(callbackTarget) : callback;
132.906 +
132.907 + var subscription = new ko.subscription(this, boundCallback, function () {
132.908 + ko.utils.arrayRemoveItem(this._subscriptions[event], subscription);
132.909 + }.bind(this));
132.910 +
132.911 + if (!this._subscriptions[event])
132.912 + this._subscriptions[event] = [];
132.913 + this._subscriptions[event].push(subscription);
132.914 + return subscription;
132.915 + },
132.916 +
132.917 + "notifySubscribers": function (valueToNotify, event) {
132.918 + event = event || defaultEvent;
132.919 + if (this._subscriptions[event]) {
132.920 + ko.dependencyDetection.ignore(function() {
132.921 + ko.utils.arrayForEach(this._subscriptions[event].slice(0), function (subscription) {
132.922 + // In case a subscription was disposed during the arrayForEach cycle, check
132.923 + // for isDisposed on each subscription before invoking its callback
132.924 + if (subscription && (subscription.isDisposed !== true))
132.925 + subscription.callback(valueToNotify);
132.926 + });
132.927 + }, this);
132.928 + }
132.929 + },
132.930 +
132.931 + getSubscriptionsCount: function () {
132.932 + var total = 0;
132.933 + for (var eventName in this._subscriptions) {
132.934 + if (this._subscriptions.hasOwnProperty(eventName))
132.935 + total += this._subscriptions[eventName].length;
132.936 + }
132.937 + return total;
132.938 + },
132.939 +
132.940 + extend: applyExtenders
132.941 +};
132.942 +
132.943 +
132.944 +ko.isSubscribable = function (instance) {
132.945 + return typeof instance.subscribe == "function" && typeof instance["notifySubscribers"] == "function";
132.946 +};
132.947 +
132.948 +ko.exportSymbol('subscribable', ko.subscribable);
132.949 +ko.exportSymbol('isSubscribable', ko.isSubscribable);
132.950 +
132.951 +ko.dependencyDetection = (function () {
132.952 + var _frames = [];
132.953 +
132.954 + return {
132.955 + begin: function (callback) {
132.956 + _frames.push({ callback: callback, distinctDependencies:[] });
132.957 + },
132.958 +
132.959 + end: function () {
132.960 + _frames.pop();
132.961 + },
132.962 +
132.963 + registerDependency: function (subscribable) {
132.964 + if (!ko.isSubscribable(subscribable))
132.965 + throw new Error("Only subscribable things can act as dependencies");
132.966 + if (_frames.length > 0) {
132.967 + var topFrame = _frames[_frames.length - 1];
132.968 + if (!topFrame || ko.utils.arrayIndexOf(topFrame.distinctDependencies, subscribable) >= 0)
132.969 + return;
132.970 + topFrame.distinctDependencies.push(subscribable);
132.971 + topFrame.callback(subscribable);
132.972 + }
132.973 + },
132.974 +
132.975 + ignore: function(callback, callbackTarget, callbackArgs) {
132.976 + try {
132.977 + _frames.push(null);
132.978 + return callback.apply(callbackTarget, callbackArgs || []);
132.979 + } finally {
132.980 + _frames.pop();
132.981 + }
132.982 + }
132.983 + };
132.984 +})();
132.985 +var primitiveTypes = { 'undefined':true, 'boolean':true, 'number':true, 'string':true };
132.986 +
132.987 +ko.observable = function (initialValue) {
132.988 + var _latestValue = initialValue;
132.989 +
132.990 + function observable() {
132.991 + if (arguments.length > 0) {
132.992 + // Write
132.993 +
132.994 + // Ignore writes if the value hasn't changed
132.995 + if ((!observable['equalityComparer']) || !observable['equalityComparer'](_latestValue, arguments[0])) {
132.996 + observable.valueWillMutate();
132.997 + _latestValue = arguments[0];
132.998 + if (DEBUG) observable._latestValue = _latestValue;
132.999 + observable.valueHasMutated();
132.1000 + }
132.1001 + return this; // Permits chained assignments
132.1002 + }
132.1003 + else {
132.1004 + // Read
132.1005 + ko.dependencyDetection.registerDependency(observable); // The caller only needs to be notified of changes if they did a "read" operation
132.1006 + return _latestValue;
132.1007 + }
132.1008 + }
132.1009 + if (DEBUG) observable._latestValue = _latestValue;
132.1010 + ko.subscribable.call(observable);
132.1011 + observable.peek = function() { return _latestValue };
132.1012 + observable.valueHasMutated = function () { observable["notifySubscribers"](_latestValue); }
132.1013 + observable.valueWillMutate = function () { observable["notifySubscribers"](_latestValue, "beforeChange"); }
132.1014 + ko.utils.extend(observable, ko.observable['fn']);
132.1015 +
132.1016 + ko.exportProperty(observable, 'peek', observable.peek);
132.1017 + ko.exportProperty(observable, "valueHasMutated", observable.valueHasMutated);
132.1018 + ko.exportProperty(observable, "valueWillMutate", observable.valueWillMutate);
132.1019 +
132.1020 + return observable;
132.1021 +}
132.1022 +
132.1023 +ko.observable['fn'] = {
132.1024 + "equalityComparer": function valuesArePrimitiveAndEqual(a, b) {
132.1025 + var oldValueIsPrimitive = (a === null) || (typeof(a) in primitiveTypes);
132.1026 + return oldValueIsPrimitive ? (a === b) : false;
132.1027 + }
132.1028 +};
132.1029 +
132.1030 +var protoProperty = ko.observable.protoProperty = "__ko_proto__";
132.1031 +ko.observable['fn'][protoProperty] = ko.observable;
132.1032 +
132.1033 +ko.hasPrototype = function(instance, prototype) {
132.1034 + if ((instance === null) || (instance === undefined) || (instance[protoProperty] === undefined)) return false;
132.1035 + if (instance[protoProperty] === prototype) return true;
132.1036 + return ko.hasPrototype(instance[protoProperty], prototype); // Walk the prototype chain
132.1037 +};
132.1038 +
132.1039 +ko.isObservable = function (instance) {
132.1040 + return ko.hasPrototype(instance, ko.observable);
132.1041 +}
132.1042 +ko.isWriteableObservable = function (instance) {
132.1043 + // Observable
132.1044 + if ((typeof instance == "function") && instance[protoProperty] === ko.observable)
132.1045 + return true;
132.1046 + // Writeable dependent observable
132.1047 + if ((typeof instance == "function") && (instance[protoProperty] === ko.dependentObservable) && (instance.hasWriteFunction))
132.1048 + return true;
132.1049 + // Anything else
132.1050 + return false;
132.1051 +}
132.1052 +
132.1053 +
132.1054 +ko.exportSymbol('observable', ko.observable);
132.1055 +ko.exportSymbol('isObservable', ko.isObservable);
132.1056 +ko.exportSymbol('isWriteableObservable', ko.isWriteableObservable);
132.1057 +ko.observableArray = function (initialValues) {
132.1058 + if (arguments.length == 0) {
132.1059 + // Zero-parameter constructor initializes to empty array
132.1060 + initialValues = [];
132.1061 + }
132.1062 + if ((initialValues !== null) && (initialValues !== undefined) && !('length' in initialValues))
132.1063 + throw new Error("The argument passed when initializing an observable array must be an array, or null, or undefined.");
132.1064 +
132.1065 + var result = ko.observable(initialValues);
132.1066 + ko.utils.extend(result, ko.observableArray['fn']);
132.1067 + return result;
132.1068 +}
132.1069 +
132.1070 +ko.observableArray['fn'] = {
132.1071 + 'remove': function (valueOrPredicate) {
132.1072 + var underlyingArray = this.peek();
132.1073 + var removedValues = [];
132.1074 + var predicate = typeof valueOrPredicate == "function" ? valueOrPredicate : function (value) { return value === valueOrPredicate; };
132.1075 + for (var i = 0; i < underlyingArray.length; i++) {
132.1076 + var value = underlyingArray[i];
132.1077 + if (predicate(value)) {
132.1078 + if (removedValues.length === 0) {
132.1079 + this.valueWillMutate();
132.1080 + }
132.1081 + removedValues.push(value);
132.1082 + underlyingArray.splice(i, 1);
132.1083 + i--;
132.1084 + }
132.1085 + }
132.1086 + if (removedValues.length) {
132.1087 + this.valueHasMutated();
132.1088 + }
132.1089 + return removedValues;
132.1090 + },
132.1091 +
132.1092 + 'removeAll': function (arrayOfValues) {
132.1093 + // If you passed zero args, we remove everything
132.1094 + if (arrayOfValues === undefined) {
132.1095 + var underlyingArray = this.peek();
132.1096 + var allValues = underlyingArray.slice(0);
132.1097 + this.valueWillMutate();
132.1098 + underlyingArray.splice(0, underlyingArray.length);
132.1099 + this.valueHasMutated();
132.1100 + return allValues;
132.1101 + }
132.1102 + // If you passed an arg, we interpret it as an array of entries to remove
132.1103 + if (!arrayOfValues)
132.1104 + return [];
132.1105 + return this['remove'](function (value) {
132.1106 + return ko.utils.arrayIndexOf(arrayOfValues, value) >= 0;
132.1107 + });
132.1108 + },
132.1109 +
132.1110 + 'destroy': function (valueOrPredicate) {
132.1111 + var underlyingArray = this.peek();
132.1112 + var predicate = typeof valueOrPredicate == "function" ? valueOrPredicate : function (value) { return value === valueOrPredicate; };
132.1113 + this.valueWillMutate();
132.1114 + for (var i = underlyingArray.length - 1; i >= 0; i--) {
132.1115 + var value = underlyingArray[i];
132.1116 + if (predicate(value))
132.1117 + underlyingArray[i]["_destroy"] = true;
132.1118 + }
132.1119 + this.valueHasMutated();
132.1120 + },
132.1121 +
132.1122 + 'destroyAll': function (arrayOfValues) {
132.1123 + // If you passed zero args, we destroy everything
132.1124 + if (arrayOfValues === undefined)
132.1125 + return this['destroy'](function() { return true });
132.1126 +
132.1127 + // If you passed an arg, we interpret it as an array of entries to destroy
132.1128 + if (!arrayOfValues)
132.1129 + return [];
132.1130 + return this['destroy'](function (value) {
132.1131 + return ko.utils.arrayIndexOf(arrayOfValues, value) >= 0;
132.1132 + });
132.1133 + },
132.1134 +
132.1135 + 'indexOf': function (item) {
132.1136 + var underlyingArray = this();
132.1137 + return ko.utils.arrayIndexOf(underlyingArray, item);
132.1138 + },
132.1139 +
132.1140 + 'replace': function(oldItem, newItem) {
132.1141 + var index = this['indexOf'](oldItem);
132.1142 + if (index >= 0) {
132.1143 + this.valueWillMutate();
132.1144 + this.peek()[index] = newItem;
132.1145 + this.valueHasMutated();
132.1146 + }
132.1147 + }
132.1148 +}
132.1149 +
132.1150 +// Populate ko.observableArray.fn with read/write functions from native arrays
132.1151 +// Important: Do not add any additional functions here that may reasonably be used to *read* data from the array
132.1152 +// because we'll eval them without causing subscriptions, so ko.computed output could end up getting stale
132.1153 +ko.utils.arrayForEach(["pop", "push", "reverse", "shift", "sort", "splice", "unshift"], function (methodName) {
132.1154 + ko.observableArray['fn'][methodName] = function () {
132.1155 + // Use "peek" to avoid creating a subscription in any computed that we're executing in the context of
132.1156 + // (for consistency with mutating regular observables)
132.1157 + var underlyingArray = this.peek();
132.1158 + this.valueWillMutate();
132.1159 + var methodCallResult = underlyingArray[methodName].apply(underlyingArray, arguments);
132.1160 + this.valueHasMutated();
132.1161 + return methodCallResult;
132.1162 + };
132.1163 +});
132.1164 +
132.1165 +// Populate ko.observableArray.fn with read-only functions from native arrays
132.1166 +ko.utils.arrayForEach(["slice"], function (methodName) {
132.1167 + ko.observableArray['fn'][methodName] = function () {
132.1168 + var underlyingArray = this();
132.1169 + return underlyingArray[methodName].apply(underlyingArray, arguments);
132.1170 + };
132.1171 +});
132.1172 +
132.1173 +ko.exportSymbol('observableArray', ko.observableArray);
132.1174 +ko.dependentObservable = function (evaluatorFunctionOrOptions, evaluatorFunctionTarget, options) {
132.1175 + var _latestValue,
132.1176 + _hasBeenEvaluated = false,
132.1177 + _isBeingEvaluated = false,
132.1178 + readFunction = evaluatorFunctionOrOptions;
132.1179 +
132.1180 + if (readFunction && typeof readFunction == "object") {
132.1181 + // Single-parameter syntax - everything is on this "options" param
132.1182 + options = readFunction;
132.1183 + readFunction = options["read"];
132.1184 + } else {
132.1185 + // Multi-parameter syntax - construct the options according to the params passed
132.1186 + options = options || {};
132.1187 + if (!readFunction)
132.1188 + readFunction = options["read"];
132.1189 + }
132.1190 + if (typeof readFunction != "function")
132.1191 + throw new Error("Pass a function that returns the value of the ko.computed");
132.1192 +
132.1193 + function addSubscriptionToDependency(subscribable) {
132.1194 + _subscriptionsToDependencies.push(subscribable.subscribe(evaluatePossiblyAsync));
132.1195 + }
132.1196 +
132.1197 + function disposeAllSubscriptionsToDependencies() {
132.1198 + ko.utils.arrayForEach(_subscriptionsToDependencies, function (subscription) {
132.1199 + subscription.dispose();
132.1200 + });
132.1201 + _subscriptionsToDependencies = [];
132.1202 + }
132.1203 +
132.1204 + function evaluatePossiblyAsync() {
132.1205 + var throttleEvaluationTimeout = dependentObservable['throttleEvaluation'];
132.1206 + if (throttleEvaluationTimeout && throttleEvaluationTimeout >= 0) {
132.1207 + clearTimeout(evaluationTimeoutInstance);
132.1208 + evaluationTimeoutInstance = setTimeout(evaluateImmediate, throttleEvaluationTimeout);
132.1209 + } else
132.1210 + evaluateImmediate();
132.1211 + }
132.1212 +
132.1213 + function evaluateImmediate() {
132.1214 + if (_isBeingEvaluated) {
132.1215 + // If the evaluation of a ko.computed causes side effects, it's possible that it will trigger its own re-evaluation.
132.1216 + // This is not desirable (it's hard for a developer to realise a chain of dependencies might cause this, and they almost
132.1217 + // certainly didn't intend infinite re-evaluations). So, for predictability, we simply prevent ko.computeds from causing
132.1218 + // their own re-evaluation. Further discussion at https://github.com/SteveSanderson/knockout/pull/387
132.1219 + return;
132.1220 + }
132.1221 +
132.1222 + // Don't dispose on first evaluation, because the "disposeWhen" callback might
132.1223 + // e.g., dispose when the associated DOM element isn't in the doc, and it's not
132.1224 + // going to be in the doc until *after* the first evaluation
132.1225 + if (_hasBeenEvaluated && disposeWhen()) {
132.1226 + dispose();
132.1227 + return;
132.1228 + }
132.1229 +
132.1230 + _isBeingEvaluated = true;
132.1231 + try {
132.1232 + // Initially, we assume that none of the subscriptions are still being used (i.e., all are candidates for disposal).
132.1233 + // Then, during evaluation, we cross off any that are in fact still being used.
132.1234 + var disposalCandidates = ko.utils.arrayMap(_subscriptionsToDependencies, function(item) {return item.target;});
132.1235 +
132.1236 + ko.dependencyDetection.begin(function(subscribable) {
132.1237 + var inOld;
132.1238 + if ((inOld = ko.utils.arrayIndexOf(disposalCandidates, subscribable)) >= 0)
132.1239 + disposalCandidates[inOld] = undefined; // Don't want to dispose this subscription, as it's still being used
132.1240 + else
132.1241 + addSubscriptionToDependency(subscribable); // Brand new subscription - add it
132.1242 + });
132.1243 +
132.1244 + var newValue = readFunction.call(evaluatorFunctionTarget);
132.1245 +
132.1246 + // For each subscription no longer being used, remove it from the active subscriptions list and dispose it
132.1247 + for (var i = disposalCandidates.length - 1; i >= 0; i--) {
132.1248 + if (disposalCandidates[i])
132.1249 + _subscriptionsToDependencies.splice(i, 1)[0].dispose();
132.1250 + }
132.1251 + _hasBeenEvaluated = true;
132.1252 +
132.1253 + dependentObservable["notifySubscribers"](_latestValue, "beforeChange");
132.1254 + _latestValue = newValue;
132.1255 + if (DEBUG) dependentObservable._latestValue = _latestValue;
132.1256 + } finally {
132.1257 + ko.dependencyDetection.end();
132.1258 + }
132.1259 +
132.1260 + dependentObservable["notifySubscribers"](_latestValue);
132.1261 + _isBeingEvaluated = false;
132.1262 + if (!_subscriptionsToDependencies.length)
132.1263 + dispose();
132.1264 + }
132.1265 +
132.1266 + function dependentObservable() {
132.1267 + if (arguments.length > 0) {
132.1268 + if (typeof writeFunction === "function") {
132.1269 + // Writing a value
132.1270 + writeFunction.apply(evaluatorFunctionTarget, arguments);
132.1271 + } else {
132.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.");
132.1273 + }
132.1274 + return this; // Permits chained assignments
132.1275 + } else {
132.1276 + // Reading the value
132.1277 + if (!_hasBeenEvaluated)
132.1278 + evaluateImmediate();
132.1279 + ko.dependencyDetection.registerDependency(dependentObservable);
132.1280 + return _latestValue;
132.1281 + }
132.1282 + }
132.1283 +
132.1284 + function peek() {
132.1285 + if (!_hasBeenEvaluated)
132.1286 + evaluateImmediate();
132.1287 + return _latestValue;
132.1288 + }
132.1289 +
132.1290 + function isActive() {
132.1291 + return !_hasBeenEvaluated || _subscriptionsToDependencies.length > 0;
132.1292 + }
132.1293 +
132.1294 + // By here, "options" is always non-null
132.1295 + var writeFunction = options["write"],
132.1296 + disposeWhenNodeIsRemoved = options["disposeWhenNodeIsRemoved"] || options.disposeWhenNodeIsRemoved || null,
132.1297 + disposeWhen = options["disposeWhen"] || options.disposeWhen || function() { return false; },
132.1298 + dispose = disposeAllSubscriptionsToDependencies,
132.1299 + _subscriptionsToDependencies = [],
132.1300 + evaluationTimeoutInstance = null;
132.1301 +
132.1302 + if (!evaluatorFunctionTarget)
132.1303 + evaluatorFunctionTarget = options["owner"];
132.1304 +
132.1305 + dependentObservable.peek = peek;
132.1306 + dependentObservable.getDependenciesCount = function () { return _subscriptionsToDependencies.length; };
132.1307 + dependentObservable.hasWriteFunction = typeof options["write"] === "function";
132.1308 + dependentObservable.dispose = function () { dispose(); };
132.1309 + dependentObservable.isActive = isActive;
132.1310 + dependentObservable.valueHasMutated = function() {
132.1311 + _hasBeenEvaluated = false;
132.1312 + evaluateImmediate();
132.1313 + };
132.1314 +
132.1315 + ko.subscribable.call(dependentObservable);
132.1316 + ko.utils.extend(dependentObservable, ko.dependentObservable['fn']);
132.1317 +
132.1318 + ko.exportProperty(dependentObservable, 'peek', dependentObservable.peek);
132.1319 + ko.exportProperty(dependentObservable, 'dispose', dependentObservable.dispose);
132.1320 + ko.exportProperty(dependentObservable, 'isActive', dependentObservable.isActive);
132.1321 + ko.exportProperty(dependentObservable, 'getDependenciesCount', dependentObservable.getDependenciesCount);
132.1322 +
132.1323 + // Evaluate, unless deferEvaluation is true
132.1324 + if (options['deferEvaluation'] !== true)
132.1325 + evaluateImmediate();
132.1326 +
132.1327 + // Build "disposeWhenNodeIsRemoved" and "disposeWhenNodeIsRemovedCallback" option values.
132.1328 + // But skip if isActive is false (there will never be any dependencies to dispose).
132.1329 + // (Note: "disposeWhenNodeIsRemoved" option both proactively disposes as soon as the node is removed using ko.removeNode(),
132.1330 + // plus adds a "disposeWhen" callback that, on each evaluation, disposes if the node was removed by some other means.)
132.1331 + if (disposeWhenNodeIsRemoved && isActive()) {
132.1332 + dispose = function() {
132.1333 + ko.utils.domNodeDisposal.removeDisposeCallback(disposeWhenNodeIsRemoved, arguments.callee);
132.1334 + disposeAllSubscriptionsToDependencies();
132.1335 + };
132.1336 + ko.utils.domNodeDisposal.addDisposeCallback(disposeWhenNodeIsRemoved, dispose);
132.1337 + var existingDisposeWhenFunction = disposeWhen;
132.1338 + disposeWhen = function () {
132.1339 + return !ko.utils.domNodeIsAttachedToDocument(disposeWhenNodeIsRemoved) || existingDisposeWhenFunction();
132.1340 + }
132.1341 + }
132.1342 +
132.1343 + return dependentObservable;
132.1344 +};
132.1345 +
132.1346 +ko.isComputed = function(instance) {
132.1347 + return ko.hasPrototype(instance, ko.dependentObservable);
132.1348 +};
132.1349 +
132.1350 +var protoProp = ko.observable.protoProperty; // == "__ko_proto__"
132.1351 +ko.dependentObservable[protoProp] = ko.observable;
132.1352 +
132.1353 +ko.dependentObservable['fn'] = {};
132.1354 +ko.dependentObservable['fn'][protoProp] = ko.dependentObservable;
132.1355 +
132.1356 +ko.exportSymbol('dependentObservable', ko.dependentObservable);
132.1357 +ko.exportSymbol('computed', ko.dependentObservable); // Make "ko.computed" an alias for "ko.dependentObservable"
132.1358 +ko.exportSymbol('isComputed', ko.isComputed);
132.1359 +
132.1360 +(function() {
132.1361 + var maxNestedObservableDepth = 10; // Escape the (unlikely) pathalogical case where an observable's current value is itself (or similar reference cycle)
132.1362 +
132.1363 + ko.toJS = function(rootObject) {
132.1364 + if (arguments.length == 0)
132.1365 + throw new Error("When calling ko.toJS, pass the object you want to convert.");
132.1366 +
132.1367 + // We just unwrap everything at every level in the object graph
132.1368 + return mapJsObjectGraph(rootObject, function(valueToMap) {
132.1369 + // Loop because an observable's value might in turn be another observable wrapper
132.1370 + for (var i = 0; ko.isObservable(valueToMap) && (i < maxNestedObservableDepth); i++)
132.1371 + valueToMap = valueToMap();
132.1372 + return valueToMap;
132.1373 + });
132.1374 + };
132.1375 +
132.1376 + ko.toJSON = function(rootObject, replacer, space) { // replacer and space are optional
132.1377 + var plainJavaScriptObject = ko.toJS(rootObject);
132.1378 + return ko.utils.stringifyJson(plainJavaScriptObject, replacer, space);
132.1379 + };
132.1380 +
132.1381 + function mapJsObjectGraph(rootObject, mapInputCallback, visitedObjects) {
132.1382 + visitedObjects = visitedObjects || new objectLookup();
132.1383 +
132.1384 + rootObject = mapInputCallback(rootObject);
132.1385 + var canHaveProperties = (typeof rootObject == "object") && (rootObject !== null) && (rootObject !== undefined) && (!(rootObject instanceof Date));
132.1386 + if (!canHaveProperties)
132.1387 + return rootObject;
132.1388 +
132.1389 + var outputProperties = rootObject instanceof Array ? [] : {};
132.1390 + visitedObjects.save(rootObject, outputProperties);
132.1391 +
132.1392 + visitPropertiesOrArrayEntries(rootObject, function(indexer) {
132.1393 + var propertyValue = mapInputCallback(rootObject[indexer]);
132.1394 +
132.1395 + switch (typeof propertyValue) {
132.1396 + case "boolean":
132.1397 + case "number":
132.1398 + case "string":
132.1399 + case "function":
132.1400 + outputProperties[indexer] = propertyValue;
132.1401 + break;
132.1402 + case "object":
132.1403 + case "undefined":
132.1404 + var previouslyMappedValue = visitedObjects.get(propertyValue);
132.1405 + outputProperties[indexer] = (previouslyMappedValue !== undefined)
132.1406 + ? previouslyMappedValue
132.1407 + : mapJsObjectGraph(propertyValue, mapInputCallback, visitedObjects);
132.1408 + break;
132.1409 + }
132.1410 + });
132.1411 +
132.1412 + return outputProperties;
132.1413 + }
132.1414 +
132.1415 + function visitPropertiesOrArrayEntries(rootObject, visitorCallback) {
132.1416 + if (rootObject instanceof Array) {
132.1417 + for (var i = 0; i < rootObject.length; i++)
132.1418 + visitorCallback(i);
132.1419 +
132.1420 + // For arrays, also respect toJSON property for custom mappings (fixes #278)
132.1421 + if (typeof rootObject['toJSON'] == 'function')
132.1422 + visitorCallback('toJSON');
132.1423 + } else {
132.1424 + for (var propertyName in rootObject)
132.1425 + visitorCallback(propertyName);
132.1426 + }
132.1427 + };
132.1428 +
132.1429 + function objectLookup() {
132.1430 + var keys = [];
132.1431 + var values = [];
132.1432 + this.save = function(key, value) {
132.1433 + var existingIndex = ko.utils.arrayIndexOf(keys, key);
132.1434 + if (existingIndex >= 0)
132.1435 + values[existingIndex] = value;
132.1436 + else {
132.1437 + keys.push(key);
132.1438 + values.push(value);
132.1439 + }
132.1440 + };
132.1441 + this.get = function(key) {
132.1442 + var existingIndex = ko.utils.arrayIndexOf(keys, key);
132.1443 + return (existingIndex >= 0) ? values[existingIndex] : undefined;
132.1444 + };
132.1445 + };
132.1446 +})();
132.1447 +
132.1448 +ko.exportSymbol('toJS', ko.toJS);
132.1449 +ko.exportSymbol('toJSON', ko.toJSON);
132.1450 +(function () {
132.1451 + var hasDomDataExpandoProperty = '__ko__hasDomDataOptionValue__';
132.1452 +
132.1453 + // Normally, SELECT elements and their OPTIONs can only take value of type 'string' (because the values
132.1454 + // are stored on DOM attributes). ko.selectExtensions provides a way for SELECTs/OPTIONs to have values
132.1455 + // that are arbitrary objects. This is very convenient when implementing things like cascading dropdowns.
132.1456 + ko.selectExtensions = {
132.1457 + readValue : function(element) {
132.1458 + switch (ko.utils.tagNameLower(element)) {
132.1459 + case 'option':
132.1460 + if (element[hasDomDataExpandoProperty] === true)
132.1461 + return ko.utils.domData.get(element, ko.bindingHandlers.options.optionValueDomDataKey);
132.1462 + return ko.utils.ieVersion <= 7
132.1463 + ? (element.getAttributeNode('value').specified ? element.value : element.text)
132.1464 + : element.value;
132.1465 + case 'select':
132.1466 + return element.selectedIndex >= 0 ? ko.selectExtensions.readValue(element.options[element.selectedIndex]) : undefined;
132.1467 + default:
132.1468 + return element.value;
132.1469 + }
132.1470 + },
132.1471 +
132.1472 + writeValue: function(element, value) {
132.1473 + switch (ko.utils.tagNameLower(element)) {
132.1474 + case 'option':
132.1475 + switch(typeof value) {
132.1476 + case "string":
132.1477 + ko.utils.domData.set(element, ko.bindingHandlers.options.optionValueDomDataKey, undefined);
132.1478 + if (hasDomDataExpandoProperty in element) { // IE <= 8 throws errors if you delete non-existent properties from a DOM node
132.1479 + delete element[hasDomDataExpandoProperty];
132.1480 + }
132.1481 + element.value = value;
132.1482 + break;
132.1483 + default:
132.1484 + // Store arbitrary object using DomData
132.1485 + ko.utils.domData.set(element, ko.bindingHandlers.options.optionValueDomDataKey, value);
132.1486 + element[hasDomDataExpandoProperty] = true;
132.1487 +
132.1488 + // Special treatment of numbers is just for backward compatibility. KO 1.2.1 wrote numerical values to element.value.
132.1489 + element.value = typeof value === "number" ? value : "";
132.1490 + break;
132.1491 + }
132.1492 + break;
132.1493 + case 'select':
132.1494 + for (var i = element.options.length - 1; i >= 0; i--) {
132.1495 + if (ko.selectExtensions.readValue(element.options[i]) == value) {
132.1496 + element.selectedIndex = i;
132.1497 + break;
132.1498 + }
132.1499 + }
132.1500 + break;
132.1501 + default:
132.1502 + if ((value === null) || (value === undefined))
132.1503 + value = "";
132.1504 + element.value = value;
132.1505 + break;
132.1506 + }
132.1507 + }
132.1508 + };
132.1509 +})();
132.1510 +
132.1511 +ko.exportSymbol('selectExtensions', ko.selectExtensions);
132.1512 +ko.exportSymbol('selectExtensions.readValue', ko.selectExtensions.readValue);
132.1513 +ko.exportSymbol('selectExtensions.writeValue', ko.selectExtensions.writeValue);
132.1514 +ko.expressionRewriting = (function () {
132.1515 + var restoreCapturedTokensRegex = /\@ko_token_(\d+)\@/g;
132.1516 + var javaScriptReservedWords = ["true", "false"];
132.1517 +
132.1518 + // Matches something that can be assigned to--either an isolated identifier or something ending with a property accessor
132.1519 + // This is designed to be simple and avoid false negatives, but could produce false positives (e.g., a+b.c).
132.1520 + var javaScriptAssignmentTarget = /^(?:[$_a-z][$\w]*|(.+)(\.\s*[$_a-z][$\w]*|\[.+\]))$/i;
132.1521 +
132.1522 + function restoreTokens(string, tokens) {
132.1523 + var prevValue = null;
132.1524 + while (string != prevValue) { // Keep restoring tokens until it no longer makes a difference (they may be nested)
132.1525 + prevValue = string;
132.1526 + string = string.replace(restoreCapturedTokensRegex, function (match, tokenIndex) {
132.1527 + return tokens[tokenIndex];
132.1528 + });
132.1529 + }
132.1530 + return string;
132.1531 + }
132.1532 +
132.1533 + function getWriteableValue(expression) {
132.1534 + if (ko.utils.arrayIndexOf(javaScriptReservedWords, ko.utils.stringTrim(expression).toLowerCase()) >= 0)
132.1535 + return false;
132.1536 + var match = expression.match(javaScriptAssignmentTarget);
132.1537 + return match === null ? false : match[1] ? ('Object(' + match[1] + ')' + match[2]) : expression;
132.1538 + }
132.1539 +
132.1540 + function ensureQuoted(key) {
132.1541 + var trimmedKey = ko.utils.stringTrim(key);
132.1542 + switch (trimmedKey.length && trimmedKey.charAt(0)) {
132.1543 + case "'":
132.1544 + case '"':
132.1545 + return key;
132.1546 + default:
132.1547 + return "'" + trimmedKey + "'";
132.1548 + }
132.1549 + }
132.1550 +
132.1551 + return {
132.1552 + bindingRewriteValidators: [],
132.1553 +
132.1554 + parseObjectLiteral: function(objectLiteralString) {
132.1555 + // A full tokeniser+lexer would add too much weight to this library, so here's a simple parser
132.1556 + // that is sufficient just to split an object literal string into a set of top-level key-value pairs
132.1557 +
132.1558 + var str = ko.utils.stringTrim(objectLiteralString);
132.1559 + if (str.length < 3)
132.1560 + return [];
132.1561 + if (str.charAt(0) === "{")// Ignore any braces surrounding the whole object literal
132.1562 + str = str.substring(1, str.length - 1);
132.1563 +
132.1564 + // Pull out any string literals and regex literals
132.1565 + var tokens = [];
132.1566 + var tokenStart = null, tokenEndChar;
132.1567 + for (var position = 0; position < str.length; position++) {
132.1568 + var c = str.charAt(position);
132.1569 + if (tokenStart === null) {
132.1570 + switch (c) {
132.1571 + case '"':
132.1572 + case "'":
132.1573 + case "/":
132.1574 + tokenStart = position;
132.1575 + tokenEndChar = c;
132.1576 + break;
132.1577 + }
132.1578 + } else if ((c == tokenEndChar) && (str.charAt(position - 1) !== "\\")) {
132.1579 + var token = str.substring(tokenStart, position + 1);
132.1580 + tokens.push(token);
132.1581 + var replacement = "@ko_token_" + (tokens.length - 1) + "@";
132.1582 + str = str.substring(0, tokenStart) + replacement + str.substring(position + 1);
132.1583 + position -= (token.length - replacement.length);
132.1584 + tokenStart = null;
132.1585 + }
132.1586 + }
132.1587 +
132.1588 + // Next pull out balanced paren, brace, and bracket blocks
132.1589 + tokenStart = null;
132.1590 + tokenEndChar = null;
132.1591 + var tokenDepth = 0, tokenStartChar = null;
132.1592 + for (var position = 0; position < str.length; position++) {
132.1593 + var c = str.charAt(position);
132.1594 + if (tokenStart === null) {
132.1595 + switch (c) {
132.1596 + case "{": tokenStart = position; tokenStartChar = c;
132.1597 + tokenEndChar = "}";
132.1598 + break;
132.1599 + case "(": tokenStart = position; tokenStartChar = c;
132.1600 + tokenEndChar = ")";
132.1601 + break;
132.1602 + case "[": tokenStart = position; tokenStartChar = c;
132.1603 + tokenEndChar = "]";
132.1604 + break;
132.1605 + }
132.1606 + }
132.1607 +
132.1608 + if (c === tokenStartChar)
132.1609 + tokenDepth++;
132.1610 + else if (c === tokenEndChar) {
132.1611 + tokenDepth--;
132.1612 + if (tokenDepth === 0) {
132.1613 + var token = str.substring(tokenStart, position + 1);
132.1614 + tokens.push(token);
132.1615 + var replacement = "@ko_token_" + (tokens.length - 1) + "@";
132.1616 + str = str.substring(0, tokenStart) + replacement + str.substring(position + 1);
132.1617 + position -= (token.length - replacement.length);
132.1618 + tokenStart = null;
132.1619 + }
132.1620 + }
132.1621 + }
132.1622 +
132.1623 + // Now we can safely split on commas to get the key/value pairs
132.1624 + var result = [];
132.1625 + var keyValuePairs = str.split(",");
132.1626 + for (var i = 0, j = keyValuePairs.length; i < j; i++) {
132.1627 + var pair = keyValuePairs[i];
132.1628 + var colonPos = pair.indexOf(":");
132.1629 + if ((colonPos > 0) && (colonPos < pair.length - 1)) {
132.1630 + var key = pair.substring(0, colonPos);
132.1631 + var value = pair.substring(colonPos + 1);
132.1632 + result.push({ 'key': restoreTokens(key, tokens), 'value': restoreTokens(value, tokens) });
132.1633 + } else {
132.1634 + result.push({ 'unknown': restoreTokens(pair, tokens) });
132.1635 + }
132.1636 + }
132.1637 + return result;
132.1638 + },
132.1639 +
132.1640 + preProcessBindings: function (objectLiteralStringOrKeyValueArray) {
132.1641 + var keyValueArray = typeof objectLiteralStringOrKeyValueArray === "string"
132.1642 + ? ko.expressionRewriting.parseObjectLiteral(objectLiteralStringOrKeyValueArray)
132.1643 + : objectLiteralStringOrKeyValueArray;
132.1644 + var resultStrings = [], propertyAccessorResultStrings = [];
132.1645 +
132.1646 + var keyValueEntry;
132.1647 + for (var i = 0; keyValueEntry = keyValueArray[i]; i++) {
132.1648 + if (resultStrings.length > 0)
132.1649 + resultStrings.push(",");
132.1650 +
132.1651 + if (keyValueEntry['key']) {
132.1652 + var quotedKey = ensureQuoted(keyValueEntry['key']), val = keyValueEntry['value'];
132.1653 + resultStrings.push(quotedKey);
132.1654 + resultStrings.push(":");
132.1655 + resultStrings.push(val);
132.1656 +
132.1657 + if (val = getWriteableValue(ko.utils.stringTrim(val))) {
132.1658 + if (propertyAccessorResultStrings.length > 0)
132.1659 + propertyAccessorResultStrings.push(", ");
132.1660 + propertyAccessorResultStrings.push(quotedKey + " : function(__ko_value) { " + val + " = __ko_value; }");
132.1661 + }
132.1662 + } else if (keyValueEntry['unknown']) {
132.1663 + resultStrings.push(keyValueEntry['unknown']);
132.1664 + }
132.1665 + }
132.1666 +
132.1667 + var combinedResult = resultStrings.join("");
132.1668 + if (propertyAccessorResultStrings.length > 0) {
132.1669 + var allPropertyAccessors = propertyAccessorResultStrings.join("");
132.1670 + combinedResult = combinedResult + ", '_ko_property_writers' : { " + allPropertyAccessors + " } ";
132.1671 + }
132.1672 +
132.1673 + return combinedResult;
132.1674 + },
132.1675 +
132.1676 + keyValueArrayContainsKey: function(keyValueArray, key) {
132.1677 + for (var i = 0; i < keyValueArray.length; i++)
132.1678 + if (ko.utils.stringTrim(keyValueArray[i]['key']) == key)
132.1679 + return true;
132.1680 + return false;
132.1681 + },
132.1682 +
132.1683 + // Internal, private KO utility for updating model properties from within bindings
132.1684 + // property: If the property being updated is (or might be) an observable, pass it here
132.1685 + // If it turns out to be a writable observable, it will be written to directly
132.1686 + // allBindingsAccessor: All bindings in the current execution context.
132.1687 + // This will be searched for a '_ko_property_writers' property in case you're writing to a non-observable
132.1688 + // key: The key identifying the property to be written. Example: for { hasFocus: myValue }, write to 'myValue' by specifying the key 'hasFocus'
132.1689 + // value: The value to be written
132.1690 + // checkIfDifferent: If true, and if the property being written is a writable observable, the value will only be written if
132.1691 + // it is !== existing value on that writable observable
132.1692 + writeValueToProperty: function(property, allBindingsAccessor, key, value, checkIfDifferent) {
132.1693 + if (!property || !ko.isWriteableObservable(property)) {
132.1694 + var propWriters = allBindingsAccessor()['_ko_property_writers'];
132.1695 + if (propWriters && propWriters[key])
132.1696 + propWriters[key](value);
132.1697 + } else if (!checkIfDifferent || property.peek() !== value) {
132.1698 + property(value);
132.1699 + }
132.1700 + }
132.1701 + };
132.1702 +})();
132.1703 +
132.1704 +ko.exportSymbol('expressionRewriting', ko.expressionRewriting);
132.1705 +ko.exportSymbol('expressionRewriting.bindingRewriteValidators', ko.expressionRewriting.bindingRewriteValidators);
132.1706 +ko.exportSymbol('expressionRewriting.parseObjectLiteral', ko.expressionRewriting.parseObjectLiteral);
132.1707 +ko.exportSymbol('expressionRewriting.preProcessBindings', ko.expressionRewriting.preProcessBindings);
132.1708 +
132.1709 +// For backward compatibility, define the following aliases. (Previously, these function names were misleading because
132.1710 +// they referred to JSON specifically, even though they actually work with arbitrary JavaScript object literal expressions.)
132.1711 +ko.exportSymbol('jsonExpressionRewriting', ko.expressionRewriting);
132.1712 +ko.exportSymbol('jsonExpressionRewriting.insertPropertyAccessorsIntoJson', ko.expressionRewriting.preProcessBindings);(function() {
132.1713 + // "Virtual elements" is an abstraction on top of the usual DOM API which understands the notion that comment nodes
132.1714 + // may be used to represent hierarchy (in addition to the DOM's natural hierarchy).
132.1715 + // If you call the DOM-manipulating functions on ko.virtualElements, you will be able to read and write the state
132.1716 + // of that virtual hierarchy
132.1717 + //
132.1718 + // The point of all this is to support containerless templates (e.g., <!-- ko foreach:someCollection -->blah<!-- /ko -->)
132.1719 + // without having to scatter special cases all over the binding and templating code.
132.1720 +
132.1721 + // IE 9 cannot reliably read the "nodeValue" property of a comment node (see https://github.com/SteveSanderson/knockout/issues/186)
132.1722 + // but it does give them a nonstandard alternative property called "text" that it can read reliably. Other browsers don't have that property.
132.1723 + // So, use node.text where available, and node.nodeValue elsewhere
132.1724 + var commentNodesHaveTextProperty = document.createComment("test").text === "<!--test-->";
132.1725 +
132.1726 + var startCommentRegex = commentNodesHaveTextProperty ? /^<!--\s*ko(?:\s+(.+\s*\:[\s\S]*))?\s*-->$/ : /^\s*ko(?:\s+(.+\s*\:[\s\S]*))?\s*$/;
132.1727 + var endCommentRegex = commentNodesHaveTextProperty ? /^<!--\s*\/ko\s*-->$/ : /^\s*\/ko\s*$/;
132.1728 + var htmlTagsWithOptionallyClosingChildren = { 'ul': true, 'ol': true };
132.1729 +
132.1730 + function isStartComment(node) {
132.1731 + return (node.nodeType == 8) && (commentNodesHaveTextProperty ? node.text : node.nodeValue).match(startCommentRegex);
132.1732 + }
132.1733 +
132.1734 + function isEndComment(node) {
132.1735 + return (node.nodeType == 8) && (commentNodesHaveTextProperty ? node.text : node.nodeValue).match(endCommentRegex);
132.1736 + }
132.1737 +
132.1738 + function getVirtualChildren(startComment, allowUnbalanced) {
132.1739 + var currentNode = startComment;
132.1740 + var depth = 1;
132.1741 + var children = [];
132.1742 + while (currentNode = currentNode.nextSibling) {
132.1743 + if (isEndComment(currentNode)) {
132.1744 + depth--;
132.1745 + if (depth === 0)
132.1746 + return children;
132.1747 + }
132.1748 +
132.1749 + children.push(currentNode);
132.1750 +
132.1751 + if (isStartComment(currentNode))
132.1752 + depth++;
132.1753 + }
132.1754 + if (!allowUnbalanced)
132.1755 + throw new Error("Cannot find closing comment tag to match: " + startComment.nodeValue);
132.1756 + return null;
132.1757 + }
132.1758 +
132.1759 + function getMatchingEndComment(startComment, allowUnbalanced) {
132.1760 + var allVirtualChildren = getVirtualChildren(startComment, allowUnbalanced);
132.1761 + if (allVirtualChildren) {
132.1762 + if (allVirtualChildren.length > 0)
132.1763 + return allVirtualChildren[allVirtualChildren.length - 1].nextSibling;
132.1764 + return startComment.nextSibling;
132.1765 + } else
132.1766 + return null; // Must have no matching end comment, and allowUnbalanced is true
132.1767 + }
132.1768 +
132.1769 + function getUnbalancedChildTags(node) {
132.1770 + // e.g., from <div>OK</div><!-- ko blah --><span>Another</span>, returns: <!-- ko blah --><span>Another</span>
132.1771 + // from <div>OK</div><!-- /ko --><!-- /ko -->, returns: <!-- /ko --><!-- /ko -->
132.1772 + var childNode = node.firstChild, captureRemaining = null;
132.1773 + if (childNode) {
132.1774 + do {
132.1775 + if (captureRemaining) // We already hit an unbalanced node and are now just scooping up all subsequent nodes
132.1776 + captureRemaining.push(childNode);
132.1777 + else if (isStartComment(childNode)) {
132.1778 + var matchingEndComment = getMatchingEndComment(childNode, /* allowUnbalanced: */ true);
132.1779 + if (matchingEndComment) // It's a balanced tag, so skip immediately to the end of this virtual set
132.1780 + childNode = matchingEndComment;
132.1781 + else
132.1782 + captureRemaining = [childNode]; // It's unbalanced, so start capturing from this point
132.1783 + } else if (isEndComment(childNode)) {
132.1784 + captureRemaining = [childNode]; // It's unbalanced (if it wasn't, we'd have skipped over it already), so start capturing
132.1785 + }
132.1786 + } while (childNode = childNode.nextSibling);
132.1787 + }
132.1788 + return captureRemaining;
132.1789 + }
132.1790 +
132.1791 + ko.virtualElements = {
132.1792 + allowedBindings: {},
132.1793 +
132.1794 + childNodes: function(node) {
132.1795 + return isStartComment(node) ? getVirtualChildren(node) : node.childNodes;
132.1796 + },
132.1797 +
132.1798 + emptyNode: function(node) {
132.1799 + if (!isStartComment(node))
132.1800 + ko.utils.emptyDomNode(node);
132.1801 + else {
132.1802 + var virtualChildren = ko.virtualElements.childNodes(node);
132.1803 + for (var i = 0, j = virtualChildren.length; i < j; i++)
132.1804 + ko.removeNode(virtualChildren[i]);
132.1805 + }
132.1806 + },
132.1807 +
132.1808 + setDomNodeChildren: function(node, childNodes) {
132.1809 + if (!isStartComment(node))
132.1810 + ko.utils.setDomNodeChildren(node, childNodes);
132.1811 + else {
132.1812 + ko.virtualElements.emptyNode(node);
132.1813 + var endCommentNode = node.nextSibling; // Must be the next sibling, as we just emptied the children
132.1814 + for (var i = 0, j = childNodes.length; i < j; i++)
132.1815 + endCommentNode.parentNode.insertBefore(childNodes[i], endCommentNode);
132.1816 + }
132.1817 + },
132.1818 +
132.1819 + prepend: function(containerNode, nodeToPrepend) {
132.1820 + if (!isStartComment(containerNode)) {
132.1821 + if (containerNode.firstChild)
132.1822 + containerNode.insertBefore(nodeToPrepend, containerNode.firstChild);
132.1823 + else
132.1824 + containerNode.appendChild(nodeToPrepend);
132.1825 + } else {
132.1826 + // Start comments must always have a parent and at least one following sibling (the end comment)
132.1827 + containerNode.parentNode.insertBefore(nodeToPrepend, containerNode.nextSibling);
132.1828 + }
132.1829 + },
132.1830 +
132.1831 + insertAfter: function(containerNode, nodeToInsert, insertAfterNode) {
132.1832 + if (!insertAfterNode) {
132.1833 + ko.virtualElements.prepend(containerNode, nodeToInsert);
132.1834 + } else if (!isStartComment(containerNode)) {
132.1835 + // Insert after insertion point
132.1836 + if (insertAfterNode.nextSibling)
132.1837 + containerNode.insertBefore(nodeToInsert, insertAfterNode.nextSibling);
132.1838 + else
132.1839 + containerNode.appendChild(nodeToInsert);
132.1840 + } else {
132.1841 + // Children of start comments must always have a parent and at least one following sibling (the end comment)
132.1842 + containerNode.parentNode.insertBefore(nodeToInsert, insertAfterNode.nextSibling);
132.1843 + }
132.1844 + },
132.1845 +
132.1846 + firstChild: function(node) {
132.1847 + if (!isStartComment(node))
132.1848 + return node.firstChild;
132.1849 + if (!node.nextSibling || isEndComment(node.nextSibling))
132.1850 + return null;
132.1851 + return node.nextSibling;
132.1852 + },
132.1853 +
132.1854 + nextSibling: function(node) {
132.1855 + if (isStartComment(node))
132.1856 + node = getMatchingEndComment(node);
132.1857 + if (node.nextSibling && isEndComment(node.nextSibling))
132.1858 + return null;
132.1859 + return node.nextSibling;
132.1860 + },
132.1861 +
132.1862 + virtualNodeBindingValue: function(node) {
132.1863 + var regexMatch = isStartComment(node);
132.1864 + return regexMatch ? regexMatch[1] : null;
132.1865 + },
132.1866 +
132.1867 + normaliseVirtualElementDomStructure: function(elementVerified) {
132.1868 + // Workaround for https://github.com/SteveSanderson/knockout/issues/155
132.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
132.1870 + // that are direct descendants of <ul> into the preceding <li>)
132.1871 + if (!htmlTagsWithOptionallyClosingChildren[ko.utils.tagNameLower(elementVerified)])
132.1872 + return;
132.1873 +
132.1874 + // Scan immediate children to see if they contain unbalanced comment tags. If they do, those comment tags
132.1875 + // must be intended to appear *after* that child, so move them there.
132.1876 + var childNode = elementVerified.firstChild;
132.1877 + if (childNode) {
132.1878 + do {
132.1879 + if (childNode.nodeType === 1) {
132.1880 + var unbalancedTags = getUnbalancedChildTags(childNode);
132.1881 + if (unbalancedTags) {
132.1882 + // Fix up the DOM by moving the unbalanced tags to where they most likely were intended to be placed - *after* the child
132.1883 + var nodeToInsertBefore = childNode.nextSibling;
132.1884 + for (var i = 0; i < unbalancedTags.length; i++) {
132.1885 + if (nodeToInsertBefore)
132.1886 + elementVerified.insertBefore(unbalancedTags[i], nodeToInsertBefore);
132.1887 + else
132.1888 + elementVerified.appendChild(unbalancedTags[i]);
132.1889 + }
132.1890 + }
132.1891 + }
132.1892 + } while (childNode = childNode.nextSibling);
132.1893 + }
132.1894 + }
132.1895 + };
132.1896 +})();
132.1897 +ko.exportSymbol('virtualElements', ko.virtualElements);
132.1898 +ko.exportSymbol('virtualElements.allowedBindings', ko.virtualElements.allowedBindings);
132.1899 +ko.exportSymbol('virtualElements.emptyNode', ko.virtualElements.emptyNode);
132.1900 +//ko.exportSymbol('virtualElements.firstChild', ko.virtualElements.firstChild); // firstChild is not minified
132.1901 +ko.exportSymbol('virtualElements.insertAfter', ko.virtualElements.insertAfter);
132.1902 +//ko.exportSymbol('virtualElements.nextSibling', ko.virtualElements.nextSibling); // nextSibling is not minified
132.1903 +ko.exportSymbol('virtualElements.prepend', ko.virtualElements.prepend);
132.1904 +ko.exportSymbol('virtualElements.setDomNodeChildren', ko.virtualElements.setDomNodeChildren);
132.1905 +(function() {
132.1906 + var defaultBindingAttributeName = "data-bind";
132.1907 +
132.1908 + ko.bindingProvider = function() {
132.1909 + this.bindingCache = {};
132.1910 + };
132.1911 +
132.1912 + ko.utils.extend(ko.bindingProvider.prototype, {
132.1913 + 'nodeHasBindings': function(node) {
132.1914 + switch (node.nodeType) {
132.1915 + case 1: return node.getAttribute(defaultBindingAttributeName) != null; // Element
132.1916 + case 8: return ko.virtualElements.virtualNodeBindingValue(node) != null; // Comment node
132.1917 + default: return false;
132.1918 + }
132.1919 + },
132.1920 +
132.1921 + 'getBindings': function(node, bindingContext) {
132.1922 + var bindingsString = this['getBindingsString'](node, bindingContext);
132.1923 + return bindingsString ? this['parseBindingsString'](bindingsString, bindingContext, node) : null;
132.1924 + },
132.1925 +
132.1926 + // The following function is only used internally by this default provider.
132.1927 + // It's not part of the interface definition for a general binding provider.
132.1928 + 'getBindingsString': function(node, bindingContext) {
132.1929 + switch (node.nodeType) {
132.1930 + case 1: return node.getAttribute(defaultBindingAttributeName); // Element
132.1931 + case 8: return ko.virtualElements.virtualNodeBindingValue(node); // Comment node
132.1932 + default: return null;
132.1933 + }
132.1934 + },
132.1935 +
132.1936 + // The following function is only used internally by this default provider.
132.1937 + // It's not part of the interface definition for a general binding provider.
132.1938 + 'parseBindingsString': function(bindingsString, bindingContext, node) {
132.1939 + try {
132.1940 + var bindingFunction = createBindingsStringEvaluatorViaCache(bindingsString, this.bindingCache);
132.1941 + return bindingFunction(bindingContext, node);
132.1942 + } catch (ex) {
132.1943 + throw new Error("Unable to parse bindings.\nMessage: " + ex + ";\nBindings value: " + bindingsString);
132.1944 + }
132.1945 + }
132.1946 + });
132.1947 +
132.1948 + ko.bindingProvider['instance'] = new ko.bindingProvider();
132.1949 +
132.1950 + function createBindingsStringEvaluatorViaCache(bindingsString, cache) {
132.1951 + var cacheKey = bindingsString;
132.1952 + return cache[cacheKey]
132.1953 + || (cache[cacheKey] = createBindingsStringEvaluator(bindingsString));
132.1954 + }
132.1955 +
132.1956 + function createBindingsStringEvaluator(bindingsString) {
132.1957 + // Build the source for a function that evaluates "expression"
132.1958 + // For each scope variable, add an extra level of "with" nesting
132.1959 + // Example result: with(sc1) { with(sc0) { return (expression) } }
132.1960 + var rewrittenBindings = ko.expressionRewriting.preProcessBindings(bindingsString),
132.1961 + functionBody = "with($context){with($data||{}){return{" + rewrittenBindings + "}}}";
132.1962 + return new Function("$context", "$element", functionBody);
132.1963 + }
132.1964 +})();
132.1965 +
132.1966 +ko.exportSymbol('bindingProvider', ko.bindingProvider);
132.1967 +(function () {
132.1968 + ko.bindingHandlers = {};
132.1969 +
132.1970 + ko.bindingContext = function(dataItem, parentBindingContext, dataItemAlias) {
132.1971 + if (parentBindingContext) {
132.1972 + ko.utils.extend(this, parentBindingContext); // Inherit $root and any custom properties
132.1973 + this['$parentContext'] = parentBindingContext;
132.1974 + this['$parent'] = parentBindingContext['$data'];
132.1975 + this['$parents'] = (parentBindingContext['$parents'] || []).slice(0);
132.1976 + this['$parents'].unshift(this['$parent']);
132.1977 + } else {
132.1978 + this['$parents'] = [];
132.1979 + this['$root'] = dataItem;
132.1980 + // Export 'ko' in the binding context so it will be available in bindings and templates
132.1981 + // even if 'ko' isn't exported as a global, such as when using an AMD loader.
132.1982 + // See https://github.com/SteveSanderson/knockout/issues/490
132.1983 + this['ko'] = ko;
132.1984 + }
132.1985 + this['$data'] = dataItem;
132.1986 + if (dataItemAlias)
132.1987 + this[dataItemAlias] = dataItem;
132.1988 + }
132.1989 + ko.bindingContext.prototype['createChildContext'] = function (dataItem, dataItemAlias) {
132.1990 + return new ko.bindingContext(dataItem, this, dataItemAlias);
132.1991 + };
132.1992 + ko.bindingContext.prototype['extend'] = function(properties) {
132.1993 + var clone = ko.utils.extend(new ko.bindingContext(), this);
132.1994 + return ko.utils.extend(clone, properties);
132.1995 + };
132.1996 +
132.1997 + function validateThatBindingIsAllowedForVirtualElements(bindingName) {
132.1998 + var validator = ko.virtualElements.allowedBindings[bindingName];
132.1999 + if (!validator)
132.2000 + throw new Error("The binding '" + bindingName + "' cannot be used with virtual elements")
132.2001 + }
132.2002 +
132.2003 + function applyBindingsToDescendantsInternal (viewModel, elementOrVirtualElement, bindingContextsMayDifferFromDomParentElement) {
132.2004 + var currentChild, nextInQueue = ko.virtualElements.firstChild(elementOrVirtualElement);
132.2005 + while (currentChild = nextInQueue) {
132.2006 + // Keep a record of the next child *before* applying bindings, in case the binding removes the current child from its position
132.2007 + nextInQueue = ko.virtualElements.nextSibling(currentChild);
132.2008 + applyBindingsToNodeAndDescendantsInternal(viewModel, currentChild, bindingContextsMayDifferFromDomParentElement);
132.2009 + }
132.2010 + }
132.2011 +
132.2012 + function applyBindingsToNodeAndDescendantsInternal (viewModel, nodeVerified, bindingContextMayDifferFromDomParentElement) {
132.2013 + var shouldBindDescendants = true;
132.2014 +
132.2015 + // Perf optimisation: Apply bindings only if...
132.2016 + // (1) We need to store the binding context on this node (because it may differ from the DOM parent node's binding context)
132.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
132.2018 + // (2) It might have bindings (e.g., it has a data-bind attribute, or it's a marker for a containerless template)
132.2019 + var isElement = (nodeVerified.nodeType === 1);
132.2020 + if (isElement) // Workaround IE <= 8 HTML parsing weirdness
132.2021 + ko.virtualElements.normaliseVirtualElementDomStructure(nodeVerified);
132.2022 +
132.2023 + var shouldApplyBindings = (isElement && bindingContextMayDifferFromDomParentElement) // Case (1)
132.2024 + || ko.bindingProvider['instance']['nodeHasBindings'](nodeVerified); // Case (2)
132.2025 + if (shouldApplyBindings)
132.2026 + shouldBindDescendants = applyBindingsToNodeInternal(nodeVerified, null, viewModel, bindingContextMayDifferFromDomParentElement).shouldBindDescendants;
132.2027 +
132.2028 + if (shouldBindDescendants) {
132.2029 + // We're recursing automatically into (real or virtual) child nodes without changing binding contexts. So,
132.2030 + // * For children of a *real* element, the binding context is certainly the same as on their DOM .parentNode,
132.2031 + // hence bindingContextsMayDifferFromDomParentElement is false
132.2032 + // * For children of a *virtual* element, we can't be sure. Evaluating .parentNode on those children may
132.2033 + // skip over any number of intermediate virtual elements, any of which might define a custom binding context,
132.2034 + // hence bindingContextsMayDifferFromDomParentElement is true
132.2035 + applyBindingsToDescendantsInternal(viewModel, nodeVerified, /* bindingContextsMayDifferFromDomParentElement: */ !isElement);
132.2036 + }
132.2037 + }
132.2038 +
132.2039 + function applyBindingsToNodeInternal (node, bindings, viewModelOrBindingContext, bindingContextMayDifferFromDomParentElement) {
132.2040 + // Need to be sure that inits are only run once, and updates never run until all the inits have been run
132.2041 + var initPhase = 0; // 0 = before all inits, 1 = during inits, 2 = after all inits
132.2042 +
132.2043 + // Each time the dependentObservable is evaluated (after data changes),
132.2044 + // the binding attribute is reparsed so that it can pick out the correct
132.2045 + // model properties in the context of the changed data.
132.2046 + // DOM event callbacks need to be able to access this changed data,
132.2047 + // so we need a single parsedBindings variable (shared by all callbacks
132.2048 + // associated with this node's bindings) that all the closures can access.
132.2049 + var parsedBindings;
132.2050 + function makeValueAccessor(bindingKey) {
132.2051 + return function () { return parsedBindings[bindingKey] }
132.2052 + }
132.2053 + function parsedBindingsAccessor() {
132.2054 + return parsedBindings;
132.2055 + }
132.2056 +
132.2057 + var bindingHandlerThatControlsDescendantBindings;
132.2058 + ko.dependentObservable(
132.2059 + function () {
132.2060 + // Ensure we have a nonnull binding context to work with
132.2061 + var bindingContextInstance = viewModelOrBindingContext && (viewModelOrBindingContext instanceof ko.bindingContext)
132.2062 + ? viewModelOrBindingContext
132.2063 + : new ko.bindingContext(ko.utils.unwrapObservable(viewModelOrBindingContext));
132.2064 + var viewModel = bindingContextInstance['$data'];
132.2065 +
132.2066 + // Optimization: Don't store the binding context on this node if it's definitely the same as on node.parentNode, because
132.2067 + // we can easily recover it just by scanning up the node's ancestors in the DOM
132.2068 + // (note: here, parent node means "real DOM parent" not "virtual parent", as there's no O(1) way to find the virtual parent)
132.2069 + if (bindingContextMayDifferFromDomParentElement)
132.2070 + ko.storedBindingContextForNode(node, bindingContextInstance);
132.2071 +
132.2072 + // Use evaluatedBindings if given, otherwise fall back on asking the bindings provider to give us some bindings
132.2073 + var evaluatedBindings = (typeof bindings == "function") ? bindings(bindingContextInstance, node) : bindings;
132.2074 + parsedBindings = evaluatedBindings || ko.bindingProvider['instance']['getBindings'](node, bindingContextInstance);
132.2075 +
132.2076 + if (parsedBindings) {
132.2077 + // First run all the inits, so bindings can register for notification on changes
132.2078 + if (initPhase === 0) {
132.2079 + initPhase = 1;
132.2080 + for (var bindingKey in parsedBindings) {
132.2081 + var binding = ko.bindingHandlers[bindingKey];
132.2082 + if (binding && node.nodeType === 8)
132.2083 + validateThatBindingIsAllowedForVirtualElements(bindingKey);
132.2084 +
132.2085 + if (binding && typeof binding["init"] == "function") {
132.2086 + var handlerInitFn = binding["init"];
132.2087 + var initResult = handlerInitFn(node, makeValueAccessor(bindingKey), parsedBindingsAccessor, viewModel, bindingContextInstance);
132.2088 +
132.2089 + // If this binding handler claims to control descendant bindings, make a note of this
132.2090 + if (initResult && initResult['controlsDescendantBindings']) {
132.2091 + if (bindingHandlerThatControlsDescendantBindings !== undefined)
132.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.");
132.2093 + bindingHandlerThatControlsDescendantBindings = bindingKey;
132.2094 + }
132.2095 + }
132.2096 + }
132.2097 + initPhase = 2;
132.2098 + }
132.2099 +
132.2100 + // ... then run all the updates, which might trigger changes even on the first evaluation
132.2101 + if (initPhase === 2) {
132.2102 + for (var bindingKey in parsedBindings) {
132.2103 + var binding = ko.bindingHandlers[bindingKey];
132.2104 + if (binding && typeof binding["update"] == "function") {
132.2105 + var handlerUpdateFn = binding["update"];
132.2106 + handlerUpdateFn(node, makeValueAccessor(bindingKey), parsedBindingsAccessor, viewModel, bindingContextInstance);
132.2107 + }
132.2108 + }
132.2109 + }
132.2110 + }
132.2111 + },
132.2112 + null,
132.2113 + { disposeWhenNodeIsRemoved : node }
132.2114 + );
132.2115 +
132.2116 + return {
132.2117 + shouldBindDescendants: bindingHandlerThatControlsDescendantBindings === undefined
132.2118 + };
132.2119 + };
132.2120 +
132.2121 + var storedBindingContextDomDataKey = "__ko_bindingContext__";
132.2122 + ko.storedBindingContextForNode = function (node, bindingContext) {
132.2123 + if (arguments.length == 2)
132.2124 + ko.utils.domData.set(node, storedBindingContextDomDataKey, bindingContext);
132.2125 + else
132.2126 + return ko.utils.domData.get(node, storedBindingContextDomDataKey);
132.2127 + }
132.2128 +
132.2129 + ko.applyBindingsToNode = function (node, bindings, viewModel) {
132.2130 + if (node.nodeType === 1) // If it's an element, workaround IE <= 8 HTML parsing weirdness
132.2131 + ko.virtualElements.normaliseVirtualElementDomStructure(node);
132.2132 + return applyBindingsToNodeInternal(node, bindings, viewModel, true);
132.2133 + };
132.2134 +
132.2135 + ko.applyBindingsToDescendants = function(viewModel, rootNode) {
132.2136 + if (rootNode.nodeType === 1 || rootNode.nodeType === 8)
132.2137 + applyBindingsToDescendantsInternal(viewModel, rootNode, true);
132.2138 + };
132.2139 +
132.2140 + ko.applyBindings = function (viewModel, rootNode) {
132.2141 + if (rootNode && (rootNode.nodeType !== 1) && (rootNode.nodeType !== 8))
132.2142 + throw new Error("ko.applyBindings: first parameter should be your view model; second parameter should be a DOM node");
132.2143 + rootNode = rootNode || window.document.body; // Make "rootNode" parameter optional
132.2144 +
132.2145 + applyBindingsToNodeAndDescendantsInternal(viewModel, rootNode, true);
132.2146 + };
132.2147 +
132.2148 + // Retrieving binding context from arbitrary nodes
132.2149 + ko.contextFor = function(node) {
132.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)
132.2151 + switch (node.nodeType) {
132.2152 + case 1:
132.2153 + case 8:
132.2154 + var context = ko.storedBindingContextForNode(node);
132.2155 + if (context) return context;
132.2156 + if (node.parentNode) return ko.contextFor(node.parentNode);
132.2157 + break;
132.2158 + }
132.2159 + return undefined;
132.2160 + };
132.2161 + ko.dataFor = function(node) {
132.2162 + var context = ko.contextFor(node);
132.2163 + return context ? context['$data'] : undefined;
132.2164 + };
132.2165 +
132.2166 + ko.exportSymbol('bindingHandlers', ko.bindingHandlers);
132.2167 + ko.exportSymbol('applyBindings', ko.applyBindings);
132.2168 + ko.exportSymbol('applyBindingsToDescendants', ko.applyBindingsToDescendants);
132.2169 + ko.exportSymbol('applyBindingsToNode', ko.applyBindingsToNode);
132.2170 + ko.exportSymbol('contextFor', ko.contextFor);
132.2171 + ko.exportSymbol('dataFor', ko.dataFor);
132.2172 +})();
132.2173 +var attrHtmlToJavascriptMap = { 'class': 'className', 'for': 'htmlFor' };
132.2174 +ko.bindingHandlers['attr'] = {
132.2175 + 'update': function(element, valueAccessor, allBindingsAccessor) {
132.2176 + var value = ko.utils.unwrapObservable(valueAccessor()) || {};
132.2177 + for (var attrName in value) {
132.2178 + if (typeof attrName == "string") {
132.2179 + var attrValue = ko.utils.unwrapObservable(value[attrName]);
132.2180 +
132.2181 + // To cover cases like "attr: { checked:someProp }", we want to remove the attribute entirely
132.2182 + // when someProp is a "no value"-like value (strictly null, false, or undefined)
132.2183 + // (because the absence of the "checked" attr is how to mark an element as not checked, etc.)
132.2184 + var toRemove = (attrValue === false) || (attrValue === null) || (attrValue === undefined);
132.2185 + if (toRemove)
132.2186 + element.removeAttribute(attrName);
132.2187 +
132.2188 + // In IE <= 7 and IE8 Quirks Mode, you have to use the Javascript property name instead of the
132.2189 + // HTML attribute name for certain attributes. IE8 Standards Mode supports the correct behavior,
132.2190 + // but instead of figuring out the mode, we'll just set the attribute through the Javascript
132.2191 + // property for IE <= 8.
132.2192 + if (ko.utils.ieVersion <= 8 && attrName in attrHtmlToJavascriptMap) {
132.2193 + attrName = attrHtmlToJavascriptMap[attrName];
132.2194 + if (toRemove)
132.2195 + element.removeAttribute(attrName);
132.2196 + else
132.2197 + element[attrName] = attrValue;
132.2198 + } else if (!toRemove) {
132.2199 + try {
132.2200 + element.setAttribute(attrName, attrValue.toString());
132.2201 + } catch (err) {
132.2202 + // ignore for now
132.2203 + if (console) {
132.2204 + console.log("Can't set attribute " + attrName + " to " + attrValue + " error: " + err);
132.2205 + }
132.2206 + }
132.2207 + }
132.2208 +
132.2209 + // Treat "name" specially - although you can think of it as an attribute, it also needs
132.2210 + // special handling on older versions of IE (https://github.com/SteveSanderson/knockout/pull/333)
132.2211 + // Deliberately being case-sensitive here because XHTML would regard "Name" as a different thing
132.2212 + // entirely, and there's no strong reason to allow for such casing in HTML.
132.2213 + if (attrName === "name") {
132.2214 + ko.utils.setElementName(element, toRemove ? "" : attrValue.toString());
132.2215 + }
132.2216 + }
132.2217 + }
132.2218 + }
132.2219 +};
132.2220 +ko.bindingHandlers['checked'] = {
132.2221 + 'init': function (element, valueAccessor, allBindingsAccessor) {
132.2222 + var updateHandler = function() {
132.2223 + var valueToWrite;
132.2224 + if (element.type == "checkbox") {
132.2225 + valueToWrite = element.checked;
132.2226 + } else if ((element.type == "radio") && (element.checked)) {
132.2227 + valueToWrite = element.value;
132.2228 + } else {
132.2229 + return; // "checked" binding only responds to checkboxes and selected radio buttons
132.2230 + }
132.2231 +
132.2232 + var modelValue = valueAccessor(), unwrappedValue = ko.utils.unwrapObservable(modelValue);
132.2233 + if ((element.type == "checkbox") && (unwrappedValue instanceof Array)) {
132.2234 + // For checkboxes bound to an array, we add/remove the checkbox value to that array
132.2235 + // This works for both observable and non-observable arrays
132.2236 + var existingEntryIndex = ko.utils.arrayIndexOf(unwrappedValue, element.value);
132.2237 + if (element.checked && (existingEntryIndex < 0))
132.2238 + modelValue.push(element.value);
132.2239 + else if ((!element.checked) && (existingEntryIndex >= 0))
132.2240 + modelValue.splice(existingEntryIndex, 1);
132.2241 + } else {
132.2242 + ko.expressionRewriting.writeValueToProperty(modelValue, allBindingsAccessor, 'checked', valueToWrite, true);
132.2243 + }
132.2244 + };
132.2245 + ko.utils.registerEventHandler(element, "click", updateHandler);
132.2246 +
132.2247 + // IE 6 won't allow radio buttons to be selected unless they have a name
132.2248 + if ((element.type == "radio") && !element.name)
132.2249 + ko.bindingHandlers['uniqueName']['init'](element, function() { return true });
132.2250 + },
132.2251 + 'update': function (element, valueAccessor) {
132.2252 + var value = ko.utils.unwrapObservable(valueAccessor());
132.2253 +
132.2254 + if (element.type == "checkbox") {
132.2255 + if (value instanceof Array) {
132.2256 + // When bound to an array, the checkbox being checked represents its value being present in that array
132.2257 + element.checked = ko.utils.arrayIndexOf(value, element.value) >= 0;
132.2258 + } else {
132.2259 + // When bound to anything other value (not an array), the checkbox being checked represents the value being trueish
132.2260 + element.checked = value;
132.2261 + }
132.2262 + } else if (element.type == "radio") {
132.2263 + element.checked = (element.value == value);
132.2264 + }
132.2265 + }
132.2266 +};
132.2267 +var classesWrittenByBindingKey = '__ko__cssValue';
132.2268 +ko.bindingHandlers['css'] = {
132.2269 + 'update': function (element, valueAccessor) {
132.2270 + var value = ko.utils.unwrapObservable(valueAccessor());
132.2271 + if (typeof value == "object") {
132.2272 + for (var className in value) {
132.2273 + var shouldHaveClass = ko.utils.unwrapObservable(value[className]);
132.2274 + ko.utils.toggleDomNodeCssClass(element, className, shouldHaveClass);
132.2275 + }
132.2276 + } else {
132.2277 + value = String(value || ''); // Make sure we don't try to store or set a non-string value
132.2278 + ko.utils.toggleDomNodeCssClass(element, element[classesWrittenByBindingKey], false);
132.2279 + element[classesWrittenByBindingKey] = value;
132.2280 + ko.utils.toggleDomNodeCssClass(element, value, true);
132.2281 + }
132.2282 + }
132.2283 +};
132.2284 +ko.bindingHandlers['enable'] = {
132.2285 + 'update': function (element, valueAccessor) {
132.2286 + var value = ko.utils.unwrapObservable(valueAccessor());
132.2287 + if (value && element.disabled)
132.2288 + element.removeAttribute("disabled");
132.2289 + else if ((!value) && (!element.disabled))
132.2290 + element.disabled = true;
132.2291 + }
132.2292 +};
132.2293 +
132.2294 +ko.bindingHandlers['disable'] = {
132.2295 + 'update': function (element, valueAccessor) {
132.2296 + ko.bindingHandlers['enable']['update'](element, function() { return !ko.utils.unwrapObservable(valueAccessor()) });
132.2297 + }
132.2298 +};
132.2299 +// For certain common events (currently just 'click'), allow a simplified data-binding syntax
132.2300 +// e.g. click:handler instead of the usual full-length event:{click:handler}
132.2301 +function makeEventHandlerShortcut(eventName) {
132.2302 + ko.bindingHandlers[eventName] = {
132.2303 + 'init': function(element, valueAccessor, allBindingsAccessor, viewModel) {
132.2304 + var newValueAccessor = function () {
132.2305 + var result = {};
132.2306 + result[eventName] = valueAccessor();
132.2307 + return result;
132.2308 + };
132.2309 + return ko.bindingHandlers['event']['init'].call(this, element, newValueAccessor, allBindingsAccessor, viewModel);
132.2310 + }
132.2311 + }
132.2312 +}
132.2313 +
132.2314 +ko.bindingHandlers['event'] = {
132.2315 + 'init' : function (element, valueAccessor, allBindingsAccessor, viewModel) {
132.2316 + var eventsToHandle = valueAccessor() || {};
132.2317 + for(var eventNameOutsideClosure in eventsToHandle) {
132.2318 + (function() {
132.2319 + var eventName = eventNameOutsideClosure; // Separate variable to be captured by event handler closure
132.2320 + if (typeof eventName == "string") {
132.2321 + ko.utils.registerEventHandler(element, eventName, function (event) {
132.2322 + var handlerReturnValue;
132.2323 + var handlerFunction = valueAccessor()[eventName];
132.2324 + if (!handlerFunction)
132.2325 + return;
132.2326 + var allBindings = allBindingsAccessor();
132.2327 +
132.2328 + try {
132.2329 + // Take all the event args, and prefix with the viewmodel
132.2330 + var argsForHandler = ko.utils.makeArray(arguments);
132.2331 + argsForHandler.unshift(viewModel);
132.2332 + handlerReturnValue = handlerFunction.apply(viewModel, argsForHandler);
132.2333 + } finally {
132.2334 + if (handlerReturnValue !== true) { // Normally we want to prevent default action. Developer can override this be explicitly returning true.
132.2335 + if (event.preventDefault)
132.2336 + event.preventDefault();
132.2337 + else
132.2338 + event.returnValue = false;
132.2339 + }
132.2340 + }
132.2341 +
132.2342 + var bubble = allBindings[eventName + 'Bubble'] !== false;
132.2343 + if (!bubble) {
132.2344 + event.cancelBubble = true;
132.2345 + if (event.stopPropagation)
132.2346 + event.stopPropagation();
132.2347 + }
132.2348 + });
132.2349 + }
132.2350 + })();
132.2351 + }
132.2352 + }
132.2353 +};
132.2354 +// "foreach: someExpression" is equivalent to "template: { foreach: someExpression }"
132.2355 +// "foreach: { data: someExpression, afterAdd: myfn }" is equivalent to "template: { foreach: someExpression, afterAdd: myfn }"
132.2356 +ko.bindingHandlers['foreach'] = {
132.2357 + makeTemplateValueAccessor: function(valueAccessor) {
132.2358 + return function() {
132.2359 + var modelValue = valueAccessor(),
132.2360 + unwrappedValue = ko.utils.peekObservable(modelValue); // Unwrap without setting a dependency here
132.2361 +
132.2362 + // If unwrappedValue is the array, pass in the wrapped value on its own
132.2363 + // The value will be unwrapped and tracked within the template binding
132.2364 + // (See https://github.com/SteveSanderson/knockout/issues/523)
132.2365 + if ((!unwrappedValue) || typeof unwrappedValue.length == "number")
132.2366 + return { 'foreach': modelValue, 'templateEngine': ko.nativeTemplateEngine.instance };
132.2367 +
132.2368 + // If unwrappedValue.data is the array, preserve all relevant options and unwrap again value so we get updates
132.2369 + ko.utils.unwrapObservable(modelValue);
132.2370 + return {
132.2371 + 'foreach': unwrappedValue['data'],
132.2372 + 'as': unwrappedValue['as'],
132.2373 + 'includeDestroyed': unwrappedValue['includeDestroyed'],
132.2374 + 'afterAdd': unwrappedValue['afterAdd'],
132.2375 + 'beforeRemove': unwrappedValue['beforeRemove'],
132.2376 + 'afterRender': unwrappedValue['afterRender'],
132.2377 + 'beforeMove': unwrappedValue['beforeMove'],
132.2378 + 'afterMove': unwrappedValue['afterMove'],
132.2379 + 'templateEngine': ko.nativeTemplateEngine.instance
132.2380 + };
132.2381 + };
132.2382 + },
132.2383 + 'init': function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
132.2384 + return ko.bindingHandlers['template']['init'](element, ko.bindingHandlers['foreach'].makeTemplateValueAccessor(valueAccessor));
132.2385 + },
132.2386 + 'update': function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
132.2387 + return ko.bindingHandlers['template']['update'](element, ko.bindingHandlers['foreach'].makeTemplateValueAccessor(valueAccessor), allBindingsAccessor, viewModel, bindingContext);
132.2388 + }
132.2389 +};
132.2390 +ko.expressionRewriting.bindingRewriteValidators['foreach'] = false; // Can't rewrite control flow bindings
132.2391 +ko.virtualElements.allowedBindings['foreach'] = true;
132.2392 +var hasfocusUpdatingProperty = '__ko_hasfocusUpdating';
132.2393 +ko.bindingHandlers['hasfocus'] = {
132.2394 + 'init': function(element, valueAccessor, allBindingsAccessor) {
132.2395 + var handleElementFocusChange = function(isFocused) {
132.2396 + // Where possible, ignore which event was raised and determine focus state using activeElement,
132.2397 + // as this avoids phantom focus/blur events raised when changing tabs in modern browsers.
132.2398 + // However, not all KO-targeted browsers (Firefox 2) support activeElement. For those browsers,
132.2399 + // prevent a loss of focus when changing tabs/windows by setting a flag that prevents hasfocus
132.2400 + // from calling 'blur()' on the element when it loses focus.
132.2401 + // Discussion at https://github.com/SteveSanderson/knockout/pull/352
132.2402 + element[hasfocusUpdatingProperty] = true;
132.2403 + var ownerDoc = element.ownerDocument;
132.2404 + if ("activeElement" in ownerDoc) {
132.2405 + isFocused = (ownerDoc.activeElement === element);
132.2406 + }
132.2407 + var modelValue = valueAccessor();
132.2408 + ko.expressionRewriting.writeValueToProperty(modelValue, allBindingsAccessor, 'hasfocus', isFocused, true);
132.2409 + element[hasfocusUpdatingProperty] = false;
132.2410 + };
132.2411 + var handleElementFocusIn = handleElementFocusChange.bind(null, true);
132.2412 + var handleElementFocusOut = handleElementFocusChange.bind(null, false);
132.2413 +
132.2414 + ko.utils.registerEventHandler(element, "focus", handleElementFocusIn);
132.2415 + ko.utils.registerEventHandler(element, "focusin", handleElementFocusIn); // For IE
132.2416 + ko.utils.registerEventHandler(element, "blur", handleElementFocusOut);
132.2417 + ko.utils.registerEventHandler(element, "focusout", handleElementFocusOut); // For IE
132.2418 + },
132.2419 + 'update': function(element, valueAccessor) {
132.2420 + var value = ko.utils.unwrapObservable(valueAccessor());
132.2421 + if (!element[hasfocusUpdatingProperty]) {
132.2422 + value ? element.focus() : element.blur();
132.2423 + ko.dependencyDetection.ignore(ko.utils.triggerEvent, null, [element, value ? "focusin" : "focusout"]); // For IE, which doesn't reliably fire "focus" or "blur" events synchronously
132.2424 + }
132.2425 + }
132.2426 +};
132.2427 +ko.bindingHandlers['html'] = {
132.2428 + 'init': function() {
132.2429 + // Prevent binding on the dynamically-injected HTML (as developers are unlikely to expect that, and it has security implications)
132.2430 + return { 'controlsDescendantBindings': true };
132.2431 + },
132.2432 + 'update': function (element, valueAccessor) {
132.2433 + // setHtml will unwrap the value if needed
132.2434 + ko.utils.setHtml(element, valueAccessor());
132.2435 + }
132.2436 +};
132.2437 +var withIfDomDataKey = '__ko_withIfBindingData';
132.2438 +// Makes a binding like with or if
132.2439 +function makeWithIfBinding(bindingKey, isWith, isNot, makeContextCallback) {
132.2440 + ko.bindingHandlers[bindingKey] = {
132.2441 + 'init': function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
132.2442 + ko.utils.domData.set(element, withIfDomDataKey, {});
132.2443 + return { 'controlsDescendantBindings': true };
132.2444 + },
132.2445 + 'update': function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
132.2446 + var withIfData = ko.utils.domData.get(element, withIfDomDataKey),
132.2447 + dataValue = ko.utils.unwrapObservable(valueAccessor()),
132.2448 + shouldDisplay = !isNot !== !dataValue, // equivalent to isNot ? !dataValue : !!dataValue
132.2449 + isFirstRender = !withIfData.savedNodes,
132.2450 + needsRefresh = isFirstRender || isWith || (shouldDisplay !== withIfData.didDisplayOnLastUpdate);
132.2451 +
132.2452 + if (needsRefresh) {
132.2453 + if (isFirstRender) {
132.2454 + withIfData.savedNodes = ko.utils.cloneNodes(ko.virtualElements.childNodes(element), true /* shouldCleanNodes */);
132.2455 + }
132.2456 +
132.2457 + if (shouldDisplay) {
132.2458 + if (!isFirstRender) {
132.2459 + ko.virtualElements.setDomNodeChildren(element, ko.utils.cloneNodes(withIfData.savedNodes));
132.2460 + }
132.2461 + ko.applyBindingsToDescendants(makeContextCallback ? makeContextCallback(bindingContext, dataValue) : bindingContext, element);
132.2462 + } else {
132.2463 + ko.virtualElements.emptyNode(element);
132.2464 + }
132.2465 +
132.2466 + withIfData.didDisplayOnLastUpdate = shouldDisplay;
132.2467 + }
132.2468 + }
132.2469 + };
132.2470 + ko.expressionRewriting.bindingRewriteValidators[bindingKey] = false; // Can't rewrite control flow bindings
132.2471 + ko.virtualElements.allowedBindings[bindingKey] = true;
132.2472 +}
132.2473 +
132.2474 +// Construct the actual binding handlers
132.2475 +makeWithIfBinding('if');
132.2476 +makeWithIfBinding('ifnot', false /* isWith */, true /* isNot */);
132.2477 +makeWithIfBinding('with', true /* isWith */, false /* isNot */,
132.2478 + function(bindingContext, dataValue) {
132.2479 + return bindingContext['createChildContext'](dataValue);
132.2480 + }
132.2481 +);
132.2482 +function ensureDropdownSelectionIsConsistentWithModelValue(element, modelValue, preferModelValue) {
132.2483 + if (preferModelValue) {
132.2484 + if (modelValue !== ko.selectExtensions.readValue(element))
132.2485 + ko.selectExtensions.writeValue(element, modelValue);
132.2486 + }
132.2487 +
132.2488 + // No matter which direction we're syncing in, we want the end result to be equality between dropdown value and model value.
132.2489 + // If they aren't equal, either we prefer the dropdown value, or the model value couldn't be represented, so either way,
132.2490 + // change the model value to match the dropdown.
132.2491 + if (modelValue !== ko.selectExtensions.readValue(element))
132.2492 + ko.dependencyDetection.ignore(ko.utils.triggerEvent, null, [element, "change"]);
132.2493 +};
132.2494 +
132.2495 +ko.bindingHandlers['options'] = {
132.2496 + 'update': function (element, valueAccessor, allBindingsAccessor) {
132.2497 + if (ko.utils.tagNameLower(element) !== "select")
132.2498 + throw new Error("options binding applies only to SELECT elements");
132.2499 +
132.2500 + var selectWasPreviouslyEmpty = element.length == 0;
132.2501 + var previousSelectedValues = ko.utils.arrayMap(ko.utils.arrayFilter(element.childNodes, function (node) {
132.2502 + return node.tagName && (ko.utils.tagNameLower(node) === "option") && node.selected;
132.2503 + }), function (node) {
132.2504 + return ko.selectExtensions.readValue(node) || node.innerText || node.textContent;
132.2505 + });
132.2506 + var previousScrollTop = element.scrollTop;
132.2507 +
132.2508 + var value = ko.utils.unwrapObservable(valueAccessor());
132.2509 + var selectedValue = element.value;
132.2510 +
132.2511 + // Remove all existing <option>s.
132.2512 + // Need to use .remove() rather than .removeChild() for <option>s otherwise IE behaves oddly (https://github.com/SteveSanderson/knockout/issues/134)
132.2513 + while (element.length > 0) {
132.2514 + ko.cleanNode(element.options[0]);
132.2515 + element.remove(0);
132.2516 + }
132.2517 +
132.2518 + if (value) {
132.2519 + var allBindings = allBindingsAccessor(),
132.2520 + includeDestroyed = allBindings['optionsIncludeDestroyed'];
132.2521 +
132.2522 + if (typeof value.length != "number")
132.2523 + value = [value];
132.2524 + if (allBindings['optionsCaption']) {
132.2525 + var option = document.createElement("option");
132.2526 + ko.utils.setHtml(option, allBindings['optionsCaption']);
132.2527 + ko.selectExtensions.writeValue(option, undefined);
132.2528 + element.appendChild(option);
132.2529 + }
132.2530 +
132.2531 + for (var i = 0, j = value.length; i < j; i++) {
132.2532 + // Skip destroyed items
132.2533 + var arrayEntry = value[i];
132.2534 + if (arrayEntry && arrayEntry['_destroy'] && !includeDestroyed)
132.2535 + continue;
132.2536 +
132.2537 + var option = document.createElement("option");
132.2538 +
132.2539 + function applyToObject(object, predicate, defaultValue) {
132.2540 + var predicateType = typeof predicate;
132.2541 + if (predicateType == "function") // Given a function; run it against the data value
132.2542 + return predicate(object);
132.2543 + else if (predicateType == "string") // Given a string; treat it as a property name on the data value
132.2544 + return object[predicate];
132.2545 + else // Given no optionsText arg; use the data value itself
132.2546 + return defaultValue;
132.2547 + }
132.2548 +
132.2549 + // Apply a value to the option element
132.2550 + var optionValue = applyToObject(arrayEntry, allBindings['optionsValue'], arrayEntry);
132.2551 + ko.selectExtensions.writeValue(option, ko.utils.unwrapObservable(optionValue));
132.2552 +
132.2553 + // Apply some text to the option element
132.2554 + var optionText = applyToObject(arrayEntry, allBindings['optionsText'], optionValue);
132.2555 + ko.utils.setTextContent(option, optionText);
132.2556 +
132.2557 + element.appendChild(option);
132.2558 + }
132.2559 +
132.2560 + // IE6 doesn't like us to assign selection to OPTION nodes before they're added to the document.
132.2561 + // That's why we first added them without selection. Now it's time to set the selection.
132.2562 + var newOptions = element.getElementsByTagName("option");
132.2563 + var countSelectionsRetained = 0;
132.2564 + for (var i = 0, j = newOptions.length; i < j; i++) {
132.2565 + if (ko.utils.arrayIndexOf(previousSelectedValues, ko.selectExtensions.readValue(newOptions[i])) >= 0) {
132.2566 + ko.utils.setOptionNodeSelectionState(newOptions[i], true);
132.2567 + countSelectionsRetained++;
132.2568 + }
132.2569 + }
132.2570 +
132.2571 + element.scrollTop = previousScrollTop;
132.2572 +
132.2573 + if (selectWasPreviouslyEmpty && ('value' in allBindings)) {
132.2574 + // Ensure consistency between model value and selected option.
132.2575 + // If the dropdown is being populated for the first time here (or was otherwise previously empty),
132.2576 + // the dropdown selection state is meaningless, so we preserve the model value.
132.2577 + ensureDropdownSelectionIsConsistentWithModelValue(element, ko.utils.peekObservable(allBindings['value']), /* preferModelValue */ true);
132.2578 + }
132.2579 +
132.2580 + // Workaround for IE9 bug
132.2581 + ko.utils.ensureSelectElementIsRenderedCorrectly(element);
132.2582 + }
132.2583 + }
132.2584 +};
132.2585 +ko.bindingHandlers['options'].optionValueDomDataKey = '__ko.optionValueDomData__';
132.2586 +ko.bindingHandlers['selectedOptions'] = {
132.2587 + 'init': function (element, valueAccessor, allBindingsAccessor) {
132.2588 + ko.utils.registerEventHandler(element, "change", function () {
132.2589 + var value = valueAccessor(), valueToWrite = [];
132.2590 + ko.utils.arrayForEach(element.getElementsByTagName("option"), function(node) {
132.2591 + if (node.selected)
132.2592 + valueToWrite.push(ko.selectExtensions.readValue(node));
132.2593 + });
132.2594 + ko.expressionRewriting.writeValueToProperty(value, allBindingsAccessor, 'value', valueToWrite);
132.2595 + });
132.2596 + },
132.2597 + 'update': function (element, valueAccessor) {
132.2598 + if (ko.utils.tagNameLower(element) != "select")
132.2599 + throw new Error("values binding applies only to SELECT elements");
132.2600 +
132.2601 + var newValue = ko.utils.unwrapObservable(valueAccessor());
132.2602 + if (newValue && typeof newValue.length == "number") {
132.2603 + ko.utils.arrayForEach(element.getElementsByTagName("option"), function(node) {
132.2604 + var isSelected = ko.utils.arrayIndexOf(newValue, ko.selectExtensions.readValue(node)) >= 0;
132.2605 + ko.utils.setOptionNodeSelectionState(node, isSelected);
132.2606 + });
132.2607 + }
132.2608 + }
132.2609 +};
132.2610 +ko.bindingHandlers['style'] = {
132.2611 + 'update': function (element, valueAccessor) {
132.2612 + var value = ko.utils.unwrapObservable(valueAccessor() || {});
132.2613 + for (var styleName in value) {
132.2614 + if (typeof styleName == "string") {
132.2615 + var styleValue = ko.utils.unwrapObservable(value[styleName]);
132.2616 + element.style[styleName] = styleValue || ""; // Empty string removes the value, whereas null/undefined have no effect
132.2617 + }
132.2618 + }
132.2619 + }
132.2620 +};
132.2621 +ko.bindingHandlers['submit'] = {
132.2622 + 'init': function (element, valueAccessor, allBindingsAccessor, viewModel) {
132.2623 + if (typeof valueAccessor() != "function")
132.2624 + throw new Error("The value for a submit binding must be a function");
132.2625 + ko.utils.registerEventHandler(element, "submit", function (event) {
132.2626 + var handlerReturnValue;
132.2627 + var value = valueAccessor();
132.2628 + try { handlerReturnValue = value.call(viewModel, element); }
132.2629 + finally {
132.2630 + if (handlerReturnValue !== true) { // Normally we want to prevent default action. Developer can override this be explicitly returning true.
132.2631 + if (event.preventDefault)
132.2632 + event.preventDefault();
132.2633 + else
132.2634 + event.returnValue = false;
132.2635 + }
132.2636 + }
132.2637 + });
132.2638 + }
132.2639 +};
132.2640 +ko.bindingHandlers['text'] = {
132.2641 + 'update': function (element, valueAccessor) {
132.2642 + ko.utils.setTextContent(element, valueAccessor());
132.2643 + }
132.2644 +};
132.2645 +ko.virtualElements.allowedBindings['text'] = true;
132.2646 +ko.bindingHandlers['uniqueName'] = {
132.2647 + 'init': function (element, valueAccessor) {
132.2648 + if (valueAccessor()) {
132.2649 + var name = "ko_unique_" + (++ko.bindingHandlers['uniqueName'].currentIndex);
132.2650 + ko.utils.setElementName(element, name);
132.2651 + }
132.2652 + }
132.2653 +};
132.2654 +ko.bindingHandlers['uniqueName'].currentIndex = 0;
132.2655 +ko.bindingHandlers['value'] = {
132.2656 + 'init': function (element, valueAccessor, allBindingsAccessor) {
132.2657 + // Always catch "change" event; possibly other events too if asked
132.2658 + var eventsToCatch = ["change"];
132.2659 + var requestedEventsToCatch = allBindingsAccessor()["valueUpdate"];
132.2660 + var propertyChangedFired = false;
132.2661 + if (requestedEventsToCatch) {
132.2662 + if (typeof requestedEventsToCatch == "string") // Allow both individual event names, and arrays of event names
132.2663 + requestedEventsToCatch = [requestedEventsToCatch];
132.2664 + ko.utils.arrayPushAll(eventsToCatch, requestedEventsToCatch);
132.2665 + eventsToCatch = ko.utils.arrayGetDistinctValues(eventsToCatch);
132.2666 + }
132.2667 +
132.2668 + var valueUpdateHandler = function() {
132.2669 + propertyChangedFired = false;
132.2670 + var modelValue = valueAccessor();
132.2671 + var elementValue = ko.selectExtensions.readValue(element);
132.2672 + ko.expressionRewriting.writeValueToProperty(modelValue, allBindingsAccessor, 'value', elementValue);
132.2673 + }
132.2674 +
132.2675 + // Workaround for https://github.com/SteveSanderson/knockout/issues/122
132.2676 + // IE doesn't fire "change" events on textboxes if the user selects a value from its autocomplete list
132.2677 + var ieAutoCompleteHackNeeded = ko.utils.ieVersion && element.tagName.toLowerCase() == "input" && element.type == "text"
132.2678 + && element.autocomplete != "off" && (!element.form || element.form.autocomplete != "off");
132.2679 + if (ieAutoCompleteHackNeeded && ko.utils.arrayIndexOf(eventsToCatch, "propertychange") == -1) {
132.2680 + ko.utils.registerEventHandler(element, "propertychange", function () { propertyChangedFired = true });
132.2681 + ko.utils.registerEventHandler(element, "blur", function() {
132.2682 + if (propertyChangedFired) {
132.2683 + valueUpdateHandler();
132.2684 + }
132.2685 + });
132.2686 + }
132.2687 +
132.2688 + ko.utils.arrayForEach(eventsToCatch, function(eventName) {
132.2689 + // The syntax "after<eventname>" means "run the handler asynchronously after the event"
132.2690 + // This is useful, for example, to catch "keydown" events after the browser has updated the control
132.2691 + // (otherwise, ko.selectExtensions.readValue(this) will receive the control's value *before* the key event)
132.2692 + var handler = valueUpdateHandler;
132.2693 + if (ko.utils.stringStartsWith(eventName, "after")) {
132.2694 + handler = function() { setTimeout(valueUpdateHandler, 0) };
132.2695 + eventName = eventName.substring("after".length);
132.2696 + }
132.2697 + ko.utils.registerEventHandler(element, eventName, handler);
132.2698 + });
132.2699 + },
132.2700 + 'update': function (element, valueAccessor) {
132.2701 + var valueIsSelectOption = ko.utils.tagNameLower(element) === "select";
132.2702 + var newValue = ko.utils.unwrapObservable(valueAccessor());
132.2703 + var elementValue = ko.selectExtensions.readValue(element);
132.2704 + var valueHasChanged = (newValue != elementValue);
132.2705 +
132.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).
132.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.
132.2708 + if ((newValue === 0) && (elementValue !== 0) && (elementValue !== "0"))
132.2709 + valueHasChanged = true;
132.2710 +
132.2711 + if (valueHasChanged) {
132.2712 + var applyValueAction = function () { ko.selectExtensions.writeValue(element, newValue); };
132.2713 + applyValueAction();
132.2714 +
132.2715 + // Workaround for IE6 bug: It won't reliably apply values to SELECT nodes during the same execution thread
132.2716 + // right after you've changed the set of OPTION nodes on it. So for that node type, we'll schedule a second thread
132.2717 + // to apply the value as well.
132.2718 + var alsoApplyAsynchronously = valueIsSelectOption;
132.2719 + if (alsoApplyAsynchronously)
132.2720 + setTimeout(applyValueAction, 0);
132.2721 + }
132.2722 +
132.2723 + // If you try to set a model value that can't be represented in an already-populated dropdown, reject that change,
132.2724 + // because you're not allowed to have a model value that disagrees with a visible UI selection.
132.2725 + if (valueIsSelectOption && (element.length > 0))
132.2726 + ensureDropdownSelectionIsConsistentWithModelValue(element, newValue, /* preferModelValue */ false);
132.2727 + }
132.2728 +};
132.2729 +ko.bindingHandlers['visible'] = {
132.2730 + 'update': function (element, valueAccessor) {
132.2731 + var value = ko.utils.unwrapObservable(valueAccessor());
132.2732 + var isCurrentlyVisible = !(element.style.display == "none");
132.2733 + if (value && !isCurrentlyVisible)
132.2734 + element.style.display = "";
132.2735 + else if ((!value) && isCurrentlyVisible)
132.2736 + element.style.display = "none";
132.2737 + }
132.2738 +};
132.2739 +// 'click' is just a shorthand for the usual full-length event:{click:handler}
132.2740 +makeEventHandlerShortcut('click');
132.2741 +// If you want to make a custom template engine,
132.2742 +//
132.2743 +// [1] Inherit from this class (like ko.nativeTemplateEngine does)
132.2744 +// [2] Override 'renderTemplateSource', supplying a function with this signature:
132.2745 +//
132.2746 +// function (templateSource, bindingContext, options) {
132.2747 +// // - templateSource.text() is the text of the template you should render
132.2748 +// // - bindingContext.$data is the data you should pass into the template
132.2749 +// // - you might also want to make bindingContext.$parent, bindingContext.$parents,
132.2750 +// // and bindingContext.$root available in the template too
132.2751 +// // - options gives you access to any other properties set on "data-bind: { template: options }"
132.2752 +// //
132.2753 +// // Return value: an array of DOM nodes
132.2754 +// }
132.2755 +//
132.2756 +// [3] Override 'createJavaScriptEvaluatorBlock', supplying a function with this signature:
132.2757 +//
132.2758 +// function (script) {
132.2759 +// // Return value: Whatever syntax means "Evaluate the JavaScript statement 'script' and output the result"
132.2760 +// // For example, the jquery.tmpl template engine converts 'someScript' to '${ someScript }'
132.2761 +// }
132.2762 +//
132.2763 +// This is only necessary if you want to allow data-bind attributes to reference arbitrary template variables.
132.2764 +// If you don't want to allow that, you can set the property 'allowTemplateRewriting' to false (like ko.nativeTemplateEngine does)
132.2765 +// and then you don't need to override 'createJavaScriptEvaluatorBlock'.
132.2766 +
132.2767 +ko.templateEngine = function () { };
132.2768 +
132.2769 +ko.templateEngine.prototype['renderTemplateSource'] = function (templateSource, bindingContext, options) {
132.2770 + throw new Error("Override renderTemplateSource");
132.2771 +};
132.2772 +
132.2773 +ko.templateEngine.prototype['createJavaScriptEvaluatorBlock'] = function (script) {
132.2774 + throw new Error("Override createJavaScriptEvaluatorBlock");
132.2775 +};
132.2776 +
132.2777 +ko.templateEngine.prototype['makeTemplateSource'] = function(template, templateDocument) {
132.2778 + // Named template
132.2779 + if (typeof template == "string") {
132.2780 + templateDocument = templateDocument || document;
132.2781 + var elem = templateDocument.getElementById(template);
132.2782 + if (!elem)
132.2783 + throw new Error("Cannot find template with ID " + template);
132.2784 + return new ko.templateSources.domElement(elem);
132.2785 + } else if ((template.nodeType == 1) || (template.nodeType == 8)) {
132.2786 + // Anonymous template
132.2787 + return new ko.templateSources.anonymousTemplate(template);
132.2788 + } else
132.2789 + throw new Error("Unknown template type: " + template);
132.2790 +};
132.2791 +
132.2792 +ko.templateEngine.prototype['renderTemplate'] = function (template, bindingContext, options, templateDocument) {
132.2793 + var templateSource = this['makeTemplateSource'](template, templateDocument);
132.2794 + return this['renderTemplateSource'](templateSource, bindingContext, options);
132.2795 +};
132.2796 +
132.2797 +ko.templateEngine.prototype['isTemplateRewritten'] = function (template, templateDocument) {
132.2798 + // Skip rewriting if requested
132.2799 + if (this['allowTemplateRewriting'] === false)
132.2800 + return true;
132.2801 + return this['makeTemplateSource'](template, templateDocument)['data']("isRewritten");
132.2802 +};
132.2803 +
132.2804 +ko.templateEngine.prototype['rewriteTemplate'] = function (template, rewriterCallback, templateDocument) {
132.2805 + var templateSource = this['makeTemplateSource'](template, templateDocument);
132.2806 + var rewritten = rewriterCallback(templateSource['text']());
132.2807 + templateSource['text'](rewritten);
132.2808 + templateSource['data']("isRewritten", true);
132.2809 +};
132.2810 +
132.2811 +ko.exportSymbol('templateEngine', ko.templateEngine);
132.2812 +
132.2813 +ko.templateRewriting = (function () {
132.2814 + var memoizeDataBindingAttributeSyntaxRegex = /(<[a-z]+\d*(\s+(?!data-bind=)[a-z0-9\-]+(=(\"[^\"]*\"|\'[^\']*\'))?)*\s+)data-bind=(["'])([\s\S]*?)\5/gi;
132.2815 + var memoizeVirtualContainerBindingSyntaxRegex = /<!--\s*ko\b\s*([\s\S]*?)\s*-->/g;
132.2816 +
132.2817 + function validateDataBindValuesForRewriting(keyValueArray) {
132.2818 + var allValidators = ko.expressionRewriting.bindingRewriteValidators;
132.2819 + for (var i = 0; i < keyValueArray.length; i++) {
132.2820 + var key = keyValueArray[i]['key'];
132.2821 + if (allValidators.hasOwnProperty(key)) {
132.2822 + var validator = allValidators[key];
132.2823 +
132.2824 + if (typeof validator === "function") {
132.2825 + var possibleErrorMessage = validator(keyValueArray[i]['value']);
132.2826 + if (possibleErrorMessage)
132.2827 + throw new Error(possibleErrorMessage);
132.2828 + } else if (!validator) {
132.2829 + throw new Error("This template engine does not support the '" + key + "' binding within its templates");
132.2830 + }
132.2831 + }
132.2832 + }
132.2833 + }
132.2834 +
132.2835 + function constructMemoizedTagReplacement(dataBindAttributeValue, tagToRetain, templateEngine) {
132.2836 + var dataBindKeyValueArray = ko.expressionRewriting.parseObjectLiteral(dataBindAttributeValue);
132.2837 + validateDataBindValuesForRewriting(dataBindKeyValueArray);
132.2838 + var rewrittenDataBindAttributeValue = ko.expressionRewriting.preProcessBindings(dataBindKeyValueArray);
132.2839 +
132.2840 + // For no obvious reason, Opera fails to evaluate rewrittenDataBindAttributeValue unless it's wrapped in an additional
132.2841 + // anonymous function, even though Opera's built-in debugger can evaluate it anyway. No other browser requires this
132.2842 + // extra indirection.
132.2843 + var applyBindingsToNextSiblingScript =
132.2844 + "ko.__tr_ambtns(function($context,$element){return(function(){return{ " + rewrittenDataBindAttributeValue + " } })()})";
132.2845 + return templateEngine['createJavaScriptEvaluatorBlock'](applyBindingsToNextSiblingScript) + tagToRetain;
132.2846 + }
132.2847 +
132.2848 + return {
132.2849 + ensureTemplateIsRewritten: function (template, templateEngine, templateDocument) {
132.2850 + if (!templateEngine['isTemplateRewritten'](template, templateDocument))
132.2851 + templateEngine['rewriteTemplate'](template, function (htmlString) {
132.2852 + return ko.templateRewriting.memoizeBindingAttributeSyntax(htmlString, templateEngine);
132.2853 + }, templateDocument);
132.2854 + },
132.2855 +
132.2856 + memoizeBindingAttributeSyntax: function (htmlString, templateEngine) {
132.2857 + return htmlString.replace(memoizeDataBindingAttributeSyntaxRegex, function () {
132.2858 + return constructMemoizedTagReplacement(/* dataBindAttributeValue: */ arguments[6], /* tagToRetain: */ arguments[1], templateEngine);
132.2859 + }).replace(memoizeVirtualContainerBindingSyntaxRegex, function() {
132.2860 + return constructMemoizedTagReplacement(/* dataBindAttributeValue: */ arguments[1], /* tagToRetain: */ "<!-- ko -->", templateEngine);
132.2861 + });
132.2862 + },
132.2863 +
132.2864 + applyMemoizedBindingsToNextSibling: function (bindings) {
132.2865 + return ko.memoization.memoize(function (domNode, bindingContext) {
132.2866 + if (domNode.nextSibling)
132.2867 + ko.applyBindingsToNode(domNode.nextSibling, bindings, bindingContext);
132.2868 + });
132.2869 + }
132.2870 + }
132.2871 +})();
132.2872 +
132.2873 +
132.2874 +// Exported only because it has to be referenced by string lookup from within rewritten template
132.2875 +ko.exportSymbol('__tr_ambtns', ko.templateRewriting.applyMemoizedBindingsToNextSibling);
132.2876 +(function() {
132.2877 + // A template source represents a read/write way of accessing a template. This is to eliminate the need for template loading/saving
132.2878 + // logic to be duplicated in every template engine (and means they can all work with anonymous templates, etc.)
132.2879 + //
132.2880 + // Two are provided by default:
132.2881 + // 1. ko.templateSources.domElement - reads/writes the text content of an arbitrary DOM element
132.2882 + // 2. ko.templateSources.anonymousElement - uses ko.utils.domData to read/write text *associated* with the DOM element, but
132.2883 + // without reading/writing the actual element text content, since it will be overwritten
132.2884 + // with the rendered template output.
132.2885 + // You can implement your own template source if you want to fetch/store templates somewhere other than in DOM elements.
132.2886 + // Template sources need to have the following functions:
132.2887 + // text() - returns the template text from your storage location
132.2888 + // text(value) - writes the supplied template text to your storage location
132.2889 + // data(key) - reads values stored using data(key, value) - see below
132.2890 + // data(key, value) - associates "value" with this template and the key "key". Is used to store information like "isRewritten".
132.2891 + //
132.2892 + // Optionally, template sources can also have the following functions:
132.2893 + // nodes() - returns a DOM element containing the nodes of this template, where available
132.2894 + // nodes(value) - writes the given DOM element to your storage location
132.2895 + // If a DOM element is available for a given template source, template engines are encouraged to use it in preference over text()
132.2896 + // for improved speed. However, all templateSources must supply text() even if they don't supply nodes().
132.2897 + //
132.2898 + // Once you've implemented a templateSource, make your template engine use it by subclassing whatever template engine you were
132.2899 + // using and overriding "makeTemplateSource" to return an instance of your custom template source.
132.2900 +
132.2901 + ko.templateSources = {};
132.2902 +
132.2903 + // ---- ko.templateSources.domElement -----
132.2904 +
132.2905 + ko.templateSources.domElement = function(element) {
132.2906 + this.domElement = element;
132.2907 + }
132.2908 +
132.2909 + ko.templateSources.domElement.prototype['text'] = function(/* valueToWrite */) {
132.2910 + var tagNameLower = ko.utils.tagNameLower(this.domElement),
132.2911 + elemContentsProperty = tagNameLower === "script" ? "text"
132.2912 + : tagNameLower === "textarea" ? "value"
132.2913 + : "innerHTML";
132.2914 +
132.2915 + if (arguments.length == 0) {
132.2916 + return this.domElement[elemContentsProperty];
132.2917 + } else {
132.2918 + var valueToWrite = arguments[0];
132.2919 + if (elemContentsProperty === "innerHTML")
132.2920 + ko.utils.setHtml(this.domElement, valueToWrite);
132.2921 + else
132.2922 + this.domElement[elemContentsProperty] = valueToWrite;
132.2923 + }
132.2924 + };
132.2925 +
132.2926 + ko.templateSources.domElement.prototype['data'] = function(key /*, valueToWrite */) {
132.2927 + if (arguments.length === 1) {
132.2928 + return ko.utils.domData.get(this.domElement, "templateSourceData_" + key);
132.2929 + } else {
132.2930 + ko.utils.domData.set(this.domElement, "templateSourceData_" + key, arguments[1]);
132.2931 + }
132.2932 + };
132.2933 +
132.2934 + // ---- ko.templateSources.anonymousTemplate -----
132.2935 + // Anonymous templates are normally saved/retrieved as DOM nodes through "nodes".
132.2936 + // For compatibility, you can also read "text"; it will be serialized from the nodes on demand.
132.2937 + // Writing to "text" is still supported, but then the template data will not be available as DOM nodes.
132.2938 +
132.2939 + var anonymousTemplatesDomDataKey = "__ko_anon_template__";
132.2940 + ko.templateSources.anonymousTemplate = function(element) {
132.2941 + this.domElement = element;
132.2942 + }
132.2943 + ko.templateSources.anonymousTemplate.prototype = new ko.templateSources.domElement();
132.2944 + ko.templateSources.anonymousTemplate.prototype['text'] = function(/* valueToWrite */) {
132.2945 + if (arguments.length == 0) {
132.2946 + var templateData = ko.utils.domData.get(this.domElement, anonymousTemplatesDomDataKey) || {};
132.2947 + if (templateData.textData === undefined && templateData.containerData)
132.2948 + templateData.textData = templateData.containerData.innerHTML;
132.2949 + return templateData.textData;
132.2950 + } else {
132.2951 + var valueToWrite = arguments[0];
132.2952 + ko.utils.domData.set(this.domElement, anonymousTemplatesDomDataKey, {textData: valueToWrite});
132.2953 + }
132.2954 + };
132.2955 + ko.templateSources.domElement.prototype['nodes'] = function(/* valueToWrite */) {
132.2956 + if (arguments.length == 0) {
132.2957 + var templateData = ko.utils.domData.get(this.domElement, anonymousTemplatesDomDataKey) || {};
132.2958 + return templateData.containerData;
132.2959 + } else {
132.2960 + var valueToWrite = arguments[0];
132.2961 + ko.utils.domData.set(this.domElement, anonymousTemplatesDomDataKey, {containerData: valueToWrite});
132.2962 + }
132.2963 + };
132.2964 +
132.2965 + ko.exportSymbol('templateSources', ko.templateSources);
132.2966 + ko.exportSymbol('templateSources.domElement', ko.templateSources.domElement);
132.2967 + ko.exportSymbol('templateSources.anonymousTemplate', ko.templateSources.anonymousTemplate);
132.2968 +})();
132.2969 +(function () {
132.2970 + var _templateEngine;
132.2971 + ko.setTemplateEngine = function (templateEngine) {
132.2972 + if ((templateEngine != undefined) && !(templateEngine instanceof ko.templateEngine))
132.2973 + throw new Error("templateEngine must inherit from ko.templateEngine");
132.2974 + _templateEngine = templateEngine;
132.2975 + }
132.2976 +
132.2977 + function invokeForEachNodeOrCommentInContinuousRange(firstNode, lastNode, action) {
132.2978 + var node, nextInQueue = firstNode, firstOutOfRangeNode = ko.virtualElements.nextSibling(lastNode);
132.2979 + while (nextInQueue && ((node = nextInQueue) !== firstOutOfRangeNode)) {
132.2980 + nextInQueue = ko.virtualElements.nextSibling(node);
132.2981 + if (node.nodeType === 1 || node.nodeType === 8)
132.2982 + action(node);
132.2983 + }
132.2984 + }
132.2985 +
132.2986 + function activateBindingsOnContinuousNodeArray(continuousNodeArray, bindingContext) {
132.2987 + // To be used on any nodes that have been rendered by a template and have been inserted into some parent element
132.2988 + // Walks through continuousNodeArray (which *must* be continuous, i.e., an uninterrupted sequence of sibling nodes, because
132.2989 + // the algorithm for walking them relies on this), and for each top-level item in the virtual-element sense,
132.2990 + // (1) Does a regular "applyBindings" to associate bindingContext with this node and to activate any non-memoized bindings
132.2991 + // (2) Unmemoizes any memos in the DOM subtree (e.g., to activate bindings that had been memoized during template rewriting)
132.2992 +
132.2993 + if (continuousNodeArray.length) {
132.2994 + var firstNode = continuousNodeArray[0], lastNode = continuousNodeArray[continuousNodeArray.length - 1];
132.2995 +
132.2996 + // Need to applyBindings *before* unmemoziation, because unmemoization might introduce extra nodes (that we don't want to re-bind)
132.2997 + // whereas a regular applyBindings won't introduce new memoized nodes
132.2998 + invokeForEachNodeOrCommentInContinuousRange(firstNode, lastNode, function(node) {
132.2999 + ko.applyBindings(bindingContext, node);
132.3000 + });
132.3001 + invokeForEachNodeOrCommentInContinuousRange(firstNode, lastNode, function(node) {
132.3002 + ko.memoization.unmemoizeDomNodeAndDescendants(node, [bindingContext]);
132.3003 + });
132.3004 + }
132.3005 + }
132.3006 +
132.3007 + function getFirstNodeFromPossibleArray(nodeOrNodeArray) {
132.3008 + return nodeOrNodeArray.nodeType ? nodeOrNodeArray
132.3009 + : nodeOrNodeArray.length > 0 ? nodeOrNodeArray[0]
132.3010 + : null;
132.3011 + }
132.3012 +
132.3013 + function executeTemplate(targetNodeOrNodeArray, renderMode, template, bindingContext, options) {
132.3014 + options = options || {};
132.3015 + var firstTargetNode = targetNodeOrNodeArray && getFirstNodeFromPossibleArray(targetNodeOrNodeArray);
132.3016 + var templateDocument = firstTargetNode && firstTargetNode.ownerDocument;
132.3017 + var templateEngineToUse = (options['templateEngine'] || _templateEngine);
132.3018 + ko.templateRewriting.ensureTemplateIsRewritten(template, templateEngineToUse, templateDocument);
132.3019 + var renderedNodesArray = templateEngineToUse['renderTemplate'](template, bindingContext, options, templateDocument);
132.3020 +
132.3021 + // Loosely check result is an array of DOM nodes
132.3022 + if ((typeof renderedNodesArray.length != "number") || (renderedNodesArray.length > 0 && typeof renderedNodesArray[0].nodeType != "number"))
132.3023 + throw new Error("Template engine must return an array of DOM nodes");
132.3024 +
132.3025 + var haveAddedNodesToParent = false;
132.3026 + switch (renderMode) {
132.3027 + case "replaceChildren":
132.3028 + ko.virtualElements.setDomNodeChildren(targetNodeOrNodeArray, renderedNodesArray);
132.3029 + haveAddedNodesToParent = true;
132.3030 + break;
132.3031 + case "replaceNode":
132.3032 + ko.utils.replaceDomNodes(targetNodeOrNodeArray, renderedNodesArray);
132.3033 + haveAddedNodesToParent = true;
132.3034 + break;
132.3035 + case "ignoreTargetNode": break;
132.3036 + default:
132.3037 + throw new Error("Unknown renderMode: " + renderMode);
132.3038 + }
132.3039 +
132.3040 + if (haveAddedNodesToParent) {
132.3041 + activateBindingsOnContinuousNodeArray(renderedNodesArray, bindingContext);
132.3042 + if (options['afterRender'])
132.3043 + ko.dependencyDetection.ignore(options['afterRender'], null, [renderedNodesArray, bindingContext['$data']]);
132.3044 + }
132.3045 +
132.3046 + return renderedNodesArray;
132.3047 + }
132.3048 +
132.3049 + ko.renderTemplate = function (template, dataOrBindingContext, options, targetNodeOrNodeArray, renderMode) {
132.3050 + options = options || {};
132.3051 + if ((options['templateEngine'] || _templateEngine) == undefined)
132.3052 + throw new Error("Set a template engine before calling renderTemplate");
132.3053 + renderMode = renderMode || "replaceChildren";
132.3054 +
132.3055 + if (targetNodeOrNodeArray) {
132.3056 + var firstTargetNode = getFirstNodeFromPossibleArray(targetNodeOrNodeArray);
132.3057 +
132.3058 + var whenToDispose = function () { return (!firstTargetNode) || !ko.utils.domNodeIsAttachedToDocument(firstTargetNode); }; // Passive disposal (on next evaluation)
132.3059 + var activelyDisposeWhenNodeIsRemoved = (firstTargetNode && renderMode == "replaceNode") ? firstTargetNode.parentNode : firstTargetNode;
132.3060 +
132.3061 + return ko.dependentObservable( // So the DOM is automatically updated when any dependency changes
132.3062 + function () {
132.3063 + // Ensure we've got a proper binding context to work with
132.3064 + var bindingContext = (dataOrBindingContext && (dataOrBindingContext instanceof ko.bindingContext))
132.3065 + ? dataOrBindingContext
132.3066 + : new ko.bindingContext(ko.utils.unwrapObservable(dataOrBindingContext));
132.3067 +
132.3068 + // Support selecting template as a function of the data being rendered
132.3069 + var templateName = typeof(template) == 'function' ? template(bindingContext['$data'], bindingContext) : template;
132.3070 +
132.3071 + var renderedNodesArray = executeTemplate(targetNodeOrNodeArray, renderMode, templateName, bindingContext, options);
132.3072 + if (renderMode == "replaceNode") {
132.3073 + targetNodeOrNodeArray = renderedNodesArray;
132.3074 + firstTargetNode = getFirstNodeFromPossibleArray(targetNodeOrNodeArray);
132.3075 + }
132.3076 + },
132.3077 + null,
132.3078 + { disposeWhen: whenToDispose, disposeWhenNodeIsRemoved: activelyDisposeWhenNodeIsRemoved }
132.3079 + );
132.3080 + } else {
132.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
132.3082 + return ko.memoization.memoize(function (domNode) {
132.3083 + ko.renderTemplate(template, dataOrBindingContext, options, domNode, "replaceNode");
132.3084 + });
132.3085 + }
132.3086 + };
132.3087 +
132.3088 + ko.renderTemplateForEach = function (template, arrayOrObservableArray, options, targetNode, parentBindingContext) {
132.3089 + // Since setDomNodeChildrenFromArrayMapping always calls executeTemplateForArrayItem and then
132.3090 + // activateBindingsCallback for added items, we can store the binding context in the former to use in the latter.
132.3091 + var arrayItemContext;
132.3092 +
132.3093 + // This will be called by setDomNodeChildrenFromArrayMapping to get the nodes to add to targetNode
132.3094 + var executeTemplateForArrayItem = function (arrayValue, index) {
132.3095 + // Support selecting template as a function of the data being rendered
132.3096 + arrayItemContext = parentBindingContext['createChildContext'](ko.utils.unwrapObservable(arrayValue), options['as']);
132.3097 + arrayItemContext['$index'] = index;
132.3098 + var templateName = typeof(template) == 'function' ? template(arrayValue, arrayItemContext) : template;
132.3099 + return executeTemplate(null, "ignoreTargetNode", templateName, arrayItemContext, options);
132.3100 + }
132.3101 +
132.3102 + // This will be called whenever setDomNodeChildrenFromArrayMapping has added nodes to targetNode
132.3103 + var activateBindingsCallback = function(arrayValue, addedNodesArray, index) {
132.3104 + activateBindingsOnContinuousNodeArray(addedNodesArray, arrayItemContext);
132.3105 + if (options['afterRender'])
132.3106 + options['afterRender'](addedNodesArray, arrayValue);
132.3107 + };
132.3108 +
132.3109 + return ko.dependentObservable(function () {
132.3110 + var unwrappedArray = ko.utils.unwrapObservable(arrayOrObservableArray) || [];
132.3111 + if (typeof unwrappedArray.length == "undefined") // Coerce single value into array
132.3112 + unwrappedArray = [unwrappedArray];
132.3113 +
132.3114 + // Filter out any entries marked as destroyed
132.3115 + var filteredArray = ko.utils.arrayFilter(unwrappedArray, function(item) {
132.3116 + return options['includeDestroyed'] || item === undefined || item === null || !ko.utils.unwrapObservable(item['_destroy']);
132.3117 + });
132.3118 +
132.3119 + // Call setDomNodeChildrenFromArrayMapping, ignoring any observables unwrapped within (most likely from a callback function).
132.3120 + // If the array items are observables, though, they will be unwrapped in executeTemplateForArrayItem and managed within setDomNodeChildrenFromArrayMapping.
132.3121 + ko.dependencyDetection.ignore(ko.utils.setDomNodeChildrenFromArrayMapping, null, [targetNode, filteredArray, executeTemplateForArrayItem, options, activateBindingsCallback]);
132.3122 +
132.3123 + }, null, { disposeWhenNodeIsRemoved: targetNode });
132.3124 + };
132.3125 +
132.3126 + var templateComputedDomDataKey = '__ko__templateComputedDomDataKey__';
132.3127 + function disposeOldComputedAndStoreNewOne(element, newComputed) {
132.3128 + var oldComputed = ko.utils.domData.get(element, templateComputedDomDataKey);
132.3129 + if (oldComputed && (typeof(oldComputed.dispose) == 'function'))
132.3130 + oldComputed.dispose();
132.3131 + ko.utils.domData.set(element, templateComputedDomDataKey, (newComputed && newComputed.isActive()) ? newComputed : undefined);
132.3132 + }
132.3133 +
132.3134 + ko.bindingHandlers['template'] = {
132.3135 + 'init': function(element, valueAccessor) {
132.3136 + // Support anonymous templates
132.3137 + var bindingValue = ko.utils.unwrapObservable(valueAccessor());
132.3138 + if ((typeof bindingValue != "string") && (!bindingValue['name']) && (element.nodeType == 1 || element.nodeType == 8)) {
132.3139 + // It's an anonymous template - store the element contents, then clear the element
132.3140 + var templateNodes = element.nodeType == 1 ? element.childNodes : ko.virtualElements.childNodes(element),
132.3141 + container = ko.utils.moveCleanedNodesToContainerElement(templateNodes); // This also removes the nodes from their current parent
132.3142 + new ko.templateSources.anonymousTemplate(element)['nodes'](container);
132.3143 + }
132.3144 + return { 'controlsDescendantBindings': true };
132.3145 + },
132.3146 + 'update': function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
132.3147 + var templateName = ko.utils.unwrapObservable(valueAccessor()),
132.3148 + options = {},
132.3149 + shouldDisplay = true,
132.3150 + dataValue,
132.3151 + templateComputed = null;
132.3152 +
132.3153 + if (typeof templateName != "string") {
132.3154 + options = templateName;
132.3155 + templateName = options['name'];
132.3156 +
132.3157 + // Support "if"/"ifnot" conditions
132.3158 + if ('if' in options)
132.3159 + shouldDisplay = ko.utils.unwrapObservable(options['if']);
132.3160 + if (shouldDisplay && 'ifnot' in options)
132.3161 + shouldDisplay = !ko.utils.unwrapObservable(options['ifnot']);
132.3162 +
132.3163 + dataValue = ko.utils.unwrapObservable(options['data']);
132.3164 + }
132.3165 +
132.3166 + if ('foreach' in options) {
132.3167 + // Render once for each data point (treating data set as empty if shouldDisplay==false)
132.3168 + var dataArray = (shouldDisplay && options['foreach']) || [];
132.3169 + templateComputed = ko.renderTemplateForEach(templateName || element, dataArray, options, element, bindingContext);
132.3170 + } else if (!shouldDisplay) {
132.3171 + ko.virtualElements.emptyNode(element);
132.3172 + } else {
132.3173 + // Render once for this single data point (or use the viewModel if no data was provided)
132.3174 + var innerBindingContext = ('data' in options) ?
132.3175 + bindingContext['createChildContext'](dataValue, options['as']) : // Given an explitit 'data' value, we create a child binding context for it
132.3176 + bindingContext; // Given no explicit 'data' value, we retain the same binding context
132.3177 + templateComputed = ko.renderTemplate(templateName || element, innerBindingContext, options, element);
132.3178 + }
132.3179 +
132.3180 + // It only makes sense to have a single template computed per element (otherwise which one should have its output displayed?)
132.3181 + disposeOldComputedAndStoreNewOne(element, templateComputed);
132.3182 + }
132.3183 + };
132.3184 +
132.3185 + // Anonymous templates can't be rewritten. Give a nice error message if you try to do it.
132.3186 + ko.expressionRewriting.bindingRewriteValidators['template'] = function(bindingValue) {
132.3187 + var parsedBindingValue = ko.expressionRewriting.parseObjectLiteral(bindingValue);
132.3188 +
132.3189 + if ((parsedBindingValue.length == 1) && parsedBindingValue[0]['unknown'])
132.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)
132.3191 +
132.3192 + if (ko.expressionRewriting.keyValueArrayContainsKey(parsedBindingValue, "name"))
132.3193 + return null; // Named templates can be rewritten, so return "no error"
132.3194 + return "This template engine does not support anonymous templates nested within its templates";
132.3195 + };
132.3196 +
132.3197 + ko.virtualElements.allowedBindings['template'] = true;
132.3198 +})();
132.3199 +
132.3200 +ko.exportSymbol('setTemplateEngine', ko.setTemplateEngine);
132.3201 +ko.exportSymbol('renderTemplate', ko.renderTemplate);
132.3202 +
132.3203 +ko.utils.compareArrays = (function () {
132.3204 + var statusNotInOld = 'added', statusNotInNew = 'deleted';
132.3205 +
132.3206 + // Simple calculation based on Levenshtein distance.
132.3207 + function compareArrays(oldArray, newArray, dontLimitMoves) {
132.3208 + oldArray = oldArray || [];
132.3209 + newArray = newArray || [];
132.3210 +
132.3211 + if (oldArray.length <= newArray.length)
132.3212 + return compareSmallArrayToBigArray(oldArray, newArray, statusNotInOld, statusNotInNew, dontLimitMoves);
132.3213 + else
132.3214 + return compareSmallArrayToBigArray(newArray, oldArray, statusNotInNew, statusNotInOld, dontLimitMoves);
132.3215 + }
132.3216 +
132.3217 + function compareSmallArrayToBigArray(smlArray, bigArray, statusNotInSml, statusNotInBig, dontLimitMoves) {
132.3218 + var myMin = Math.min,
132.3219 + myMax = Math.max,
132.3220 + editDistanceMatrix = [],
132.3221 + smlIndex, smlIndexMax = smlArray.length,
132.3222 + bigIndex, bigIndexMax = bigArray.length,
132.3223 + compareRange = (bigIndexMax - smlIndexMax) || 1,
132.3224 + maxDistance = smlIndexMax + bigIndexMax + 1,
132.3225 + thisRow, lastRow,
132.3226 + bigIndexMaxForRow, bigIndexMinForRow;
132.3227 +
132.3228 + for (smlIndex = 0; smlIndex <= smlIndexMax; smlIndex++) {
132.3229 + lastRow = thisRow;
132.3230 + editDistanceMatrix.push(thisRow = []);
132.3231 + bigIndexMaxForRow = myMin(bigIndexMax, smlIndex + compareRange);
132.3232 + bigIndexMinForRow = myMax(0, smlIndex - 1);
132.3233 + for (bigIndex = bigIndexMinForRow; bigIndex <= bigIndexMaxForRow; bigIndex++) {
132.3234 + if (!bigIndex)
132.3235 + thisRow[bigIndex] = smlIndex + 1;
132.3236 + else if (!smlIndex) // Top row - transform empty array into new array via additions
132.3237 + thisRow[bigIndex] = bigIndex + 1;
132.3238 + else if (smlArray[smlIndex - 1] === bigArray[bigIndex - 1])
132.3239 + thisRow[bigIndex] = lastRow[bigIndex - 1]; // copy value (no edit)
132.3240 + else {
132.3241 + var northDistance = lastRow[bigIndex] || maxDistance; // not in big (deletion)
132.3242 + var westDistance = thisRow[bigIndex - 1] || maxDistance; // not in small (addition)
132.3243 + thisRow[bigIndex] = myMin(northDistance, westDistance) + 1;
132.3244 + }
132.3245 + }
132.3246 + }
132.3247 +
132.3248 + var editScript = [], meMinusOne, notInSml = [], notInBig = [];
132.3249 + for (smlIndex = smlIndexMax, bigIndex = bigIndexMax; smlIndex || bigIndex;) {
132.3250 + meMinusOne = editDistanceMatrix[smlIndex][bigIndex] - 1;
132.3251 + if (bigIndex && meMinusOne === editDistanceMatrix[smlIndex][bigIndex-1]) {
132.3252 + notInSml.push(editScript[editScript.length] = { // added
132.3253 + 'status': statusNotInSml,
132.3254 + 'value': bigArray[--bigIndex],
132.3255 + 'index': bigIndex });
132.3256 + } else if (smlIndex && meMinusOne === editDistanceMatrix[smlIndex - 1][bigIndex]) {
132.3257 + notInBig.push(editScript[editScript.length] = { // deleted
132.3258 + 'status': statusNotInBig,
132.3259 + 'value': smlArray[--smlIndex],
132.3260 + 'index': smlIndex });
132.3261 + } else {
132.3262 + editScript.push({
132.3263 + 'status': "retained",
132.3264 + 'value': bigArray[--bigIndex] });
132.3265 + --smlIndex;
132.3266 + }
132.3267 + }
132.3268 +
132.3269 + if (notInSml.length && notInBig.length) {
132.3270 + // Set a limit on the number of consecutive non-matching comparisons; having it a multiple of
132.3271 + // smlIndexMax keeps the time complexity of this algorithm linear.
132.3272 + var limitFailedCompares = smlIndexMax * 10, failedCompares,
132.3273 + a, d, notInSmlItem, notInBigItem;
132.3274 + // Go through the items that have been added and deleted and try to find matches between them.
132.3275 + for (failedCompares = a = 0; (dontLimitMoves || failedCompares < limitFailedCompares) && (notInSmlItem = notInSml[a]); a++) {
132.3276 + for (d = 0; notInBigItem = notInBig[d]; d++) {
132.3277 + if (notInSmlItem['value'] === notInBigItem['value']) {
132.3278 + notInSmlItem['moved'] = notInBigItem['index'];
132.3279 + notInBigItem['moved'] = notInSmlItem['index'];
132.3280 + notInBig.splice(d,1); // This item is marked as moved; so remove it from notInBig list
132.3281 + failedCompares = d = 0; // Reset failed compares count because we're checking for consecutive failures
132.3282 + break;
132.3283 + }
132.3284 + }
132.3285 + failedCompares += d;
132.3286 + }
132.3287 + }
132.3288 + return editScript.reverse();
132.3289 + }
132.3290 +
132.3291 + return compareArrays;
132.3292 +})();
132.3293 +
132.3294 +ko.exportSymbol('utils.compareArrays', ko.utils.compareArrays);
132.3295 +
132.3296 +(function () {
132.3297 + // Objective:
132.3298 + // * Given an input array, a container DOM node, and a function from array elements to arrays of DOM nodes,
132.3299 + // map the array elements to arrays of DOM nodes, concatenate together all these arrays, and use them to populate the container DOM node
132.3300 + // * Next time we're given the same combination of things (with the array possibly having mutated), update the container DOM node
132.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
132.3302 + // previously mapped - retain those nodes, and just insert/delete other ones
132.3303 +
132.3304 + // "callbackAfterAddingNodes" will be invoked after any "mapping"-generated nodes are inserted into the container node
132.3305 + // You can use this, for example, to activate bindings on those nodes.
132.3306 +
132.3307 + function fixUpNodesToBeMovedOrRemoved(contiguousNodeArray) {
132.3308 + // Before moving, deleting, or replacing a set of nodes that were previously outputted by the "map" function, we have to reconcile
132.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,
132.3310 + // or that new nodes might have been inserted in the middle, for example by a binding. Also, there may previously have been
132.3311 + // leading comment nodes (created by rewritten string-based templates) that have since been removed during binding.
132.3312 + // So, this function translates the old "map" output array into its best guess of what set of current DOM nodes should be removed.
132.3313 + //
132.3314 + // Rules:
132.3315 + // [A] Any leading nodes that aren't in the document any more should be ignored
132.3316 + // These most likely correspond to memoization nodes that were already removed during binding
132.3317 + // See https://github.com/SteveSanderson/knockout/pull/440
132.3318 + // [B] We want to output a contiguous series of nodes that are still in the document. So, ignore any nodes that
132.3319 + // have already been removed, and include any nodes that have been inserted among the previous collection
132.3320 +
132.3321 + // Rule [A]
132.3322 + while (contiguousNodeArray.length && !ko.utils.domNodeIsAttachedToDocument(contiguousNodeArray[0]))
132.3323 + contiguousNodeArray.splice(0, 1);
132.3324 +
132.3325 + // Rule [B]
132.3326 + if (contiguousNodeArray.length > 1) {
132.3327 + // Build up the actual new contiguous node set
132.3328 + var current = contiguousNodeArray[0], last = contiguousNodeArray[contiguousNodeArray.length - 1], newContiguousSet = [current];
132.3329 + while (current !== last) {
132.3330 + current = current.nextSibling;
132.3331 + if (!current) // Won't happen, except if the developer has manually removed some DOM elements (then we're in an undefined scenario)
132.3332 + return;
132.3333 + newContiguousSet.push(current);
132.3334 + }
132.3335 +
132.3336 + // ... then mutate the input array to match this.
132.3337 + // (The following line replaces the contents of contiguousNodeArray with newContiguousSet)
132.3338 + Array.prototype.splice.apply(contiguousNodeArray, [0, contiguousNodeArray.length].concat(newContiguousSet));
132.3339 + }
132.3340 + return contiguousNodeArray;
132.3341 + }
132.3342 +
132.3343 + function mapNodeAndRefreshWhenChanged(containerNode, mapping, valueToMap, callbackAfterAddingNodes, index) {
132.3344 + // Map this array value inside a dependentObservable so we re-map when any dependency changes
132.3345 + var mappedNodes = [];
132.3346 + var dependentObservable = ko.dependentObservable(function() {
132.3347 + var newMappedNodes = mapping(valueToMap, index) || [];
132.3348 +
132.3349 + // On subsequent evaluations, just replace the previously-inserted DOM nodes
132.3350 + if (mappedNodes.length > 0) {
132.3351 + ko.utils.replaceDomNodes(fixUpNodesToBeMovedOrRemoved(mappedNodes), newMappedNodes);
132.3352 + if (callbackAfterAddingNodes)
132.3353 + ko.dependencyDetection.ignore(callbackAfterAddingNodes, null, [valueToMap, newMappedNodes, index]);
132.3354 + }
132.3355 +
132.3356 + // Replace the contents of the mappedNodes array, thereby updating the record
132.3357 + // of which nodes would be deleted if valueToMap was itself later removed
132.3358 + mappedNodes.splice(0, mappedNodes.length);
132.3359 + ko.utils.arrayPushAll(mappedNodes, newMappedNodes);
132.3360 + }, null, { disposeWhenNodeIsRemoved: containerNode, disposeWhen: function() { return (mappedNodes.length == 0) || !ko.utils.domNodeIsAttachedToDocument(mappedNodes[0]) } });
132.3361 + return { mappedNodes : mappedNodes, dependentObservable : (dependentObservable.isActive() ? dependentObservable : undefined) };
132.3362 + }
132.3363 +
132.3364 + var lastMappingResultDomDataKey = "setDomNodeChildrenFromArrayMapping_lastMappingResult";
132.3365 +
132.3366 + ko.utils.setDomNodeChildrenFromArrayMapping = function (domNode, array, mapping, options, callbackAfterAddingNodes) {
132.3367 + // Compare the provided array against the previous one
132.3368 + array = array || [];
132.3369 + options = options || {};
132.3370 + var isFirstExecution = ko.utils.domData.get(domNode, lastMappingResultDomDataKey) === undefined;
132.3371 + var lastMappingResult = ko.utils.domData.get(domNode, lastMappingResultDomDataKey) || [];
132.3372 + var lastArray = ko.utils.arrayMap(lastMappingResult, function (x) { return x.arrayEntry; });
132.3373 + var editScript = ko.utils.compareArrays(lastArray, array);
132.3374 +
132.3375 + // Build the new mapping result
132.3376 + var newMappingResult = [];
132.3377 + var lastMappingResultIndex = 0;
132.3378 + var newMappingResultIndex = 0;
132.3379 +
132.3380 + var nodesToDelete = [];
132.3381 + var itemsToProcess = [];
132.3382 + var itemsForBeforeRemoveCallbacks = [];
132.3383 + var itemsForMoveCallbacks = [];
132.3384 + var itemsForAfterAddCallbacks = [];
132.3385 + var mapData;
132.3386 +
132.3387 + function itemMovedOrRetained(editScriptIndex, oldPosition) {
132.3388 + mapData = lastMappingResult[oldPosition];
132.3389 + if (newMappingResultIndex !== oldPosition)
132.3390 + itemsForMoveCallbacks[editScriptIndex] = mapData;
132.3391 + // Since updating the index might change the nodes, do so before calling fixUpNodesToBeMovedOrRemoved
132.3392 + mapData.indexObservable(newMappingResultIndex++);
132.3393 + fixUpNodesToBeMovedOrRemoved(mapData.mappedNodes);
132.3394 + newMappingResult.push(mapData);
132.3395 + itemsToProcess.push(mapData);
132.3396 + }
132.3397 +
132.3398 + function callCallback(callback, items) {
132.3399 + if (callback) {
132.3400 + for (var i = 0, n = items.length; i < n; i++) {
132.3401 + if (items[i]) {
132.3402 + ko.utils.arrayForEach(items[i].mappedNodes, function(node) {
132.3403 + callback(node, i, items[i].arrayEntry);
132.3404 + });
132.3405 + }
132.3406 + }
132.3407 + }
132.3408 + }
132.3409 +
132.3410 + for (var i = 0, editScriptItem, movedIndex; editScriptItem = editScript[i]; i++) {
132.3411 + movedIndex = editScriptItem['moved'];
132.3412 + switch (editScriptItem['status']) {
132.3413 + case "deleted":
132.3414 + if (movedIndex === undefined) {
132.3415 + mapData = lastMappingResult[lastMappingResultIndex];
132.3416 +
132.3417 + // Stop tracking changes to the mapping for these nodes
132.3418 + if (mapData.dependentObservable)
132.3419 + mapData.dependentObservable.dispose();
132.3420 +
132.3421 + // Queue these nodes for later removal
132.3422 + nodesToDelete.push.apply(nodesToDelete, fixUpNodesToBeMovedOrRemoved(mapData.mappedNodes));
132.3423 + if (options['beforeRemove']) {
132.3424 + itemsForBeforeRemoveCallbacks[i] = mapData;
132.3425 + itemsToProcess.push(mapData);
132.3426 + }
132.3427 + }
132.3428 + lastMappingResultIndex++;
132.3429 + break;
132.3430 +
132.3431 + case "retained":
132.3432 + itemMovedOrRetained(i, lastMappingResultIndex++);
132.3433 + break;
132.3434 +
132.3435 + case "added":
132.3436 + if (movedIndex !== undefined) {
132.3437 + itemMovedOrRetained(i, movedIndex);
132.3438 + } else {
132.3439 + mapData = { arrayEntry: editScriptItem['value'], indexObservable: ko.observable(newMappingResultIndex++) };
132.3440 + newMappingResult.push(mapData);
132.3441 + itemsToProcess.push(mapData);
132.3442 + if (!isFirstExecution)
132.3443 + itemsForAfterAddCallbacks[i] = mapData;
132.3444 + }
132.3445 + break;
132.3446 + }
132.3447 + }
132.3448 +
132.3449 + // Call beforeMove first before any changes have been made to the DOM
132.3450 + callCallback(options['beforeMove'], itemsForMoveCallbacks);
132.3451 +
132.3452 + // Next remove nodes for deleted items (or just clean if there's a beforeRemove callback)
132.3453 + ko.utils.arrayForEach(nodesToDelete, options['beforeRemove'] ? ko.cleanNode : ko.removeNode);
132.3454 +
132.3455 + // Next add/reorder the remaining items (will include deleted items if there's a beforeRemove callback)
132.3456 + for (var i = 0, nextNode = ko.virtualElements.firstChild(domNode), lastNode, node; mapData = itemsToProcess[i]; i++) {
132.3457 + // Get nodes for newly added items
132.3458 + if (!mapData.mappedNodes)
132.3459 + ko.utils.extend(mapData, mapNodeAndRefreshWhenChanged(domNode, mapping, mapData.arrayEntry, callbackAfterAddingNodes, mapData.indexObservable));
132.3460 +
132.3461 + // Put nodes in the right place if they aren't there already
132.3462 + for (var j = 0; node = mapData.mappedNodes[j]; nextNode = node.nextSibling, lastNode = node, j++) {
132.3463 + if (node !== nextNode)
132.3464 + ko.virtualElements.insertAfter(domNode, node, lastNode);
132.3465 + }
132.3466 +
132.3467 + // Run the callbacks for newly added nodes (for example, to apply bindings, etc.)
132.3468 + if (!mapData.initialized && callbackAfterAddingNodes) {
132.3469 + callbackAfterAddingNodes(mapData.arrayEntry, mapData.mappedNodes, mapData.indexObservable);
132.3470 + mapData.initialized = true;
132.3471 + }
132.3472 + }
132.3473 +
132.3474 + // If there's a beforeRemove callback, call it after reordering.
132.3475 + // Note that we assume that the beforeRemove callback will usually be used to remove the nodes using
132.3476 + // some sort of animation, which is why we first reorder the nodes that will be removed. If the
132.3477 + // callback instead removes the nodes right away, it would be more efficient to skip reordering them.
132.3478 + // Perhaps we'll make that change in the future if this scenario becomes more common.
132.3479 + callCallback(options['beforeRemove'], itemsForBeforeRemoveCallbacks);
132.3480 +
132.3481 + // Finally call afterMove and afterAdd callbacks
132.3482 + callCallback(options['afterMove'], itemsForMoveCallbacks);
132.3483 + callCallback(options['afterAdd'], itemsForAfterAddCallbacks);
132.3484 +
132.3485 + // Store a copy of the array items we just considered so we can difference it next time
132.3486 + ko.utils.domData.set(domNode, lastMappingResultDomDataKey, newMappingResult);
132.3487 + }
132.3488 +})();
132.3489 +
132.3490 +ko.exportSymbol('utils.setDomNodeChildrenFromArrayMapping', ko.utils.setDomNodeChildrenFromArrayMapping);
132.3491 +ko.nativeTemplateEngine = function () {
132.3492 + this['allowTemplateRewriting'] = false;
132.3493 +}
132.3494 +
132.3495 +ko.nativeTemplateEngine.prototype = new ko.templateEngine();
132.3496 +ko.nativeTemplateEngine.prototype['renderTemplateSource'] = function (templateSource, bindingContext, options) {
132.3497 + var useNodesIfAvailable = !(ko.utils.ieVersion < 9), // IE<9 cloneNode doesn't work properly
132.3498 + templateNodesFunc = useNodesIfAvailable ? templateSource['nodes'] : null,
132.3499 + templateNodes = templateNodesFunc ? templateSource['nodes']() : null;
132.3500 +
132.3501 + if (templateNodes) {
132.3502 + return ko.utils.makeArray(templateNodes.cloneNode(true).childNodes);
132.3503 + } else {
132.3504 + var templateText = templateSource['text']();
132.3505 + return ko.utils.parseHtmlFragment(templateText);
132.3506 + }
132.3507 +};
132.3508 +
132.3509 +ko.nativeTemplateEngine.instance = new ko.nativeTemplateEngine();
132.3510 +ko.setTemplateEngine(ko.nativeTemplateEngine.instance);
132.3511 +
132.3512 +ko.exportSymbol('nativeTemplateEngine', ko.nativeTemplateEngine);
132.3513 +(function() {
132.3514 + ko.jqueryTmplTemplateEngine = function () {
132.3515 + // Detect which version of jquery-tmpl you're using. Unfortunately jquery-tmpl
132.3516 + // doesn't expose a version number, so we have to infer it.
132.3517 + // Note that as of Knockout 1.3, we only support jQuery.tmpl 1.0.0pre and later,
132.3518 + // which KO internally refers to as version "2", so older versions are no longer detected.
132.3519 + var jQueryTmplVersion = this.jQueryTmplVersion = (function() {
132.3520 + if ((typeof(jQuery) == "undefined") || !(jQuery['tmpl']))
132.3521 + return 0;
132.3522 + // Since it exposes no official version number, we use our own numbering system. To be updated as jquery-tmpl evolves.
132.3523 + try {
132.3524 + if (jQuery['tmpl']['tag']['tmpl']['open'].toString().indexOf('__') >= 0) {
132.3525 + // Since 1.0.0pre, custom tags should append markup to an array called "__"
132.3526 + return 2; // Final version of jquery.tmpl
132.3527 + }
132.3528 + } catch(ex) { /* Apparently not the version we were looking for */ }
132.3529 +
132.3530 + return 1; // Any older version that we don't support
132.3531 + })();
132.3532 +
132.3533 + function ensureHasReferencedJQueryTemplates() {
132.3534 + if (jQueryTmplVersion < 2)
132.3535 + throw new Error("Your version of jQuery.tmpl is too old. Please upgrade to jQuery.tmpl 1.0.0pre or later.");
132.3536 + }
132.3537 +
132.3538 + function executeTemplate(compiledTemplate, data, jQueryTemplateOptions) {
132.3539 + return jQuery['tmpl'](compiledTemplate, data, jQueryTemplateOptions);
132.3540 + }
132.3541 +
132.3542 + this['renderTemplateSource'] = function(templateSource, bindingContext, options) {
132.3543 + options = options || {};
132.3544 + ensureHasReferencedJQueryTemplates();
132.3545 +
132.3546 + // Ensure we have stored a precompiled version of this template (don't want to reparse on every render)
132.3547 + var precompiled = templateSource['data']('precompiled');
132.3548 + if (!precompiled) {
132.3549 + var templateText = templateSource['text']() || "";
132.3550 + // Wrap in "with($whatever.koBindingContext) { ... }"
132.3551 + templateText = "{{ko_with $item.koBindingContext}}" + templateText + "{{/ko_with}}";
132.3552 +
132.3553 + precompiled = jQuery['template'](null, templateText);
132.3554 + templateSource['data']('precompiled', precompiled);
132.3555 + }
132.3556 +
132.3557 + var data = [bindingContext['$data']]; // Prewrap the data in an array to stop jquery.tmpl from trying to unwrap any arrays
132.3558 + var jQueryTemplateOptions = jQuery['extend']({ 'koBindingContext': bindingContext }, options['templateOptions']);
132.3559 +
132.3560 + var resultNodes = executeTemplate(precompiled, data, jQueryTemplateOptions);
132.3561 + resultNodes['appendTo'](document.createElement("div")); // Using "appendTo" forces jQuery/jQuery.tmpl to perform necessary cleanup work
132.3562 +
132.3563 + jQuery['fragments'] = {}; // Clear jQuery's fragment cache to avoid a memory leak after a large number of template renders
132.3564 + return resultNodes;
132.3565 + };
132.3566 +
132.3567 + this['createJavaScriptEvaluatorBlock'] = function(script) {
132.3568 + return "{{ko_code ((function() { return " + script + " })()) }}";
132.3569 + };
132.3570 +
132.3571 + this['addTemplate'] = function(templateName, templateMarkup) {
132.3572 + document.write("<script type='text/html' id='" + templateName + "'>" + templateMarkup + "</script>");
132.3573 + };
132.3574 +
132.3575 + if (jQueryTmplVersion > 0) {
132.3576 + jQuery['tmpl']['tag']['ko_code'] = {
132.3577 + open: "__.push($1 || '');"
132.3578 + };
132.3579 + jQuery['tmpl']['tag']['ko_with'] = {
132.3580 + open: "with($1) {",
132.3581 + close: "} "
132.3582 + };
132.3583 + }
132.3584 + };
132.3585 +
132.3586 + ko.jqueryTmplTemplateEngine.prototype = new ko.templateEngine();
132.3587 +
132.3588 + // Use this one by default *only if jquery.tmpl is referenced*
132.3589 + var jqueryTmplTemplateEngineInstance = new ko.jqueryTmplTemplateEngine();
132.3590 + if (jqueryTmplTemplateEngineInstance.jQueryTmplVersion > 0)
132.3591 + ko.setTemplateEngine(jqueryTmplTemplateEngineInstance);
132.3592 +
132.3593 + ko.exportSymbol('jqueryTmplTemplateEngine', ko.jqueryTmplTemplateEngine);
132.3594 +})();
132.3595 +});
132.3596 +})(window,document,navigator,window["jQuery"]);
132.3597 +})();
132.3598 \ No newline at end of file
133.1 --- a/ko-fx/src/test/java/org/apidesign/html/kofx/DynamicHTTP.java Mon Dec 16 15:48:09 2013 +0100
133.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
133.3 @@ -1,259 +0,0 @@
133.4 -/**
133.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
133.6 - *
133.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
133.8 - *
133.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
133.10 - * Other names may be trademarks of their respective owners.
133.11 - *
133.12 - * The contents of this file are subject to the terms of either the GNU
133.13 - * General Public License Version 2 only ("GPL") or the Common
133.14 - * Development and Distribution License("CDDL") (collectively, the
133.15 - * "License"). You may not use this file except in compliance with the
133.16 - * License. You can obtain a copy of the License at
133.17 - * http://www.netbeans.org/cddl-gplv2.html
133.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
133.19 - * specific language governing permissions and limitations under the
133.20 - * License. When distributing the software, include this License Header
133.21 - * Notice in each file and include the License file at
133.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
133.23 - * particular file as subject to the "Classpath" exception as provided
133.24 - * by Oracle in the GPL Version 2 section of the License file that
133.25 - * accompanied this code. If applicable, add the following below the
133.26 - * License Header, with the fields enclosed by brackets [] replaced by
133.27 - * your own identifying information:
133.28 - * "Portions Copyrighted [year] [name of copyright owner]"
133.29 - *
133.30 - * Contributor(s):
133.31 - *
133.32 - * The Original Software is NetBeans. The Initial Developer of the Original
133.33 - * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
133.34 - *
133.35 - * If you wish your version of this file to be governed by only the CDDL
133.36 - * or only the GPL Version 2, indicate your decision by adding
133.37 - * "[Contributor] elects to include this software in this distribution
133.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
133.39 - * single choice of license, a recipient has the option to distribute
133.40 - * your version of this file under either the CDDL, the GPL Version 2 or
133.41 - * to extend the choice of license to its licensees as provided above.
133.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
133.43 - * Version 2 license, then the option applies only if the new code is
133.44 - * made subject to such option by the copyright holder.
133.45 - */
133.46 -package org.apidesign.html.kofx;
133.47 -
133.48 -import java.io.ByteArrayInputStream;
133.49 -import java.io.ByteArrayOutputStream;
133.50 -import java.io.IOException;
133.51 -import java.io.InputStream;
133.52 -import java.io.OutputStream;
133.53 -import java.io.Reader;
133.54 -import java.net.URI;
133.55 -import java.net.URISyntaxException;
133.56 -import java.util.ArrayList;
133.57 -import java.util.List;
133.58 -import java.util.logging.Level;
133.59 -import java.util.logging.Logger;
133.60 -import org.glassfish.grizzly.PortRange;
133.61 -import org.glassfish.grizzly.http.server.HttpHandler;
133.62 -import org.glassfish.grizzly.http.server.HttpServer;
133.63 -import org.glassfish.grizzly.http.server.NetworkListener;
133.64 -import org.glassfish.grizzly.http.server.Request;
133.65 -import org.glassfish.grizzly.http.server.Response;
133.66 -import org.glassfish.grizzly.http.server.ServerConfiguration;
133.67 -import org.glassfish.grizzly.websockets.WebSocket;
133.68 -import org.glassfish.grizzly.websockets.WebSocketAddOn;
133.69 -import org.glassfish.grizzly.websockets.WebSocketApplication;
133.70 -import org.glassfish.grizzly.websockets.WebSocketEngine;
133.71 -
133.72 -/**
133.73 - *
133.74 - * @author Jaroslav Tulach <jtulach@netbeans.org>
133.75 - */
133.76 -final class DynamicHTTP extends HttpHandler {
133.77 - private static final Logger LOG = Logger.getLogger(DynamicHTTP.class.getName());
133.78 - private static int resourcesCount;
133.79 - private static List<Resource> resources;
133.80 - private static ServerConfiguration conf;
133.81 - private static HttpServer server;
133.82 -
133.83 - private DynamicHTTP() {
133.84 - }
133.85 -
133.86 - static URI initServer() throws Exception {
133.87 - server = HttpServer.createSimpleServer(null, new PortRange(8080, 65535));
133.88 - final WebSocketAddOn addon = new WebSocketAddOn();
133.89 - for (NetworkListener listener : server.getListeners()) {
133.90 - listener.registerAddOn(addon);
133.91 - }
133.92 - resources = new ArrayList<Resource>();
133.93 -
133.94 - conf = server.getServerConfiguration();
133.95 - final DynamicHTTP dh = new DynamicHTTP();
133.96 -
133.97 - conf.addHttpHandler(dh, "/");
133.98 -
133.99 - server.start();
133.100 -
133.101 - return pageURL("http", server, "/test.html");
133.102 - }
133.103 -
133.104 - @Override
133.105 - public void service(Request request, Response response) throws Exception {
133.106 - if ("/test.html".equals(request.getRequestURI())) {
133.107 - response.setContentType("text/html");
133.108 - final InputStream is = DynamicHTTP.class.getResourceAsStream("test.html");
133.109 - copyStream(is, response.getOutputStream(), null);
133.110 - return;
133.111 - }
133.112 - if ("/dynamic".equals(request.getRequestURI())) {
133.113 - String mimeType = request.getParameter("mimeType");
133.114 - List<String> params = new ArrayList<String>();
133.115 - boolean webSocket = false;
133.116 - for (int i = 0;; i++) {
133.117 - String p = request.getParameter("param" + i);
133.118 - if (p == null) {
133.119 - break;
133.120 - }
133.121 - if ("protocol:ws".equals(p)) {
133.122 - webSocket = true;
133.123 - continue;
133.124 - }
133.125 - params.add(p);
133.126 - }
133.127 - final String cnt = request.getParameter("content");
133.128 - String mangle = cnt.replace("%20", " ").replace("%0A", "\n");
133.129 - ByteArrayInputStream is = new ByteArrayInputStream(mangle.getBytes("UTF-8"));
133.130 - URI url;
133.131 - final Resource res = new Resource(is, mimeType, "/dynamic/res" + ++resourcesCount, params.toArray(new String[params.size()]));
133.132 - if (webSocket) {
133.133 - url = registerWebSocket(res);
133.134 - } else {
133.135 - url = registerResource(res);
133.136 - }
133.137 - response.getWriter().write(url.toString());
133.138 - response.getWriter().write("\n");
133.139 - return;
133.140 - }
133.141 -
133.142 - for (Resource r : resources) {
133.143 - if (r.httpPath.equals(request.getRequestURI())) {
133.144 - response.setContentType(r.httpType);
133.145 - r.httpContent.reset();
133.146 - String[] params = null;
133.147 - if (r.parameters.length != 0) {
133.148 - params = new String[r.parameters.length];
133.149 - for (int i = 0; i < r.parameters.length; i++) {
133.150 - params[i] = request.getParameter(r.parameters[i]);
133.151 - if (params[i] == null) {
133.152 - if ("http.method".equals(r.parameters[i])) {
133.153 - params[i] = request.getMethod().toString();
133.154 - } else if ("http.requestBody".equals(r.parameters[i])) {
133.155 - Reader rdr = request.getReader();
133.156 - StringBuilder sb = new StringBuilder();
133.157 - for (;;) {
133.158 - int ch = rdr.read();
133.159 - if (ch == -1) {
133.160 - break;
133.161 - }
133.162 - sb.append((char) ch);
133.163 - }
133.164 - params[i] = sb.toString();
133.165 - }
133.166 - }
133.167 - if (params[i] == null) {
133.168 - params[i] = "null";
133.169 - }
133.170 - }
133.171 - }
133.172 -
133.173 - copyStream(r.httpContent, response.getOutputStream(), null, params);
133.174 - }
133.175 - }
133.176 - }
133.177 -
133.178 - private URI registerWebSocket(Resource r) {
133.179 - WebSocketEngine.getEngine().register("", r.httpPath, new WS(r));
133.180 - return pageURL("ws", server, r.httpPath);
133.181 - }
133.182 -
133.183 - private URI registerResource(Resource r) {
133.184 - if (!resources.contains(r)) {
133.185 - resources.add(r);
133.186 - conf.addHttpHandler(this, r.httpPath);
133.187 - }
133.188 - return pageURL("http", server, r.httpPath);
133.189 - }
133.190 -
133.191 - private static URI pageURL(String proto, HttpServer server, final String page) {
133.192 - NetworkListener listener = server.getListeners().iterator().next();
133.193 - int port = listener.getPort();
133.194 - try {
133.195 - return new URI(proto + "://localhost:" + port + page);
133.196 - } catch (URISyntaxException ex) {
133.197 - throw new IllegalStateException(ex);
133.198 - }
133.199 - }
133.200 -
133.201 - static final class Resource {
133.202 -
133.203 - final InputStream httpContent;
133.204 - final String httpType;
133.205 - final String httpPath;
133.206 - final String[] parameters;
133.207 -
133.208 - Resource(InputStream httpContent, String httpType, String httpPath,
133.209 - String[] parameters) {
133.210 - httpContent.mark(Integer.MAX_VALUE);
133.211 - this.httpContent = httpContent;
133.212 - this.httpType = httpType;
133.213 - this.httpPath = httpPath;
133.214 - this.parameters = parameters;
133.215 - }
133.216 - }
133.217 -
133.218 - static void copyStream(InputStream is, OutputStream os, String baseURL, String... params) throws IOException {
133.219 - for (;;) {
133.220 - int ch = is.read();
133.221 - if (ch == -1) {
133.222 - break;
133.223 - }
133.224 - if (ch == '$' && params.length > 0) {
133.225 - int cnt = is.read() - '0';
133.226 - if (baseURL != null && cnt == 'U' - '0') {
133.227 - os.write(baseURL.getBytes("UTF-8"));
133.228 - } else {
133.229 - if (cnt >= 0 && cnt < params.length) {
133.230 - os.write(params[cnt].getBytes("UTF-8"));
133.231 - } else {
133.232 - os.write('$');
133.233 - os.write(cnt + '0');
133.234 - }
133.235 - }
133.236 - } else {
133.237 - os.write(ch);
133.238 - }
133.239 - }
133.240 - }
133.241 -
133.242 - private static class WS extends WebSocketApplication {
133.243 - private final Resource r;
133.244 -
133.245 - private WS(Resource r) {
133.246 - this.r = r;
133.247 - }
133.248 -
133.249 - @Override
133.250 - public void onMessage(WebSocket socket, String text) {
133.251 - try {
133.252 - r.httpContent.reset();
133.253 - ByteArrayOutputStream out = new ByteArrayOutputStream();
133.254 - copyStream(r.httpContent, out, null, text);
133.255 - String s = new String(out.toByteArray(), "UTF-8");
133.256 - socket.send(s);
133.257 - } catch (IOException ex) {
133.258 - LOG.log(Level.WARNING, "Error processing message " + text, ex);
133.259 - }
133.260 - }
133.261 - }
133.262 -}
134.1 --- a/ko-fx/src/test/java/org/apidesign/html/kofx/KOFx.java Mon Dec 16 15:48:09 2013 +0100
134.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
134.3 @@ -1,118 +0,0 @@
134.4 -/**
134.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
134.6 - *
134.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
134.8 - *
134.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
134.10 - * Other names may be trademarks of their respective owners.
134.11 - *
134.12 - * The contents of this file are subject to the terms of either the GNU
134.13 - * General Public License Version 2 only ("GPL") or the Common
134.14 - * Development and Distribution License("CDDL") (collectively, the
134.15 - * "License"). You may not use this file except in compliance with the
134.16 - * License. You can obtain a copy of the License at
134.17 - * http://www.netbeans.org/cddl-gplv2.html
134.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
134.19 - * specific language governing permissions and limitations under the
134.20 - * License. When distributing the software, include this License Header
134.21 - * Notice in each file and include the License file at
134.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
134.23 - * particular file as subject to the "Classpath" exception as provided
134.24 - * by Oracle in the GPL Version 2 section of the License file that
134.25 - * accompanied this code. If applicable, add the following below the
134.26 - * License Header, with the fields enclosed by brackets [] replaced by
134.27 - * your own identifying information:
134.28 - * "Portions Copyrighted [year] [name of copyright owner]"
134.29 - *
134.30 - * Contributor(s):
134.31 - *
134.32 - * The Original Software is NetBeans. The Initial Developer of the Original
134.33 - * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
134.34 - *
134.35 - * If you wish your version of this file to be governed by only the CDDL
134.36 - * or only the GPL Version 2, indicate your decision by adding
134.37 - * "[Contributor] elects to include this software in this distribution
134.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
134.39 - * single choice of license, a recipient has the option to distribute
134.40 - * your version of this file under either the CDDL, the GPL Version 2 or
134.41 - * to extend the choice of license to its licensees as provided above.
134.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
134.43 - * Version 2 license, then the option applies only if the new code is
134.44 - * made subject to such option by the copyright holder.
134.45 - */
134.46 -package org.apidesign.html.kofx;
134.47 -
134.48 -import java.io.Closeable;
134.49 -import java.lang.reflect.InvocationTargetException;
134.50 -import java.lang.reflect.Method;
134.51 -import javafx.application.Platform;
134.52 -import org.apidesign.html.boot.spi.Fn;
134.53 -import org.testng.ITest;
134.54 -import org.testng.annotations.Test;
134.55 -
134.56 -/**
134.57 - *
134.58 - * @author Jaroslav Tulach <jtulach@netbeans.org>
134.59 - */
134.60 -public final class KOFx implements ITest, Runnable {
134.61 - private final Fn.Presenter p;
134.62 - private final Method m;
134.63 - private Object result;
134.64 - private Object inst;
134.65 - private int count;
134.66 -
134.67 - KOFx(Fn.Presenter p, Method m) {
134.68 - this.p = p;
134.69 - this.m = m;
134.70 - }
134.71 -
134.72 - @Override
134.73 - public String getTestName() {
134.74 - return m.getName();
134.75 - }
134.76 -
134.77 - @Test
134.78 - public synchronized void executeTest() throws Exception {
134.79 - if (result == null) {
134.80 - Platform.runLater(this);
134.81 - wait();
134.82 - }
134.83 - if (result instanceof Exception) {
134.84 - throw (Exception)result;
134.85 - }
134.86 - if (result instanceof Error) {
134.87 - throw (Error)result;
134.88 - }
134.89 - }
134.90 -
134.91 - @Override
134.92 - public synchronized void run() {
134.93 - boolean notify = true;
134.94 - try (Closeable a = Fn.activate(p)) {
134.95 - if (inst == null) {
134.96 - inst = m.getDeclaringClass().newInstance();
134.97 - }
134.98 - result = m.invoke(inst);
134.99 - if (result == null) {
134.100 - result = this;
134.101 - }
134.102 - } catch (InvocationTargetException ex) {
134.103 - Throwable r = ex.getTargetException();
134.104 - if (r instanceof InterruptedException) {
134.105 - if (count++ < 10000) {
134.106 - notify = false;
134.107 - Platform.runLater(this);
134.108 - return;
134.109 - }
134.110 - }
134.111 - result = r;
134.112 - } catch (Exception ex) {
134.113 - result = ex;
134.114 - } finally {
134.115 - if (notify) {
134.116 - notifyAll();
134.117 - }
134.118 - }
134.119 - }
134.120 -
134.121 -}
135.1 --- a/ko-fx/src/test/java/org/apidesign/html/kofx/KnockoutFXTest.java Mon Dec 16 15:48:09 2013 +0100
135.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
135.3 @@ -1,229 +0,0 @@
135.4 -/**
135.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
135.6 - *
135.7 - * Copyright 1997-2010 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.kofx;
135.47 -
135.48 -import java.io.BufferedReader;
135.49 -import java.io.IOException;
135.50 -import java.io.InputStreamReader;
135.51 -import java.lang.annotation.Annotation;
135.52 -import java.lang.reflect.Method;
135.53 -import java.net.URI;
135.54 -import java.net.URISyntaxException;
135.55 -import java.net.URL;
135.56 -import java.net.URLConnection;
135.57 -import java.util.ArrayList;
135.58 -import java.util.List;
135.59 -import java.util.Map;
135.60 -import java.util.concurrent.Executors;
135.61 -import net.java.html.BrwsrCtx;
135.62 -import net.java.html.boot.BrowserBuilder;
135.63 -import net.java.html.js.JavaScriptBody;
135.64 -import org.apidesign.html.boot.impl.FnContext;
135.65 -import org.apidesign.html.boot.spi.Fn;
135.66 -import org.apidesign.html.context.spi.Contexts;
135.67 -import org.apidesign.html.json.spi.Technology;
135.68 -import org.apidesign.html.json.spi.Transfer;
135.69 -import org.apidesign.html.json.spi.WSTransfer;
135.70 -import org.apidesign.html.json.tck.KOTest;
135.71 -import org.apidesign.html.json.tck.KnockoutTCK;
135.72 -import org.json.JSONException;
135.73 -import org.json.JSONObject;
135.74 -import org.openide.util.lookup.ServiceProvider;
135.75 -import org.testng.annotations.Factory;
135.76 -import static org.testng.Assert.*;
135.77 -
135.78 -/**
135.79 - *
135.80 - * @author Jaroslav Tulach <jtulach@netbeans.org>
135.81 - */
135.82 -@ServiceProvider(service = KnockoutTCK.class)
135.83 -public final class KnockoutFXTest extends KnockoutTCK {
135.84 - private static Class<?> browserClass;
135.85 - private static Fn.Presenter browserContext;
135.86 -
135.87 - public KnockoutFXTest() {
135.88 - }
135.89 -
135.90 - @Factory public static Object[] compatibilityTests() throws Exception {
135.91 - Class[] arr = testClasses();
135.92 - for (int i = 0; i < arr.length; i++) {
135.93 - assertEquals(
135.94 - arr[i].getClassLoader(),
135.95 - KnockoutFXTest.class.getClassLoader(),
135.96 - "All classes loaded by the same classloader"
135.97 - );
135.98 - }
135.99 -
135.100 - URI uri = DynamicHTTP.initServer();
135.101 -
135.102 - final BrowserBuilder bb = BrowserBuilder.newBrowser().loadClass(KnockoutFXTest.class).
135.103 - loadPage(uri.toString()).
135.104 - invoke("initialized");
135.105 -
135.106 - Executors.newSingleThreadExecutor().submit(new Runnable() {
135.107 - @Override
135.108 - public void run() {
135.109 - bb.showAndWait();
135.110 - }
135.111 - });
135.112 -
135.113 - ClassLoader l = getClassLoader();
135.114 - List<Object> res = new ArrayList<Object>();
135.115 - for (int i = 0; i < arr.length; i++) {
135.116 - Class<?> c = Class.forName(arr[i].getName(), true, l);
135.117 - seekKOTests(c, res);
135.118 - }
135.119 - Class<?> c = Class.forName(LessCallbacksCheck.class.getName(), true, l);
135.120 - seekKOTests(c, res);
135.121 - return res.toArray();
135.122 - }
135.123 -
135.124 - private static void seekKOTests(Class<?> c, List<Object> res) throws SecurityException, ClassNotFoundException {
135.125 - Class<? extends Annotation> koTest =
135.126 - c.getClassLoader().loadClass(KOTest.class.getName()).
135.127 - asSubclass(Annotation.class);
135.128 - for (Method m : c.getMethods()) {
135.129 - if (m.getAnnotation(koTest) != null) {
135.130 - res.add(new KOFx(browserContext, m));
135.131 - }
135.132 - }
135.133 - }
135.134 -
135.135 - static synchronized ClassLoader getClassLoader() throws InterruptedException {
135.136 - while (browserClass == null) {
135.137 - KnockoutFXTest.class.wait();
135.138 - }
135.139 - return browserClass.getClassLoader();
135.140 - }
135.141 -
135.142 - public static synchronized void initialized(Class<?> browserCls) throws Exception {
135.143 - browserClass = browserCls;
135.144 - browserContext = FnContext.currentPresenter();
135.145 - KnockoutFXTest.class.notifyAll();
135.146 - }
135.147 -
135.148 - public static void initialized() throws Exception {
135.149 - Class<?> classpathClass = ClassLoader.getSystemClassLoader().loadClass(KnockoutFXTest.class.getName());
135.150 - Method m = classpathClass.getMethod("initialized", Class.class);
135.151 - m.invoke(null, KnockoutFXTest.class);
135.152 - browserContext = FnContext.currentPresenter();
135.153 - }
135.154 -
135.155 - @Override
135.156 - public BrwsrCtx createContext() {
135.157 - FXContext fx = new FXContext(browserContext);
135.158 - Contexts.Builder cb = Contexts.newBuilder().
135.159 - register(Technology.class, fx, 10).
135.160 - register(Transfer.class, fx, 10);
135.161 - if (fx.areWebSocketsSupported()) {
135.162 - cb.register(WSTransfer.class, fx, 10);
135.163 - }
135.164 - return cb.build();
135.165 - }
135.166 -
135.167 - @Override
135.168 - public Object createJSON(Map<String, Object> values) {
135.169 - JSONObject json = new JSONObject();
135.170 - for (Map.Entry<String, Object> entry : values.entrySet()) {
135.171 - try {
135.172 - json.put(entry.getKey(), entry.getValue());
135.173 - } catch (JSONException ex) {
135.174 - throw new IllegalStateException(ex);
135.175 - }
135.176 - }
135.177 - return json;
135.178 - }
135.179 -
135.180 - @Override
135.181 - @JavaScriptBody(args = { "s", "args" }, body = ""
135.182 - + "var f = new Function(s); "
135.183 - + "return f.apply(null, args);"
135.184 - )
135.185 - public native Object executeScript(String script, Object[] arguments);
135.186 -
135.187 - @JavaScriptBody(args = { }, body =
135.188 - "var h;"
135.189 - + "if (!!window && !!window.location && !!window.location.href)\n"
135.190 - + " h = window.location.href;\n"
135.191 - + "else "
135.192 - + " h = null;"
135.193 - + "return h;\n"
135.194 - )
135.195 - private static native String findBaseURL();
135.196 -
135.197 - @Override
135.198 - public URI prepareURL(String content, String mimeType, String[] parameters) {
135.199 - try {
135.200 - final URL baseURL = new URL(findBaseURL());
135.201 - StringBuilder sb = new StringBuilder();
135.202 - sb.append("/dynamic?mimeType=").append(mimeType);
135.203 - for (int i = 0; i < parameters.length; i++) {
135.204 - sb.append("¶m" + i).append("=").append(parameters[i]);
135.205 - }
135.206 - String mangle = content.replace("\n", "%0a")
135.207 - .replace("\"", "\\\"").replace(" ", "%20");
135.208 - sb.append("&content=").append(mangle);
135.209 -
135.210 - URL query = new URL(baseURL, sb.toString());
135.211 - URLConnection c = query.openConnection();
135.212 - BufferedReader br = new BufferedReader(new InputStreamReader(c.getInputStream()));
135.213 - URI connectTo = new URI(br.readLine());
135.214 - return connectTo;
135.215 - } catch (IOException ex) {
135.216 - throw new IllegalStateException(ex);
135.217 - } catch (URISyntaxException ex) {
135.218 - throw new IllegalStateException(ex);
135.219 - }
135.220 - }
135.221 -
135.222 - @Override
135.223 - public boolean canFailWebSocketTest() {
135.224 - try {
135.225 - Class.forName("java.util.function.Function");
135.226 - return false;
135.227 - } catch (ClassNotFoundException ex) {
135.228 - // running on JDK7, FX WebView WebSocket impl does not work
135.229 - return true;
135.230 - }
135.231 - }
135.232 -}
136.1 --- a/ko-fx/src/test/java/org/apidesign/html/kofx/LessCallbacksCheck.java Mon Dec 16 15:48:09 2013 +0100
136.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
136.3 @@ -1,82 +0,0 @@
136.4 -/**
136.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
136.6 - *
136.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
136.8 - *
136.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
136.10 - * Other names may be trademarks of their respective owners.
136.11 - *
136.12 - * The contents of this file are subject to the terms of either the GNU
136.13 - * General Public License Version 2 only ("GPL") or the Common
136.14 - * Development and Distribution License("CDDL") (collectively, the
136.15 - * "License"). You may not use this file except in compliance with the
136.16 - * License. You can obtain a copy of the License at
136.17 - * http://www.netbeans.org/cddl-gplv2.html
136.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
136.19 - * specific language governing permissions and limitations under the
136.20 - * License. When distributing the software, include this License Header
136.21 - * Notice in each file and include the License file at
136.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
136.23 - * particular file as subject to the "Classpath" exception as provided
136.24 - * by Oracle in the GPL Version 2 section of the License file that
136.25 - * accompanied this code. If applicable, add the following below the
136.26 - * License Header, with the fields enclosed by brackets [] replaced by
136.27 - * your own identifying information:
136.28 - * "Portions Copyrighted [year] [name of copyright owner]"
136.29 - *
136.30 - * Contributor(s):
136.31 - *
136.32 - * The Original Software is NetBeans. The Initial Developer of the Original
136.33 - * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
136.34 - *
136.35 - * If you wish your version of this file to be governed by only the CDDL
136.36 - * or only the GPL Version 2, indicate your decision by adding
136.37 - * "[Contributor] elects to include this software in this distribution
136.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
136.39 - * single choice of license, a recipient has the option to distribute
136.40 - * your version of this file under either the CDDL, the GPL Version 2 or
136.41 - * to extend the choice of license to its licensees as provided above.
136.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
136.43 - * Version 2 license, then the option applies only if the new code is
136.44 - * made subject to such option by the copyright holder.
136.45 - */
136.46 -package org.apidesign.html.kofx;
136.47 -
136.48 -import java.io.PrintWriter;
136.49 -import java.io.StringWriter;
136.50 -import net.java.html.json.ComputedProperty;
136.51 -import net.java.html.json.Model;
136.52 -import net.java.html.json.Property;
136.53 -import org.apidesign.html.json.tck.KOTest;
136.54 -
136.55 -/**
136.56 - *
136.57 - * @author Jaroslav Tulach <jtulach@netbeans.org>
136.58 - */
136.59 -@Model(className = "LessCalls", properties = {
136.60 - @Property(name = "value", type = int.class)
136.61 -})
136.62 -public class LessCallbacksCheck {
136.63 - private static StringWriter sw;
136.64 -
136.65 - @ComputedProperty static int plusOne(int value) {
136.66 - if (sw == null) {
136.67 - sw = new StringWriter();
136.68 - }
136.69 - new Exception("Who calls me?").printStackTrace(
136.70 - new PrintWriter(sw)
136.71 - );
136.72 - return value + 1;
136.73 - }
136.74 -
136.75 - @KOTest public void dontCallForInitialValueBackToJavaVM() {
136.76 - LessCalls m = new LessCalls(10).applyBindings();
136.77 - assert m.getPlusOne() == 11 : "Expecting 11: " + m.getPlusOne();
136.78 -
136.79 - assert sw != null : "StringWriter should be initialized: " + sw;
136.80 -
136.81 - if (sw.toString().contains("$JsCallbacks$")) {
136.82 - assert false : "Don't call for initial value via JsCallbacks:\n" + sw;
136.83 - }
136.84 - }
136.85 -}
137.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
137.2 +++ b/ko-fx/src/test/java/org/netbeans/html/kofx/DynamicHTTP.java Mon Dec 16 16:59:43 2013 +0100
137.3 @@ -0,0 +1,259 @@
137.4 +/**
137.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
137.6 + *
137.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
137.8 + *
137.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
137.10 + * Other names may be trademarks of their respective owners.
137.11 + *
137.12 + * The contents of this file are subject to the terms of either the GNU
137.13 + * General Public License Version 2 only ("GPL") or the Common
137.14 + * Development and Distribution License("CDDL") (collectively, the
137.15 + * "License"). You may not use this file except in compliance with the
137.16 + * License. You can obtain a copy of the License at
137.17 + * http://www.netbeans.org/cddl-gplv2.html
137.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
137.19 + * specific language governing permissions and limitations under the
137.20 + * License. When distributing the software, include this License Header
137.21 + * Notice in each file and include the License file at
137.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
137.23 + * particular file as subject to the "Classpath" exception as provided
137.24 + * by Oracle in the GPL Version 2 section of the License file that
137.25 + * accompanied this code. If applicable, add the following below the
137.26 + * License Header, with the fields enclosed by brackets [] replaced by
137.27 + * your own identifying information:
137.28 + * "Portions Copyrighted [year] [name of copyright owner]"
137.29 + *
137.30 + * Contributor(s):
137.31 + *
137.32 + * The Original Software is NetBeans. The Initial Developer of the Original
137.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
137.34 + *
137.35 + * If you wish your version of this file to be governed by only the CDDL
137.36 + * or only the GPL Version 2, indicate your decision by adding
137.37 + * "[Contributor] elects to include this software in this distribution
137.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
137.39 + * single choice of license, a recipient has the option to distribute
137.40 + * your version of this file under either the CDDL, the GPL Version 2 or
137.41 + * to extend the choice of license to its licensees as provided above.
137.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
137.43 + * Version 2 license, then the option applies only if the new code is
137.44 + * made subject to such option by the copyright holder.
137.45 + */
137.46 +package org.netbeans.html.kofx;
137.47 +
137.48 +import java.io.ByteArrayInputStream;
137.49 +import java.io.ByteArrayOutputStream;
137.50 +import java.io.IOException;
137.51 +import java.io.InputStream;
137.52 +import java.io.OutputStream;
137.53 +import java.io.Reader;
137.54 +import java.net.URI;
137.55 +import java.net.URISyntaxException;
137.56 +import java.util.ArrayList;
137.57 +import java.util.List;
137.58 +import java.util.logging.Level;
137.59 +import java.util.logging.Logger;
137.60 +import org.glassfish.grizzly.PortRange;
137.61 +import org.glassfish.grizzly.http.server.HttpHandler;
137.62 +import org.glassfish.grizzly.http.server.HttpServer;
137.63 +import org.glassfish.grizzly.http.server.NetworkListener;
137.64 +import org.glassfish.grizzly.http.server.Request;
137.65 +import org.glassfish.grizzly.http.server.Response;
137.66 +import org.glassfish.grizzly.http.server.ServerConfiguration;
137.67 +import org.glassfish.grizzly.websockets.WebSocket;
137.68 +import org.glassfish.grizzly.websockets.WebSocketAddOn;
137.69 +import org.glassfish.grizzly.websockets.WebSocketApplication;
137.70 +import org.glassfish.grizzly.websockets.WebSocketEngine;
137.71 +
137.72 +/**
137.73 + *
137.74 + * @author Jaroslav Tulach <jtulach@netbeans.org>
137.75 + */
137.76 +final class DynamicHTTP extends HttpHandler {
137.77 + private static final Logger LOG = Logger.getLogger(DynamicHTTP.class.getName());
137.78 + private static int resourcesCount;
137.79 + private static List<Resource> resources;
137.80 + private static ServerConfiguration conf;
137.81 + private static HttpServer server;
137.82 +
137.83 + private DynamicHTTP() {
137.84 + }
137.85 +
137.86 + static URI initServer() throws Exception {
137.87 + server = HttpServer.createSimpleServer(null, new PortRange(8080, 65535));
137.88 + final WebSocketAddOn addon = new WebSocketAddOn();
137.89 + for (NetworkListener listener : server.getListeners()) {
137.90 + listener.registerAddOn(addon);
137.91 + }
137.92 + resources = new ArrayList<Resource>();
137.93 +
137.94 + conf = server.getServerConfiguration();
137.95 + final DynamicHTTP dh = new DynamicHTTP();
137.96 +
137.97 + conf.addHttpHandler(dh, "/");
137.98 +
137.99 + server.start();
137.100 +
137.101 + return pageURL("http", server, "/test.html");
137.102 + }
137.103 +
137.104 + @Override
137.105 + public void service(Request request, Response response) throws Exception {
137.106 + if ("/test.html".equals(request.getRequestURI())) {
137.107 + response.setContentType("text/html");
137.108 + final InputStream is = DynamicHTTP.class.getResourceAsStream("test.html");
137.109 + copyStream(is, response.getOutputStream(), null);
137.110 + return;
137.111 + }
137.112 + if ("/dynamic".equals(request.getRequestURI())) {
137.113 + String mimeType = request.getParameter("mimeType");
137.114 + List<String> params = new ArrayList<String>();
137.115 + boolean webSocket = false;
137.116 + for (int i = 0;; i++) {
137.117 + String p = request.getParameter("param" + i);
137.118 + if (p == null) {
137.119 + break;
137.120 + }
137.121 + if ("protocol:ws".equals(p)) {
137.122 + webSocket = true;
137.123 + continue;
137.124 + }
137.125 + params.add(p);
137.126 + }
137.127 + final String cnt = request.getParameter("content");
137.128 + String mangle = cnt.replace("%20", " ").replace("%0A", "\n");
137.129 + ByteArrayInputStream is = new ByteArrayInputStream(mangle.getBytes("UTF-8"));
137.130 + URI url;
137.131 + final Resource res = new Resource(is, mimeType, "/dynamic/res" + ++resourcesCount, params.toArray(new String[params.size()]));
137.132 + if (webSocket) {
137.133 + url = registerWebSocket(res);
137.134 + } else {
137.135 + url = registerResource(res);
137.136 + }
137.137 + response.getWriter().write(url.toString());
137.138 + response.getWriter().write("\n");
137.139 + return;
137.140 + }
137.141 +
137.142 + for (Resource r : resources) {
137.143 + if (r.httpPath.equals(request.getRequestURI())) {
137.144 + response.setContentType(r.httpType);
137.145 + r.httpContent.reset();
137.146 + String[] params = null;
137.147 + if (r.parameters.length != 0) {
137.148 + params = new String[r.parameters.length];
137.149 + for (int i = 0; i < r.parameters.length; i++) {
137.150 + params[i] = request.getParameter(r.parameters[i]);
137.151 + if (params[i] == null) {
137.152 + if ("http.method".equals(r.parameters[i])) {
137.153 + params[i] = request.getMethod().toString();
137.154 + } else if ("http.requestBody".equals(r.parameters[i])) {
137.155 + Reader rdr = request.getReader();
137.156 + StringBuilder sb = new StringBuilder();
137.157 + for (;;) {
137.158 + int ch = rdr.read();
137.159 + if (ch == -1) {
137.160 + break;
137.161 + }
137.162 + sb.append((char) ch);
137.163 + }
137.164 + params[i] = sb.toString();
137.165 + }
137.166 + }
137.167 + if (params[i] == null) {
137.168 + params[i] = "null";
137.169 + }
137.170 + }
137.171 + }
137.172 +
137.173 + copyStream(r.httpContent, response.getOutputStream(), null, params);
137.174 + }
137.175 + }
137.176 + }
137.177 +
137.178 + private URI registerWebSocket(Resource r) {
137.179 + WebSocketEngine.getEngine().register("", r.httpPath, new WS(r));
137.180 + return pageURL("ws", server, r.httpPath);
137.181 + }
137.182 +
137.183 + private URI registerResource(Resource r) {
137.184 + if (!resources.contains(r)) {
137.185 + resources.add(r);
137.186 + conf.addHttpHandler(this, r.httpPath);
137.187 + }
137.188 + return pageURL("http", server, r.httpPath);
137.189 + }
137.190 +
137.191 + private static URI pageURL(String proto, HttpServer server, final String page) {
137.192 + NetworkListener listener = server.getListeners().iterator().next();
137.193 + int port = listener.getPort();
137.194 + try {
137.195 + return new URI(proto + "://localhost:" + port + page);
137.196 + } catch (URISyntaxException ex) {
137.197 + throw new IllegalStateException(ex);
137.198 + }
137.199 + }
137.200 +
137.201 + static final class Resource {
137.202 +
137.203 + final InputStream httpContent;
137.204 + final String httpType;
137.205 + final String httpPath;
137.206 + final String[] parameters;
137.207 +
137.208 + Resource(InputStream httpContent, String httpType, String httpPath,
137.209 + String[] parameters) {
137.210 + httpContent.mark(Integer.MAX_VALUE);
137.211 + this.httpContent = httpContent;
137.212 + this.httpType = httpType;
137.213 + this.httpPath = httpPath;
137.214 + this.parameters = parameters;
137.215 + }
137.216 + }
137.217 +
137.218 + static void copyStream(InputStream is, OutputStream os, String baseURL, String... params) throws IOException {
137.219 + for (;;) {
137.220 + int ch = is.read();
137.221 + if (ch == -1) {
137.222 + break;
137.223 + }
137.224 + if (ch == '$' && params.length > 0) {
137.225 + int cnt = is.read() - '0';
137.226 + if (baseURL != null && cnt == 'U' - '0') {
137.227 + os.write(baseURL.getBytes("UTF-8"));
137.228 + } else {
137.229 + if (cnt >= 0 && cnt < params.length) {
137.230 + os.write(params[cnt].getBytes("UTF-8"));
137.231 + } else {
137.232 + os.write('$');
137.233 + os.write(cnt + '0');
137.234 + }
137.235 + }
137.236 + } else {
137.237 + os.write(ch);
137.238 + }
137.239 + }
137.240 + }
137.241 +
137.242 + private static class WS extends WebSocketApplication {
137.243 + private final Resource r;
137.244 +
137.245 + private WS(Resource r) {
137.246 + this.r = r;
137.247 + }
137.248 +
137.249 + @Override
137.250 + public void onMessage(WebSocket socket, String text) {
137.251 + try {
137.252 + r.httpContent.reset();
137.253 + ByteArrayOutputStream out = new ByteArrayOutputStream();
137.254 + copyStream(r.httpContent, out, null, text);
137.255 + String s = new String(out.toByteArray(), "UTF-8");
137.256 + socket.send(s);
137.257 + } catch (IOException ex) {
137.258 + LOG.log(Level.WARNING, "Error processing message " + text, ex);
137.259 + }
137.260 + }
137.261 + }
137.262 +}
138.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
138.2 +++ b/ko-fx/src/test/java/org/netbeans/html/kofx/KOFx.java Mon Dec 16 16:59:43 2013 +0100
138.3 @@ -0,0 +1,118 @@
138.4 +/**
138.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
138.6 + *
138.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
138.8 + *
138.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
138.10 + * Other names may be trademarks of their respective owners.
138.11 + *
138.12 + * The contents of this file are subject to the terms of either the GNU
138.13 + * General Public License Version 2 only ("GPL") or the Common
138.14 + * Development and Distribution License("CDDL") (collectively, the
138.15 + * "License"). You may not use this file except in compliance with the
138.16 + * License. You can obtain a copy of the License at
138.17 + * http://www.netbeans.org/cddl-gplv2.html
138.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
138.19 + * specific language governing permissions and limitations under the
138.20 + * License. When distributing the software, include this License Header
138.21 + * Notice in each file and include the License file at
138.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
138.23 + * particular file as subject to the "Classpath" exception as provided
138.24 + * by Oracle in the GPL Version 2 section of the License file that
138.25 + * accompanied this code. If applicable, add the following below the
138.26 + * License Header, with the fields enclosed by brackets [] replaced by
138.27 + * your own identifying information:
138.28 + * "Portions Copyrighted [year] [name of copyright owner]"
138.29 + *
138.30 + * Contributor(s):
138.31 + *
138.32 + * The Original Software is NetBeans. The Initial Developer of the Original
138.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
138.34 + *
138.35 + * If you wish your version of this file to be governed by only the CDDL
138.36 + * or only the GPL Version 2, indicate your decision by adding
138.37 + * "[Contributor] elects to include this software in this distribution
138.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
138.39 + * single choice of license, a recipient has the option to distribute
138.40 + * your version of this file under either the CDDL, the GPL Version 2 or
138.41 + * to extend the choice of license to its licensees as provided above.
138.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
138.43 + * Version 2 license, then the option applies only if the new code is
138.44 + * made subject to such option by the copyright holder.
138.45 + */
138.46 +package org.netbeans.html.kofx;
138.47 +
138.48 +import java.io.Closeable;
138.49 +import java.lang.reflect.InvocationTargetException;
138.50 +import java.lang.reflect.Method;
138.51 +import javafx.application.Platform;
138.52 +import org.apidesign.html.boot.spi.Fn;
138.53 +import org.testng.ITest;
138.54 +import org.testng.annotations.Test;
138.55 +
138.56 +/**
138.57 + *
138.58 + * @author Jaroslav Tulach <jtulach@netbeans.org>
138.59 + */
138.60 +public final class KOFx implements ITest, Runnable {
138.61 + private final Fn.Presenter p;
138.62 + private final Method m;
138.63 + private Object result;
138.64 + private Object inst;
138.65 + private int count;
138.66 +
138.67 + KOFx(Fn.Presenter p, Method m) {
138.68 + this.p = p;
138.69 + this.m = m;
138.70 + }
138.71 +
138.72 + @Override
138.73 + public String getTestName() {
138.74 + return m.getName();
138.75 + }
138.76 +
138.77 + @Test
138.78 + public synchronized void executeTest() throws Exception {
138.79 + if (result == null) {
138.80 + Platform.runLater(this);
138.81 + wait();
138.82 + }
138.83 + if (result instanceof Exception) {
138.84 + throw (Exception)result;
138.85 + }
138.86 + if (result instanceof Error) {
138.87 + throw (Error)result;
138.88 + }
138.89 + }
138.90 +
138.91 + @Override
138.92 + public synchronized void run() {
138.93 + boolean notify = true;
138.94 + try (Closeable a = Fn.activate(p)) {
138.95 + if (inst == null) {
138.96 + inst = m.getDeclaringClass().newInstance();
138.97 + }
138.98 + result = m.invoke(inst);
138.99 + if (result == null) {
138.100 + result = this;
138.101 + }
138.102 + } catch (InvocationTargetException ex) {
138.103 + Throwable r = ex.getTargetException();
138.104 + if (r instanceof InterruptedException) {
138.105 + if (count++ < 10000) {
138.106 + notify = false;
138.107 + Platform.runLater(this);
138.108 + return;
138.109 + }
138.110 + }
138.111 + result = r;
138.112 + } catch (Exception ex) {
138.113 + result = ex;
138.114 + } finally {
138.115 + if (notify) {
138.116 + notifyAll();
138.117 + }
138.118 + }
138.119 + }
138.120 +
138.121 +}
139.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
139.2 +++ b/ko-fx/src/test/java/org/netbeans/html/kofx/KnockoutFXTest.java Mon Dec 16 16:59:43 2013 +0100
139.3 @@ -0,0 +1,229 @@
139.4 +/**
139.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
139.6 + *
139.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
139.8 + *
139.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
139.10 + * Other names may be trademarks of their respective owners.
139.11 + *
139.12 + * The contents of this file are subject to the terms of either the GNU
139.13 + * General Public License Version 2 only ("GPL") or the Common
139.14 + * Development and Distribution License("CDDL") (collectively, the
139.15 + * "License"). You may not use this file except in compliance with the
139.16 + * License. You can obtain a copy of the License at
139.17 + * http://www.netbeans.org/cddl-gplv2.html
139.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
139.19 + * specific language governing permissions and limitations under the
139.20 + * License. When distributing the software, include this License Header
139.21 + * Notice in each file and include the License file at
139.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
139.23 + * particular file as subject to the "Classpath" exception as provided
139.24 + * by Oracle in the GPL Version 2 section of the License file that
139.25 + * accompanied this code. If applicable, add the following below the
139.26 + * License Header, with the fields enclosed by brackets [] replaced by
139.27 + * your own identifying information:
139.28 + * "Portions Copyrighted [year] [name of copyright owner]"
139.29 + *
139.30 + * Contributor(s):
139.31 + *
139.32 + * The Original Software is NetBeans. The Initial Developer of the Original
139.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
139.34 + *
139.35 + * If you wish your version of this file to be governed by only the CDDL
139.36 + * or only the GPL Version 2, indicate your decision by adding
139.37 + * "[Contributor] elects to include this software in this distribution
139.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
139.39 + * single choice of license, a recipient has the option to distribute
139.40 + * your version of this file under either the CDDL, the GPL Version 2 or
139.41 + * to extend the choice of license to its licensees as provided above.
139.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
139.43 + * Version 2 license, then the option applies only if the new code is
139.44 + * made subject to such option by the copyright holder.
139.45 + */
139.46 +package org.netbeans.html.kofx;
139.47 +
139.48 +import java.io.BufferedReader;
139.49 +import java.io.IOException;
139.50 +import java.io.InputStreamReader;
139.51 +import java.lang.annotation.Annotation;
139.52 +import java.lang.reflect.Method;
139.53 +import java.net.URI;
139.54 +import java.net.URISyntaxException;
139.55 +import java.net.URL;
139.56 +import java.net.URLConnection;
139.57 +import java.util.ArrayList;
139.58 +import java.util.List;
139.59 +import java.util.Map;
139.60 +import java.util.concurrent.Executors;
139.61 +import net.java.html.BrwsrCtx;
139.62 +import net.java.html.boot.BrowserBuilder;
139.63 +import net.java.html.js.JavaScriptBody;
139.64 +import org.netbeans.html.boot.impl.FnContext;
139.65 +import org.apidesign.html.boot.spi.Fn;
139.66 +import org.apidesign.html.context.spi.Contexts;
139.67 +import org.apidesign.html.json.spi.Technology;
139.68 +import org.apidesign.html.json.spi.Transfer;
139.69 +import org.apidesign.html.json.spi.WSTransfer;
139.70 +import org.apidesign.html.json.tck.KOTest;
139.71 +import org.apidesign.html.json.tck.KnockoutTCK;
139.72 +import org.json.JSONException;
139.73 +import org.json.JSONObject;
139.74 +import org.openide.util.lookup.ServiceProvider;
139.75 +import org.testng.annotations.Factory;
139.76 +import static org.testng.Assert.*;
139.77 +
139.78 +/**
139.79 + *
139.80 + * @author Jaroslav Tulach <jtulach@netbeans.org>
139.81 + */
139.82 +@ServiceProvider(service = KnockoutTCK.class)
139.83 +public final class KnockoutFXTest extends KnockoutTCK {
139.84 + private static Class<?> browserClass;
139.85 + private static Fn.Presenter browserContext;
139.86 +
139.87 + public KnockoutFXTest() {
139.88 + }
139.89 +
139.90 + @Factory public static Object[] compatibilityTests() throws Exception {
139.91 + Class[] arr = testClasses();
139.92 + for (int i = 0; i < arr.length; i++) {
139.93 + assertEquals(
139.94 + arr[i].getClassLoader(),
139.95 + KnockoutFXTest.class.getClassLoader(),
139.96 + "All classes loaded by the same classloader"
139.97 + );
139.98 + }
139.99 +
139.100 + URI uri = DynamicHTTP.initServer();
139.101 +
139.102 + final BrowserBuilder bb = BrowserBuilder.newBrowser().loadClass(KnockoutFXTest.class).
139.103 + loadPage(uri.toString()).
139.104 + invoke("initialized");
139.105 +
139.106 + Executors.newSingleThreadExecutor().submit(new Runnable() {
139.107 + @Override
139.108 + public void run() {
139.109 + bb.showAndWait();
139.110 + }
139.111 + });
139.112 +
139.113 + ClassLoader l = getClassLoader();
139.114 + List<Object> res = new ArrayList<Object>();
139.115 + for (int i = 0; i < arr.length; i++) {
139.116 + Class<?> c = Class.forName(arr[i].getName(), true, l);
139.117 + seekKOTests(c, res);
139.118 + }
139.119 + Class<?> c = Class.forName(LessCallbacksCheck.class.getName(), true, l);
139.120 + seekKOTests(c, res);
139.121 + return res.toArray();
139.122 + }
139.123 +
139.124 + private static void seekKOTests(Class<?> c, List<Object> res) throws SecurityException, ClassNotFoundException {
139.125 + Class<? extends Annotation> koTest =
139.126 + c.getClassLoader().loadClass(KOTest.class.getName()).
139.127 + asSubclass(Annotation.class);
139.128 + for (Method m : c.getMethods()) {
139.129 + if (m.getAnnotation(koTest) != null) {
139.130 + res.add(new KOFx(browserContext, m));
139.131 + }
139.132 + }
139.133 + }
139.134 +
139.135 + static synchronized ClassLoader getClassLoader() throws InterruptedException {
139.136 + while (browserClass == null) {
139.137 + KnockoutFXTest.class.wait();
139.138 + }
139.139 + return browserClass.getClassLoader();
139.140 + }
139.141 +
139.142 + public static synchronized void initialized(Class<?> browserCls) throws Exception {
139.143 + browserClass = browserCls;
139.144 + browserContext = FnContext.currentPresenter();
139.145 + KnockoutFXTest.class.notifyAll();
139.146 + }
139.147 +
139.148 + public static void initialized() throws Exception {
139.149 + Class<?> classpathClass = ClassLoader.getSystemClassLoader().loadClass(KnockoutFXTest.class.getName());
139.150 + Method m = classpathClass.getMethod("initialized", Class.class);
139.151 + m.invoke(null, KnockoutFXTest.class);
139.152 + browserContext = FnContext.currentPresenter();
139.153 + }
139.154 +
139.155 + @Override
139.156 + public BrwsrCtx createContext() {
139.157 + FXContext fx = new FXContext(browserContext);
139.158 + Contexts.Builder cb = Contexts.newBuilder().
139.159 + register(Technology.class, fx, 10).
139.160 + register(Transfer.class, fx, 10);
139.161 + if (fx.areWebSocketsSupported()) {
139.162 + cb.register(WSTransfer.class, fx, 10);
139.163 + }
139.164 + return cb.build();
139.165 + }
139.166 +
139.167 + @Override
139.168 + public Object createJSON(Map<String, Object> values) {
139.169 + JSONObject json = new JSONObject();
139.170 + for (Map.Entry<String, Object> entry : values.entrySet()) {
139.171 + try {
139.172 + json.put(entry.getKey(), entry.getValue());
139.173 + } catch (JSONException ex) {
139.174 + throw new IllegalStateException(ex);
139.175 + }
139.176 + }
139.177 + return json;
139.178 + }
139.179 +
139.180 + @Override
139.181 + @JavaScriptBody(args = { "s", "args" }, body = ""
139.182 + + "var f = new Function(s); "
139.183 + + "return f.apply(null, args);"
139.184 + )
139.185 + public native Object executeScript(String script, Object[] arguments);
139.186 +
139.187 + @JavaScriptBody(args = { }, body =
139.188 + "var h;"
139.189 + + "if (!!window && !!window.location && !!window.location.href)\n"
139.190 + + " h = window.location.href;\n"
139.191 + + "else "
139.192 + + " h = null;"
139.193 + + "return h;\n"
139.194 + )
139.195 + private static native String findBaseURL();
139.196 +
139.197 + @Override
139.198 + public URI prepareURL(String content, String mimeType, String[] parameters) {
139.199 + try {
139.200 + final URL baseURL = new URL(findBaseURL());
139.201 + StringBuilder sb = new StringBuilder();
139.202 + sb.append("/dynamic?mimeType=").append(mimeType);
139.203 + for (int i = 0; i < parameters.length; i++) {
139.204 + sb.append("¶m" + i).append("=").append(parameters[i]);
139.205 + }
139.206 + String mangle = content.replace("\n", "%0a")
139.207 + .replace("\"", "\\\"").replace(" ", "%20");
139.208 + sb.append("&content=").append(mangle);
139.209 +
139.210 + URL query = new URL(baseURL, sb.toString());
139.211 + URLConnection c = query.openConnection();
139.212 + BufferedReader br = new BufferedReader(new InputStreamReader(c.getInputStream()));
139.213 + URI connectTo = new URI(br.readLine());
139.214 + return connectTo;
139.215 + } catch (IOException ex) {
139.216 + throw new IllegalStateException(ex);
139.217 + } catch (URISyntaxException ex) {
139.218 + throw new IllegalStateException(ex);
139.219 + }
139.220 + }
139.221 +
139.222 + @Override
139.223 + public boolean canFailWebSocketTest() {
139.224 + try {
139.225 + Class.forName("java.util.function.Function");
139.226 + return false;
139.227 + } catch (ClassNotFoundException ex) {
139.228 + // running on JDK7, FX WebView WebSocket impl does not work
139.229 + return true;
139.230 + }
139.231 + }
139.232 +}
140.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
140.2 +++ b/ko-fx/src/test/java/org/netbeans/html/kofx/LessCallbacksCheck.java Mon Dec 16 16:59:43 2013 +0100
140.3 @@ -0,0 +1,82 @@
140.4 +/**
140.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
140.6 + *
140.7 + * Copyright 1997-2010 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.kofx;
140.47 +
140.48 +import java.io.PrintWriter;
140.49 +import java.io.StringWriter;
140.50 +import net.java.html.json.ComputedProperty;
140.51 +import net.java.html.json.Model;
140.52 +import net.java.html.json.Property;
140.53 +import org.apidesign.html.json.tck.KOTest;
140.54 +
140.55 +/**
140.56 + *
140.57 + * @author Jaroslav Tulach <jtulach@netbeans.org>
140.58 + */
140.59 +@Model(className = "LessCalls", properties = {
140.60 + @Property(name = "value", type = int.class)
140.61 +})
140.62 +public class LessCallbacksCheck {
140.63 + private static StringWriter sw;
140.64 +
140.65 + @ComputedProperty static int plusOne(int value) {
140.66 + if (sw == null) {
140.67 + sw = new StringWriter();
140.68 + }
140.69 + new Exception("Who calls me?").printStackTrace(
140.70 + new PrintWriter(sw)
140.71 + );
140.72 + return value + 1;
140.73 + }
140.74 +
140.75 + @KOTest public void dontCallForInitialValueBackToJavaVM() {
140.76 + LessCalls m = new LessCalls(10).applyBindings();
140.77 + assert m.getPlusOne() == 11 : "Expecting 11: " + m.getPlusOne();
140.78 +
140.79 + assert sw != null : "StringWriter should be initialized: " + sw;
140.80 +
140.81 + if (sw.toString().contains("$JsCallbacks$")) {
140.82 + assert false : "Don't call for initial value via JsCallbacks:\n" + sw;
140.83 + }
140.84 + }
140.85 +}
141.1 --- a/ko-fx/src/test/resources/org/apidesign/html/kofx/test.html Mon Dec 16 15:48:09 2013 +0100
141.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
141.3 @@ -1,56 +0,0 @@
141.4 -<!--
141.5 -
141.6 - DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
141.7 -
141.8 - Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
141.9 -
141.10 - Oracle and Java are registered trademarks of Oracle and/or its affiliates.
141.11 - Other names may be trademarks of their respective owners.
141.12 -
141.13 - The contents of this file are subject to the terms of either the GNU
141.14 - General Public License Version 2 only ("GPL") or the Common
141.15 - Development and Distribution License("CDDL") (collectively, the
141.16 - "License"). You may not use this file except in compliance with the
141.17 - License. You can obtain a copy of the License at
141.18 - http://www.netbeans.org/cddl-gplv2.html
141.19 - or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
141.20 - specific language governing permissions and limitations under the
141.21 - License. When distributing the software, include this License Header
141.22 - Notice in each file and include the License file at
141.23 - nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
141.24 - particular file as subject to the "Classpath" exception as provided
141.25 - by Oracle in the GPL Version 2 section of the License file that
141.26 - accompanied this code. If applicable, add the following below the
141.27 - License Header, with the fields enclosed by brackets [] replaced by
141.28 - your own identifying information:
141.29 - "Portions Copyrighted [year] [name of copyright owner]"
141.30 -
141.31 - Contributor(s):
141.32 -
141.33 - The Original Software is NetBeans. The Initial Developer of the Original
141.34 - Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
141.35 -
141.36 - If you wish your version of this file to be governed by only the CDDL
141.37 - or only the GPL Version 2, indicate your decision by adding
141.38 - "[Contributor] elects to include this software in this distribution
141.39 - under the [CDDL or GPL Version 2] license." If you do not indicate a
141.40 - single choice of license, a recipient has the option to distribute
141.41 - your version of this file under either the CDDL, the GPL Version 2 or
141.42 - to extend the choice of license to its licensees as provided above.
141.43 - However, if you add GPL Version 2 code and therefore, elected the GPL
141.44 - Version 2 license, then the option applies only if the new code is
141.45 - made subject to such option by the copyright holder.
141.46 -
141.47 --->
141.48 -<!DOCTYPE html>
141.49 -<html>
141.50 - <head>
141.51 - <title>Knockout.fx Execution Harness</title>
141.52 - <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
141.53 - <meta name="viewport" content="width=device-width">
141.54 - </head>
141.55 - <body>
141.56 - <h1>Knockout.fx Execution Harness</h1>
141.57 - </body>
141.58 - <script></script>
141.59 -</html>
142.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
142.2 +++ b/ko-fx/src/test/resources/org/netbeans/html/kofx/test.html Mon Dec 16 16:59:43 2013 +0100
142.3 @@ -0,0 +1,56 @@
142.4 +<!--
142.5 +
142.6 + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
142.7 +
142.8 + Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
142.9 +
142.10 + Oracle and Java are registered trademarks of Oracle and/or its affiliates.
142.11 + Other names may be trademarks of their respective owners.
142.12 +
142.13 + The contents of this file are subject to the terms of either the GNU
142.14 + General Public License Version 2 only ("GPL") or the Common
142.15 + Development and Distribution License("CDDL") (collectively, the
142.16 + "License"). You may not use this file except in compliance with the
142.17 + License. You can obtain a copy of the License at
142.18 + http://www.netbeans.org/cddl-gplv2.html
142.19 + or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
142.20 + specific language governing permissions and limitations under the
142.21 + License. When distributing the software, include this License Header
142.22 + Notice in each file and include the License file at
142.23 + nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
142.24 + particular file as subject to the "Classpath" exception as provided
142.25 + by Oracle in the GPL Version 2 section of the License file that
142.26 + accompanied this code. If applicable, add the following below the
142.27 + License Header, with the fields enclosed by brackets [] replaced by
142.28 + your own identifying information:
142.29 + "Portions Copyrighted [year] [name of copyright owner]"
142.30 +
142.31 + Contributor(s):
142.32 +
142.33 + The Original Software is NetBeans. The Initial Developer of the Original
142.34 + Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
142.35 +
142.36 + If you wish your version of this file to be governed by only the CDDL
142.37 + or only the GPL Version 2, indicate your decision by adding
142.38 + "[Contributor] elects to include this software in this distribution
142.39 + under the [CDDL or GPL Version 2] license." If you do not indicate a
142.40 + single choice of license, a recipient has the option to distribute
142.41 + your version of this file under either the CDDL, the GPL Version 2 or
142.42 + to extend the choice of license to its licensees as provided above.
142.43 + However, if you add GPL Version 2 code and therefore, elected the GPL
142.44 + Version 2 license, then the option applies only if the new code is
142.45 + made subject to such option by the copyright holder.
142.46 +
142.47 +-->
142.48 +<!DOCTYPE html>
142.49 +<html>
142.50 + <head>
142.51 + <title>Knockout.fx Execution Harness</title>
142.52 + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
142.53 + <meta name="viewport" content="width=device-width">
142.54 + </head>
142.55 + <body>
142.56 + <h1>Knockout.fx Execution Harness</h1>
142.57 + </body>
142.58 + <script></script>
142.59 +</html>
143.1 --- a/ko-ws-tyrus/src/main/java/org/apidesign/html/wstyrus/TyrusContext.java Mon Dec 16 15:48:09 2013 +0100
143.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
143.3 @@ -1,190 +0,0 @@
143.4 -/**
143.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
143.6 - *
143.7 - * Copyright 1997-2010 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.apidesign.html.wstyrus;
143.47 -
143.48 -import java.io.IOException;
143.49 -import java.net.URI;
143.50 -import java.net.URISyntaxException;
143.51 -import java.util.Iterator;
143.52 -import javax.websocket.ClientEndpoint;
143.53 -import javax.websocket.ContainerProvider;
143.54 -import javax.websocket.DeploymentException;
143.55 -import javax.websocket.OnClose;
143.56 -import javax.websocket.OnError;
143.57 -import javax.websocket.OnMessage;
143.58 -import javax.websocket.OnOpen;
143.59 -import javax.websocket.Session;
143.60 -import javax.websocket.WebSocketContainer;
143.61 -import net.java.html.json.OnReceive;
143.62 -import org.apidesign.html.context.spi.Contexts;
143.63 -import org.apidesign.html.json.spi.JSONCall;
143.64 -import org.apidesign.html.json.spi.WSTransfer;
143.65 -import org.apidesign.html.wstyrus.TyrusContext.Comm;
143.66 -import org.json.JSONArray;
143.67 -import org.json.JSONException;
143.68 -import org.json.JSONObject;
143.69 -import org.json.JSONTokener;
143.70 -import org.openide.util.lookup.ServiceProvider;
143.71 -
143.72 -/** This is an implementation module that provides support for
143.73 - * WebSocket protocol for {@link OnReceive} communication end point for
143.74 - * JDK7.
143.75 - * <p>
143.76 - * Don't deal with this module directly, rather use the
143.77 - * {@link OnReceive @OnReceive(url="ws://...", ...)} API to establish your
143.78 - * WebSocket connection.
143.79 - * <p>
143.80 - * There is no need to include this module in your application if you are
143.81 - * running on JDK8. JDK8 WebView provides its own implementation of the
143.82 - * WebSocket API based on WebSocket object inside a browser. This is included
143.83 - * in the <code>org.apidesign.html:ko-fx:0.5</code> module.
143.84 - *
143.85 - * @author Jaroslav Tulach <jtulach@netbeans.org>
143.86 - */
143.87 -@ServiceProvider(service = Contexts.Provider.class)
143.88 -public final class TyrusContext implements Contexts.Provider, WSTransfer<Comm> {
143.89 - @Override
143.90 - public void fillContext(Contexts.Builder context, Class<?> requestor) {
143.91 - // default WebSocket transfer implementation is registered
143.92 - // in ko-fx module with 100, provide this one as a fallback only
143.93 - context.register(WSTransfer.class, this, 1000);
143.94 - }
143.95 -
143.96 - @Override
143.97 - public Comm open(String url, JSONCall callback) {
143.98 - try {
143.99 - return new Comm(new URI(url), callback);
143.100 - } catch (URISyntaxException ex) {
143.101 - throw new IllegalStateException(ex);
143.102 - }
143.103 - }
143.104 -
143.105 - @Override
143.106 - public void send(Comm socket, JSONCall data) {
143.107 - socket.session.getAsyncRemote().sendText(data.getMessage());
143.108 - }
143.109 -
143.110 - @Override
143.111 - public void close(Comm socket) {
143.112 - try {
143.113 - final Session s = socket.session;
143.114 - if (s != null) {
143.115 - s.close();
143.116 - }
143.117 - } catch (IOException ex) {
143.118 - socket.callback.notifyError(ex);
143.119 - }
143.120 - }
143.121 -
143.122 - /** Implementation class in an implementation. Represents a {@link ClientEndpoint} of the
143.123 - * WebSocket channel. You are unlikely to get on hold of it.
143.124 - */
143.125 - @ClientEndpoint
143.126 - public static final class Comm {
143.127 - private final JSONCall callback;
143.128 - private Session session;
143.129 -
143.130 - Comm(final URI url, JSONCall callback) {
143.131 - this.callback = callback;
143.132 - try {
143.133 - final WebSocketContainer c = ContainerProvider.getWebSocketContainer();
143.134 - c.connectToServer(Comm.this, url);
143.135 - } catch (DeploymentException | IOException ex) {
143.136 - wasAnError(ex);
143.137 - }
143.138 - }
143.139 -
143.140 - @OnOpen
143.141 - public synchronized void open(Session s) {
143.142 - this.session = s;
143.143 - callback.notifySuccess(null);
143.144 - }
143.145 -
143.146 - @OnClose
143.147 - public void close() {
143.148 - this.session = null;
143.149 - callback.notifyError(null);
143.150 - }
143.151 -
143.152 - @OnMessage
143.153 - public void message(final String orig, Session s) {
143.154 - Object json;
143.155 - String data = orig.trim();
143.156 - try {
143.157 - JSONTokener tok = new JSONTokener(data);
143.158 - Object obj = data.startsWith("[") ? new JSONArray(tok) : new JSONObject(tok);
143.159 - json = convertToArray(obj);
143.160 - } catch (JSONException ex) {
143.161 - json = data;
143.162 - }
143.163 - callback.notifySuccess(json);
143.164 - }
143.165 -
143.166 - @OnError
143.167 - public void wasAnError(Throwable t) {
143.168 - callback.notifyError(t);
143.169 - }
143.170 -
143.171 - static Object convertToArray(Object o) throws JSONException {
143.172 - if (o instanceof JSONArray) {
143.173 - JSONArray ja = (JSONArray) o;
143.174 - Object[] arr = new Object[ja.length()];
143.175 - for (int i = 0; i < arr.length; i++) {
143.176 - arr[i] = convertToArray(ja.get(i));
143.177 - }
143.178 - return arr;
143.179 - } else if (o instanceof JSONObject) {
143.180 - JSONObject obj = (JSONObject) o;
143.181 - Iterator it = obj.keys();
143.182 - while (it.hasNext()) {
143.183 - String key = (String) it.next();
143.184 - obj.put(key, convertToArray(obj.get(key)));
143.185 - }
143.186 - return obj;
143.187 - } else {
143.188 - return o;
143.189 - }
143.190 - }
143.191 -
143.192 - } // end of Comm
143.193 -}
144.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
144.2 +++ b/ko-ws-tyrus/src/main/java/org/netbeans/html/wstyrus/TyrusContext.java Mon Dec 16 16:59:43 2013 +0100
144.3 @@ -0,0 +1,190 @@
144.4 +/**
144.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
144.6 + *
144.7 + * Copyright 1997-2010 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.wstyrus;
144.47 +
144.48 +import java.io.IOException;
144.49 +import java.net.URI;
144.50 +import java.net.URISyntaxException;
144.51 +import java.util.Iterator;
144.52 +import javax.websocket.ClientEndpoint;
144.53 +import javax.websocket.ContainerProvider;
144.54 +import javax.websocket.DeploymentException;
144.55 +import javax.websocket.OnClose;
144.56 +import javax.websocket.OnError;
144.57 +import javax.websocket.OnMessage;
144.58 +import javax.websocket.OnOpen;
144.59 +import javax.websocket.Session;
144.60 +import javax.websocket.WebSocketContainer;
144.61 +import net.java.html.json.OnReceive;
144.62 +import org.apidesign.html.context.spi.Contexts;
144.63 +import org.apidesign.html.json.spi.JSONCall;
144.64 +import org.apidesign.html.json.spi.WSTransfer;
144.65 +import org.netbeans.html.wstyrus.TyrusContext.Comm;
144.66 +import org.json.JSONArray;
144.67 +import org.json.JSONException;
144.68 +import org.json.JSONObject;
144.69 +import org.json.JSONTokener;
144.70 +import org.openide.util.lookup.ServiceProvider;
144.71 +
144.72 +/** This is an implementation module that provides support for
144.73 + * WebSocket protocol for {@link OnReceive} communication end point for
144.74 + * JDK7.
144.75 + * <p>
144.76 + * Don't deal with this module directly, rather use the
144.77 + * {@link OnReceive @OnReceive(url="ws://...", ...)} API to establish your
144.78 + * WebSocket connection.
144.79 + * <p>
144.80 + * There is no need to include this module in your application if you are
144.81 + * running on JDK8. JDK8 WebView provides its own implementation of the
144.82 + * WebSocket API based on WebSocket object inside a browser. This is included
144.83 + * in the <code>org.apidesign.html:ko-fx:0.5</code> module.
144.84 + *
144.85 + * @author Jaroslav Tulach <jtulach@netbeans.org>
144.86 + */
144.87 +@ServiceProvider(service = Contexts.Provider.class)
144.88 +public final class TyrusContext implements Contexts.Provider, WSTransfer<Comm> {
144.89 + @Override
144.90 + public void fillContext(Contexts.Builder context, Class<?> requestor) {
144.91 + // default WebSocket transfer implementation is registered
144.92 + // in ko-fx module with 100, provide this one as a fallback only
144.93 + context.register(WSTransfer.class, this, 1000);
144.94 + }
144.95 +
144.96 + @Override
144.97 + public Comm open(String url, JSONCall callback) {
144.98 + try {
144.99 + return new Comm(new URI(url), callback);
144.100 + } catch (URISyntaxException ex) {
144.101 + throw new IllegalStateException(ex);
144.102 + }
144.103 + }
144.104 +
144.105 + @Override
144.106 + public void send(Comm socket, JSONCall data) {
144.107 + socket.session.getAsyncRemote().sendText(data.getMessage());
144.108 + }
144.109 +
144.110 + @Override
144.111 + public void close(Comm socket) {
144.112 + try {
144.113 + final Session s = socket.session;
144.114 + if (s != null) {
144.115 + s.close();
144.116 + }
144.117 + } catch (IOException ex) {
144.118 + socket.callback.notifyError(ex);
144.119 + }
144.120 + }
144.121 +
144.122 + /** Implementation class in an implementation. Represents a {@link ClientEndpoint} of the
144.123 + * WebSocket channel. You are unlikely to get on hold of it.
144.124 + */
144.125 + @ClientEndpoint
144.126 + public static final class Comm {
144.127 + private final JSONCall callback;
144.128 + private Session session;
144.129 +
144.130 + Comm(final URI url, JSONCall callback) {
144.131 + this.callback = callback;
144.132 + try {
144.133 + final WebSocketContainer c = ContainerProvider.getWebSocketContainer();
144.134 + c.connectToServer(Comm.this, url);
144.135 + } catch (DeploymentException | IOException ex) {
144.136 + wasAnError(ex);
144.137 + }
144.138 + }
144.139 +
144.140 + @OnOpen
144.141 + public synchronized void open(Session s) {
144.142 + this.session = s;
144.143 + callback.notifySuccess(null);
144.144 + }
144.145 +
144.146 + @OnClose
144.147 + public void close() {
144.148 + this.session = null;
144.149 + callback.notifyError(null);
144.150 + }
144.151 +
144.152 + @OnMessage
144.153 + public void message(final String orig, Session s) {
144.154 + Object json;
144.155 + String data = orig.trim();
144.156 + try {
144.157 + JSONTokener tok = new JSONTokener(data);
144.158 + Object obj = data.startsWith("[") ? new JSONArray(tok) : new JSONObject(tok);
144.159 + json = convertToArray(obj);
144.160 + } catch (JSONException ex) {
144.161 + json = data;
144.162 + }
144.163 + callback.notifySuccess(json);
144.164 + }
144.165 +
144.166 + @OnError
144.167 + public void wasAnError(Throwable t) {
144.168 + callback.notifyError(t);
144.169 + }
144.170 +
144.171 + static Object convertToArray(Object o) throws JSONException {
144.172 + if (o instanceof JSONArray) {
144.173 + JSONArray ja = (JSONArray) o;
144.174 + Object[] arr = new Object[ja.length()];
144.175 + for (int i = 0; i < arr.length; i++) {
144.176 + arr[i] = convertToArray(ja.get(i));
144.177 + }
144.178 + return arr;
144.179 + } else if (o instanceof JSONObject) {
144.180 + JSONObject obj = (JSONObject) o;
144.181 + Iterator it = obj.keys();
144.182 + while (it.hasNext()) {
144.183 + String key = (String) it.next();
144.184 + obj.put(key, convertToArray(obj.get(key)));
144.185 + }
144.186 + return obj;
144.187 + } else {
144.188 + return o;
144.189 + }
144.190 + }
144.191 +
144.192 + } // end of Comm
144.193 +}
145.1 --- a/ko-ws-tyrus/src/test/java/org/apidesign/html/wstyrus/TyrusDynamicHTTP.java Mon Dec 16 15:48:09 2013 +0100
145.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
145.3 @@ -1,260 +0,0 @@
145.4 -/**
145.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
145.6 - *
145.7 - * Copyright 1997-2010 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.apidesign.html.wstyrus;
145.47 -
145.48 -import java.io.ByteArrayInputStream;
145.49 -import java.io.ByteArrayOutputStream;
145.50 -import java.io.IOException;
145.51 -import java.io.InputStream;
145.52 -import java.io.OutputStream;
145.53 -import java.io.Reader;
145.54 -import java.net.URI;
145.55 -import java.net.URISyntaxException;
145.56 -import java.util.ArrayList;
145.57 -import java.util.List;
145.58 -import java.util.logging.Level;
145.59 -import java.util.logging.Logger;
145.60 -import org.glassfish.grizzly.PortRange;
145.61 -import org.glassfish.grizzly.http.server.HttpHandler;
145.62 -import org.glassfish.grizzly.http.server.HttpServer;
145.63 -import org.glassfish.grizzly.http.server.NetworkListener;
145.64 -import org.glassfish.grizzly.http.server.Request;
145.65 -import org.glassfish.grizzly.http.server.Response;
145.66 -import org.glassfish.grizzly.http.server.ServerConfiguration;
145.67 -import org.glassfish.grizzly.websockets.WebSocket;
145.68 -import org.glassfish.grizzly.websockets.WebSocketAddOn;
145.69 -import org.glassfish.grizzly.websockets.WebSocketApplication;
145.70 -import org.glassfish.grizzly.websockets.WebSocketEngine;
145.71 -
145.72 -/**
145.73 - *
145.74 - * @author Jaroslav Tulach <jtulach@netbeans.org>
145.75 - */
145.76 -final class TyrusDynamicHTTP extends HttpHandler {
145.77 - private static int resourcesCount;
145.78 - private static List<Resource> resources;
145.79 - private static ServerConfiguration conf;
145.80 - private static HttpServer server;
145.81 -
145.82 - private TyrusDynamicHTTP() {
145.83 - }
145.84 -
145.85 - static URI initServer() throws Exception {
145.86 - server = HttpServer.createSimpleServer(null, new PortRange(8080, 65535));
145.87 - final WebSocketAddOn addon = new WebSocketAddOn();
145.88 - for (NetworkListener listener : server.getListeners()) {
145.89 - listener.registerAddOn(addon);
145.90 - }
145.91 - resources = new ArrayList<Resource>();
145.92 -
145.93 - conf = server.getServerConfiguration();
145.94 - final TyrusDynamicHTTP dh = new TyrusDynamicHTTP();
145.95 -
145.96 - conf.addHttpHandler(dh, "/");
145.97 -
145.98 - server.start();
145.99 -
145.100 - return pageURL("http", server, "/test.html");
145.101 - }
145.102 -
145.103 - @Override
145.104 - public void service(Request request, Response response) throws Exception {
145.105 - if ("/test.html".equals(request.getRequestURI())) {
145.106 - response.setContentType("text/html");
145.107 - final InputStream is = TyrusDynamicHTTP.class.getResourceAsStream("test.html");
145.108 - copyStream(is, response.getOutputStream(), null);
145.109 - return;
145.110 - }
145.111 - if ("/dynamic".equals(request.getRequestURI())) {
145.112 - String mimeType = request.getParameter("mimeType");
145.113 - List<String> params = new ArrayList<String>();
145.114 - boolean webSocket = false;
145.115 - for (int i = 0;; i++) {
145.116 - String p = request.getParameter("param" + i);
145.117 - if (p == null) {
145.118 - break;
145.119 - }
145.120 - if ("protocol:ws".equals(p)) {
145.121 - webSocket = true;
145.122 - continue;
145.123 - }
145.124 - params.add(p);
145.125 - }
145.126 - final String cnt = request.getParameter("content");
145.127 - String mangle = cnt.replace("%20", " ").replace("%0A", "\n");
145.128 - ByteArrayInputStream is = new ByteArrayInputStream(mangle.getBytes("UTF-8"));
145.129 - URI url;
145.130 - final Resource res = new Resource(is, mimeType, "/dynamic/res" + ++resourcesCount, params.toArray(new String[params.size()]));
145.131 - if (webSocket) {
145.132 - url = registerWebSocket(res);
145.133 - } else {
145.134 - url = registerResource(res);
145.135 - }
145.136 - response.getWriter().write(url.toString());
145.137 - response.getWriter().write("\n");
145.138 - return;
145.139 - }
145.140 -
145.141 - for (Resource r : resources) {
145.142 - if (r.httpPath.equals(request.getRequestURI())) {
145.143 - response.setContentType(r.httpType);
145.144 - r.httpContent.reset();
145.145 - String[] params = null;
145.146 - if (r.parameters.length != 0) {
145.147 - params = new String[r.parameters.length];
145.148 - for (int i = 0; i < r.parameters.length; i++) {
145.149 - params[i] = request.getParameter(r.parameters[i]);
145.150 - if (params[i] == null) {
145.151 - if ("http.method".equals(r.parameters[i])) {
145.152 - params[i] = request.getMethod().toString();
145.153 - } else if ("http.requestBody".equals(r.parameters[i])) {
145.154 - Reader rdr = request.getReader();
145.155 - StringBuilder sb = new StringBuilder();
145.156 - for (;;) {
145.157 - int ch = rdr.read();
145.158 - if (ch == -1) {
145.159 - break;
145.160 - }
145.161 - sb.append((char) ch);
145.162 - }
145.163 - params[i] = sb.toString();
145.164 - }
145.165 - }
145.166 - if (params[i] == null) {
145.167 - params[i] = "null";
145.168 - }
145.169 - }
145.170 - }
145.171 -
145.172 - copyStream(r.httpContent, response.getOutputStream(), null, params);
145.173 - }
145.174 - }
145.175 - }
145.176 -
145.177 - private URI registerWebSocket(Resource r) {
145.178 - WebSocketEngine.getEngine().register("", r.httpPath, new WS(r));
145.179 - return pageURL("ws", server, r.httpPath);
145.180 - }
145.181 -
145.182 - private URI registerResource(Resource r) {
145.183 - if (!resources.contains(r)) {
145.184 - resources.add(r);
145.185 - conf.addHttpHandler(this, r.httpPath);
145.186 - }
145.187 - return pageURL("http", server, r.httpPath);
145.188 - }
145.189 -
145.190 - private static URI pageURL(String proto, HttpServer server, final String page) {
145.191 - NetworkListener listener = server.getListeners().iterator().next();
145.192 - int port = listener.getPort();
145.193 - try {
145.194 - return new URI(proto + "://localhost:" + port + page);
145.195 - } catch (URISyntaxException ex) {
145.196 - throw new IllegalStateException(ex);
145.197 - }
145.198 - }
145.199 -
145.200 - static final class Resource {
145.201 -
145.202 - final InputStream httpContent;
145.203 - final String httpType;
145.204 - final String httpPath;
145.205 - final String[] parameters;
145.206 -
145.207 - Resource(InputStream httpContent, String httpType, String httpPath,
145.208 - String[] parameters) {
145.209 - httpContent.mark(Integer.MAX_VALUE);
145.210 - this.httpContent = httpContent;
145.211 - this.httpType = httpType;
145.212 - this.httpPath = httpPath;
145.213 - this.parameters = parameters;
145.214 - }
145.215 - }
145.216 -
145.217 - static void copyStream(InputStream is, OutputStream os, String baseURL, String... params) throws IOException {
145.218 - for (;;) {
145.219 - int ch = is.read();
145.220 - if (ch == -1) {
145.221 - break;
145.222 - }
145.223 - if (ch == '$' && params.length > 0) {
145.224 - int cnt = is.read() - '0';
145.225 - if (baseURL != null && cnt == 'U' - '0') {
145.226 - os.write(baseURL.getBytes("UTF-8"));
145.227 - } else {
145.228 - if (cnt >= 0 && cnt < params.length) {
145.229 - os.write(params[cnt].getBytes("UTF-8"));
145.230 - } else {
145.231 - os.write('$');
145.232 - os.write(cnt + '0');
145.233 - }
145.234 - }
145.235 - } else {
145.236 - os.write(ch);
145.237 - }
145.238 - }
145.239 - }
145.240 -
145.241 - private static class WS extends WebSocketApplication {
145.242 - private final Resource r;
145.243 -
145.244 - private WS(Resource r) {
145.245 - this.r = r;
145.246 - }
145.247 -
145.248 - @Override
145.249 - public void onMessage(WebSocket socket, String text) {
145.250 - try {
145.251 - r.httpContent.reset();
145.252 - ByteArrayOutputStream out = new ByteArrayOutputStream();
145.253 - copyStream(r.httpContent, out, null, text);
145.254 - String s = new String(out.toByteArray(), "UTF-8");
145.255 - socket.send(s);
145.256 - } catch (IOException ex) {
145.257 - LOG.log(Level.WARNING, null, ex);
145.258 - }
145.259 - }
145.260 - private static final Logger LOG = Logger.getLogger(WS.class.getName());
145.261 -
145.262 - }
145.263 -}
146.1 --- a/ko-ws-tyrus/src/test/java/org/apidesign/html/wstyrus/TyrusFX.java Mon Dec 16 15:48:09 2013 +0100
146.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
146.3 @@ -1,120 +0,0 @@
146.4 -/**
146.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
146.6 - *
146.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
146.8 - *
146.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
146.10 - * Other names may be trademarks of their respective owners.
146.11 - *
146.12 - * The contents of this file are subject to the terms of either the GNU
146.13 - * General Public License Version 2 only ("GPL") or the Common
146.14 - * Development and Distribution License("CDDL") (collectively, the
146.15 - * "License"). You may not use this file except in compliance with the
146.16 - * License. You can obtain a copy of the License at
146.17 - * http://www.netbeans.org/cddl-gplv2.html
146.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
146.19 - * specific language governing permissions and limitations under the
146.20 - * License. When distributing the software, include this License Header
146.21 - * Notice in each file and include the License file at
146.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
146.23 - * particular file as subject to the "Classpath" exception as provided
146.24 - * by Oracle in the GPL Version 2 section of the License file that
146.25 - * accompanied this code. If applicable, add the following below the
146.26 - * License Header, with the fields enclosed by brackets [] replaced by
146.27 - * your own identifying information:
146.28 - * "Portions Copyrighted [year] [name of copyright owner]"
146.29 - *
146.30 - * Contributor(s):
146.31 - *
146.32 - * The Original Software is NetBeans. The Initial Developer of the Original
146.33 - * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
146.34 - *
146.35 - * If you wish your version of this file to be governed by only the CDDL
146.36 - * or only the GPL Version 2, indicate your decision by adding
146.37 - * "[Contributor] elects to include this software in this distribution
146.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
146.39 - * single choice of license, a recipient has the option to distribute
146.40 - * your version of this file under either the CDDL, the GPL Version 2 or
146.41 - * to extend the choice of license to its licensees as provided above.
146.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
146.43 - * Version 2 license, then the option applies only if the new code is
146.44 - * made subject to such option by the copyright holder.
146.45 - */
146.46 -package org.apidesign.html.wstyrus;
146.47 -
146.48 -import java.lang.reflect.InvocationTargetException;
146.49 -import java.lang.reflect.Method;
146.50 -import javafx.application.Platform;
146.51 -import org.apidesign.html.boot.impl.FnContext;
146.52 -import org.apidesign.html.boot.spi.Fn;
146.53 -import org.testng.ITest;
146.54 -import org.testng.annotations.Test;
146.55 -
146.56 -/**
146.57 - *
146.58 - * @author Jaroslav Tulach <jtulach@netbeans.org>
146.59 - */
146.60 -public final class TyrusFX implements ITest, Runnable {
146.61 - private final Fn.Presenter p;
146.62 - private final Method m;
146.63 - private Object result;
146.64 - private Object inst;
146.65 - private int count;
146.66 -
146.67 - TyrusFX(Fn.Presenter p, Method m) {
146.68 - this.p = p;
146.69 - this.m = m;
146.70 - }
146.71 -
146.72 - @Override
146.73 - public String getTestName() {
146.74 - return m.getName();
146.75 - }
146.76 -
146.77 - @Test
146.78 - public synchronized void executeTest() throws Exception {
146.79 - if (result == null) {
146.80 - Platform.runLater(this);
146.81 - wait();
146.82 - }
146.83 - if (result instanceof Exception) {
146.84 - throw (Exception)result;
146.85 - }
146.86 - if (result instanceof Error) {
146.87 - throw (Error)result;
146.88 - }
146.89 - }
146.90 -
146.91 - @Override
146.92 - public synchronized void run() {
146.93 - boolean notify = true;
146.94 - try {
146.95 - FnContext.currentPresenter(p);
146.96 - if (inst == null) {
146.97 - inst = m.getDeclaringClass().newInstance();
146.98 - }
146.99 - result = m.invoke(inst);
146.100 - if (result == null) {
146.101 - result = this;
146.102 - }
146.103 - } catch (InvocationTargetException ex) {
146.104 - Throwable r = ex.getTargetException();
146.105 - if (r instanceof InterruptedException) {
146.106 - if (count++ < 10000) {
146.107 - notify = false;
146.108 - Platform.runLater(this);
146.109 - return;
146.110 - }
146.111 - }
146.112 - result = r;
146.113 - } catch (Exception ex) {
146.114 - result = ex;
146.115 - } finally {
146.116 - if (notify) {
146.117 - notifyAll();
146.118 - }
146.119 - FnContext.currentPresenter(null);
146.120 - }
146.121 - }
146.122 -
146.123 -}
147.1 --- a/ko-ws-tyrus/src/test/java/org/apidesign/html/wstyrus/TyrusKnockoutTest.java Mon Dec 16 15:48:09 2013 +0100
147.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
147.3 @@ -1,213 +0,0 @@
147.4 -/**
147.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
147.6 - *
147.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
147.8 - *
147.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
147.10 - * Other names may be trademarks of their respective owners.
147.11 - *
147.12 - * The contents of this file are subject to the terms of either the GNU
147.13 - * General Public License Version 2 only ("GPL") or the Common
147.14 - * Development and Distribution License("CDDL") (collectively, the
147.15 - * "License"). You may not use this file except in compliance with the
147.16 - * License. You can obtain a copy of the License at
147.17 - * http://www.netbeans.org/cddl-gplv2.html
147.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
147.19 - * specific language governing permissions and limitations under the
147.20 - * License. When distributing the software, include this License Header
147.21 - * Notice in each file and include the License file at
147.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
147.23 - * particular file as subject to the "Classpath" exception as provided
147.24 - * by Oracle in the GPL Version 2 section of the License file that
147.25 - * accompanied this code. If applicable, add the following below the
147.26 - * License Header, with the fields enclosed by brackets [] replaced by
147.27 - * your own identifying information:
147.28 - * "Portions Copyrighted [year] [name of copyright owner]"
147.29 - *
147.30 - * Contributor(s):
147.31 - *
147.32 - * The Original Software is NetBeans. The Initial Developer of the Original
147.33 - * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
147.34 - *
147.35 - * If you wish your version of this file to be governed by only the CDDL
147.36 - * or only the GPL Version 2, indicate your decision by adding
147.37 - * "[Contributor] elects to include this software in this distribution
147.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
147.39 - * single choice of license, a recipient has the option to distribute
147.40 - * your version of this file under either the CDDL, the GPL Version 2 or
147.41 - * to extend the choice of license to its licensees as provided above.
147.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
147.43 - * Version 2 license, then the option applies only if the new code is
147.44 - * made subject to such option by the copyright holder.
147.45 - */
147.46 -package org.apidesign.html.wstyrus;
147.47 -
147.48 -import java.io.BufferedReader;
147.49 -import java.io.IOException;
147.50 -import java.io.InputStreamReader;
147.51 -import java.lang.annotation.Annotation;
147.52 -import java.lang.reflect.Method;
147.53 -import java.net.URI;
147.54 -import java.net.URISyntaxException;
147.55 -import java.net.URL;
147.56 -import java.net.URLConnection;
147.57 -import java.util.ArrayList;
147.58 -import java.util.List;
147.59 -import java.util.Map;
147.60 -import java.util.concurrent.Executors;
147.61 -import net.java.html.BrwsrCtx;
147.62 -import net.java.html.boot.BrowserBuilder;
147.63 -import net.java.html.js.JavaScriptBody;
147.64 -import org.apidesign.html.boot.impl.FnContext;
147.65 -import org.apidesign.html.boot.impl.FnUtils;
147.66 -import org.apidesign.html.boot.spi.Fn;
147.67 -import org.apidesign.html.context.spi.Contexts;
147.68 -import org.apidesign.html.json.spi.Technology;
147.69 -import org.apidesign.html.json.spi.Transfer;
147.70 -import org.apidesign.html.json.spi.WSTransfer;
147.71 -import org.apidesign.html.json.tck.KOTest;
147.72 -import org.apidesign.html.json.tck.KnockoutTCK;
147.73 -import org.apidesign.html.kofx.FXContext;
147.74 -import org.json.JSONException;
147.75 -import org.json.JSONObject;
147.76 -import org.openide.util.lookup.ServiceProvider;
147.77 -import org.testng.annotations.Factory;
147.78 -import static org.testng.Assert.*;
147.79 -
147.80 -/**
147.81 - *
147.82 - * @author Jaroslav Tulach <jtulach@netbeans.org>
147.83 - */
147.84 -@ServiceProvider(service = KnockoutTCK.class)
147.85 -public final class TyrusKnockoutTest extends KnockoutTCK {
147.86 - private static Class<?> browserClass;
147.87 - private static Fn.Presenter browserContext;
147.88 -
147.89 - public TyrusKnockoutTest() {
147.90 - }
147.91 -
147.92 - @Factory public static Object[] compatibilityTests() throws Exception {
147.93 - Class[] arr = testClasses();
147.94 - for (int i = 0; i < arr.length; i++) {
147.95 - assertEquals(
147.96 - arr[i].getClassLoader(),
147.97 - TyrusKnockoutTest.class.getClassLoader(),
147.98 - "All classes loaded by the same classloader"
147.99 - );
147.100 - }
147.101 -
147.102 - URI uri = TyrusDynamicHTTP.initServer();
147.103 -
147.104 - final BrowserBuilder bb = BrowserBuilder.newBrowser().loadClass(TyrusKnockoutTest.class).
147.105 - loadPage(uri.toString()).
147.106 - invoke("initialized");
147.107 -
147.108 - Executors.newSingleThreadExecutor().submit(new Runnable() {
147.109 - @Override
147.110 - public void run() {
147.111 - bb.showAndWait();
147.112 - }
147.113 - });
147.114 -
147.115 - ClassLoader l = getClassLoader();
147.116 - List<Object> res = new ArrayList<Object>();
147.117 - for (int i = 0; i < arr.length; i++) {
147.118 - Class<?> c = Class.forName(arr[i].getName(), true, l);
147.119 - Class<? extends Annotation> koTest =
147.120 - c.getClassLoader().loadClass(KOTest.class.getName()).
147.121 - asSubclass(Annotation.class);
147.122 - for (Method m : c.getMethods()) {
147.123 - if (m.getAnnotation(koTest) != null) {
147.124 - res.add(new TyrusFX(browserContext, m));
147.125 - }
147.126 - }
147.127 - }
147.128 - return res.toArray();
147.129 - }
147.130 -
147.131 - static synchronized ClassLoader getClassLoader() throws InterruptedException {
147.132 - while (browserClass == null) {
147.133 - TyrusKnockoutTest.class.wait();
147.134 - }
147.135 - return browserClass.getClassLoader();
147.136 - }
147.137 -
147.138 - public static synchronized void initialized(Class<?> browserCls) throws Exception {
147.139 - browserClass = browserCls;
147.140 - browserContext = FnContext.currentPresenter();
147.141 - TyrusKnockoutTest.class.notifyAll();
147.142 - }
147.143 -
147.144 - public static void initialized() throws Exception {
147.145 - Class<?> classpathClass = ClassLoader.getSystemClassLoader().loadClass(TyrusKnockoutTest.class.getName());
147.146 - Method m = classpathClass.getMethod("initialized", Class.class);
147.147 - m.invoke(null, TyrusKnockoutTest.class);
147.148 - browserContext = FnContext.currentPresenter();
147.149 - }
147.150 -
147.151 - @Override
147.152 - public BrwsrCtx createContext() {
147.153 - FXContext fx = new FXContext(browserContext);
147.154 - TyrusContext tc = new TyrusContext();
147.155 - Contexts.Builder cb = Contexts.newBuilder().
147.156 - register(Technology.class, fx, 10).
147.157 - register(Transfer.class, fx, 10).
147.158 - register(WSTransfer.class, tc, 10);
147.159 - return cb.build();
147.160 - }
147.161 -
147.162 - @Override
147.163 - public Object createJSON(Map<String, Object> values) {
147.164 - JSONObject json = new JSONObject();
147.165 - for (Map.Entry<String, Object> entry : values.entrySet()) {
147.166 - try {
147.167 - json.put(entry.getKey(), entry.getValue());
147.168 - } catch (JSONException ex) {
147.169 - throw new IllegalStateException(ex);
147.170 - }
147.171 - }
147.172 - return json;
147.173 - }
147.174 -
147.175 - @Override
147.176 - @JavaScriptBody(args = { "s", "args" }, body = ""
147.177 - + "var f = new Function(s); "
147.178 - + "return f.apply(null, args);"
147.179 - )
147.180 - public native Object executeScript(String script, Object[] arguments);
147.181 -
147.182 - @JavaScriptBody(args = { }, body =
147.183 - "var h;"
147.184 - + "if (!!window && !!window.location && !!window.location.href)\n"
147.185 - + " h = window.location.href;\n"
147.186 - + "else "
147.187 - + " h = null;"
147.188 - + "return h;\n"
147.189 - )
147.190 - private static native String findBaseURL();
147.191 -
147.192 - @Override
147.193 - public URI prepareURL(String content, String mimeType, String[] parameters) {
147.194 - try {
147.195 - final URL baseURL = new URL(findBaseURL());
147.196 - StringBuilder sb = new StringBuilder();
147.197 - sb.append("/dynamic?mimeType=").append(mimeType);
147.198 - for (int i = 0; i < parameters.length; i++) {
147.199 - sb.append("¶m" + i).append("=").append(parameters[i]);
147.200 - }
147.201 - String mangle = content.replace("\n", "%0a")
147.202 - .replace("\"", "\\\"").replace(" ", "%20");
147.203 - sb.append("&content=").append(mangle);
147.204 -
147.205 - URL query = new URL(baseURL, sb.toString());
147.206 - URLConnection c = query.openConnection();
147.207 - BufferedReader br = new BufferedReader(new InputStreamReader(c.getInputStream()));
147.208 - URI connectTo = new URI(br.readLine());
147.209 - return connectTo;
147.210 - } catch (IOException ex) {
147.211 - throw new IllegalStateException(ex);
147.212 - } catch (URISyntaxException ex) {
147.213 - throw new IllegalStateException(ex);
147.214 - }
147.215 - }
147.216 -}
148.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
148.2 +++ b/ko-ws-tyrus/src/test/java/org/netbeans/html/wstyrus/TyrusDynamicHTTP.java Mon Dec 16 16:59:43 2013 +0100
148.3 @@ -0,0 +1,260 @@
148.4 +/**
148.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
148.6 + *
148.7 + * Copyright 1997-2010 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 +package org.netbeans.html.wstyrus;
148.47 +
148.48 +import java.io.ByteArrayInputStream;
148.49 +import java.io.ByteArrayOutputStream;
148.50 +import java.io.IOException;
148.51 +import java.io.InputStream;
148.52 +import java.io.OutputStream;
148.53 +import java.io.Reader;
148.54 +import java.net.URI;
148.55 +import java.net.URISyntaxException;
148.56 +import java.util.ArrayList;
148.57 +import java.util.List;
148.58 +import java.util.logging.Level;
148.59 +import java.util.logging.Logger;
148.60 +import org.glassfish.grizzly.PortRange;
148.61 +import org.glassfish.grizzly.http.server.HttpHandler;
148.62 +import org.glassfish.grizzly.http.server.HttpServer;
148.63 +import org.glassfish.grizzly.http.server.NetworkListener;
148.64 +import org.glassfish.grizzly.http.server.Request;
148.65 +import org.glassfish.grizzly.http.server.Response;
148.66 +import org.glassfish.grizzly.http.server.ServerConfiguration;
148.67 +import org.glassfish.grizzly.websockets.WebSocket;
148.68 +import org.glassfish.grizzly.websockets.WebSocketAddOn;
148.69 +import org.glassfish.grizzly.websockets.WebSocketApplication;
148.70 +import org.glassfish.grizzly.websockets.WebSocketEngine;
148.71 +
148.72 +/**
148.73 + *
148.74 + * @author Jaroslav Tulach <jtulach@netbeans.org>
148.75 + */
148.76 +final class TyrusDynamicHTTP extends HttpHandler {
148.77 + private static int resourcesCount;
148.78 + private static List<Resource> resources;
148.79 + private static ServerConfiguration conf;
148.80 + private static HttpServer server;
148.81 +
148.82 + private TyrusDynamicHTTP() {
148.83 + }
148.84 +
148.85 + static URI initServer() throws Exception {
148.86 + server = HttpServer.createSimpleServer(null, new PortRange(8080, 65535));
148.87 + final WebSocketAddOn addon = new WebSocketAddOn();
148.88 + for (NetworkListener listener : server.getListeners()) {
148.89 + listener.registerAddOn(addon);
148.90 + }
148.91 + resources = new ArrayList<Resource>();
148.92 +
148.93 + conf = server.getServerConfiguration();
148.94 + final TyrusDynamicHTTP dh = new TyrusDynamicHTTP();
148.95 +
148.96 + conf.addHttpHandler(dh, "/");
148.97 +
148.98 + server.start();
148.99 +
148.100 + return pageURL("http", server, "/test.html");
148.101 + }
148.102 +
148.103 + @Override
148.104 + public void service(Request request, Response response) throws Exception {
148.105 + if ("/test.html".equals(request.getRequestURI())) {
148.106 + response.setContentType("text/html");
148.107 + final InputStream is = TyrusDynamicHTTP.class.getResourceAsStream("test.html");
148.108 + copyStream(is, response.getOutputStream(), null);
148.109 + return;
148.110 + }
148.111 + if ("/dynamic".equals(request.getRequestURI())) {
148.112 + String mimeType = request.getParameter("mimeType");
148.113 + List<String> params = new ArrayList<String>();
148.114 + boolean webSocket = false;
148.115 + for (int i = 0;; i++) {
148.116 + String p = request.getParameter("param" + i);
148.117 + if (p == null) {
148.118 + break;
148.119 + }
148.120 + if ("protocol:ws".equals(p)) {
148.121 + webSocket = true;
148.122 + continue;
148.123 + }
148.124 + params.add(p);
148.125 + }
148.126 + final String cnt = request.getParameter("content");
148.127 + String mangle = cnt.replace("%20", " ").replace("%0A", "\n");
148.128 + ByteArrayInputStream is = new ByteArrayInputStream(mangle.getBytes("UTF-8"));
148.129 + URI url;
148.130 + final Resource res = new Resource(is, mimeType, "/dynamic/res" + ++resourcesCount, params.toArray(new String[params.size()]));
148.131 + if (webSocket) {
148.132 + url = registerWebSocket(res);
148.133 + } else {
148.134 + url = registerResource(res);
148.135 + }
148.136 + response.getWriter().write(url.toString());
148.137 + response.getWriter().write("\n");
148.138 + return;
148.139 + }
148.140 +
148.141 + for (Resource r : resources) {
148.142 + if (r.httpPath.equals(request.getRequestURI())) {
148.143 + response.setContentType(r.httpType);
148.144 + r.httpContent.reset();
148.145 + String[] params = null;
148.146 + if (r.parameters.length != 0) {
148.147 + params = new String[r.parameters.length];
148.148 + for (int i = 0; i < r.parameters.length; i++) {
148.149 + params[i] = request.getParameter(r.parameters[i]);
148.150 + if (params[i] == null) {
148.151 + if ("http.method".equals(r.parameters[i])) {
148.152 + params[i] = request.getMethod().toString();
148.153 + } else if ("http.requestBody".equals(r.parameters[i])) {
148.154 + Reader rdr = request.getReader();
148.155 + StringBuilder sb = new StringBuilder();
148.156 + for (;;) {
148.157 + int ch = rdr.read();
148.158 + if (ch == -1) {
148.159 + break;
148.160 + }
148.161 + sb.append((char) ch);
148.162 + }
148.163 + params[i] = sb.toString();
148.164 + }
148.165 + }
148.166 + if (params[i] == null) {
148.167 + params[i] = "null";
148.168 + }
148.169 + }
148.170 + }
148.171 +
148.172 + copyStream(r.httpContent, response.getOutputStream(), null, params);
148.173 + }
148.174 + }
148.175 + }
148.176 +
148.177 + private URI registerWebSocket(Resource r) {
148.178 + WebSocketEngine.getEngine().register("", r.httpPath, new WS(r));
148.179 + return pageURL("ws", server, r.httpPath);
148.180 + }
148.181 +
148.182 + private URI registerResource(Resource r) {
148.183 + if (!resources.contains(r)) {
148.184 + resources.add(r);
148.185 + conf.addHttpHandler(this, r.httpPath);
148.186 + }
148.187 + return pageURL("http", server, r.httpPath);
148.188 + }
148.189 +
148.190 + private static URI pageURL(String proto, HttpServer server, final String page) {
148.191 + NetworkListener listener = server.getListeners().iterator().next();
148.192 + int port = listener.getPort();
148.193 + try {
148.194 + return new URI(proto + "://localhost:" + port + page);
148.195 + } catch (URISyntaxException ex) {
148.196 + throw new IllegalStateException(ex);
148.197 + }
148.198 + }
148.199 +
148.200 + static final class Resource {
148.201 +
148.202 + final InputStream httpContent;
148.203 + final String httpType;
148.204 + final String httpPath;
148.205 + final String[] parameters;
148.206 +
148.207 + Resource(InputStream httpContent, String httpType, String httpPath,
148.208 + String[] parameters) {
148.209 + httpContent.mark(Integer.MAX_VALUE);
148.210 + this.httpContent = httpContent;
148.211 + this.httpType = httpType;
148.212 + this.httpPath = httpPath;
148.213 + this.parameters = parameters;
148.214 + }
148.215 + }
148.216 +
148.217 + static void copyStream(InputStream is, OutputStream os, String baseURL, String... params) throws IOException {
148.218 + for (;;) {
148.219 + int ch = is.read();
148.220 + if (ch == -1) {
148.221 + break;
148.222 + }
148.223 + if (ch == '$' && params.length > 0) {
148.224 + int cnt = is.read() - '0';
148.225 + if (baseURL != null && cnt == 'U' - '0') {
148.226 + os.write(baseURL.getBytes("UTF-8"));
148.227 + } else {
148.228 + if (cnt >= 0 && cnt < params.length) {
148.229 + os.write(params[cnt].getBytes("UTF-8"));
148.230 + } else {
148.231 + os.write('$');
148.232 + os.write(cnt + '0');
148.233 + }
148.234 + }
148.235 + } else {
148.236 + os.write(ch);
148.237 + }
148.238 + }
148.239 + }
148.240 +
148.241 + private static class WS extends WebSocketApplication {
148.242 + private final Resource r;
148.243 +
148.244 + private WS(Resource r) {
148.245 + this.r = r;
148.246 + }
148.247 +
148.248 + @Override
148.249 + public void onMessage(WebSocket socket, String text) {
148.250 + try {
148.251 + r.httpContent.reset();
148.252 + ByteArrayOutputStream out = new ByteArrayOutputStream();
148.253 + copyStream(r.httpContent, out, null, text);
148.254 + String s = new String(out.toByteArray(), "UTF-8");
148.255 + socket.send(s);
148.256 + } catch (IOException ex) {
148.257 + LOG.log(Level.WARNING, null, ex);
148.258 + }
148.259 + }
148.260 + private static final Logger LOG = Logger.getLogger(WS.class.getName());
148.261 +
148.262 + }
148.263 +}
149.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
149.2 +++ b/ko-ws-tyrus/src/test/java/org/netbeans/html/wstyrus/TyrusFX.java Mon Dec 16 16:59:43 2013 +0100
149.3 @@ -0,0 +1,120 @@
149.4 +/**
149.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
149.6 + *
149.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
149.8 + *
149.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
149.10 + * Other names may be trademarks of their respective owners.
149.11 + *
149.12 + * The contents of this file are subject to the terms of either the GNU
149.13 + * General Public License Version 2 only ("GPL") or the Common
149.14 + * Development and Distribution License("CDDL") (collectively, the
149.15 + * "License"). You may not use this file except in compliance with the
149.16 + * License. You can obtain a copy of the License at
149.17 + * http://www.netbeans.org/cddl-gplv2.html
149.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
149.19 + * specific language governing permissions and limitations under the
149.20 + * License. When distributing the software, include this License Header
149.21 + * Notice in each file and include the License file at
149.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
149.23 + * particular file as subject to the "Classpath" exception as provided
149.24 + * by Oracle in the GPL Version 2 section of the License file that
149.25 + * accompanied this code. If applicable, add the following below the
149.26 + * License Header, with the fields enclosed by brackets [] replaced by
149.27 + * your own identifying information:
149.28 + * "Portions Copyrighted [year] [name of copyright owner]"
149.29 + *
149.30 + * Contributor(s):
149.31 + *
149.32 + * The Original Software is NetBeans. The Initial Developer of the Original
149.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
149.34 + *
149.35 + * If you wish your version of this file to be governed by only the CDDL
149.36 + * or only the GPL Version 2, indicate your decision by adding
149.37 + * "[Contributor] elects to include this software in this distribution
149.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
149.39 + * single choice of license, a recipient has the option to distribute
149.40 + * your version of this file under either the CDDL, the GPL Version 2 or
149.41 + * to extend the choice of license to its licensees as provided above.
149.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
149.43 + * Version 2 license, then the option applies only if the new code is
149.44 + * made subject to such option by the copyright holder.
149.45 + */
149.46 +package org.netbeans.html.wstyrus;
149.47 +
149.48 +import java.lang.reflect.InvocationTargetException;
149.49 +import java.lang.reflect.Method;
149.50 +import javafx.application.Platform;
149.51 +import org.netbeans.html.boot.impl.FnContext;
149.52 +import org.apidesign.html.boot.spi.Fn;
149.53 +import org.testng.ITest;
149.54 +import org.testng.annotations.Test;
149.55 +
149.56 +/**
149.57 + *
149.58 + * @author Jaroslav Tulach <jtulach@netbeans.org>
149.59 + */
149.60 +public final class TyrusFX implements ITest, Runnable {
149.61 + private final Fn.Presenter p;
149.62 + private final Method m;
149.63 + private Object result;
149.64 + private Object inst;
149.65 + private int count;
149.66 +
149.67 + TyrusFX(Fn.Presenter p, Method m) {
149.68 + this.p = p;
149.69 + this.m = m;
149.70 + }
149.71 +
149.72 + @Override
149.73 + public String getTestName() {
149.74 + return m.getName();
149.75 + }
149.76 +
149.77 + @Test
149.78 + public synchronized void executeTest() throws Exception {
149.79 + if (result == null) {
149.80 + Platform.runLater(this);
149.81 + wait();
149.82 + }
149.83 + if (result instanceof Exception) {
149.84 + throw (Exception)result;
149.85 + }
149.86 + if (result instanceof Error) {
149.87 + throw (Error)result;
149.88 + }
149.89 + }
149.90 +
149.91 + @Override
149.92 + public synchronized void run() {
149.93 + boolean notify = true;
149.94 + try {
149.95 + FnContext.currentPresenter(p);
149.96 + if (inst == null) {
149.97 + inst = m.getDeclaringClass().newInstance();
149.98 + }
149.99 + result = m.invoke(inst);
149.100 + if (result == null) {
149.101 + result = this;
149.102 + }
149.103 + } catch (InvocationTargetException ex) {
149.104 + Throwable r = ex.getTargetException();
149.105 + if (r instanceof InterruptedException) {
149.106 + if (count++ < 10000) {
149.107 + notify = false;
149.108 + Platform.runLater(this);
149.109 + return;
149.110 + }
149.111 + }
149.112 + result = r;
149.113 + } catch (Exception ex) {
149.114 + result = ex;
149.115 + } finally {
149.116 + if (notify) {
149.117 + notifyAll();
149.118 + }
149.119 + FnContext.currentPresenter(null);
149.120 + }
149.121 + }
149.122 +
149.123 +}
150.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
150.2 +++ b/ko-ws-tyrus/src/test/java/org/netbeans/html/wstyrus/TyrusKnockoutTest.java Mon Dec 16 16:59:43 2013 +0100
150.3 @@ -0,0 +1,212 @@
150.4 +/**
150.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
150.6 + *
150.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
150.8 + *
150.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
150.10 + * Other names may be trademarks of their respective owners.
150.11 + *
150.12 + * The contents of this file are subject to the terms of either the GNU
150.13 + * General Public License Version 2 only ("GPL") or the Common
150.14 + * Development and Distribution License("CDDL") (collectively, the
150.15 + * "License"). You may not use this file except in compliance with the
150.16 + * License. You can obtain a copy of the License at
150.17 + * http://www.netbeans.org/cddl-gplv2.html
150.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
150.19 + * specific language governing permissions and limitations under the
150.20 + * License. When distributing the software, include this License Header
150.21 + * Notice in each file and include the License file at
150.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
150.23 + * particular file as subject to the "Classpath" exception as provided
150.24 + * by Oracle in the GPL Version 2 section of the License file that
150.25 + * accompanied this code. If applicable, add the following below the
150.26 + * License Header, with the fields enclosed by brackets [] replaced by
150.27 + * your own identifying information:
150.28 + * "Portions Copyrighted [year] [name of copyright owner]"
150.29 + *
150.30 + * Contributor(s):
150.31 + *
150.32 + * The Original Software is NetBeans. The Initial Developer of the Original
150.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
150.34 + *
150.35 + * If you wish your version of this file to be governed by only the CDDL
150.36 + * or only the GPL Version 2, indicate your decision by adding
150.37 + * "[Contributor] elects to include this software in this distribution
150.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
150.39 + * single choice of license, a recipient has the option to distribute
150.40 + * your version of this file under either the CDDL, the GPL Version 2 or
150.41 + * to extend the choice of license to its licensees as provided above.
150.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
150.43 + * Version 2 license, then the option applies only if the new code is
150.44 + * made subject to such option by the copyright holder.
150.45 + */
150.46 +package org.netbeans.html.wstyrus;
150.47 +
150.48 +import java.io.BufferedReader;
150.49 +import java.io.IOException;
150.50 +import java.io.InputStreamReader;
150.51 +import java.lang.annotation.Annotation;
150.52 +import java.lang.reflect.Method;
150.53 +import java.net.URI;
150.54 +import java.net.URISyntaxException;
150.55 +import java.net.URL;
150.56 +import java.net.URLConnection;
150.57 +import java.util.ArrayList;
150.58 +import java.util.List;
150.59 +import java.util.Map;
150.60 +import java.util.concurrent.Executors;
150.61 +import net.java.html.BrwsrCtx;
150.62 +import net.java.html.boot.BrowserBuilder;
150.63 +import net.java.html.js.JavaScriptBody;
150.64 +import org.netbeans.html.boot.impl.FnContext;
150.65 +import org.apidesign.html.boot.spi.Fn;
150.66 +import org.apidesign.html.context.spi.Contexts;
150.67 +import org.apidesign.html.json.spi.Technology;
150.68 +import org.apidesign.html.json.spi.Transfer;
150.69 +import org.apidesign.html.json.spi.WSTransfer;
150.70 +import org.apidesign.html.json.tck.KOTest;
150.71 +import org.apidesign.html.json.tck.KnockoutTCK;
150.72 +import org.json.JSONException;
150.73 +import org.json.JSONObject;
150.74 +import org.netbeans.html.kofx.FXContext;
150.75 +import org.openide.util.lookup.ServiceProvider;
150.76 +import org.testng.annotations.Factory;
150.77 +import static org.testng.Assert.*;
150.78 +
150.79 +/**
150.80 + *
150.81 + * @author Jaroslav Tulach <jtulach@netbeans.org>
150.82 + */
150.83 +@ServiceProvider(service = KnockoutTCK.class)
150.84 +public final class TyrusKnockoutTest extends KnockoutTCK {
150.85 + private static Class<?> browserClass;
150.86 + private static Fn.Presenter browserContext;
150.87 +
150.88 + public TyrusKnockoutTest() {
150.89 + }
150.90 +
150.91 + @Factory public static Object[] compatibilityTests() throws Exception {
150.92 + Class[] arr = testClasses();
150.93 + for (int i = 0; i < arr.length; i++) {
150.94 + assertEquals(
150.95 + arr[i].getClassLoader(),
150.96 + TyrusKnockoutTest.class.getClassLoader(),
150.97 + "All classes loaded by the same classloader"
150.98 + );
150.99 + }
150.100 +
150.101 + URI uri = TyrusDynamicHTTP.initServer();
150.102 +
150.103 + final BrowserBuilder bb = BrowserBuilder.newBrowser().loadClass(TyrusKnockoutTest.class).
150.104 + loadPage(uri.toString()).
150.105 + invoke("initialized");
150.106 +
150.107 + Executors.newSingleThreadExecutor().submit(new Runnable() {
150.108 + @Override
150.109 + public void run() {
150.110 + bb.showAndWait();
150.111 + }
150.112 + });
150.113 +
150.114 + ClassLoader l = getClassLoader();
150.115 + List<Object> res = new ArrayList<Object>();
150.116 + for (int i = 0; i < arr.length; i++) {
150.117 + Class<?> c = Class.forName(arr[i].getName(), true, l);
150.118 + Class<? extends Annotation> koTest =
150.119 + c.getClassLoader().loadClass(KOTest.class.getName()).
150.120 + asSubclass(Annotation.class);
150.121 + for (Method m : c.getMethods()) {
150.122 + if (m.getAnnotation(koTest) != null) {
150.123 + res.add(new TyrusFX(browserContext, m));
150.124 + }
150.125 + }
150.126 + }
150.127 + return res.toArray();
150.128 + }
150.129 +
150.130 + static synchronized ClassLoader getClassLoader() throws InterruptedException {
150.131 + while (browserClass == null) {
150.132 + TyrusKnockoutTest.class.wait();
150.133 + }
150.134 + return browserClass.getClassLoader();
150.135 + }
150.136 +
150.137 + public static synchronized void initialized(Class<?> browserCls) throws Exception {
150.138 + browserClass = browserCls;
150.139 + browserContext = FnContext.currentPresenter();
150.140 + TyrusKnockoutTest.class.notifyAll();
150.141 + }
150.142 +
150.143 + public static void initialized() throws Exception {
150.144 + Class<?> classpathClass = ClassLoader.getSystemClassLoader().loadClass(TyrusKnockoutTest.class.getName());
150.145 + Method m = classpathClass.getMethod("initialized", Class.class);
150.146 + m.invoke(null, TyrusKnockoutTest.class);
150.147 + browserContext = FnContext.currentPresenter();
150.148 + }
150.149 +
150.150 + @Override
150.151 + public BrwsrCtx createContext() {
150.152 + FXContext fx = new FXContext(browserContext);
150.153 + TyrusContext tc = new TyrusContext();
150.154 + Contexts.Builder cb = Contexts.newBuilder().
150.155 + register(Technology.class, fx, 10).
150.156 + register(Transfer.class, fx, 10).
150.157 + register(WSTransfer.class, tc, 10);
150.158 + return cb.build();
150.159 + }
150.160 +
150.161 + @Override
150.162 + public Object createJSON(Map<String, Object> values) {
150.163 + JSONObject json = new JSONObject();
150.164 + for (Map.Entry<String, Object> entry : values.entrySet()) {
150.165 + try {
150.166 + json.put(entry.getKey(), entry.getValue());
150.167 + } catch (JSONException ex) {
150.168 + throw new IllegalStateException(ex);
150.169 + }
150.170 + }
150.171 + return json;
150.172 + }
150.173 +
150.174 + @Override
150.175 + @JavaScriptBody(args = { "s", "args" }, body = ""
150.176 + + "var f = new Function(s); "
150.177 + + "return f.apply(null, args);"
150.178 + )
150.179 + public native Object executeScript(String script, Object[] arguments);
150.180 +
150.181 + @JavaScriptBody(args = { }, body =
150.182 + "var h;"
150.183 + + "if (!!window && !!window.location && !!window.location.href)\n"
150.184 + + " h = window.location.href;\n"
150.185 + + "else "
150.186 + + " h = null;"
150.187 + + "return h;\n"
150.188 + )
150.189 + private static native String findBaseURL();
150.190 +
150.191 + @Override
150.192 + public URI prepareURL(String content, String mimeType, String[] parameters) {
150.193 + try {
150.194 + final URL baseURL = new URL(findBaseURL());
150.195 + StringBuilder sb = new StringBuilder();
150.196 + sb.append("/dynamic?mimeType=").append(mimeType);
150.197 + for (int i = 0; i < parameters.length; i++) {
150.198 + sb.append("¶m" + i).append("=").append(parameters[i]);
150.199 + }
150.200 + String mangle = content.replace("\n", "%0a")
150.201 + .replace("\"", "\\\"").replace(" ", "%20");
150.202 + sb.append("&content=").append(mangle);
150.203 +
150.204 + URL query = new URL(baseURL, sb.toString());
150.205 + URLConnection c = query.openConnection();
150.206 + BufferedReader br = new BufferedReader(new InputStreamReader(c.getInputStream()));
150.207 + URI connectTo = new URI(br.readLine());
150.208 + return connectTo;
150.209 + } catch (IOException ex) {
150.210 + throw new IllegalStateException(ex);
150.211 + } catch (URISyntaxException ex) {
150.212 + throw new IllegalStateException(ex);
150.213 + }
150.214 + }
150.215 +}
151.1 --- a/ko-ws-tyrus/src/test/resources/org/apidesign/html/wstyrus/test.html Mon Dec 16 15:48:09 2013 +0100
151.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
151.3 @@ -1,56 +0,0 @@
151.4 -<!--
151.5 -
151.6 - DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
151.7 -
151.8 - Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
151.9 -
151.10 - Oracle and Java are registered trademarks of Oracle and/or its affiliates.
151.11 - Other names may be trademarks of their respective owners.
151.12 -
151.13 - The contents of this file are subject to the terms of either the GNU
151.14 - General Public License Version 2 only ("GPL") or the Common
151.15 - Development and Distribution License("CDDL") (collectively, the
151.16 - "License"). You may not use this file except in compliance with the
151.17 - License. You can obtain a copy of the License at
151.18 - http://www.netbeans.org/cddl-gplv2.html
151.19 - or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
151.20 - specific language governing permissions and limitations under the
151.21 - License. When distributing the software, include this License Header
151.22 - Notice in each file and include the License file at
151.23 - nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
151.24 - particular file as subject to the "Classpath" exception as provided
151.25 - by Oracle in the GPL Version 2 section of the License file that
151.26 - accompanied this code. If applicable, add the following below the
151.27 - License Header, with the fields enclosed by brackets [] replaced by
151.28 - your own identifying information:
151.29 - "Portions Copyrighted [year] [name of copyright owner]"
151.30 -
151.31 - Contributor(s):
151.32 -
151.33 - The Original Software is NetBeans. The Initial Developer of the Original
151.34 - Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
151.35 -
151.36 - If you wish your version of this file to be governed by only the CDDL
151.37 - or only the GPL Version 2, indicate your decision by adding
151.38 - "[Contributor] elects to include this software in this distribution
151.39 - under the [CDDL or GPL Version 2] license." If you do not indicate a
151.40 - single choice of license, a recipient has the option to distribute
151.41 - your version of this file under either the CDDL, the GPL Version 2 or
151.42 - to extend the choice of license to its licensees as provided above.
151.43 - However, if you add GPL Version 2 code and therefore, elected the GPL
151.44 - Version 2 license, then the option applies only if the new code is
151.45 - made subject to such option by the copyright holder.
151.46 -
151.47 --->
151.48 -<!DOCTYPE html>
151.49 -<html>
151.50 - <head>
151.51 - <title>Tyrus WebSockets Execution Harness</title>
151.52 - <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
151.53 - <meta name="viewport" content="width=device-width">
151.54 - </head>
151.55 - <body>
151.56 - <h1>Tyrus WebSockets Execution Harness</h1>
151.57 - </body>
151.58 - <script></script>
151.59 -</html>
152.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
152.2 +++ b/ko-ws-tyrus/src/test/resources/org/netbeans/html/wstyrus/test.html Mon Dec 16 16:59:43 2013 +0100
152.3 @@ -0,0 +1,56 @@
152.4 +<!--
152.5 +
152.6 + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
152.7 +
152.8 + Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
152.9 +
152.10 + Oracle and Java are registered trademarks of Oracle and/or its affiliates.
152.11 + Other names may be trademarks of their respective owners.
152.12 +
152.13 + The contents of this file are subject to the terms of either the GNU
152.14 + General Public License Version 2 only ("GPL") or the Common
152.15 + Development and Distribution License("CDDL") (collectively, the
152.16 + "License"). You may not use this file except in compliance with the
152.17 + License. You can obtain a copy of the License at
152.18 + http://www.netbeans.org/cddl-gplv2.html
152.19 + or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
152.20 + specific language governing permissions and limitations under the
152.21 + License. When distributing the software, include this License Header
152.22 + Notice in each file and include the License file at
152.23 + nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
152.24 + particular file as subject to the "Classpath" exception as provided
152.25 + by Oracle in the GPL Version 2 section of the License file that
152.26 + accompanied this code. If applicable, add the following below the
152.27 + License Header, with the fields enclosed by brackets [] replaced by
152.28 + your own identifying information:
152.29 + "Portions Copyrighted [year] [name of copyright owner]"
152.30 +
152.31 + Contributor(s):
152.32 +
152.33 + The Original Software is NetBeans. The Initial Developer of the Original
152.34 + Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
152.35 +
152.36 + If you wish your version of this file to be governed by only the CDDL
152.37 + or only the GPL Version 2, indicate your decision by adding
152.38 + "[Contributor] elects to include this software in this distribution
152.39 + under the [CDDL or GPL Version 2] license." If you do not indicate a
152.40 + single choice of license, a recipient has the option to distribute
152.41 + your version of this file under either the CDDL, the GPL Version 2 or
152.42 + to extend the choice of license to its licensees as provided above.
152.43 + However, if you add GPL Version 2 code and therefore, elected the GPL
152.44 + Version 2 license, then the option applies only if the new code is
152.45 + made subject to such option by the copyright holder.
152.46 +
152.47 +-->
152.48 +<!DOCTYPE html>
152.49 +<html>
152.50 + <head>
152.51 + <title>Tyrus WebSockets Execution Harness</title>
152.52 + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
152.53 + <meta name="viewport" content="width=device-width">
152.54 + </head>
152.55 + <body>
152.56 + <h1>Tyrus WebSockets Execution Harness</h1>
152.57 + </body>
152.58 + <script></script>
152.59 +</html>
153.1 --- a/pom.xml Mon Dec 16 15:48:09 2013 +0100
153.2 +++ b/pom.xml Mon Dec 16 16:59:43 2013 +0100
153.3 @@ -92,7 +92,7 @@
153.4 <exclude>*</exclude>
153.5 <exclude>.*/**</exclude>
153.6 <exclude>ko-archetype/src/main/resources/**</exclude>
153.7 - <exclude>ko-fx/src/main/resources/org/apidesign/html/kofx/knockout*.js</exclude>
153.8 + <exclude>ko-fx/src/main/resources/org/netbeans/html/kofx/knockout*.js</exclude>
153.9 </excludes>
153.10 </configuration>
153.11 </plugin>
154.1 --- a/sound/src/main/java/org/apidesign/html/sound/impl/BrowserAudioEnv.java Mon Dec 16 15:48:09 2013 +0100
154.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
154.3 @@ -1,81 +0,0 @@
154.4 -/**
154.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
154.6 - *
154.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
154.8 - *
154.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
154.10 - * Other names may be trademarks of their respective owners.
154.11 - *
154.12 - * The contents of this file are subject to the terms of either the GNU
154.13 - * General Public License Version 2 only ("GPL") or the Common
154.14 - * Development and Distribution License("CDDL") (collectively, the
154.15 - * "License"). You may not use this file except in compliance with the
154.16 - * License. You can obtain a copy of the License at
154.17 - * http://www.netbeans.org/cddl-gplv2.html
154.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
154.19 - * specific language governing permissions and limitations under the
154.20 - * License. When distributing the software, include this License Header
154.21 - * Notice in each file and include the License file at
154.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
154.23 - * particular file as subject to the "Classpath" exception as provided
154.24 - * by Oracle in the GPL Version 2 section of the License file that
154.25 - * accompanied this code. If applicable, add the following below the
154.26 - * License Header, with the fields enclosed by brackets [] replaced by
154.27 - * your own identifying information:
154.28 - * "Portions Copyrighted [year] [name of copyright owner]"
154.29 - *
154.30 - * Contributor(s):
154.31 - *
154.32 - * The Original Software is NetBeans. The Initial Developer of the Original
154.33 - * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
154.34 - *
154.35 - * If you wish your version of this file to be governed by only the CDDL
154.36 - * or only the GPL Version 2, indicate your decision by adding
154.37 - * "[Contributor] elects to include this software in this distribution
154.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
154.39 - * single choice of license, a recipient has the option to distribute
154.40 - * your version of this file under either the CDDL, the GPL Version 2 or
154.41 - * to extend the choice of license to its licensees as provided above.
154.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
154.43 - * Version 2 license, then the option applies only if the new code is
154.44 - * made subject to such option by the copyright holder.
154.45 - */
154.46 -package org.apidesign.html.sound.impl;
154.47 -
154.48 -import net.java.html.js.JavaScriptBody;
154.49 -import org.apidesign.html.sound.spi.AudioEnvironment;
154.50 -import org.openide.util.lookup.ServiceProvider;
154.51 -
154.52 -/** Registers an audio provider that delegates to HTML5 Audio tag.
154.53 - *
154.54 - * @author Jaroslav Tulach <jtulach@netbeans.org>
154.55 - */
154.56 -@ServiceProvider(service = AudioEnvironment.class, position = 100)
154.57 -public final class BrowserAudioEnv implements AudioEnvironment<Object> {
154.58 - @Override
154.59 - @JavaScriptBody(args = { "src" }, body = ""
154.60 - + "if (!Audio) return null;"
154.61 - + "return new Audio(src);")
154.62 - public Object create(String src) {
154.63 - // null if not running in browser
154.64 - return null;
154.65 - }
154.66 -
154.67 - @Override @JavaScriptBody(args = { "a" }, body = "a.play();")
154.68 - public void play(Object a) {
154.69 - }
154.70 -
154.71 - @Override @JavaScriptBody(args = { "a" }, body = "a.pause();")
154.72 - public void pause(Object a) {
154.73 - }
154.74 -
154.75 - @Override @JavaScriptBody(args = { "a", "volume" }, body = "a.setVolume(volume);")
154.76 - public void setVolume(Object a, double volume) {
154.77 - }
154.78 -
154.79 - @Override
154.80 - @JavaScriptBody(args = "a", body = "return true;")
154.81 - public boolean isSupported(Object a) {
154.82 - return false;
154.83 - }
154.84 -}
155.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
155.2 +++ b/sound/src/main/java/org/netbeans/html/sound/impl/BrowserAudioEnv.java Mon Dec 16 16:59:43 2013 +0100
155.3 @@ -0,0 +1,81 @@
155.4 +/**
155.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
155.6 + *
155.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
155.8 + *
155.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
155.10 + * Other names may be trademarks of their respective owners.
155.11 + *
155.12 + * The contents of this file are subject to the terms of either the GNU
155.13 + * General Public License Version 2 only ("GPL") or the Common
155.14 + * Development and Distribution License("CDDL") (collectively, the
155.15 + * "License"). You may not use this file except in compliance with the
155.16 + * License. You can obtain a copy of the License at
155.17 + * http://www.netbeans.org/cddl-gplv2.html
155.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
155.19 + * specific language governing permissions and limitations under the
155.20 + * License. When distributing the software, include this License Header
155.21 + * Notice in each file and include the License file at
155.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
155.23 + * particular file as subject to the "Classpath" exception as provided
155.24 + * by Oracle in the GPL Version 2 section of the License file that
155.25 + * accompanied this code. If applicable, add the following below the
155.26 + * License Header, with the fields enclosed by brackets [] replaced by
155.27 + * your own identifying information:
155.28 + * "Portions Copyrighted [year] [name of copyright owner]"
155.29 + *
155.30 + * Contributor(s):
155.31 + *
155.32 + * The Original Software is NetBeans. The Initial Developer of the Original
155.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
155.34 + *
155.35 + * If you wish your version of this file to be governed by only the CDDL
155.36 + * or only the GPL Version 2, indicate your decision by adding
155.37 + * "[Contributor] elects to include this software in this distribution
155.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
155.39 + * single choice of license, a recipient has the option to distribute
155.40 + * your version of this file under either the CDDL, the GPL Version 2 or
155.41 + * to extend the choice of license to its licensees as provided above.
155.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
155.43 + * Version 2 license, then the option applies only if the new code is
155.44 + * made subject to such option by the copyright holder.
155.45 + */
155.46 +package org.netbeans.html.sound.impl;
155.47 +
155.48 +import net.java.html.js.JavaScriptBody;
155.49 +import org.apidesign.html.sound.spi.AudioEnvironment;
155.50 +import org.openide.util.lookup.ServiceProvider;
155.51 +
155.52 +/** Registers an audio provider that delegates to HTML5 Audio tag.
155.53 + *
155.54 + * @author Jaroslav Tulach <jtulach@netbeans.org>
155.55 + */
155.56 +@ServiceProvider(service = AudioEnvironment.class, position = 100)
155.57 +public final class BrowserAudioEnv implements AudioEnvironment<Object> {
155.58 + @Override
155.59 + @JavaScriptBody(args = { "src" }, body = ""
155.60 + + "if (!Audio) return null;"
155.61 + + "return new Audio(src);")
155.62 + public Object create(String src) {
155.63 + // null if not running in browser
155.64 + return null;
155.65 + }
155.66 +
155.67 + @Override @JavaScriptBody(args = { "a" }, body = "a.play();")
155.68 + public void play(Object a) {
155.69 + }
155.70 +
155.71 + @Override @JavaScriptBody(args = { "a" }, body = "a.pause();")
155.72 + public void pause(Object a) {
155.73 + }
155.74 +
155.75 + @Override @JavaScriptBody(args = { "a", "volume" }, body = "a.setVolume(volume);")
155.76 + public void setVolume(Object a, double volume) {
155.77 + }
155.78 +
155.79 + @Override
155.80 + @JavaScriptBody(args = "a", body = "return true;")
155.81 + public boolean isSupported(Object a) {
155.82 + return false;
155.83 + }
155.84 +}