http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot/src/test/java/org/netbeans/html/boot/impl/JsMethods.java ---------------------------------------------------------------------- diff --git a/boot/src/test/java/org/netbeans/html/boot/impl/JsMethods.java b/boot/src/test/java/org/netbeans/html/boot/impl/JsMethods.java new file mode 100644 index 0000000..e680bdf --- /dev/null +++ b/boot/src/test/java/org/netbeans/html/boot/impl/JsMethods.java @@ -0,0 +1,157 @@ +/** + * 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.boot.impl; + +import java.util.Map; +import net.java.html.js.JavaScriptBody; +import net.java.html.js.JavaScriptResource; + + +/** + * + * @author Jaroslav Tulach + */ +@JavaScriptResource("jsmethods.js") +public class JsMethods { + private java.lang.Object value; + + @JavaScriptBody(args = {}, body = "return 42;") + public static java.lang.Object fortyTwo() { + return -42; + } + + @JavaScriptBody(args = {"x", "y" }, body = "return x + y;") + public static native int plus(int x, int y); + + @JavaScriptBody(args = {"x"}, body = "return x;") + public static native int plus(int x); + + @JavaScriptBody(args = {}, body = "return this;") + public static native java.lang.Object staticThis(); + + @JavaScriptBody(args = {}, body = "return this;") + public native java.lang.Object getThis(); + @JavaScriptBody(args = {"x"}, body = "return x;") + public native int plusInst(int x); + + @JavaScriptBody(args = {}, body = "return true;") + public static boolean truth() { + return false; + } + + @JavaScriptBody(args = { "r" }, javacall=true, body = "[email protected]::run()();") + public static native void callback(Runnable r); + + @JavaScriptBody(args = { "at", "arr" }, javacall = true, body = + "var a = 0;\n" + + "for (var i = 0; i < arr.length; i++) {\n" + + " a = [email protected]::sumTwo(II)(a, arr[i]);\n" + + "}\n" + + "return a;" + ) + private static native int sumArr(Arithm at, int... arr); + + public static int sumArr(int... arr) { + return sumArr(new Arithm(), arr); + } + + @JavaScriptBody(args = { "x", "y" }, body = "return mul(x, y);") + public static native int useExternalMul(int x, int y); + + @JavaScriptBody(args = { "m" }, javacall = true, body = "return [email protected]::getThis()();") + public static native JsMethods returnYourSelf(JsMethods m); + + @JavaScriptBody(args = { "x", "y" }, javacall = true, body = "return @org.netbeans.html.boot.impl.JsMethods::useExternalMul(II)(x, y);") + public static native int staticCallback(int x, int y); + + @JavaScriptBody(args = { "v" }, javacall = true, body = "return @java.lang.Integer::parseInt(Ljava/lang/String;)(v);") + public static native int parseInt(String v); + + @JavaScriptBody(args = { "v" }, body = "return v.toString();") + public static native String fromEnum(Enm v); + + @JavaScriptBody(args = "arr", body = "return arr;") + public static native java.lang.Object[] arr(java.lang.Object[] arr); + + @JavaScriptBody(args = { "useA", "useB", "a", "b" }, body = "var l = 0;" + + "if (useA) l += a;\n" + + "if (useB) l += b;\n" + + "return l;\n" + ) + public static native long chooseLong(boolean useA, boolean useB, long a, long b); + + protected void onError(java.lang.Object o) throws Exception { + value = o; + } + + java.lang.Object getError() { + return value; + } + + @JavaScriptBody(args = { "err" }, javacall = true, body = + "[email protected]::onError(Ljava/lang/Object;)(err);" + + "return [email protected]::getError()();" + ) + public native java.lang.Object recordError(java.lang.Object err); + + @JavaScriptBody(args = { "x", "y" }, body = "return x + y;") + public static int plusOrMul(int x, int y) { + return x * y; + } + + @JavaScriptBody(args = { "x" }, keepAlive = false, body = "throw 'Do not call me!'") + public static native int checkAllowGC(java.lang.Object x); + + @JavaScriptBody(args = { "map", "value" }, javacall = true, body = + "[email protected]::put(Ljava/lang/Object;Ljava/lang/Object;)('key',value);" + ) + public static native void callParamTypes(Map<String,Integer> map, int value); + + @JavaScriptBody(args = { "a", "b" }, body = "return [ a, b ];") + public static native double[] both(double a, double b); + + enum Enm { + A, B; + } +} +
http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot/src/test/java/org/netbeans/html/boot/impl/KeepAliveTest.java ---------------------------------------------------------------------- diff --git a/boot/src/test/java/org/netbeans/html/boot/impl/KeepAliveTest.java b/boot/src/test/java/org/netbeans/html/boot/impl/KeepAliveTest.java new file mode 100644 index 0000000..0f8761d --- /dev/null +++ b/boot/src/test/java/org/netbeans/html/boot/impl/KeepAliveTest.java @@ -0,0 +1,113 @@ +/** + * 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.boot.impl; + +import java.io.Closeable; +import java.io.Reader; +import java.net.URL; +import java.util.Collection; +import org.netbeans.html.boot.spi.Fn; +import static org.testng.Assert.assertEquals; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +public class KeepAliveTest implements Fn.Presenter, Fn.KeepAlive, FindResources { + private Class<?> jsMethods; + @Test public void keepAliveIsSetToFalse() throws Exception { + Closeable c = Fn.activate(this); + Number ret = (Number)jsMethods.getMethod("checkAllowGC", java.lang.Object.class).invoke(null, this); + c.close(); + assertEquals(ret.intValue(), 0, "keepAlive is set to false"); + } + + @Test public void keepAliveIsTheDefault() throws Exception { + Closeable c = Fn.activate(this); + Number ret = (Number)jsMethods.getMethod("plus", int.class, int.class).invoke(null, 40, 2); + c.close(); + assertEquals(ret.intValue(), 1, "keepAlive returns true when the presenter is invoked"); + } + + @BeforeMethod + public void initClass() throws ClassNotFoundException { + ClassLoader loader = FnUtils.newLoader(this, this, KeepAliveTest.class.getClassLoader().getParent()); + jsMethods = loader.loadClass(JsMethods.class.getName()); + } + + @Override + public Fn defineFn(String code, String[] names, final boolean[] keepAlive) { + return new Fn(this) { + @Override + public java.lang.Object invoke(java.lang.Object thiz, java.lang.Object... args) throws Exception { + boolean res = true; + if (keepAlive != null) { + for (int i = 0; i < keepAlive.length; i++) { + res &= keepAlive[i]; + } + } + return res ? 1 : 0; + } + }; + } + + @Override + public Fn defineFn(String code, String... names) { + throw new UnsupportedOperationException("Never called!"); + } + + @Override + public void displayPage(URL page, Runnable onPageLoad) { + throw new UnsupportedOperationException(); + } + + @Override + public void loadScript(Reader code) throws Exception { + } + + @Override + public void findResources(String path, Collection<? super URL> results, boolean oneIsEnough) { + URL u = ClassLoader.getSystemClassLoader().getResource(path); + if (u != null) { + results.add(u); + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot/src/test/java/org/netbeans/html/boot/impl/Object.java ---------------------------------------------------------------------- diff --git a/boot/src/test/java/org/netbeans/html/boot/impl/Object.java b/boot/src/test/java/org/netbeans/html/boot/impl/Object.java new file mode 100644 index 0000000..8c23265 --- /dev/null +++ b/boot/src/test/java/org/netbeans/html/boot/impl/Object.java @@ -0,0 +1,49 @@ +/** + * 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.boot.impl; + +/** Fake class to cause confusion in the generated code and force it + * to use fully qualified names + */ +final class Object { +} http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot/src/test/resources/org/netbeans/html/boot/impl/empty.js ---------------------------------------------------------------------- diff --git a/boot/src/test/resources/org/netbeans/html/boot/impl/empty.js b/boot/src/test/resources/org/netbeans/html/boot/impl/empty.js new file mode 100644 index 0000000..2ecbb58 --- /dev/null +++ b/boot/src/test/resources/org/netbeans/html/boot/impl/empty.js @@ -0,0 +1,42 @@ +/* + * 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. + */ http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/boot/src/test/resources/org/netbeans/html/boot/impl/jsmethods.js ---------------------------------------------------------------------- diff --git a/boot/src/test/resources/org/netbeans/html/boot/impl/jsmethods.js b/boot/src/test/resources/org/netbeans/html/boot/impl/jsmethods.js new file mode 100644 index 0000000..f88184b --- /dev/null +++ b/boot/src/test/resources/org/netbeans/html/boot/impl/jsmethods.js @@ -0,0 +1,43 @@ +/* + * 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. + */ +function mul(x, y) { return x * y; } http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/context/pom.xml ---------------------------------------------------------------------- diff --git a/context/pom.xml b/context/pom.xml new file mode 100644 index 0000000..c127c48 --- /dev/null +++ b/context/pom.xml @@ -0,0 +1,91 @@ +<?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> + <groupId>org.netbeans.html</groupId> + <artifactId>net.java.html</artifactId> + <version>2.0-SNAPSHOT</version> + <packaging>bundle</packaging> + <name>HTML Context</name> + <url>http://maven.apache.org</url> + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <publicPackages>net.java.html,org.netbeans.html.context.spi</publicPackages> + </properties> + <build> + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <configuration> + <instructions> + <Eclipse-BuddyPolicy>dependent</Eclipse-BuddyPolicy> + <Require-Capability>osgi.extender;resolution:=optional;filter:="(osgi.extender=osgi.serviceloader.processor)",osgi.serviceloader;filter:="(osgi.serviceloader=org.netbeans.html.context.spi.Contexts$Provider)";cardinality:=multiple;resolution:=optional</Require-Capability> + </instructions> + </configuration> + </plugin> + </plugins> + </build> + <dependencies> + <dependency> + <groupId>org.testng</groupId> + <artifactId>testng</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.netbeans.api</groupId> + <artifactId>org-openide-util-lookup</artifactId> + <scope>test</scope> + <type>jar</type> + </dependency> + </dependencies> + <description>Representation of an HTML page context a Java program operates in.</description> +</project> http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/context/src/main/java/net/java/html/BrwsrCtx.java ---------------------------------------------------------------------- diff --git a/context/src/main/java/net/java/html/BrwsrCtx.java b/context/src/main/java/net/java/html/BrwsrCtx.java new file mode 100644 index 0000000..59a4a21 --- /dev/null +++ b/context/src/main/java/net/java/html/BrwsrCtx.java @@ -0,0 +1,192 @@ +/** + * 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 net.java.html; + +import java.util.concurrent.Executor; +import java.util.logging.Logger; +import org.netbeans.html.context.impl.CtxAccssr; +import org.netbeans.html.context.impl.CtxImpl; +import org.netbeans.html.context.spi.Contexts; +import org.netbeans.html.context.spi.Contexts.Id; + +/** Represents context where the <code>net.java.html.json.Model</code> + * and other objects + * operate in. The context is usually a particular HTML page in a browser. + * The context is also associated with the actual HTML technology + * in the HTML page - there is likely to be different context for + * <a href="http://knockoutjs.com">knockout.js</a> and different one + * for <a href="http://angularjs.org">angular</a>. Since version 1.1 + * the content of contexts can be selected by registering + * implementations under specific + * {@link Id technology identifiers} and requesting them during + * {@link Contexts#newBuilder(java.lang.Object...) construction} of the + * context. + * + * @author Jaroslav Tulach + */ +public final class BrwsrCtx implements Executor { + private static final Logger LOG = Logger.getLogger(BrwsrCtx.class.getName()); + private final CtxImpl impl; + private BrwsrCtx(CtxImpl impl) { + this.impl = impl; + } + /** currently {@link #execute(java.lang.Runnable) activated context} */ + private static final ThreadLocal<BrwsrCtx> CURRENT = new ThreadLocal<BrwsrCtx>(); + static { + new CtxAccssr() { + @Override + protected BrwsrCtx newContext(CtxImpl impl) { + return new BrwsrCtx(impl); + } + + @Override + protected CtxImpl find(BrwsrCtx context) { + return context.impl; + } + }; + } + /** Dummy context without binding to any real browser or technology. + * Useful for simple unit testing of behavior of various business logic + * code. + */ + public static final BrwsrCtx EMPTY = Contexts.newBuilder().build(); + + + /** Seeks for the default context that is associated with the requesting + * class. If no suitable context is found, a warning message is + * printed and {@link #EMPTY} context is returned. One can enter + * a context by calling {@link #execute(java.lang.Runnable)}. + * + * @param requestor the class that makes the request + * @return appropriate context for the request + */ + public static BrwsrCtx findDefault(Class<?> requestor) { + if (requestor == CtxAccssr.class) { + return EMPTY; + } + BrwsrCtx brwsr = CURRENT.get(); + if (brwsr != null) { + return brwsr; + } + + org.netbeans.html.context.spi.Contexts.Builder cb = Contexts.newBuilder(); + boolean found = Contexts.fillInByProviders(requestor, cb); + if (!found) { + LOG.config("No browser context found. Returning empty technology!"); + return EMPTY; + } + return cb.build(); + } + + /** + * <p> + * Runs provided code in the context of this {@link BrwsrCtx}. + * If there is an {@link Executor} {@link Contexts#find(net.java.html.BrwsrCtx, java.lang.Class) registered in the context} + * it is used to perform the given code. While the code <code>exec</code> + * is running the value of {@link #findDefault(java.lang.Class)} returns + * <code>this</code>. If the executor supports a single thread execution + * policy, it may execute the runnable later (in such case this method + * returns immediately). If the call to this method is done on the right + * thread, the runnable should be executed synchronously. + * </p> + * <p> + * <b>Example Using a Timer</b> + * </p> +<pre> +<b>public final class</b> Periodicaly <b>extends</b> {@link java.util.TimerTask} { + <b>private final</b> {@link BrwsrCtx} ctx; + + <b>private</b> Periodicaly(BrwsrCtx ctx) { + // remember the browser context and use it later + this.ctx = ctx; + } + + <b>public void</b> run() { + // arrives on wrong thread, needs to be re-scheduled + ctx.{@link #execute(java.lang.Runnable) execute}(new Runnable() { + <b>public void</b> run() { + // code that needs to run in a browser environment + } + }); + } + + // called when your page is ready + <b>public static void</b> onPageLoad(String... args) <b>throws</b> Exception { + // the context at the time of page initialization + BrwsrCtx initialCtx = BrwsrCtx.findDefault(Periodicaly.<b>class</b>); + // the task that is associated with context + Periodicaly task = new Periodicaly(initialCtx); + // creates a timer + {@link java.util.Timer} t = new {@link java.util.Timer}("Move the box"); + // run the task every 100ms + t.{@link java.util.Timer#scheduleAtFixedRate(java.util.TimerTask, long, long) scheduleAtFixedRate}(task, 0, 100); + } +} +</pre> + * + * @param exec the code to execute + * @since 0.7.6 + */ + @Override public final void execute(final Runnable exec) { + class Wrap implements Runnable { + @Override + public void run() { + BrwsrCtx prev = CURRENT.get(); + try { + CURRENT.set(BrwsrCtx.this); + exec.run(); + } finally { + CURRENT.set(prev); + } + } + } + Wrap w = new Wrap(); + Executor runIn = Contexts.find(this, Executor.class); + if (runIn == null) { + w.run(); + } else { + runIn.execute(w); + } + } +} + http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/context/src/main/java/net/java/html/package.html ---------------------------------------------------------------------- diff --git a/context/src/main/java/net/java/html/package.html b/context/src/main/java/net/java/html/package.html new file mode 100644 index 0000000..007b8a0 --- /dev/null +++ b/context/src/main/java/net/java/html/package.html @@ -0,0 +1,49 @@ +<!-- + + 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. + +--> +<body> + <p> + Representation of the {@link net.java.html.BrwsrCtx browser context}. + </p> +</body> http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/context/src/main/java/org/netbeans/html/context/impl/CtxAccssr.java ---------------------------------------------------------------------- diff --git a/context/src/main/java/org/netbeans/html/context/impl/CtxAccssr.java b/context/src/main/java/org/netbeans/html/context/impl/CtxAccssr.java new file mode 100644 index 0000000..641ca7a --- /dev/null +++ b/context/src/main/java/org/netbeans/html/context/impl/CtxAccssr.java @@ -0,0 +1,71 @@ +/** + * 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.context.impl; + +import net.java.html.BrwsrCtx; +import org.netbeans.html.context.spi.Contexts.Builder; + +/** Internal communication between API (e.g. {@link BrwsrCtx}), SPI + * (e.g. {@link Builder}) and the implementation package. + * + * @author Jaroslav Tulach + */ +public abstract class CtxAccssr { + private static CtxAccssr DEFAULT; + static { + // run initializers + BrwsrCtx.findDefault(CtxAccssr.class); + } + + protected CtxAccssr() { + if (DEFAULT != null) throw new IllegalStateException(); + DEFAULT = this; + } + + protected abstract BrwsrCtx newContext(CtxImpl impl); + protected abstract CtxImpl find(BrwsrCtx context); + + static CtxAccssr getDefault() { + return DEFAULT; + } +} http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/context/src/main/java/org/netbeans/html/context/impl/CtxImpl.java ---------------------------------------------------------------------- diff --git a/context/src/main/java/org/netbeans/html/context/impl/CtxImpl.java b/context/src/main/java/org/netbeans/html/context/impl/CtxImpl.java new file mode 100644 index 0000000..a5c64b6 --- /dev/null +++ b/context/src/main/java/org/netbeans/html/context/impl/CtxImpl.java @@ -0,0 +1,139 @@ +/** + * 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.context.impl; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import net.java.html.BrwsrCtx; +import org.netbeans.html.context.spi.Contexts; + +/** Implementation detail. Holds list of technologies for particular + * {@link BrwsrCtx}. + * + * @author Jaroslav Tulach + */ +public final class CtxImpl { + private final List<Bind<?>> techs; + private final Object[] context; + + public CtxImpl(Object[] context) { + this(context, new ArrayList<Bind<?>>()); + } + + private CtxImpl(Object[] context, List<Bind<?>> techs) { + this.techs = techs; + this.context = context; + } + + public static <Tech> Tech find(BrwsrCtx context, Class<Tech> technology) { + CtxImpl impl = CtxAccssr.getDefault().find(context); + for (Bind<?> bind : impl.techs) { + if (technology == bind.clazz) { + return technology.cast(bind.impl); + } + } + return null; + } + + public BrwsrCtx build() { + Collections.sort(techs, new BindCompare()); + final List<Bind<?>> arr = Collections.unmodifiableList(techs); + CtxImpl impl = new CtxImpl(context, arr); + BrwsrCtx ctx = CtxAccssr.getDefault().newContext(impl); + return ctx; + } + + public <Tech> void register(Class<Tech> type, Tech impl, int priority) { + techs.add(new Bind<Tech>(type, impl, priority)); + } + + private static final class Bind<Tech> { + private final Class<Tech> clazz; + private final Tech impl; + private final int priority; + + public Bind(Class<Tech> clazz, Tech impl, int priority) { + this.clazz = clazz; + this.impl = impl; + this.priority = priority; + } + + @Override + public String toString() { + return "Bind{" + "clazz=" + clazz + "@" + clazz.getClassLoader() + ", impl=" + impl + ", priority=" + priority + '}'; + } + } + + private final class BindCompare implements Comparator<Bind<?>> { + boolean isPrefered(Bind<?> b) { + final Class<?> implClazz = b.impl.getClass(); + Contexts.Id id = implClazz.getAnnotation(Contexts.Id.class); + if (id == null) { + return false; + } + for (String v : id.value()) { + for (Object c : context) { + if (v.equals(c)) { + return true; + } + } + } + return false; + } + + @Override + public int compare(Bind<?> o1, Bind<?> o2) { + boolean p1 = isPrefered(o1); + boolean p2 = isPrefered(o2); + if (p1 != p2) { + return p1 ? -1 : 1; + } + if (o1.priority != o2.priority) { + return o1.priority - o2.priority; + } + return o1.clazz.getName().compareTo(o2.clazz.getName()); + } + } // end of BindCompare +} http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/context/src/main/java/org/netbeans/html/context/spi/Contexts.java ---------------------------------------------------------------------- diff --git a/context/src/main/java/org/netbeans/html/context/spi/Contexts.java b/context/src/main/java/org/netbeans/html/context/spi/Contexts.java new file mode 100644 index 0000000..5d45e1e --- /dev/null +++ b/context/src/main/java/org/netbeans/html/context/spi/Contexts.java @@ -0,0 +1,244 @@ +/** + * 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.context.spi; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.util.HashSet; +import java.util.ServiceLoader; +import java.util.Set; +import net.java.html.BrwsrCtx; +import org.netbeans.html.context.impl.CtxImpl; + +/** Factory class to assign various technologies + * to a {@link BrwsrCtx browser context}. Start with {@link #newBuilder()} + * and then assign technologies with {@link Builder#register(java.lang.Class, java.lang.Object, int)} + * method. + * + * @author Jaroslav Tulach + */ +public final class Contexts { + private Contexts() { + } + + /** Creates new, empty builder for creation of {@link BrwsrCtx}. At the + * end call the {@link Builder#build()} method to generate the context. + * + * @param context instances of various classes or names of {@link Id technologies} + * to be preferred and used in the built {@link BrwsrCtx context}. + * @return new instance of the builder + * @since 1.1 + */ + public static Builder newBuilder(Object... context) { + return new Builder(context); + } + /** Creates new, empty builder for creation of {@link BrwsrCtx}. At the + * end call the {@link Builder#build()} method to generate the context. + * Simply calls {@link #newBuilder(java.lang.Object...) newBuilder(new Object[0])}. + * + * @return new instance of the builder + */ + public static Builder newBuilder() { + return newBuilder(new Object[0]); + } + + /** Seeks for the specified technology in the provided context. + * + * @param <Tech> type of the technology + * @param context the context to seek in + * (previously filled with ({@link Builder#register(java.lang.Class, java.lang.Object, int)}) + * @param technology class that identifies the technology + * @return the technology in the context or <code>null</code> + */ + public static <Tech> Tech find(BrwsrCtx context, Class<Tech> technology) { + return CtxImpl.find(context, technology); + } + + /** Seeks {@link ServiceLoader} for all registered instances of + * {@link Provider} and asks them to {@link Provider#fillContext(org.netbeans.html.context.spi.Contexts.Builder, java.lang.Class) fill + * the builder}. + * + * @param requestor the application class for which to find the context + * @param cb the context builder to register technologies into + * @return <code>true</code>, if some instances of the provider were + * found, <code>false</code> otherwise + * @since 0.7.6 + */ + public static boolean fillInByProviders(Class<?> requestor, Contexts.Builder cb) { + boolean found = false; + ClassLoader l; + try { + l = requestor.getClassLoader(); + } catch (SecurityException ex) { + l = null; + } + Set<Class<?>> classes = new HashSet<Class<?>>(); + for (Provider cp : ServiceLoader.load(Provider.class, l)) { + if (!classes.add(cp.getClass())) { + continue; + } + cp.fillContext(cb, requestor); + found = true; + } + try { + for (Provider cp : ServiceLoader.load(Provider.class, Provider.class.getClassLoader())) { + if (!classes.add(cp.getClass())) { + continue; + } + cp.fillContext(cb, requestor); + found = true; + } + } catch (SecurityException ex) { + if (!found) { + throw ex; + } + } + if (!found) { + for (Provider cp : ServiceLoader.load(Provider.class)) { + if (!classes.add(cp.getClass())) { + continue; + } + cp.fillContext(cb, requestor); + found = true; + } + } + return found; + } + + /** Identifies the technologies passed to {@link Builder context builder} + * by a name. Each implementation of a technology + * {@link Builder#register(java.lang.Class, java.lang.Object, int) registered into a context} + * can be annotated with a name (or multiple names). Such implementation + * will later be + * {@link Contexts#fillInByProviders(java.lang.Class, org.netbeans.html.context.spi.Contexts.Builder) preferred during lookup} + * if their name(s) has been requested in when + * {@link Contexts#newBuilder(java.lang.Object...) creating a context}. + * @since 1.1 + */ + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.TYPE) + @Documented + public @interface Id { + /** Identifier(s) for the implementation. + * + * @return one of more identifiers giving this implementation name(s) + */ + public String[] value(); + } + + /** Implementors of various HTML technologies should + * register their implementation via <code>org.openide.util.lookup.ServiceProvider</code>, so + * {@link ServiceLoader} can find them, when their JARs are included + * on the classpath of the running application. + * + * @author Jaroslav Tulach + */ + public static interface Provider { + + /** Register into the context if suitable technology is + * available for the requesting class. + * The provider should check if its own technology is available in current + * scope (e.g. proper JDK, proper browser, etc.). The provider + * can also find the right context depending on requestor's classloader, etc. + * <p> + * Providers should use {@link Builder} to enrich appropriately + * the context. + * + * @param context the context builder to fill with technologies + * @param requestor the application class requesting access the the HTML page + * @see BrwsrCtx#findDefault(java.lang.Class) + */ + void fillContext(Builder context, Class<?> requestor); + } + + /** Support for providers of new {@link BrwsrCtx}. Providers of different + * technologies should be of particular interest in this class. End users + * designing their application with existing technologies should rather + * point their attention to {@link BrwsrCtx} and co. + * + * @author Jaroslav Tulach + */ + public static final class Builder { + private final CtxImpl impl; + + public Builder(Object[] context) { + this.impl = new CtxImpl(context); + } + + /** Registers new technology into the context. Each technology is + * exactly identified by its implementation class and can be associated + * with (positive) priority. In case of presence of multiple technologies + * with the same class, the one with higher lower priority takes precedence. + * @param <Tech> type of technology to register + * @param type the real class of the technology type + * @param impl an instance of the technology class + * @param position the lower position (but higher than zero), the more important implementation + * which will be consulted sooner when seeking for a {@link Contexts#find(net.java.html.BrwsrCtx, java.lang.Class)} + * an implementation + * @return this builder + * @throws IllegalStateException if the position isn't higher than <code>0</code> + */ + public <Tech> Builder register(Class<Tech> type, Tech impl, int position) { + if (impl == null) { + return this; + } + if (position <= 0) { + throw new IllegalStateException(); + } + this.impl.register(type, impl, position); + return this; + } + + /** Generates context based on values previously inserted into + * this builder. + * + * @return new, immutable instance of {@link BrwsrCtx} + */ + public BrwsrCtx build() { + return impl.build(); + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/context/src/main/java/org/netbeans/html/context/spi/package.html ---------------------------------------------------------------------- diff --git a/context/src/main/java/org/netbeans/html/context/spi/package.html b/context/src/main/java/org/netbeans/html/context/spi/package.html new file mode 100644 index 0000000..ea999bb --- /dev/null +++ b/context/src/main/java/org/netbeans/html/context/spi/package.html @@ -0,0 +1,50 @@ +<!-- + + 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. + +--> +<body> + <p> + Service provider classes to build {@link net.java.html.BrwsrCtx} + instances. + </p> +</body> http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/context/src/test/java/net/java/html/BrwsrCtxTest.java ---------------------------------------------------------------------- diff --git a/context/src/test/java/net/java/html/BrwsrCtxTest.java b/context/src/test/java/net/java/html/BrwsrCtxTest.java new file mode 100644 index 0000000..9253bec --- /dev/null +++ b/context/src/test/java/net/java/html/BrwsrCtxTest.java @@ -0,0 +1,120 @@ +/** + * 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 net.java.html; + +import org.netbeans.html.context.spi.Contexts; +import static org.testng.Assert.*; +import org.testng.annotations.Test; + +/** + * + * @author Jaroslav Tulach + */ +public class BrwsrCtxTest { + + public BrwsrCtxTest() { + } + + + @org.testng.annotations.Test + public void canSetAssociateCtx() { + final BrwsrCtx ctx = Contexts.newBuilder().build(); + final boolean[] arr = { false }; + + assertNotSame(BrwsrCtx.findDefault(BrwsrCtxTest.class), ctx, "Not associated yet"); + ctx.execute(new Runnable() { + @Override public void run() { + assertSame(BrwsrCtx.findDefault(BrwsrCtxTest.class), ctx, "Once same"); + assertSame(BrwsrCtx.findDefault(BrwsrCtxTest.class), ctx, "2nd same"); + arr[0] = true; + } + }); + assertNotSame(BrwsrCtx.findDefault(BrwsrCtxTest.class), ctx, "Not associated again"); + assertTrue(arr[0], "Runnable was executed"); + } + + + @Test public void defaultOrderOfRegistrations() { + BrwsrCtx ctx = registerRs(Contexts.newBuilder()); + Class<? extends Runnable> clazz = Contexts.find(ctx, Runnable.class).getClass(); + assertEquals(clazz, R1.class, "R1 is registered at value 10"); + } + + @Test public void preferOne() { + BrwsrCtx ctx = registerRs(Contexts.newBuilder("one")); + Class<? extends Runnable> clazz = Contexts.find(ctx, Runnable.class).getClass(); + assertEquals(clazz, R1.class, "R1 is registered at value 10"); + } + + @Test public void preferTwo() { + BrwsrCtx ctx = registerRs(Contexts.newBuilder("two")); + Class<? extends Runnable> clazz = Contexts.find(ctx, Runnable.class).getClass(); + assertEquals(clazz, R2.class, "R2 is preferred"); + } + + @Test public void preferBoth() { + BrwsrCtx ctx = registerRs(Contexts.newBuilder("one", "two")); + Class<? extends Runnable> clazz = Contexts.find(ctx, Runnable.class).getClass(); + assertEquals(clazz, R1.class, "R1 is registered at value 10"); + } + + private static BrwsrCtx registerRs(Contexts.Builder b) { + b.register(Runnable.class, new R1(), 10); + b.register(Runnable.class, new R2(), 20); + return b.build(); + } + + @Contexts.Id("one") + static final class R1 implements Runnable { + @Override + public void run() { + } + } + @Contexts.Id("two") + static final class R2 implements Runnable { + @Override + public void run() { + } + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/context/src/test/java/org/netbeans/html/context/spi/ContextsTest.java ---------------------------------------------------------------------- diff --git a/context/src/test/java/org/netbeans/html/context/spi/ContextsTest.java b/context/src/test/java/org/netbeans/html/context/spi/ContextsTest.java new file mode 100644 index 0000000..e579a37 --- /dev/null +++ b/context/src/test/java/org/netbeans/html/context/spi/ContextsTest.java @@ -0,0 +1,115 @@ +/** + * 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.context.spi; + +import javax.xml.ws.ServiceMode; +import net.java.html.BrwsrCtx; +import org.openide.util.lookup.ServiceProvider; +import static org.testng.Assert.*; +import org.testng.annotations.AfterClass; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +/** + * + * @author Jaroslav Tulach + */ +public class ContextsTest { + + public ContextsTest() { + } + + @Test public void twoInstancesButOneCall() { + class Two implements Runnable { + int cnt; + + @Override + public void run() { + cnt++; + } + } + class One implements Runnable { + int cnt; + + @Override + public void run() { + cnt++; + } + } + + One one = new One(); + Two two = new Two(); + + CountingProvider.onNew = two; + CountingProvider.onFill = one; + + Contexts.Builder b = Contexts.newBuilder(); + Contexts.fillInByProviders(ContextsTest.class, b); + + assertEquals(two.cnt, 2, "Two instances created"); + assertEquals(one.cnt, 1, "But only one call to fill"); + } + + @ServiceProvider(service = Contexts.Provider.class) + public static final class CountingProvider implements Contexts.Provider { + static Runnable onNew; + static Runnable onFill; + + public CountingProvider() { + if (onNew != null) { + onNew.run(); + } + } + + @Override + public void fillContext(Contexts.Builder context, Class<?> requestor) { + if (onFill != null) { + onFill.run(); + context.register(Runnable.class, onFill, 1); + } + } + } + +} http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/equinox-agentclass-hook/pom.xml ---------------------------------------------------------------------- diff --git a/equinox-agentclass-hook/pom.xml b/equinox-agentclass-hook/pom.xml new file mode 100644 index 0000000..436c7d5 --- /dev/null +++ b/equinox-agentclass-hook/pom.xml @@ -0,0 +1,86 @@ +<?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>AgentClass Hook for Equinox</name> + <artifactId>equinox-agentclass-hook</artifactId> + <packaging>bundle</packaging> + <build> + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <configuration> + <instructions> + <Fragment-Host>org.eclipse.osgi;bundle-version="[3.8.0,4.0)"</Fragment-Host> + <Import-Package /> + </instructions> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <version>2.3.2</version> + <configuration> + <source>1.5</source> + <target>1.5</target> + </configuration> + </plugin> + </plugins> + </build> + <dependencies> + <dependency> + <groupId>org.eclipse</groupId> + <artifactId>org.eclipse.osgi</artifactId> + <version>3.8.0.v20120529-1548</version> + </dependency> + </dependencies> +</project> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/equinox-agentclass-hook/src/main/java/org/netbeans/html/equinox/agentclass/AgentHook.java ---------------------------------------------------------------------- diff --git a/equinox-agentclass-hook/src/main/java/org/netbeans/html/equinox/agentclass/AgentHook.java b/equinox-agentclass-hook/src/main/java/org/netbeans/html/equinox/agentclass/AgentHook.java new file mode 100644 index 0000000..c087d87 --- /dev/null +++ b/equinox-agentclass-hook/src/main/java/org/netbeans/html/equinox/agentclass/AgentHook.java @@ -0,0 +1,164 @@ +/** + * 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.equinox.agentclass; + +import java.lang.instrument.IllegalClassFormatException; +import java.security.ProtectionDomain; +import java.util.ArrayList; +import java.util.logging.Logger; + +import org.eclipse.osgi.baseadaptor.BaseData; +import org.eclipse.osgi.baseadaptor.HookConfigurator; +import org.eclipse.osgi.baseadaptor.HookRegistry; +import org.eclipse.osgi.baseadaptor.bundlefile.BundleEntry; +import org.eclipse.osgi.baseadaptor.hooks.ClassLoadingHook; +import org.eclipse.osgi.baseadaptor.loader.BaseClassLoader; +import org.eclipse.osgi.baseadaptor.loader.ClasspathEntry; +import org.eclipse.osgi.baseadaptor.loader.ClasspathManager; +import org.eclipse.osgi.framework.adaptor.BundleProtectionDomain; +import org.eclipse.osgi.framework.adaptor.BundleWatcher; +import org.eclipse.osgi.framework.adaptor.ClassLoaderDelegate; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.wiring.BundleWiring; + +public class AgentHook implements HookConfigurator, BundleWatcher, ClassLoadingHook { + private static final Logger LOG = Logger.getLogger(AgentHook.class.getName()); + private boolean all; + + @Override + public void addHooks(HookRegistry hookRegistry) { + LOG.info("Agent hook for Equinox initialized!"); + hookRegistry.addWatcher(this); + hookRegistry.addClassLoadingHook(this); + } + + @Override + public void watchBundle(Bundle bundle, int type) { + if (!all) { + BundleContext c = bundle.getBundleContext(); + if (c != null) { + Bundle[] arr = bundle.getBundleContext().getBundles(); + for (Bundle b : arr) { + agentBundle(b); + } + all = true; + } + } + if (type == BundleWatcher.END_ACTIVATION) { + agentBundle(bundle); + } + } + + private void agentBundle(Bundle bundle) { + String agentClass = (String)bundle.getHeaders().get("Agent-Class"); + if (agentClass != null) { + Class<?> agent; + try { + agent = bundle.loadClass(agentClass); + NbInstrumentation.registerAgent(agent.getClassLoader(), agent.getName()); + } catch (ClassNotFoundException e) { + throw new IllegalStateException(e); + } + } + } + + @Override + public byte[] processClass(String name, byte[] bytes, + ClasspathEntry ce, BundleEntry entry, + ClasspathManager manager) { + final BaseData bd = ce.getBaseData(); + if (bd == null) { + return bytes; + } + final Bundle b = bd.getBundle(); + if (b == null) { + return bytes; + } + BundleWiring w = (BundleWiring)b.adapt(BundleWiring.class); + if (w == null) { + return bytes; + } + ClassLoader loader = w.getClassLoader(); + try { + return NbInstrumentation.patchByteCode(loader, name, ce.getDomain(), bytes); + } catch (IllegalClassFormatException e) { + return bytes; + } + } + + @Override + public boolean addClassPathEntry(ArrayList cpEntries, + String cp, ClasspathManager hostmanager, BaseData sourcedata, + ProtectionDomain sourcedomain) { + // TODO Auto-generated method stub + return false; + } + + @Override + public String findLibrary(BaseData data, String libName) { + // TODO Auto-generated method stub + return null; + } + + @Override + public ClassLoader getBundleClassLoaderParent() { + // TODO Auto-generated method stub + return null; + } + + @Override + public BaseClassLoader createClassLoader(ClassLoader parent, + ClassLoaderDelegate delegate, BundleProtectionDomain domain, + BaseData data, String[] bundleclasspath) { + // TODO Auto-generated method stub + return null; + } + + @Override + public void initializedClassLoader(BaseClassLoader baseClassLoader, + BaseData data) { + // TODO Auto-generated method stub + + } +} http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/equinox-agentclass-hook/src/main/java/org/netbeans/html/equinox/agentclass/NbInstrumentation.java ---------------------------------------------------------------------- diff --git a/equinox-agentclass-hook/src/main/java/org/netbeans/html/equinox/agentclass/NbInstrumentation.java b/equinox-agentclass-hook/src/main/java/org/netbeans/html/equinox/agentclass/NbInstrumentation.java new file mode 100644 index 0000000..de0aa63 --- /dev/null +++ b/equinox-agentclass-hook/src/main/java/org/netbeans/html/equinox/agentclass/NbInstrumentation.java @@ -0,0 +1,213 @@ +/** + * 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.equinox.agentclass; + +import java.lang.instrument.ClassDefinition; +import java.lang.instrument.ClassFileTransformer; +import java.lang.instrument.IllegalClassFormatException; +import java.lang.instrument.Instrumentation; +import java.lang.instrument.UnmodifiableClassException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.security.ProtectionDomain; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.jar.JarFile; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * + * @author Jaroslav Tulach + */ +final class NbInstrumentation implements Instrumentation { + private static final Logger LOG = Logger.getLogger(NbInstrumentation.class.getName()); + private static final Object LOCK = new Object(); + private static volatile Collection<NbInstrumentation> ACTIVE; + + private final List<ClassFileTransformer> transformers = new CopyOnWriteArrayList<ClassFileTransformer>(); + private static final ThreadLocal<Boolean> IN = new ThreadLocal<Boolean>(); + + static NbInstrumentation registerAgent(ClassLoader l, String agentClassName) { + try { + return registerImpl(agentClassName, l); + } catch (Throwable ex) { + LOG.log(Level.WARNING, "Cannot register " + agentClassName, ex); + return null; + } + } + static void unregisterAgent(NbInstrumentation instr) { + synchronized (LOCK) { + if (ACTIVE != null) { + Collection<NbInstrumentation> clone = new HashSet<NbInstrumentation>(); + clone.addAll(ACTIVE); + clone.remove(instr); + ACTIVE = clone; + } + } + } + private static NbInstrumentation registerImpl(String agentClassName, ClassLoader l) throws ClassNotFoundException, IllegalArgumentException, NoSuchMethodException, SecurityException, IllegalAccessException, InvocationTargetException { + final NbInstrumentation inst = new NbInstrumentation(); + synchronized (LOCK) { + if (ACTIVE == null) { + ACTIVE = new HashSet<NbInstrumentation>(); + } else { + Set<NbInstrumentation> s = new HashSet<NbInstrumentation>(); + s.addAll(ACTIVE); + ACTIVE = s; + } + ACTIVE.add(inst); + } + Class<?> agentClass = Class.forName(agentClassName, true, l); + try { + Method m = agentClass.getMethod("agentmain", String.class, Instrumentation.class); // NOI18N + m.invoke(null, "", inst); + } catch (NoSuchMethodException ex) { + Method m = agentClass.getMethod("agentmain", String.class); // NOI18N + m.invoke(null, ""); + } + return inst; + } + + public static byte[] patchByteCode(ClassLoader l, String className, ProtectionDomain pd, byte[] arr) throws IllegalClassFormatException { + if (ACTIVE == null) { + return arr; + } + if (Boolean.TRUE.equals(IN.get())) { + return arr; + } + try { + IN.set(Boolean.TRUE); + for (NbInstrumentation inst : ACTIVE) { + for (ClassFileTransformer t : inst.transformers) { + arr = t.transform(l, className, null, pd, arr); + } + } + } finally { + IN.set(null); + } + return arr; + } + + // + // Instrumentation methods + // + + @Override + public void addTransformer(ClassFileTransformer transformer, boolean canRetransform) { + transformers.add(transformer); + } + + @Override + public void addTransformer(ClassFileTransformer transformer) { + transformers.add(transformer); + } + + @Override + public boolean removeTransformer(ClassFileTransformer transformer) { + return transformers.remove(transformer); + } + + @Override + public boolean isRetransformClassesSupported() { + return false; + } + + @Override + public void retransformClasses(Class<?>... classes) throws UnmodifiableClassException { + throw new UnmodifiableClassException(); + } + + @Override + public boolean isRedefineClassesSupported() { + return false; + } + + @Override + public void redefineClasses(ClassDefinition... definitions) throws ClassNotFoundException, UnmodifiableClassException { + throw new UnmodifiableClassException(); + } + + @Override + public boolean isModifiableClass(Class<?> theClass) { + return false; + } + + @Override + public Class[] getAllLoadedClasses() { + return new Class[0]; + } + + @Override + public Class[] getInitiatedClasses(ClassLoader loader) { + return new Class[0]; + } + + @Override + public long getObjectSize(Object objectToSize) { + return 42; + } + + @Override + public void appendToBootstrapClassLoaderSearch(JarFile jarfile) { + } + + @Override + public void appendToSystemClassLoaderSearch(JarFile jarfile) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isNativeMethodPrefixSupported() { + return false; + } + + @Override + public void setNativeMethodPrefix(ClassFileTransformer transformer, String prefix) { + throw new UnsupportedOperationException(); + } + +}
