1.1 --- a/boot-fx/src/main/java/org/apidesign/html/boot/fx/FXPresenter.java Wed Jun 26 08:41:40 2013 +0200
1.2 +++ b/boot-fx/src/main/java/org/apidesign/html/boot/fx/FXPresenter.java Wed Jun 26 08:43:32 2013 +0200
1.3 @@ -20,6 +20,8 @@
1.4 */
1.5 package org.apidesign.html.boot.fx;
1.6
1.7 +import java.io.BufferedReader;
1.8 +import java.io.Reader;
1.9 import java.lang.reflect.Method;
1.10 import java.net.URL;
1.11 import java.net.URLClassLoader;
1.12 @@ -95,6 +97,20 @@
1.13 }
1.14
1.15 @Override
1.16 + public void loadScript(Reader code) throws Exception {
1.17 + BufferedReader r = new BufferedReader(code);
1.18 + StringBuilder sb = new StringBuilder();
1.19 + for (;;) {
1.20 + String l = r.readLine();
1.21 + if (l == null) {
1.22 + break;
1.23 + }
1.24 + sb.append(l).append('\n');
1.25 + }
1.26 + engine.executeScript(sb.toString());
1.27 + }
1.28 +
1.29 + @Override
1.30 public void displayPage(final URL resource, Runnable onLoad) {
1.31 engine = FXBrwsr.findEngine(onLoad);
1.32 Platform.runLater(new Runnable() {
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/boot/src/main/java/net/java/html/js/JavaScriptResource.java Wed Jun 26 08:43:32 2013 +0200
2.3 @@ -0,0 +1,42 @@
2.4 +/**
2.5 + * HTML via Java(tm) Language Bindings
2.6 + * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
2.7 + *
2.8 + * This program is free software: you can redistribute it and/or modify
2.9 + * it under the terms of the GNU General Public License as published by
2.10 + * the Free Software Foundation, version 2 of the License.
2.11 + *
2.12 + * This program is distributed in the hope that it will be useful,
2.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
2.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2.15 + * GNU General Public License for more details. apidesign.org
2.16 + * designates this particular file as subject to the
2.17 + * "Classpath" exception as provided by apidesign.org
2.18 + * in the License file that accompanied this code.
2.19 + *
2.20 + * You should have received a copy of the GNU General Public License
2.21 + * along with this program. Look for COPYING file in the top folder.
2.22 + * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
2.23 + */
2.24 +package net.java.html.js;
2.25 +
2.26 +import java.lang.annotation.ElementType;
2.27 +import java.lang.annotation.Retention;
2.28 +import java.lang.annotation.RetentionPolicy;
2.29 +import java.lang.annotation.Target;
2.30 +import net.java.html.boot.BrowserBuilder;
2.31 +
2.32 +/** When a class annotated by this annotation is loaded into the Java virtual
2.33 + * machine by {@link BrowserBuilder} classloader, the script referenced by
2.34 + * this annotation gets loaded into associated JavaScript executor environment.
2.35 + *
2.36 + * @author Jaroslav Tulach <jtulach@netbeans.org>
2.37 + */
2.38 +@Retention(RetentionPolicy.CLASS)
2.39 +@Target(ElementType.TYPE)
2.40 +public @interface JavaScriptResource {
2.41 + /** The JavaScript file to load in before associated class can execute.
2.42 + * @return relative path with respect to the annotated class
2.43 + */
2.44 + public String value();
2.45 +}
3.1 --- a/boot/src/main/java/org/apidesign/html/boot/impl/FnUtils.java Wed Jun 26 08:41:40 2013 +0200
3.2 +++ b/boot/src/main/java/org/apidesign/html/boot/impl/FnUtils.java Wed Jun 26 08:43:32 2013 +0200
3.3 @@ -20,6 +20,9 @@
3.4 */
3.5 package org.apidesign.html.boot.impl;
3.6
3.7 +import java.io.InputStream;
3.8 +import java.io.InputStreamReader;
3.9 +import java.io.Reader;
3.10 import java.lang.reflect.Method;
3.11 import java.net.URL;
3.12 import java.util.ArrayList;
3.13 @@ -65,6 +68,11 @@
3.14 protected Fn defineFn(String code, String... names) {
3.15 return d.defineFn(code, names);
3.16 }
3.17 +
3.18 + @Override
3.19 + protected void loadScript(Reader code) throws Exception {
3.20 + d.loadScript(code);
3.21 + }
3.22 };
3.23 }
3.24
3.25 @@ -145,5 +153,24 @@
3.26 }
3.27 return Class.forName(t.getClassName(), false, loader);
3.28 }
3.29 -
3.30 +
3.31 + static void loadScript(JsClassLoader jcl, String resource) {
3.32 + final InputStream script = jcl.getResourceAsStream(resource);
3.33 + if (script == null) {
3.34 + throw new NullPointerException("Can't find " + resource);
3.35 + }
3.36 + try {
3.37 + Reader isr = null;
3.38 + try {
3.39 + isr = new InputStreamReader(script, "UTF-8");
3.40 + jcl.loadScript(isr);
3.41 + } finally {
3.42 + if (isr != null) {
3.43 + isr.close();
3.44 + }
3.45 + }
3.46 + } catch (Exception ex) {
3.47 + throw new IllegalStateException("Can't execute " + resource, ex);
3.48 + }
3.49 + }
3.50 }
4.1 --- a/boot/src/main/java/org/apidesign/html/boot/impl/JsClassLoader.java Wed Jun 26 08:41:40 2013 +0200
4.2 +++ b/boot/src/main/java/org/apidesign/html/boot/impl/JsClassLoader.java Wed Jun 26 08:43:32 2013 +0200
4.3 @@ -23,6 +23,7 @@
4.4 import org.apidesign.html.boot.spi.Fn;
4.5 import java.io.IOException;
4.6 import java.io.InputStream;
4.7 +import java.io.Reader;
4.8 import java.net.URL;
4.9 import java.util.ArrayList;
4.10 import java.util.Enumeration;
4.11 @@ -126,7 +127,7 @@
4.12 }
4.13
4.14 protected abstract Fn defineFn(String code, String... names);
4.15 -
4.16 + protected abstract void loadScript(Reader code) throws Exception;
4.17
4.18 private final class FindInClass extends ClassVisitor {
4.19 private String name;
4.20 @@ -141,7 +142,14 @@
4.21 this.name = name;
4.22 super.visit(version, access, name, signature, superName, interfaces);
4.23 }
4.24 -
4.25 +
4.26 + @Override
4.27 + public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
4.28 + if ("Lnet/java/html/js/JavaScriptResource;".equals(desc)) {
4.29 + return new LoadResource();
4.30 + }
4.31 + return super.visitAnnotation(desc, visible);
4.32 + }
4.33
4.34
4.35 @Override
4.36 @@ -403,6 +411,24 @@
4.37 }
4.38 }
4.39 }
4.40 +
4.41 + private final class LoadResource extends AnnotationVisitor {
4.42 + public LoadResource() {
4.43 + super(Opcodes.ASM4);
4.44 + }
4.45 +
4.46 + @Override
4.47 + public void visit(String attrName, Object value) {
4.48 + String relPath = (String) value;
4.49 + if (relPath.startsWith("/")) {
4.50 + FnUtils.loadScript(JsClassLoader.this, relPath);
4.51 + } else {
4.52 + int last = name.lastIndexOf('/');
4.53 + String fullPath = name.substring(0, last + 1) + relPath;
4.54 + FnUtils.loadScript(JsClassLoader.this, fullPath);
4.55 + }
4.56 + }
4.57 + }
4.58 }
4.59
4.60 private class ClassWriterEx extends ClassWriter {
5.1 --- a/boot/src/main/java/org/apidesign/html/boot/spi/Fn.java Wed Jun 26 08:41:40 2013 +0200
5.2 +++ b/boot/src/main/java/org/apidesign/html/boot/spi/Fn.java Wed Jun 26 08:43:32 2013 +0200
5.3 @@ -20,8 +20,8 @@
5.4 */
5.5 package org.apidesign.html.boot.spi;
5.6
5.7 +import java.io.Reader;
5.8 import java.net.URL;
5.9 -import java.util.Collection;
5.10
5.11 /**
5.12 *
5.13 @@ -33,5 +33,6 @@
5.14 public interface Presenter {
5.15 public Fn defineFn(String code, String... names);
5.16 public void displayPage(URL page, Runnable onPageLoad);
5.17 + public void loadScript(Reader code) throws Exception;
5.18 }
5.19 }
6.1 --- a/boot/src/test/java/org/apidesign/html/boot/impl/FnTest.java Wed Jun 26 08:41:40 2013 +0200
6.2 +++ b/boot/src/test/java/org/apidesign/html/boot/impl/FnTest.java Wed Jun 26 08:43:32 2013 +0200
6.3 @@ -21,6 +21,7 @@
6.4
6.5 package org.apidesign.html.boot.impl;
6.6
6.7 +import java.io.Reader;
6.8 import java.net.URL;
6.9 import java.net.URLClassLoader;
6.10 import java.util.ArrayList;
6.11 @@ -102,6 +103,11 @@
6.12 public void displayPage(URL resource, Runnable r) {
6.13 throw new UnsupportedOperationException();
6.14 }
6.15 +
6.16 + @Override
6.17 + public void loadScript(Reader code) throws Exception {
6.18 + eng.eval(code);
6.19 + }
6.20 }
6.21 Impl impl = new Impl();
6.22 ClassLoader loader = FnUtils.newLoader(impl, impl, parent);
7.1 --- a/boot/src/test/java/org/apidesign/html/boot/impl/JsClassLoaderBase.java Wed Jun 26 08:41:40 2013 +0200
7.2 +++ b/boot/src/test/java/org/apidesign/html/boot/impl/JsClassLoaderBase.java Wed Jun 26 08:43:32 2013 +0200
7.3 @@ -127,4 +127,13 @@
7.4 Method st = methodClass.getMethod("sumArr", int[].class);
7.5 assertEquals(st.invoke(null, new int[] { 1, 2, 3 }), 6, "1+2+3 is six");
7.6 }
7.7 +
7.8 + @Test public void javaScriptResource() throws Throwable {
7.9 + try {
7.10 + Method st = methodClass.getMethod("useExternalMul", int.class, int.class);
7.11 + assertEquals(st.invoke(null, 6, 7), 42, "Meaning of JavaScript?");
7.12 + } catch (InvocationTargetException ex) {
7.13 + throw ex.getTargetException();
7.14 + }
7.15 + }
7.16 }
7.17 \ No newline at end of file
8.1 --- a/boot/src/test/java/org/apidesign/html/boot/impl/JsClassLoaderTest.java Wed Jun 26 08:41:40 2013 +0200
8.2 +++ b/boot/src/test/java/org/apidesign/html/boot/impl/JsClassLoaderTest.java Wed Jun 26 08:43:32 2013 +0200
8.3 @@ -20,6 +20,7 @@
8.4 */
8.5 package org.apidesign.html.boot.impl;
8.6
8.7 +import java.io.Reader;
8.8 import org.apidesign.html.boot.spi.Fn;
8.9 import java.net.URL;
8.10 import java.net.URLClassLoader;
8.11 @@ -94,6 +95,11 @@
8.12 protected Enumeration<URL> findResources(String name) {
8.13 throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
8.14 }
8.15 +
8.16 + @Override
8.17 + protected void loadScript(Reader code) throws ScriptException {
8.18 + eng.eval(code);
8.19 + }
8.20 };
8.21
8.22 methodClass = loader.loadClass(JsMethods.class.getName());
9.1 --- a/boot/src/test/java/org/apidesign/html/boot/impl/JsMethods.java Wed Jun 26 08:41:40 2013 +0200
9.2 +++ b/boot/src/test/java/org/apidesign/html/boot/impl/JsMethods.java Wed Jun 26 08:43:32 2013 +0200
9.3 @@ -21,12 +21,14 @@
9.4 package org.apidesign.html.boot.impl;
9.5
9.6 import net.java.html.js.JavaScriptBody;
9.7 +import net.java.html.js.JavaScriptResource;
9.8
9.9
9.10 /**
9.11 *
9.12 * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
9.13 */
9.14 +@JavaScriptResource("jsmethods.js")
9.15 public class JsMethods {
9.16 @JavaScriptBody(args = {}, body = "return 42;")
9.17 public static Object fortyTwo() {
9.18 @@ -67,4 +69,7 @@
9.19 public static int sumArr(int... arr) {
9.20 return sumArr(new Arithm(), arr);
9.21 }
9.22 +
9.23 + @JavaScriptBody(args = { "x", "y" }, body = "return mul(x, y);")
9.24 + public static native int useExternalMul(int x, int y);
9.25 }
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
10.2 +++ b/boot/src/test/resources/org/apidesign/html/boot/impl/jsmethods.js Wed Jun 26 08:43:32 2013 +0200
10.3 @@ -0,0 +1,22 @@
10.4 +/*
10.5 + * HTML via Java(tm) Language Bindings
10.6 + * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
10.7 + *
10.8 + * This program is free software: you can redistribute it and/or modify
10.9 + * it under the terms of the GNU General Public License as published by
10.10 + * the Free Software Foundation, version 2 of the License.
10.11 + *
10.12 + * This program is distributed in the hope that it will be useful,
10.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
10.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10.15 + * GNU General Public License for more details. apidesign.org
10.16 + * designates this particular file as subject to the
10.17 + * "Classpath" exception as provided by apidesign.org
10.18 + * in the License file that accompanied this code.
10.19 + *
10.20 + * You should have received a copy of the GNU General Public License
10.21 + * along with this program. Look for COPYING file in the top folder.
10.22 + * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
10.23 + */
10.24 +
10.25 +function mul(x, y) { return x * y; }
11.1 --- a/ko-fx/src/main/java/org/apidesign/html/kofx/Knockout.java Wed Jun 26 08:41:40 2013 +0200
11.2 +++ b/ko-fx/src/main/java/org/apidesign/html/kofx/Knockout.java Wed Jun 26 08:43:32 2013 +0200
11.3 @@ -27,6 +27,7 @@
11.4 import java.util.logging.Level;
11.5 import java.util.logging.Logger;
11.6 import net.java.html.js.JavaScriptBody;
11.7 +import net.java.html.js.JavaScriptResource;
11.8 import net.java.html.json.Model;
11.9 import netscape.javascript.JSObject;
11.10 import org.apidesign.html.json.spi.FunctionBinding;
11.11 @@ -41,6 +42,7 @@
11.12 *
11.13 * @author Jaroslav Tulach <jtulach@netbeans.org>
11.14 */
11.15 +@JavaScriptResource("knockout-2.2.1.js")
11.16 public final class Knockout {
11.17 private static final Logger LOG = Logger.getLogger(Knockout.class.getName());
11.18 /** used by tests */
11.19 @@ -110,25 +112,6 @@
11.20 static final JSObject KObject;
11.21
11.22 static {
11.23 - final InputStream koScript = Knockout.class.getResourceAsStream("knockout-2.2.1.js");
11.24 - assert koScript != null : "Can't load knockout.js";
11.25 - BufferedReader r = new BufferedReader(new InputStreamReader(koScript));
11.26 - StringBuilder sb = new StringBuilder();
11.27 - for (;;) {
11.28 - try {
11.29 - String l = r.readLine();
11.30 - if (l == null) {
11.31 - break;
11.32 - }
11.33 - sb.append(l).append('\n');
11.34 - } catch (IOException ex) {
11.35 - throw new IllegalStateException(ex);
11.36 - }
11.37 - }
11.38 - exec(sb.toString());
11.39 - Object ko = exec("ko");
11.40 - assert ko != null : "Knockout library successfully defined 'ko'";
11.41 -
11.42 Console.register();
11.43 KObject = (JSObject) kObj();
11.44 }