http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/json/src/test/java/org/netbeans/html/json/impl/OnReceiveTest.java ---------------------------------------------------------------------- diff --git a/json/src/test/java/org/netbeans/html/json/impl/OnReceiveTest.java b/json/src/test/java/org/netbeans/html/json/impl/OnReceiveTest.java new file mode 100644 index 0000000..f2a52bb --- /dev/null +++ b/json/src/test/java/org/netbeans/html/json/impl/OnReceiveTest.java @@ -0,0 +1,180 @@ +/** + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved. + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + */ +package org.netbeans.html.json.impl; + +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; +import net.java.html.BrwsrCtx; +import net.java.html.json.Models; +import net.java.html.json.Person; +import org.netbeans.html.context.spi.Contexts; +import org.netbeans.html.json.spi.JSONCall; +import org.netbeans.html.json.spi.Transfer; +import static org.testng.Assert.*; +import org.testng.annotations.Test; + +/** + * + * @author Jaroslav Tulach + */ +public class OnReceiveTest { + @Test public void performJSONCall() { + MockTrans mt = new MockTrans(); + BrwsrCtx ctx = Contexts.newBuilder().register(Transfer.class, mt, 1).build(); + + Employee e = Models.bind(new Employee(), ctx); + e.setCall(null); + Person p = new Person(); + + mt.result = new HashMap<String, String>(); + mt.result.put("firstName", "Jarda"); + mt.result.put("lastName", "Tulach"); + e.changePersonalities(1, 2.0, "3", p); + final Call c = e.getCall(); + assertNotNull(c, "A call has been made"); + assertEquals(c.getI(), 1); + assertEquals(c.getD(), 2.0); + assertEquals(c.getS(), "3"); + assertEquals(c.getP(), p); + assertEquals(c.getData().size(), 1, "One result sent over wire"); + assertEquals(c.getData().get(0).getFirstName(), "Jarda"); + assertEquals(c.getData().get(0).getLastName(), "Tulach"); + } + + @Test public void performErrorJSONCallNoHandling() { + MockTrans mt = new MockTrans(); + mt.err = new Exception("Error"); + BrwsrCtx ctx = Contexts.newBuilder().register(Transfer.class, mt, 1).build(); + + Employee e = Models.bind(new Employee(), ctx); + e.setCall(null); + Person p = new Person(); + + mt.result = new HashMap<String, String>(); + mt.result.put("firstName", "Jarda"); + mt.result.put("lastName", "Tulach"); + e.changePersonalities(1, 2.0, "3", p); + final Call c = e.getCall(); + assertNull(c, "Error has been swallowed"); + } + + @Test public void performErrorJSONCall() { + MockTrans mt = new MockTrans(); + mt.err = new Exception("Error"); + BrwsrCtx ctx = Contexts.newBuilder().register(Transfer.class, mt, 1).build(); + + Employee e = Models.bind(new Employee(), ctx); + e.setCall(null); + Person p = new Person(); + + mt.result = new HashMap<String, String>(); + mt.result.put("firstName", "Jarda"); + mt.result.put("lastName", "Tulach"); + e.changePersonalitiesWithEx(1, 2.0, "3", p); + final Call c = e.getCall(); + assertNotNull(c, "A call has been made"); + assertTrue(c.getData().isEmpty(), "No data provided"); + + assertEquals(c.getI(), -1); + assertEquals(c.getD(), -1.0); + assertEquals(c.getS(), null); + assertEquals(c.getP(), null); + } + + @Test public void performErrorWithValuesJSONCall() { + MockTrans mt = new MockTrans(); + mt.err = new Exception("Error"); + BrwsrCtx ctx = Contexts.newBuilder().register(Transfer.class, mt, 1).build(); + + Employee e = Models.bind(new Employee(), ctx); + e.setCall(null); + Person p = new Person(); + + mt.result = new HashMap<String, String>(); + mt.result.put("firstName", "Jarda"); + mt.result.put("lastName", "Tulach"); + e.changePersonalitiesWithParam(1, 2.0, "3", p); + final Call c = e.getCall(); + assertNotNull(c, "A call has been made"); + assertTrue(c.getData().isEmpty(), "No data provided"); + + assertEquals(c.getI(), 1); + assertEquals(c.getD(), 2.0); + assertEquals(c.getS(), "3"); + assertEquals(c.getP(), p); + } + + + public static class MockTrans implements Transfer { + Map<String,String> result; + Exception err; + + @Override + public void extract(Object obj, String[] props, Object[] values) { + assertTrue(obj instanceof Map, "It is a map: " + obj); + Map<?,?> mt = (Map<?,?>) obj; + for (int i = 0; i < props.length; i++) { + values[i] = mt.get(props[i]); + } + } + + @Override + public Object toJSON(InputStream is) throws IOException { + throw new IOException(); + } + + @Override + public void loadJSON(JSONCall call) { + Object r = result; + assertNotNull(r, "We need a reply!"); + result = null; + if (err != null) { + call.notifyError(err); + } else { + call.notifySuccess(r); + } + } + } +}
http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/json/src/test/java/org/netbeans/html/json/impl/ParallelChangeTest.java ---------------------------------------------------------------------- diff --git a/json/src/test/java/org/netbeans/html/json/impl/ParallelChangeTest.java b/json/src/test/java/org/netbeans/html/json/impl/ParallelChangeTest.java new file mode 100644 index 0000000..66c89e3 --- /dev/null +++ b/json/src/test/java/org/netbeans/html/json/impl/ParallelChangeTest.java @@ -0,0 +1,199 @@ +/** + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved. + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + */ +package org.netbeans.html.json.impl; + +import java.util.Map; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import net.java.html.BrwsrCtx; +import net.java.html.json.ComputedProperty; +import net.java.html.json.Model; +import net.java.html.json.Models; +import net.java.html.json.Property; +import org.netbeans.html.context.spi.Contexts; +import org.netbeans.html.json.impl.DeepChangeTest.One; +import org.netbeans.html.json.spi.Technology; +import org.netbeans.html.json.spi.Transfer; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; +import static org.testng.Assert.assertEquals; + +public class ParallelChangeTest { + private DeepChangeTest.MapTechnology t; + private BrwsrCtx c; + + @BeforeMethod public void initTechnology() { + t = new DeepChangeTest.MapTechnology(); + c = Contexts.newBuilder().register(Technology.class, t, 1). + register(Transfer.class, t, 1).build(); + } + + @Test + public void multipleValues() throws InterruptedException { + doTest(true); + } + + @Test + public void singleValue() throws InterruptedException { + doTest(false); + } + + private void doTest(boolean multipleValues) throws InterruptedException { + class Test implements Runnable { + final int offset; + final Depending dep; + private Error error; + + public Test(int index, Depending dep) { + this.offset = index; + this.dep = dep; + } + + @Override + public void run() { + try { + int value = dep.getValuePlusAdd(); + assertEquals(value, offset + 11, "Offset " + offset + " plus one plus ten"); + } catch (Error err) { + this.error = err; + } + } + + private void assertException() { + if (error != null) { + throw error; + } + } + } + + Depending[] deps = new Depending[2]; + BlockingValue[] values = new BlockingValue[deps.length]; + CountDownLatch blockInCall = new CountDownLatch(deps.length); + Test[] runs = new Test[deps.length]; + ExecutorService exec = Executors.newFixedThreadPool(deps.length); + for (int i = 0; i < deps.length; i++) { + if (multipleValues) { + values[i] = BlockingValueCntrl.create(c); + } else { + values[i] = i == 0 ? BlockingValueCntrl.create(c) : values[0]; + } + deps[i] = DependingCntrl.create(c, values[i], 10); + runs[i] = new Test(0, deps[i]); + } + BlockingValueCntrl.initialize(blockInCall); + for (int i = 0; i < deps.length; i++) { + exec.execute(runs[i]); + } + + exec.awaitTermination(1, TimeUnit.SECONDS); + + for (int i = 0; i < deps.length; i++) { + Map raw = (Map) Models.toRaw(deps[i]); + One value = (One) raw.get("valuePlusAdd"); + value.assertNoChange("No changes yet for index " + i); + } + + for (int i = 0; i < deps.length; i++) { + runs[i].assertException(); + values[i].setValue(30); + } + + for (int i = 0; i < deps.length; i++) { + Map raw = (Map) Models.toRaw(deps[i]); + One value = (One) raw.get("valuePlusAdd"); + value.assertChange("A change for index " + i); + } + + for (int i = 0; i < deps.length; i++) { + assertEquals(deps[i].getValuePlusAdd(), 41, "[" + i + "] = 0 plus 30 plus one plus 10"); + } + } + + @Model(className="BlockingValue", properties = { + @Property(name = "value", type = int.class) + }) + static class BlockingValueCntrl { + private static CountDownLatch latch; + + static void initialize(CountDownLatch l) { + latch = l; + } + + @ComputedProperty + static int plusOne(int value) { + if (latch != null) { + latch.countDown(); + try { + latch.await(); + } catch (InterruptedException ex) { + throw new IllegalStateException(ex); + } + } + return value + 1; + } + + static BlockingValue create(BrwsrCtx c) { + return Models.bind(new BlockingValue(), c); + } + } + + @Model(className = "Depending", properties = { + @Property(name = "add", type = int.class), + @Property(name = "dep", type = BlockingValue.class) + }) + static class DependingCntrl { + @ComputedProperty + static int valuePlusAdd(BlockingValue dep, int add) { + return dep.getPlusOne() + add; + } + + static Depending create(BrwsrCtx c, BlockingValue value, int add) { + Depending d = Models.bind(new Depending(add, null), c); + d.setDep(value); + return d; + } + } + +} http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/json/src/test/java/org/netbeans/html/json/impl/ToDoTest.java ---------------------------------------------------------------------- diff --git a/json/src/test/java/org/netbeans/html/json/impl/ToDoTest.java b/json/src/test/java/org/netbeans/html/json/impl/ToDoTest.java new file mode 100644 index 0000000..e12d443 --- /dev/null +++ b/json/src/test/java/org/netbeans/html/json/impl/ToDoTest.java @@ -0,0 +1,132 @@ +/** + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved. + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + */ +package org.netbeans.html.json.impl; + +import java.util.List; +import java.util.Map; +import net.java.html.BrwsrCtx; +import net.java.html.json.ComputedProperty; +import net.java.html.json.Model; +import net.java.html.json.Models; +import net.java.html.json.Property; +import org.netbeans.html.context.spi.Contexts; +import org.netbeans.html.json.spi.Technology; +import org.netbeans.html.json.spi.Transfer; +import org.netbeans.html.json.impl.DeepChangeTest.MapTechnology; +import org.netbeans.html.json.impl.DeepChangeTest.One; +import static org.testng.Assert.*; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +/** + * + * @author Jaroslav Tulach + */ +@Model(className = "TodoUI", properties = { + @Property(name = "todos", type = Todo.class, array = true), + @Property(name = "todoText", type = String.class) +}) +public class ToDoTest { + @Model(className = "Todo", properties = { + @Property(name = "text", type = String.class), + @Property(name = "done", type = boolean.class) + }) + static class ItemCtrl { + } + + @ComputedProperty + static int remaining( + List<Todo> todos, String todoText + ) { + int count = 0; + for (Todo d : todos) { + if (!d.isDone()) { + count++; + } + } + return count; + } + + private MapTechnology t; + private BrwsrCtx c; + + @BeforeMethod + public void initTechnology() { + t = new MapTechnology(); + c = Contexts.newBuilder().register(Technology.class, t, 1). + register(Transfer.class, t, 1).build(); + } + + + @Test public void checkAndUncheckFirstItem() throws Exception { + TodoUI ui = Models.bind( + new TodoUI( + null, + new Todo("First", false), + new Todo("2nd", true), + new Todo("Third", false) + ), c); + Models.applyBindings(ui); + + Map m = (Map) Models.toRaw(ui); + Object v = m.get("remaining"); + assertNotNull(v, "Value should be in the map"); + assertEquals(v.getClass(), One.class, "It is instance of One"); + One o = (One) v; + assertEquals(o.changes, 0, "No changes so far"); + assertTrue(o.pb.isReadOnly(), "Derived property"); + assertEquals(o.get(), 2); + + ui.getTodos().get(0).setDone(true); + + assertEquals(o.get(), 1); + assertEquals(o.changes, 1, "One change so far"); + + ui.getTodos().get(0).setDone(false); + + assertEquals(o.get(), 2); + assertEquals(o.changes, 2, "2nd change so far"); + + } + +} http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/ko-felix-test/pom.xml ---------------------------------------------------------------------- diff --git a/ko-felix-test/pom.xml b/ko-felix-test/pom.xml new file mode 100644 index 0000000..591127e --- /dev/null +++ b/ko-felix-test/pom.xml @@ -0,0 +1,184 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + + Copyright 2013-2016 Oracle and/or its affiliates. All rights reserved. + + Oracle and Java are registered trademarks of Oracle and/or its affiliates. + Other names may be trademarks of their respective owners. + + The contents of this file are subject to the terms of either the GNU + General Public License Version 2 only ("GPL") or the Common + Development and Distribution License("CDDL") (collectively, the + "License"). You may not use this file except in compliance with the + License. You can obtain a copy of the License at + http://www.netbeans.org/cddl-gplv2.html + or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + specific language governing permissions and limitations under the + License. When distributing the software, include this License Header + Notice in each file and include the License file at + nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + particular file as subject to the "Classpath" exception as provided + by Oracle in the GPL Version 2 section of the License file that + accompanied this code. If applicable, add the following below the + License Header, with the fields enclosed by brackets [] replaced by + your own identifying information: + "Portions Copyrighted [year] [name of copyright owner]" + + Contributor(s): + + The Original Software is NetBeans. The Initial Developer of the Original + Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved. + + If you wish your version of this file to be governed by only the CDDL + or only the GPL Version 2, indicate your decision by adding + "[Contributor] elects to include this software in this distribution + under the [CDDL or GPL Version 2] license." If you do not indicate a + single choice of license, a recipient has the option to distribute + your version of this file under either the CDDL, the GPL Version 2 or + to extend the choice of license to its licensees as provided above. + However, if you add GPL Version 2 code and therefore, elected the GPL + Version 2 license, then the option applies only if the new code is + made subject to such option by the copyright holder. + +--> +<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"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.netbeans.html</groupId> + <artifactId>pom</artifactId> + <version>2.0-SNAPSHOT</version> + </parent> + <name>KO Tests in Felix OSGi Container</name> + <artifactId>ko-felix-test</artifactId> + <packaging>bundle</packaging> + <description>Runs the TCK for Knockout in Felix OSGi Container</description> + <properties> + <netbeans.compile.on.save>none</netbeans.compile.on.save> + </properties> + <build> + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + </plugin> + <plugin> + <groupId>org.netbeans.html</groupId> + <artifactId>html4j-maven-plugin</artifactId> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-deploy-plugin</artifactId> + <configuration> + <skip>true</skip> + </configuration> + </plugin> + <plugin> + <artifactId>maven-failsafe-plugin</artifactId> + <configuration> + <additionalClasspathElements> + <additionalClasspathElement>${project.build.directory}/${project.build.finalName}.jar</additionalClasspathElement> + </additionalClasspathElements> + <forkMode>always</forkMode> + </configuration> + <executions> + <execution> + <goals> + <goal>integration-test</goal> + <goal>verify</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> + <dependencies> + <dependency> + <groupId>com.oracle</groupId> + <artifactId>javafx</artifactId> + <version>2.2</version> + <scope>system</scope> + <systemPath>${jfxrt.jar}</systemPath> + </dependency> + <dependency> + <groupId>de.twentyeleven.skysail</groupId> + <artifactId>org.json-osgi</artifactId> + </dependency> + <dependency> + <groupId>org.netbeans.html</groupId> + <artifactId>net.java.html.json</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.testng</groupId> + <artifactId>testng</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>net.java.html.json.tck</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.netbeans.api</groupId> + <artifactId>org-openide-util-lookup</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.netbeans.html</groupId> + <artifactId>net.java.html.boot</artifactId> + <version>${project.version}</version> + <type>jar</type> + </dependency> + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>ko4j</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>net.java.html.boot.fx</artifactId> + <version>${project.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.glassfish.grizzly</groupId> + <artifactId>grizzly-http-server</artifactId> + <version>${grizzly.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.glassfish.grizzly</groupId> + <artifactId>grizzly-websockets-server</artifactId> + <version>${grizzly.version}</version> + <scope>test</scope> + <type>jar</type> + </dependency> + <dependency> + <groupId>org.glassfish.grizzly</groupId> + <artifactId>grizzly-http-servlet</artifactId> + <version>${grizzly.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>javax.servlet</groupId> + <artifactId>javax.servlet-api</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.felix</groupId> + <artifactId>org.apache.felix.framework</artifactId> + </dependency> + <dependency> + <groupId>org.apache.aries.spifly</groupId> + <artifactId>org.apache.aries.spifly.dynamic.bundle</artifactId> + <version>1.0.4</version> + </dependency> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.service.log</artifactId> + <version>1.3.0</version> + </dependency> + </dependencies> +</project> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/ko-felix-test/src/main/java/org/netbeans/html/ko/felix/test/KnockoutFelixTCKImpl.java ---------------------------------------------------------------------- diff --git a/ko-felix-test/src/main/java/org/netbeans/html/ko/felix/test/KnockoutFelixTCKImpl.java b/ko-felix-test/src/main/java/org/netbeans/html/ko/felix/test/KnockoutFelixTCKImpl.java new file mode 100644 index 0000000..c085ff3 --- /dev/null +++ b/ko-felix-test/src/main/java/org/netbeans/html/ko/felix/test/KnockoutFelixTCKImpl.java @@ -0,0 +1,283 @@ +/** + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved. + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + */ +package org.netbeans.html.ko.felix.test; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.net.URLConnection; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Enumeration; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Callable; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; +import net.java.html.BrwsrCtx; +import net.java.html.boot.BrowserBuilder; +import net.java.html.js.JavaScriptBody; +import org.netbeans.html.boot.spi.Fn; +import org.netbeans.html.context.spi.Contexts; +import org.netbeans.html.json.spi.Technology; +import org.netbeans.html.json.spi.Transfer; +import org.netbeans.html.json.tck.KnockoutTCK; +import org.openide.util.lookup.ServiceProvider; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.FrameworkUtil; + +/** + * + * @author Jaroslav Tulach + */ +@ServiceProvider(service = KnockoutTCK.class) +public class KnockoutFelixTCKImpl extends KnockoutTCK implements Callable<Class[]> { + + private static Fn.Presenter browserContext; + + public static Class loadOSGiClass(String name, BundleContext ctx) throws Exception { + for (Bundle b : ctx.getBundles()) { + try { + Class<?> osgiClass = b.loadClass(name); + if (osgiClass != null && osgiClass.getClassLoader() != ClassLoader.getSystemClassLoader()) { + return osgiClass; + } + } catch (ClassNotFoundException cnfe) { + // go on + } + } + throw new IllegalStateException("Cannot load " + name + " from the OSGi container!"); + } + + @Override + public Class[] call() throws Exception { + return testClasses(); + } + + public static void start(String callBackClass, URI server, final boolean useAllClassloader) throws Exception { + final BrowserBuilder bb = BrowserBuilder.newBrowser().loadClass(KnockoutFelixTCKImpl.class). + loadPage(server.toString()). + invoke("initialized", callBackClass); + + Executors.newSingleThreadExecutor().submit(new Runnable() { + @Override + public void run() { + try { + Bundle[] arr = FrameworkUtil.getBundle(BrowserBuilder.class).getBundleContext().getBundles(); + if (useAllClassloader) { + final ClassLoader osgiClassLoader = new AllBundlesLoader(arr); + bb.classloader(osgiClassLoader); + } + bb.showAndWait(); + } catch (Throwable t) { + t.printStackTrace(); + } + } + }); + } + + public static void initialized(String... args) throws Exception { + Bundle bundle = FrameworkUtil.getBundle(KnockoutFelixTCKImpl.class); + if (bundle == null) { + throw new IllegalStateException( + "Should be loaded from a bundle. But was: " + KnockoutFelixTCKImpl.class.getClassLoader() + ); + } + Class<?> classpathClass = ClassLoader.getSystemClassLoader().loadClass(args[0]); + Method m = classpathClass.getMethod("initialized", Class.class, Object.class); + browserContext = Fn.activePresenter(); + m.invoke(null, KnockoutFelixTCKImpl.class, browserContext); + } + + @Override + public BrwsrCtx createContext() { + try { + Contexts.Builder cb = Contexts.newBuilder(). + register(Technology.class, (Technology)osgiInstance("KOTech"), 10). + register(Transfer.class, (Transfer)osgiInstance("KOTransfer"), 10). + register(Executor.class, (Executor)browserContext, 10); +// if (fx.areWebSocketsSupported()) { +// cb.register(WSTransfer.class, fx, 10); +// } + return cb.build(); + } catch (Exception ex) { + throw new IllegalStateException(ex); + } + } + + private Object osgiInstance(String simpleName) throws IllegalAccessException, SecurityException, IllegalArgumentException, Exception, NoSuchMethodException, InstantiationException, InvocationTargetException { + Class<?> fxCls = loadOSGiClass( + "org.netbeans.html.ko4j." + simpleName, + FrameworkUtil.getBundle(KnockoutFelixTCKImpl.class).getBundleContext() + ); + final Constructor<?> cnstr = fxCls.getDeclaredConstructor(); + cnstr.setAccessible(true); + Object fx = cnstr.newInstance(); + return fx; + } + + @Override + public Object createJSON(Map<String, Object> values) { + Object json = createObj(); + for (Map.Entry<String, Object> entry : values.entrySet()) { + putObj(json, entry.getKey(), entry.getValue()); + } + return json; + } + + @JavaScriptBody(args = { }, body = "return {};") + private static native Object createObj(); + @JavaScriptBody(args = { "obj", "prop", "val" }, body = "obj[prop] = val;") + private static native void putObj(Object obj, String prop, Object val); + + @Override + @JavaScriptBody(args = { "s", "args" }, body = "" + + "var f = new Function(s); " + + "return f.apply(null, args);" + ) + public native Object executeScript(String script, Object[] arguments); + + @JavaScriptBody(args = { }, body = + "var h;" + + "if (!!window && !!window.location && !!window.location.href)\n" + + " h = window.location.href;\n" + + "else " + + " h = null;" + + "return h;\n" + ) + private static native String findBaseURL(); + + @Override + public URI prepareURL(String content, String mimeType, String[] parameters) { + try { + final URL baseURL = new URL(findBaseURL()); + StringBuilder sb = new StringBuilder(); + sb.append("/dynamic?mimeType=").append(mimeType); + for (int i = 0; i < parameters.length; i++) { + sb.append("¶m" + i).append("=").append(parameters[i]); + } + String mangle = content.replace("\n", "%0a") + .replace("\"", "\\\"").replace(" ", "%20"); + sb.append("&content=").append(mangle); + + URL query = new URL(baseURL, sb.toString()); + URLConnection c = query.openConnection(); + BufferedReader br = new BufferedReader(new InputStreamReader(c.getInputStream())); + URI connectTo = new URI(br.readLine()); + return connectTo; + } catch (IOException ex) { + throw new IllegalStateException(ex); + } catch (URISyntaxException ex) { + throw new IllegalStateException(ex); + } + } + + @Override + public boolean canFailWebSocketTest() { + return true; + } + + private static final class AllBundlesLoader extends ClassLoader { + private final Bundle[] arr; + + public AllBundlesLoader(Bundle[] arr) { + super(ClassLoader.getSystemClassLoader().getParent()); + this.arr = arr; + } + + @Override + public Class<?> loadClass(String name) throws ClassNotFoundException { + return loadClass(name, false); + } + + @Override + protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { + ClassNotFoundException err = null; + for (Bundle b : arr) { + try { + Class<?> cls = b.loadClass(name); + if (FrameworkUtil.getBundle(cls) == b) { + return cls; + } + } catch (ClassNotFoundException ex) { + err = ex; + } + } + throw err; + } + + @Override + protected URL findResource(String name) { + for (Bundle b : arr) { + URL r = b.getResource(name); + if (r != null) { + return r; + } + } + return null; + } + + @Override + protected Enumeration<URL> findResources(String name) throws IOException { + List<URL> ret = new ArrayList<URL>(); + for (Bundle b : arr) { + Enumeration<URL> en = b.getResources(name); + if (en != null) while (en.hasMoreElements()) { + URL u = en.nextElement(); + ret.add(u); + } + } + return Collections.enumeration(ret); + } + + + + } +} http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/ko-felix-test/src/test/java/org/netbeans/html/ko/felix/test/DynamicHTTP.java ---------------------------------------------------------------------- diff --git a/ko-felix-test/src/test/java/org/netbeans/html/ko/felix/test/DynamicHTTP.java b/ko-felix-test/src/test/java/org/netbeans/html/ko/felix/test/DynamicHTTP.java new file mode 100644 index 0000000..ce99dce --- /dev/null +++ b/ko-felix-test/src/test/java/org/netbeans/html/ko/felix/test/DynamicHTTP.java @@ -0,0 +1,261 @@ +/** + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved. + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + */ +package org.netbeans.html.ko.felix.test; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.glassfish.grizzly.PortRange; +import org.glassfish.grizzly.http.server.HttpHandler; +import org.glassfish.grizzly.http.server.HttpServer; +import org.glassfish.grizzly.http.server.NetworkListener; +import org.glassfish.grizzly.http.server.Request; +import org.glassfish.grizzly.http.server.Response; +import org.glassfish.grizzly.http.server.ServerConfiguration; +import org.glassfish.grizzly.websockets.WebSocket; +import org.glassfish.grizzly.websockets.WebSocketAddOn; +import org.glassfish.grizzly.websockets.WebSocketApplication; +import org.glassfish.grizzly.websockets.WebSocketEngine; + +/** + * + * @author Jaroslav Tulach + */ +final class DynamicHTTP extends HttpHandler { + private static final Logger LOG = Logger.getLogger(DynamicHTTP.class.getName()); + private static int resourcesCount; + private static List<Resource> resources; + private static ServerConfiguration conf; + private static HttpServer server; + + private DynamicHTTP() { + } + + static URI initServer() throws Exception { + server = HttpServer.createSimpleServer(null, new PortRange(8080, 65535)); + final WebSocketAddOn addon = new WebSocketAddOn(); + for (NetworkListener listener : server.getListeners()) { + listener.registerAddOn(addon); + } + resources = new ArrayList<Resource>(); + + conf = server.getServerConfiguration(); + final DynamicHTTP dh = new DynamicHTTP(); + + conf.addHttpHandler(dh, "/"); + + server.start(); + + return pageURL("http", server, "/test.html"); + } + + @Override + public void service(Request request, Response response) throws Exception { + if ("/test.html".equals(request.getRequestURI())) { + response.setContentType("text/html"); + final InputStream is = DynamicHTTP.class.getResourceAsStream("test.html"); + copyStream(is, response.getOutputStream(), null); + return; + } + if ("/dynamic".equals(request.getRequestURI())) { + String mimeType = request.getParameter("mimeType"); + List<String> params = new ArrayList<String>(); + boolean webSocket = false; + for (int i = 0;; i++) { + String p = request.getParameter("param" + i); + if (p == null) { + break; + } + if ("protocol:ws".equals(p)) { + webSocket = true; + continue; + } + params.add(p); + } + final String cnt = request.getParameter("content"); + String mangle = cnt.replace("%20", " ").replace("%0A", "\n"); + ByteArrayInputStream is = new ByteArrayInputStream(mangle.getBytes("UTF-8")); + URI url; + final Resource res = new Resource(is, mimeType, "/dynamic/res" + ++resourcesCount, params.toArray(new String[params.size()])); + if (webSocket) { + url = registerWebSocket(res); + } else { + url = registerResource(res); + } + response.getWriter().write(url.toString()); + response.getWriter().write("\n"); + return; + } + + for (Resource r : resources) { + if (r.httpPath.equals(request.getRequestURI())) { + response.setContentType(r.httpType); + r.httpContent.reset(); + String[] params = null; + if (r.parameters.length != 0) { + params = new String[r.parameters.length]; + for (int i = 0; i < r.parameters.length; i++) { + params[i] = request.getParameter(r.parameters[i]); + if (params[i] == null) { + if ("http.method".equals(r.parameters[i])) { + params[i] = request.getMethod().toString(); + } else if ("http.requestBody".equals(r.parameters[i])) { + Reader rdr = request.getReader(); + StringBuilder sb = new StringBuilder(); + for (;;) { + int ch = rdr.read(); + if (ch == -1) { + break; + } + sb.append((char) ch); + } + params[i] = sb.toString(); + } else if (r.parameters[i].startsWith("http.header.")) { + params[i] = request.getHeader(r.parameters[i].substring(12)); + } + } + if (params[i] == null) { + params[i] = "null"; + } + } + } + + copyStream(r.httpContent, response.getOutputStream(), null, params); + } + } + } + + private URI registerWebSocket(Resource r) { + WebSocketEngine.getEngine().register("", r.httpPath, new WS(r)); + return pageURL("ws", server, r.httpPath); + } + + private URI registerResource(Resource r) { + if (!resources.contains(r)) { + resources.add(r); + conf.addHttpHandler(this, r.httpPath); + } + return pageURL("http", server, r.httpPath); + } + + private static URI pageURL(String proto, HttpServer server, final String page) { + NetworkListener listener = server.getListeners().iterator().next(); + int port = listener.getPort(); + try { + return new URI(proto + "://localhost:" + port + page); + } catch (URISyntaxException ex) { + throw new IllegalStateException(ex); + } + } + + static final class Resource { + + final InputStream httpContent; + final String httpType; + final String httpPath; + final String[] parameters; + + Resource(InputStream httpContent, String httpType, String httpPath, + String[] parameters) { + httpContent.mark(Integer.MAX_VALUE); + this.httpContent = httpContent; + this.httpType = httpType; + this.httpPath = httpPath; + this.parameters = parameters; + } + } + + static void copyStream(InputStream is, OutputStream os, String baseURL, String... params) throws IOException { + for (;;) { + int ch = is.read(); + if (ch == -1) { + break; + } + if (ch == '$' && params.length > 0) { + int cnt = is.read() - '0'; + if (baseURL != null && cnt == 'U' - '0') { + os.write(baseURL.getBytes("UTF-8")); + } else { + if (cnt >= 0 && cnt < params.length) { + os.write(params[cnt].getBytes("UTF-8")); + } else { + os.write('$'); + os.write(cnt + '0'); + } + } + } else { + os.write(ch); + } + } + } + + private static class WS extends WebSocketApplication { + private final Resource r; + + private WS(Resource r) { + this.r = r; + } + + @Override + public void onMessage(WebSocket socket, String text) { + try { + r.httpContent.reset(); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + copyStream(r.httpContent, out, null, text); + String s = new String(out.toByteArray(), "UTF-8"); + socket.send(s); + } catch (IOException ex) { + LOG.log(Level.WARNING, "Error processing message " + text, ex); + } + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/ko-felix-test/src/test/java/org/netbeans/html/ko/felix/test/KOFx.java ---------------------------------------------------------------------- diff --git a/ko-felix-test/src/test/java/org/netbeans/html/ko/felix/test/KOFx.java b/ko-felix-test/src/test/java/org/netbeans/html/ko/felix/test/KOFx.java new file mode 100644 index 0000000..acd21be --- /dev/null +++ b/ko-felix-test/src/test/java/org/netbeans/html/ko/felix/test/KOFx.java @@ -0,0 +1,132 @@ +/** + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved. + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + */ +package org.netbeans.html.ko.felix.test; + +import java.io.Closeable; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import javafx.application.Platform; +import org.testng.ITest; +import org.testng.annotations.Test; + +/** + * + * @author Jaroslav Tulach + */ +public final class KOFx implements ITest, Runnable { + private final Object p; + private final Method m; + private Object result; + private Object inst; + private int count; + private final Class<?> itClass; + + KOFx(Class<?> itClass, Object p, Method m) { + this.itClass = itClass; + this.p = p; + this.m = m; + } + + @Override + public String getTestName() { + return m.getName(); + } + + @Test + public synchronized void executeTest() throws Exception { + if (result == null) { + Platform.runLater(this); + wait(); + } + if (result instanceof Exception) { + throw (Exception)result; + } + if (result instanceof Error) { + throw (Error)result; + } + } + + @Override + public synchronized void run() { + boolean notify = true; + Closeable a = null; + try { + a = (Closeable) itClass.getMethod("activateInOSGi", Object.class).invoke(null, p); + if (inst == null) { + inst = m.getDeclaringClass().newInstance(); + } + result = m.invoke(inst); + if (result == null) { + result = this; + } + } catch (InvocationTargetException ex) { + Throwable r = ex.getTargetException(); + if (r instanceof InterruptedException) { + if (count++ < 10000) { + notify = false; + try { + Thread.sleep(100); + } catch (Exception ex1) { + // ignore and continue + } + Platform.runLater(this); + return; + } + } + result = r; + } catch (Exception ex) { + result = ex; + } finally { + if (notify) { + notifyAll(); + } + try { + if (a != null) a.close(); + } catch (IOException ex) { + throw new IllegalStateException(ex); + } + } + } + +} http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/ko-felix-test/src/test/java/org/netbeans/html/ko/felix/test/KnockoutFelixAriesIT.java ---------------------------------------------------------------------- diff --git a/ko-felix-test/src/test/java/org/netbeans/html/ko/felix/test/KnockoutFelixAriesIT.java b/ko-felix-test/src/test/java/org/netbeans/html/ko/felix/test/KnockoutFelixAriesIT.java new file mode 100644 index 0000000..adcfaef --- /dev/null +++ b/ko-felix-test/src/test/java/org/netbeans/html/ko/felix/test/KnockoutFelixAriesIT.java @@ -0,0 +1,258 @@ +/** + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved. + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + */ +package org.netbeans.html.ko.felix.test; + +import java.io.Closeable; +import java.io.File; +import java.io.IOException; +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.net.URI; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.ServiceLoader; +import java.util.concurrent.Callable; +import java.util.jar.JarFile; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.netbeans.html.boot.spi.Fn; +import org.netbeans.html.json.tck.KOTest; +import org.netbeans.html.json.tck.KnockoutTCK; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleException; +import org.osgi.framework.Constants; +import org.osgi.framework.launch.Framework; +import org.osgi.framework.launch.FrameworkFactory; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertTrue; +import static org.testng.Assert.fail; +import org.testng.annotations.AfterClass; +import org.testng.annotations.Factory; + +public class KnockoutFelixAriesIT { + private static final Logger LOG = Logger.getLogger(KnockoutFelixAriesIT.class.getName()); + private static Framework framework; + private static File dir; + static Framework framework() throws Exception { + if (framework != null) { + return framework; + } + for (FrameworkFactory ff : ServiceLoader.load(FrameworkFactory.class)) { + + String basedir = System.getProperty("basedir"); + assertNotNull("basedir preperty provided", basedir); + File target = new File(basedir, "target"); + dir = new File(target, "osgi-aries"); + dir.mkdirs(); + + Map<String,String> config = new HashMap<String, String>(); + config.put(Constants.FRAMEWORK_STORAGE, dir.getPath()); + config.put(Constants.FRAMEWORK_STORAGE_CLEAN, "true"); + config.put(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA, "sun.misc," + + "javafx.application," + + "javafx.beans," + + "javafx.beans.property," + + "javafx.beans.value," + + "javafx.collections," + + "javafx.concurrent," + + "javafx.event," + + "javafx.geometry," + + "javafx.scene," + + "javafx.scene.control," + + "javafx.scene.image," + + "javafx.scene.layout," + + "javafx.scene.text," + + "javafx.scene.web," + + "javafx.stage," + + "javafx.util," + + "netscape.javascript" + ); + framework = ff.newFramework(config); + framework.init(); + loadClassPathBundles(framework); + framework.start(); + boolean ok = false; + for (Bundle b : framework.getBundleContext().getBundles()) { + try { + if (!b.getSymbolicName().equals("org.apache.aries.spifly.dynamic.bundle")) { + continue; + } + b.start(); + ok = true; + LOG.log(Level.INFO, "Started {0}", b.getSymbolicName()); + } catch (BundleException ex) { + LOG.log(Level.WARNING, "Cannot start bundle " + b.getSymbolicName(), ex); + } + } + assertTrue(ok, "Aries installed"); + for (Bundle b : framework.getBundleContext().getBundles()) { + try { + if (b.getSymbolicName().contains("felix.framework")) { + continue; + } + if (b.getSymbolicName().contains("glassfish.grizzly")) { + continue; + } + b.start(); + LOG.log(Level.INFO, "Started {0}", b.getSymbolicName()); + } catch (BundleException ex) { + LOG.log(Level.WARNING, "Cannot start bundle " + b.getSymbolicName(), ex); + } + } + return framework; + } + fail("No OSGi framework in the path"); + return null; + } + + @AfterClass public static void cleanUp() throws Exception { + if (framework != null) framework.stop(); + clearUpDir(dir); + } + private static void clearUpDir(File dir) { + if (dir.isDirectory()) { + for (File f : dir.listFiles()) { + clearUpDir(f); + } + } + dir.delete(); + } + + + + private static void loadClassPathBundles(Framework f) throws IOException, BundleException { + for (String jar : System.getProperty("java.class.path").split(File.pathSeparator)) { + File file = new File(jar); + if (!file.isFile()) { + LOG.info("Not loading " + file); + continue; + } + JarFile jf = new JarFile(file); + final String name = jf.getManifest().getMainAttributes().getValue("Bundle-SymbolicName"); + jf.close(); + if (name != null) { + if (name.contains("org.eclipse.osgi")) { + throw new IllegalStateException("Found " + name + " !"); + } + if (name.contains("felix.framework")) { + continue; + } + if (name.contains("testng")) { + continue; + } + final String path = "reference:" + file.toURI().toString(); + try { + Bundle b = f.getBundleContext().installBundle(path); + } catch (BundleException ex) { + LOG.log(Level.WARNING, "Cannot install " + file, ex); + } + } + } + } + + private static Class<?> loadOSGiClass(Class<?> c) throws Exception { + return KnockoutFelixTCKImpl.loadOSGiClass(c.getName(), KnockoutFelixAriesIT.framework().getBundleContext()); + } + + private static Class<?> browserClass; + private static Object browserContext; + + @Factory public static Object[] compatibilityTests() throws Exception { + Class<?> tck = loadOSGiClass(KnockoutTCK.class); + Class<?> peer = loadOSGiClass(KnockoutFelixTCKImpl.class); + // initialize the TCK + Callable<Class[]> inst = (Callable<Class[]>) peer.newInstance(); + + Class[] arr = inst.call(); + for (int i = 0; i < arr.length; i++) { + if (arr[i].getClassLoader() == ClassLoader.getSystemClassLoader()) { + fail("Should be an OSGi class: " + arr[i]); + } + } + + URI uri = DynamicHTTP.initServer(); + + Method start = peer.getMethod("start", String.class, URI.class, boolean.class); + start.invoke(null, KnockoutFelixAriesIT.class.getName(), uri, false); + + ClassLoader l = getClassLoader(); + List<Object> res = new ArrayList<Object>(); + for (int i = 0; i < arr.length; i++) { + seekKOTests(arr[i], res); + } + return res.toArray(); + } + + private static void seekKOTests(Class<?> c, List<Object> res) throws SecurityException, ClassNotFoundException { + Class<? extends Annotation> koTest = + c.getClassLoader().loadClass(KOTest.class.getName()). + asSubclass(Annotation.class); + for (Method m : c.getMethods()) { + if (m.getAnnotation(koTest) != null) { + res.add(new KOFx(KnockoutFelixAriesIT.class, browserContext, m)); + } + } + } + + static synchronized ClassLoader getClassLoader() throws InterruptedException { + while (browserClass == null) { + KnockoutFelixAriesIT.class.wait(); + } + return browserClass.getClassLoader(); + } + + public static synchronized void initialized(Class<?> browserCls, Object presenter) throws Exception { + browserClass = browserCls; + browserContext = presenter; + KnockoutFelixAriesIT.class.notifyAll(); + } + + public static Closeable activateInOSGi(Object presenter) throws Exception { + Class<?> presenterClass = loadOSGiClass(Fn.Presenter.class); + Class<?> fnClass = loadOSGiClass(Fn.class); + Method m = fnClass.getMethod("activate", presenterClass); + return (Closeable) m.invoke(null, presenter); + } +} http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/ko-felix-test/src/test/java/org/netbeans/html/ko/felix/test/KnockoutFelixIT.java ---------------------------------------------------------------------- diff --git a/ko-felix-test/src/test/java/org/netbeans/html/ko/felix/test/KnockoutFelixIT.java b/ko-felix-test/src/test/java/org/netbeans/html/ko/felix/test/KnockoutFelixIT.java new file mode 100644 index 0000000..7d085d9 --- /dev/null +++ b/ko-felix-test/src/test/java/org/netbeans/html/ko/felix/test/KnockoutFelixIT.java @@ -0,0 +1,253 @@ +/** + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved. + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + */ +package org.netbeans.html.ko.felix.test; + +import java.io.Closeable; +import java.io.File; +import java.io.IOException; +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.net.URI; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.ServiceLoader; +import java.util.concurrent.Callable; +import java.util.jar.JarFile; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.netbeans.html.boot.spi.Fn; +import org.netbeans.html.json.tck.KOTest; +import org.netbeans.html.json.tck.KnockoutTCK; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleException; +import org.osgi.framework.Constants; +import org.osgi.framework.launch.Framework; +import org.osgi.framework.launch.FrameworkFactory; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.fail; +import org.testng.annotations.AfterClass; +import org.testng.annotations.Factory; + +/** + * + * @author Jaroslav Tulach + */ +public class KnockoutFelixIT { + private static final Logger LOG = Logger.getLogger(KnockoutFelixIT.class.getName()); + private static Framework framework; + private static File dir; + static Framework framework() throws Exception { + if (framework != null) { + return framework; + } + for (FrameworkFactory ff : ServiceLoader.load(FrameworkFactory.class)) { + + String basedir = System.getProperty("basedir"); + assertNotNull("basedir preperty provided", basedir); + File target = new File(basedir, "target"); + dir = new File(target, "osgi"); + dir.mkdirs(); + + Map<String,String> config = new HashMap<String, String>(); + config.put(Constants.FRAMEWORK_STORAGE, dir.getPath()); + config.put(Constants.FRAMEWORK_STORAGE_CLEAN, "true"); + config.put(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA, "sun.misc," + + "javafx.application," + + "javafx.beans," + + "javafx.beans.property," + + "javafx.beans.value," + + "javafx.collections," + + "javafx.concurrent," + + "javafx.event," + + "javafx.geometry," + + "javafx.scene," + + "javafx.scene.control," + + "javafx.scene.image," + + "javafx.scene.layout," + + "javafx.scene.text," + + "javafx.scene.web," + + "javafx.stage," + + "javafx.util," + + "netscape.javascript" + ); + framework = ff.newFramework(config); + framework.init(); + loadClassPathBundles(framework); + framework.start(); + for (Bundle b : framework.getBundleContext().getBundles()) { + try { + if (b.getSymbolicName().contains("felix.framework")) { + continue; + } + if (b.getSymbolicName().contains("glassfish.grizzly")) { + continue; + } + b.start(); + LOG.log(Level.INFO, "Started {0}", b.getSymbolicName()); + } catch (BundleException ex) { + throw new IllegalStateException("Cannot start bundle " + b.getSymbolicName(), ex); + } + } + return framework; + } + fail("No OSGi framework in the path"); + return null; + } + + @AfterClass public static void cleanUp() throws Exception { + if (framework != null) framework.stop(); + clearUpDir(dir); + } + private static void clearUpDir(File dir) { + if (dir.isDirectory()) { + for (File f : dir.listFiles()) { + clearUpDir(f); + } + } + dir.delete(); + } + + + + private static void loadClassPathBundles(Framework f) throws IOException, BundleException { + for (String jar : System.getProperty("java.class.path").split(File.pathSeparator)) { + File file = new File(jar); + if (!file.isFile()) { + LOG.info("Not loading " + file); + continue; + } + JarFile jf = new JarFile(file); + final String name = jf.getManifest().getMainAttributes().getValue("Bundle-SymbolicName"); + jf.close(); + if (name != null) { + if (name.contains("org.eclipse.osgi")) { + throw new IllegalStateException("Found " + name + " !"); + } + if (name.contains("felix.framework")) { + continue; + } + if (name.contains("testng")) { + continue; + } + if (name.equals("org.apache.aries.spifly.dynamic.bundle")) { + continue; + } + final String path = "reference:" + file.toURI().toString(); + try { + Bundle b = f.getBundleContext().installBundle(path); + } catch (BundleException ex) { + LOG.log(Level.WARNING, "Cannot install " + file, ex); + } + } + } + } + + private static Class<?> loadOSGiClass(Class<?> c) throws Exception { + return KnockoutFelixTCKImpl.loadOSGiClass(c.getName(), KnockoutFelixIT.framework().getBundleContext()); + } + + private static Class<?> browserClass; + private static Object browserContext; + + @Factory public static Object[] compatibilityTests() throws Exception { + Class<?> tck = loadOSGiClass(KnockoutTCK.class); + Class<?> peer = loadOSGiClass(KnockoutFelixTCKImpl.class); + // initialize the TCK + Callable<Class[]> inst = (Callable<Class[]>) peer.newInstance(); + + Class[] arr = inst.call(); + for (int i = 0; i < arr.length; i++) { + if (arr[i].getClassLoader() == ClassLoader.getSystemClassLoader()) { + fail("Should be an OSGi class: " + arr[i]); + } + } + + URI uri = DynamicHTTP.initServer(); + + Method start = peer.getMethod("start", String.class, URI.class, boolean.class); + start.invoke(null, KnockoutFelixIT.class.getName(), uri, true); + + ClassLoader l = getClassLoader(null); + List<Object> res = new ArrayList<Object>(); + for (int i = 0; i < arr.length; i++) { + seekKOTests(arr[i], res); + } + return res.toArray(); + } + + private static void seekKOTests(Class<?> c, List<Object> res) throws SecurityException, ClassNotFoundException { + Class<? extends Annotation> koTest = + c.getClassLoader().loadClass(KOTest.class.getName()). + asSubclass(Annotation.class); + for (Method m : c.getMethods()) { + if (m.getAnnotation(koTest) != null) { + res.add(new KOFx(KnockoutFelixIT.class, browserContext, m)); + } + } + } + + static synchronized ClassLoader getClassLoader(Object[] presenter) throws InterruptedException { + while (browserClass == null) { + KnockoutFelixIT.class.wait(); + } + if (presenter != null) { + presenter[0] = browserContext; + } + return browserClass.getClassLoader(); + } + + public static synchronized void initialized(Class<?> browserCls, Object presenter) throws Exception { + browserClass = browserCls; + browserContext = presenter; + KnockoutFelixIT.class.notifyAll(); + } + + public static Closeable activateInOSGi(Object presenter) throws Exception { + Class<?> presenterClass = loadOSGiClass(Fn.Presenter.class); + Class<?> fnClass = loadOSGiClass(Fn.class); + Method m = fnClass.getMethod("activate", presenterClass); + return (Closeable) m.invoke(null, presenter); + } +} http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/ko-felix-test/src/test/resources/org/netbeans/html/ko/felix/test/test.html ---------------------------------------------------------------------- diff --git a/ko-felix-test/src/test/resources/org/netbeans/html/ko/felix/test/test.html b/ko-felix-test/src/test/resources/org/netbeans/html/ko/felix/test/test.html new file mode 100644 index 0000000..6edd632 --- /dev/null +++ b/ko-felix-test/src/test/resources/org/netbeans/html/ko/felix/test/test.html @@ -0,0 +1,56 @@ +<!-- + + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + + Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved. + + Oracle and Java are registered trademarks of Oracle and/or its affiliates. + Other names may be trademarks of their respective owners. + + The contents of this file are subject to the terms of either the GNU + General Public License Version 2 only ("GPL") or the Common + Development and Distribution License("CDDL") (collectively, the + "License"). You may not use this file except in compliance with the + License. You can obtain a copy of the License at + http://www.netbeans.org/cddl-gplv2.html + or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + specific language governing permissions and limitations under the + License. When distributing the software, include this License Header + Notice in each file and include the License file at + nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + particular file as subject to the "Classpath" exception as provided + by Oracle in the GPL Version 2 section of the License file that + accompanied this code. If applicable, add the following below the + License Header, with the fields enclosed by brackets [] replaced by + your own identifying information: + "Portions Copyrighted [year] [name of copyright owner]" + + Contributor(s): + + The Original Software is NetBeans. The Initial Developer of the Original + Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved. + + If you wish your version of this file to be governed by only the CDDL + or only the GPL Version 2, indicate your decision by adding + "[Contributor] elects to include this software in this distribution + under the [CDDL or GPL Version 2] license." If you do not indicate a + single choice of license, a recipient has the option to distribute + your version of this file under either the CDDL, the GPL Version 2 or + to extend the choice of license to its licensees as provided above. + However, if you add GPL Version 2 code and therefore, elected the GPL + Version 2 license, then the option applies only if the new code is + made subject to such option by the copyright holder. + +--> +<!DOCTYPE html> +<html> + <head> + <title>Knockout.fx Execution Harness</title> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> + <meta name="viewport" content="width=device-width"> + </head> + <body> + <h1>Knockout.fx in Felix Execution Harness</h1> + </body> + <script></script> +</html>
