The preprocessing behavior seems to be in good shape, merging to default branch
1.1 --- a/boot-fx/pom.xml Thu Jan 30 12:09:09 2014 +0100
1.2 +++ b/boot-fx/pom.xml Thu Jan 30 17:08:51 2014 +0100
1.3 @@ -23,6 +23,10 @@
1.4 <artifactId>maven-bundle-plugin</artifactId>
1.5 </plugin>
1.6 <plugin>
1.7 + <groupId>org.netbeans.html</groupId>
1.8 + <artifactId>html4j-maven-plugin</artifactId>
1.9 + </plugin>
1.10 + <plugin>
1.11 <groupId>org.apache.maven.plugins</groupId>
1.12 <artifactId>maven-surefire-plugin</artifactId>
1.13 <configuration>
2.1 --- a/boot-fx/src/test/java/org/netbeans/html/boot/fx/BootstrapTest.java Thu Jan 30 12:09:09 2014 +0100
2.2 +++ b/boot-fx/src/test/java/org/netbeans/html/boot/fx/BootstrapTest.java Thu Jan 30 17:08:51 2014 +0100
2.3 @@ -48,10 +48,10 @@
2.4 import java.util.List;
2.5 import java.util.concurrent.Executors;
2.6 import net.java.html.boot.BrowserBuilder;
2.7 -import org.netbeans.html.boot.impl.FnContext;
2.8 import org.apidesign.html.boot.spi.Fn;
2.9 +import org.apidesign.html.json.tck.KOTest;
2.10 +import org.testng.Assert;
2.11 import org.testng.annotations.Factory;
2.12 -import org.testng.annotations.Test;
2.13
2.14 /**
2.15 *
2.16 @@ -78,11 +78,15 @@
2.17
2.18 List<Object> res = new ArrayList<Object>();
2.19 Class<? extends Annotation> test =
2.20 - loadClass().getClassLoader().loadClass(Test.class.getName()).
2.21 + loadClass().getClassLoader().loadClass(KOTest.class.getName()).
2.22 asSubclass(Annotation.class);
2.23 - for (Method m : loadClass().getMethods()) {
2.24 - if (m.getAnnotation(test) != null) {
2.25 - res.add(new KOFx(browserPresenter, m));
2.26 +
2.27 + Class[] arr = (Class[]) loadClass().getDeclaredMethod("tests").invoke(null);
2.28 + for (Class c : arr) {
2.29 + for (Method m : c.getMethods()) {
2.30 + if (m.getAnnotation(test) != null) {
2.31 + res.add(new KOFx(browserPresenter, m));
2.32 + }
2.33 }
2.34 }
2.35 return res.toArray();
2.36 @@ -97,13 +101,16 @@
2.37
2.38 public static synchronized void ready(Class<?> browserCls) throws Exception {
2.39 browserClass = browserCls;
2.40 - browserPresenter = FnContext.currentPresenter();
2.41 + browserPresenter = Fn.activePresenter();
2.42 BootstrapTest.class.notifyAll();
2.43 }
2.44
2.45 public static void initialized() throws Exception {
2.46 - Class<?> classpathClass = ClassLoader.getSystemClassLoader().loadClass(BootstrapTest.class.getName());
2.47 - Method m = classpathClass.getMethod("ready", Class.class);
2.48 - m.invoke(null, FXPresenterTst.class);
2.49 + Assert.assertSame(
2.50 + BootstrapTest.class.getClassLoader(),
2.51 + ClassLoader.getSystemClassLoader(),
2.52 + "No special classloaders"
2.53 + );
2.54 + BootstrapTest.ready(FxJavaScriptTst.class);
2.55 }
2.56 }
3.1 --- a/boot-fx/src/test/java/org/netbeans/html/boot/fx/FXJavaScriptTest.java Thu Jan 30 12:09:09 2014 +0100
3.2 +++ b/boot-fx/src/test/java/org/netbeans/html/boot/fx/FXJavaScriptTest.java Thu Jan 30 17:08:51 2014 +0100
3.3 @@ -50,9 +50,8 @@
3.4 import net.java.html.boot.BrowserBuilder;
3.5 import org.apidesign.html.boot.spi.Fn;
3.6 import org.apidesign.html.json.tck.KOTest;
3.7 -import org.netbeans.html.boot.impl.FnContext;
3.8 +import org.testng.Assert;
3.9 import org.testng.annotations.Factory;
3.10 -import org.testng.annotations.Test;
3.11
3.12 /**
3.13 *
3.14 @@ -81,7 +80,9 @@
3.15 Class<? extends Annotation> test =
3.16 loadClass().getClassLoader().loadClass(KOTest.class.getName()).
3.17 asSubclass(Annotation.class);
3.18 - for (Class<?> c : (Class[])loadClass().getMethod("tests").invoke(null)) {
3.19 +
3.20 + Class[] arr = (Class[]) loadClass().getDeclaredMethod("tests").invoke(null);
3.21 + for (Class c : arr) {
3.22 for (Method m : c.getMethods()) {
3.23 if (m.getAnnotation(test) != null) {
3.24 res.add(new KOFx(browserPresenter, m));
3.25 @@ -100,13 +101,16 @@
3.26
3.27 public static synchronized void ready(Class<?> browserCls) throws Exception {
3.28 browserClass = browserCls;
3.29 - browserPresenter = FnContext.currentPresenter();
3.30 + browserPresenter = Fn.activePresenter();
3.31 FXJavaScriptTest.class.notifyAll();
3.32 }
3.33
3.34 public static void initialized() throws Exception {
3.35 - Class<?> classpathClass = ClassLoader.getSystemClassLoader().loadClass(FXJavaScriptTest.class.getName());
3.36 - Method m = classpathClass.getMethod("ready", Class.class);
3.37 - m.invoke(null, FxJavaScriptTst.class);
3.38 + Assert.assertSame(
3.39 + FXJavaScriptTest.class.getClassLoader(),
3.40 + ClassLoader.getSystemClassLoader(),
3.41 + "No special classloaders"
3.42 + );
3.43 + FXJavaScriptTest.ready(FxJavaScriptTst.class);
3.44 }
3.45 }
4.1 --- a/boot/pom.xml Thu Jan 30 12:09:09 2014 +0100
4.2 +++ b/boot/pom.xml Thu Jan 30 17:08:51 2014 +0100
4.3 @@ -34,7 +34,6 @@
4.4 <dependency>
4.5 <groupId>org.ow2.asm</groupId>
4.6 <artifactId>asm</artifactId>
4.7 - <version>4.1</version>
4.8 <type>jar</type>
4.9 </dependency>
4.10 <dependency>
5.1 --- a/boot/src/main/java/net/java/html/boot/BrowserBuilder.java Thu Jan 30 12:09:09 2014 +0100
5.2 +++ b/boot/src/main/java/net/java/html/boot/BrowserBuilder.java Thu Jan 30 17:08:51 2014 +0100
5.3 @@ -54,10 +54,10 @@
5.4 import java.util.logging.Level;
5.5 import java.util.logging.Logger;
5.6 import net.java.html.js.JavaScriptBody;
5.7 -import org.netbeans.html.boot.impl.FnUtils;
5.8 import org.apidesign.html.boot.spi.Fn;
5.9 import org.netbeans.html.boot.impl.FindResources;
5.10 import org.netbeans.html.boot.impl.FnContext;
5.11 +import org.netbeans.html.boot.impl.FnUtils;
5.12
5.13 /** Use this builder to launch your Java/HTML based application. Typical
5.14 * usage in a main method of your application looks like this:
6.1 --- a/boot/src/main/java/org/netbeans/html/boot/impl/FnContext.java Thu Jan 30 12:09:09 2014 +0100
6.2 +++ b/boot/src/main/java/org/netbeans/html/boot/impl/FnContext.java Thu Jan 30 17:08:51 2014 +0100
6.3 @@ -87,10 +87,6 @@
6.4 return prev;
6.5 }
6.6
6.7 - public static Fn.Presenter currentPresenter() {
6.8 - return currentPresenter(true);
6.9 - }
6.10 -
6.11 public static Fn.Presenter currentPresenter(boolean fail) {
6.12 Fn.Presenter p = CURRENT.get();
6.13 if (p == null && fail) {
7.1 --- a/boot/src/main/java/org/netbeans/html/boot/impl/FnUtils.java Thu Jan 30 12:09:09 2014 +0100
7.2 +++ b/boot/src/main/java/org/netbeans/html/boot/impl/FnUtils.java Thu Jan 30 17:08:51 2014 +0100
7.3 @@ -43,6 +43,7 @@
7.4 package org.netbeans.html.boot.impl;
7.5
7.6 import java.io.Closeable;
7.7 +import java.io.IOException;
7.8 import java.io.InputStream;
7.9 import java.io.InputStreamReader;
7.10 import java.io.Reader;
7.11 @@ -74,29 +75,48 @@
7.12 private FnUtils() {
7.13 }
7.14
7.15 + /** Seeks for {@link JavaScriptBody} and {@link JavaScriptResource} annotations
7.16 + * in the bytecode and converts them into real code. Used by Maven plugin
7.17 + * postprocessing classes.
7.18 + *
7.19 + * @param bytecode the original bytecode with javascript specific annotations
7.20 + * @param loader the loader to load resources (scripts and classes) when needed
7.21 + * @return the transformed bytecode
7.22 + * @since 0.7
7.23 + */
7.24 + public static byte[] transform(byte[] bytecode, ClassLoader loader) {
7.25 + ClassReader cr = new ClassReader(bytecode) {
7.26 + // to allow us to compile with -profile compact1 on
7.27 + // JDK8 while processing the class as JDK7, the highest
7.28 + // class format asm 4.1 understands to
7.29 + @Override
7.30 + public short readShort(int index) {
7.31 + short s = super.readShort(index);
7.32 + if (index == 6 && s > Opcodes.V1_7) {
7.33 + return Opcodes.V1_7;
7.34 + }
7.35 + return s;
7.36 + }
7.37 + };
7.38 + FindInClass tst = new FindInClass(loader, null);
7.39 + cr.accept(tst, 0);
7.40 + if (tst.found > 0) {
7.41 + ClassWriter w = new ClassWriterEx(loader, cr, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
7.42 + FindInClass fic = new FindInClass(loader, w);
7.43 + cr.accept(fic, 0);
7.44 + bytecode = w.toByteArray();
7.45 + }
7.46 + return bytecode;
7.47 + }
7.48 +
7.49 public static boolean isJavaScriptCapable(ClassLoader l) {
7.50 if (l instanceof JsClassLoader) {
7.51 return true;
7.52 }
7.53 - Class<?> clazz;
7.54 - Closeable c = Fn.activate(new TrueFn());
7.55 - try {
7.56 - try {
7.57 - clazz = Class.forName(Test.class.getName(), true, l);
7.58 - } catch (ClassNotFoundException ex) {
7.59 - clazz = Test.class;
7.60 - }
7.61 - final Object is = ((Callable<?>)clazz.newInstance()).call();
7.62 - return Boolean.TRUE.equals(is);
7.63 - } catch (Exception ex) {
7.64 + if (l.getResource("META-INF/net.java.html.js.classes") != null) {
7.65 return false;
7.66 - } finally {
7.67 - try {
7.68 - c.close();
7.69 - } catch (Exception ex) {
7.70 - return false;
7.71 - }
7.72 }
7.73 + return true;
7.74 }
7.75
7.76 public static boolean isValid(Fn fn) {
7.77 @@ -161,7 +181,7 @@
7.78 Reader isr = null;
7.79 try {
7.80 isr = new InputStreamReader(script, "UTF-8");
7.81 - FnContext.currentPresenter().loadScript(isr);
7.82 + FnContext.currentPresenter(false).loadScript(isr);
7.83 } finally {
7.84 if (isr != null) {
7.85 isr.close();
7.86 @@ -172,39 +192,6 @@
7.87 }
7.88 }
7.89
7.90 - /** Checks bytecode for usage of {@link JavaScriptBody} annotation
7.91 - * and rewrites it to invoke {@link Fn.Presenter} directly.
7.92 - *
7.93 - * @param arr the byte code to check
7.94 - * @param loader loader to load additional resources and classes
7.95 - * @return the same <code>arr</code> (if no change needed) or new
7.96 - * array with rewritten bytecode
7.97 - * @since 0.7
7.98 - */
7.99 - public static byte[] transform(byte[] arr, ClassLoader loader) {
7.100 - ClassReader cr = new ClassReader(arr) {
7.101 - // to allow us to compile with -profile compact1 on
7.102 - // JDK8 while processing the class as JDK7, the highest
7.103 - // class format asm 4.1 understands to
7.104 - @Override
7.105 - public short readShort(int index) {
7.106 - short s = super.readShort(index);
7.107 - if (index == 6 && s > Opcodes.V1_7) {
7.108 - return Opcodes.V1_7;
7.109 - }
7.110 - return s;
7.111 - }
7.112 - };
7.113 - FindInClass tst = new FindInClass(loader, null);
7.114 - cr.accept(tst, 0);
7.115 - if (tst.found > 0) {
7.116 - ClassWriter w = new ClassWriterEx(loader, cr, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
7.117 - FindInClass fic = new FindInClass(loader, w);
7.118 - cr.accept(fic, 0);
7.119 - arr = w.toByteArray();
7.120 - }
7.121 - return arr;
7.122 - }
7.123
7.124 private static final class FindInClass extends ClassVisitor {
7.125 private String name;
7.126 @@ -606,24 +593,4 @@
7.127 }
7.128 }
7.129 }
7.130 -
7.131 - private static final class TrueFn extends Fn implements Fn.Presenter {
7.132 - @Override
7.133 - public Object invoke(Object thiz, Object... args) throws Exception {
7.134 - return Boolean.TRUE;
7.135 - }
7.136 -
7.137 - @Override
7.138 - public Fn defineFn(String code, String... names) {
7.139 - return this;
7.140 - }
7.141 -
7.142 - @Override
7.143 - public void displayPage(URL page, Runnable onPageLoad) {
7.144 - }
7.145 -
7.146 - @Override
7.147 - public void loadScript(Reader code) throws Exception {
7.148 - }
7.149 - } // end of TrueFn
7.150 }
8.1 --- a/boot/src/main/java/org/netbeans/html/boot/impl/JavaScriptProcesor.java Thu Jan 30 12:09:09 2014 +0100
8.2 +++ b/boot/src/main/java/org/netbeans/html/boot/impl/JavaScriptProcesor.java Thu Jan 30 17:08:51 2014 +0100
8.3 @@ -66,6 +66,7 @@
8.4 import javax.lang.model.element.ElementKind;
8.5 import javax.lang.model.element.ExecutableElement;
8.6 import javax.lang.model.element.Modifier;
8.7 +import javax.lang.model.element.Name;
8.8 import javax.lang.model.element.PackageElement;
8.9 import javax.lang.model.element.TypeElement;
8.10 import javax.lang.model.element.VariableElement;
8.11 @@ -280,11 +281,20 @@
8.12 }
8.13
8.14 private void generateJavaScriptBodyList(Map<String,Set<TypeElement>> bodies) {
8.15 - for (Map.Entry<String, Set<TypeElement>> entry : bodies.entrySet()) {
8.16 - String pkg = entry.getKey();
8.17 - Set<TypeElement> classes = entry.getValue();
8.18 -
8.19 - try {
8.20 + if (bodies.isEmpty()) {
8.21 + return;
8.22 + }
8.23 + try {
8.24 + FileObject all = processingEnv.getFiler().createResource(
8.25 + StandardLocation.CLASS_OUTPUT, "", "META-INF/net.java.html.js.classes"
8.26 + );
8.27 + PrintWriter wAll = new PrintWriter(new OutputStreamWriter(
8.28 + all.openOutputStream(), "UTF-8"
8.29 + ));
8.30 + for (Map.Entry<String, Set<TypeElement>> entry : bodies.entrySet()) {
8.31 + String pkg = entry.getKey();
8.32 + Set<TypeElement> classes = entry.getValue();
8.33 +
8.34 FileObject out = processingEnv.getFiler().createResource(
8.35 StandardLocation.CLASS_OUTPUT, pkg, "net.java.html.js.classes",
8.36 classes.iterator().next()
8.37 @@ -293,16 +303,21 @@
8.38 try {
8.39 PrintWriter w = new PrintWriter(new OutputStreamWriter(os, "UTF-8"));
8.40 for (TypeElement type : classes) {
8.41 - w.println(processingEnv.getElementUtils().getBinaryName(type));
8.42 + final Name bn = processingEnv.getElementUtils().getBinaryName(type);
8.43 + w.println(bn);
8.44 + wAll.println(bn);
8.45 }
8.46 w.flush();
8.47 w.close();
8.48 + } catch (IOException x) {
8.49 + processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Failed to write to " + entry.getKey() + ": " + x.toString());
8.50 } finally {
8.51 os.close();
8.52 }
8.53 - } catch (IOException x) {
8.54 - processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Failed to write to " + entry.getKey() + ": " + x.toString());
8.55 }
8.56 + wAll.close();
8.57 + } catch (IOException x) {
8.58 + processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Failed to write to " + "META-INF/net.java.html.js.classes: " + x.toString());
8.59 }
8.60 }
8.61
9.1 --- a/boot/src/main/java/org/netbeans/html/boot/impl/JsPkgCache.java Thu Jan 30 12:09:09 2014 +0100
9.2 +++ b/boot/src/main/java/org/netbeans/html/boot/impl/JsPkgCache.java Thu Jan 30 17:08:51 2014 +0100
9.3 @@ -66,7 +66,7 @@
9.4 private static final Set<String> NONE = Collections.emptySet();
9.5
9.6 public static boolean process(ClassLoader l, String className) {
9.7 - if (className.equals("org.netbeans.html.boot.impl.Test")) {
9.8 + if (className.equals("org.netbeans.html.boot.impl.Test")) { // NOI18N
9.9 return true;
9.10 }
9.11 Set<String> p;
10.1 --- a/boot/src/main/java/org/netbeans/html/boot/impl/Test.java Thu Jan 30 12:09:09 2014 +0100
10.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
10.3 @@ -1,57 +0,0 @@
10.4 -/**
10.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
10.6 - *
10.7 - * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
10.8 - *
10.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
10.10 - * Other names may be trademarks of their respective owners.
10.11 - *
10.12 - * The contents of this file are subject to the terms of either the GNU
10.13 - * General Public License Version 2 only ("GPL") or the Common
10.14 - * Development and Distribution License("CDDL") (collectively, the
10.15 - * "License"). You may not use this file except in compliance with the
10.16 - * License. You can obtain a copy of the License at
10.17 - * http://www.netbeans.org/cddl-gplv2.html
10.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
10.19 - * specific language governing permissions and limitations under the
10.20 - * License. When distributing the software, include this License Header
10.21 - * Notice in each file and include the License file at
10.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
10.23 - * particular file as subject to the "Classpath" exception as provided
10.24 - * by Oracle in the GPL Version 2 section of the License file that
10.25 - * accompanied this code. If applicable, add the following below the
10.26 - * License Header, with the fields enclosed by brackets [] replaced by
10.27 - * your own identifying information:
10.28 - * "Portions Copyrighted [year] [name of copyright owner]"
10.29 - *
10.30 - * Contributor(s):
10.31 - *
10.32 - * The Original Software is NetBeans. The Initial Developer of the Original
10.33 - * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
10.34 - *
10.35 - * If you wish your version of this file to be governed by only the CDDL
10.36 - * or only the GPL Version 2, indicate your decision by adding
10.37 - * "[Contributor] elects to include this software in this distribution
10.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
10.39 - * single choice of license, a recipient has the option to distribute
10.40 - * your version of this file under either the CDDL, the GPL Version 2 or
10.41 - * to extend the choice of license to its licensees as provided above.
10.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
10.43 - * Version 2 license, then the option applies only if the new code is
10.44 - * made subject to such option by the copyright holder.
10.45 - */
10.46 -package org.netbeans.html.boot.impl;
10.47 -
10.48 -import java.util.concurrent.Callable;
10.49 -import net.java.html.js.JavaScriptBody;
10.50 -
10.51 -/**
10.52 - *
10.53 - * @author Jaroslav Tulach <jtulach@netbeans.org>
10.54 - */
10.55 -public final class Test implements Callable<Boolean> {
10.56 - @Override @JavaScriptBody(args = {}, body = "return true;")
10.57 - public Boolean call() {
10.58 - return false;
10.59 - }
10.60 -}
11.1 --- a/geo/pom.xml Thu Jan 30 12:09:09 2014 +0100
11.2 +++ b/geo/pom.xml Thu Jan 30 17:08:51 2014 +0100
11.3 @@ -22,6 +22,10 @@
11.4 <groupId>org.apache.felix</groupId>
11.5 <artifactId>maven-bundle-plugin</artifactId>
11.6 </plugin>
11.7 + <plugin>
11.8 + <groupId>org.netbeans.html</groupId>
11.9 + <artifactId>html4j-maven-plugin</artifactId>
11.10 + </plugin>
11.11 </plugins>
11.12 </build>
11.13 <dependencies>
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
12.2 +++ b/html4j-maven-plugin/pom.xml Thu Jan 30 17:08:51 2014 +0100
12.3 @@ -0,0 +1,75 @@
12.4 +<?xml version="1.0"?>
12.5 +<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
12.6 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
12.7 + <modelVersion>4.0.0</modelVersion>
12.8 + <parent>
12.9 + <groupId>org.netbeans.html</groupId>
12.10 + <artifactId>pom</artifactId>
12.11 + <version>0.8-SNAPSHOT</version>
12.12 + </parent>
12.13 + <packaging>maven-plugin</packaging>
12.14 + <groupId>org.netbeans.html</groupId>
12.15 + <artifactId>html4j-maven-plugin</artifactId>
12.16 + <version>0.8-SNAPSHOT</version>
12.17 + <name>html4j-maven-plugin</name>
12.18 + <url>http://maven.apache.org</url>
12.19 + <properties>
12.20 + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
12.21 + </properties>
12.22 + <build>
12.23 + <plugins>
12.24 + <plugin>
12.25 + <groupId>org.apache.maven.plugins</groupId>
12.26 + <artifactId>maven-plugin-plugin</artifactId>
12.27 + <version>3.1</version>
12.28 + <configuration>
12.29 + <extractors>
12.30 + <extractor>java-annotations</extractor>
12.31 + </extractors>
12.32 + <skipErrorNoDescriptorsFound>true</skipErrorNoDescriptorsFound>
12.33 + </configuration>
12.34 + <executions>
12.35 + <execution>
12.36 + <id>mojo-descriptor</id>
12.37 + <phase>process-classes</phase>
12.38 + <goals>
12.39 + <goal>descriptor</goal>
12.40 + </goals>
12.41 + </execution>
12.42 + </executions>
12.43 + </plugin>
12.44 + </plugins>
12.45 + </build>
12.46 +
12.47 + <dependencies>
12.48 + <dependency>
12.49 + <groupId>org.apache.maven</groupId>
12.50 + <artifactId>maven-plugin-api</artifactId>
12.51 + <version>3.0.4</version>
12.52 + <type>jar</type>
12.53 + </dependency>
12.54 + <dependency>
12.55 + <groupId>org.apache.maven.plugin-tools</groupId>
12.56 + <artifactId>maven-plugin-annotations</artifactId>
12.57 + <version>3.0</version>
12.58 + <type>jar</type>
12.59 + </dependency>
12.60 + <dependency>
12.61 + <groupId>org.apache.maven</groupId>
12.62 + <artifactId>maven-core</artifactId>
12.63 + <version>3.0.2</version>
12.64 + <type>jar</type>
12.65 + </dependency>
12.66 + <dependency>
12.67 + <groupId>org.ow2.asm</groupId>
12.68 + <artifactId>asm</artifactId>
12.69 + <type>jar</type>
12.70 + </dependency>
12.71 + <dependency>
12.72 + <groupId>org.testng</groupId>
12.73 + <artifactId>testng</artifactId>
12.74 + <scope>test</scope>
12.75 + <type>jar</type>
12.76 + </dependency>
12.77 + </dependencies>
12.78 +</project>
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
13.2 +++ b/html4j-maven-plugin/src/main/java/org/apidesign/html/mojo/ProcessJsAnnotationsMojo.java Thu Jan 30 17:08:51 2014 +0100
13.3 @@ -0,0 +1,221 @@
13.4 +/**
13.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
13.6 + *
13.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
13.8 + *
13.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
13.10 + * Other names may be trademarks of their respective owners.
13.11 + *
13.12 + * The contents of this file are subject to the terms of either the GNU
13.13 + * General Public License Version 2 only ("GPL") or the Common
13.14 + * Development and Distribution License("CDDL") (collectively, the
13.15 + * "License"). You may not use this file except in compliance with the
13.16 + * License. You can obtain a copy of the License at
13.17 + * http://www.netbeans.org/cddl-gplv2.html
13.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13.19 + * specific language governing permissions and limitations under the
13.20 + * License. When distributing the software, include this License Header
13.21 + * Notice in each file and include the License file at
13.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
13.23 + * particular file as subject to the "Classpath" exception as provided
13.24 + * by Oracle in the GPL Version 2 section of the License file that
13.25 + * accompanied this code. If applicable, add the following below the
13.26 + * License Header, with the fields enclosed by brackets [] replaced by
13.27 + * your own identifying information:
13.28 + * "Portions Copyrighted [year] [name of copyright owner]"
13.29 + *
13.30 + * Contributor(s):
13.31 + *
13.32 + * The Original Software is NetBeans. The Initial Developer of the Original
13.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
13.34 + *
13.35 + * If you wish your version of this file to be governed by only the CDDL
13.36 + * or only the GPL Version 2, indicate your decision by adding
13.37 + * "[Contributor] elects to include this software in this distribution
13.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
13.39 + * single choice of license, a recipient has the option to distribute
13.40 + * your version of this file under either the CDDL, the GPL Version 2 or
13.41 + * to extend the choice of license to its licensees as provided above.
13.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
13.43 + * Version 2 license, then the option applies only if the new code is
13.44 + * made subject to such option by the copyright holder.
13.45 + */
13.46 +package org.apidesign.html.mojo;
13.47 +
13.48 +import java.io.BufferedReader;
13.49 +import java.io.File;
13.50 +import java.io.FileInputStream;
13.51 +import java.io.FileNotFoundException;
13.52 +import java.io.FileOutputStream;
13.53 +import java.io.FileReader;
13.54 +import java.io.FileWriter;
13.55 +import java.io.IOException;
13.56 +import java.io.InputStream;
13.57 +import java.lang.reflect.Method;
13.58 +import java.net.MalformedURLException;
13.59 +import java.net.URL;
13.60 +import java.net.URLClassLoader;
13.61 +import java.util.ArrayList;
13.62 +import java.util.List;
13.63 +import org.apache.maven.artifact.Artifact;
13.64 +import org.apache.maven.plugin.AbstractMojo;
13.65 +import org.apache.maven.plugin.MojoExecutionException;
13.66 +import org.apache.maven.plugin.MojoFailureException;
13.67 +import org.apache.maven.plugins.annotations.Component;
13.68 +import org.apache.maven.plugins.annotations.LifecyclePhase;
13.69 +import org.apache.maven.plugins.annotations.Mojo;
13.70 +import org.apache.maven.plugins.annotations.Parameter;
13.71 +import org.apache.maven.plugins.annotations.ResolutionScope;
13.72 +import org.apache.maven.project.MavenProject;
13.73 +import org.objectweb.asm.ClassReader;
13.74 +
13.75 +@Mojo(
13.76 + name="process-js-annotations",
13.77 + requiresDependencyResolution = ResolutionScope.COMPILE,
13.78 + defaultPhase= LifecyclePhase.PROCESS_CLASSES
13.79 +)
13.80 +public final class ProcessJsAnnotationsMojo extends AbstractMojo {
13.81 + @Component
13.82 + private MavenProject prj;
13.83 +
13.84 + @Parameter(defaultValue = "${project.build.directory}/classes")
13.85 + private File classes;
13.86 +
13.87 + public ProcessJsAnnotationsMojo() {
13.88 + }
13.89 +
13.90 + @Override
13.91 + public void execute() throws MojoExecutionException, MojoFailureException {
13.92 + List<URL> arr = new ArrayList<URL>();
13.93 + boolean foundAsm = false;
13.94 + for (Artifact a : prj.getArtifacts()) {
13.95 + final File f = a.getFile();
13.96 + if (f != null) {
13.97 + if (a.getArtifactId().equals("asm")) {
13.98 + foundAsm = true;
13.99 + }
13.100 + try {
13.101 + arr.add(f.toURI().toURL());
13.102 + } catch (MalformedURLException ex) {
13.103 + throw new IllegalStateException(ex);
13.104 + }
13.105 + }
13.106 + }
13.107 + if (!foundAsm) {
13.108 + URL loc = ClassReader.class.getProtectionDomain().getCodeSource().getLocation();
13.109 + arr.add(loc);
13.110 + }
13.111 + URLClassLoader l = new URLClassLoader(arr.toArray(new URL[arr.size()]));
13.112 + try {
13.113 + File master = new File(new File(classes, "META-INF"), "net.java.html.js.classes");
13.114 + processClasses(l, master, classes);
13.115 + } catch (IOException ex) {
13.116 + throw new MojoExecutionException("Problem converting JavaScriptXXX annotations", ex);
13.117 + }
13.118 + }
13.119 +
13.120 + private void processClasses(ClassLoader l, File master, File f) throws IOException, MojoExecutionException {
13.121 + if (!f.exists()) {
13.122 + return;
13.123 + }
13.124 + if (f.isDirectory()) {
13.125 + boolean classes = new File(f, "net.java.html.js.classes").exists();
13.126 + File[] arr = f.listFiles();
13.127 + if (arr != null) {
13.128 + for (File file : arr) {
13.129 + if (classes || file.isDirectory()) {
13.130 + processClasses(l, master, file);
13.131 + }
13.132 + }
13.133 + }
13.134 + return;
13.135 + }
13.136 +
13.137 + if (!f.getName().endsWith(".class")) {
13.138 + return;
13.139 + }
13.140 +
13.141 + byte[] arr = new byte[(int)f.length()];
13.142 + FileInputStream is = new FileInputStream(f);
13.143 + try {
13.144 + readArr(arr, is);
13.145 + } finally {
13.146 + is.close();
13.147 + }
13.148 +
13.149 + byte[] newArr = null;
13.150 + try {
13.151 + Class<?> fnUtils = l.loadClass("org.netbeans.html.boot.impl.FnUtils");
13.152 + Method transform = fnUtils.getMethod("transform", byte[].class, ClassLoader.class);
13.153 +
13.154 + newArr = (byte[]) transform.invoke(null, arr, l);
13.155 + if (newArr == null || newArr == arr) {
13.156 + return;
13.157 + }
13.158 + filterClass(new File(f.getParentFile(), "net.java.html.js.classes"), f.getName());
13.159 + filterClass(master, f.getName());
13.160 + } catch (Exception ex) {
13.161 + throw new MojoExecutionException("Can't process " + f, ex);
13.162 + }
13.163 + getLog().info("Processing " + f);
13.164 + writeArr(f, newArr);
13.165 + }
13.166 +
13.167 + private void writeArr(File f, byte[] newArr) throws IOException, FileNotFoundException {
13.168 + FileOutputStream os = new FileOutputStream(f);
13.169 + try {
13.170 + os.write(newArr);
13.171 + } finally {
13.172 + os.close();
13.173 + }
13.174 + }
13.175 +
13.176 + private static void readArr(byte[] arr, InputStream is) throws IOException {
13.177 + int off = 0;
13.178 + while (off< arr.length) {
13.179 + int read = is.read(arr, off, arr.length - off);
13.180 + if (read == -1) {
13.181 + break;
13.182 + }
13.183 + off += read;
13.184 + }
13.185 + }
13.186 +
13.187 + private static void filterClass(File f, String className) throws IOException {
13.188 + if (!f.exists()) {
13.189 + return;
13.190 + }
13.191 + if (className.endsWith(".class")) {
13.192 + className = className.substring(0, className.length() - 6);
13.193 + }
13.194 +
13.195 + BufferedReader r = new BufferedReader(new FileReader(f));
13.196 + List<String> arr = new ArrayList<String>();
13.197 + boolean modified = false;
13.198 + for (;;) {
13.199 + String line = r.readLine();
13.200 + if (line == null) {
13.201 + break;
13.202 + }
13.203 + if (line.endsWith(className)) {
13.204 + modified = true;
13.205 + continue;
13.206 + }
13.207 + arr.add(line);
13.208 + }
13.209 + r.close();
13.210 +
13.211 + if (modified) {
13.212 + if (arr.isEmpty()) {
13.213 + f.delete();
13.214 + } else {
13.215 + FileWriter w = new FileWriter(f);
13.216 + for (String l : arr) {
13.217 + w.write(l);
13.218 + w.write("\n");
13.219 + }
13.220 + w.close();
13.221 + }
13.222 + }
13.223 + }
13.224 +}
14.1 --- a/json-tck/pom.xml Thu Jan 30 12:09:09 2014 +0100
14.2 +++ b/json-tck/pom.xml Thu Jan 30 17:08:51 2014 +0100
14.3 @@ -23,6 +23,10 @@
14.4 <artifactId>maven-bundle-plugin</artifactId>
14.5 </plugin>
14.6 <plugin>
14.7 + <groupId>org.netbeans.html</groupId>
14.8 + <artifactId>html4j-maven-plugin</artifactId>
14.9 + </plugin>
14.10 + <plugin>
14.11 <groupId>org.apache.maven.plugins</groupId>
14.12 <artifactId>maven-javadoc-plugin</artifactId>
14.13 <configuration>
15.1 --- a/json-tck/src/main/java/net/java/html/js/tests/JavaScriptBodyTest.java Thu Jan 30 12:09:09 2014 +0100
15.2 +++ b/json-tck/src/main/java/net/java/html/js/tests/JavaScriptBodyTest.java Thu Jan 30 17:08:51 2014 +0100
15.3 @@ -42,8 +42,10 @@
15.4 */
15.5 package net.java.html.js.tests;
15.6
15.7 +import java.io.StringReader;
15.8 import java.util.Arrays;
15.9 import java.util.concurrent.Callable;
15.10 +import org.apidesign.html.boot.spi.Fn;
15.11 import org.apidesign.html.json.tck.KOTest;
15.12
15.13 /**
15.14 @@ -272,6 +274,18 @@
15.15 assert r == 6 : "Sum is six: " + r;
15.16 }
15.17
15.18 + @KOTest public void callLater() throws Exception{
15.19 + Fn.activePresenter().loadScript(new StringReader(
15.20 + "if (typeof window === 'undefined') window = {};"
15.21 + ));
15.22 + Later l = new Later();
15.23 + l.register();
15.24 + Fn.activePresenter().loadScript(new StringReader(
15.25 + "window.later();"
15.26 + ));
15.27 + assert l.call == 42 : "Method was called: " + l.call;
15.28 + }
15.29 +
15.30 private static class R implements Runnable {
15.31 int cnt;
15.32 private final Thread initThread;
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
16.2 +++ b/json-tck/src/main/java/net/java/html/js/tests/Later.java Thu Jan 30 17:08:51 2014 +0100
16.3 @@ -0,0 +1,65 @@
16.4 +/**
16.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
16.6 + *
16.7 + * Copyright 2013-2013 Oracle and/or its affiliates. All rights reserved.
16.8 + *
16.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
16.10 + * Other names may be trademarks of their respective owners.
16.11 + *
16.12 + * The contents of this file are subject to the terms of either the GNU
16.13 + * General Public License Version 2 only ("GPL") or the Common
16.14 + * Development and Distribution License("CDDL") (collectively, the
16.15 + * "License"). You may not use this file except in compliance with the
16.16 + * License. You can obtain a copy of the License at
16.17 + * http://www.netbeans.org/cddl-gplv2.html
16.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16.19 + * specific language governing permissions and limitations under the
16.20 + * License. When distributing the software, include this License Header
16.21 + * Notice in each file and include the License file at
16.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
16.23 + * particular file as subject to the "Classpath" exception as provided
16.24 + * by Oracle in the GPL Version 2 section of the License file that
16.25 + * accompanied this code. If applicable, add the following below the
16.26 + * License Header, with the fields enclosed by brackets [] replaced by
16.27 + * your own identifying information:
16.28 + * "Portions Copyrighted [year] [name of copyright owner]"
16.29 + *
16.30 + * Contributor(s):
16.31 + *
16.32 + * The Original Software is NetBeans. The Initial Developer of the Original
16.33 + * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
16.34 + *
16.35 + * If you wish your version of this file to be governed by only the CDDL
16.36 + * or only the GPL Version 2, indicate your decision by adding
16.37 + * "[Contributor] elects to include this software in this distribution
16.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
16.39 + * single choice of license, a recipient has the option to distribute
16.40 + * your version of this file under either the CDDL, the GPL Version 2 or
16.41 + * to extend the choice of license to its licensees as provided above.
16.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
16.43 + * Version 2 license, then the option applies only if the new code is
16.44 + * made subject to such option by the copyright holder.
16.45 + */
16.46 +package net.java.html.js.tests;
16.47 +
16.48 +import net.java.html.js.JavaScriptBody;
16.49 +
16.50 +/**
16.51 + *
16.52 + * @author Jaroslav Tulach <jtulach@netbeans.org>
16.53 + */
16.54 +public final class Later {
16.55 + int call;
16.56 +
16.57 + @JavaScriptBody(args = { }, javacall = true, body =
16.58 + "var self = this;"
16.59 + + "window.later = function() {"
16.60 + + " self.@net.java.html.js.tests.Later::call(I)(42);"
16.61 + + "};"
16.62 + )
16.63 + native void register();
16.64 +
16.65 + void call(int value) {
16.66 + this.call = value;
16.67 + }
16.68 +}
17.1 --- a/ko-osgi-test/pom.xml Thu Jan 30 12:09:09 2014 +0100
17.2 +++ b/ko-osgi-test/pom.xml Thu Jan 30 17:08:51 2014 +0100
17.3 @@ -20,6 +20,10 @@
17.4 <artifactId>maven-bundle-plugin</artifactId>
17.5 </plugin>
17.6 <plugin>
17.7 + <groupId>org.netbeans.html</groupId>
17.8 + <artifactId>html4j-maven-plugin</artifactId>
17.9 + </plugin>
17.10 + <plugin>
17.11 <artifactId>maven-failsafe-plugin</artifactId>
17.12 <version>2.16</version>
17.13 <configuration>
18.1 --- a/ko-ws-tyrus/pom.xml Thu Jan 30 12:09:09 2014 +0100
18.2 +++ b/ko-ws-tyrus/pom.xml Thu Jan 30 17:08:51 2014 +0100
18.3 @@ -19,6 +19,10 @@
18.4 <artifactId>maven-bundle-plugin</artifactId>
18.5 </plugin>
18.6 <plugin>
18.7 + <groupId>org.netbeans.html</groupId>
18.8 + <artifactId>html4j-maven-plugin</artifactId>
18.9 + </plugin>
18.10 + <plugin>
18.11 <groupId>org.apache.maven.plugins</groupId>
18.12 <artifactId>maven-javadoc-plugin</artifactId>
18.13 <configuration>
19.1 --- a/ko-ws-tyrus/src/test/java/org/netbeans/html/wstyrus/TyrusKnockoutTest.java Thu Jan 30 12:09:09 2014 +0100
19.2 +++ b/ko-ws-tyrus/src/test/java/org/netbeans/html/wstyrus/TyrusKnockoutTest.java Thu Jan 30 17:08:51 2014 +0100
19.3 @@ -70,6 +70,7 @@
19.4 import org.netbeans.html.boot.impl.FnContext;
19.5 import org.netbeans.html.ko4j.KO4J;
19.6 import org.openide.util.lookup.ServiceProvider;
19.7 +import org.testng.Assert;
19.8 import static org.testng.Assert.*;
19.9 import org.testng.annotations.Factory;
19.10
19.11 @@ -133,15 +134,17 @@
19.12
19.13 public static synchronized void initialized(Class<?> browserCls) throws Exception {
19.14 browserClass = browserCls;
19.15 - browserContext = FnContext.currentPresenter();
19.16 + browserContext = Fn.activePresenter();
19.17 TyrusKnockoutTest.class.notifyAll();
19.18 }
19.19
19.20 public static void initialized() throws Exception {
19.21 - Class<?> classpathClass = ClassLoader.getSystemClassLoader().loadClass(TyrusKnockoutTest.class.getName());
19.22 - Method m = classpathClass.getMethod("initialized", Class.class);
19.23 - m.invoke(null, TyrusKnockoutTest.class);
19.24 - browserContext = FnContext.currentPresenter();
19.25 + Assert.assertSame(
19.26 + TyrusKnockoutTest.class.getClassLoader(),
19.27 + ClassLoader.getSystemClassLoader(),
19.28 + "No special classloaders"
19.29 + );
19.30 + TyrusKnockoutTest.initialized(TyrusKnockoutTest.class);
19.31 }
19.32
19.33 @Override
20.1 --- a/ko4j/pom.xml Thu Jan 30 12:09:09 2014 +0100
20.2 +++ b/ko4j/pom.xml Thu Jan 30 17:08:51 2014 +0100
20.3 @@ -23,6 +23,10 @@
20.4 <artifactId>maven-bundle-plugin</artifactId>
20.5 </plugin>
20.6 <plugin>
20.7 + <groupId>org.netbeans.html</groupId>
20.8 + <artifactId>html4j-maven-plugin</artifactId>
20.9 + </plugin>
20.10 + <plugin>
20.11 <groupId>org.apache.maven.plugins</groupId>
20.12 <artifactId>maven-javadoc-plugin</artifactId>
20.13 <configuration>
21.1 --- a/ko4j/src/test/java/org/netbeans/html/ko4j/KnockoutFXTest.java Thu Jan 30 12:09:09 2014 +0100
21.2 +++ b/ko4j/src/test/java/org/netbeans/html/ko4j/KnockoutFXTest.java Thu Jan 30 17:08:51 2014 +0100
21.3 @@ -58,7 +58,6 @@
21.4 import net.java.html.BrwsrCtx;
21.5 import net.java.html.boot.BrowserBuilder;
21.6 import net.java.html.js.JavaScriptBody;
21.7 -import org.netbeans.html.boot.impl.FnContext;
21.8 import org.apidesign.html.boot.spi.Fn;
21.9 import org.apidesign.html.context.spi.Contexts;
21.10 import org.apidesign.html.json.spi.Technology;
21.11 @@ -66,9 +65,11 @@
21.12 import org.apidesign.html.json.spi.WSTransfer;
21.13 import org.apidesign.html.json.tck.KOTest;
21.14 import org.apidesign.html.json.tck.KnockoutTCK;
21.15 +import org.netbeans.html.boot.impl.FnContext;
21.16 import org.openide.util.lookup.ServiceProvider;
21.17 +import org.testng.Assert;
21.18 +import static org.testng.Assert.*;
21.19 import org.testng.annotations.Factory;
21.20 -import static org.testng.Assert.*;
21.21
21.22 /**
21.23 *
21.24 @@ -136,15 +137,18 @@
21.25
21.26 public static synchronized void initialized(Class<?> browserCls) throws Exception {
21.27 browserClass = browserCls;
21.28 - browserContext = FnContext.currentPresenter();
21.29 + browserContext = Fn.activePresenter();
21.30 KnockoutFXTest.class.notifyAll();
21.31 }
21.32
21.33 public static void initialized() throws Exception {
21.34 - Class<?> classpathClass = ClassLoader.getSystemClassLoader().loadClass(KnockoutFXTest.class.getName());
21.35 - Method m = classpathClass.getMethod("initialized", Class.class);
21.36 - m.invoke(null, KnockoutFXTest.class);
21.37 - browserContext = FnContext.currentPresenter();
21.38 + Assert.assertSame(
21.39 + KnockoutFXTest.class.getClassLoader(),
21.40 + ClassLoader.getSystemClassLoader(),
21.41 + "No special classloaders"
21.42 + );
21.43 + KnockoutFXTest.initialized(KnockoutFXTest.class);
21.44 + browserContext = Fn.activePresenter();
21.45 }
21.46
21.47 @Override
22.1 --- a/pom.xml Thu Jan 30 12:09:09 2014 +0100
22.2 +++ b/pom.xml Thu Jan 30 17:08:51 2014 +0100
22.3 @@ -31,6 +31,7 @@
22.4 <module>boot-fx</module>
22.5 <module>geo</module>
22.6 <module>ko-ws-tyrus</module>
22.7 + <module>html4j-maven-plugin</module>
22.8 <module>ko-osgi-test</module>
22.9 <module>equinox-agentclass-hook</module>
22.10 </modules>
22.11 @@ -133,11 +134,34 @@
22.12 <extensions>true</extensions>
22.13 <configuration>
22.14 <instructions>
22.15 - <Export-Package>${publicPackages},META-INF.services.*</Export-Package>
22.16 + <Export-Package>${publicPackages},META-INF.services.*;-noimport:=true;-split-package:=first</Export-Package>
22.17 <Bundle-SymbolicName>${bundleSymbolicName}</Bundle-SymbolicName>
22.18 </instructions>
22.19 </configuration>
22.20 </plugin>
22.21 + <plugin>
22.22 + <groupId>org.netbeans.html</groupId>
22.23 + <artifactId>html4j-maven-plugin</artifactId>
22.24 + <version>${project.version}</version>
22.25 + <executions>
22.26 + <execution>
22.27 + <id>classes</id>
22.28 + <goals>
22.29 + <goal>process-js-annotations</goal>
22.30 + </goals>
22.31 + </execution>
22.32 + <execution>
22.33 + <id>test-classes</id>
22.34 + <phase>process-test-classes</phase>
22.35 + <goals>
22.36 + <goal>process-js-annotations</goal>
22.37 + </goals>
22.38 + <configuration>
22.39 + <classes>${project.build.directory}/test-classes</classes>
22.40 + </configuration>
22.41 + </execution>
22.42 + </executions>
22.43 + </plugin>
22.44 </plugins>
22.45 </pluginManagement>
22.46 </build>
22.47 @@ -161,6 +185,11 @@
22.48 <version>20080701</version>
22.49 </dependency>
22.50 <dependency>
22.51 + <groupId>org.ow2.asm</groupId>
22.52 + <artifactId>asm</artifactId>
22.53 + <version>4.1</version>
22.54 + </dependency>
22.55 + <dependency>
22.56 <groupId>org.netbeans.api</groupId>
22.57 <artifactId>org-netbeans-modules-classfile</artifactId>
22.58 <version>${netbeans.version}</version>
23.1 --- a/sound/pom.xml Thu Jan 30 12:09:09 2014 +0100
23.2 +++ b/sound/pom.xml Thu Jan 30 17:08:51 2014 +0100
23.3 @@ -22,6 +22,10 @@
23.4 <groupId>org.apache.felix</groupId>
23.5 <artifactId>maven-bundle-plugin</artifactId>
23.6 </plugin>
23.7 + <plugin>
23.8 + <groupId>org.netbeans.html</groupId>
23.9 + <artifactId>html4j-maven-plugin</artifactId>
23.10 + </plugin>
23.11 </plugins>
23.12 </build>
23.13 <dependencies>