1.1 --- a/boot/pom.xml Mon Dec 16 18:08:40 2013 +0100
1.2 +++ b/boot/pom.xml Mon Jan 06 09:44:07 2014 +0100
1.3 @@ -24,6 +24,7 @@
1.4 <configuration>
1.5 <instructions>
1.6 <Agent-Class>org.netbeans.html.boot.impl.JsAgent</Agent-Class>
1.7 + <Eclipse-BuddyPolicy>dependent</Eclipse-BuddyPolicy>
1.8 </instructions>
1.9 </configuration>
1.10 </plugin>
2.1 --- a/boot/src/main/java/org/netbeans/html/boot/impl/FnUtils.java Mon Dec 16 18:08:40 2013 +0100
2.2 +++ b/boot/src/main/java/org/netbeans/html/boot/impl/FnUtils.java Mon Jan 06 09:44:07 2014 +0100
2.3 @@ -80,7 +80,11 @@
2.4 }
2.5 Class<?> clazz;
2.6 try (Closeable c = Fn.activate(new FnUtils())) {
2.7 - clazz = Class.forName(Test.class.getName(), true, l);
2.8 + try {
2.9 + clazz = Class.forName(Test.class.getName(), true, l);
2.10 + } catch (ClassNotFoundException ex) {
2.11 + clazz = Test.class;
2.12 + }
2.13 final Object is = ((Callable<?>)clazz.newInstance()).call();
2.14 return Boolean.TRUE.equals(is);
2.15 } catch (Exception ex) {
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/equinox-agentclass-hook/pom.xml Mon Jan 06 09:44:07 2014 +0100
3.3 @@ -0,0 +1,42 @@
3.4 +<?xml version="1.0" encoding="UTF-8"?>
3.5 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
3.6 + <modelVersion>4.0.0</modelVersion>
3.7 + <parent>
3.8 + <groupId>org.netbeans.html</groupId>
3.9 + <artifactId>pom</artifactId>
3.10 + <version>0.7-SNAPSHOT</version>
3.11 + </parent>
3.12 + <name>AgentClass Hook for Equinox</name>
3.13 + <artifactId>equinox-agentclass-hook</artifactId>
3.14 + <packaging>bundle</packaging>
3.15 + <build>
3.16 + <plugins>
3.17 + <plugin>
3.18 + <groupId>org.apache.felix</groupId>
3.19 + <artifactId>maven-bundle-plugin</artifactId>
3.20 + <configuration>
3.21 + <instructions>
3.22 + <Fragment-Host>org.eclipse.osgi;bundle-version="[3.8.0,4.0)"</Fragment-Host>
3.23 + <Import-Package></Import-Package>
3.24 + </instructions>
3.25 + </configuration>
3.26 + </plugin>
3.27 + <plugin>
3.28 + <groupId>org.apache.maven.plugins</groupId>
3.29 + <artifactId>maven-compiler-plugin</artifactId>
3.30 + <version>2.3.2</version>
3.31 + <configuration>
3.32 + <source>1.5</source>
3.33 + <target>1.5</target>
3.34 + </configuration>
3.35 + </plugin>
3.36 + </plugins>
3.37 + </build>
3.38 + <dependencies>
3.39 + <dependency>
3.40 + <groupId>org.eclipse</groupId>
3.41 + <artifactId>org.eclipse.osgi</artifactId>
3.42 + <version>3.8.0.v20120529-1548</version>
3.43 + </dependency>
3.44 + </dependencies>
3.45 +</project>
3.46 \ No newline at end of file
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/equinox-agentclass-hook/src/main/java/org/netbeans/html/equinox/agentclass/AgentHook.java Mon Jan 06 09:44:07 2014 +0100
4.3 @@ -0,0 +1,164 @@
4.4 +/**
4.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4.6 + *
4.7 + * Copyright 2013-2013 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.netbeans.html.equinox.agentclass;
4.47 +
4.48 +import java.lang.instrument.IllegalClassFormatException;
4.49 +import java.security.ProtectionDomain;
4.50 +import java.util.ArrayList;
4.51 +import java.util.logging.Logger;
4.52 +
4.53 +import org.eclipse.osgi.baseadaptor.BaseData;
4.54 +import org.eclipse.osgi.baseadaptor.HookConfigurator;
4.55 +import org.eclipse.osgi.baseadaptor.HookRegistry;
4.56 +import org.eclipse.osgi.baseadaptor.bundlefile.BundleEntry;
4.57 +import org.eclipse.osgi.baseadaptor.hooks.ClassLoadingHook;
4.58 +import org.eclipse.osgi.baseadaptor.loader.BaseClassLoader;
4.59 +import org.eclipse.osgi.baseadaptor.loader.ClasspathEntry;
4.60 +import org.eclipse.osgi.baseadaptor.loader.ClasspathManager;
4.61 +import org.eclipse.osgi.framework.adaptor.BundleProtectionDomain;
4.62 +import org.eclipse.osgi.framework.adaptor.BundleWatcher;
4.63 +import org.eclipse.osgi.framework.adaptor.ClassLoaderDelegate;
4.64 +import org.osgi.framework.Bundle;
4.65 +import org.osgi.framework.BundleContext;
4.66 +import org.osgi.framework.wiring.BundleWiring;
4.67 +
4.68 +public class AgentHook implements HookConfigurator, BundleWatcher, ClassLoadingHook {
4.69 + private static final Logger LOG = Logger.getLogger(AgentHook.class.getName());
4.70 + private boolean all;
4.71 +
4.72 + @Override
4.73 + public void addHooks(HookRegistry hookRegistry) {
4.74 + LOG.info("Agent hook for Equinox initialized!");
4.75 + hookRegistry.addWatcher(this);
4.76 + hookRegistry.addClassLoadingHook(this);
4.77 + }
4.78 +
4.79 + @Override
4.80 + public void watchBundle(Bundle bundle, int type) {
4.81 + if (!all) {
4.82 + BundleContext c = bundle.getBundleContext();
4.83 + if (c != null) {
4.84 + Bundle[] arr = bundle.getBundleContext().getBundles();
4.85 + for (Bundle b : arr) {
4.86 + agentBundle(b);
4.87 + }
4.88 + all = true;
4.89 + }
4.90 + }
4.91 + if (type == BundleWatcher.END_ACTIVATION) {
4.92 + agentBundle(bundle);
4.93 + }
4.94 + }
4.95 +
4.96 + private void agentBundle(Bundle bundle) {
4.97 + String agentClass = (String)bundle.getHeaders().get("Agent-Class");
4.98 + if (agentClass != null) {
4.99 + Class<?> agent;
4.100 + try {
4.101 + agent = bundle.loadClass(agentClass);
4.102 + NbInstrumentation.registerAgent(agent.getClassLoader(), agent.getName());
4.103 + } catch (ClassNotFoundException e) {
4.104 + throw new IllegalStateException(e);
4.105 + }
4.106 + }
4.107 + }
4.108 +
4.109 + @Override
4.110 + public byte[] processClass(String name, byte[] bytes,
4.111 + ClasspathEntry ce, BundleEntry entry,
4.112 + ClasspathManager manager) {
4.113 + final BaseData bd = ce.getBaseData();
4.114 + if (bd == null) {
4.115 + return bytes;
4.116 + }
4.117 + final Bundle b = bd.getBundle();
4.118 + if (b == null) {
4.119 + return bytes;
4.120 + }
4.121 + BundleWiring w = (BundleWiring)b.adapt(BundleWiring.class);
4.122 + if (w == null) {
4.123 + return bytes;
4.124 + }
4.125 + ClassLoader loader = w.getClassLoader();
4.126 + try {
4.127 + return NbInstrumentation.patchByteCode(loader, name, ce.getDomain(), bytes);
4.128 + } catch (IllegalClassFormatException e) {
4.129 + return bytes;
4.130 + }
4.131 + }
4.132 +
4.133 + @Override
4.134 + public boolean addClassPathEntry(ArrayList cpEntries,
4.135 + String cp, ClasspathManager hostmanager, BaseData sourcedata,
4.136 + ProtectionDomain sourcedomain) {
4.137 + // TODO Auto-generated method stub
4.138 + return false;
4.139 + }
4.140 +
4.141 + @Override
4.142 + public String findLibrary(BaseData data, String libName) {
4.143 + // TODO Auto-generated method stub
4.144 + return null;
4.145 + }
4.146 +
4.147 + @Override
4.148 + public ClassLoader getBundleClassLoaderParent() {
4.149 + // TODO Auto-generated method stub
4.150 + return null;
4.151 + }
4.152 +
4.153 + @Override
4.154 + public BaseClassLoader createClassLoader(ClassLoader parent,
4.155 + ClassLoaderDelegate delegate, BundleProtectionDomain domain,
4.156 + BaseData data, String[] bundleclasspath) {
4.157 + // TODO Auto-generated method stub
4.158 + return null;
4.159 + }
4.160 +
4.161 + @Override
4.162 + public void initializedClassLoader(BaseClassLoader baseClassLoader,
4.163 + BaseData data) {
4.164 + // TODO Auto-generated method stub
4.165 +
4.166 + }
4.167 +}
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/equinox-agentclass-hook/src/main/java/org/netbeans/html/equinox/agentclass/NbInstrumentation.java Mon Jan 06 09:44:07 2014 +0100
5.3 @@ -0,0 +1,214 @@
5.4 +/**
5.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
5.6 + *
5.7 + * Copyright 2013-2013 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 +
5.47 +package org.netbeans.html.equinox.agentclass;
5.48 +
5.49 +import java.lang.instrument.ClassDefinition;
5.50 +import java.lang.instrument.ClassFileTransformer;
5.51 +import java.lang.instrument.IllegalClassFormatException;
5.52 +import java.lang.instrument.Instrumentation;
5.53 +import java.lang.instrument.UnmodifiableClassException;
5.54 +import java.lang.reflect.InvocationTargetException;
5.55 +import java.lang.reflect.Method;
5.56 +import java.security.ProtectionDomain;
5.57 +import java.util.Collection;
5.58 +import java.util.HashSet;
5.59 +import java.util.List;
5.60 +import java.util.Set;
5.61 +import java.util.concurrent.CopyOnWriteArrayList;
5.62 +import java.util.jar.JarFile;
5.63 +import java.util.logging.Level;
5.64 +import java.util.logging.Logger;
5.65 +
5.66 +/**
5.67 + *
5.68 + * @author Jaroslav Tulach <jtulach@netbeans.org>
5.69 + */
5.70 +final class NbInstrumentation implements Instrumentation {
5.71 + private static final Logger LOG = Logger.getLogger(NbInstrumentation.class.getName());
5.72 + private static final Object LOCK = new Object();
5.73 + private static volatile Collection<NbInstrumentation> ACTIVE;
5.74 +
5.75 + private final List<ClassFileTransformer> transformers = new CopyOnWriteArrayList<ClassFileTransformer>();
5.76 + private static final ThreadLocal<Boolean> IN = new ThreadLocal<Boolean>();
5.77 +
5.78 + static NbInstrumentation registerAgent(ClassLoader l, String agentClassName) {
5.79 + try {
5.80 + return registerImpl(agentClassName, l);
5.81 + } catch (Throwable ex) {
5.82 + LOG.log(Level.WARNING, "Cannot register " + agentClassName, ex);
5.83 + return null;
5.84 + }
5.85 + }
5.86 + static void unregisterAgent(NbInstrumentation instr) {
5.87 + synchronized (LOCK) {
5.88 + if (ACTIVE != null) {
5.89 + Collection<NbInstrumentation> clone = new HashSet<NbInstrumentation>();
5.90 + clone.addAll(ACTIVE);
5.91 + clone.remove(instr);
5.92 + ACTIVE = clone;
5.93 + }
5.94 + }
5.95 + }
5.96 + private static NbInstrumentation registerImpl(String agentClassName, ClassLoader l) throws ClassNotFoundException, IllegalArgumentException, NoSuchMethodException, SecurityException, IllegalAccessException, InvocationTargetException {
5.97 + final NbInstrumentation inst = new NbInstrumentation();
5.98 + synchronized (LOCK) {
5.99 + if (ACTIVE == null) {
5.100 + ACTIVE = new HashSet<NbInstrumentation>();
5.101 + } else {
5.102 + Set<NbInstrumentation> s = new HashSet<NbInstrumentation>();
5.103 + s.addAll(ACTIVE);
5.104 + ACTIVE = s;
5.105 + }
5.106 + ACTIVE.add(inst);
5.107 + }
5.108 + Class<?> agentClass = Class.forName(agentClassName, true, l);
5.109 + try {
5.110 + Method m = agentClass.getMethod("agentmain", String.class, Instrumentation.class); // NOI18N
5.111 + m.invoke(null, "", inst);
5.112 + } catch (NoSuchMethodException ex) {
5.113 + Method m = agentClass.getMethod("agentmain", String.class); // NOI18N
5.114 + m.invoke(null, "");
5.115 + }
5.116 + return inst;
5.117 + }
5.118 +
5.119 + public static byte[] patchByteCode(ClassLoader l, String className, ProtectionDomain pd, byte[] arr) throws IllegalClassFormatException {
5.120 + if (ACTIVE == null) {
5.121 + return arr;
5.122 + }
5.123 + if (Boolean.TRUE.equals(IN.get())) {
5.124 + return arr;
5.125 + }
5.126 + try {
5.127 + IN.set(Boolean.TRUE);
5.128 + for (NbInstrumentation inst : ACTIVE) {
5.129 + for (ClassFileTransformer t : inst.transformers) {
5.130 + arr = t.transform(l, className, null, pd, arr);
5.131 + }
5.132 + }
5.133 + } finally {
5.134 + IN.set(null);
5.135 + }
5.136 + return arr;
5.137 + }
5.138 +
5.139 + //
5.140 + // Instrumentation methods
5.141 + //
5.142 +
5.143 + @Override
5.144 + public void addTransformer(ClassFileTransformer transformer, boolean canRetransform) {
5.145 + transformers.add(transformer);
5.146 + }
5.147 +
5.148 + @Override
5.149 + public void addTransformer(ClassFileTransformer transformer) {
5.150 + transformers.add(transformer);
5.151 + }
5.152 +
5.153 + @Override
5.154 + public boolean removeTransformer(ClassFileTransformer transformer) {
5.155 + return transformers.remove(transformer);
5.156 + }
5.157 +
5.158 + @Override
5.159 + public boolean isRetransformClassesSupported() {
5.160 + return false;
5.161 + }
5.162 +
5.163 + @Override
5.164 + public void retransformClasses(Class<?>... classes) throws UnmodifiableClassException {
5.165 + throw new UnmodifiableClassException();
5.166 + }
5.167 +
5.168 + @Override
5.169 + public boolean isRedefineClassesSupported() {
5.170 + return false;
5.171 + }
5.172 +
5.173 + @Override
5.174 + public void redefineClasses(ClassDefinition... definitions) throws ClassNotFoundException, UnmodifiableClassException {
5.175 + throw new UnmodifiableClassException();
5.176 + }
5.177 +
5.178 + @Override
5.179 + public boolean isModifiableClass(Class<?> theClass) {
5.180 + return false;
5.181 + }
5.182 +
5.183 + @Override
5.184 + public Class[] getAllLoadedClasses() {
5.185 + return new Class[0];
5.186 + }
5.187 +
5.188 + @Override
5.189 + public Class[] getInitiatedClasses(ClassLoader loader) {
5.190 + return new Class[0];
5.191 + }
5.192 +
5.193 + @Override
5.194 + public long getObjectSize(Object objectToSize) {
5.195 + return 42;
5.196 + }
5.197 +
5.198 + @Override
5.199 + public void appendToBootstrapClassLoaderSearch(JarFile jarfile) {
5.200 + }
5.201 +
5.202 + @Override
5.203 + public void appendToSystemClassLoaderSearch(JarFile jarfile) {
5.204 + throw new UnsupportedOperationException();
5.205 + }
5.206 +
5.207 + @Override
5.208 + public boolean isNativeMethodPrefixSupported() {
5.209 + return false;
5.210 + }
5.211 +
5.212 + @Override
5.213 + public void setNativeMethodPrefix(ClassFileTransformer transformer, String prefix) {
5.214 + throw new UnsupportedOperationException();
5.215 + }
5.216 +
5.217 +}
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/equinox-agentclass-hook/src/main/resources/hookconfigurators.properties Mon Jan 06 09:44:07 2014 +0100
6.3 @@ -0,0 +1,44 @@
6.4 +#
6.5 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
6.6 +#
6.7 +# Copyright 2013-2013 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 +
6.47 +hook.configurators=org.netbeans.equinox.agentclass.AgentHook
7.1 --- a/json-tck/src/main/java/net/java/html/json/tests/ConvertTypesTest.java Mon Dec 16 18:08:40 2013 +0100
7.2 +++ b/json-tck/src/main/java/net/java/html/json/tests/ConvertTypesTest.java Mon Jan 06 09:44:07 2014 +0100
7.3 @@ -49,7 +49,6 @@
7.4 import java.util.Map;
7.5 import net.java.html.BrwsrCtx;
7.6 import net.java.html.json.Models;
7.7 -import org.netbeans.html.json.impl.JSON;
7.8 import org.apidesign.html.json.tck.KOTest;
7.9
7.10 /**
7.11 @@ -86,7 +85,7 @@
7.12 public void testConvertToPeople() throws Exception {
7.13 final Object o = createJSON(true);
7.14
7.15 - Person p = JSON.read(newContext(), Person.class, o);
7.16 + Person p = Models.fromRaw(newContext(), Person.class, o);
7.17
7.18 assert "son".equals(p.getFirstName()) : "First name: " + p.getFirstName();
7.19 assert "dj".equals(p.getLastName()) : "Last name: " + p.getLastName();
7.20 @@ -123,7 +122,7 @@
7.21 public void testConvertToPeopleWithoutSex() throws Exception {
7.22 final Object o = createJSON(false);
7.23
7.24 - Person p = JSON.read(newContext(), Person.class, o);
7.25 + Person p = Models.fromRaw(newContext(), Person.class, o);
7.26
7.27 assert "son".equals(p.getFirstName()) : "First name: " + p.getFirstName();
7.28 assert "dj".equals(p.getLastName()) : "Last name: " + p.getLastName();
8.1 --- a/json-tck/src/main/java/net/java/html/json/tests/JSONTest.java Mon Dec 16 18:08:40 2013 +0100
8.2 +++ b/json-tck/src/main/java/net/java/html/json/tests/JSONTest.java Mon Jan 06 09:44:07 2014 +0100
8.3 @@ -49,7 +49,6 @@
8.4 import net.java.html.json.Models;
8.5 import net.java.html.json.OnReceive;
8.6 import net.java.html.json.Property;
8.7 -import org.netbeans.html.json.impl.JSON;
8.8 import org.apidesign.html.json.tck.KOTest;
8.9
8.10 /** Need to verify that models produce reasonable JSON objects.
8.11 @@ -84,7 +83,7 @@
8.12 throw new IllegalStateException("Can't parse " + p).initCause(ex);
8.13 }
8.14
8.15 - Person p2 = JSON.read(newContext(), Person.class, json);
8.16 + Person p2 = Models.fromRaw(newContext(), Person.class, json);
8.17
8.18 assert p2.getFirstName().equals(p.getFirstName()) :
8.19 "Should be the same: " + p.getFirstName() + " != " + p2.getFirstName();
8.20 @@ -104,7 +103,7 @@
8.21 throw new IllegalStateException("Can't parse " + txt).initCause(ex);
8.22 }
8.23
8.24 - Person p2 = JSON.read(newContext(), Person.class, json);
8.25 + Person p2 = Models.fromRaw(newContext(), Person.class, json);
8.26
8.27 assert p2.getFirstName().equals(p.getFirstName()) :
8.28 "Should be the same: " + p.getFirstName() + " != " + p2.getFirstName();
8.29 @@ -124,7 +123,7 @@
8.30 throw new IllegalStateException("Can't parse " + txt).initCause(ex);
8.31 }
8.32
8.33 - Person p2 = JSON.read(newContext(), Person.class, json);
8.34 + Person p2 = Models.fromRaw(newContext(), Person.class, json);
8.35
8.36 assert p2.getFirstName().equals(p.getFirstName()) :
8.37 "Should be the same: " + p.getFirstName() + " != " + p2.getFirstName();
8.38 @@ -144,7 +143,7 @@
8.39 throw new IllegalStateException("Can't parse " + txt).initCause(ex);
8.40 }
8.41
8.42 - Person p2 = JSON.read(newContext(), Person.class, json);
8.43 + Person p2 = Models.fromRaw(newContext(), Person.class, json);
8.44
8.45 assert p2.getFirstName().equals(p.getFirstName()) :
8.46 "Should be the same: " + p.getFirstName() + " != " + p2.getFirstName();
9.1 --- a/json-tck/src/main/java/net/java/html/json/tests/KnockoutTest.java Mon Dec 16 18:08:40 2013 +0100
9.2 +++ b/json-tck/src/main/java/net/java/html/json/tests/KnockoutTest.java Mon Jan 06 09:44:07 2014 +0100
9.3 @@ -50,6 +50,7 @@
9.4 import net.java.html.json.Models;
9.5 import net.java.html.json.Property;
9.6 import org.apidesign.html.json.tck.KOTest;
9.7 +import org.apidesign.html.json.tck.KnockoutTCK;
9.8
9.9 /**
9.10 *
10.1 --- a/json-tck/src/main/java/net/java/html/json/tests/Utils.java Mon Dec 16 18:08:40 2013 +0100
10.2 +++ b/json-tck/src/main/java/net/java/html/json/tests/Utils.java Mon Jan 06 09:44:07 2014 +0100
10.3 @@ -43,6 +43,7 @@
10.4 package net.java.html.json.tests;
10.5
10.6 import java.net.URI;
10.7 +import java.util.Collections;
10.8 import java.util.Map;
10.9 import java.util.ServiceLoader;
10.10 import net.java.html.BrwsrCtx;
10.11 @@ -52,12 +53,18 @@
10.12 *
10.13 * @author Jaroslav Tulach <jtulach@netbeans.org>
10.14 */
10.15 -final class Utils {
10.16 +public final class Utils {
10.17 + private static KnockoutTCK instantiatedTCK;
10.18 +
10.19 private Utils() {
10.20 }
10.21 +
10.22 + public static void registerTCK(KnockoutTCK tck) {
10.23 + instantiatedTCK = tck;
10.24 + }
10.25
10.26 static BrwsrCtx newContext(Class<?> clazz) {
10.27 - for (KnockoutTCK tck : ServiceLoader.load(KnockoutTCK.class, cl(clazz))) {
10.28 + for (KnockoutTCK tck : tcks(clazz)) {
10.29 BrwsrCtx c = tck.createContext();
10.30 if (c != null) {
10.31 return c;
10.32 @@ -66,7 +73,7 @@
10.33 throw new AssertionError("Can't find appropriate Context in ServiceLoader!");
10.34 }
10.35 static Object createObject(Map<String,Object> values, Class<?> clazz) {
10.36 - for (KnockoutTCK tck : ServiceLoader.load(KnockoutTCK.class, cl(clazz))) {
10.37 + for (KnockoutTCK tck : tcks(clazz)) {
10.38 Object o = tck.createJSON(values);
10.39 if (o != null) {
10.40 return o;
10.41 @@ -77,11 +84,18 @@
10.42 static Object executeScript(Class<?> clazz,
10.43 String script, Object... arguments
10.44 ) throws Exception {
10.45 - for (KnockoutTCK tck : ServiceLoader.load(KnockoutTCK.class, cl(clazz))) {
10.46 + for (KnockoutTCK tck : tcks(clazz)) {
10.47 return tck.executeScript(script, arguments);
10.48 }
10.49 throw new AssertionError("Can't find appropriate Context in ServiceLoader!");
10.50 }
10.51 +
10.52 + private static Iterable<KnockoutTCK> tcks(Class<?> clazz) {
10.53 + if (instantiatedTCK != null) {
10.54 + return Collections.singleton(instantiatedTCK);
10.55 + }
10.56 + return ServiceLoader.load(KnockoutTCK.class, cl(clazz));
10.57 + }
10.58
10.59 static Object exposeHTML(Class<?> clazz, String html) throws Exception {
10.60 String s =
10.61 @@ -98,7 +112,7 @@
10.62
10.63 static String prepareURL(
10.64 Class<?> clazz, String content, String mimeType, String... parameters) {
10.65 - for (KnockoutTCK tck : ServiceLoader.load(KnockoutTCK.class, cl(clazz))) {
10.66 + for (KnockoutTCK tck : tcks(clazz)) {
10.67 URI o = tck.prepareURL(content, mimeType, parameters);
10.68 if (o != null) {
10.69 return o.toString();
10.70 @@ -109,7 +123,7 @@
10.71
10.72 static boolean canFailWebSockets(
10.73 Class<?> clazz) {
10.74 - for (KnockoutTCK tck : ServiceLoader.load(KnockoutTCK.class, cl(clazz))) {
10.75 + for (KnockoutTCK tck : tcks(clazz)) {
10.76 if (tck.canFailWebSocketTest()) {
10.77 return true;
10.78 }
11.1 --- a/json-tck/src/main/java/org/apidesign/html/json/tck/KnockoutTCK.java Mon Dec 16 18:08:40 2013 +0100
11.2 +++ b/json-tck/src/main/java/org/apidesign/html/json/tck/KnockoutTCK.java Mon Jan 06 09:44:07 2014 +0100
11.3 @@ -46,9 +46,10 @@
11.4 import java.util.Map;
11.5 import net.java.html.BrwsrCtx;
11.6 import net.java.html.json.tests.ConvertTypesTest;
11.7 +import net.java.html.json.tests.JSONTest;
11.8 import net.java.html.json.tests.KnockoutTest;
11.9 -import net.java.html.json.tests.JSONTest;
11.10 import net.java.html.json.tests.OperationsTest;
11.11 +import net.java.html.json.tests.Utils;
11.12 import net.java.html.json.tests.WebSocketTest;
11.13 import org.openide.util.lookup.ServiceProvider;
11.14
11.15 @@ -72,6 +73,7 @@
11.16 */
11.17 public abstract class KnockoutTCK {
11.18 protected KnockoutTCK() {
11.19 + Utils.registerTCK(this);
11.20 }
11.21
11.22 /** Implement to create new context for the test.
12.1 --- a/json/src/main/java/org/apidesign/html/json/spi/FunctionBinding.java Mon Dec 16 18:08:40 2013 +0100
12.2 +++ b/json/src/main/java/org/apidesign/html/json/spi/FunctionBinding.java Mon Jan 06 09:44:07 2014 +0100
12.3 @@ -44,35 +44,59 @@
12.4
12.5 import net.java.html.json.Function;
12.6 import net.java.html.json.Model;
12.7 -import org.netbeans.html.json.impl.PropertyBindingAccessor.FBData;
12.8
12.9 /** Describes a function provided by the {@link Model} and
12.10 * annotated by {@link Function} annotation.
12.11 *
12.12 * @author Jaroslav Tulach <jtulach@netbeans.org>
12.13 */
12.14 -public final class FunctionBinding {
12.15 - private final FBData<?> fb;
12.16 -
12.17 - FunctionBinding(FBData<?> fb) {
12.18 - this.fb = fb;
12.19 - }
12.20 -
12.21 - public String getFunctionName() {
12.22 - return fb.name;
12.23 +public abstract class FunctionBinding {
12.24 + FunctionBinding() {
12.25 }
12.26
12.27 - /** Calls the function provided data associated with current element,
12.28 - * as well as information about the event that triggered the event.
12.29 - *
12.30 + /** Returns name of the function.
12.31 + * @return function name
12.32 + */
12.33 + public abstract String getFunctionName();
12.34 +
12.35 + /**
12.36 + * Calls the function provided data associated with current element, as well
12.37 + * as information about the event that triggered the event.
12.38 + *
12.39 * @param data data associated with selected element
12.40 * @param ev event (with additional properties) that triggered the event
12.41 */
12.42 - public void call(Object data, Object ev) {
12.43 - try {
12.44 - fb.call(data, ev);
12.45 - } catch (Throwable ex) {
12.46 - ex.printStackTrace();
12.47 + public abstract void call(Object data, Object ev);
12.48 +
12.49 + static <M> FunctionBinding registerFunction(String name, int index, M model, Proto.Type<M> access) {
12.50 + return new Impl<M>(name, index, model, access);
12.51 + }
12.52 +
12.53 + private static final class Impl<M> extends FunctionBinding {
12.54 + final String name;
12.55 + private final M model;
12.56 + private final Proto.Type<M> access;
12.57 + private final int index;
12.58 +
12.59 + public Impl(String name, int index, M model, Proto.Type<M> access) {
12.60 + this.name = name;
12.61 + this.index = index;
12.62 + this.model = model;
12.63 + this.access = access;
12.64 + }
12.65 +
12.66 + @Override
12.67 + public String getFunctionName() {
12.68 + return name;
12.69 + }
12.70 +
12.71 + @Override
12.72 + public void call(Object data, Object ev) {
12.73 + try {
12.74 + access.call(model, index, data, ev);
12.75 + } catch (Throwable ex) {
12.76 + ex.printStackTrace();
12.77 + }
12.78 }
12.79 }
12.80 }
13.1 --- a/json/src/main/java/org/apidesign/html/json/spi/PropertyBinding.java Mon Dec 16 18:08:40 2013 +0100
13.2 +++ b/json/src/main/java/org/apidesign/html/json/spi/PropertyBinding.java Mon Jan 06 09:44:07 2014 +0100
13.3 @@ -43,57 +43,126 @@
13.4 package org.apidesign.html.json.spi;
13.5
13.6 import net.java.html.BrwsrCtx;
13.7 +import org.netbeans.html.json.impl.Bindings;
13.8 +import org.netbeans.html.json.impl.JSON;
13.9 import org.netbeans.html.json.impl.PropertyBindingAccessor;
13.10 -import org.netbeans.html.json.impl.PropertyBindingAccessor.PBData;
13.11 import org.netbeans.html.json.impl.RcvrJSON;
13.12 -import org.netbeans.html.json.impl.WrapperObject;
13.13
13.14 /** Describes a property when one is asked to
13.15 * bind it
13.16 *
13.17 * @author Jaroslav Tulach <jtulach@netbeans.org>
13.18 */
13.19 -public final class PropertyBinding {
13.20 - private final PBData<?> data;
13.21 -
13.22 - private PropertyBinding(PBData<?> p) {
13.23 - this.data = p;
13.24 +public abstract class PropertyBinding {
13.25 + PropertyBinding() {
13.26 }
13.27
13.28 static {
13.29 new PropertyBindingAccessor() {
13.30 @Override
13.31 - protected <M> PropertyBinding newBinding(PBData<M> d) {
13.32 - return new PropertyBinding(d);
13.33 + protected JSONCall newCall(BrwsrCtx ctx, RcvrJSON callback, String urlBefore, String urlAfter, String method, Object data) {
13.34 + return new JSONCall(ctx, callback, urlBefore, urlAfter, method, data);
13.35 }
13.36
13.37 @Override
13.38 - protected <M> FunctionBinding newFunction(FBData<M> d) {
13.39 - return new FunctionBinding(d);
13.40 + protected Bindings bindings(Proto proto, boolean initialize) {
13.41 + return initialize ? proto.initBindings() : proto.getBindings();
13.42 }
13.43
13.44 @Override
13.45 - protected JSONCall newCall(BrwsrCtx ctx, RcvrJSON callback, String urlBefore, String urlAfter, String method, Object data) {
13.46 - return new JSONCall(ctx, callback, urlBefore, urlAfter, method, data);
13.47 + protected void notifyChange(Proto proto, int propIndex) {
13.48 + proto.onChange(propIndex);
13.49 + }
13.50 +
13.51 + @Override
13.52 + protected Proto findProto(Proto.Type<?> type, Object object) {
13.53 + return type.protoFor(object);
13.54 + }
13.55 +
13.56 + @Override
13.57 + protected <Model> Model cloneTo(Proto.Type<Model> type, Model model, BrwsrCtx c) {
13.58 + return type.cloneTo(model, c);
13.59 + }
13.60 +
13.61 + @Override
13.62 + protected Object read(Proto.Type<?> from, BrwsrCtx c, Object data) {
13.63 + return from.read(c, data);
13.64 + }
13.65 +
13.66 + @Override
13.67 + protected <M> PropertyBinding newBinding(
13.68 + Proto.Type<M> access, Bindings<?> bindings, String name,
13.69 + int index, M model, boolean readOnly
13.70 + ) {
13.71 + return new Impl(bindings, name, index, model, access, readOnly);
13.72 }
13.73 };
13.74 }
13.75
13.76 - public String getPropertyName() {
13.77 - return data.name;
13.78 - }
13.79 + /** Name of the property this binding represents.
13.80 + * @return name of the property
13.81 + */
13.82 + public abstract String getPropertyName();
13.83
13.84 - public void setValue(Object v) {
13.85 - data.setValue(v);
13.86 - }
13.87 + /** Changes value of the property. Can be called only on dedicated
13.88 + * thread. See {@link Technology#runSafe(java.lang.Runnable)}.
13.89 + *
13.90 + * @param v new value of the property
13.91 + */
13.92 + public abstract void setValue(Object v);
13.93
13.94 - public Object getValue() {
13.95 - Object v = data.getValue();
13.96 - Object r = WrapperObject.find(v, data.getBindings());
13.97 - return r == null ? v : r;
13.98 - }
13.99 + /** Obtains current value of the property this binding represents.
13.100 + * Can be called only on dedicated
13.101 + * thread. See {@link Technology#runSafe(java.lang.Runnable)}.
13.102 + *
13.103 + * @return the value or <code>null</code>
13.104 + */
13.105 + public abstract Object getValue();
13.106
13.107 - public boolean isReadOnly() {
13.108 - return data.isReadOnly();
13.109 - }
13.110 + /** Is this property read only? Or can one call {@link #setValue(java.lang.Object)}?
13.111 + *
13.112 + * @return true, if this property is read only
13.113 + */
13.114 + public abstract boolean isReadOnly();
13.115 +
13.116 + private static final class Impl<M> extends PropertyBinding {
13.117 + public final String name;
13.118 + public final boolean readOnly;
13.119 + private final M model;
13.120 + private final Proto.Type<M> access;
13.121 + private final Bindings<?> bindings;
13.122 + private final int index;
13.123 +
13.124 + public Impl(Bindings<?> bindings, String name, int index, M model, Proto.Type<M> access, boolean readOnly) {
13.125 + this.bindings = bindings;
13.126 + this.name = name;
13.127 + this.index = index;
13.128 + this.model = model;
13.129 + this.access = access;
13.130 + this.readOnly = readOnly;
13.131 + }
13.132 +
13.133 + @Override
13.134 + public void setValue(Object v) {
13.135 + access.setValue(model, index, v);
13.136 + }
13.137 +
13.138 + @Override
13.139 + public Object getValue() {
13.140 + Object v = access.getValue(model, index);
13.141 + Object r = JSON.find(v, bindings);
13.142 + return r == null ? v : r;
13.143 + }
13.144 +
13.145 + @Override
13.146 + public boolean isReadOnly() {
13.147 + return readOnly;
13.148 + }
13.149 +
13.150 + @Override
13.151 + public String getPropertyName() {
13.152 + return name;
13.153 + }
13.154 + } // end of PBData
13.155 +
13.156 }
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
14.2 +++ b/json/src/main/java/org/apidesign/html/json/spi/Proto.java Mon Jan 06 09:44:07 2014 +0100
14.3 @@ -0,0 +1,656 @@
14.4 +/**
14.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
14.6 + *
14.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
14.8 + *
14.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
14.10 + * Other names may be trademarks of their respective owners.
14.11 + *
14.12 + * The contents of this file are subject to the terms of either the GNU
14.13 + * General Public License Version 2 only ("GPL") or the Common
14.14 + * Development and Distribution License("CDDL") (collectively, the
14.15 + * "License"). You may not use this file except in compliance with the
14.16 + * License. You can obtain a copy of the License at
14.17 + * http://www.netbeans.org/cddl-gplv2.html
14.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
14.19 + * specific language governing permissions and limitations under the
14.20 + * License. When distributing the software, include this License Header
14.21 + * Notice in each file and include the License file at
14.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
14.23 + * particular file as subject to the "Classpath" exception as provided
14.24 + * by Oracle in the GPL Version 2 section of the License file that
14.25 + * accompanied this code. If applicable, add the following below the
14.26 + * License Header, with the fields enclosed by brackets [] replaced by
14.27 + * your own identifying information:
14.28 + * "Portions Copyrighted [year] [name of copyright owner]"
14.29 + *
14.30 + * Contributor(s):
14.31 + *
14.32 + * The Original Software is NetBeans. The Initial Developer of the Original
14.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
14.34 + *
14.35 + * If you wish your version of this file to be governed by only the CDDL
14.36 + * or only the GPL Version 2, indicate your decision by adding
14.37 + * "[Contributor] elects to include this software in this distribution
14.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
14.39 + * single choice of license, a recipient has the option to distribute
14.40 + * your version of this file under either the CDDL, the GPL Version 2 or
14.41 + * to extend the choice of license to its licensees as provided above.
14.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
14.43 + * Version 2 license, then the option applies only if the new code is
14.44 + * made subject to such option by the copyright holder.
14.45 + */
14.46 +package org.apidesign.html.json.spi;
14.47 +
14.48 +import java.util.Collection;
14.49 +import java.util.List;
14.50 +import net.java.html.BrwsrCtx;
14.51 +import net.java.html.json.ComputedProperty;
14.52 +import net.java.html.json.Model;
14.53 +import org.netbeans.html.json.impl.Bindings;
14.54 +import org.netbeans.html.json.impl.JSON;
14.55 +import org.netbeans.html.json.impl.JSONList;
14.56 +import org.netbeans.html.json.impl.RcvrJSON;
14.57 +import org.netbeans.html.json.impl.RcvrJSON.MsgEvnt;
14.58 +
14.59 +/** Object associated with one instance of a model generated by the
14.60 + * {@link Model} annotation. Contains methods the generated class can
14.61 + * use to communicate with behind the scene associated {@link Technology}.
14.62 + * Each {@link Proto} object is associated with <a href="http://wiki.apidesign.org/wiki/Singletonizer">
14.63 + * singletonizer</a>-like interface {@link Type} which provides the
14.64 + * associated {@link Technology} the necessary information about the
14.65 + * generated {@link Model} class.
14.66 + *
14.67 + * @author Jaroslav Tulach <jtulach@netbeans.org>
14.68 + * @since 0.7
14.69 + */
14.70 +public final class Proto {
14.71 + private final Object obj;
14.72 + private final Type type;
14.73 + private final net.java.html.BrwsrCtx context;
14.74 + private boolean locked;
14.75 + private org.netbeans.html.json.impl.Bindings ko;
14.76 +
14.77 + Proto(Object obj, Type type, BrwsrCtx context) {
14.78 + this.obj = obj;
14.79 + this.type = type;
14.80 + this.context = context;
14.81 + }
14.82 +
14.83 + /** Browser context this proto object and its associated model
14.84 + * are operating-in.
14.85 + *
14.86 + * @return the associated context
14.87 + */
14.88 + public BrwsrCtx getContext() {
14.89 + return context;
14.90 + }
14.91 +
14.92 + /** Before doing modification of the model properties, the
14.93 + * generated code enters write lock by calling this method.
14.94 + * @throws IllegalStateException if already locked
14.95 + */
14.96 + public void acquireLock() throws IllegalStateException {
14.97 + if (locked) throw new IllegalStateException();
14.98 + locked = true;
14.99 + }
14.100 +
14.101 + /** Verifies the model is not locked otherwise throws an exception.
14.102 + * @throws IllegalStateException if the model is locked
14.103 + */
14.104 + public void verifyUnlocked() throws IllegalStateException {
14.105 + if (locked) throw new IllegalStateException();
14.106 + }
14.107 +
14.108 + /** When modifications are over, the model is switched into
14.109 + * unlocked state by calling this method.
14.110 + */
14.111 + public void releaseLock() {
14.112 + locked = false;
14.113 + }
14.114 +
14.115 + /** Whenever model changes a property. It should notify the
14.116 + * associated technology by calling this method.
14.117 + *
14.118 + *@param propName name of the changed property
14.119 + */
14.120 + public void valueHasMutated(String propName) {
14.121 + if (ko != null) {
14.122 + ko.valueHasMutated(propName);
14.123 + }
14.124 + }
14.125 +
14.126 + /** Initializes the associated model in the current {@link #getContext() context}.
14.127 + * In case of <em>knockout.js</em> technology, applies given bindings
14.128 + * of the current model to the <em>body</em> element of the page.
14.129 + */
14.130 + public void applyBindings() {
14.131 + initBindings().applyBindings();
14.132 + }
14.133 +
14.134 + /** Invokes the provided runnable in the {@link #getContext() context}
14.135 + * of the browser. If the caller is already on the right thread, the
14.136 + * <code>run.run()</code> is invoked immediately and synchronously.
14.137 + * Otherwise the method returns immediately and the <code>run()</code>
14.138 + * method is performed later
14.139 + *
14.140 + * @param run the action to execute
14.141 + */
14.142 + public void runInBrowser(Runnable run) {
14.143 + JSON.runInBrowser(context, run);
14.144 + }
14.145 +
14.146 + /** Initializes the provided collection with a content of the <code>array</code>.
14.147 + * The initialization can only be done soon after the the collection
14.148 + * is created, otherwise an exception is throw
14.149 + *
14.150 + * @param to the collection to initialize (assumed to be empty)
14.151 + * @param array the array to add to the collection
14.152 + * @throws IllegalStateException if the system has already been initialized
14.153 + */
14.154 + public void initTo(Collection<?> to, Object array) {
14.155 + if (ko != null) {
14.156 + throw new IllegalStateException();
14.157 + }
14.158 + if (to instanceof JSONList) {
14.159 + ((JSONList)to).init(array);
14.160 + } else {
14.161 + JSONList.init(to, array);
14.162 + }
14.163 + }
14.164 +
14.165 + /** Takes an object representing JSON result and extract some of its
14.166 + * properties. It is assumed that the <code>props</code> and
14.167 + * <code>values</code> arrays have the same length.
14.168 + *
14.169 + * @param json the JSON object (actual type depends on the associated
14.170 + * {@link Technology})
14.171 + * @param props list of properties to extract
14.172 + * @param values array that will be filled with extracted values
14.173 + */
14.174 + public void extract(Object json, String[] props, Object[] values) {
14.175 + JSON.extract(context, json, props, values);
14.176 + }
14.177 +
14.178 + /** Converts raw JSON <code>data</code> into a Java {@link Model} class.
14.179 + *
14.180 + * @param <T> type of the model class
14.181 + * @param modelClass the type of the class to create
14.182 + * @param data the raw JSON data
14.183 + * @return newly created instance of the model class
14.184 + */
14.185 + public <T> T read(Class<T> modelClass, Object data) {
14.186 + return JSON.read(context, modelClass, data);
14.187 + }
14.188 +
14.189 + /** Initializes asynchronous JSON connection to specified URL. The
14.190 + * method returns immediately and later does callback later.
14.191 + *
14.192 + * @param index the callback index to be used when a reply is received
14.193 + * to call {@link Type#onMessage(java.lang.Object, int, int, java.lang.Object)}.
14.194 + *
14.195 + * @param urlBefore the part of the URL before JSON-P callback parameter
14.196 + * @param urlAfter the rest of the URL or <code>null</code> if no JSON-P is used
14.197 + * @param method method to use for connection to the server
14.198 + * @param data string, number or a {@link Model} generated class to send to
14.199 + * the server when doing a query
14.200 + */
14.201 + public void loadJSON(final int index,
14.202 + String urlBefore, String urlAfter, String method,
14.203 + final Object data
14.204 + ) {
14.205 + class Rcvr extends RcvrJSON {
14.206 + @Override
14.207 + protected void onMessage(MsgEvnt msg) {
14.208 + type.onMessage(obj, index, 1, msg.getValues());
14.209 + }
14.210 +
14.211 + @Override
14.212 + protected void onError(MsgEvnt msg) {
14.213 + type.onMessage(obj, index, 2, msg.getException());
14.214 + }
14.215 + }
14.216 + JSON.loadJSON(context, new Rcvr(), urlBefore, urlAfter, method, data);
14.217 + }
14.218 +
14.219 + /** Opens new WebSocket connection to the specified URL.
14.220 + *
14.221 + * @param index the index to use later during callbacks to
14.222 + * {@link Type#onMessage(java.lang.Object, int, int, java.lang.Object)}
14.223 + * @param url the <code>ws://</code> or <code>wss://</code> URL to connect to
14.224 + * @param data data to send to server (usually <code>null</code>)
14.225 + * @return returns a non-null object representing the socket
14.226 + * which can be used when calling {@link #wsSend(java.lang.Object, java.lang.String, java.lang.Object) }
14.227 + */
14.228 + public Object wsOpen(final int index, String url, Object data) {
14.229 + class WSrcvr extends RcvrJSON {
14.230 + @Override
14.231 + protected void onError(MsgEvnt msg) {
14.232 + type.onMessage(obj, index, 2, msg.getException());
14.233 + }
14.234 +
14.235 + @Override
14.236 + protected void onMessage(MsgEvnt msg) {
14.237 + type.onMessage(obj, index, 1, msg.getValues());
14.238 + }
14.239 +
14.240 + @Override
14.241 + protected void onClose(MsgEvnt msg) {
14.242 + type.onMessage(obj, index, 3, null);
14.243 + }
14.244 +
14.245 + @Override
14.246 + protected void onOpen(MsgEvnt msg) {
14.247 + type.onMessage(obj, index, 0, null);
14.248 + }
14.249 + }
14.250 + return JSON.openWS(context, new WSrcvr(), url, data);
14.251 + }
14.252 +
14.253 + /** Sends a message to existing socket.
14.254 + *
14.255 + * @param webSocket the socket to send message to
14.256 + * @param url the <code>ws://</code> or <code>wss://</code> URL to connect to,
14.257 + * preferably the same as the one used when the socket was
14.258 + * {@link #wsOpen(int, java.lang.String, java.lang.Object) opened}
14.259 + * @param data the data to send or <code>null</code> if the socket is
14.260 + * supposed to be closed
14.261 + */
14.262 + public void wsSend(Object webSocket, String url, Object data) {
14.263 + ((JSON.WS)webSocket).send(context, url, data);
14.264 + }
14.265 +
14.266 + /** Converts raw data (one of its properties) to string representation.
14.267 + *
14.268 + * @param data the object
14.269 + * @param propName the name of object property or <code>null</code>
14.270 + * if the whole object should be converted
14.271 + * @return the string representation of the object or its property
14.272 + */
14.273 + public String toString(Object data, String propName) {
14.274 + return JSON.toString(context, data, propName);
14.275 + }
14.276 +
14.277 + /** Converts raw data (one of its properties) to a number representation.
14.278 + *
14.279 + * @param data the object
14.280 + * @param propName the name of object property or <code>null</code>
14.281 + * if the whole object should be converted
14.282 + * @return the number representation of the object or its property
14.283 + */
14.284 + public Number toNumber(Object data, String propName) {
14.285 + return JSON.toNumber(context, data, propName);
14.286 + }
14.287 +
14.288 + /** Converts raw JSON data into a {@link Model} class representation.
14.289 + *
14.290 + * @param <T> type of the model to create
14.291 + * @param type class of the model to create
14.292 + * @param data raw JSON data (depends on associated {@link Technology})
14.293 + * @return new instances of the model class filled with values from the
14.294 + * <code>data</code> object
14.295 + */
14.296 + public <T> T toModel(Class<T> type, Object data) {
14.297 + return JSON.toModel(context, type, data, null);
14.298 + }
14.299 +
14.300 + /** Creates new JSON like observable list.
14.301 + *
14.302 + * @param <T> the type of the list elements
14.303 + * @param propName name of a property this list is associated with
14.304 + * @param onChange index of the property to use when the list is modified
14.305 + * during callback to {@link Type#onChange(java.lang.Object, int)}
14.306 + * @param dependingProps the array of {@link ComputedProperty derived properties}
14.307 + * that depend on the value of the list
14.308 + * @return new, empty list associated with this proto-object and its model
14.309 + */
14.310 + public <T> List<T> createList(String propName, int onChange, String... dependingProps) {
14.311 + return new JSONList<T>(this, propName, onChange, dependingProps);
14.312 + }
14.313 +
14.314 + /** Copies content of one collection to another, re-assigning all its
14.315 + * elements from their current context to the new <code>ctx</code>.
14.316 + *
14.317 + * @param <T> type of the collections
14.318 + * @param to the target collection to be filled with cloned values
14.319 + * @param ctx context for the new collection
14.320 + * @param from original collection with its data
14.321 + */
14.322 + public <T> void cloneList(Collection<T> to, BrwsrCtx ctx, Collection<T> from) {
14.323 + Boolean isModel = null;
14.324 + for (T t : from) {
14.325 + if (isModel == null) {
14.326 + isModel = JSON.isModel(t.getClass());
14.327 + }
14.328 + if (isModel) {
14.329 + to.add(JSON.bindTo(t, ctx));
14.330 + } else {
14.331 + to.add(t);
14.332 + }
14.333 + }
14.334 + }
14.335 +
14.336 + //
14.337 + // internal state
14.338 + //
14.339 +
14.340 +
14.341 + final Bindings initBindings() {
14.342 + if (ko == null) {
14.343 + Bindings b = Bindings.apply(context, obj);
14.344 + PropertyBinding[] pb = new PropertyBinding[type.propertyNames.length];
14.345 + for (int i = 0; i < pb.length; i++) {
14.346 + pb[i] = b.registerProperty(
14.347 + type.propertyNames[i], i, obj, type, type.propertyReadOnly[i]
14.348 + );
14.349 + }
14.350 + FunctionBinding[] fb = new FunctionBinding[type.functions.length];
14.351 + for (int i = 0; i < fb.length; i++) {
14.352 + fb[i] = FunctionBinding.registerFunction(
14.353 + type.functions[i], i, obj, type
14.354 + );
14.355 + }
14.356 + ko = b;
14.357 + b.finish(obj, pb, fb);
14.358 + }
14.359 + return ko;
14.360 + }
14.361 +
14.362 + final Bindings getBindings() {
14.363 + return ko;
14.364 + }
14.365 +
14.366 + final void onChange(int index) {
14.367 + type.onChange(obj, index);
14.368 + }
14.369 +
14.370 + /** Functionality used by the code generated by annotation
14.371 + * processor for the {@link net.java.html.json.Model} annotation.
14.372 + *
14.373 + * @param <Model> the generated class
14.374 + * @since 0.7
14.375 + */
14.376 + public static abstract class Type<Model> {
14.377 + private final Class<Model> clazz;
14.378 + private final String[] propertyNames;
14.379 + private final boolean[] propertyReadOnly;
14.380 + private final String[] functions;
14.381 +
14.382 + /** Constructor for subclasses generated by the annotation processor
14.383 + * associated with {@link net.java.html.json.Model} annotation.
14.384 + *
14.385 + * @param clazz the generated model class
14.386 + * @param modelFor the original class annotated by the {@link net.java.html.json.Model} annotation.
14.387 + * @param properties number of properties the class has
14.388 + * @param functions number of functions the class has
14.389 + */
14.390 + protected Type(
14.391 + Class<Model> clazz, Class<?> modelFor, int properties, int functions
14.392 + ) {
14.393 + assert getClass().getName().endsWith("$Html4JavaType");
14.394 + assert getClass().getDeclaringClass() == clazz;
14.395 + this.clazz = clazz;
14.396 + this.propertyNames = new String[properties];
14.397 + this.propertyReadOnly = new boolean[properties];
14.398 + this.functions = new String[functions];
14.399 + JSON.register(clazz, this);
14.400 + }
14.401 +
14.402 + /** Registers property for the type. It is expected each index
14.403 + * is initialized only once.
14.404 + *
14.405 + * @param name name of the property
14.406 + * @param index index of the property
14.407 + * @param readOnly is the property read only?
14.408 + */
14.409 + protected final void registerProperty(String name, int index, boolean readOnly) {
14.410 + assert propertyNames[index] == null;
14.411 + propertyNames[index] = name;
14.412 + propertyReadOnly[index] = readOnly;
14.413 + }
14.414 +
14.415 + /** Registers function of given name at given index.
14.416 + *
14.417 + * @param name name of the function
14.418 + * @param index name of the type
14.419 + */
14.420 + protected final void registerFunction(String name, int index) {
14.421 + assert functions[index] == null;
14.422 + functions[index] = name;
14.423 + }
14.424 +
14.425 + /** Creates new proto-object for given {@link Model} class bound to
14.426 + * provided context.
14.427 + *
14.428 + * @param obj instance of appropriate {@link Model} class
14.429 + * @param context the browser context
14.430 + * @return new proto-object that the generated class can use for
14.431 + * communication with the infrastructure
14.432 + */
14.433 + public Proto createProto(Object obj, BrwsrCtx context) {
14.434 + return new Proto(obj, this, context);
14.435 + }
14.436 +
14.437 + //
14.438 + // Implemented by subclasses
14.439 + //
14.440 +
14.441 + /** Sets value of a {@link #registerProperty(java.lang.String, int, boolean) registered property}
14.442 + * to new value.
14.443 + *
14.444 + * @param model the instance of {@link Model model class}
14.445 + * @param index index of the property used during registration
14.446 + * @param value the value to set the property to
14.447 + */
14.448 + protected abstract void setValue(Model model, int index, Object value);
14.449 +
14.450 + /** Obtains and returns value of a
14.451 + * {@link #registerProperty(java.lang.String, int, boolean) registered property}.
14.452 + *
14.453 + * @param model the instance of {@link Model model class}
14.454 + * @param index index of the property used during registration
14.455 + * @return current value of the property
14.456 + */
14.457 + protected abstract Object getValue(Model model, int index);
14.458 +
14.459 + /** Invokes a {@link #registerFunction(java.lang.String, int) registered function
14.460 + * on given object.
14.461 + *
14.462 + * @param model the instance of {@link Model model class}
14.463 + * @param index index of the property used during registration
14.464 + * @param data the currently selected object the function is about to operate on
14.465 + * @param event the event that triggered the event
14.466 + */
14.467 + protected abstract void call(Model model, int index, Object data, Object event);
14.468 +
14.469 + /** Re-binds the model object to new browser context.
14.470 + *
14.471 + * @param model the instance of {@link Model model class}
14.472 + * @param ctx browser context to clone the object to
14.473 + * @return new instance of the model suitable for new context
14.474 + */
14.475 + protected abstract Model cloneTo(Model model, BrwsrCtx ctx);
14.476 +
14.477 + /** Reads raw JSON data and converts them to our model class.
14.478 + *
14.479 + * @param c the browser context to work in
14.480 + * @param json raw JSON data to get values from
14.481 + * @return new instance of model class filled by the data
14.482 + */
14.483 + protected abstract Model read(BrwsrCtx c, Object json);
14.484 +
14.485 + /** Called when a {@link #registerProperty(java.lang.String, int, boolean) registered property}
14.486 + * changes its value.
14.487 + *
14.488 + * @param model the object that has the property
14.489 + * @param index the index of the property during registration
14.490 + */
14.491 + protected abstract void onChange(Model model, int index);
14.492 +
14.493 + /** Finds out if there is an associated proto-object for given
14.494 + * object.
14.495 + *
14.496 + * @param object an object, presumably (but not necessarily) instance of Model class
14.497 + * @return associated proto-object or <code>null</code>
14.498 + */
14.499 + protected abstract Proto protoFor(Object object);
14.500 +
14.501 + /** Called to report results of asynchronous over-the-wire
14.502 + * communication. Result of calling {@link Proto#wsOpen(int, java.lang.String, java.lang.Object)}
14.503 + * or {@link Proto#loadJSON(int, java.lang.String, java.lang.String, java.lang.String, java.lang.Object)}.
14.504 + *
14.505 + * @param model the instance of the model class
14.506 + * @param index index used during initiating the communication (via <code>loadJSON</code> or <code>wsOpen</code> calls)
14.507 + * @param type type of the message: 0 - onOpen, 1 - onMessage, 2 - onError, 3 - onClose -
14.508 + * not all messages are applicable to all communication protocols (JSON has only 1 and 2).
14.509 + * @param data <code>null</code> or string, number or a {@link Model} class
14.510 + * obtained to the server as a response
14.511 + */
14.512 + protected abstract void onMessage(Model model, int index, int type, Object data);
14.513 +
14.514 + //
14.515 + // Various support methods the generated classes use
14.516 + //
14.517 +
14.518 + /** Converts and array of raw JSON objects into an array of typed
14.519 + * Java {@lin Model} classes.
14.520 + *
14.521 + * @param <T> the type of the destination array
14.522 + * @param context browser context to use
14.523 + * @param src array of raw JSON objects
14.524 + * @param destType type of the individual array elements
14.525 + * @param dest array to be filled with read type instances
14.526 + */
14.527 + public <T> void copyJSON(BrwsrCtx context, Object[] src, Class<T> destType, T[] dest) {
14.528 + for (int i = 0; i < src.length && i < dest.length; i++) {
14.529 + dest[i] = org.netbeans.html.json.impl.JSON.read(context, destType, src[i]);
14.530 + }
14.531 + }
14.532 +
14.533 + /** Compares two objects that can be converted to integers.
14.534 + * @return true if they are the same
14.535 + */
14.536 + public final boolean isSame(int a, int b) {
14.537 + return a == b;
14.538 + }
14.539 +
14.540 + /** Compares two objects that can be converted to (floating point)
14.541 + * numbers.
14.542 + * @return true if they are the same
14.543 + */
14.544 + public final boolean isSame(double a, double b) {
14.545 + return a == b;
14.546 + }
14.547 +
14.548 + /** Compares two objects for being the same - e.g. either <code>==</code>
14.549 + * or <code>equals</code>.
14.550 + * @return true if they are equals
14.551 + */
14.552 + public final boolean isSame(Object a, Object b) {
14.553 + if (a == b) {
14.554 + return true;
14.555 + }
14.556 + if (a == null || b == null) {
14.557 + return false;
14.558 + }
14.559 + return a.equals(b);
14.560 + }
14.561 +
14.562 + /** Cumulative hash function. Adds hashcode of the object to the
14.563 + * previous value.
14.564 + * @param o the object (or <code>null</code>)
14.565 + * @param h the previous value of the hash
14.566 + * @return new hash - the old one xor the object's one
14.567 + */
14.568 + public final int hashPlus(Object o, int h) {
14.569 + return o == null ? h : h ^ o.hashCode();
14.570 + }
14.571 +
14.572 + /** Converts an object to its JSON value.
14.573 + *
14.574 + * @param obj the object to convert
14.575 + * @return JSON representation of the object
14.576 + */
14.577 + public final String toJSON(Object obj) {
14.578 + return JSON.toJSON(obj);
14.579 + }
14.580 +
14.581 + /** Converts the value to string.
14.582 + *
14.583 + * @param val the value
14.584 + * @return the converted value
14.585 + */
14.586 + public final String stringValue(Object val) {
14.587 + return JSON.stringValue(val);
14.588 + }
14.589 +
14.590 + /** Converts the value to number.
14.591 + *
14.592 + * @param val the value
14.593 + * @return the converted value
14.594 + */
14.595 + public final Number numberValue(Object val) {
14.596 + return JSON.numberValue(val);
14.597 + }
14.598 +
14.599 + /** Converts the value to character.
14.600 + *
14.601 + * @param val the value
14.602 + * @return the converted value
14.603 + */
14.604 + public final Character charValue(Object val) {
14.605 + return JSON.charValue(val);
14.606 + }
14.607 +
14.608 + /** Converts the value to boolean.
14.609 + *
14.610 + * @param val the value
14.611 + * @return the converted value
14.612 + */
14.613 + public final Boolean boolValue(Object val) {
14.614 + return JSON.boolValue(val);
14.615 + }
14.616 +
14.617 + /** Extracts value of specific type from given object.
14.618 + *
14.619 + * @param <T> the type of object one is interested in
14.620 + * @param type the type
14.621 + * @param val the object to convert to type
14.622 + * @return the converted value
14.623 + */
14.624 + public final <T> T extractValue(Class<T> type, Object val) {
14.625 + if (Number.class.isAssignableFrom(type)) {
14.626 + val = numberValue(val);
14.627 + }
14.628 + if (Boolean.class == type) {
14.629 + val = boolValue(val);
14.630 + }
14.631 + if (String.class == type) {
14.632 + val = stringValue(val);
14.633 + }
14.634 + if (Character.class == type) {
14.635 + val = charValue(val);
14.636 + }
14.637 + if (Integer.class == type) {
14.638 + val = val instanceof Number ? ((Number) val).intValue() : 0;
14.639 + }
14.640 + if (Long.class == type) {
14.641 + val = val instanceof Number ? ((Number) val).longValue() : 0;
14.642 + }
14.643 + if (Short.class == type) {
14.644 + val = val instanceof Number ? ((Number) val).shortValue() : 0;
14.645 + }
14.646 + if (Byte.class == type) {
14.647 + val = val instanceof Number ? ((Number) val).byteValue() : 0;
14.648 + }
14.649 + if (Double.class == type) {
14.650 + val = val instanceof Number ? ((Number) val).doubleValue() : Double.NaN;
14.651 + }
14.652 + if (Float.class == type) {
14.653 + val = val instanceof Number ? ((Number) val).floatValue() : Float.NaN;
14.654 + }
14.655 + return type.cast(val);
14.656 + }
14.657 +
14.658 + }
14.659 +}
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
15.2 +++ b/json/src/main/java/org/apidesign/html/json/spi/package.html Mon Jan 06 09:44:07 2014 +0100
15.3 @@ -0,0 +1,51 @@
15.4 +<!--
15.5 +
15.6 + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
15.7 +
15.8 + Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
15.9 +
15.10 + Oracle and Java are registered trademarks of Oracle and/or its affiliates.
15.11 + Other names may be trademarks of their respective owners.
15.12 +
15.13 + The contents of this file are subject to the terms of either the GNU
15.14 + General Public License Version 2 only ("GPL") or the Common
15.15 + Development and Distribution License("CDDL") (collectively, the
15.16 + "License"). You may not use this file except in compliance with the
15.17 + License. You can obtain a copy of the License at
15.18 + http://www.netbeans.org/cddl-gplv2.html
15.19 + or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
15.20 + specific language governing permissions and limitations under the
15.21 + License. When distributing the software, include this License Header
15.22 + Notice in each file and include the License file at
15.23 + nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
15.24 + particular file as subject to the "Classpath" exception as provided
15.25 + by Oracle in the GPL Version 2 section of the License file that
15.26 + accompanied this code. If applicable, add the following below the
15.27 + License Header, with the fields enclosed by brackets [] replaced by
15.28 + your own identifying information:
15.29 + "Portions Copyrighted [year] [name of copyright owner]"
15.30 +
15.31 + Contributor(s):
15.32 +
15.33 + The Original Software is NetBeans. The Initial Developer of the Original
15.34 + Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
15.35 +
15.36 + If you wish your version of this file to be governed by only the CDDL
15.37 + or only the GPL Version 2, indicate your decision by adding
15.38 + "[Contributor] elects to include this software in this distribution
15.39 + under the [CDDL or GPL Version 2] license." If you do not indicate a
15.40 + single choice of license, a recipient has the option to distribute
15.41 + your version of this file under either the CDDL, the GPL Version 2 or
15.42 + to extend the choice of license to its licensees as provided above.
15.43 + However, if you add GPL Version 2 code and therefore, elected the GPL
15.44 + Version 2 license, then the option applies only if the new code is
15.45 + made subject to such option by the copyright holder.
15.46 +
15.47 +-->
15.48 +<html>
15.49 + <body>
15.50 + <div>Service Provider Interfaces for those who wish to integrate own
15.51 + <a href="Technology.html">technology</a> with the HTML for Java API.
15.52 + </div>
15.53 + </body>
15.54 +</html>
16.1 --- a/json/src/main/java/org/netbeans/html/json/impl/Bindings.java Mon Dec 16 18:08:40 2013 +0100
16.2 +++ b/json/src/main/java/org/netbeans/html/json/impl/Bindings.java Mon Jan 06 09:44:07 2014 +0100
16.3 @@ -42,11 +42,10 @@
16.4 */
16.5 package org.netbeans.html.json.impl;
16.6
16.7 +import net.java.html.BrwsrCtx;
16.8 +import org.apidesign.html.json.spi.FunctionBinding;
16.9 import org.apidesign.html.json.spi.PropertyBinding;
16.10 -import net.java.html.BrwsrCtx;
16.11 -import org.netbeans.html.json.impl.PropertyBindingAccessor.FBData;
16.12 -import org.netbeans.html.json.impl.PropertyBindingAccessor.PBData;
16.13 -import org.apidesign.html.json.spi.FunctionBinding;
16.14 +import org.apidesign.html.json.spi.Proto;
16.15 import org.apidesign.html.json.spi.Technology;
16.16
16.17 /**
16.18 @@ -61,14 +60,10 @@
16.19 this.bp = bp;
16.20 }
16.21
16.22 - public <M> PropertyBinding registerProperty(String propName, M model, SetAndGet<M> access, boolean readOnly) {
16.23 - return PropertyBindingAccessor.create(new PBData<M>(this, propName, model, access, readOnly));
16.24 + public <M> PropertyBinding registerProperty(String propName, int index, M model, Proto.Type<M> access, boolean readOnly) {
16.25 + return PropertyBindingAccessor.create(access, this, propName, index, model, readOnly);
16.26 }
16.27
16.28 - public <M> FunctionBinding registerFunction(String name, M model, Callback<M> access) {
16.29 - return PropertyBindingAccessor.createFunction(new FBData<M>(name, model, access));
16.30 - }
16.31 -
16.32 public static Bindings<?> apply(BrwsrCtx c, Object model) {
16.33 Technology<?> bp = JSON.findTechnology(c);
16.34 return apply(bp);
17.1 --- a/json/src/main/java/org/netbeans/html/json/impl/Callback.java Mon Dec 16 18:08:40 2013 +0100
17.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
17.3 @@ -1,51 +0,0 @@
17.4 -/**
17.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
17.6 - *
17.7 - * Copyright 2013-2013 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.json.impl;
17.47 -
17.48 -/**
17.49 - *
17.50 - * @author Jaroslav Tulach <jtulach@netbeans.org>
17.51 - */
17.52 -public interface Callback<Data> {
17.53 - public void call(Data model, Object data, Object ev);
17.54 -}
18.1 --- a/json/src/main/java/org/netbeans/html/json/impl/FromJSON.java Mon Dec 16 18:08:40 2013 +0100
18.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
18.3 @@ -1,55 +0,0 @@
18.4 -/**
18.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
18.6 - *
18.7 - * Copyright 2013-2013 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.json.impl;
18.47 -
18.48 -import net.java.html.BrwsrCtx;
18.49 -
18.50 -/**
18.51 - *
18.52 - * @author Jaroslav Tulach <jtulach@netbeans.org>
18.53 - */
18.54 -public interface FromJSON<Data> {
18.55 - public Class<Data> factoryFor();
18.56 - public Data read(BrwsrCtx c, Object d);
18.57 - public Data cloneTo(Object d, BrwsrCtx c);
18.58 -}
19.1 --- a/json/src/main/java/org/netbeans/html/json/impl/JSON.java Mon Dec 16 18:08:40 2013 +0100
19.2 +++ b/json/src/main/java/org/netbeans/html/json/impl/JSON.java Mon Jan 06 09:44:07 2014 +0100
19.3 @@ -44,6 +44,7 @@
19.4
19.5 import java.io.IOException;
19.6 import java.io.InputStream;
19.7 +import java.util.Collection;
19.8 import java.util.HashMap;
19.9 import java.util.Map;
19.10 import net.java.html.BrwsrCtx;
19.11 @@ -51,6 +52,7 @@
19.12 import org.apidesign.html.json.spi.FunctionBinding;
19.13 import org.apidesign.html.json.spi.JSONCall;
19.14 import org.apidesign.html.json.spi.PropertyBinding;
19.15 +import org.apidesign.html.json.spi.Proto;
19.16 import org.apidesign.html.json.spi.Technology;
19.17 import org.apidesign.html.json.spi.Transfer;
19.18 import org.apidesign.html.json.spi.WSTransfer;
19.19 @@ -96,7 +98,7 @@
19.20 return val[0];
19.21 }
19.22
19.23 - public static Object toJSON(Object value) {
19.24 + public static String toJSON(Object value) {
19.25 if (value == null) {
19.26 return "null";
19.27 }
19.28 @@ -198,7 +200,7 @@
19.29 return type.cast(val);
19.30 }
19.31
19.32 - protected static boolean isNumeric(Object val) {
19.33 + static boolean isNumeric(Object val) {
19.34 return ((val instanceof Integer) || (val instanceof Long) || (val instanceof Short) || (val instanceof Byte));
19.35 }
19.36
19.37 @@ -217,7 +219,7 @@
19.38 }
19.39 return (String)val;
19.40 }
19.41 -
19.42 +
19.43 public static Number numberValue(Object val) {
19.44 if (val instanceof String) {
19.45 try {
19.46 @@ -257,6 +259,32 @@
19.47 return Boolean.TRUE.equals(val);
19.48 }
19.49
19.50 + public static Object find(Object object, Bindings model) {
19.51 + if (object == null) {
19.52 + return null;
19.53 + }
19.54 + if (object instanceof JSONList) {
19.55 + return ((JSONList<?>) object).koData();
19.56 + }
19.57 + if (object instanceof Collection) {
19.58 + return JSONList.koData((Collection<?>) object, model);
19.59 + }
19.60 + Proto.Type<?> type = JSON.findType(object.getClass());
19.61 + if (type == null) {
19.62 + return null;
19.63 + }
19.64 + final Proto proto = PropertyBindingAccessor.protoFor(type, object);
19.65 + if (proto == null) {
19.66 + return null;
19.67 + }
19.68 + final Bindings b = PropertyBindingAccessor.getBindings(proto, true);
19.69 + return b == null ? null : b.koData();
19.70 + }
19.71 +
19.72 + public static Object find(Object object) {
19.73 + return find(object, null);
19.74 + }
19.75 +
19.76 public static void loadJSON(
19.77 BrwsrCtx c, RcvrJSON callback,
19.78 String urlBefore, String urlAfter, String method,
19.79 @@ -326,22 +354,21 @@
19.80
19.81 }
19.82
19.83 - private static final Map<Class,FromJSON<?>> froms;
19.84 + private static final Map<Class,Proto.Type<?>> modelTypes;
19.85 static {
19.86 - Map<Class,FromJSON<?>> m = new HashMap<Class,FromJSON<?>>();
19.87 - froms = m;
19.88 + modelTypes = new HashMap<Class, Proto.Type<?>>();
19.89 }
19.90 - public static void register(FromJSON<?> from) {
19.91 - froms.put(from.factoryFor(), from);
19.92 + public static void register(Class c, Proto.Type<?> type) {
19.93 + modelTypes.put(c, type);
19.94 }
19.95
19.96 public static boolean isModel(Class<?> clazz) {
19.97 - return findFrom(clazz) != null;
19.98 + return findType(clazz) != null;
19.99 }
19.100
19.101 - private static FromJSON<?> findFrom(Class<?> clazz) {
19.102 + static Proto.Type<?> findType(Class<?> clazz) {
19.103 for (int i = 0; i < 2; i++) {
19.104 - FromJSON<?> from = froms.get(clazz);
19.105 + Proto.Type<?> from = modelTypes.get(clazz);
19.106 if (from == null) {
19.107 initClass(clazz);
19.108 } else {
19.109 @@ -352,11 +379,11 @@
19.110 }
19.111
19.112 public static <Model> Model bindTo(Model model, BrwsrCtx c) {
19.113 - FromJSON<?> from = findFrom(model.getClass());
19.114 + Proto.Type<Model> from = (Proto.Type<Model>) findType(model.getClass());
19.115 if (from == null) {
19.116 throw new IllegalArgumentException();
19.117 }
19.118 - return (Model) from.cloneTo(model, c);
19.119 + return PropertyBindingAccessor.clone(from, model, c);
19.120 }
19.121
19.122 public static <T> T readStream(BrwsrCtx c, Class<T> modelClazz, InputStream data)
19.123 @@ -372,11 +399,11 @@
19.124 return modelClazz.cast(data.toString());
19.125 }
19.126 for (int i = 0; i < 2; i++) {
19.127 - FromJSON<?> from = froms.get(modelClazz);
19.128 + Proto.Type<?> from = modelTypes.get(modelClazz);
19.129 if (from == null) {
19.130 initClass(modelClazz);
19.131 } else {
19.132 - return modelClazz.cast(from.read(c, data));
19.133 + return modelClazz.cast(PropertyBindingAccessor.readFrom(from, c, data));
19.134 }
19.135 }
19.136 throw new NullPointerException();
20.1 --- a/json/src/main/java/org/netbeans/html/json/impl/JSONList.java Mon Dec 16 18:08:40 2013 +0100
20.2 +++ b/json/src/main/java/org/netbeans/html/json/impl/JSONList.java Mon Jan 06 09:44:07 2014 +0100
20.3 @@ -44,37 +44,25 @@
20.4
20.5 import java.lang.reflect.Array;
20.6 import java.util.ArrayList;
20.7 -import java.util.Arrays;
20.8 import java.util.Collection;
20.9 import java.util.Iterator;
20.10 -import java.util.List;
20.11 -import net.java.html.BrwsrCtx;
20.12 +import org.apidesign.html.json.spi.Proto;
20.13
20.14 /**
20.15 *
20.16 * @author Jaroslav Tulach <jtulach@netbeans.org>
20.17 */
20.18 public final class JSONList<T> extends ArrayList<T> {
20.19 + private final Proto proto;
20.20 private final String name;
20.21 private final String[] deps;
20.22 - private Bindings[] model;
20.23 - private Runnable onchange;
20.24 + private final int index;
20.25
20.26 - public JSONList(Bindings[] model, String name, String... deps) {
20.27 - assert model.length == 1;
20.28 - this.model = model;
20.29 + public JSONList(Proto proto, String name, int changeIndex, String... deps) {
20.30 + this.proto = proto;
20.31 this.name = name;
20.32 this.deps = deps;
20.33 - }
20.34 -
20.35 - public void init(T... values) {
20.36 - if (values == null || values.length == 0) {
20.37 - return;
20.38 - }
20.39 - if (this.model[0] != null || !isEmpty()) {
20.40 - throw new IllegalStateException();
20.41 - }
20.42 - super.addAll(Arrays.asList(values));
20.43 + this.index = changeIndex;
20.44 }
20.45
20.46 public void init(Object values) {
20.47 @@ -82,23 +70,22 @@
20.48 if (values == null || (len = Array.getLength(values)) == 0) {
20.49 return;
20.50 }
20.51 - if (this.model[0] != null || !isEmpty()) {
20.52 - throw new IllegalStateException();
20.53 - }
20.54 for (int i = 0; i < len; i++) {
20.55 Object data = Array.get(values, i);
20.56 super.add((T)data);
20.57 }
20.58 }
20.59 + public static <T> void init(Collection<T> to, Object values) {
20.60 + int len;
20.61 + if (values == null || (len = Array.getLength(values)) == 0) {
20.62 + return;
20.63 + }
20.64 + for (int i = 0; i < len; i++) {
20.65 + Object data = Array.get(values, i);
20.66 + to.add((T)data);
20.67 + }
20.68 + }
20.69
20.70 - public JSONList<T> onChange(Runnable r) {
20.71 - if (this.onchange != null) {
20.72 - throw new IllegalStateException();
20.73 - }
20.74 - this.onchange = r;
20.75 - return this;
20.76 - }
20.77 -
20.78 @Override
20.79 public boolean add(T e) {
20.80 boolean ret = super.add(e);
20.81 @@ -187,29 +174,14 @@
20.82 }
20.83
20.84 private void notifyChange() {
20.85 - Bindings m = model[0];
20.86 + Bindings m = PropertyBindingAccessor.getBindings(proto, false);
20.87 if (m != null) {
20.88 m.valueHasMutated(name);
20.89 for (String dependant : deps) {
20.90 m.valueHasMutated(dependant);
20.91 }
20.92 - Runnable r = onchange;
20.93 - if (r != null) {
20.94 - r.run();
20.95 - }
20.96 - }
20.97 - }
20.98 -
20.99 - public void cloneAll(BrwsrCtx c, Collection<T> other) {
20.100 - Boolean isModel = null;
20.101 - for (T t : other) {
20.102 - if (isModel == null) {
20.103 - isModel = JSON.isModel(t.getClass());
20.104 - }
20.105 - if (isModel) {
20.106 - add(JSON.bindTo(t, c));
20.107 - } else {
20.108 - add(t);
20.109 + if (index >= 0) {
20.110 + PropertyBindingAccessor.notifyProtoChange(proto, index);
20.111 }
20.112 }
20.113 }
20.114 @@ -222,7 +194,7 @@
20.115 static final Object koData(Collection<?> c, Bindings m) {
20.116 Object[] arr = c.toArray(new Object[c.size()]);
20.117 for (int i = 0; i < arr.length; i++) {
20.118 - Object r = WrapperObject.find(arr[i], m);
20.119 + Object r = JSON.find(arr[i], m);
20.120 if (r != null) {
20.121 arr[i] = r;
20.122 }
20.123 @@ -231,6 +203,6 @@
20.124 }
20.125
20.126 final Object koData() {
20.127 - return koData(this, model[0]);
20.128 + return koData(this, PropertyBindingAccessor.getBindings(proto, true));
20.129 }
20.130 }
21.1 --- a/json/src/main/java/org/netbeans/html/json/impl/ModelProcessor.java Mon Dec 16 18:08:40 2013 +0100
21.2 +++ b/json/src/main/java/org/netbeans/html/json/impl/ModelProcessor.java Mon Jan 06 09:44:07 2014 +0100
21.3 @@ -183,6 +183,7 @@
21.4 models.put(e, className);
21.5 try {
21.6 StringWriter body = new StringWriter();
21.7 + StringBuilder onReceiveType = new StringBuilder();
21.8 List<String> propsGetSet = new ArrayList<String>();
21.9 List<String> functions = new ArrayList<String>();
21.10 Map<String, Collection<String>> propsDeps = new HashMap<String, Collection<String>>();
21.11 @@ -195,13 +196,13 @@
21.12 if (!generateOnChange(e, propsDeps, props, className, functionDeps)) {
21.13 ok = false;
21.14 }
21.15 - if (!generateProperties(e, body, props, propsGetSet, propsDeps, functionDeps)) {
21.16 + if (!generateProperties(e, body, className, props, propsGetSet, propsDeps, functionDeps)) {
21.17 ok = false;
21.18 }
21.19 if (!generateFunctions(e, body, className, e.getEnclosedElements(), functions)) {
21.20 ok = false;
21.21 }
21.22 - if (!generateReceive(e, body, className, e.getEnclosedElements(), functions)) {
21.23 + if (!generateReceive(e, body, className, e.getEnclosedElements(), onReceiveType)) {
21.24 ok = false;
21.25 }
21.26 if (!generateOperation(e, body, className, e.getEnclosedElements())) {
21.27 @@ -213,26 +214,49 @@
21.28 w.append("package " + pkg + ";\n");
21.29 w.append("import net.java.html.json.*;\n");
21.30 w.append("public final class ").append(className).append(" implements Cloneable {\n");
21.31 - w.append(" private boolean locked;\n");
21.32 - w.append(" private net.java.html.BrwsrCtx context;\n");
21.33 - w.append(" private org.netbeans.html.json.impl.Bindings[] ko = { null };\n");
21.34 + w.append(" private static final Html4JavaType TYPE = new Html4JavaType();\n");
21.35 + w.append(" private final org.apidesign.html.json.spi.Proto proto;\n");
21.36 w.append(body.toString());
21.37 w.append(" private static Class<" + inPckName(e) + "> modelFor() { return null; }\n");
21.38 w.append(" private ").append(className).append("(net.java.html.BrwsrCtx context) {\n");
21.39 - w.append(" this.context = context;\n");
21.40 + w.append(" this.proto = TYPE.createProto(this, context);\n");
21.41 + for (Prprt p : props) {
21.42 + if (p.array()) {
21.43 + final String tn = typeName(e, p);
21.44 + String[] gs = toGetSet(p.name(), tn, p.array());
21.45 + w.write(" this.prop_" + p.name() + " = proto.createList(\""
21.46 + + p.name() + "\"");
21.47 + if (functionDeps.containsKey(p.name())) {
21.48 + int index = Arrays.asList(functionDeps.keySet().toArray()).indexOf(p.name());
21.49 + w.write(", " + index);
21.50 + } else {
21.51 + w.write(", -1");
21.52 + }
21.53 + Collection<String> dependants = propsDeps.get(p.name());
21.54 + if (dependants != null) {
21.55 + for (String depProp : dependants) {
21.56 + w.write(", ");
21.57 + w.write('\"');
21.58 + w.write(depProp);
21.59 + w.write('\"');
21.60 + }
21.61 + }
21.62 + w.write(")");
21.63 + w.write(";\n");
21.64 + }
21.65 + }
21.66 w.append(" };\n");
21.67 w.append(" public ").append(className).append("() {\n");
21.68 w.append(" this(net.java.html.BrwsrCtx.findDefault(").append(className).append(".class));\n");
21.69 for (Prprt p : props) {
21.70 - if (p.array()) {
21.71 - continue;
21.72 - }
21.73 - boolean[] isModel = {false};
21.74 - boolean[] isEnum = {false};
21.75 - boolean isPrimitive[] = {false};
21.76 - String tn = checkType(p, isModel, isEnum, isPrimitive);
21.77 - if (isModel[0]) {
21.78 - w.write(" prop_" + p.name() + " = new " + tn + "();\n");
21.79 + if (!p.array()) {
21.80 + boolean[] isModel = {false};
21.81 + boolean[] isEnum = {false};
21.82 + boolean isPrimitive[] = {false};
21.83 + String tn = checkType(p, isModel, isEnum, isPrimitive);
21.84 + if (isModel[0]) {
21.85 + w.write(" prop_" + p.name() + " = new " + tn + "();\n");
21.86 + }
21.87 }
21.88 }
21.89 w.append(" };\n");
21.90 @@ -272,38 +296,28 @@
21.91 w.write(" this.prop_" + p.name() + " = " + p.name() + ";\n");
21.92 }
21.93 if (firstArray != null) {
21.94 - w.write(" this.prop_" + firstArray.name() + ".init(" + firstArray.name() + ");\n");
21.95 + w.write(" proto.initTo(this.prop_" + firstArray.name() + ", " + firstArray.name() + ");\n");
21.96 }
21.97 w.append(" };\n");
21.98 }
21.99 - w.append(" private org.netbeans.html.json.impl.Bindings intKnckt() {\n");
21.100 - w.append(" if (ko[0] != null) return ko[0];\n");
21.101 - w.append(" ko[0] = org.netbeans.html.json.impl.Bindings.apply(context, this);\n");
21.102 + w.append(" private static class Html4JavaType extends org.apidesign.html.json.spi.Proto.Type<").append(className).append("> {\n");
21.103 + w.append(" private Html4JavaType() {\n super(").append(className).append(".class, ").
21.104 + append(inPckName(e)).append(".class, " + (propsGetSet.size() / 5) + ", "
21.105 + + (functions.size() / 2) + ");\n");
21.106 {
21.107 - w.append(" org.apidesign.html.json.spi.PropertyBinding[] propArr = {\n");
21.108 for (int i = 0; i < propsGetSet.size(); i += 5) {
21.109 - w.append(" ko[0].registerProperty(\"").append(propsGetSet.get(i)).append("\", this, new P(");
21.110 - w.append((i / 5) + "), " + (propsGetSet.get(i + 2) == null) + "),\n");
21.111 + w.append(" registerProperty(\"").append(propsGetSet.get(i)).append("\", ");
21.112 + w.append((i / 5) + ", " + (propsGetSet.get(i + 2) == null) + ");\n");
21.113 }
21.114 - w.append(" };\n");
21.115 }
21.116 {
21.117 - w.append(" org.apidesign.html.json.spi.FunctionBinding[] funcArr = {\n");
21.118 for (int i = 0; i < functions.size(); i += 2) {
21.119 - w.append(" ko[0].registerFunction(\"").append(functions.get(i)).append("\", this, new P(");
21.120 - w.append((i / 2) + ")),\n");
21.121 + w.append(" registerFunction(\"").append(functions.get(i)).append("\", ");
21.122 + w.append((i / 2) + ");\n");
21.123 }
21.124 - w.append(" };\n");
21.125 }
21.126 - w.append(" ko[0].finish(this, propArr, funcArr);\n");
21.127 - w.append(" return ko[0];\n");
21.128 - w.append(" };\n");
21.129 - w.append(" private static final class P implements org.netbeans.html.json.impl.SetAndGet<" + className + ">,\n");
21.130 - w.append(" org.netbeans.html.json.impl.Callback<" + className + ">,\n");
21.131 - w.append(" org.netbeans.html.json.impl.FromJSON<" + className + "> {\n");
21.132 - w.append(" private final int type;\n");
21.133 - w.append(" P(int t) { type = t; };\n");
21.134 - w.append(" public void setValue(" + className + " data, Object value) {\n");
21.135 + w.append(" }\n");
21.136 + w.append(" @Override public void setValue(" + className + " data, int type, Object value) {\n");
21.137 w.append(" switch (type) {\n");
21.138 for (int i = 0; i < propsGetSet.size(); i += 5) {
21.139 final String set = propsGetSet.get(i + 2);
21.140 @@ -313,12 +327,12 @@
21.141 tn = btn;
21.142 }
21.143 if (set != null) {
21.144 - w.append(" case " + (i / 5) + ": data." + strip(set) + "(org.netbeans.html.json.impl.JSON.extractValue(" + tn + ".class, value)); return;\n");
21.145 + w.append(" case " + (i / 5) + ": data." + strip(set) + "(TYPE.extractValue(" + tn + ".class, value)); return;\n");
21.146 }
21.147 }
21.148 w.append(" }\n");
21.149 w.append(" }\n");
21.150 - w.append(" public Object getValue(" + className + " data) {\n");
21.151 + w.append(" @Override public Object getValue(" + className + " data, int type) {\n");
21.152 w.append(" switch (type) {\n");
21.153 for (int i = 0; i < propsGetSet.size(); i += 5) {
21.154 final String get = propsGetSet.get(i + 1);
21.155 @@ -329,7 +343,7 @@
21.156 w.append(" }\n");
21.157 w.append(" throw new UnsupportedOperationException();\n");
21.158 w.append(" }\n");
21.159 - w.append(" public void call(" + className + " model, Object data, Object ev) {\n");
21.160 + w.append(" @Override public void call(" + className + " model, int type, Object data, Object ev) {\n");
21.161 w.append(" switch (type) {\n");
21.162 for (int i = 0; i < functions.size(); i += 2) {
21.163 final String name = functions.get(i);
21.164 @@ -338,13 +352,33 @@
21.165 w.append(" }\n");
21.166 w.append(" throw new UnsupportedOperationException();\n");
21.167 w.append(" }\n");
21.168 - w.append(" public Class<" + className + "> factoryFor() { return " + className + ".class; }\n");
21.169 - w.append(" public " + className + " read(net.java.html.BrwsrCtx c, Object json) { return new " + className + "(c, json); }\n");
21.170 - w.append(" public " + className + " cloneTo(Object o, net.java.html.BrwsrCtx c) { return ((" + className + ")o).clone(c); }\n");
21.171 + w.append(" @Override public org.apidesign.html.json.spi.Proto protoFor(Object obj) {\n");
21.172 + w.append(" return ((" + className + ")obj).proto;");
21.173 + w.append(" }\n");
21.174 + w.append(" @Override public void onChange(" + className + " model, int type) {\n");
21.175 + w.append(" switch (type) {\n");
21.176 + {
21.177 + String[] arr = functionDeps.keySet().toArray(new String[0]);
21.178 + for (int i = 0; i < arr.length; i++) {
21.179 + Collection<String> onChange = functionDeps.get(arr[i]);
21.180 + if (onChange != null) {
21.181 + w.append(" case " + i + ":\n");
21.182 + for (String call : onChange) {
21.183 + w.append(" ").append(call).append("\n");
21.184 + }
21.185 + w.write(" return;\n");
21.186 + }
21.187 + }
21.188 + }
21.189 + w.append(" }\n");
21.190 + w.append(" throw new UnsupportedOperationException();\n");
21.191 + w.append(" }\n");
21.192 + w.append(onReceiveType);
21.193 + w.append(" @Override public " + className + " read(net.java.html.BrwsrCtx c, Object json) { return new " + className + "(c, json); }\n");
21.194 + w.append(" @Override public " + className + " cloneTo(" + className + " o, net.java.html.BrwsrCtx c) { return o.clone(c); }\n");
21.195 w.append(" }\n");
21.196 - w.append(" static { org.netbeans.html.json.impl.JSON.register(new P(0)); }\n");
21.197 w.append(" private ").append(className).append("(net.java.html.BrwsrCtx c, Object json) {\n");
21.198 - w.append(" this.context = c;\n");
21.199 + w.append(" this(c);\n");
21.200 int values = 0;
21.201 for (int i = 0; i < propsGetSet.size(); i += 5) {
21.202 Prprt p = findPrprt(props, propsGetSet.get(i));
21.203 @@ -354,7 +388,7 @@
21.204 values++;
21.205 }
21.206 w.append(" Object[] ret = new Object[" + values + "];\n");
21.207 - w.append(" org.netbeans.html.json.impl.JSON.extract(context, json, new String[] {\n");
21.208 + w.append(" proto.extract(json, new String[] {\n");
21.209 for (int i = 0; i < propsGetSet.size(); i += 5) {
21.210 Prprt p = findPrprt(props, propsGetSet.get(i));
21.211 if (p == null) {
21.212 @@ -377,15 +411,15 @@
21.213 w.append(" if (ret[" + cnt + "] instanceof Object[]) {\n");
21.214 w.append(" for (Object e : ((Object[])ret[" + cnt + "])) {\n");
21.215 if (isModel[0]) {
21.216 - w.append(" this.prop_").append(pn).append(".add(org.netbeans.html.json.impl.JSON.read");
21.217 - w.append("(c, " + type + ".class, e));\n");
21.218 + w.append(" this.prop_").append(pn).append(".add(proto.read");
21.219 + w.append("(" + type + ".class, e));\n");
21.220 } else if (isEnum[0]) {
21.221 w.append(" this.prop_").append(pn);
21.222 w.append(".add(e == null ? null : ");
21.223 - w.append(type).append(".valueOf(org.netbeans.html.json.impl.JSON.stringValue(e)));\n");
21.224 + w.append(type).append(".valueOf(TYPE.stringValue(e)));\n");
21.225 } else {
21.226 if (isPrimitive(type)) {
21.227 - w.append(" this.prop_").append(pn).append(".add(org.netbeans.html.json.impl.JSON.numberValue(e).");
21.228 + w.append(" this.prop_").append(pn).append(".add(TYPE.numberValue(e).");
21.229 w.append(type).append("Value());\n");
21.230 } else {
21.231 w.append(" this.prop_").append(pn).append(".add((");
21.232 @@ -399,7 +433,7 @@
21.233 w.append(" try {\n");
21.234 w.append(" this.prop_").append(pn);
21.235 w.append(" = ret[" + cnt + "] == null ? null : ");
21.236 - w.append(type).append(".valueOf(org.netbeans.html.json.impl.JSON.stringValue(ret[" + cnt + "]));\n");
21.237 + w.append(type).append(".valueOf(TYPE.stringValue(ret[" + cnt + "]));\n");
21.238 w.append(" } catch (IllegalArgumentException ex) {\n");
21.239 w.append(" ex.printStackTrace();\n");
21.240 w.append(" }\n");
21.241 @@ -407,17 +441,17 @@
21.242 w.append(" this.prop_").append(pn);
21.243 w.append(" = ret[" + cnt + "] == null ? ");
21.244 if ("char".equals(type)) {
21.245 - w.append("0 : (org.netbeans.html.json.impl.JSON.charValue(");
21.246 + w.append("0 : (TYPE.charValue(");
21.247 } else if ("boolean".equals(type)) {
21.248 - w.append("false : (org.netbeans.html.json.impl.JSON.boolValue(");
21.249 + w.append("false : (TYPE.boolValue(");
21.250 } else {
21.251 - w.append("0 : (org.netbeans.html.json.impl.JSON.numberValue(");
21.252 + w.append("0 : (TYPE.numberValue(");
21.253 }
21.254 w.append("ret[" + cnt + "])).");
21.255 w.append(type).append("Value();\n");
21.256 } else if (isModel[0]) {
21.257 - w.append(" this.prop_").append(pn).append(" = org.netbeans.html.json.impl.JSON.read");
21.258 - w.append("(c, " + type + ".class, ");
21.259 + w.append(" this.prop_").append(pn).append(" = proto.read");
21.260 + w.append("(" + type + ".class, ");
21.261 w.append("ret[" + cnt + "]);\n");
21.262 }else {
21.263 w.append(" this.prop_").append(pn);
21.264 @@ -427,7 +461,7 @@
21.265 }
21.266 cnt++;
21.267 }
21.268 - w.append(" };\n");
21.269 + w.append(" }\n");
21.270 writeToString(props, w);
21.271 writeClone(className, props, w);
21.272 w.write(" /** Activates this model instance in the current {@link \n"
21.273 @@ -438,26 +472,22 @@
21.274 + "*/\n"
21.275 );
21.276 w.write(" public " + className + " applyBindings() {\n");
21.277 - w.write(" intKnckt().applyBindings();\n");
21.278 + w.write(" proto.applyBindings();\n");
21.279 w.write(" return this;\n");
21.280 w.write(" }\n");
21.281 w.write(" public boolean equals(Object o) {\n");
21.282 w.write(" if (o == this) return true;\n");
21.283 - w.write(" if (o instanceof org.netbeans.html.json.impl.WrapperObject) {\n");
21.284 - w.write(" ((org.netbeans.html.json.impl.WrapperObject)o).setRealObject(intKnckt().koData());\n");
21.285 - w.write(" return false;\n");
21.286 - w.write(" }\n");
21.287 w.write(" if (!(o instanceof " + className + ")) return false;\n");
21.288 w.write(" " + className + " p = (" + className + ")o;\n");
21.289 for (Prprt p : props) {
21.290 - w.write(" if (!org.netbeans.html.json.impl.JSON.isSame(prop_" + p.name() + ", p.prop_" + p.name() + ")) return false;\n");
21.291 + w.write(" if (!TYPE.isSame(prop_" + p.name() + ", p.prop_" + p.name() + ")) return false;\n");
21.292 }
21.293 w.write(" return true;\n");
21.294 w.write(" }\n");
21.295 w.write(" public int hashCode() {\n");
21.296 w.write(" int h = " + className + ".class.getName().hashCode();\n");
21.297 for (Prprt p : props) {
21.298 - w.write(" h = org.netbeans.html.json.impl.JSON.hashPlus(prop_" + p.name() + ", h);\n");
21.299 + w.write(" h = TYPE.hashPlus(prop_" + p.name() + ", h);\n");
21.300 }
21.301 w.write(" return h;\n");
21.302 w.write(" }\n");
21.303 @@ -474,7 +504,7 @@
21.304
21.305 private boolean generateProperties(
21.306 Element where,
21.307 - Writer w, Prprt[] properties,
21.308 + Writer w, String className, Prprt[] properties,
21.309 Collection<String> props,
21.310 Map<String,Collection<String>> deps,
21.311 Map<String,Collection<String>> functionDeps
21.312 @@ -487,57 +517,34 @@
21.313 String castTo;
21.314
21.315 if (p.array()) {
21.316 - w.write(" private org.netbeans.html.json.impl.JSONList<" + tn + "> prop_" + p.name() + " = new org.netbeans.html.json.impl.JSONList<" + tn + ">(ko, \""
21.317 - + p.name() + "\"");
21.318 - Collection<String> dependants = deps.get(p.name());
21.319 - if (dependants != null) {
21.320 - for (String depProp : dependants) {
21.321 - w.write(", ");
21.322 - w.write('\"');
21.323 - w.write(depProp);
21.324 - w.write('\"');
21.325 - }
21.326 - }
21.327 - w.write(")");
21.328 -
21.329 - dependants = functionDeps.get(p.name());
21.330 - if (dependants != null) {
21.331 - w.write(".onChange(new Runnable() { public void run() {\n");
21.332 - for (String call : dependants) {
21.333 - w.append(" ").append(call);
21.334 - }
21.335 - w.write(" }})");
21.336 - }
21.337 - w.write(";\n");
21.338 + w.write(" private final java.util.List<" + tn + "> prop_" + p.name() + ";\n");
21.339
21.340 castTo = "java.util.List";
21.341 w.write(" public java.util.List<" + tn + "> " + gs[0] + "() {\n");
21.342 - w.write(" if (locked) throw new IllegalStateException();\n");
21.343 + w.write(" proto.verifyUnlocked();\n");
21.344 w.write(" return prop_" + p.name() + ";\n");
21.345 w.write(" }\n");
21.346 } else {
21.347 castTo = tn;
21.348 w.write(" private " + tn + " prop_" + p.name() + ";\n");
21.349 w.write(" public " + tn + " " + gs[0] + "() {\n");
21.350 - w.write(" if (locked) throw new IllegalStateException();\n");
21.351 + w.write(" proto.verifyUnlocked();\n");
21.352 w.write(" return prop_" + p.name() + ";\n");
21.353 w.write(" }\n");
21.354 w.write(" public void " + gs[1] + "(" + tn + " v) {\n");
21.355 - w.write(" if (locked) throw new IllegalStateException();\n");
21.356 - w.write(" if (org.netbeans.html.json.impl.JSON.isSame(prop_" + p.name() + ", v)) return;\n");
21.357 + w.write(" proto.verifyUnlocked();\n");
21.358 + w.write(" if (TYPE.isSame(prop_" + p.name() + ", v)) return;\n");
21.359 w.write(" prop_" + p.name() + " = v;\n");
21.360 - w.write(" org.netbeans.html.json.impl.Bindings b = ko[0];\n");
21.361 - w.write(" if (b != null) {\n");
21.362 - w.write(" b.valueHasMutated(\"" + p.name() + "\");\n");
21.363 + w.write(" proto.valueHasMutated(\"" + p.name() + "\");\n");
21.364 Collection<String> dependants = deps.get(p.name());
21.365 if (dependants != null) {
21.366 for (String depProp : dependants) {
21.367 - w.write(" b.valueHasMutated(\"" + depProp + "\");\n");
21.368 + w.write(" proto.valueHasMutated(\"" + depProp + "\");\n");
21.369 }
21.370 }
21.371 - w.write(" }\n");
21.372 dependants = functionDeps.get(p.name());
21.373 if (dependants != null) {
21.374 + w.append(className).append(" model = ").append(className).append(".this;\n");
21.375 for (String call : dependants) {
21.376 w.append(" ").append(call);
21.377 }
21.378 @@ -609,7 +616,6 @@
21.379 String[] gs = toGetSet(sn, tn, array);
21.380
21.381 w.write(" public " + tn + " " + gs[0] + "() {\n");
21.382 - w.write(" if (locked) throw new IllegalStateException();\n");
21.383 int arg = 0;
21.384 for (VariableElement pe : ee.getParameters()) {
21.385 final String dn = pe.getSimpleName().toString();
21.386 @@ -631,7 +637,7 @@
21.387 depends.add(sn);
21.388 }
21.389 w.write(" try {\n");
21.390 - w.write(" locked = true;\n");
21.391 + w.write(" proto.acquireLock();\n");
21.392 w.write(" return " + fqn(ee.getEnclosingElement().asType(), ee) + '.' + e.getSimpleName() + "(");
21.393 String sep = "";
21.394 for (int i = 1; i <= arg; i++) {
21.395 @@ -641,7 +647,7 @@
21.396 }
21.397 w.write(");\n");
21.398 w.write(" } finally {\n");
21.399 - w.write(" locked = false;\n");
21.400 + w.write(" proto.releaseLock();\n");
21.401 w.write(" }\n");
21.402 w.write(" }\n");
21.403
21.404 @@ -908,7 +914,7 @@
21.405 }
21.406 }
21.407 body.append(") {\n");
21.408 - body.append(" org.netbeans.html.json.impl.JSON.runInBrowser(this.context, new Runnable() { public void run() {\n");
21.409 + body.append(" proto.runInBrowser(new Runnable() { public void run() {\n");
21.410 body.append(" ").append(clazz.getSimpleName()).append(".").append(m.getSimpleName()).append("(");
21.411 body.append(className).append(".this");
21.412 for (String s : args) {
21.413 @@ -926,8 +932,11 @@
21.414
21.415 private boolean generateReceive(
21.416 Element clazz, StringWriter body, String className,
21.417 - List<? extends Element> enclosedElements, List<String> functions
21.418 + List<? extends Element> enclosedElements, StringBuilder inType
21.419 ) {
21.420 + inType.append(" @Override public void onMessage(").append(className).append(" model, int index, int type, Object data) {\n");
21.421 + inType.append(" switch (index) {\n");
21.422 + int index = 0;
21.423 for (Element m : enclosedElements) {
21.424 if (m.getKind() != ElementKind.METHOD) {
21.425 continue;
21.426 @@ -975,7 +984,7 @@
21.427 simpleName = type.toString();
21.428 }
21.429 if (simpleName.toString().equals(className)) {
21.430 - args.add(className + ".this");
21.431 + args.add("model");
21.432 } else if (isModel(ve.asType())) {
21.433 modelType = ve.asType();
21.434 } else if (ve.asType().getKind() == TypeKind.ARRAY) {
21.435 @@ -1038,47 +1047,49 @@
21.436 body.append(") {\n");
21.437 boolean webSocket = onR.method().equals("WebSocket");
21.438 if (webSocket) {
21.439 - if (generateWSReceiveBody(body, onR, e, clazz, className, expectsList, modelClass, n, args, urlBefore, jsonpVarName, urlAfter, dataMirror)) {
21.440 + if (generateWSReceiveBody(index++, body, inType, onR, e, clazz, className, expectsList, modelClass, n, args, urlBefore, jsonpVarName, urlAfter, dataMirror)) {
21.441 return false;
21.442 }
21.443 body.append(" }\n");
21.444 - body.append(" private org.netbeans.html.json.impl.JSON.WS ws_" + e.getSimpleName() + ";\n");
21.445 + body.append(" private Object ws_" + e.getSimpleName() + ";\n");
21.446 } else {
21.447 - if (generateJSONReceiveBody(body, onR, e, clazz, className, expectsList, modelClass, n, args, urlBefore, jsonpVarName, urlAfter, dataMirror)) {
21.448 + if (generateJSONReceiveBody(index++, body, inType, onR, e, clazz, className, expectsList, modelClass, n, args, urlBefore, jsonpVarName, urlAfter, dataMirror)) {
21.449 return false;
21.450 }
21.451 body.append(" }\n");
21.452 }
21.453 }
21.454 + inType.append(" }\n");
21.455 + inType.append(" throw new UnsupportedOperationException(\"index: \" + index + \" type: \" + type);\n");
21.456 + inType.append(" }\n");
21.457 return true;
21.458 }
21.459
21.460 - 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) {
21.461 + private boolean generateJSONReceiveBody(int index, StringWriter method, StringBuilder body, OnReceive onR, ExecutableElement e, Element clazz, String className, boolean expectsList, String modelClass, String n, List<String> args, StringBuilder urlBefore, String jsonpVarName, StringBuilder urlAfter, String dataMirror) {
21.462 body.append(
21.463 - " class ProcessResult extends org.netbeans.html.json.impl.RcvrJSON {\n" +
21.464 - " @Override\n" +
21.465 - " public void onError(org.netbeans.html.json.impl.RcvrJSON.MsgEvnt ev) {\n" +
21.466 - " Exception value = ev.getException();\n"
21.467 + " case " + index + ": {\n" +
21.468 + " if (type == 2) { /* on error */\n" +
21.469 + " Exception ex = (Exception)data;\n"
21.470 );
21.471 if (onR.onError().isEmpty()) {
21.472 body.append(
21.473 - " value.printStackTrace();\n"
21.474 + " ex.printStackTrace();\n"
21.475 );
21.476 } else {
21.477 if (!findOnError(e, ((TypeElement)clazz), onR.onError(), className)) {
21.478 return true;
21.479 }
21.480 body.append(" ").append(clazz.getSimpleName()).append(".").append(onR.onError()).append("(");
21.481 - body.append(className).append(".this, value);\n");
21.482 + body.append("model, ex);\n");
21.483 }
21.484 body.append(
21.485 - " }\n" +
21.486 - " @Override\n" +
21.487 - " public void onMessage(org.netbeans.html.json.impl.RcvrJSON.MsgEvnt ev) {\n"
21.488 + " return;\n" +
21.489 + " } else if (type == 1) {\n" +
21.490 + " Object[] ev = (Object[])data;\n"
21.491 );
21.492 if (expectsList) {
21.493 body.append(
21.494 - " " + modelClass + "[] arr = new " + modelClass + "[ev.dataSize()];\n"
21.495 + " " + modelClass + "[] arr = new " + modelClass + "[ev.length];\n"
21.496 );
21.497 } else {
21.498 body.append(
21.499 @@ -1086,8 +1097,8 @@
21.500 );
21.501 }
21.502 body.append(
21.503 - " ev.dataRead(context, " + modelClass + ".class, arr);\n"
21.504 - );
21.505 + " TYPE.copyJSON(model.proto.getContext(), ev, " + modelClass + ".class, arr);\n"
21.506 + );
21.507 {
21.508 body.append(" ").append(clazz.getSimpleName()).append(".").append(n).append("(");
21.509 String sep = "";
21.510 @@ -1099,38 +1110,36 @@
21.511 body.append(");\n");
21.512 }
21.513 body.append(
21.514 + " return;\n" +
21.515 " }\n" +
21.516 " }\n"
21.517 );
21.518 - body.append(" ProcessResult pr = new ProcessResult();\n");
21.519 - body.append(" org.netbeans.html.json.impl.JSON.loadJSON(context, pr,\n ");
21.520 - body.append(urlBefore).append(", ");
21.521 + method.append(" proto.loadJSON(" + index + ",\n ");
21.522 + method.append(urlBefore).append(", ");
21.523 if (jsonpVarName != null) {
21.524 - body.append(urlAfter);
21.525 + method.append(urlAfter);
21.526 } else {
21.527 - body.append("null");
21.528 + method.append("null");
21.529 }
21.530 if (!"GET".equals(onR.method()) || dataMirror != null) {
21.531 - body.append(", \"").append(onR.method()).append('"');
21.532 + method.append(", \"").append(onR.method()).append('"');
21.533 if (dataMirror != null) {
21.534 - body.append(", data");
21.535 + method.append(", data");
21.536 } else {
21.537 - body.append(", null");
21.538 + method.append(", null");
21.539 }
21.540 } else {
21.541 - body.append(", null, null");
21.542 + method.append(", null, null");
21.543 }
21.544 - body.append(");\n");
21.545 + method.append(");\n");
21.546 return false;
21.547 }
21.548
21.549 - 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) {
21.550 + private boolean generateWSReceiveBody(int index, StringWriter method, StringBuilder body, OnReceive onR, ExecutableElement e, Element clazz, String className, boolean expectsList, String modelClass, String n, List<String> args, StringBuilder urlBefore, String jsonpVarName, StringBuilder urlAfter, String dataMirror) {
21.551 body.append(
21.552 - " class ProcessResult extends org.netbeans.html.json.impl.RcvrJSON {\n" +
21.553 - " @Override\n" +
21.554 - " public void onOpen(org.netbeans.html.json.impl.RcvrJSON.MsgEvnt ev) {\n"
21.555 - );
21.556 - body.append(" ").append(clazz.getSimpleName()).append(".").append(n).append("(");
21.557 + " case " + index + ": {\n" +
21.558 + " if (type == 0) { /* on open */\n" +
21.559 + " ").append(clazz.getSimpleName()).append(".").append(n).append("(");
21.560 {
21.561 String sep = "";
21.562 for (String arg : args) {
21.563 @@ -1145,10 +1154,9 @@
21.564 }
21.565 body.append(");\n");
21.566 body.append(
21.567 - " }\n" +
21.568 - " @Override\n" +
21.569 - " public void onError(org.netbeans.html.json.impl.RcvrJSON.MsgEvnt ev) {\n" +
21.570 - " Exception value = ev.getException();\n"
21.571 + " return;\n" +
21.572 + " } else if (type == 2) { /* on error */\n" +
21.573 + " Exception value = (Exception)data;\n"
21.574 );
21.575 if (onR.onError().isEmpty()) {
21.576 body.append(
21.577 @@ -1159,16 +1167,16 @@
21.578 return true;
21.579 }
21.580 body.append(" ").append(clazz.getSimpleName()).append(".").append(onR.onError()).append("(");
21.581 - body.append(className).append(".this, value);\n");
21.582 + body.append("model, value);\n");
21.583 }
21.584 body.append(
21.585 - " }\n" +
21.586 - " @Override\n" +
21.587 - " public void onMessage(org.netbeans.html.json.impl.RcvrJSON.MsgEvnt ev) {\n"
21.588 + " return;\n" +
21.589 + " } else if (type == 1) {\n" +
21.590 + " Object[] ev = (Object[])data;\n"
21.591 );
21.592 if (expectsList) {
21.593 body.append(
21.594 - " " + modelClass + "[] arr = new " + modelClass + "[ev.dataSize()];\n"
21.595 + " " + modelClass + "[] arr = new " + modelClass + "[ev.length];\n"
21.596 );
21.597 } else {
21.598 body.append(
21.599 @@ -1176,8 +1184,8 @@
21.600 );
21.601 }
21.602 body.append(
21.603 - " ev.dataRead(context, " + modelClass + ".class, arr);\n"
21.604 - );
21.605 + " TYPE.copyJSON(model.proto.getContext(), ev, " + modelClass + ".class, arr);\n"
21.606 + );
21.607 {
21.608 body.append(" ").append(clazz.getSimpleName()).append(".").append(n).append("(");
21.609 String sep = "";
21.610 @@ -1189,28 +1197,27 @@
21.611 body.append(");\n");
21.612 }
21.613 body.append(
21.614 - " }\n"
21.615 + " return;\n" +
21.616 + " }"
21.617 );
21.618 if (!onR.onError().isEmpty()) {
21.619 + body.append(" else if (type == 3) { /* on close */\n");
21.620 + body.append(" ").append(clazz.getSimpleName()).append(".").append(onR.onError()).append("(");
21.621 + body.append("model, null);\n");
21.622 body.append(
21.623 - " @Override\n"
21.624 - + " public void onClose(org.netbeans.html.json.impl.RcvrJSON.MsgEvnt ev) {\n"
21.625 - );
21.626 - body.append(" ").append(clazz.getSimpleName()).append(".").append(onR.onError()).append("(");
21.627 - body.append(className).append(".this, null);\n");
21.628 - body.append(
21.629 - " }\n"
21.630 + " return;" +
21.631 + " }"
21.632 );
21.633 }
21.634 + body.append("\n");
21.635 body.append(" }\n");
21.636 - body.append(" if (this.ws_").append(e.getSimpleName()).append(" == null) {\n");
21.637 - body.append(" ProcessResult pr = new ProcessResult();\n");
21.638 - body.append(" this.ws_").append(e.getSimpleName());
21.639 - body.append("= org.netbeans.html.json.impl.JSON.openWS(context, pr,\n ");
21.640 - body.append(urlBefore).append(", data);\n");
21.641 - body.append(" } else {\n");
21.642 - body.append(" this.ws_").append(e.getSimpleName()).append(".send(context, ").append(urlBefore).append(", data);\n");
21.643 - body.append(" }\n");
21.644 + method.append(" if (this.ws_").append(e.getSimpleName()).append(" == null) {\n");
21.645 + method.append(" this.ws_").append(e.getSimpleName());
21.646 + method.append("= proto.wsOpen(" + index + ", ");
21.647 + method.append(urlBefore).append(", data);\n");
21.648 + method.append(" } else {\n");
21.649 + method.append(" proto.wsSend(this.ws_").append(e.getSimpleName()).append(", ").append(urlBefore).append(", data);\n");
21.650 + method.append(" }\n");
21.651 return false;
21.652 }
21.653
21.654 @@ -1227,30 +1234,34 @@
21.655 first = false;
21.656 String toCall = null;
21.657 String toFinish = null;
21.658 + boolean addNull = true;
21.659 if (ve.asType() == stringType) {
21.660 if (ve.getSimpleName().contentEquals("id")) {
21.661 params.append('"').append(id).append('"');
21.662 continue;
21.663 }
21.664 - toCall = "org.netbeans.html.json.impl.JSON.toString(context, ";
21.665 + toCall = "proto.toString(";
21.666 }
21.667 if (ve.asType().getKind() == TypeKind.DOUBLE) {
21.668 - toCall = "org.netbeans.html.json.impl.JSON.toNumber(context, ";
21.669 + toCall = "proto.toNumber(";
21.670 toFinish = ".doubleValue()";
21.671 }
21.672 if (ve.asType().getKind() == TypeKind.INT) {
21.673 - toCall = "org.netbeans.html.json.impl.JSON.toNumber(context, ";
21.674 + toCall = "proto.toNumber(";
21.675 toFinish = ".intValue()";
21.676 }
21.677 if (dataName != null && ve.getSimpleName().contentEquals(dataName) && isModel(ve.asType())) {
21.678 - toCall = "org.netbeans.html.json.impl.JSON.toModel(context, " + ve.asType() + ".class, ";
21.679 + toCall = "proto.toModel(" + ve.asType() + ".class, ";
21.680 + addNull = false;
21.681 }
21.682
21.683 if (toCall != null) {
21.684 params.append(toCall);
21.685 if (dataName != null && ve.getSimpleName().contentEquals(dataName)) {
21.686 params.append(dataName);
21.687 - params.append(", null");
21.688 + if (addNull) {
21.689 + params.append(", null");
21.690 + }
21.691 } else {
21.692 if (evName == null) {
21.693 final StringBuilder sb = new StringBuilder();
21.694 @@ -1314,7 +1325,7 @@
21.695 rn = rn.substring(last + 1);
21.696 }
21.697 if (rn.equals(className)) {
21.698 - params.append(className).append(".this");
21.699 + params.append("model");
21.700 continue;
21.701 }
21.702 error(
21.703 @@ -1352,7 +1363,7 @@
21.704 w.write(sep);
21.705 w.append(" sb.append('\"').append(\"" + p.name() + "\")");
21.706 w.append(".append('\"').append(\":\");\n");
21.707 - w.append(" sb.append(org.netbeans.html.json.impl.JSON.toJSON(prop_");
21.708 + w.append(" sb.append(TYPE.toJSON(prop_");
21.709 w.append(p.name()).append("));\n");
21.710 sep = " sb.append(',');\n";
21.711 }
21.712 @@ -1362,7 +1373,7 @@
21.713 }
21.714 private void writeClone(String className, Prprt[] props, Writer w) throws IOException {
21.715 w.write(" public " + className + " clone() {\n");
21.716 - w.write(" return clone(context);\n");
21.717 + w.write(" return clone(proto.getContext());\n");
21.718 w.write(" }\n");
21.719 w.write(" private " + className + " clone(net.java.html.BrwsrCtx ctx) {\n");
21.720 w.write(" " + className + " ret = new " + className + "(ctx);\n");
21.721 @@ -1378,7 +1389,7 @@
21.722 }
21.723 w.write(" ret.prop_" + p.name() + " = prop_" + p.name() + " == null ? null : prop_" + p.name() + ".clone();\n");
21.724 } else {
21.725 - w.write(" ret.prop_" + p.name() + ".cloneAll(ctx, prop_" + p.name() + ");\n");
21.726 + w.write(" proto.cloneList(ret.prop_" + p.name() + ", ctx, prop_" + p.name() + ");\n");
21.727 }
21.728 }
21.729
22.1 --- a/json/src/main/java/org/netbeans/html/json/impl/PropertyBindingAccessor.java Mon Dec 16 18:08:40 2013 +0100
22.2 +++ b/json/src/main/java/org/netbeans/html/json/impl/PropertyBindingAccessor.java Mon Jan 06 09:44:07 2014 +0100
22.3 @@ -46,6 +46,7 @@
22.4 import org.apidesign.html.json.spi.FunctionBinding;
22.5 import org.apidesign.html.json.spi.JSONCall;
22.6 import org.apidesign.html.json.spi.PropertyBinding;
22.7 +import org.apidesign.html.json.spi.Proto;
22.8
22.9 /**
22.10 *
22.11 @@ -63,19 +64,32 @@
22.12 JSON.initClass(PropertyBinding.class);
22.13 }
22.14
22.15 - protected abstract <M> PropertyBinding newBinding(PBData<M> d);
22.16 - protected abstract <M> FunctionBinding newFunction(FBData<M> d);
22.17 + protected abstract <M> PropertyBinding newBinding(
22.18 + Proto.Type<M> access, Bindings<?> bindings, String name, int index, M model, boolean readOnly
22.19 + );
22.20 protected abstract JSONCall newCall(
22.21 BrwsrCtx ctx, RcvrJSON callback, String urlBefore, String urlAfter,
22.22 String method, Object data
22.23 );
22.24 -
22.25
22.26 - static <M> PropertyBinding create(PBData<M> d) {
22.27 - return DEFAULT.newBinding(d);
22.28 + protected abstract Bindings bindings(Proto proto, boolean initialize);
22.29 + protected abstract void notifyChange(Proto proto, int propIndex);
22.30 + protected abstract Proto findProto(Proto.Type<?> type, Object object);
22.31 + protected abstract <Model> Model cloneTo(Proto.Type<Model> type, Model model, BrwsrCtx c);
22.32 + protected abstract Object read(Proto.Type<?> from, BrwsrCtx c, Object data);
22.33 +
22.34 + static Bindings getBindings(Proto proto, boolean initialize) {
22.35 + return DEFAULT.bindings(proto, initialize);
22.36 }
22.37 - static <M> FunctionBinding createFunction(FBData<M> d) {
22.38 - return DEFAULT.newFunction(d);
22.39 +
22.40 + static void notifyProtoChange(Proto proto, int propIndex) {
22.41 + DEFAULT.notifyChange(proto, propIndex);
22.42 + }
22.43 +
22.44 + static <M> PropertyBinding create(
22.45 + Proto.Type<M> access, Bindings<?> bindings, String name, int index, M model , boolean readOnly
22.46 + ) {
22.47 + return DEFAULT.newBinding(access, bindings, name, index, model, readOnly);
22.48 }
22.49 static JSONCall createCall(
22.50 BrwsrCtx ctx, RcvrJSON callback, String urlBefore, String urlAfter,
22.51 @@ -83,53 +97,13 @@
22.52 ) {
22.53 return DEFAULT.newCall(ctx, callback, urlBefore, urlAfter, method, data);
22.54 }
22.55 -
22.56 - public static final class PBData<M> {
22.57 - public final String name;
22.58 - public final boolean readOnly;
22.59 - private final M model;
22.60 - private final SetAndGet<M> access;
22.61 - private final Bindings<?> bindings;
22.62 -
22.63 - public PBData(Bindings<?> bindings, String name, M model, SetAndGet<M> access, boolean readOnly) {
22.64 - this.bindings = bindings;
22.65 - this.name = name;
22.66 - this.model = model;
22.67 - this.access = access;
22.68 - this.readOnly = readOnly;
22.69 - }
22.70 -
22.71 - public void setValue(Object v) {
22.72 - access.setValue(model, v);
22.73 - }
22.74 -
22.75 - public Object getValue() {
22.76 - return access.getValue(model);
22.77 - }
22.78 -
22.79 - public boolean isReadOnly() {
22.80 - return readOnly;
22.81 - }
22.82 -
22.83 - public Bindings getBindings() {
22.84 - return bindings;
22.85 - }
22.86 - } // end of PBData
22.87 -
22.88 - public static final class FBData<M> {
22.89 - public final String name;
22.90 - private final M model;
22.91 - private final Callback<M> access;
22.92 -
22.93 - public FBData(String name, M model, Callback<M> access) {
22.94 - this.name = name;
22.95 - this.model = model;
22.96 - this.access = access;
22.97 - }
22.98 -
22.99 -
22.100 - public void call(Object data, Object ev) {
22.101 - access.call(model, data, ev);
22.102 - }
22.103 - } // end of FBData
22.104 + static Proto protoFor(Proto.Type<?> type, Object object) {
22.105 + return DEFAULT.findProto(type, object);
22.106 + }
22.107 + static <Model> Model clone(Proto.Type<Model> type, Model model, BrwsrCtx c) {
22.108 + return DEFAULT.cloneTo(type, model, c);
22.109 + }
22.110 + static Object readFrom(Proto.Type<?> from, BrwsrCtx c, Object data) {
22.111 + return DEFAULT.read(from, c, data);
22.112 + }
22.113 }
23.1 --- a/json/src/main/java/org/netbeans/html/json/impl/RcvrJSON.java Mon Dec 16 18:08:40 2013 +0100
23.2 +++ b/json/src/main/java/org/netbeans/html/json/impl/RcvrJSON.java Mon Jan 06 09:44:07 2014 +0100
23.3 @@ -42,6 +42,7 @@
23.4 */
23.5 package org.netbeans.html.json.impl;
23.6
23.7 +import java.util.ArrayList;
23.8 import net.java.html.BrwsrCtx;
23.9
23.10 /** Super type for those who wish to receive JSON messages.
23.11 @@ -73,13 +74,10 @@
23.12 return new Exception(t);
23.13 }
23.14
23.15 - public int dataSize() {
23.16 - return -1;
23.17 + public Object[] getValues() {
23.18 + return null;
23.19 }
23.20
23.21 - public <Data> void dataRead(BrwsrCtx ctx, Class<? extends Data> type, Data[] fillTheArray) {
23.22 - }
23.23 -
23.24 public abstract void dispatch(RcvrJSON r);
23.25
23.26 public static MsgEvnt createError(final Throwable t) {
23.27 @@ -99,26 +97,8 @@
23.28 public static MsgEvnt createMessage(final Object value) {
23.29 return new MsgEvnt() {
23.30 @Override
23.31 - public int dataSize() {
23.32 - if (value instanceof Object[]) {
23.33 - return ((Object[])value).length;
23.34 - } else {
23.35 - return 1;
23.36 - }
23.37 - }
23.38 -
23.39 - @Override
23.40 - public <Data> void dataRead(BrwsrCtx context, Class<? extends Data> type, Data[] arr) {
23.41 - if (value instanceof Object[]) {
23.42 - Object[] data = ((Object[]) value);
23.43 - for (int i = 0; i < data.length && i < arr.length; i++) {
23.44 - arr[i] = org.netbeans.html.json.impl.JSON.read(context, type, data[i]);
23.45 - }
23.46 - } else {
23.47 - if (arr.length > 0) {
23.48 - arr[0] = org.netbeans.html.json.impl.JSON.read(context, type, value);
23.49 - }
23.50 - }
23.51 + public Object[] getValues() {
23.52 + return value instanceof Object[] ? (Object[])value : new Object[] { value };
23.53 }
23.54
23.55 @Override
23.56 @@ -145,5 +125,4 @@
23.57 }
23.58 };
23.59 }
23.60 - } // end MsgEvnt
23.61 -}
23.62 + } }
24.1 --- a/json/src/main/java/org/netbeans/html/json/impl/SetAndGet.java Mon Dec 16 18:08:40 2013 +0100
24.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
24.3 @@ -1,54 +0,0 @@
24.4 -/**
24.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
24.6 - *
24.7 - * Copyright 2013-2013 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.netbeans.html.json.impl;
24.47 -
24.48 -import org.apidesign.html.json.spi.PropertyBinding;
24.49 -
24.50 -/** A way to implement a {@link PropertyBinding}.
24.51 - *
24.52 - * @author Jaroslav Tulach <jtulach@netbeans.org>
24.53 - */
24.54 -public interface SetAndGet<Data> {
24.55 - public void setValue(Data data, Object value);
24.56 - public Object getValue(Data data);
24.57 -}
25.1 --- a/json/src/main/java/org/netbeans/html/json/impl/WrapperObject.java Mon Dec 16 18:08:40 2013 +0100
25.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
25.3 @@ -1,82 +0,0 @@
25.4 -/**
25.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
25.6 - *
25.7 - * Copyright 2013-2013 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.netbeans.html.json.impl;
25.47 -
25.48 -import java.util.Collection;
25.49 -import org.netbeans.html.json.impl.PropertyBindingAccessor.PBData;
25.50 -
25.51 -/** A way to extract real object from a model classes.
25.52 - *
25.53 - * @author Jaroslav Tulach <jtulach@netbeans.org>
25.54 - */
25.55 -public final class WrapperObject {
25.56 - private Object ko;
25.57 -
25.58 - private WrapperObject() {
25.59 - }
25.60 -
25.61 - public void setRealObject(Object ko) {
25.62 - this.ko = ko;
25.63 - }
25.64 -
25.65 - public static Object find(Object object) {
25.66 - return find(object, null);
25.67 - }
25.68 -
25.69 - public static Object find(Object object, Bindings model) {
25.70 - if (object == null) {
25.71 - return null;
25.72 - }
25.73 -
25.74 - if (object instanceof JSONList) {
25.75 - return ((JSONList<?>)object).koData();
25.76 - }
25.77 - if (object instanceof Collection) {
25.78 - return JSONList.koData((Collection<?>)object, model);
25.79 - }
25.80 -
25.81 - WrapperObject ro = new WrapperObject();
25.82 - object.equals(ro);
25.83 - return ro.ko;
25.84 - }
25.85 -}
26.1 --- a/json/src/test/java/net/java/html/json/MapModelTest.java Mon Dec 16 18:08:40 2013 +0100
26.2 +++ b/json/src/test/java/net/java/html/json/MapModelTest.java Mon Jan 06 09:44:07 2014 +0100
26.3 @@ -49,12 +49,12 @@
26.4 import java.util.HashMap;
26.5 import java.util.Map;
26.6 import org.apidesign.html.context.spi.Contexts;
26.7 -import org.netbeans.html.json.impl.WrapperObject;
26.8 import org.apidesign.html.json.spi.FunctionBinding;
26.9 import org.apidesign.html.json.spi.JSONCall;
26.10 import org.apidesign.html.json.spi.PropertyBinding;
26.11 import org.apidesign.html.json.spi.Technology;
26.12 import org.apidesign.html.json.spi.Transfer;
26.13 +import org.netbeans.html.json.impl.JSON;
26.14 import org.testng.annotations.BeforeMethod;
26.15 import org.testng.annotations.Test;
26.16 import static org.testng.Assert.*;
26.17 @@ -77,7 +77,7 @@
26.18 Person p = Models.bind(new Person(), c).applyBindings();
26.19 p.setFirstName("Jarda");
26.20
26.21 - Map m = (Map)WrapperObject.find(p);
26.22 + Map m = (Map)JSON.find(p);
26.23 Object v = m.get("firstName");
26.24 assertNotNull(v, "Value should be in the map");
26.25 assertEquals(v.getClass(), One.class, "It is instance of One");
26.26 @@ -98,7 +98,7 @@
26.27 Person p = Models.bind(new Person(), c);
26.28 p.setFirstName("Jirka");
26.29
26.30 - Map m = (Map)WrapperObject.find(p);
26.31 + Map m = (Map)JSON.find(p);
26.32 Object v = m.get("firstName");
26.33 assertNotNull(v, "Value should be in the map");
26.34 assertEquals(v.getClass(), One.class, "It is instance of One");
26.35 @@ -122,7 +122,7 @@
26.36 @Test public void derivedProperty() throws Exception {
26.37 Person p = Models.bind(new Person(), c);
26.38
26.39 - Map m = (Map)WrapperObject.find(p);
26.40 + Map m = (Map)JSON.find(p);
26.41 Object v = m.get("fullName");
26.42 assertNotNull(v, "Value should be in the map");
26.43 assertEquals(v.getClass(), One.class, "It is instance of One");
26.44 @@ -135,7 +135,7 @@
26.45 p.setFirstName("Trans");
26.46 p.setSex(Sex.MALE);
26.47
26.48 - Map m = (Map)WrapperObject.find(p);
26.49 + Map m = (Map)JSON.find(p);
26.50 Object o = m.get("changeSex");
26.51 assertNotNull(o, "Function registered in the model");
26.52 assertEquals(o.getClass(), One.class);
26.53 @@ -152,7 +152,7 @@
26.54 Person p = Models.bind(new Person(), c);
26.55 p.setFirstName("Trans");
26.56
26.57 - Map m = (Map)WrapperObject.find(p);
26.58 + Map m = (Map)JSON.find(p);
26.59 Object o = m.get("changeSex");
26.60 assertNotNull(o, "Function registered in the model");
26.61 assertEquals(o.getClass(), One.class);
27.1 --- a/json/src/test/java/net/java/html/json/PrimitiveArrayTest.java Mon Dec 16 18:08:40 2013 +0100
27.2 +++ b/json/src/test/java/net/java/html/json/PrimitiveArrayTest.java Mon Jan 06 09:44:07 2014 +0100
27.3 @@ -42,6 +42,7 @@
27.4 */
27.5 package net.java.html.json;
27.6
27.7 +import java.util.List;
27.8 import org.testng.Assert;
27.9 import org.testng.annotations.Test;
27.10
27.11 @@ -53,11 +54,16 @@
27.12 @Property(name = "array", type = byte.class, array = true)
27.13 })
27.14 public class PrimitiveArrayTest {
27.15 + @ComputedProperty static int length(List<Byte> array) {
27.16 + return array.size();
27.17 + }
27.18 +
27.19 @Test public void generatedConstructorWithPrimitiveType() {
27.20 byte[] arr = new byte[10];
27.21 arr[3] = 10;
27.22 ByteArray a = new ByteArray(arr);
27.23 Assert.assertEquals(a.getArray().size(), 10, "Ten elements");
27.24 Assert.assertEquals(a.getArray().get(3).byteValue(), 10, "Value ten");
27.25 + Assert.assertEquals(a.getLength(), 10, "Derived property is OK too");
27.26 }
27.27 }
28.1 --- a/json/src/test/java/net/java/html/json/TypesTest.java Mon Dec 16 18:08:40 2013 +0100
28.2 +++ b/json/src/test/java/net/java/html/json/TypesTest.java Mon Jan 06 09:44:07 2014 +0100
28.3 @@ -46,9 +46,9 @@
28.4 import java.util.Map;
28.5 import net.java.html.json.MapModelTest.One;
28.6 import org.apidesign.html.context.spi.Contexts;
28.7 -import org.netbeans.html.json.impl.WrapperObject;
28.8 import org.apidesign.html.json.spi.Technology;
28.9 import org.apidesign.html.json.spi.Transfer;
28.10 +import org.netbeans.html.json.impl.JSON;
28.11 import org.testng.annotations.BeforeMethod;
28.12 import org.testng.annotations.Test;
28.13 import static org.testng.Assert.*;
28.14 @@ -111,10 +111,10 @@
28.15 t.setFloatX(99f);
28.16 */
28.17
28.18 - Object json = WrapperObject.find(t);
28.19 + Object json = JSON.find(t);
28.20
28.21 Types copy = Models.bind(new Types(), c);
28.22 - Map copyMap = (Map) WrapperObject.find(copy);
28.23 + Map copyMap = (Map) JSON.find(copy);
28.24 One o = (One) copyMap.get("readFromEvent");
28.25 o.fb.call(null, json);
28.26
29.1 --- a/json/src/test/java/org/netbeans/html/json/impl/JSONListTest.java Mon Dec 16 18:08:40 2013 +0100
29.2 +++ b/json/src/test/java/org/netbeans/html/json/impl/JSONListTest.java Mon Jan 06 09:44:07 2014 +0100
29.3 @@ -80,7 +80,7 @@
29.4 p.setLastName("2");
29.5 p.setSex(Sex.MALE);
29.6
29.7 - Object real = WrapperObject.find(p);
29.8 + Object real = JSON.find(p);
29.9 assertEquals(this, real, "I am the right model");
29.10 }
29.11
29.12 @@ -135,7 +135,7 @@
29.13 People people = Models.bind(new People(), c).applyBindings();
29.14 people.getInfo().add(p);
29.15
29.16 - Object real = WrapperObject.find(people.getInfo());
29.17 + Object real = JSON.find(people.getInfo());
29.18 assertEquals(real, this, "I am the model of the array");
29.19 }
29.20
30.1 --- a/json/src/test/java/org/netbeans/html/json/impl/JSONTest.java Mon Dec 16 18:08:40 2013 +0100
30.2 +++ b/json/src/test/java/org/netbeans/html/json/impl/JSONTest.java Mon Jan 06 09:44:07 2014 +0100
30.3 @@ -42,7 +42,6 @@
30.4 */
30.5 package org.netbeans.html.json.impl;
30.6
30.7 -import org.netbeans.html.json.impl.JSON;
30.8 import static org.testng.Assert.*;
30.9 import org.testng.annotations.Test;
30.10
31.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
31.2 +++ b/ko-osgi-test/pom.xml Mon Jan 06 09:44:07 2014 +0100
31.3 @@ -0,0 +1,136 @@
31.4 +<?xml version="1.0" encoding="UTF-8"?>
31.5 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
31.6 + <modelVersion>4.0.0</modelVersion>
31.7 + <parent>
31.8 + <groupId>org.netbeans.html</groupId>
31.9 + <artifactId>pom</artifactId>
31.10 + <version>0.7-SNAPSHOT</version>
31.11 + </parent>
31.12 + <name>KO Tests in an OSGi Container</name>
31.13 + <artifactId>ko-osgi-test</artifactId>
31.14 + <packaging>bundle</packaging>
31.15 + <description>Runs the TCK for Knockout in an OSGi Container</description>
31.16 + <properties>
31.17 + <netbeans.compile.on.save>none</netbeans.compile.on.save>
31.18 + </properties>
31.19 + <build>
31.20 + <plugins>
31.21 + <plugin>
31.22 + <groupId>org.apache.felix</groupId>
31.23 + <artifactId>maven-bundle-plugin</artifactId>
31.24 + </plugin>
31.25 + <plugin>
31.26 + <groupId>org.apache.maven.plugins</groupId>
31.27 + <artifactId>maven-compiler-plugin</artifactId>
31.28 + <version>2.3.2</version>
31.29 + <configuration>
31.30 + <source>1.7</source>
31.31 + <target>1.7</target>
31.32 + </configuration>
31.33 + </plugin>
31.34 + <plugin>
31.35 + <artifactId>maven-failsafe-plugin</artifactId>
31.36 + <version>2.16</version>
31.37 + <configuration>
31.38 + <additionalClasspathElements>
31.39 + <additionalClasspathElement>${project.build.directory}/${project.build.finalName}.jar</additionalClasspathElement>
31.40 + </additionalClasspathElements>
31.41 + </configuration>
31.42 + <executions>
31.43 + <execution>
31.44 + <goals>
31.45 + <goal>integration-test</goal>
31.46 + <goal>verify</goal>
31.47 + </goals>
31.48 + </execution>
31.49 + </executions>
31.50 + </plugin>
31.51 + </plugins>
31.52 + </build>
31.53 + <dependencies>
31.54 + <dependency>
31.55 + <groupId>com.oracle</groupId>
31.56 + <artifactId>javafx</artifactId>
31.57 + <version>2.2</version>
31.58 + <scope>system</scope>
31.59 + <systemPath>${jfxrt.jar}</systemPath>
31.60 + </dependency>
31.61 + <dependency>
31.62 + <groupId>de.twentyeleven.skysail</groupId>
31.63 + <artifactId>org.json-osgi</artifactId>
31.64 + </dependency>
31.65 + <dependency>
31.66 + <groupId>org.netbeans.html</groupId>
31.67 + <artifactId>net.java.html.json</artifactId>
31.68 + <version>${project.version}</version>
31.69 + </dependency>
31.70 + <dependency>
31.71 + <groupId>org.testng</groupId>
31.72 + <artifactId>testng</artifactId>
31.73 + <scope>test</scope>
31.74 + </dependency>
31.75 + <dependency>
31.76 + <groupId>${project.groupId}</groupId>
31.77 + <artifactId>net.java.html.json.tck</artifactId>
31.78 + <version>${project.version}</version>
31.79 + </dependency>
31.80 + <dependency>
31.81 + <groupId>org.netbeans.api</groupId>
31.82 + <artifactId>org-openide-util-lookup</artifactId>
31.83 + <scope>provided</scope>
31.84 + </dependency>
31.85 + <dependency>
31.86 + <groupId>org.netbeans.html</groupId>
31.87 + <artifactId>net.java.html.boot</artifactId>
31.88 + <version>${project.version}</version>
31.89 + <type>jar</type>
31.90 + </dependency>
31.91 + <dependency>
31.92 + <groupId>${project.groupId}</groupId>
31.93 + <artifactId>ko-fx</artifactId>
31.94 + <version>${project.version}</version>
31.95 + </dependency>
31.96 + <dependency>
31.97 + <groupId>${project.groupId}</groupId>
31.98 + <artifactId>net.java.html.boot.fx</artifactId>
31.99 + <version>${project.version}</version>
31.100 + <scope>test</scope>
31.101 + </dependency>
31.102 + <dependency>
31.103 + <groupId>org.glassfish.grizzly</groupId>
31.104 + <artifactId>grizzly-http-server</artifactId>
31.105 + <version>2.3.3</version>
31.106 + <scope>test</scope>
31.107 + </dependency>
31.108 + <dependency>
31.109 + <groupId>org.glassfish.grizzly</groupId>
31.110 + <artifactId>grizzly-websockets-server</artifactId>
31.111 + <version>2.3.3</version>
31.112 + <scope>test</scope>
31.113 + <type>jar</type>
31.114 + </dependency>
31.115 + <dependency>
31.116 + <groupId>org.glassfish.grizzly</groupId>
31.117 + <artifactId>grizzly-http-servlet</artifactId>
31.118 + <version>2.3.3</version>
31.119 + <scope>test</scope>
31.120 + </dependency>
31.121 + <dependency>
31.122 + <groupId>javax.servlet</groupId>
31.123 + <artifactId>javax.servlet-api</artifactId>
31.124 + <scope>test</scope>
31.125 + <version>3.1.0</version>
31.126 + </dependency>
31.127 + <dependency>
31.128 + <groupId>org.eclipse</groupId>
31.129 + <artifactId>org.eclipse.osgi</artifactId>
31.130 + <version>3.8.0.v20120529-1548</version>
31.131 + </dependency>
31.132 + <dependency>
31.133 + <groupId>${project.groupId}</groupId>
31.134 + <artifactId>equinox-agentclass-hook</artifactId>
31.135 + <version>${project.version}</version>
31.136 + <scope>test</scope>
31.137 + </dependency>
31.138 + </dependencies>
31.139 +</project>
31.140 \ No newline at end of file
32.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
32.2 +++ b/ko-osgi-test/src/main/java/org/netbeans/html/ko/osgi/test/KnockoutEquinoxTCKImpl.java Mon Jan 06 09:44:07 2014 +0100
32.3 @@ -0,0 +1,219 @@
32.4 +/**
32.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
32.6 + *
32.7 + * Copyright 2013-2013 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.ko.osgi.test;
32.47 +
32.48 +import java.io.BufferedReader;
32.49 +import java.io.IOException;
32.50 +import java.io.InputStreamReader;
32.51 +import java.lang.reflect.Method;
32.52 +import java.net.URI;
32.53 +import java.net.URISyntaxException;
32.54 +import java.net.URL;
32.55 +import java.net.URLConnection;
32.56 +import java.util.Map;
32.57 +import java.util.concurrent.Callable;
32.58 +import java.util.concurrent.Executors;
32.59 +import net.java.html.BrwsrCtx;
32.60 +import net.java.html.boot.BrowserBuilder;
32.61 +import net.java.html.js.JavaScriptBody;
32.62 +import org.apidesign.html.boot.spi.Fn;
32.63 +import org.apidesign.html.context.spi.Contexts;
32.64 +import org.apidesign.html.json.spi.Technology;
32.65 +import org.apidesign.html.json.spi.Transfer;
32.66 +import org.apidesign.html.json.tck.KnockoutTCK;
32.67 +import org.json.JSONException;
32.68 +import org.json.JSONObject;
32.69 +import org.openide.util.lookup.ServiceProvider;
32.70 +import org.osgi.framework.Bundle;
32.71 +import org.osgi.framework.BundleContext;
32.72 +import org.osgi.framework.FrameworkUtil;
32.73 +
32.74 +/**
32.75 + *
32.76 + * @author Jaroslav Tulach <jtulach@netbeans.org>
32.77 + */
32.78 +@ServiceProvider(service = KnockoutTCK.class)
32.79 +public class KnockoutEquinoxTCKImpl extends KnockoutTCK implements Callable<Class[]> {
32.80 +
32.81 + private static Fn.Presenter browserContext;
32.82 +
32.83 + public static Class loadOSGiClass(String name, BundleContext ctx) throws Exception {
32.84 + for (Bundle b : ctx.getBundles()) {
32.85 + try {
32.86 + Class<?> osgiClass = b.loadClass(name);
32.87 + if (osgiClass != null && osgiClass.getClassLoader() != ClassLoader.getSystemClassLoader()) {
32.88 + return osgiClass;
32.89 + }
32.90 + } catch (ClassNotFoundException cnfe) {
32.91 + // go on
32.92 + }
32.93 + }
32.94 + throw new IllegalStateException("Cannot load " + name + " from the OSGi container!");
32.95 + }
32.96 +
32.97 + @Override
32.98 + public Class[] call() throws Exception {
32.99 + return testClasses();
32.100 + }
32.101 +
32.102 + public static void start(URI server) throws Exception {
32.103 + final BrowserBuilder bb = BrowserBuilder.newBrowser().loadClass(KnockoutEquinoxTCKImpl.class).
32.104 + loadPage(server.toString()).
32.105 + invoke("initialized");
32.106 +
32.107 + Executors.newSingleThreadExecutor().submit(new Runnable() {
32.108 + @Override
32.109 + public void run() {
32.110 + try {
32.111 + final ClassLoader osgiClassLoader = BrowserBuilder.class.getClassLoader();
32.112 + Thread.currentThread().setContextClassLoader(osgiClassLoader);
32.113 + bb.showAndWait();
32.114 + } catch (Throwable t) {
32.115 + t.printStackTrace();
32.116 + }
32.117 + }
32.118 + });
32.119 + }
32.120 +
32.121 + public static void initialized() throws Exception {
32.122 + Bundle bundle = FrameworkUtil.getBundle(KnockoutEquinoxTCKImpl.class);
32.123 + if (bundle == null) {
32.124 + throw new IllegalStateException(
32.125 + "Should be loaded from a bundle. But was: " + KnockoutEquinoxTCKImpl.class.getClassLoader()
32.126 + );
32.127 + }
32.128 + Class<?> classpathClass = ClassLoader.getSystemClassLoader().loadClass(
32.129 + "org.netbeans.html.ko.osgi.test.KnockoutEquinoxIT"
32.130 + );
32.131 + Method m = classpathClass.getMethod("initialized", Class.class, Object.class);
32.132 + browserContext = Fn.activePresenter();
32.133 + m.invoke(null, KnockoutEquinoxTCKImpl.class, browserContext);
32.134 + }
32.135 +
32.136 + @Override
32.137 + public BrwsrCtx createContext() {
32.138 + try {
32.139 + Class<?> fxCls = loadOSGiClass(
32.140 + "org.netbeans.html.kofx.FXContext",
32.141 + FrameworkUtil.getBundle(KnockoutEquinoxTCKImpl.class).getBundleContext()
32.142 + );
32.143 + Object fx = fxCls.getConstructor(Fn.Presenter.class).newInstance(browserContext);
32.144 + Contexts.Builder cb = Contexts.newBuilder().
32.145 + register(Technology.class, (Technology)fx, 10).
32.146 + register(Transfer.class, (Transfer)fx, 10);
32.147 +// if (fx.areWebSocketsSupported()) {
32.148 +// cb.register(WSTransfer.class, fx, 10);
32.149 +// }
32.150 + return cb.build();
32.151 + } catch (Exception ex) {
32.152 + throw new IllegalStateException(ex);
32.153 + }
32.154 + }
32.155 +
32.156 + @Override
32.157 + public Object createJSON(Map<String, Object> values) {
32.158 + JSONObject json = new JSONObject();
32.159 + for (Map.Entry<String, Object> entry : values.entrySet()) {
32.160 + try {
32.161 + json.put(entry.getKey(), entry.getValue());
32.162 + } catch (JSONException ex) {
32.163 + throw new IllegalStateException(ex);
32.164 + }
32.165 + }
32.166 + return json;
32.167 + }
32.168 +
32.169 + @Override
32.170 + @JavaScriptBody(args = { "s", "args" }, body = ""
32.171 + + "var f = new Function(s); "
32.172 + + "return f.apply(null, args);"
32.173 + )
32.174 + public native Object executeScript(String script, Object[] arguments);
32.175 +
32.176 + @JavaScriptBody(args = { }, body =
32.177 + "var h;"
32.178 + + "if (!!window && !!window.location && !!window.location.href)\n"
32.179 + + " h = window.location.href;\n"
32.180 + + "else "
32.181 + + " h = null;"
32.182 + + "return h;\n"
32.183 + )
32.184 + private static native String findBaseURL();
32.185 +
32.186 + @Override
32.187 + public URI prepareURL(String content, String mimeType, String[] parameters) {
32.188 + try {
32.189 + final URL baseURL = new URL(findBaseURL());
32.190 + StringBuilder sb = new StringBuilder();
32.191 + sb.append("/dynamic?mimeType=").append(mimeType);
32.192 + for (int i = 0; i < parameters.length; i++) {
32.193 + sb.append("¶m" + i).append("=").append(parameters[i]);
32.194 + }
32.195 + String mangle = content.replace("\n", "%0a")
32.196 + .replace("\"", "\\\"").replace(" ", "%20");
32.197 + sb.append("&content=").append(mangle);
32.198 +
32.199 + URL query = new URL(baseURL, sb.toString());
32.200 + URLConnection c = query.openConnection();
32.201 + BufferedReader br = new BufferedReader(new InputStreamReader(c.getInputStream()));
32.202 + URI connectTo = new URI(br.readLine());
32.203 + return connectTo;
32.204 + } catch (IOException ex) {
32.205 + throw new IllegalStateException(ex);
32.206 + } catch (URISyntaxException ex) {
32.207 + throw new IllegalStateException(ex);
32.208 + }
32.209 + }
32.210 +
32.211 + @Override
32.212 + public boolean canFailWebSocketTest() {
32.213 + try {
32.214 + Class.forName("java.util.function.Function");
32.215 + return false;
32.216 + } catch (ClassNotFoundException ex) {
32.217 + // running on JDK7, FX WebView WebSocket impl does not work
32.218 + return true;
32.219 + }
32.220 + }
32.221 +
32.222 +}
33.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
33.2 +++ b/ko-osgi-test/src/test/java/org/netbeans/html/ko/osgi/test/DynamicHTTP.java Mon Jan 06 09:44:07 2014 +0100
33.3 @@ -0,0 +1,259 @@
33.4 +/**
33.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
33.6 + *
33.7 + * Copyright 2013-2013 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.ko.osgi.test;
33.47 +
33.48 +import java.io.ByteArrayInputStream;
33.49 +import java.io.ByteArrayOutputStream;
33.50 +import java.io.IOException;
33.51 +import java.io.InputStream;
33.52 +import java.io.OutputStream;
33.53 +import java.io.Reader;
33.54 +import java.net.URI;
33.55 +import java.net.URISyntaxException;
33.56 +import java.util.ArrayList;
33.57 +import java.util.List;
33.58 +import java.util.logging.Level;
33.59 +import java.util.logging.Logger;
33.60 +import org.glassfish.grizzly.PortRange;
33.61 +import org.glassfish.grizzly.http.server.HttpHandler;
33.62 +import org.glassfish.grizzly.http.server.HttpServer;
33.63 +import org.glassfish.grizzly.http.server.NetworkListener;
33.64 +import org.glassfish.grizzly.http.server.Request;
33.65 +import org.glassfish.grizzly.http.server.Response;
33.66 +import org.glassfish.grizzly.http.server.ServerConfiguration;
33.67 +import org.glassfish.grizzly.websockets.WebSocket;
33.68 +import org.glassfish.grizzly.websockets.WebSocketAddOn;
33.69 +import org.glassfish.grizzly.websockets.WebSocketApplication;
33.70 +import org.glassfish.grizzly.websockets.WebSocketEngine;
33.71 +
33.72 +/**
33.73 + *
33.74 + * @author Jaroslav Tulach <jtulach@netbeans.org>
33.75 + */
33.76 +final class DynamicHTTP extends HttpHandler {
33.77 + private static final Logger LOG = Logger.getLogger(DynamicHTTP.class.getName());
33.78 + private static int resourcesCount;
33.79 + private static List<Resource> resources;
33.80 + private static ServerConfiguration conf;
33.81 + private static HttpServer server;
33.82 +
33.83 + private DynamicHTTP() {
33.84 + }
33.85 +
33.86 + static URI initServer() throws Exception {
33.87 + server = HttpServer.createSimpleServer(null, new PortRange(8080, 65535));
33.88 + final WebSocketAddOn addon = new WebSocketAddOn();
33.89 + for (NetworkListener listener : server.getListeners()) {
33.90 + listener.registerAddOn(addon);
33.91 + }
33.92 + resources = new ArrayList<Resource>();
33.93 +
33.94 + conf = server.getServerConfiguration();
33.95 + final DynamicHTTP dh = new DynamicHTTP();
33.96 +
33.97 + conf.addHttpHandler(dh, "/");
33.98 +
33.99 + server.start();
33.100 +
33.101 + return pageURL("http", server, "/test.html");
33.102 + }
33.103 +
33.104 + @Override
33.105 + public void service(Request request, Response response) throws Exception {
33.106 + if ("/test.html".equals(request.getRequestURI())) {
33.107 + response.setContentType("text/html");
33.108 + final InputStream is = DynamicHTTP.class.getResourceAsStream("test.html");
33.109 + copyStream(is, response.getOutputStream(), null);
33.110 + return;
33.111 + }
33.112 + if ("/dynamic".equals(request.getRequestURI())) {
33.113 + String mimeType = request.getParameter("mimeType");
33.114 + List<String> params = new ArrayList<String>();
33.115 + boolean webSocket = false;
33.116 + for (int i = 0;; i++) {
33.117 + String p = request.getParameter("param" + i);
33.118 + if (p == null) {
33.119 + break;
33.120 + }
33.121 + if ("protocol:ws".equals(p)) {
33.122 + webSocket = true;
33.123 + continue;
33.124 + }
33.125 + params.add(p);
33.126 + }
33.127 + final String cnt = request.getParameter("content");
33.128 + String mangle = cnt.replace("%20", " ").replace("%0A", "\n");
33.129 + ByteArrayInputStream is = new ByteArrayInputStream(mangle.getBytes("UTF-8"));
33.130 + URI url;
33.131 + final Resource res = new Resource(is, mimeType, "/dynamic/res" + ++resourcesCount, params.toArray(new String[params.size()]));
33.132 + if (webSocket) {
33.133 + url = registerWebSocket(res);
33.134 + } else {
33.135 + url = registerResource(res);
33.136 + }
33.137 + response.getWriter().write(url.toString());
33.138 + response.getWriter().write("\n");
33.139 + return;
33.140 + }
33.141 +
33.142 + for (Resource r : resources) {
33.143 + if (r.httpPath.equals(request.getRequestURI())) {
33.144 + response.setContentType(r.httpType);
33.145 + r.httpContent.reset();
33.146 + String[] params = null;
33.147 + if (r.parameters.length != 0) {
33.148 + params = new String[r.parameters.length];
33.149 + for (int i = 0; i < r.parameters.length; i++) {
33.150 + params[i] = request.getParameter(r.parameters[i]);
33.151 + if (params[i] == null) {
33.152 + if ("http.method".equals(r.parameters[i])) {
33.153 + params[i] = request.getMethod().toString();
33.154 + } else if ("http.requestBody".equals(r.parameters[i])) {
33.155 + Reader rdr = request.getReader();
33.156 + StringBuilder sb = new StringBuilder();
33.157 + for (;;) {
33.158 + int ch = rdr.read();
33.159 + if (ch == -1) {
33.160 + break;
33.161 + }
33.162 + sb.append((char) ch);
33.163 + }
33.164 + params[i] = sb.toString();
33.165 + }
33.166 + }
33.167 + if (params[i] == null) {
33.168 + params[i] = "null";
33.169 + }
33.170 + }
33.171 + }
33.172 +
33.173 + copyStream(r.httpContent, response.getOutputStream(), null, params);
33.174 + }
33.175 + }
33.176 + }
33.177 +
33.178 + private URI registerWebSocket(Resource r) {
33.179 + WebSocketEngine.getEngine().register("", r.httpPath, new WS(r));
33.180 + return pageURL("ws", server, r.httpPath);
33.181 + }
33.182 +
33.183 + private URI registerResource(Resource r) {
33.184 + if (!resources.contains(r)) {
33.185 + resources.add(r);
33.186 + conf.addHttpHandler(this, r.httpPath);
33.187 + }
33.188 + return pageURL("http", server, r.httpPath);
33.189 + }
33.190 +
33.191 + private static URI pageURL(String proto, HttpServer server, final String page) {
33.192 + NetworkListener listener = server.getListeners().iterator().next();
33.193 + int port = listener.getPort();
33.194 + try {
33.195 + return new URI(proto + "://localhost:" + port + page);
33.196 + } catch (URISyntaxException ex) {
33.197 + throw new IllegalStateException(ex);
33.198 + }
33.199 + }
33.200 +
33.201 + static final class Resource {
33.202 +
33.203 + final InputStream httpContent;
33.204 + final String httpType;
33.205 + final String httpPath;
33.206 + final String[] parameters;
33.207 +
33.208 + Resource(InputStream httpContent, String httpType, String httpPath,
33.209 + String[] parameters) {
33.210 + httpContent.mark(Integer.MAX_VALUE);
33.211 + this.httpContent = httpContent;
33.212 + this.httpType = httpType;
33.213 + this.httpPath = httpPath;
33.214 + this.parameters = parameters;
33.215 + }
33.216 + }
33.217 +
33.218 + static void copyStream(InputStream is, OutputStream os, String baseURL, String... params) throws IOException {
33.219 + for (;;) {
33.220 + int ch = is.read();
33.221 + if (ch == -1) {
33.222 + break;
33.223 + }
33.224 + if (ch == '$' && params.length > 0) {
33.225 + int cnt = is.read() - '0';
33.226 + if (baseURL != null && cnt == 'U' - '0') {
33.227 + os.write(baseURL.getBytes("UTF-8"));
33.228 + } else {
33.229 + if (cnt >= 0 && cnt < params.length) {
33.230 + os.write(params[cnt].getBytes("UTF-8"));
33.231 + } else {
33.232 + os.write('$');
33.233 + os.write(cnt + '0');
33.234 + }
33.235 + }
33.236 + } else {
33.237 + os.write(ch);
33.238 + }
33.239 + }
33.240 + }
33.241 +
33.242 + private static class WS extends WebSocketApplication {
33.243 + private final Resource r;
33.244 +
33.245 + private WS(Resource r) {
33.246 + this.r = r;
33.247 + }
33.248 +
33.249 + @Override
33.250 + public void onMessage(WebSocket socket, String text) {
33.251 + try {
33.252 + r.httpContent.reset();
33.253 + ByteArrayOutputStream out = new ByteArrayOutputStream();
33.254 + copyStream(r.httpContent, out, null, text);
33.255 + String s = new String(out.toByteArray(), "UTF-8");
33.256 + socket.send(s);
33.257 + } catch (IOException ex) {
33.258 + LOG.log(Level.WARNING, "Error processing message " + text, ex);
33.259 + }
33.260 + }
33.261 + }
33.262 +}
34.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
34.2 +++ b/ko-osgi-test/src/test/java/org/netbeans/html/ko/osgi/test/KOFx.java Mon Jan 06 09:44:07 2014 +0100
34.3 @@ -0,0 +1,118 @@
34.4 +/**
34.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
34.6 + *
34.7 + * Copyright 2013-2013 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.ko.osgi.test;
34.47 +
34.48 +import java.io.Closeable;
34.49 +import java.lang.reflect.InvocationTargetException;
34.50 +import java.lang.reflect.Method;
34.51 +import javafx.application.Platform;
34.52 +import org.apidesign.html.boot.spi.Fn;
34.53 +import org.testng.ITest;
34.54 +import org.testng.annotations.Test;
34.55 +
34.56 +/**
34.57 + *
34.58 + * @author Jaroslav Tulach <jtulach@netbeans.org>
34.59 + */
34.60 +public final class KOFx implements ITest, Runnable {
34.61 + private final Object p;
34.62 + private final Method m;
34.63 + private Object result;
34.64 + private Object inst;
34.65 + private int count;
34.66 +
34.67 + KOFx(Object p, Method m) {
34.68 + this.p = p;
34.69 + this.m = m;
34.70 + }
34.71 +
34.72 + @Override
34.73 + public String getTestName() {
34.74 + return m.getName();
34.75 + }
34.76 +
34.77 + @Test
34.78 + public synchronized void executeTest() throws Exception {
34.79 + if (result == null) {
34.80 + Platform.runLater(this);
34.81 + wait();
34.82 + }
34.83 + if (result instanceof Exception) {
34.84 + throw (Exception)result;
34.85 + }
34.86 + if (result instanceof Error) {
34.87 + throw (Error)result;
34.88 + }
34.89 + }
34.90 +
34.91 + @Override
34.92 + public synchronized void run() {
34.93 + boolean notify = true;
34.94 + try (Closeable a = KnockoutEquinoxIT.activateInOSGi(p)) {
34.95 + if (inst == null) {
34.96 + inst = m.getDeclaringClass().newInstance();
34.97 + }
34.98 + result = m.invoke(inst);
34.99 + if (result == null) {
34.100 + result = this;
34.101 + }
34.102 + } catch (InvocationTargetException ex) {
34.103 + Throwable r = ex.getTargetException();
34.104 + if (r instanceof InterruptedException) {
34.105 + if (count++ < 10000) {
34.106 + notify = false;
34.107 + Platform.runLater(this);
34.108 + return;
34.109 + }
34.110 + }
34.111 + result = r;
34.112 + } catch (Exception ex) {
34.113 + result = ex;
34.114 + } finally {
34.115 + if (notify) {
34.116 + notifyAll();
34.117 + }
34.118 + }
34.119 + }
34.120 +
34.121 +}
35.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
35.2 +++ b/ko-osgi-test/src/test/java/org/netbeans/html/ko/osgi/test/KnockoutEquinoxIT.java Mon Jan 06 09:44:07 2014 +0100
35.3 @@ -0,0 +1,243 @@
35.4 +/**
35.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
35.6 + *
35.7 + * Copyright 2013-2013 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.ko.osgi.test;
35.47 +
35.48 +import java.io.Closeable;
35.49 +import java.io.File;
35.50 +import java.io.IOException;
35.51 +import java.lang.annotation.Annotation;
35.52 +import java.lang.reflect.Method;
35.53 +import java.net.URI;
35.54 +import java.util.ArrayList;
35.55 +import java.util.HashMap;
35.56 +import java.util.List;
35.57 +import java.util.Map;
35.58 +import java.util.ServiceLoader;
35.59 +import java.util.concurrent.Callable;
35.60 +import java.util.jar.JarFile;
35.61 +import java.util.logging.Level;
35.62 +import java.util.logging.Logger;
35.63 +import org.apidesign.html.boot.spi.Fn;
35.64 +import org.apidesign.html.json.tck.KOTest;
35.65 +import org.apidesign.html.json.tck.KnockoutTCK;
35.66 +import org.osgi.framework.Bundle;
35.67 +import org.osgi.framework.BundleException;
35.68 +import org.osgi.framework.Constants;
35.69 +import org.osgi.framework.launch.Framework;
35.70 +import org.osgi.framework.launch.FrameworkFactory;
35.71 +import static org.testng.Assert.assertNotNull;
35.72 +import static org.testng.Assert.fail;
35.73 +import org.testng.annotations.AfterClass;
35.74 +import org.testng.annotations.Factory;
35.75 +
35.76 +/**
35.77 + *
35.78 + * @author Jaroslav Tulach <jtulach@netbeans.org>
35.79 + */
35.80 +public class KnockoutEquinoxIT {
35.81 + private static final Logger LOG = Logger.getLogger(KnockoutEquinoxIT.class.getName());
35.82 + private static Framework framework;
35.83 + private static File dir;
35.84 + static Framework framework() throws Exception {
35.85 + if (framework != null) {
35.86 + return framework;
35.87 + }
35.88 + for (FrameworkFactory ff : ServiceLoader.load(FrameworkFactory.class)) {
35.89 +
35.90 + String basedir = System.getProperty("basedir");
35.91 + assertNotNull("basedir preperty provided", basedir);
35.92 + File target = new File(basedir, "target");
35.93 + dir = new File(target, "osgi");
35.94 + dir.mkdirs();
35.95 +
35.96 + Map<String,String> config = new HashMap<>();
35.97 + config.put(Constants.FRAMEWORK_STORAGE, dir.getPath());
35.98 + config.put(Constants.FRAMEWORK_STORAGE_CLEAN, "true");
35.99 + config.put(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA, "sun.misc,"
35.100 + + "javafx.application,"
35.101 + + "javafx.beans.property,"
35.102 + + "javafx.beans.value,"
35.103 + + "javafx.collections,"
35.104 + + "javafx.concurrent,"
35.105 + + "javafx.event,"
35.106 + + "javafx.geometry,"
35.107 + + "javafx.scene,"
35.108 + + "javafx.scene.control,"
35.109 + + "javafx.scene.layout,"
35.110 + + "javafx.scene.text,"
35.111 + + "javafx.scene.web,"
35.112 + + "javafx.stage,"
35.113 + + "javafx.util,"
35.114 + + "netscape.javascript"
35.115 + );
35.116 + config.put("osgi.hook.configurators.include", "org.netbeans.html.equinox.agentclass.AgentHook");
35.117 + framework = ff.newFramework(config);
35.118 + framework.init();
35.119 + loadClassPathBundles(framework);
35.120 + framework.start();
35.121 + for (Bundle b : framework.getBundleContext().getBundles()) {
35.122 + try {
35.123 + if (b.getSymbolicName().contains("equinox-agentclass-hook")) {
35.124 + continue;
35.125 + }
35.126 + if (b.getSymbolicName().contains("grizzly.websockets-server")) {
35.127 + continue;
35.128 + }
35.129 + b.start();
35.130 + LOG.log(Level.INFO, "Started {0}", b.getSymbolicName());
35.131 + } catch (BundleException ex) {
35.132 + LOG.log(Level.WARNING, "Cannot start bundle " + b.getSymbolicName(), ex);
35.133 + }
35.134 + }
35.135 + return framework;
35.136 + }
35.137 + fail("No OSGi framework in the path");
35.138 + return null;
35.139 + }
35.140 +
35.141 + @AfterClass public static void cleanUp() throws Exception {
35.142 + if (framework != null) framework.stop();
35.143 + clearUpDir(dir);
35.144 + }
35.145 + private static void clearUpDir(File dir) {
35.146 + if (dir.isDirectory()) {
35.147 + for (File f : dir.listFiles()) {
35.148 + clearUpDir(f);
35.149 + }
35.150 + }
35.151 + dir.delete();
35.152 + }
35.153 +
35.154 +
35.155 +
35.156 + private static void loadClassPathBundles(Framework f) throws IOException, BundleException {
35.157 + for (String jar : System.getProperty("java.class.path").split(File.pathSeparator)) {
35.158 + File file = new File(jar);
35.159 + if (!file.isFile()) {
35.160 + LOG.info("Not loading " + file);
35.161 + continue;
35.162 + }
35.163 + JarFile jf = new JarFile(file);
35.164 + final String name = jf.getManifest().getMainAttributes().getValue("Bundle-SymbolicName");
35.165 + jf.close();
35.166 + if (name != null) {
35.167 + if (name.contains("org.eclipse.osgi")) {
35.168 + continue;
35.169 + }
35.170 + if (name.contains("testng")) {
35.171 + continue;
35.172 + }
35.173 + final String path = "reference:" + file.toURI().toString();
35.174 + try {
35.175 + Bundle b = f.getBundleContext().installBundle(path);
35.176 + } catch (BundleException ex) {
35.177 + LOG.log(Level.WARNING, "Cannot install " + file, ex);
35.178 + }
35.179 + }
35.180 + }
35.181 + }
35.182 +
35.183 + private static Class<?> loadOSGiClass(Class<?> c) throws Exception {
35.184 + return KnockoutEquinoxTCKImpl.loadOSGiClass(c.getName(), KnockoutEquinoxIT.framework().getBundleContext());
35.185 + }
35.186 +
35.187 + private static Class<?> browserClass;
35.188 + private static Object browserContext;
35.189 +
35.190 + @Factory public static Object[] compatibilityTests() throws Exception {
35.191 + Class<?> tck = loadOSGiClass(KnockoutTCK.class);
35.192 + Class<?> peer = loadOSGiClass(KnockoutEquinoxTCKImpl.class);
35.193 + // initialize the TCK
35.194 + Callable<Class[]> inst = (Callable<Class[]>) peer.newInstance();
35.195 +
35.196 + Class[] arr = inst.call();
35.197 + for (int i = 0; i < arr.length; i++) {
35.198 + if (arr[i].getClassLoader() == ClassLoader.getSystemClassLoader()) {
35.199 + fail("Should be an OSGi class: " + arr[i]);
35.200 + }
35.201 + }
35.202 +
35.203 + URI uri = DynamicHTTP.initServer();
35.204 +
35.205 + Method start = peer.getMethod("start", URI.class);
35.206 + start.invoke(null, uri);
35.207 +
35.208 + ClassLoader l = getClassLoader();
35.209 + List<Object> res = new ArrayList<Object>();
35.210 + for (int i = 0; i < arr.length; i++) {
35.211 + seekKOTests(arr[i], res);
35.212 + }
35.213 + return res.toArray();
35.214 + }
35.215 +
35.216 + private static void seekKOTests(Class<?> c, List<Object> res) throws SecurityException, ClassNotFoundException {
35.217 + Class<? extends Annotation> koTest =
35.218 + c.getClassLoader().loadClass(KOTest.class.getName()).
35.219 + asSubclass(Annotation.class);
35.220 + for (Method m : c.getMethods()) {
35.221 + if (m.getAnnotation(koTest) != null) {
35.222 + res.add(new KOFx(browserContext, m));
35.223 + }
35.224 + }
35.225 + }
35.226 +
35.227 + static synchronized ClassLoader getClassLoader() throws InterruptedException {
35.228 + while (browserClass == null) {
35.229 + KnockoutEquinoxIT.class.wait();
35.230 + }
35.231 + return browserClass.getClassLoader();
35.232 + }
35.233 +
35.234 + public static synchronized void initialized(Class<?> browserCls, Object presenter) throws Exception {
35.235 + browserClass = browserCls;
35.236 + browserContext = presenter;
35.237 + KnockoutEquinoxIT.class.notifyAll();
35.238 + }
35.239 +
35.240 + static Closeable activateInOSGi(Object presenter) throws Exception {
35.241 + Class<?> presenterClass = loadOSGiClass(Fn.Presenter.class);
35.242 + Class<?> fnClass = loadOSGiClass(Fn.class);
35.243 + Method m = fnClass.getMethod("activate", presenterClass);
35.244 + return (Closeable) m.invoke(null, presenter);
35.245 + }
35.246 +}
36.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
36.2 +++ b/ko-osgi-test/src/test/resources/org/netbeans/html/ko/osgi/test/test.html Mon Jan 06 09:44:07 2014 +0100
36.3 @@ -0,0 +1,56 @@
36.4 +<!--
36.5 +
36.6 + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
36.7 +
36.8 + Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
36.9 +
36.10 + Oracle and Java are registered trademarks of Oracle and/or its affiliates.
36.11 + Other names may be trademarks of their respective owners.
36.12 +
36.13 + The contents of this file are subject to the terms of either the GNU
36.14 + General Public License Version 2 only ("GPL") or the Common
36.15 + Development and Distribution License("CDDL") (collectively, the
36.16 + "License"). You may not use this file except in compliance with the
36.17 + License. You can obtain a copy of the License at
36.18 + http://www.netbeans.org/cddl-gplv2.html
36.19 + or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
36.20 + specific language governing permissions and limitations under the
36.21 + License. When distributing the software, include this License Header
36.22 + Notice in each file and include the License file at
36.23 + nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
36.24 + particular file as subject to the "Classpath" exception as provided
36.25 + by Oracle in the GPL Version 2 section of the License file that
36.26 + accompanied this code. If applicable, add the following below the
36.27 + License Header, with the fields enclosed by brackets [] replaced by
36.28 + your own identifying information:
36.29 + "Portions Copyrighted [year] [name of copyright owner]"
36.30 +
36.31 + Contributor(s):
36.32 +
36.33 + The Original Software is NetBeans. The Initial Developer of the Original
36.34 + Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
36.35 +
36.36 + If you wish your version of this file to be governed by only the CDDL
36.37 + or only the GPL Version 2, indicate your decision by adding
36.38 + "[Contributor] elects to include this software in this distribution
36.39 + under the [CDDL or GPL Version 2] license." If you do not indicate a
36.40 + single choice of license, a recipient has the option to distribute
36.41 + your version of this file under either the CDDL, the GPL Version 2 or
36.42 + to extend the choice of license to its licensees as provided above.
36.43 + However, if you add GPL Version 2 code and therefore, elected the GPL
36.44 + Version 2 license, then the option applies only if the new code is
36.45 + made subject to such option by the copyright holder.
36.46 +
36.47 +-->
36.48 +<!DOCTYPE html>
36.49 +<html>
36.50 + <head>
36.51 + <title>Knockout.fx Execution Harness</title>
36.52 + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
36.53 + <meta name="viewport" content="width=device-width">
36.54 + </head>
36.55 + <body>
36.56 + <h1>Knockout.fx Execution Harness</h1>
36.57 + </body>
36.58 + <script></script>
36.59 +</html>
37.1 --- a/pom.xml Mon Dec 16 18:08:40 2013 +0100
37.2 +++ b/pom.xml Mon Jan 06 09:44:07 2014 +0100
37.3 @@ -30,6 +30,8 @@
37.4 <module>boot-fx</module>
37.5 <module>geo</module>
37.6 <module>ko-ws-tyrus</module>
37.7 + <module>ko-osgi-test</module>
37.8 + <module>equinox-agentclass-hook</module>
37.9 </modules>
37.10 <licenses>
37.11 <license>