Merging with latest state - e.g. 0.7 version
1.1 --- a/.hgtags Tue Apr 02 15:40:51 2013 +0200
1.2 +++ b/.hgtags Thu May 02 09:18:22 2013 +0200
1.3 @@ -1,3 +1,10 @@
1.4 0a115f1c6f3c70458fc479ae82b4d7fcdeb7e95a jdk7-b147_base
1.5 7367a296a9ec4a88e0292a41244c96283818e563 bck2brwsr-0.3
1.6 caf1e66268fd4100d57922d973ae09a6bf3be847 release-${releaseVersion}
1.7 +30e9ac29654fba6f67d0921e7e3aa21133442592 release-0.5
1.8 +caf1e66268fd4100d57922d973ae09a6bf3be847 release-0.4
1.9 +caf1e66268fd4100d57922d973ae09a6bf3be847 release-${releaseVersion}
1.10 +0000000000000000000000000000000000000000 release-${releaseVersion}
1.11 +52a4a5f868bccc67d50ad17f793b9ebabdf75d88 release-0.6
1.12 +6792dc0bafb9c76a099e45bfc9e967d6a2823827 release-0.7
1.13 +623816269b75e53fffb4b19960df7040a3c20056 release-0.7
2.1 --- a/benchmarks/matrix-multiplication/pom.xml Tue Apr 02 15:40:51 2013 +0200
2.2 +++ b/benchmarks/matrix-multiplication/pom.xml Thu May 02 09:18:22 2013 +0200
2.3 @@ -4,12 +4,12 @@
2.4
2.5 <groupId>org.apidesign.bck2brwsr</groupId>
2.6 <artifactId>matrix.multiplication</artifactId>
2.7 - <version>0.5-SNAPSHOT</version>
2.8 + <version>0.8-SNAPSHOT</version>
2.9 <packaging>jar</packaging>
2.10 <parent>
2.11 <artifactId>benchmarks</artifactId>
2.12 <groupId>org.apidesign.bck2brwsr</groupId>
2.13 - <version>0.5-SNAPSHOT</version>
2.14 + <version>0.8-SNAPSHOT</version>
2.15 </parent>
2.16
2.17 <name>Matrix multiplication</name>
2.18 @@ -74,7 +74,7 @@
2.19 <dependency>
2.20 <groupId>org.apidesign.bck2brwsr</groupId>
2.21 <artifactId>emul.mini</artifactId>
2.22 - <version>0.5-SNAPSHOT</version>
2.23 + <version>0.8-SNAPSHOT</version>
2.24 </dependency>
2.25 <dependency>
2.26 <groupId>org.testng</groupId>
2.27 @@ -91,7 +91,13 @@
2.28 <dependency>
2.29 <groupId>org.apidesign.bck2brwsr</groupId>
2.30 <artifactId>vmtest</artifactId>
2.31 - <version>0.5-SNAPSHOT</version>
2.32 + <version>0.8-SNAPSHOT</version>
2.33 + <scope>test</scope>
2.34 + </dependency>
2.35 + <dependency>
2.36 + <groupId>org.apidesign.bck2brwsr</groupId>
2.37 + <artifactId>launcher.http</artifactId>
2.38 + <version>0.8-SNAPSHOT</version>
2.39 <scope>test</scope>
2.40 </dependency>
2.41 </dependencies>
3.1 --- a/benchmarks/pom.xml Tue Apr 02 15:40:51 2013 +0200
3.2 +++ b/benchmarks/pom.xml Thu May 02 09:18:22 2013 +0200
3.3 @@ -4,11 +4,11 @@
3.4 <parent>
3.5 <artifactId>bck2brwsr</artifactId>
3.6 <groupId>org.apidesign</groupId>
3.7 - <version>0.5-SNAPSHOT</version>
3.8 + <version>0.8-SNAPSHOT</version>
3.9 </parent>
3.10 <groupId>org.apidesign.bck2brwsr</groupId>
3.11 <artifactId>benchmarks</artifactId>
3.12 - <version>0.5-SNAPSHOT</version>
3.13 + <version>0.8-SNAPSHOT</version>
3.14 <packaging>pom</packaging>
3.15 <name>Performance benchmarks</name>
3.16 <modules>
4.1 --- a/dew/pom.xml Tue Apr 02 15:40:51 2013 +0200
4.2 +++ b/dew/pom.xml Thu May 02 09:18:22 2013 +0200
4.3 @@ -4,11 +4,11 @@
4.4 <parent>
4.5 <groupId>org.apidesign</groupId>
4.6 <artifactId>bck2brwsr</artifactId>
4.7 - <version>0.5-SNAPSHOT</version>
4.8 + <version>0.8-SNAPSHOT</version>
4.9 </parent>
4.10 <groupId>org.apidesign.bck2brwsr</groupId>
4.11 <artifactId>dew</artifactId>
4.12 - <version>0.5-SNAPSHOT</version>
4.13 + <version>0.8-SNAPSHOT</version>
4.14 <name>Development Environment for Web</name>
4.15 <url>http://maven.apache.org</url>
4.16 <build>
5.1 --- a/ide/editor/pom.xml Tue Apr 02 15:40:51 2013 +0200
5.2 +++ b/ide/editor/pom.xml Thu May 02 09:18:22 2013 +0200
5.3 @@ -4,19 +4,18 @@
5.4 <parent>
5.5 <artifactId>ide</artifactId>
5.6 <groupId>org.apidesign.bck2brwsr</groupId>
5.7 - <version>0.5-SNAPSHOT</version>
5.8 + <version>0.8-SNAPSHOT</version>
5.9 </parent>
5.10
5.11 - <groupId>org.apidesign.bck2brwsr.ide.editor</groupId>
5.12 + <groupId>org.apidesign.bck2brwsr.ide</groupId>
5.13 <artifactId>editor</artifactId>
5.14 - <version>0.5-SNAPSHOT</version>
5.15 + <version>0.8-SNAPSHOT</version>
5.16 <packaging>nbm</packaging>
5.17
5.18 <name>Editor Support for Bck2Brwsr</name>
5.19
5.20 <properties>
5.21 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
5.22 - <netbeans.version>RELEASE73</netbeans.version>
5.23 <endorsed.dir>${project.build.directory}/endorsed</endorsed.dir>
5.24 </properties>
5.25
5.26 @@ -40,71 +39,59 @@
5.27 <dependency>
5.28 <groupId>org.netbeans.api</groupId>
5.29 <artifactId>org-netbeans-api-annotations-common</artifactId>
5.30 - <version>${netbeans.version}</version>
5.31 </dependency>
5.32 <dependency>
5.33 <groupId>org.netbeans.api</groupId>
5.34 <artifactId>org-netbeans-modules-java-source</artifactId>
5.35 - <version>${netbeans.version}</version>
5.36 </dependency>
5.37 <dependency>
5.38 <groupId>org.netbeans.api</groupId>
5.39 <artifactId>org-netbeans-libs-javacapi</artifactId>
5.40 - <version>${netbeans.version}</version>
5.41 </dependency>
5.42 <dependency>
5.43 <groupId>org.netbeans.api</groupId>
5.44 <artifactId>org-netbeans-spi-java-hints</artifactId>
5.45 - <version>${netbeans.version}</version>
5.46 </dependency>
5.47 <dependency>
5.48 <groupId>org.netbeans.api</groupId>
5.49 <artifactId>org-netbeans-modules-parsing-api</artifactId>
5.50 - <version>${netbeans.version}</version>
5.51 </dependency>
5.52 <dependency>
5.53 <groupId>org.netbeans.api</groupId>
5.54 <artifactId>org-netbeans-spi-editor-hints</artifactId>
5.55 - <version>${netbeans.version}</version>
5.56 </dependency>
5.57 <dependency>
5.58 <groupId>org.netbeans.api</groupId>
5.59 <artifactId>org-openide-util</artifactId>
5.60 - <version>${netbeans.version}</version>
5.61 </dependency>
5.62 <dependency>
5.63 <groupId>org.netbeans.api</groupId>
5.64 <artifactId>org-netbeans-modules-java-lexer</artifactId>
5.65 - <version>${netbeans.version}</version>
5.66 </dependency>
5.67 <dependency>
5.68 <groupId>org.netbeans.api</groupId>
5.69 <artifactId>org-netbeans-modules-lexer</artifactId>
5.70 - <version>${netbeans.version}</version>
5.71 </dependency>
5.72 <dependency>
5.73 <groupId>org.apidesign.bck2brwsr</groupId>
5.74 <artifactId>core</artifactId>
5.75 - <version>0.5-SNAPSHOT</version>
5.76 + <version>0.8-SNAPSHOT</version>
5.77 <type>jar</type>
5.78 <scope>test</scope>
5.79 </dependency>
5.80 <dependency>
5.81 <groupId>org.netbeans.api</groupId>
5.82 <artifactId>org-netbeans-modules-java-hints-test</artifactId>
5.83 - <version>${netbeans.version}</version>
5.84 <scope>test</scope>
5.85 </dependency>
5.86 <dependency>
5.87 <groupId>org.netbeans.api</groupId>
5.88 <artifactId>org-netbeans-libs-junit4</artifactId>
5.89 - <version>${netbeans.version}</version>
5.90 <scope>test</scope>
5.91 </dependency>
5.92 <dependency>
5.93 <groupId>org.netbeans.modules</groupId>
5.94 <artifactId>org-netbeans-lib-nbjavac</artifactId>
5.95 - <version>${netbeans.version}</version>
5.96 <scope>test</scope>
5.97 </dependency>
5.98 <dependency>
6.1 --- a/ide/pom.xml Tue Apr 02 15:40:51 2013 +0200
6.2 +++ b/ide/pom.xml Thu May 02 09:18:22 2013 +0200
6.3 @@ -4,14 +4,26 @@
6.4 <parent>
6.5 <artifactId>bck2brwsr</artifactId>
6.6 <groupId>org.apidesign</groupId>
6.7 - <version>0.5-SNAPSHOT</version>
6.8 + <version>0.8-SNAPSHOT</version>
6.9 </parent>
6.10 <groupId>org.apidesign.bck2brwsr</groupId>
6.11 <artifactId>ide</artifactId>
6.12 - <version>0.5-SNAPSHOT</version>
6.13 + <version>0.8-SNAPSHOT</version>
6.14 <packaging>pom</packaging>
6.15 <name>IDE Support</name>
6.16 <modules>
6.17 <module>editor</module>
6.18 </modules>
6.19 + <build>
6.20 + <plugins>
6.21 + <plugin>
6.22 + <groupId>org.apache.maven.plugins</groupId>
6.23 + <artifactId>maven-deploy-plugin</artifactId>
6.24 + <version>2.7</version>
6.25 + <configuration>
6.26 + <skip>true</skip>
6.27 + </configuration>
6.28 + </plugin>
6.29 + </plugins>
6.30 + </build>
6.31 </project>
7.1 --- a/javaquery/api/pom.xml Tue Apr 02 15:40:51 2013 +0200
7.2 +++ b/javaquery/api/pom.xml Thu May 02 09:18:22 2013 +0200
7.3 @@ -4,11 +4,11 @@
7.4 <parent>
7.5 <groupId>org.apidesign.bck2brwsr</groupId>
7.6 <artifactId>javaquery</artifactId>
7.7 - <version>0.5-SNAPSHOT</version>
7.8 + <version>0.8-SNAPSHOT</version>
7.9 </parent>
7.10 <groupId>org.apidesign.bck2brwsr</groupId>
7.11 <artifactId>javaquery.api</artifactId>
7.12 - <version>0.5-SNAPSHOT</version>
7.13 + <version>0.8-SNAPSHOT</version>
7.14 <name>JavaQuery API</name>
7.15 <url>http://maven.apache.org</url>
7.16 <build>
7.17 @@ -18,8 +18,8 @@
7.18 <artifactId>maven-compiler-plugin</artifactId>
7.19 <version>2.3.2</version>
7.20 <configuration>
7.21 - <source>1.6</source>
7.22 - <target>1.6</target>
7.23 + <source>1.7</source>
7.24 + <target>1.7</target>
7.25 </configuration>
7.26 </plugin>
7.27 <plugin>
7.28 @@ -74,6 +74,12 @@
7.29 <scope>test</scope>
7.30 </dependency>
7.31 <dependency>
7.32 + <groupId>${project.groupId}</groupId>
7.33 + <artifactId>launcher.http</artifactId>
7.34 + <version>${project.version}</version>
7.35 + <scope>test</scope>
7.36 + </dependency>
7.37 + <dependency>
7.38 <groupId>org.netbeans.modules</groupId>
7.39 <artifactId>org-netbeans-modules-html-parser</artifactId>
7.40 </dependency>
8.1 --- a/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/Attributes.java Tue Apr 02 15:40:51 2013 +0200
8.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
8.3 @@ -1,57 +0,0 @@
8.4 -/**
8.5 - * Back 2 Browser Bytecode Translator
8.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
8.7 - *
8.8 - * This program is free software: you can redistribute it and/or modify
8.9 - * it under the terms of the GNU General Public License as published by
8.10 - * the Free Software Foundation, version 2 of the License.
8.11 - *
8.12 - * This program is distributed in the hope that it will be useful,
8.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
8.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8.15 - * GNU General Public License for more details.
8.16 - *
8.17 - * You should have received a copy of the GNU General Public License
8.18 - * along with this program. Look for COPYING file in the top folder.
8.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
8.20 - */
8.21 -package org.apidesign.bck2brwsr.htmlpage;
8.22 -
8.23 -import java.util.HashMap;
8.24 -import java.util.Map;
8.25 -
8.26 -/**
8.27 - * Temporary storing the type of attributes here. This should be implemented in HTML 5 model
8.28 - *
8.29 - * @author Jan Horvath <jhorvath@netbeans.org>
8.30 - */
8.31 -public class Attributes {
8.32 -
8.33 - static final Map<String, String> TYPES = new HashMap<String, String>() {
8.34 - {
8.35 - // HTML Global Attributes
8.36 - // id attribute is already defined in Element, don't add it again
8.37 - put("accesskey", "String");
8.38 - put("class", "String");
8.39 - put("contenteditable", "Boolean");
8.40 - put("contextmenu", "String");
8.41 - put("dir", "String");
8.42 - put("draggable", "Boolean");
8.43 - put("dropzone", "String");
8.44 - put("hidden", "Boolean");
8.45 - put("lang", "String");
8.46 - put("spellcheck", "Boolean");
8.47 - put("style", "String");
8.48 - put("tabindex", "String");
8.49 - put("title", "String");
8.50 - put("translate", "Boolean");
8.51 - put("width", "Integer");
8.52 - put("height", "Integer");
8.53 -
8.54 - put("value", "String");
8.55 - put("disabled", "Boolean");
8.56 -
8.57 -// put("text", "String"); 'text' field is used to set innerHTML of element
8.58 - }
8.59 - };
8.60 -}
9.1 --- a/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/ConvertTypes.java Tue Apr 02 15:40:51 2013 +0200
9.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/ConvertTypes.java Thu May 02 09:18:22 2013 +0200
9.3 @@ -41,11 +41,115 @@
9.4 Object ret = getProperty(object, property);
9.5 return ret instanceof Number ? ((Number)ret).intValue() : Integer.MIN_VALUE;
9.6 }
9.7 +
9.8 + public static <T> T toModel(Class<T> modelClass, Object object, String property) {
9.9 + Object ret = getProperty(object, property);
9.10 + if (ret == null || modelClass.isInstance(ret)) {
9.11 + return modelClass.cast(ret);
9.12 + }
9.13 + throw new IllegalStateException("Value " + ret + " is not of type " + modelClass);
9.14 + }
9.15 +
9.16 + public static String toJSON(Object value) {
9.17 + if (value == null) {
9.18 + return "null";
9.19 + }
9.20 + if (value instanceof Enum) {
9.21 + value = value.toString();
9.22 + }
9.23 + if (value instanceof String) {
9.24 + return '"' +
9.25 + ((String)value).
9.26 + replace("\"", "\\\"").
9.27 + replace("\n", "\\n").
9.28 + replace("\r", "\\r").
9.29 + replace("\t", "\\t")
9.30 + + '"';
9.31 + }
9.32 + return value.toString();
9.33 + }
9.34
9.35 @JavaScriptBody(args = { "object", "property" },
9.36 - body = "var p = object[property]; return p ? p : null;"
9.37 + body = "if (property === null) return object;\n"
9.38 + + "var p = object[property]; return p ? p : null;"
9.39 )
9.40 private static Object getProperty(Object object, String property) {
9.41 return null;
9.42 }
9.43 +
9.44 + public static String createJSONP(Object[] jsonResult, Runnable whenDone) {
9.45 + int h = whenDone.hashCode();
9.46 + String name;
9.47 + for (;;) {
9.48 + name = "jsonp" + Integer.toHexString(h);
9.49 + if (defineIfUnused(name, jsonResult, whenDone)) {
9.50 + return name;
9.51 + }
9.52 + h++;
9.53 + }
9.54 + }
9.55 +
9.56 + @JavaScriptBody(args = { "name", "arr", "run" }, body =
9.57 + "if (window[name]) return false;\n "
9.58 + + "window[name] = function(data) {\n "
9.59 + + " delete window[name];\n"
9.60 + + " var el = window.document.getElementById(name);\n"
9.61 + + " el.parentNode.removeChild(el);\n"
9.62 + + " arr[0] = data;\n"
9.63 + + " run.run__V();\n"
9.64 + + "};\n"
9.65 + + "return true;\n"
9.66 + )
9.67 + private static boolean defineIfUnused(String name, Object[] arr, Runnable run) {
9.68 + return true;
9.69 + }
9.70 +
9.71 + @JavaScriptBody(args = { "url", "arr", "callback" }, body = ""
9.72 + + "var request = new XMLHttpRequest();\n"
9.73 + + "request.open('GET', url, true);\n"
9.74 + + "request.setRequestHeader('Content-Type', 'application/json; charset=utf-8');\n"
9.75 + + "request.onreadystatechange = function() {\n"
9.76 + + " if (this.readyState!==4) return;\n"
9.77 + + " try {\n"
9.78 + + " arr[0] = eval('(' + this.response + ')');\n"
9.79 + + " } catch (error) {;\n"
9.80 + + " throw 'Cannot parse' + error + ':' + this.response;\n"
9.81 + + " };\n"
9.82 + + " callback.run__V();\n"
9.83 + + "};"
9.84 + + "request.send();"
9.85 + )
9.86 + private static void loadJSON(
9.87 + String url, Object[] jsonResult, Runnable whenDone
9.88 + ) {
9.89 + }
9.90 +
9.91 + public static void loadJSON(
9.92 + String url, Object[] jsonResult, Runnable whenDone, String jsonp
9.93 + ) {
9.94 + if (jsonp == null) {
9.95 + loadJSON(url, jsonResult, whenDone);
9.96 + } else {
9.97 + loadJSONP(url, jsonp);
9.98 + }
9.99 + }
9.100 +
9.101 + @JavaScriptBody(args = { "url", "jsonp" }, body =
9.102 + "var scrpt = window.document.createElement('script');\n "
9.103 + + "scrpt.setAttribute('src', url);\n "
9.104 + + "scrpt.setAttribute('id', jsonp);\n "
9.105 + + "scrpt.setAttribute('type', 'text/javascript');\n "
9.106 + + "var body = document.getElementsByTagName('body')[0];\n "
9.107 + + "body.appendChild(scrpt);\n"
9.108 + )
9.109 + private static void loadJSONP(String url, String jsonp) {
9.110 +
9.111 + }
9.112 +
9.113 + public static void extractJSON(Object jsonObject, String[] props, Object[] values) {
9.114 + for (int i = 0; i < props.length; i++) {
9.115 + values[i] = getProperty(jsonObject, props[i]);
9.116 + }
9.117 + }
9.118 +
9.119 }
10.1 --- a/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/ElementGenerator.java Tue Apr 02 15:40:51 2013 +0200
10.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
10.3 @@ -1,175 +0,0 @@
10.4 -/**
10.5 - * Back 2 Browser Bytecode Translator
10.6 - * Copyright (C) 2012 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.
10.16 - *
10.17 - * You should have received a copy of the GNU General Public License
10.18 - * along with this program. Look for COPYING file in the top folder.
10.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
10.20 - */
10.21 -package org.apidesign.bck2brwsr.htmlpage;
10.22 -
10.23 -import java.io.IOException;
10.24 -import java.io.OutputStreamWriter;
10.25 -import java.io.Writer;
10.26 -import java.util.Arrays;
10.27 -import java.util.Collections;
10.28 -import java.util.HashMap;
10.29 -import java.util.Map;
10.30 -import java.util.Map.Entry;
10.31 -import java.util.ServiceLoader;
10.32 -import javax.annotation.processing.ProcessingEnvironment;
10.33 -import javax.lang.model.element.Element;
10.34 -import javax.tools.Diagnostic;
10.35 -import javax.tools.FileObject;
10.36 -import org.netbeans.modules.html.editor.lib.api.HtmlVersion;
10.37 -import org.netbeans.modules.html.editor.lib.api.model.HtmlModel;
10.38 -import org.netbeans.modules.html.editor.lib.api.model.HtmlModelProvider;
10.39 -import org.netbeans.modules.html.editor.lib.api.model.HtmlTag;
10.40 -import org.netbeans.modules.html.editor.lib.api.model.HtmlTagAttribute;
10.41 -
10.42 -/**
10.43 - *
10.44 - * @author Jan Horvath <jhorvath@netbeans.org>
10.45 - */
10.46 -public class ElementGenerator {
10.47 -
10.48 - static final Map<String, String> NAMING_EXCEPTIONS = new HashMap<String, String>() {
10.49 - {
10.50 - put("img", "Image");
10.51 - put("class", "Clazz");
10.52 - }
10.53 - };
10.54 -
10.55 - static final String javaKeywords[] = {
10.56 - "abstract", "assert", "boolean", "break", "byte", "case",
10.57 - "catch", "char", "class", "const", "continue", "default",
10.58 - "do", "double", "else", "extends", "false", "final", "finally",
10.59 - "float", "for", "goto", "if", "implements", "import",
10.60 - "instanceof", "int", "interface", "long", "native", "new",
10.61 - "null", "package", "private", "protected", "public",
10.62 - "return", "short", "static", "strictfp", "super",
10.63 - "switch", "synchronized", "this", "throw", "throws",
10.64 - "transient", "true", "try", "void", "volatile", "while"
10.65 - };
10.66 -
10.67 - private static Map<String, String> elements = new HashMap<String, String>();
10.68 - private final ProcessingEnvironment processingEnv;
10.69 - private HtmlModel model = null;
10.70 -
10.71 - ElementGenerator(ProcessingEnvironment processingEnv) {
10.72 - this.processingEnv = processingEnv;
10.73 - }
10.74 -
10.75 - String getType(String pkg, String tag, Element e) {
10.76 - String className = elements.get(tag);
10.77 - if (className == null) {
10.78 - className = createClass(pkg, tag, e);
10.79 - elements.put(tag, className);
10.80 - }
10.81 - return className;
10.82 - }
10.83 -
10.84 - private String createClass(String pkg, String tag, Element e) {
10.85 - String className = className(tag);
10.86 - Writer w;
10.87 - try {
10.88 - FileObject java = processingEnv.getFiler().createSourceFile(pkg + '.' + className, e);
10.89 - w = new OutputStreamWriter(java.openOutputStream());
10.90 - try {
10.91 - w.append("package " + pkg + ";\n\n");
10.92 - w.append("import org.apidesign.bck2brwsr.htmlpage.api.*;\n");
10.93 - PredefinedFields.appendImports(w, tag);
10.94 - w.append("\n");
10.95 -
10.96 - w.append("class ").append(className).append(" extends Element {\n\n");
10.97 - w.append(" public ").append(className).append("(String id) {\n");
10.98 - w.append(" super(id);\n");
10.99 - w.append(" }\n\n");
10.100 - for (Entry<String, String> entry : getAttributes(tag).entrySet()) {
10.101 - String attrName = entry.getKey();
10.102 - String attrType = entry.getValue();
10.103 - // getter
10.104 - w.append(" public ").append(attrType).append(" ")
10.105 - .append("get").append(className(attrName)).append("() {\n");
10.106 - w.append(" return (").append(attrType).append(")getAttribute(\"")
10.107 - .append(attrName).append("\");\n");
10.108 - w.append(" }\n\n");
10.109 - // setter
10.110 - w.append(" public void ")
10.111 - .append("set").append(className(attrName)).append("(")
10.112 - .append(attrType).append(" ").append(attributeName(attrName)).append(") {\n");
10.113 - w.append(" setAttribute(\"").append(attrName).append("\", ").append(attributeName(attrName)).append(");\n");
10.114 - w.append(" }\n\n");
10.115 - }
10.116 - PredefinedFields.appendFields(w, tag);
10.117 - w.append("}\n");
10.118 - } finally {
10.119 - w.close();
10.120 - }
10.121 - } catch (IOException ex) {
10.122 - processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Can't create " + className + ".java", e);
10.123 - return null;
10.124 - }
10.125 - return className;
10.126 - }
10.127 -
10.128 - Map<String, String> getAttributes(String tagName) {
10.129 - Map<String, String> result = new HashMap<String, String>();
10.130 -
10.131 - if (model == null) {
10.132 - // HtmlModelProvider modelProvider = Lookup.getDefault().lookup(HtmlModelProvider.class);
10.133 - ServiceLoader<HtmlModelProvider> hmpLoader =
10.134 - ServiceLoader.load(HtmlModelProvider.class, this.getClass().getClassLoader());
10.135 - for (HtmlModelProvider htmlModelProvider : hmpLoader) {
10.136 - model = htmlModelProvider.getModel(HtmlVersion.HTML5);
10.137 - if (model != null) {
10.138 - break;
10.139 - }
10.140 - }
10.141 - }
10.142 -
10.143 - if (model == null) {
10.144 - processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
10.145 - "HTML 5 model provider was not found on classpath");
10.146 - return Collections.emptyMap();
10.147 - }
10.148 - HtmlTag tag = model.getTag(tagName);
10.149 - for (HtmlTagAttribute attr : tag.getAttributes()) {
10.150 - String name = attr.getName();
10.151 - String type = Attributes.TYPES.get(name);
10.152 - if (type != null) {
10.153 - result.put(name, type);
10.154 - }
10.155 - }
10.156 -
10.157 - return result;
10.158 - }
10.159 -
10.160 - private String className(String s) {
10.161 - if (s.length() == 0) {
10.162 - return s;
10.163 - }
10.164 - String name = NAMING_EXCEPTIONS.get(s.toLowerCase());
10.165 - if (name == null) {
10.166 - name = s.substring(0, 1).toUpperCase() + s.substring(1).toLowerCase();
10.167 - }
10.168 - return name;
10.169 - }
10.170 -
10.171 - private String attributeName(String s) {
10.172 - if (Arrays.binarySearch(javaKeywords, s) >= 0) {
10.173 - return String.format("%sAttr", s);
10.174 - }
10.175 - return s;
10.176 - }
10.177 -
10.178 -}
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
11.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/KOList.java Thu May 02 09:18:22 2013 +0200
11.3 @@ -0,0 +1,167 @@
11.4 +/**
11.5 + * Back 2 Browser Bytecode Translator
11.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
11.7 + *
11.8 + * This program is free software: you can redistribute it and/or modify
11.9 + * it under the terms of the GNU General Public License as published by
11.10 + * the Free Software Foundation, version 2 of the License.
11.11 + *
11.12 + * This program is distributed in the hope that it will be useful,
11.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
11.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11.15 + * GNU General Public License for more details.
11.16 + *
11.17 + * You should have received a copy of the GNU General Public License
11.18 + * along with this program. Look for COPYING file in the top folder.
11.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
11.20 + */
11.21 +package org.apidesign.bck2brwsr.htmlpage;
11.22 +
11.23 +import java.util.ArrayList;
11.24 +import java.util.Collection;
11.25 +import java.util.Iterator;
11.26 +import org.apidesign.bck2brwsr.core.JavaScriptOnly;
11.27 +
11.28 +/**
11.29 + *
11.30 + * @author Jaroslav Tulach <jtulach@netbeans.org>
11.31 + */
11.32 +public final class KOList<T> extends ArrayList<T> {
11.33 + private final String name;
11.34 + private final String[] deps;
11.35 + private Knockout model;
11.36 + private Runnable onchange;
11.37 +
11.38 + public KOList(String name, String... deps) {
11.39 + this.name = name;
11.40 + this.deps = deps;
11.41 + }
11.42 +
11.43 + public void assign(Knockout model) {
11.44 + if (this.model != model) {
11.45 + this.model = model;
11.46 + notifyChange();
11.47 + }
11.48 + }
11.49 +
11.50 + public KOList<T> onChange(Runnable r) {
11.51 + if (this.onchange != null) {
11.52 + throw new IllegalStateException();
11.53 + }
11.54 + this.onchange = r;
11.55 + return this;
11.56 + }
11.57 +
11.58 + @Override
11.59 + public boolean add(T e) {
11.60 + boolean ret = super.add(e);
11.61 + notifyChange();
11.62 + return ret;
11.63 + }
11.64 +
11.65 + @Override
11.66 + public boolean addAll(Collection<? extends T> c) {
11.67 + boolean ret = super.addAll(c);
11.68 + notifyChange();
11.69 + return ret;
11.70 + }
11.71 +
11.72 + @Override
11.73 + public boolean addAll(int index, Collection<? extends T> c) {
11.74 + boolean ret = super.addAll(index, c);
11.75 + notifyChange();
11.76 + return ret;
11.77 + }
11.78 +
11.79 + @Override
11.80 + public boolean remove(Object o) {
11.81 + boolean ret = super.remove(o);
11.82 + notifyChange();
11.83 + return ret;
11.84 + }
11.85 +
11.86 + @Override
11.87 + public void clear() {
11.88 + super.clear();
11.89 + notifyChange();
11.90 + }
11.91 +
11.92 + @Override
11.93 + public boolean removeAll(Collection<?> c) {
11.94 + boolean ret = super.removeAll(c);
11.95 + notifyChange();
11.96 + return ret;
11.97 + }
11.98 +
11.99 + @Override
11.100 + public boolean retainAll(Collection<?> c) {
11.101 + boolean ret = super.retainAll(c);
11.102 + notifyChange();
11.103 + return ret;
11.104 + }
11.105 +
11.106 + @Override
11.107 + public T set(int index, T element) {
11.108 + T ret = super.set(index, element);
11.109 + notifyChange();
11.110 + return ret;
11.111 + }
11.112 +
11.113 + @Override
11.114 + public void add(int index, T element) {
11.115 + super.add(index, element);
11.116 + notifyChange();
11.117 + }
11.118 +
11.119 + @Override
11.120 + public T remove(int index) {
11.121 + T ret = super.remove(index);
11.122 + notifyChange();
11.123 + return ret;
11.124 + }
11.125 +
11.126 + @Override
11.127 + public String toString() {
11.128 + Iterator<T> it = iterator();
11.129 + if (!it.hasNext()) {
11.130 + return "[]";
11.131 + }
11.132 + String sep = "";
11.133 + StringBuilder sb = new StringBuilder();
11.134 + sb.append('[');
11.135 + while (it.hasNext()) {
11.136 + T t = it.next();
11.137 + sb.append(sep);
11.138 + sb.append(ConvertTypes.toJSON(t));
11.139 + sep = ",";
11.140 + }
11.141 + sb.append(']');
11.142 + return sb.toString();
11.143 + }
11.144 +
11.145 +
11.146 + @JavaScriptOnly(name = "koArray", value = "function() { return this.toArray___3Ljava_lang_Object_2(); }")
11.147 + private static native int koArray();
11.148 +
11.149 + private void notifyChange() {
11.150 + Knockout m = model;
11.151 + if (m != null) {
11.152 + m.valueHasMutated(name);
11.153 + for (String dependant : deps) {
11.154 + m.valueHasMutated(dependant);
11.155 + }
11.156 + }
11.157 + Runnable r = onchange;
11.158 + if (r != null) {
11.159 + r.run();
11.160 + }
11.161 + }
11.162 +
11.163 + @Override
11.164 + public KOList clone() {
11.165 + KOList ko = (KOList)super.clone();
11.166 + ko.model = null;
11.167 + return ko;
11.168 + }
11.169 +
11.170 +}
12.1 --- a/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/Knockout.java Tue Apr 02 15:40:51 2013 +0200
12.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/Knockout.java Thu May 02 09:18:22 2013 +0200
12.3 @@ -18,6 +18,7 @@
12.4 package org.apidesign.bck2brwsr.htmlpage;
12.5
12.6 import java.lang.reflect.Method;
12.7 +import java.util.List;
12.8 import org.apidesign.bck2brwsr.core.ExtraJavaScript;
12.9 import org.apidesign.bck2brwsr.core.JavaScriptBody;
12.10
12.11 @@ -29,38 +30,40 @@
12.12 public class Knockout {
12.13 /** used by tests */
12.14 static Knockout next;
12.15 -
12.16 - Knockout() {
12.17 + private final Object model;
12.18 +
12.19 + Knockout(Object model) {
12.20 + this.model = model == null ? this : model;
12.21 }
12.22
12.23 public static <M> Knockout applyBindings(
12.24 - Class<M> modelClass, M model, String[] propsGettersAndSetters
12.25 + Object model, String[] propsGettersAndSetters,
12.26 + String[] methodsAndSignatures
12.27 + ) {
12.28 + applyImpl(propsGettersAndSetters, model.getClass(), model, model, methodsAndSignatures);
12.29 + return new Knockout(model);
12.30 + }
12.31 + public static <M> Knockout applyBindings(
12.32 + Class<M> modelClass, M model, String[] propsGettersAndSetters,
12.33 + String[] methodsAndSignatures
12.34 ) {
12.35 Knockout bindings = next;
12.36 next = null;
12.37 if (bindings == null) {
12.38 - bindings = new Knockout();
12.39 + bindings = new Knockout(null);
12.40 }
12.41 - for (int i = 0; i < propsGettersAndSetters.length; i += 4) {
12.42 - try {
12.43 - Method getter = modelClass.getMethod(propsGettersAndSetters[i + 3]);
12.44 - bind(bindings, model, propsGettersAndSetters[i],
12.45 - propsGettersAndSetters[i + 1],
12.46 - propsGettersAndSetters[i + 2],
12.47 - getter.getReturnType().isPrimitive()
12.48 - );
12.49 - } catch (NoSuchMethodException ex) {
12.50 - throw new IllegalStateException(ex.getMessage());
12.51 - }
12.52 - }
12.53 + applyImpl(propsGettersAndSetters, modelClass, bindings, model, methodsAndSignatures);
12.54 applyBindings(bindings);
12.55 return bindings;
12.56 }
12.57
12.58 - @JavaScriptBody(args = { "prop" }, body =
12.59 - "this[prop].valueHasMutated();"
12.60 + public void valueHasMutated(String prop) {
12.61 + valueHasMutated(model, prop);
12.62 + }
12.63 + @JavaScriptBody(args = { "self", "prop" }, body =
12.64 + "self[prop].valueHasMutated();"
12.65 )
12.66 - public void valueHasMutated(String prop) {
12.67 + public void valueHasMutated(Object self, String prop) {
12.68 }
12.69
12.70
12.71 @@ -68,26 +71,60 @@
12.72 public static void triggerEvent(String id, String ev) {
12.73 }
12.74
12.75 - @JavaScriptBody(args = { "bindings", "model", "prop", "getter", "setter", "primitive" }, body =
12.76 + @JavaScriptBody(args = { "bindings", "model", "prop", "getter", "setter", "primitive", "array" }, body =
12.77 "var bnd = {\n"
12.78 - + " read: function() {\n"
12.79 + + " 'read': function() {\n"
12.80 + " var v = model[getter]();\n"
12.81 + + " if (array) v = v.koArray();\n"
12.82 + " return v;\n"
12.83 + " },\n"
12.84 - + " owner: bindings\n"
12.85 + + " 'owner': bindings\n"
12.86 + "};\n"
12.87 + "if (setter != null) {\n"
12.88 - + " bnd.write = function(val) {\n"
12.89 + + " bnd['write'] = function(val) {\n"
12.90 + " model[setter](primitive ? new Number(val) : val);\n"
12.91 + " };\n"
12.92 + "}\n"
12.93 - + "bindings[prop] = ko.computed(bnd);"
12.94 + + "bindings[prop] = ko['computed'](bnd);"
12.95 )
12.96 private static void bind(
12.97 - Object bindings, Object model, String prop, String getter, String setter, boolean primitive
12.98 + Object bindings, Object model, String prop, String getter, String setter, boolean primitive, boolean array
12.99 + ) {
12.100 + }
12.101 +
12.102 + @JavaScriptBody(args = { "bindings", "model", "prop", "sig" }, body =
12.103 + "bindings[prop] = function(data, ev) { model[sig](data, ev); };"
12.104 + )
12.105 + private static void expose(
12.106 + Object bindings, Object model, String prop, String sig
12.107 ) {
12.108 }
12.109
12.110 @JavaScriptBody(args = { "bindings" }, body = "ko.applyBindings(bindings);")
12.111 private static void applyBindings(Object bindings) {}
12.112 +
12.113 + private static void applyImpl(
12.114 + String[] propsGettersAndSetters,
12.115 + Class<?> modelClass,
12.116 + Object bindings,
12.117 + Object model,
12.118 + String[] methodsAndSignatures
12.119 + ) throws IllegalStateException, SecurityException {
12.120 + for (int i = 0; i < propsGettersAndSetters.length; i += 4) {
12.121 + try {
12.122 + Method getter = modelClass.getMethod(propsGettersAndSetters[i + 3]);
12.123 + bind(bindings, model, propsGettersAndSetters[i],
12.124 + propsGettersAndSetters[i + 1],
12.125 + propsGettersAndSetters[i + 2],
12.126 + getter.getReturnType().isPrimitive(),
12.127 + List.class.isAssignableFrom(getter.getReturnType()));
12.128 + } catch (NoSuchMethodException ex) {
12.129 + throw new IllegalStateException(ex.getMessage());
12.130 + }
12.131 + }
12.132 + for (int i = 0; i < methodsAndSignatures.length; i += 2) {
12.133 + expose(
12.134 + bindings, model, methodsAndSignatures[i], methodsAndSignatures[i + 1]);
12.135 + }
12.136 + }
12.137 }
13.1 --- a/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/PageProcessor.java Tue Apr 02 15:40:51 2013 +0200
13.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/PageProcessor.java Thu May 02 09:18:22 2013 +0200
13.3 @@ -20,23 +20,30 @@
13.4 import java.io.IOException;
13.5 import java.io.InputStream;
13.6 import java.io.OutputStreamWriter;
13.7 +import java.io.StringWriter;
13.8 import java.io.Writer;
13.9 +import java.lang.annotation.AnnotationTypeMismatchException;
13.10 +import java.lang.annotation.IncompleteAnnotationException;
13.11 +import java.lang.reflect.Method;
13.12 import java.util.ArrayList;
13.13 import java.util.Collection;
13.14 import java.util.Collections;
13.15 import java.util.HashMap;
13.16 +import java.util.HashSet;
13.17 import java.util.LinkedHashSet;
13.18 import java.util.List;
13.19 -import java.util.Locale;
13.20 import java.util.Map;
13.21 import java.util.Set;
13.22 +import java.util.WeakHashMap;
13.23 import javax.annotation.processing.AbstractProcessor;
13.24 import javax.annotation.processing.Completion;
13.25 import javax.annotation.processing.Completions;
13.26 +import javax.annotation.processing.ProcessingEnvironment;
13.27 import javax.annotation.processing.Processor;
13.28 import javax.annotation.processing.RoundEnvironment;
13.29 import javax.annotation.processing.SupportedAnnotationTypes;
13.30 import javax.lang.model.element.AnnotationMirror;
13.31 +import javax.lang.model.element.AnnotationValue;
13.32 import javax.lang.model.element.Element;
13.33 import javax.lang.model.element.ElementKind;
13.34 import javax.lang.model.element.ExecutableElement;
13.35 @@ -44,14 +51,21 @@
13.36 import javax.lang.model.element.PackageElement;
13.37 import javax.lang.model.element.TypeElement;
13.38 import javax.lang.model.element.VariableElement;
13.39 +import javax.lang.model.type.ArrayType;
13.40 import javax.lang.model.type.MirroredTypeException;
13.41 import javax.lang.model.type.TypeKind;
13.42 import javax.lang.model.type.TypeMirror;
13.43 +import javax.lang.model.util.Elements;
13.44 +import javax.lang.model.util.Types;
13.45 import javax.tools.Diagnostic;
13.46 import javax.tools.FileObject;
13.47 import javax.tools.StandardLocation;
13.48 import org.apidesign.bck2brwsr.htmlpage.api.ComputedProperty;
13.49 +import org.apidesign.bck2brwsr.htmlpage.api.Model;
13.50 import org.apidesign.bck2brwsr.htmlpage.api.On;
13.51 +import org.apidesign.bck2brwsr.htmlpage.api.OnFunction;
13.52 +import org.apidesign.bck2brwsr.htmlpage.api.OnPropertyChange;
13.53 +import org.apidesign.bck2brwsr.htmlpage.api.OnReceive;
13.54 import org.apidesign.bck2brwsr.htmlpage.api.Page;
13.55 import org.apidesign.bck2brwsr.htmlpage.api.Property;
13.56 import org.openide.util.lookup.ServiceProvider;
13.57 @@ -63,90 +77,70 @@
13.58 */
13.59 @ServiceProvider(service=Processor.class)
13.60 @SupportedAnnotationTypes({
13.61 + "org.apidesign.bck2brwsr.htmlpage.api.Model",
13.62 "org.apidesign.bck2brwsr.htmlpage.api.Page",
13.63 + "org.apidesign.bck2brwsr.htmlpage.api.OnFunction",
13.64 + "org.apidesign.bck2brwsr.htmlpage.api.OnReceive",
13.65 + "org.apidesign.bck2brwsr.htmlpage.api.OnPropertyChange",
13.66 + "org.apidesign.bck2brwsr.htmlpage.api.ComputedProperty",
13.67 "org.apidesign.bck2brwsr.htmlpage.api.On"
13.68 })
13.69 public final class PageProcessor extends AbstractProcessor {
13.70 + private final Map<Element,String> models = new WeakHashMap<>();
13.71 + private final Map<Element,Prprt[]> verify = new WeakHashMap<>();
13.72 @Override
13.73 public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
13.74 - for (Element e : roundEnv.getElementsAnnotatedWith(Page.class)) {
13.75 - Page p = e.getAnnotation(Page.class);
13.76 - if (p == null) {
13.77 - continue;
13.78 - }
13.79 - PackageElement pe = (PackageElement)e.getEnclosingElement();
13.80 - String pkg = pe.getQualifiedName().toString();
13.81 -
13.82 - ProcessPage pp;
13.83 - ElementGenerator eGen = new ElementGenerator(processingEnv);
13.84 - try {
13.85 - InputStream is = openStream(pkg, p.xhtml());
13.86 - pp = ProcessPage.readPage(is);
13.87 - is.close();
13.88 - } catch (IOException iOException) {
13.89 - processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Can't read " + p.xhtml(), e);
13.90 - return false;
13.91 - }
13.92 - Writer w;
13.93 - String className = p.className();
13.94 - if (className.isEmpty()) {
13.95 - int indx = p.xhtml().indexOf('.');
13.96 - className = p.xhtml().substring(0, indx);
13.97 - }
13.98 - try {
13.99 - FileObject java = processingEnv.getFiler().createSourceFile(pkg + '.' + className, e);
13.100 - w = new OutputStreamWriter(java.openOutputStream());
13.101 - try {
13.102 - w.append("package " + pkg + ";\n");
13.103 - w.append("import org.apidesign.bck2brwsr.htmlpage.api.*;\n");
13.104 - w.append("final class ").append(className).append(" {\n");
13.105 - w.append(" private boolean locked;\n");
13.106 - if (!initializeOnClick(className, (TypeElement) e, w, pp)) {
13.107 - return false;
13.108 - }
13.109 - for (String id : pp.ids()) {
13.110 - String tag = pp.tagNameForId(id);
13.111 - String type = eGen.getType(pkg, tag, e);
13.112 - w.append(" ").append("public final ").
13.113 - append(type).append(' ').append(cnstnt(id)).append(" = new ").
13.114 - append(type).append("(\"").append(id).append("\");\n");
13.115 - }
13.116 - List<String> propsGetSet = new ArrayList<String>();
13.117 - Map<String,Collection<String>> propsDeps = new HashMap<String, Collection<String>>();
13.118 - generateComputedProperties(w, e.getEnclosedElements(), propsGetSet, propsDeps);
13.119 - generateProperties(w, p.properties(), propsGetSet, propsDeps);
13.120 - w.append(" private org.apidesign.bck2brwsr.htmlpage.Knockout ko;\n");
13.121 - if (!propsGetSet.isEmpty()) {
13.122 - w.write("public " + className + " applyBindings() {\n");
13.123 - w.write(" ko = org.apidesign.bck2brwsr.htmlpage.Knockout.applyBindings(");
13.124 - w.write(className + ".class, this, ");
13.125 - w.write("new String[] {\n");
13.126 - String sep = "";
13.127 - for (String n : propsGetSet) {
13.128 - w.write(sep);
13.129 - if (n == null) {
13.130 - w.write(" null");
13.131 - } else {
13.132 - w.write(" \"" + n + "\"");
13.133 - }
13.134 - sep = ",\n";
13.135 - }
13.136 - w.write("\n });\n return this;\n}\n");
13.137 -
13.138 - w.write("public void triggerEvent(Element e, OnEvent ev) {\n");
13.139 - w.write(" org.apidesign.bck2brwsr.htmlpage.Knockout.triggerEvent(e.getId(), ev.getElementPropertyName());\n");
13.140 - w.write("}\n");
13.141 - }
13.142 - w.append("}\n");
13.143 - } finally {
13.144 - w.close();
13.145 - }
13.146 - } catch (IOException ex) {
13.147 - processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Can't create " + className + ".java", e);
13.148 - return false;
13.149 + boolean ok = true;
13.150 + for (Element e : roundEnv.getElementsAnnotatedWith(Model.class)) {
13.151 + if (!processModel(e)) {
13.152 + ok = false;
13.153 }
13.154 }
13.155 - return true;
13.156 + for (Element e : roundEnv.getElementsAnnotatedWith(Page.class)) {
13.157 + if (!processPage(e)) {
13.158 + ok = false;
13.159 + }
13.160 + }
13.161 + if (roundEnv.processingOver()) {
13.162 + models.clear();
13.163 + for (Map.Entry<Element, Prprt[]> entry : verify.entrySet()) {
13.164 + TypeElement te = (TypeElement)entry.getKey();
13.165 + String fqn = processingEnv.getElementUtils().getBinaryName(te).toString();
13.166 + Element finalElem = processingEnv.getElementUtils().getTypeElement(fqn);
13.167 + if (finalElem == null) {
13.168 + continue;
13.169 + }
13.170 + Prprt[] props;
13.171 + Model m = finalElem.getAnnotation(Model.class);
13.172 + if (m != null) {
13.173 + props = Prprt.wrap(processingEnv, finalElem, m.properties());
13.174 + } else {
13.175 + Page p = finalElem.getAnnotation(Page.class);
13.176 + props = Prprt.wrap(processingEnv, finalElem, p.properties());
13.177 + }
13.178 + for (Prprt p : props) {
13.179 + boolean[] isModel = { false };
13.180 + boolean[] isEnum = { false };
13.181 + boolean[] isPrimitive = { false };
13.182 + String t = checkType(p, isModel, isEnum, isPrimitive);
13.183 + if (isEnum[0]) {
13.184 + continue;
13.185 + }
13.186 + if (isPrimitive[0]) {
13.187 + continue;
13.188 + }
13.189 + if (isModel[0]) {
13.190 + continue;
13.191 + }
13.192 + if ("java.lang.String".equals(t)) {
13.193 + continue;
13.194 + }
13.195 + error("The type " + t + " should be defined by @Model annotation", entry.getKey());
13.196 + }
13.197 + }
13.198 + verify.clear();
13.199 + }
13.200 + return ok;
13.201 }
13.202
13.203 private InputStream openStream(String pkg, String name) throws IOException {
13.204 @@ -159,13 +153,263 @@
13.205 }
13.206 }
13.207
13.208 + private void error(String msg, Element e) {
13.209 + processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, msg, e);
13.210 + }
13.211 +
13.212 + private boolean processModel(Element e) {
13.213 + boolean ok = true;
13.214 + Model m = e.getAnnotation(Model.class);
13.215 + if (m == null) {
13.216 + return true;
13.217 + }
13.218 + String pkg = findPkgName(e);
13.219 + Writer w;
13.220 + String className = m.className();
13.221 + models.put(e, className);
13.222 + try {
13.223 + StringWriter body = new StringWriter();
13.224 + List<String> propsGetSet = new ArrayList<>();
13.225 + List<String> functions = new ArrayList<>();
13.226 + Map<String, Collection<String>> propsDeps = new HashMap<>();
13.227 + Map<String, Collection<String>> functionDeps = new HashMap<>();
13.228 + Prprt[] props = createProps(e, m.properties());
13.229 +
13.230 + if (!generateComputedProperties(body, props, e.getEnclosedElements(), propsGetSet, propsDeps)) {
13.231 + ok = false;
13.232 + }
13.233 + if (!generateOnChange(e, propsDeps, props, className, functionDeps)) {
13.234 + ok = false;
13.235 + }
13.236 + if (!generateProperties(e, body, props, propsGetSet, propsDeps, functionDeps)) {
13.237 + ok = false;
13.238 + }
13.239 + if (!generateFunctions(e, body, className, e.getEnclosedElements(), functions)) {
13.240 + ok = false;
13.241 + }
13.242 + FileObject java = processingEnv.getFiler().createSourceFile(pkg + '.' + className, e);
13.243 + w = new OutputStreamWriter(java.openOutputStream());
13.244 + try {
13.245 + w.append("package " + pkg + ";\n");
13.246 + w.append("import org.apidesign.bck2brwsr.htmlpage.api.*;\n");
13.247 + w.append("import org.apidesign.bck2brwsr.htmlpage.KOList;\n");
13.248 + w.append("import org.apidesign.bck2brwsr.core.JavaScriptOnly;\n");
13.249 + w.append("final class ").append(className).append(" implements Cloneable {\n");
13.250 + w.append(" private boolean locked;\n");
13.251 + w.append(" private org.apidesign.bck2brwsr.htmlpage.Knockout ko;\n");
13.252 + w.append(body.toString());
13.253 + w.append(" private static Class<" + inPckName(e) + "> modelFor() { return null; }\n");
13.254 + w.append(" public ").append(className).append("() {\n");
13.255 + w.append(" intKnckt();\n");
13.256 + w.append(" };\n");
13.257 + w.append(" private void intKnckt() {\n");
13.258 + w.append(" ko = org.apidesign.bck2brwsr.htmlpage.Knockout.applyBindings(this, ");
13.259 + writeStringArray(propsGetSet, w);
13.260 + w.append(", ");
13.261 + writeStringArray(functions, w);
13.262 + w.append(" );\n");
13.263 + w.append(" };\n");
13.264 + w.append(" ").append(className).append("(Object json) {\n");
13.265 + int values = 0;
13.266 + for (int i = 0; i < propsGetSet.size(); i += 4) {
13.267 + Prprt p = findPrprt(props, propsGetSet.get(i));
13.268 + if (p == null) {
13.269 + continue;
13.270 + }
13.271 + values++;
13.272 + }
13.273 + w.append(" Object[] ret = new Object[" + values + "];\n");
13.274 + w.append(" org.apidesign.bck2brwsr.htmlpage.ConvertTypes.extractJSON(json, new String[] {\n");
13.275 + for (int i = 0; i < propsGetSet.size(); i += 4) {
13.276 + Prprt p = findPrprt(props, propsGetSet.get(i));
13.277 + if (p == null) {
13.278 + continue;
13.279 + }
13.280 + w.append(" \"").append(propsGetSet.get(i)).append("\",\n");
13.281 + }
13.282 + w.append(" }, ret);\n");
13.283 + for (int i = 0, cnt = 0, prop = 0; i < propsGetSet.size(); i += 4) {
13.284 + final String pn = propsGetSet.get(i);
13.285 + Prprt p = findPrprt(props, pn);
13.286 + if (p == null) {
13.287 + continue;
13.288 + }
13.289 + boolean[] isModel = { false };
13.290 + boolean[] isEnum = { false };
13.291 + boolean isPrimitive[] = { false };
13.292 + String type = checkType(props[prop++], isModel, isEnum, isPrimitive);
13.293 + if (p.array()) {
13.294 + w.append("if (ret[" + cnt + "] instanceof Object[]) {\n");
13.295 + w.append(" for (Object e : ((Object[])ret[" + cnt + "])) {\n");
13.296 + if (isModel[0]) {
13.297 + w.append(" this.prop_").append(pn).append(".add(new ");
13.298 + w.append(type).append("(e));\n");
13.299 + } else if (isEnum[0]) {
13.300 + w.append(" this.prop_").append(pn);
13.301 + w.append(".add(e == null ? null : ");
13.302 + w.append(type).append(".valueOf((String)e));\n");
13.303 + } else {
13.304 + if (isPrimitive(type)) {
13.305 + w.append(" this.prop_").append(pn).append(".add(((Number)e).");
13.306 + w.append(type).append("Value());\n");
13.307 + } else {
13.308 + w.append(" this.prop_").append(pn).append(".add((");
13.309 + w.append(type).append(")e);\n");
13.310 + }
13.311 + }
13.312 + w.append(" }\n");
13.313 + w.append("}\n");
13.314 + } else {
13.315 + if (isEnum[0]) {
13.316 + w.append(" this.prop_").append(pn);
13.317 + w.append(" = ret[" + cnt + "] == null ? null : ");
13.318 + w.append(type).append(".valueOf((String)ret[" + cnt + "]);\n");
13.319 + } else if (isPrimitive(type)) {
13.320 + w.append(" this.prop_").append(pn);
13.321 + w.append(" = ((Number)").append("ret[" + cnt + "]).");
13.322 + w.append(type).append("Value();\n");
13.323 + } else {
13.324 + w.append(" this.prop_").append(pn);
13.325 + w.append(" = (").append(type).append(')');
13.326 + w.append("ret[" + cnt + "];\n");
13.327 + }
13.328 + }
13.329 + cnt++;
13.330 + }
13.331 + w.append(" intKnckt();\n");
13.332 + w.append(" };\n");
13.333 + writeToString(props, w);
13.334 + writeClone(className, props, w);
13.335 + w.append("}\n");
13.336 + } finally {
13.337 + w.close();
13.338 + }
13.339 + } catch (IOException ex) {
13.340 + error("Can't create " + className + ".java", e);
13.341 + return false;
13.342 + }
13.343 + return ok;
13.344 + }
13.345 +
13.346 + private boolean processPage(Element e) {
13.347 + boolean ok = true;
13.348 + Page p = e.getAnnotation(Page.class);
13.349 + if (p == null) {
13.350 + return true;
13.351 + }
13.352 + String pkg = findPkgName(e);
13.353 +
13.354 + ProcessPage pp;
13.355 + try (InputStream is = openStream(pkg, p.xhtml())) {
13.356 + pp = ProcessPage.readPage(is);
13.357 + is.close();
13.358 + } catch (IOException iOException) {
13.359 + error("Can't read " + p.xhtml() + " as " + iOException.getMessage(), e);
13.360 + ok = false;
13.361 + pp = null;
13.362 + }
13.363 + Writer w;
13.364 + String className = p.className();
13.365 + if (className.isEmpty()) {
13.366 + int indx = p.xhtml().indexOf('.');
13.367 + className = p.xhtml().substring(0, indx);
13.368 + }
13.369 + try {
13.370 + StringWriter body = new StringWriter();
13.371 + List<String> propsGetSet = new ArrayList<>();
13.372 + List<String> functions = new ArrayList<>();
13.373 + Map<String, Collection<String>> propsDeps = new HashMap<>();
13.374 + Map<String, Collection<String>> functionDeps = new HashMap<>();
13.375 +
13.376 + Prprt[] props = createProps(e, p.properties());
13.377 + if (!generateComputedProperties(body, props, e.getEnclosedElements(), propsGetSet, propsDeps)) {
13.378 + ok = false;
13.379 + }
13.380 + if (!generateOnChange(e, propsDeps, props, className, functionDeps)) {
13.381 + ok = false;
13.382 + }
13.383 + if (!generateProperties(e, body, props, propsGetSet, propsDeps, functionDeps)) {
13.384 + ok = false;
13.385 + }
13.386 + if (!generateFunctions(e, body, className, e.getEnclosedElements(), functions)) {
13.387 + ok = false;
13.388 + }
13.389 + if (!generateReceive(e, body, className, e.getEnclosedElements(), functions)) {
13.390 + ok = false;
13.391 + }
13.392 +
13.393 + FileObject java = processingEnv.getFiler().createSourceFile(pkg + '.' + className, e);
13.394 + w = new OutputStreamWriter(java.openOutputStream());
13.395 + try {
13.396 + w.append("package " + pkg + ";\n");
13.397 + w.append("import org.apidesign.bck2brwsr.htmlpage.api.*;\n");
13.398 + w.append("import org.apidesign.bck2brwsr.htmlpage.KOList;\n");
13.399 + w.append("final class ").append(className).append(" {\n");
13.400 + w.append(" private boolean locked;\n");
13.401 + if (!initializeOnClick(className, (TypeElement) e, w, pp)) {
13.402 + ok = false;
13.403 + } else {
13.404 + if (pp != null) for (String id : pp.ids()) {
13.405 + String tag = pp.tagNameForId(id);
13.406 + String type = type(tag);
13.407 + w.append(" ").append("public final ").
13.408 + append(type).append(' ').append(cnstnt(id)).append(" = new ").
13.409 + append(type).append("(\"").append(id).append("\");\n");
13.410 + }
13.411 + }
13.412 + w.append(" private org.apidesign.bck2brwsr.htmlpage.Knockout ko;\n");
13.413 + w.append(body.toString());
13.414 + if (!propsGetSet.isEmpty()) {
13.415 + w.write("public " + className + " applyBindings() {\n");
13.416 + w.write(" ko = org.apidesign.bck2brwsr.htmlpage.Knockout.applyBindings(");
13.417 + w.write(className + ".class, this, ");
13.418 + writeStringArray(propsGetSet, w);
13.419 + w.append(", ");
13.420 + writeStringArray(functions, w);
13.421 + w.write(");\n return this;\n}\n");
13.422 +
13.423 + w.write("public void triggerEvent(Element e, OnEvent ev) {\n");
13.424 + w.write(" org.apidesign.bck2brwsr.htmlpage.Knockout.triggerEvent(e.getId(), ev.getElementPropertyName());\n");
13.425 + w.write("}\n");
13.426 + }
13.427 + w.append("}\n");
13.428 + } finally {
13.429 + w.close();
13.430 + }
13.431 + } catch (IOException ex) {
13.432 + error("Can't create " + className + ".java", e);
13.433 + return false;
13.434 + }
13.435 + return ok;
13.436 + }
13.437 +
13.438 + private static String type(String tag) {
13.439 + if (tag.equals("title")) {
13.440 + return "Title";
13.441 + }
13.442 + if (tag.equals("button")) {
13.443 + return "Button";
13.444 + }
13.445 + if (tag.equals("input")) {
13.446 + return "Input";
13.447 + }
13.448 + if (tag.equals("canvas")) {
13.449 + return "Canvas";
13.450 + }
13.451 + if (tag.equals("img")) {
13.452 + return "Image";
13.453 + }
13.454 + return "Element";
13.455 + }
13.456 +
13.457 private static String cnstnt(String id) {
13.458 - return id.toUpperCase(Locale.ENGLISH).replace('.', '_').replace('-', '_');
13.459 + return id.replace('.', '_').replace('-', '_');
13.460 }
13.461
13.462 private boolean initializeOnClick(
13.463 String className, TypeElement type, Writer w, ProcessPage pp
13.464 ) throws IOException {
13.465 + boolean ok = true;
13.466 TypeMirror stringType = processingEnv.getElementUtils().getTypeElement("java.lang.String").asType();
13.467 { //for (Element clazz : pe.getEnclosedElements()) {
13.468 // if (clazz.getKind() != ElementKind.CLASS) {
13.469 @@ -178,58 +422,27 @@
13.470 On oc = method.getAnnotation(On.class);
13.471 if (oc != null) {
13.472 for (String id : oc.id()) {
13.473 + if (pp == null) {
13.474 + error("id = " + id + " not found in HTML page.", method);
13.475 + ok = false;
13.476 + continue;
13.477 + }
13.478 if (pp.tagNameForId(id) == null) {
13.479 - processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "id = " + id + " does not exist in the HTML page. Found only " + pp.ids(), method);
13.480 - return false;
13.481 + error("id = " + id + " does not exist in the HTML page. Found only " + pp.ids(), method);
13.482 + ok = false;
13.483 + continue;
13.484 }
13.485 ExecutableElement ee = (ExecutableElement)method;
13.486 - StringBuilder params = new StringBuilder();
13.487 - {
13.488 - boolean first = true;
13.489 - for (VariableElement ve : ee.getParameters()) {
13.490 - if (!first) {
13.491 - params.append(", ");
13.492 - }
13.493 - first = false;
13.494 - if (ve.asType() == stringType) {
13.495 - if (ve.getSimpleName().contentEquals("id")) {
13.496 - params.append('"').append(id).append('"');
13.497 - continue;
13.498 - }
13.499 - params.append("org.apidesign.bck2brwsr.htmlpage.ConvertTypes.toString(ev, \"");
13.500 - params.append(ve.getSimpleName().toString());
13.501 - params.append("\")");
13.502 - continue;
13.503 - }
13.504 - if (processingEnv.getTypeUtils().getPrimitiveType(TypeKind.DOUBLE) == ve.asType()) {
13.505 - params.append("org.apidesign.bck2brwsr.htmlpage.ConvertTypes.toDouble(ev, \"");
13.506 - params.append(ve.getSimpleName().toString());
13.507 - params.append("\")");
13.508 - continue;
13.509 - }
13.510 - String rn = ve.asType().toString();
13.511 - int last = rn.lastIndexOf('.');
13.512 - if (last >= 0) {
13.513 - rn = rn.substring(last + 1);
13.514 - }
13.515 - if (rn.equals(className)) {
13.516 - params.append(className).append(".this");
13.517 - continue;
13.518 - }
13.519 - processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
13.520 - "@On method can only accept String named 'id' or " + className + " arguments",
13.521 - ee
13.522 - );
13.523 - return false;
13.524 - }
13.525 - }
13.526 + CharSequence params = wrapParams(ee, id, className, "ev", null);
13.527 if (!ee.getModifiers().contains(Modifier.STATIC)) {
13.528 - processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "@On method has to be static", ee);
13.529 - return false;
13.530 + error("@On method has to be static", ee);
13.531 + ok = false;
13.532 + continue;
13.533 }
13.534 if (ee.getModifiers().contains(Modifier.PRIVATE)) {
13.535 - processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "@On method can't be private", ee);
13.536 - return false;
13.537 + error("@On method can't be private", ee);
13.538 + ok = false;
13.539 + continue;
13.540 }
13.541 w.append(" OnEvent." + oc.event()).append(".of(").append(cnstnt(id)).
13.542 append(").perform(new OnDispatch(" + dispatchCnt + "));\n");
13.543 @@ -260,7 +473,7 @@
13.544
13.545
13.546 }
13.547 - return true;
13.548 + return ok;
13.549 }
13.550
13.551 @Override
13.552 @@ -274,8 +487,7 @@
13.553
13.554 Element cls = findClass(element);
13.555 Page p = cls.getAnnotation(Page.class);
13.556 - PackageElement pe = (PackageElement) cls.getEnclosingElement();
13.557 - String pkg = pe.getQualifiedName().toString();
13.558 + String pkg = findPkgName(cls);
13.559 ProcessPage pp;
13.560 try {
13.561 InputStream is = openStream(pkg, p.xhtml());
13.562 @@ -285,7 +497,7 @@
13.563 return Collections.emptyList();
13.564 }
13.565
13.566 - List<Completion> cc = new ArrayList<Completion>();
13.567 + List<Completion> cc = new ArrayList<>();
13.568 userText = userText.substring(1);
13.569 for (String id : pp.ids()) {
13.570 if (id.startsWith(userText)) {
13.571 @@ -306,44 +518,89 @@
13.572 return e.getEnclosingElement();
13.573 }
13.574
13.575 - private static void generateProperties(
13.576 - Writer w, Property[] properties, Collection<String> props,
13.577 - Map<String,Collection<String>> deps
13.578 + private boolean generateProperties(
13.579 + Element where,
13.580 + Writer w, Prprt[] properties,
13.581 + Collection<String> props,
13.582 + Map<String,Collection<String>> deps,
13.583 + Map<String,Collection<String>> functionDeps
13.584 ) throws IOException {
13.585 - for (Property p : properties) {
13.586 - final String tn = typeName(p);
13.587 - String[] gs = toGetSet(p.name(), tn);
13.588 + boolean ok = true;
13.589 + for (Prprt p : properties) {
13.590 + final String tn;
13.591 + tn = typeName(where, p);
13.592 + String[] gs = toGetSet(p.name(), tn, p.array());
13.593
13.594 - w.write("private " + tn + " prop_" + p.name() + ";\n");
13.595 - w.write("public " + tn + " " + gs[0] + "() {\n");
13.596 - w.write(" if (locked) throw new IllegalStateException();\n");
13.597 - w.write(" return prop_" + p.name() + ";\n");
13.598 - w.write("}\n");
13.599 - w.write("public void " + gs[1] + "(" + tn + " v) {\n");
13.600 - w.write(" if (locked) throw new IllegalStateException();\n");
13.601 - w.write(" prop_" + p.name() + " = v;\n");
13.602 - w.write(" if (ko != null) {\n");
13.603 - w.write(" ko.valueHasMutated(\"" + p.name() + "\");\n");
13.604 - final Collection<String> dependants = deps.get(p.name());
13.605 - if (dependants != null) {
13.606 - for (String depProp : dependants) {
13.607 - w.write(" ko.valueHasMutated(\"" + depProp + "\");\n");
13.608 + if (p.array()) {
13.609 + w.write("private KOList<" + tn + "> prop_" + p.name() + " = new KOList<" + tn + ">(\""
13.610 + + p.name() + "\"");
13.611 + Collection<String> dependants = deps.get(p.name());
13.612 + if (dependants != null) {
13.613 + for (String depProp : dependants) {
13.614 + w.write(", ");
13.615 + w.write('\"');
13.616 + w.write(depProp);
13.617 + w.write('\"');
13.618 + }
13.619 }
13.620 + w.write(")");
13.621 +
13.622 + dependants = functionDeps.get(p.name());
13.623 + if (dependants != null) {
13.624 + w.write(".onChange(new Runnable() { public void run() {\n");
13.625 + for (String call : dependants) {
13.626 + w.append(call);
13.627 + }
13.628 + w.write("}})");
13.629 + }
13.630 + w.write(";\n");
13.631 +
13.632 + w.write("public java.util.List<" + tn + "> " + gs[0] + "() {\n");
13.633 + w.write(" if (locked) throw new IllegalStateException();\n");
13.634 + w.write(" prop_" + p.name() + ".assign(ko);\n");
13.635 + w.write(" return prop_" + p.name() + ";\n");
13.636 + w.write("}\n");
13.637 + } else {
13.638 + w.write("private " + tn + " prop_" + p.name() + ";\n");
13.639 + w.write("public " + tn + " " + gs[0] + "() {\n");
13.640 + w.write(" if (locked) throw new IllegalStateException();\n");
13.641 + w.write(" return prop_" + p.name() + ";\n");
13.642 + w.write("}\n");
13.643 + w.write("public void " + gs[1] + "(" + tn + " v) {\n");
13.644 + w.write(" if (locked) throw new IllegalStateException();\n");
13.645 + w.write(" prop_" + p.name() + " = v;\n");
13.646 + w.write(" if (ko != null) {\n");
13.647 + w.write(" ko.valueHasMutated(\"" + p.name() + "\");\n");
13.648 + Collection<String> dependants = deps.get(p.name());
13.649 + if (dependants != null) {
13.650 + for (String depProp : dependants) {
13.651 + w.write(" ko.valueHasMutated(\"" + depProp + "\");\n");
13.652 + }
13.653 + }
13.654 + w.write(" }\n");
13.655 + dependants = functionDeps.get(p.name());
13.656 + if (dependants != null) {
13.657 + for (String call : dependants) {
13.658 + w.append(call);
13.659 + }
13.660 + }
13.661 + w.write("}\n");
13.662 }
13.663 - w.write(" }\n");
13.664 - w.write("}\n");
13.665
13.666 props.add(p.name());
13.667 props.add(gs[2]);
13.668 props.add(gs[3]);
13.669 props.add(gs[0]);
13.670 }
13.671 + return ok;
13.672 }
13.673
13.674 private boolean generateComputedProperties(
13.675 - Writer w, Collection<? extends Element> arr, Collection<String> props,
13.676 + Writer w, Prprt[] fixedProps,
13.677 + Collection<? extends Element> arr, Collection<String> props,
13.678 Map<String,Collection<String>> deps
13.679 ) throws IOException {
13.680 + boolean ok = true;
13.681 for (Element e : arr) {
13.682 if (e.getKind() != ElementKind.METHOD) {
13.683 continue;
13.684 @@ -352,30 +609,43 @@
13.685 continue;
13.686 }
13.687 ExecutableElement ee = (ExecutableElement)e;
13.688 - final String tn = ee.getReturnType().toString();
13.689 + final TypeMirror rt = ee.getReturnType();
13.690 + final Types tu = processingEnv.getTypeUtils();
13.691 + TypeMirror ert = tu.erasure(rt);
13.692 + String tn = fqn(ert, ee);
13.693 + boolean array = false;
13.694 + if (tn.equals("java.util.List")) {
13.695 + array = true;
13.696 + }
13.697 +
13.698 final String sn = ee.getSimpleName().toString();
13.699 - String[] gs = toGetSet(sn, tn);
13.700 + String[] gs = toGetSet(sn, tn, array);
13.701
13.702 w.write("public " + tn + " " + gs[0] + "() {\n");
13.703 w.write(" if (locked) throw new IllegalStateException();\n");
13.704 int arg = 0;
13.705 for (VariableElement pe : ee.getParameters()) {
13.706 final String dn = pe.getSimpleName().toString();
13.707 - final String dt = pe.asType().toString();
13.708 - String[] call = toGetSet(dn, dt);
13.709 +
13.710 + if (!verifyPropName(pe, dn, fixedProps)) {
13.711 + ok = false;
13.712 + }
13.713 +
13.714 + final String dt = fqn(pe.asType(), ee);
13.715 + String[] call = toGetSet(dn, dt, false);
13.716 w.write(" " + dt + " arg" + (++arg) + " = ");
13.717 w.write(call[0] + "();\n");
13.718
13.719 Collection<String> depends = deps.get(dn);
13.720 if (depends == null) {
13.721 - depends = new LinkedHashSet<String>();
13.722 + depends = new LinkedHashSet<>();
13.723 deps.put(dn, depends);
13.724 }
13.725 depends.add(sn);
13.726 }
13.727 w.write(" try {\n");
13.728 w.write(" locked = true;\n");
13.729 - w.write(" return " + e.getEnclosingElement().getSimpleName() + '.' + e.getSimpleName() + "(");
13.730 + w.write(" return " + fqn(ee.getEnclosingElement().asType(), ee) + '.' + e.getSimpleName() + "(");
13.731 String sep = "";
13.732 for (int i = 1; i <= arg; i++) {
13.733 w.write(sep);
13.734 @@ -387,17 +657,17 @@
13.735 w.write(" locked = false;\n");
13.736 w.write(" }\n");
13.737 w.write("}\n");
13.738 -
13.739 +
13.740 props.add(e.getSimpleName().toString());
13.741 props.add(gs[2]);
13.742 props.add(null);
13.743 props.add(gs[0]);
13.744 }
13.745
13.746 - return true;
13.747 + return ok;
13.748 }
13.749
13.750 - private static String[] toGetSet(String name, String type) {
13.751 + private static String[] toGetSet(String name, String type, boolean array) {
13.752 String n = Character.toUpperCase(name.charAt(0)) + name.substring(1);
13.753 String bck2brwsrType = "L" + type.replace('.', '_') + "_2";
13.754 if ("int".equals(type)) {
13.755 @@ -412,6 +682,14 @@
13.756 bck2brwsrType = "Z";
13.757 }
13.758 final String nu = n.replace('.', '_');
13.759 + if (array) {
13.760 + return new String[] {
13.761 + "get" + n,
13.762 + null,
13.763 + "get" + nu + "__Ljava_util_List_2",
13.764 + null
13.765 + };
13.766 + }
13.767 return new String[]{
13.768 pref + n,
13.769 "set" + n,
13.770 @@ -420,11 +698,702 @@
13.771 };
13.772 }
13.773
13.774 - private static String typeName(Property p) {
13.775 - try {
13.776 - return p.type().getName();
13.777 - } catch (MirroredTypeException ex) {
13.778 - return ex.getTypeMirror().toString();
13.779 + private String typeName(Element where, Prprt p) {
13.780 + String ret;
13.781 + boolean[] isModel = { false };
13.782 + boolean[] isEnum = { false };
13.783 + boolean isPrimitive[] = { false };
13.784 + ret = checkType(p, isModel, isEnum, isPrimitive);
13.785 + if (p.array()) {
13.786 + String bt = findBoxedType(ret);
13.787 + if (bt != null) {
13.788 + return bt;
13.789 + }
13.790 + }
13.791 + return ret;
13.792 + }
13.793 +
13.794 + private static String findBoxedType(String ret) {
13.795 + if (ret.equals("boolean")) {
13.796 + return Boolean.class.getName();
13.797 + }
13.798 + if (ret.equals("byte")) {
13.799 + return Byte.class.getName();
13.800 + }
13.801 + if (ret.equals("short")) {
13.802 + return Short.class.getName();
13.803 + }
13.804 + if (ret.equals("char")) {
13.805 + return Character.class.getName();
13.806 + }
13.807 + if (ret.equals("int")) {
13.808 + return Integer.class.getName();
13.809 + }
13.810 + if (ret.equals("long")) {
13.811 + return Long.class.getName();
13.812 + }
13.813 + if (ret.equals("float")) {
13.814 + return Float.class.getName();
13.815 + }
13.816 + if (ret.equals("double")) {
13.817 + return Double.class.getName();
13.818 + }
13.819 + return null;
13.820 + }
13.821 +
13.822 + private boolean verifyPropName(Element e, String propName, Prprt[] existingProps) {
13.823 + StringBuilder sb = new StringBuilder();
13.824 + String sep = "";
13.825 + for (Prprt Prprt : existingProps) {
13.826 + if (Prprt.name().equals(propName)) {
13.827 + return true;
13.828 + }
13.829 + sb.append(sep);
13.830 + sb.append('"');
13.831 + sb.append(Prprt.name());
13.832 + sb.append('"');
13.833 + sep = ", ";
13.834 + }
13.835 + error(
13.836 + propName + " is not one of known properties: " + sb
13.837 + , e
13.838 + );
13.839 + return false;
13.840 + }
13.841 +
13.842 + private static String findPkgName(Element e) {
13.843 + for (;;) {
13.844 + if (e.getKind() == ElementKind.PACKAGE) {
13.845 + return ((PackageElement)e).getQualifiedName().toString();
13.846 + }
13.847 + e = e.getEnclosingElement();
13.848 }
13.849 }
13.850 +
13.851 + private boolean generateFunctions(
13.852 + Element clazz, StringWriter body, String className,
13.853 + List<? extends Element> enclosedElements, List<String> functions
13.854 + ) {
13.855 + for (Element m : enclosedElements) {
13.856 + if (m.getKind() != ElementKind.METHOD) {
13.857 + continue;
13.858 + }
13.859 + ExecutableElement e = (ExecutableElement)m;
13.860 + OnFunction onF = e.getAnnotation(OnFunction.class);
13.861 + if (onF == null) {
13.862 + continue;
13.863 + }
13.864 + if (!e.getModifiers().contains(Modifier.STATIC)) {
13.865 + error("@OnFunction method needs to be static", e);
13.866 + return false;
13.867 + }
13.868 + if (e.getModifiers().contains(Modifier.PRIVATE)) {
13.869 + error("@OnFunction method cannot be private", e);
13.870 + return false;
13.871 + }
13.872 + if (e.getReturnType().getKind() != TypeKind.VOID) {
13.873 + error("@OnFunction method should return void", e);
13.874 + return false;
13.875 + }
13.876 + String n = e.getSimpleName().toString();
13.877 + body.append("private void ").append(n).append("(Object data, Object ev) {\n");
13.878 + body.append(" ").append(clazz.getSimpleName()).append(".").append(n).append("(");
13.879 + body.append(wrapParams(e, null, className, "ev", "data"));
13.880 + body.append(");\n");
13.881 + body.append("}\n");
13.882 +
13.883 + functions.add(n);
13.884 + functions.add(n + "__VLjava_lang_Object_2Ljava_lang_Object_2");
13.885 + }
13.886 + return true;
13.887 + }
13.888 +
13.889 + private boolean generateOnChange(Element clazz, Map<String,Collection<String>> propDeps,
13.890 + Prprt[] properties, String className,
13.891 + Map<String, Collection<String>> functionDeps
13.892 + ) {
13.893 + for (Element m : clazz.getEnclosedElements()) {
13.894 + if (m.getKind() != ElementKind.METHOD) {
13.895 + continue;
13.896 + }
13.897 + ExecutableElement e = (ExecutableElement) m;
13.898 + OnPropertyChange onPC = e.getAnnotation(OnPropertyChange.class);
13.899 + if (onPC == null) {
13.900 + continue;
13.901 + }
13.902 + for (String pn : onPC.value()) {
13.903 + if (findPrprt(properties, pn) == null && findDerivedFrom(propDeps, pn).isEmpty()) {
13.904 + error("No Prprt named '" + pn + "' in the model", clazz);
13.905 + return false;
13.906 + }
13.907 + }
13.908 + if (!e.getModifiers().contains(Modifier.STATIC)) {
13.909 + error("@OnPrprtChange method needs to be static", e);
13.910 + return false;
13.911 + }
13.912 + if (e.getModifiers().contains(Modifier.PRIVATE)) {
13.913 + error("@OnPrprtChange method cannot be private", e);
13.914 + return false;
13.915 + }
13.916 + if (e.getReturnType().getKind() != TypeKind.VOID) {
13.917 + error("@OnPrprtChange method should return void", e);
13.918 + return false;
13.919 + }
13.920 + String n = e.getSimpleName().toString();
13.921 +
13.922 +
13.923 + for (String pn : onPC.value()) {
13.924 + StringBuilder call = new StringBuilder();
13.925 + call.append(" ").append(clazz.getSimpleName()).append(".").append(n).append("(");
13.926 + call.append(wrapPropName(e, className, "name", pn));
13.927 + call.append(");\n");
13.928 +
13.929 + Collection<String> change = functionDeps.get(pn);
13.930 + if (change == null) {
13.931 + change = new ArrayList<>();
13.932 + functionDeps.put(pn, change);
13.933 + }
13.934 + change.add(call.toString());
13.935 + for (String dpn : findDerivedFrom(propDeps, pn)) {
13.936 + change = functionDeps.get(dpn);
13.937 + if (change == null) {
13.938 + change = new ArrayList<>();
13.939 + functionDeps.put(dpn, change);
13.940 + }
13.941 + change.add(call.toString());
13.942 + }
13.943 + }
13.944 + }
13.945 + return true;
13.946 + }
13.947 +
13.948 + private boolean generateReceive(
13.949 + Element clazz, StringWriter body, String className,
13.950 + List<? extends Element> enclosedElements, List<String> functions
13.951 + ) {
13.952 + for (Element m : enclosedElements) {
13.953 + if (m.getKind() != ElementKind.METHOD) {
13.954 + continue;
13.955 + }
13.956 + ExecutableElement e = (ExecutableElement)m;
13.957 + OnReceive onR = e.getAnnotation(OnReceive.class);
13.958 + if (onR == null) {
13.959 + continue;
13.960 + }
13.961 + if (!e.getModifiers().contains(Modifier.STATIC)) {
13.962 + error("@OnReceive method needs to be static", e);
13.963 + return false;
13.964 + }
13.965 + if (e.getModifiers().contains(Modifier.PRIVATE)) {
13.966 + error("@OnReceive method cannot be private", e);
13.967 + return false;
13.968 + }
13.969 + if (e.getReturnType().getKind() != TypeKind.VOID) {
13.970 + error("@OnReceive method should return void", e);
13.971 + return false;
13.972 + }
13.973 + String modelClass = null;
13.974 + boolean expectsList = false;
13.975 + List<String> args = new ArrayList<>();
13.976 + {
13.977 + for (VariableElement ve : e.getParameters()) {
13.978 + TypeMirror modelType = null;
13.979 + if (ve.asType().toString().equals(className)) {
13.980 + args.add(className + ".this");
13.981 + } else if (isModel(ve.asType())) {
13.982 + modelType = ve.asType();
13.983 + } else if (ve.asType().getKind() == TypeKind.ARRAY) {
13.984 + modelType = ((ArrayType)ve.asType()).getComponentType();
13.985 + expectsList = true;
13.986 + }
13.987 + if (modelType != null) {
13.988 + if (modelClass != null) {
13.989 + error("There can be only one model class among arguments", e);
13.990 + } else {
13.991 + modelClass = modelType.toString();
13.992 + if (expectsList) {
13.993 + args.add("arr");
13.994 + } else {
13.995 + args.add("arr[0]");
13.996 + }
13.997 + }
13.998 + }
13.999 + }
13.1000 + }
13.1001 + if (modelClass == null) {
13.1002 + error("The method needs to have one @Model class as parameter", e);
13.1003 + }
13.1004 + String n = e.getSimpleName().toString();
13.1005 + body.append("public void ").append(n).append("(");
13.1006 + StringBuilder assembleURL = new StringBuilder();
13.1007 + String jsonpVarName = null;
13.1008 + {
13.1009 + String sep = "";
13.1010 + boolean skipJSONP = onR.jsonp().isEmpty();
13.1011 + for (String p : findParamNames(e, onR.url(), assembleURL)) {
13.1012 + if (!skipJSONP && p.equals(onR.jsonp())) {
13.1013 + skipJSONP = true;
13.1014 + jsonpVarName = p;
13.1015 + continue;
13.1016 + }
13.1017 + body.append(sep);
13.1018 + body.append("String ").append(p);
13.1019 + sep = ", ";
13.1020 + }
13.1021 + if (!skipJSONP) {
13.1022 + error(
13.1023 + "Name of jsonp attribute ('" + onR.jsonp() +
13.1024 + "') is not used in url attribute '" + onR.url() + "'", e
13.1025 + );
13.1026 + }
13.1027 + }
13.1028 + body.append(") {\n");
13.1029 + body.append(" final Object[] result = { null };\n");
13.1030 + body.append(
13.1031 + " class ProcessResult implements Runnable {\n" +
13.1032 + " @Override\n" +
13.1033 + " public void run() {\n" +
13.1034 + " Object value = result[0];\n");
13.1035 + body.append(
13.1036 + " " + modelClass + "[] arr;\n");
13.1037 + body.append(
13.1038 + " if (value instanceof Object[]) {\n" +
13.1039 + " Object[] data = ((Object[])value);\n" +
13.1040 + " arr = new " + modelClass + "[data.length];\n" +
13.1041 + " for (int i = 0; i < data.length; i++) {\n" +
13.1042 + " arr[i] = new " + modelClass + "(data[i]);\n" +
13.1043 + " }\n" +
13.1044 + " } else {\n" +
13.1045 + " arr = new " + modelClass + "[1];\n" +
13.1046 + " arr[0] = new " + modelClass + "(value);\n" +
13.1047 + " }\n"
13.1048 + );
13.1049 + {
13.1050 + body.append(clazz.getSimpleName()).append(".").append(n).append("(");
13.1051 + String sep = "";
13.1052 + for (String arg : args) {
13.1053 + body.append(sep);
13.1054 + body.append(arg);
13.1055 + sep = ", ";
13.1056 + }
13.1057 + body.append(");\n");
13.1058 + }
13.1059 + body.append(
13.1060 + " }\n" +
13.1061 + " }\n"
13.1062 + );
13.1063 + body.append(" ProcessResult pr = new ProcessResult();\n");
13.1064 + if (jsonpVarName != null) {
13.1065 + body.append(" String ").append(jsonpVarName).
13.1066 + append(" = org.apidesign.bck2brwsr.htmlpage.ConvertTypes.createJSONP(result, pr);\n");
13.1067 + }
13.1068 + body.append(" org.apidesign.bck2brwsr.htmlpage.ConvertTypes.loadJSON(\n ");
13.1069 + body.append(assembleURL);
13.1070 + body.append(", result, pr, ").append(jsonpVarName).append("\n );\n");
13.1071 +// body.append(" ").append(clazz.getSimpleName()).append(".").append(n).append("(");
13.1072 +// body.append(wrapParams(e, null, className, "ev", "data"));
13.1073 +// body.append(");\n");
13.1074 + body.append("}\n");
13.1075 + }
13.1076 + return true;
13.1077 + }
13.1078 +
13.1079 + private CharSequence wrapParams(
13.1080 + ExecutableElement ee, String id, String className, String evName, String dataName
13.1081 + ) {
13.1082 + TypeMirror stringType = processingEnv.getElementUtils().getTypeElement("java.lang.String").asType();
13.1083 + StringBuilder params = new StringBuilder();
13.1084 + boolean first = true;
13.1085 + for (VariableElement ve : ee.getParameters()) {
13.1086 + if (!first) {
13.1087 + params.append(", ");
13.1088 + }
13.1089 + first = false;
13.1090 + String toCall = null;
13.1091 + if (ve.asType() == stringType) {
13.1092 + if (ve.getSimpleName().contentEquals("id")) {
13.1093 + params.append('"').append(id).append('"');
13.1094 + continue;
13.1095 + }
13.1096 + toCall = "org.apidesign.bck2brwsr.htmlpage.ConvertTypes.toString(";
13.1097 + }
13.1098 + if (ve.asType().getKind() == TypeKind.DOUBLE) {
13.1099 + toCall = "org.apidesign.bck2brwsr.htmlpage.ConvertTypes.toDouble(";
13.1100 + }
13.1101 + if (ve.asType().getKind() == TypeKind.INT) {
13.1102 + toCall = "org.apidesign.bck2brwsr.htmlpage.ConvertTypes.toInt(";
13.1103 + }
13.1104 + if (dataName != null && ve.getSimpleName().contentEquals(dataName) && isModel(ve.asType())) {
13.1105 + toCall = "org.apidesign.bck2brwsr.htmlpage.ConvertTypes.toModel(" + ve.asType() + ".class, ";
13.1106 + }
13.1107 +
13.1108 + if (toCall != null) {
13.1109 + params.append(toCall);
13.1110 + if (dataName != null && ve.getSimpleName().contentEquals(dataName)) {
13.1111 + params.append(dataName);
13.1112 + params.append(", null");
13.1113 + } else {
13.1114 + if (evName == null) {
13.1115 + final StringBuilder sb = new StringBuilder();
13.1116 + sb.append("Unexpected string parameter name.");
13.1117 + if (dataName != null) {
13.1118 + sb.append(" Try \"").append(dataName).append("\"");
13.1119 + }
13.1120 + error(sb.toString(), ee);
13.1121 + }
13.1122 + params.append(evName);
13.1123 + params.append(", \"");
13.1124 + params.append(ve.getSimpleName().toString());
13.1125 + params.append("\"");
13.1126 + }
13.1127 + params.append(")");
13.1128 + continue;
13.1129 + }
13.1130 + String rn = fqn(ve.asType(), ee);
13.1131 + int last = rn.lastIndexOf('.');
13.1132 + if (last >= 0) {
13.1133 + rn = rn.substring(last + 1);
13.1134 + }
13.1135 + if (rn.equals(className)) {
13.1136 + params.append(className).append(".this");
13.1137 + continue;
13.1138 + }
13.1139 + error(
13.1140 + "@On method can only accept String named 'id' or " + className + " arguments",
13.1141 + ee
13.1142 + );
13.1143 + }
13.1144 + return params;
13.1145 + }
13.1146 +
13.1147 +
13.1148 + private CharSequence wrapPropName(
13.1149 + ExecutableElement ee, String className, String propName, String propValue
13.1150 + ) {
13.1151 + TypeMirror stringType = processingEnv.getElementUtils().getTypeElement("java.lang.String").asType();
13.1152 + StringBuilder params = new StringBuilder();
13.1153 + boolean first = true;
13.1154 + for (VariableElement ve : ee.getParameters()) {
13.1155 + if (!first) {
13.1156 + params.append(", ");
13.1157 + }
13.1158 + first = false;
13.1159 + if (ve.asType() == stringType) {
13.1160 + if (propName != null && ve.getSimpleName().contentEquals(propName)) {
13.1161 + params.append('"').append(propValue).append('"');
13.1162 + } else {
13.1163 + error("Unexpected string parameter name. Try \"" + propName + "\".", ee);
13.1164 + }
13.1165 + continue;
13.1166 + }
13.1167 + String rn = fqn(ve.asType(), ee);
13.1168 + int last = rn.lastIndexOf('.');
13.1169 + if (last >= 0) {
13.1170 + rn = rn.substring(last + 1);
13.1171 + }
13.1172 + if (rn.equals(className)) {
13.1173 + params.append(className).append(".this");
13.1174 + continue;
13.1175 + }
13.1176 + error(
13.1177 + "@OnPrprtChange method can only accept String or " + className + " arguments",
13.1178 + ee);
13.1179 + }
13.1180 + return params;
13.1181 + }
13.1182 +
13.1183 + private boolean isModel(TypeMirror tm) {
13.1184 + final Element e = processingEnv.getTypeUtils().asElement(tm);
13.1185 + if (e == null) {
13.1186 + return false;
13.1187 + }
13.1188 + for (Element ch : e.getEnclosedElements()) {
13.1189 + if (ch.getKind() == ElementKind.METHOD) {
13.1190 + ExecutableElement ee = (ExecutableElement)ch;
13.1191 + if (ee.getParameters().isEmpty() && ee.getSimpleName().contentEquals("modelFor")) {
13.1192 + return true;
13.1193 + }
13.1194 + }
13.1195 + }
13.1196 + return models.values().contains(e.getSimpleName().toString());
13.1197 + }
13.1198 +
13.1199 + private void writeStringArray(List<String> strings, Writer w) throws IOException {
13.1200 + w.write("new String[] {\n");
13.1201 + String sep = "";
13.1202 + for (String n : strings) {
13.1203 + w.write(sep);
13.1204 + if (n == null) {
13.1205 + w.write(" null");
13.1206 + } else {
13.1207 + w.write(" \"" + n + "\"");
13.1208 + }
13.1209 + sep = ",\n";
13.1210 + }
13.1211 + w.write("\n }");
13.1212 + }
13.1213 +
13.1214 + private void writeToString(Prprt[] props, Writer w) throws IOException {
13.1215 + w.write(" public String toString() {\n");
13.1216 + w.write(" StringBuilder sb = new StringBuilder();\n");
13.1217 + w.write(" sb.append('{');\n");
13.1218 + String sep = "";
13.1219 + for (Prprt p : props) {
13.1220 + w.write(sep);
13.1221 + w.append(" sb.append('\"').append(\"" + p.name() + "\")");
13.1222 + w.append(".append('\"').append(\":\");\n");
13.1223 + w.append(" sb.append(org.apidesign.bck2brwsr.htmlpage.ConvertTypes.toJSON(prop_");
13.1224 + w.append(p.name()).append("));\n");
13.1225 + sep = " sb.append(',');\n";
13.1226 + }
13.1227 + w.write(" sb.append('}');\n");
13.1228 + w.write(" return sb.toString();\n");
13.1229 + w.write(" }\n");
13.1230 + }
13.1231 + private void writeClone(String className, Prprt[] props, Writer w) throws IOException {
13.1232 + w.write(" public " + className + " clone() {\n");
13.1233 + w.write(" " + className + " ret = new " + className + "();\n");
13.1234 + for (Prprt p : props) {
13.1235 + if (!p.array()) {
13.1236 + boolean isModel[] = { false };
13.1237 + boolean isEnum[] = { false };
13.1238 + boolean isPrimitive[] = { false };
13.1239 + checkType(p, isModel, isEnum, isPrimitive);
13.1240 + if (!isModel[0]) {
13.1241 + w.write(" ret.prop_" + p.name() + " = prop_" + p.name() + ";\n");
13.1242 + continue;
13.1243 + }
13.1244 + w.write(" ret.prop_" + p.name() + " = prop_" + p.name() + ".clone();\n");
13.1245 + } else {
13.1246 + w.write(" ret.prop_" + p.name() + " = prop_" + p.name() + ".clone();\n");
13.1247 + }
13.1248 + }
13.1249 +
13.1250 + w.write(" return ret;\n");
13.1251 + w.write(" }\n");
13.1252 + }
13.1253 +
13.1254 + private String inPckName(Element e) {
13.1255 + StringBuilder sb = new StringBuilder();
13.1256 + while (e.getKind() != ElementKind.PACKAGE) {
13.1257 + if (sb.length() == 0) {
13.1258 + sb.append(e.getSimpleName());
13.1259 + } else {
13.1260 + sb.insert(0, '.');
13.1261 + sb.insert(0, e.getSimpleName());
13.1262 + }
13.1263 + e = e.getEnclosingElement();
13.1264 + }
13.1265 + return sb.toString();
13.1266 + }
13.1267 +
13.1268 + private String fqn(TypeMirror pt, Element relative) {
13.1269 + if (pt.getKind() == TypeKind.ERROR) {
13.1270 + final Elements eu = processingEnv.getElementUtils();
13.1271 + PackageElement pckg = eu.getPackageOf(relative);
13.1272 + return pckg.getQualifiedName() + "." + pt.toString();
13.1273 + }
13.1274 + return pt.toString();
13.1275 + }
13.1276 +
13.1277 + private String checkType(Prprt p, boolean[] isModel, boolean[] isEnum, boolean[] isPrimitive) {
13.1278 + TypeMirror tm;
13.1279 + try {
13.1280 + String ret = p.typeName(processingEnv);
13.1281 + TypeElement e = processingEnv.getElementUtils().getTypeElement(ret);
13.1282 + if (e == null) {
13.1283 + isModel[0] = true;
13.1284 + isEnum[0] = false;
13.1285 + isPrimitive[0] = false;
13.1286 + return ret;
13.1287 + }
13.1288 + tm = e.asType();
13.1289 + } catch (MirroredTypeException ex) {
13.1290 + tm = ex.getTypeMirror();
13.1291 + }
13.1292 + tm = processingEnv.getTypeUtils().erasure(tm);
13.1293 + isPrimitive[0] = tm.getKind().isPrimitive();
13.1294 + final Element e = processingEnv.getTypeUtils().asElement(tm);
13.1295 + final Model m = e == null ? null : e.getAnnotation(Model.class);
13.1296 +
13.1297 + String ret;
13.1298 + if (m != null) {
13.1299 + ret = findPkgName(e) + '.' + m.className();
13.1300 + isModel[0] = true;
13.1301 + models.put(e, m.className());
13.1302 + } else if (findModelForMthd(e)) {
13.1303 + ret = ((TypeElement)e).getQualifiedName().toString();
13.1304 + isModel[0] = true;
13.1305 + } else {
13.1306 + ret = tm.toString();
13.1307 + }
13.1308 + TypeMirror enm = processingEnv.getElementUtils().getTypeElement("java.lang.Enum").asType();
13.1309 + enm = processingEnv.getTypeUtils().erasure(enm);
13.1310 + isEnum[0] = processingEnv.getTypeUtils().isSubtype(tm, enm);
13.1311 + return ret;
13.1312 + }
13.1313 +
13.1314 + private static boolean findModelForMthd(Element clazz) {
13.1315 + if (clazz == null) {
13.1316 + return false;
13.1317 + }
13.1318 + for (Element e : clazz.getEnclosedElements()) {
13.1319 + if (e.getKind() == ElementKind.METHOD) {
13.1320 + ExecutableElement ee = (ExecutableElement)e;
13.1321 + if (
13.1322 + ee.getSimpleName().contentEquals("modelFor") &&
13.1323 + ee.getParameters().isEmpty()
13.1324 + ) {
13.1325 + return true;
13.1326 + }
13.1327 + }
13.1328 + }
13.1329 + return false;
13.1330 + }
13.1331 +
13.1332 + private Iterable<String> findParamNames(Element e, String url, StringBuilder assembleURL) {
13.1333 + List<String> params = new ArrayList<>();
13.1334 +
13.1335 + for (int pos = 0; ;) {
13.1336 + int next = url.indexOf('{', pos);
13.1337 + if (next == -1) {
13.1338 + assembleURL.append('"')
13.1339 + .append(url.substring(pos))
13.1340 + .append('"');
13.1341 + return params;
13.1342 + }
13.1343 + int close = url.indexOf('}', next);
13.1344 + if (close == -1) {
13.1345 + error("Unbalanced '{' and '}' in " + url, e);
13.1346 + return params;
13.1347 + }
13.1348 + final String paramName = url.substring(next + 1, close);
13.1349 + params.add(paramName);
13.1350 + assembleURL.append('"')
13.1351 + .append(url.substring(pos, next))
13.1352 + .append("\" + ").append(paramName).append(" + ");
13.1353 + pos = close + 1;
13.1354 + }
13.1355 + }
13.1356 +
13.1357 + private static Prprt findPrprt(Prprt[] properties, String propName) {
13.1358 + for (Prprt p : properties) {
13.1359 + if (propName.equals(p.name())) {
13.1360 + return p;
13.1361 + }
13.1362 + }
13.1363 + return null;
13.1364 + }
13.1365 +
13.1366 + private boolean isPrimitive(String type) {
13.1367 + return
13.1368 + "int".equals(type) ||
13.1369 + "double".equals(type) ||
13.1370 + "long".equals(type) ||
13.1371 + "short".equals(type) ||
13.1372 + "byte".equals(type) ||
13.1373 + "float".equals(type);
13.1374 + }
13.1375 +
13.1376 + private static Collection<String> findDerivedFrom(Map<String, Collection<String>> propsDeps, String derivedProp) {
13.1377 + Set<String> names = new HashSet<>();
13.1378 + for (Map.Entry<String, Collection<String>> e : propsDeps.entrySet()) {
13.1379 + if (e.getValue().contains(derivedProp)) {
13.1380 + names.add(e.getKey());
13.1381 + }
13.1382 + }
13.1383 + return names;
13.1384 + }
13.1385 +
13.1386 + private Prprt[] createProps(Element e, Property[] arr) {
13.1387 + Prprt[] ret = Prprt.wrap(processingEnv, e, arr);
13.1388 + Prprt[] prev = verify.put(e, ret);
13.1389 + if (prev != null) {
13.1390 + error("Two sets of properties for ", e);
13.1391 + }
13.1392 + return ret;
13.1393 + }
13.1394 +
13.1395 + private static class Prprt {
13.1396 + private final Element e;
13.1397 + private final AnnotationMirror tm;
13.1398 + private final Property p;
13.1399 +
13.1400 + public Prprt(Element e, AnnotationMirror tm, Property p) {
13.1401 + this.e = e;
13.1402 + this.tm = tm;
13.1403 + this.p = p;
13.1404 + }
13.1405 +
13.1406 + String name() {
13.1407 + return p.name();
13.1408 + }
13.1409 +
13.1410 + boolean array() {
13.1411 + return p.array();
13.1412 + }
13.1413 +
13.1414 + String typeName(ProcessingEnvironment env) {
13.1415 + try {
13.1416 + return p.type().getName();
13.1417 + } catch (IncompleteAnnotationException | AnnotationTypeMismatchException ex) {
13.1418 + for (Object v : getAnnoValues(env)) {
13.1419 + String s = v.toString().replace(" ", "");
13.1420 + if (s.startsWith("type=") && s.endsWith(".class")) {
13.1421 + return s.substring(5, s.length() - 6);
13.1422 + }
13.1423 + }
13.1424 + throw ex;
13.1425 + }
13.1426 + }
13.1427 +
13.1428 +
13.1429 + static Prprt[] wrap(ProcessingEnvironment pe, Element e, Property[] arr) {
13.1430 + if (arr.length == 0) {
13.1431 + return new Prprt[0];
13.1432 + }
13.1433 +
13.1434 + if (e.getKind() != ElementKind.CLASS) {
13.1435 + throw new IllegalStateException("" + e.getKind());
13.1436 + }
13.1437 + TypeElement te = (TypeElement)e;
13.1438 + List<? extends AnnotationValue> val = null;
13.1439 + for (AnnotationMirror an : te.getAnnotationMirrors()) {
13.1440 + for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : an.getElementValues().entrySet()) {
13.1441 + if (entry.getKey().getSimpleName().contentEquals("properties")) {
13.1442 + val = (List)entry.getValue().getValue();
13.1443 + break;
13.1444 + }
13.1445 + }
13.1446 + }
13.1447 + if (val == null || val.size() != arr.length) {
13.1448 + pe.getMessager().printMessage(Diagnostic.Kind.ERROR, "" + val, e);
13.1449 + return new Prprt[0];
13.1450 + }
13.1451 + Prprt[] ret = new Prprt[arr.length];
13.1452 + BIG: for (int i = 0; i < ret.length; i++) {
13.1453 + AnnotationMirror am = (AnnotationMirror)val.get(i).getValue();
13.1454 + ret[i] = new Prprt(e, am, arr[i]);
13.1455 +
13.1456 + }
13.1457 + return ret;
13.1458 + }
13.1459 +
13.1460 + private List<? extends Object> getAnnoValues(ProcessingEnvironment pe) {
13.1461 + try {
13.1462 + Class<?> trees = Class.forName("com.sun.tools.javac.api.JavacTrees");
13.1463 + Method m = trees.getMethod("instance", ProcessingEnvironment.class);
13.1464 + Object instance = m.invoke(null, pe);
13.1465 + m = instance.getClass().getMethod("getPath", Element.class, AnnotationMirror.class);
13.1466 + Object path = m.invoke(instance, e, tm);
13.1467 + m = path.getClass().getMethod("getLeaf");
13.1468 + Object leaf = m.invoke(path);
13.1469 + m = leaf.getClass().getMethod("getArguments");
13.1470 + return (List)m.invoke(leaf);
13.1471 + } catch (Exception ex) {
13.1472 + return Collections.emptyList();
13.1473 + }
13.1474 + }
13.1475 + }
13.1476 +
13.1477 }
14.1 --- a/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/PredefinedFields.java Tue Apr 02 15:40:51 2013 +0200
14.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
14.3 @@ -1,65 +0,0 @@
14.4 -/**
14.5 - * Back 2 Browser Bytecode Translator
14.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
14.7 - *
14.8 - * This program is free software: you can redistribute it and/or modify
14.9 - * it under the terms of the GNU General Public License as published by
14.10 - * the Free Software Foundation, version 2 of the License.
14.11 - *
14.12 - * This program is distributed in the hope that it will be useful,
14.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
14.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14.15 - * GNU General Public License for more details.
14.16 - *
14.17 - * You should have received a copy of the GNU General Public License
14.18 - * along with this program. Look for COPYING file in the top folder.
14.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
14.20 - */
14.21 -package org.apidesign.bck2brwsr.htmlpage;
14.22 -
14.23 -import java.io.IOException;
14.24 -import java.io.Writer;
14.25 -import java.util.HashMap;
14.26 -import java.util.Map;
14.27 -
14.28 -/**
14.29 - *
14.30 - * @author Jan Horvath <jhorvath@netbeans.org>
14.31 - */
14.32 -public class PredefinedFields {
14.33 -
14.34 - private static final Map<String, String> IMPORTS = new HashMap<String, String>() {
14.35 - {
14.36 - put("canvas", "import org.apidesign.bck2brwsr.core.JavaScriptBody;");
14.37 - }
14.38 - };
14.39 -
14.40 - private static final Map<String, String> FIELDS = new HashMap<String, String>() {
14.41 - {
14.42 - put("canvas",
14.43 - " @JavaScriptBody(\n" +
14.44 - " args = {\"el\"},\n" +
14.45 - " body = \"var e = window.document.getElementById(el._id());\\n\"\n" +
14.46 - " + \"return e.getContext('2d');\\n\")\n" +
14.47 - " private native static Object getContextImpl(Canvas el);\n" +
14.48 - " \n" +
14.49 - " public GraphicsContext getContext() {\n" +
14.50 - " return new GraphicsContext(getContextImpl(this));\n" +
14.51 - " }");
14.52 - }
14.53 - };
14.54 -
14.55 - static void appendImports(Writer w, String tag) throws IOException {
14.56 - String text = IMPORTS.get(tag.toLowerCase());
14.57 - if (text != null) {
14.58 - w.append(text).append("\n");
14.59 - }
14.60 - }
14.61 -
14.62 - static void appendFields(Writer w, String tag) throws IOException {
14.63 - String text = FIELDS.get(tag.toLowerCase());
14.64 - if (text != null) {
14.65 - w.append(text).append("\n");
14.66 - }
14.67 - }
14.68 -}
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
15.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Button.java Thu May 02 09:18:22 2013 +0200
15.3 @@ -0,0 +1,36 @@
15.4 +/**
15.5 + * Back 2 Browser Bytecode Translator
15.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
15.7 + *
15.8 + * This program is free software: you can redistribute it and/or modify
15.9 + * it under the terms of the GNU General Public License as published by
15.10 + * the Free Software Foundation, version 2 of the License.
15.11 + *
15.12 + * This program is distributed in the hope that it will be useful,
15.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
15.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15.15 + * GNU General Public License for more details.
15.16 + *
15.17 + * You should have received a copy of the GNU General Public License
15.18 + * along with this program. Look for COPYING file in the top folder.
15.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
15.20 + */
15.21 +package org.apidesign.bck2brwsr.htmlpage.api;
15.22 +
15.23 +/**
15.24 + *
15.25 + * @author Jaroslav Tulach <jtulach@netbeans.org>
15.26 + */
15.27 +public final class Button extends Element {
15.28 + public Button(String id) {
15.29 + super(id);
15.30 + }
15.31 +
15.32 + @Override
15.33 + void dontSubclass() {
15.34 + }
15.35 +
15.36 + public void setDisabled(boolean state) {
15.37 + setAttribute(this, "disabled", state);
15.38 + }
15.39 +}
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
16.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Canvas.java Thu May 02 09:18:22 2013 +0200
16.3 @@ -0,0 +1,64 @@
16.4 +/**
16.5 + * Back 2 Browser Bytecode Translator
16.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
16.7 + *
16.8 + * This program is free software: you can redistribute it and/or modify
16.9 + * it under the terms of the GNU General Public License as published by
16.10 + * the Free Software Foundation, version 2 of the License.
16.11 + *
16.12 + * This program is distributed in the hope that it will be useful,
16.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
16.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16.15 + * GNU General Public License for more details.
16.16 + *
16.17 + * You should have received a copy of the GNU General Public License
16.18 + * along with this program. Look for COPYING file in the top folder.
16.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
16.20 + */
16.21 +package org.apidesign.bck2brwsr.htmlpage.api;
16.22 +
16.23 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
16.24 +import static org.apidesign.bck2brwsr.htmlpage.api.Element.getAttribute;
16.25 +
16.26 +/**
16.27 + *
16.28 + * @author Anton Epple <toni.epple@eppleton.de>
16.29 + */
16.30 +public class Canvas extends Element {
16.31 +
16.32 + public Canvas(String id) {
16.33 + super(id);
16.34 + }
16.35 +
16.36 + public void setHeight(int height) {
16.37 + setAttribute(this, "height", height);
16.38 + }
16.39 +
16.40 + public int getHeight() {
16.41 + Object ret = getAttribute(this, "height");
16.42 + return (ret instanceof Number) ? ((Number)ret).intValue(): Integer.MIN_VALUE;
16.43 + }
16.44 +
16.45 + public void setWidth(int width) {
16.46 + setAttribute(this, "width", width);
16.47 + }
16.48 +
16.49 + public int getWidth() {
16.50 + Object ret = getAttribute(this, "width");
16.51 + return (ret instanceof Number) ? ((Number)ret).intValue(): Integer.MIN_VALUE;
16.52 + }
16.53 +
16.54 + @JavaScriptBody(
16.55 + args = {"el"},
16.56 + body = "var e = window.document.getElementById(el._id());\n"
16.57 + + "return e.getContext('2d');\n")
16.58 + private native static Object getContextImpl(Canvas el);
16.59 +
16.60 + public GraphicsContext getContext() {
16.61 + return new GraphicsContext(getContextImpl(this));
16.62 + }
16.63 +
16.64 + @Override
16.65 + void dontSubclass() {
16.66 + }
16.67 +}
17.1 --- a/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/ComputedProperty.java Tue Apr 02 15:40:51 2013 +0200
17.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/ComputedProperty.java Thu May 02 09:18:22 2013 +0200
17.3 @@ -22,16 +22,11 @@
17.4 import java.lang.annotation.RetentionPolicy;
17.5 import java.lang.annotation.Target;
17.6
17.7 -/** Can be used in classes annotated with {@link Page} annotation to
17.8 - * define a derived property. Value of derived property is based on values
17.9 - * of {@link Property} as enumerated by {@link Page#properties()}.
17.10 - * <p>
17.11 - * The name of the derived property is the name of the method. The arguments
17.12 - * of the method define the property names (from {@link Page#properties()} list)
17.13 - * the value of property depends on.
17.14 - *
17.15 +/**
17.16 + * @deprecated Replaced by new {@link net.java.html.json.ComputedProperty net.java.html.json} API.
17.17 * @author Jaroslav Tulach <jtulach@netbeans.org>
17.18 */
17.19 +@Deprecated
17.20 @Retention(RetentionPolicy.SOURCE)
17.21 @Target(ElementType.METHOD)
17.22 public @interface ComputedProperty {
18.1 --- a/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Element.java Tue Apr 02 15:40:51 2013 +0200
18.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Element.java Thu May 02 09:18:22 2013 +0200
18.3 @@ -37,13 +37,7 @@
18.4 return id;
18.5 }
18.6
18.7 - public String getText() {
18.8 - return (String)getAttribute("innerHTML");
18.9 - }
18.10 -
18.11 - public void setText(String text) {
18.12 - setAttribute("innerHTML", text);
18.13 - }
18.14 + abstract void dontSubclass();
18.15
18.16 @JavaScriptBody(
18.17 args={"el", "property", "value"},
19.1 --- a/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/GraphicsContext.java Tue Apr 02 15:40:51 2013 +0200
19.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/GraphicsContext.java Thu May 02 09:18:22 2013 +0200
19.3 @@ -27,7 +27,7 @@
19.4
19.5 Object context;
19.6
19.7 - public GraphicsContext(Object contextImpl) {
19.8 + GraphicsContext(Object contextImpl) {
19.9 this.context = contextImpl;
19.10 }
19.11
19.12 @@ -113,15 +113,15 @@
19.13 @JavaScriptBody(args = {"x", "y"}, body = "this._context().scale(x,y);")
19.14 public native void scale(double x, double y);
19.15
19.16 - public void drawImage(Element image, double x, double y) {
19.17 + public void drawImage(Image image, double x, double y) {
19.18 drawImageImpl(context, Element.getElementById(image), x, y);
19.19 }
19.20
19.21 - public void drawImage(Element image, double x, double y, double width, double height) {
19.22 + public void drawImage(Image image, double x, double y, double width, double height) {
19.23 drawImageImpl(context, Element.getElementById(image), x, y, width, height);
19.24 }
19.25
19.26 - public void drawImage(Element image, double sx, double sy, double sWidth, double sHeight, double x, double y, double width, double height) {
19.27 + public void drawImage(Image image, double sx, double sy, double sWidth, double sHeight, double x, double y, double width, double height) {
19.28 drawImageImpl(context, Element.getElementById(image), sx, sy, sWidth, sHeight, x, y, width, height);
19.29 }
19.30
19.31 @@ -319,12 +319,12 @@
19.32 @JavaScriptBody(args = {"context", "x0", "y0", "x1", "y1"}, body = "return context.createLinearGradient(x0,y0,x1,y1);")
19.33 private native Object createLinearGradientImpl(Object context, double x0, double y0, double x1, double y1);
19.34
19.35 - public Pattern createPattern(Element image, String repeat) {
19.36 + public Pattern createPattern(Image image, String repeat) {
19.37 return new Pattern(createPatternImpl(context, image, repeat));
19.38 }
19.39
19.40 @JavaScriptBody(args = {"context", "image", "repeat"}, body = "return context.createPattern(image, repeat);")
19.41 - private static native Object createPatternImpl(Object context, Element image, String repeat);
19.42 + private static native Object createPatternImpl(Object context, Image image, String repeat);
19.43
19.44 public RadialGradient createRadialGradient(double x0, double y0, double r0, double x1, double y1, double r1) {
19.45 return new RadialGradient(createRadialGradientImpl(context, x0, y0, r0, x1, y1, r1));
20.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
20.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Image.java Thu May 02 09:18:22 2013 +0200
20.3 @@ -0,0 +1,36 @@
20.4 +/**
20.5 + * Back 2 Browser Bytecode Translator
20.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
20.7 + *
20.8 + * This program is free software: you can redistribute it and/or modify
20.9 + * it under the terms of the GNU General Public License as published by
20.10 + * the Free Software Foundation, version 2 of the License.
20.11 + *
20.12 + * This program is distributed in the hope that it will be useful,
20.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
20.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20.15 + * GNU General Public License for more details.
20.16 + *
20.17 + * You should have received a copy of the GNU General Public License
20.18 + * along with this program. Look for COPYING file in the top folder.
20.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
20.20 + */
20.21 +package org.apidesign.bck2brwsr.htmlpage.api;
20.22 +
20.23 +/**
20.24 + *
20.25 + * @author Anton Epple <toni.epple@eppleton.de>
20.26 + */
20.27 +public class Image extends Element{
20.28 +
20.29 + public Image(String id) {
20.30 + super(id);
20.31 + }
20.32 +
20.33 +
20.34 +
20.35 + @Override
20.36 + void dontSubclass() {
20.37 + }
20.38 +
20.39 +}
21.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
21.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Input.java Thu May 02 09:18:22 2013 +0200
21.3 @@ -0,0 +1,44 @@
21.4 +/**
21.5 + * Back 2 Browser Bytecode Translator
21.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
21.7 + *
21.8 + * This program is free software: you can redistribute it and/or modify
21.9 + * it under the terms of the GNU General Public License as published by
21.10 + * the Free Software Foundation, version 2 of the License.
21.11 + *
21.12 + * This program is distributed in the hope that it will be useful,
21.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
21.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21.15 + * GNU General Public License for more details.
21.16 + *
21.17 + * You should have received a copy of the GNU General Public License
21.18 + * along with this program. Look for COPYING file in the top folder.
21.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
21.20 + */
21.21 +package org.apidesign.bck2brwsr.htmlpage.api;
21.22 +
21.23 +/**
21.24 + *
21.25 + * @author Jaroslav Tulach <jtulach@netbeans.org>
21.26 + */
21.27 +public final class Input extends Element {
21.28 + public Input(String id) {
21.29 + super(id);
21.30 + }
21.31 +
21.32 + @Override
21.33 + void dontSubclass() {
21.34 + }
21.35 +
21.36 + public void setAutocomplete(boolean state) {
21.37 + setAttribute(this, "autocomplete", state);
21.38 + }
21.39 +
21.40 + public final String getValue() {
21.41 + return (String)getAttribute(this, "value");
21.42 + }
21.43 +
21.44 + public final void setValue(String txt) {
21.45 + setAttribute(this, "value", txt);
21.46 + }
21.47 +}
22.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
22.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Model.java Thu May 02 09:18:22 2013 +0200
22.3 @@ -0,0 +1,38 @@
22.4 +/**
22.5 + * Back 2 Browser Bytecode Translator
22.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
22.7 + *
22.8 + * This program is free software: you can redistribute it and/or modify
22.9 + * it under the terms of the GNU General Public License as published by
22.10 + * the Free Software Foundation, version 2 of the License.
22.11 + *
22.12 + * This program is distributed in the hope that it will be useful,
22.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
22.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22.15 + * GNU General Public License for more details.
22.16 + *
22.17 + * You should have received a copy of the GNU General Public License
22.18 + * along with this program. Look for COPYING file in the top folder.
22.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
22.20 + */
22.21 +package org.apidesign.bck2brwsr.htmlpage.api;
22.22 +
22.23 +import java.lang.annotation.ElementType;
22.24 +import java.lang.annotation.Retention;
22.25 +import java.lang.annotation.RetentionPolicy;
22.26 +import java.lang.annotation.Target;
22.27 +
22.28 +/**
22.29 + * @deprecated Replaced by new {@link net.java.html.json.Model net.java.html.json} API.
22.30 + * @author Jaroslav Tulach <jtulach@netbeans.org>
22.31 + */
22.32 +@Retention(RetentionPolicy.SOURCE)
22.33 +@Target(ElementType.TYPE)
22.34 +@Deprecated
22.35 +public @interface Model {
22.36 + /** Name of the model class */
22.37 + String className();
22.38 + /** List of properties in the model.
22.39 + */
22.40 + Property[] properties();
22.41 +}
23.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
23.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/OnFunction.java Thu May 02 09:18:22 2013 +0200
23.3 @@ -0,0 +1,33 @@
23.4 +/**
23.5 + * Back 2 Browser Bytecode Translator
23.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
23.7 + *
23.8 + * This program is free software: you can redistribute it and/or modify
23.9 + * it under the terms of the GNU General Public License as published by
23.10 + * the Free Software Foundation, version 2 of the License.
23.11 + *
23.12 + * This program is distributed in the hope that it will be useful,
23.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
23.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23.15 + * GNU General Public License for more details.
23.16 + *
23.17 + * You should have received a copy of the GNU General Public License
23.18 + * along with this program. Look for COPYING file in the top folder.
23.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
23.20 + */
23.21 +package org.apidesign.bck2brwsr.htmlpage.api;
23.22 +
23.23 +import java.lang.annotation.ElementType;
23.24 +import java.lang.annotation.Retention;
23.25 +import java.lang.annotation.RetentionPolicy;
23.26 +import java.lang.annotation.Target;
23.27 +
23.28 +/**
23.29 + * @deprecated Replaced by new {@link net.java.html.json.Function net.java.html.json} API.
23.30 + * @author Jaroslav Tulach <jtulach@netbeans.org>
23.31 + */
23.32 +@Target(ElementType.METHOD)
23.33 +@Retention(RetentionPolicy.SOURCE)
23.34 +@Deprecated
23.35 +public @interface OnFunction {
23.36 +}
24.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
24.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/OnPropertyChange.java Thu May 02 09:18:22 2013 +0200
24.3 @@ -0,0 +1,38 @@
24.4 +/**
24.5 + * Back 2 Browser Bytecode Translator
24.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
24.7 + *
24.8 + * This program is free software: you can redistribute it and/or modify
24.9 + * it under the terms of the GNU General Public License as published by
24.10 + * the Free Software Foundation, version 2 of the License.
24.11 + *
24.12 + * This program is distributed in the hope that it will be useful,
24.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
24.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24.15 + * GNU General Public License for more details.
24.16 + *
24.17 + * You should have received a copy of the GNU General Public License
24.18 + * along with this program. Look for COPYING file in the top folder.
24.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
24.20 + */
24.21 +package org.apidesign.bck2brwsr.htmlpage.api;
24.22 +
24.23 +import java.lang.annotation.ElementType;
24.24 +import java.lang.annotation.Retention;
24.25 +import java.lang.annotation.RetentionPolicy;
24.26 +import java.lang.annotation.Target;
24.27 +
24.28 +/**
24.29 + * @deprecated Replaced by new {@link net.java.html.json.OnPropertyChange net.java.html.json} API.
24.30 + * @author Jaroslav Tulach <jtulach@netbeans.org>
24.31 + */
24.32 +@Retention(RetentionPolicy.SOURCE)
24.33 +@Target(ElementType.METHOD)
24.34 +@Deprecated
24.35 +public @interface OnPropertyChange {
24.36 + /** Name(s) of the properties. One wishes to observe.
24.37 + *
24.38 + * @return valid java identifier
24.39 + */
24.40 + String[] value();
24.41 +}
25.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
25.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/OnReceive.java Thu May 02 09:18:22 2013 +0200
25.3 @@ -0,0 +1,53 @@
25.4 +/**
25.5 + * Back 2 Browser Bytecode Translator
25.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
25.7 + *
25.8 + * This program is free software: you can redistribute it and/or modify
25.9 + * it under the terms of the GNU General Public License as published by
25.10 + * the Free Software Foundation, version 2 of the License.
25.11 + *
25.12 + * This program is distributed in the hope that it will be useful,
25.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
25.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25.15 + * GNU General Public License for more details.
25.16 + *
25.17 + * You should have received a copy of the GNU General Public License
25.18 + * along with this program. Look for COPYING file in the top folder.
25.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
25.20 + */
25.21 +package org.apidesign.bck2brwsr.htmlpage.api;
25.22 +
25.23 +import java.lang.annotation.ElementType;
25.24 +import java.lang.annotation.Retention;
25.25 +import java.lang.annotation.RetentionPolicy;
25.26 +import java.lang.annotation.Target;
25.27 +
25.28 +/**
25.29 + * @deprecated Replaced by new {@link net.java.html.json.OnReceive net.java.html.json} API.
25.30 + * @author Jaroslav Tulach <jtulach@netbeans.org>
25.31 + * @since 0.6
25.32 + */
25.33 +@Retention(RetentionPolicy.SOURCE)
25.34 +@Target(ElementType.METHOD)
25.35 +@Deprecated
25.36 +public @interface OnReceive {
25.37 + /** The URL to connect to. Can contain variable names surrounded by '{' and '}'.
25.38 + * Those parameters will then become variables of the associated method.
25.39 + *
25.40 + * @return the (possibly parametrized) url to connect to
25.41 + */
25.42 + String url();
25.43 +
25.44 + /** Support for <a href="http://en.wikipedia.org/wiki/JSONP">JSONP</a> requires
25.45 + * a callback from the server generated page to a function defined in the
25.46 + * system. The name of such function is usually specified as a property
25.47 + * (of possibly different names). By defining the <code>jsonp</code> attribute
25.48 + * one turns on the <a href="http://en.wikipedia.org/wiki/JSONP">JSONP</a>
25.49 + * transmission and specifies the name of the property. The property should
25.50 + * also be used in the {@link #url()} attribute on appropriate place.
25.51 + *
25.52 + * @return name of a property to carry the name of <a href="http://en.wikipedia.org/wiki/JSONP">JSONP</a>
25.53 + * callback function.
25.54 + */
25.55 + String jsonp() default "";
25.56 +}
26.1 --- a/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Property.java Tue Apr 02 15:40:51 2013 +0200
26.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Property.java Thu May 02 09:18:22 2013 +0200
26.3 @@ -20,15 +20,36 @@
26.4 import java.lang.annotation.Retention;
26.5 import java.lang.annotation.RetentionPolicy;
26.6 import java.lang.annotation.Target;
26.7 +import java.util.List;
26.8
26.9 -/** Represents a property in a generated model of an HTML
26.10 - * {@link Page}.
26.11 - *
26.12 +/**
26.13 + * @deprecated Replaced by new {@link net.java.html.json.Property net.java.html.json} API.
26.14 * @author Jaroslav Tulach <jtulach@netbeans.org>
26.15 */
26.16 @Retention(RetentionPolicy.SOURCE)
26.17 @Target({})
26.18 +@Deprecated
26.19 public @interface Property {
26.20 + /** Name of the property. Will be used to define proper getter and setter
26.21 + * in the associated class.
26.22 + *
26.23 + * @return valid java identifier
26.24 + */
26.25 String name();
26.26 +
26.27 + /** Type of the property. Can either be primitive type (like <code>int.class</code>,
26.28 + * <code>double.class</code>, etc.), {@link String} or complex model
26.29 + * class (defined by {@link Model} property).
26.30 + *
26.31 + * @return the class of the property
26.32 + */
26.33 Class<?> type();
26.34 +
26.35 + /** Is this property an array of the {@link #type()} or a single value?
26.36 + * If the property is an array, only its getter (returning mutable {@link List} of
26.37 + * the boxed {@link #type()}).
26.38 + *
26.39 + * @return true, if this is supposed to be an array of values.
26.40 + */
26.41 + boolean array() default false;
26.42 }
27.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
27.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Title.java Thu May 02 09:18:22 2013 +0200
27.3 @@ -0,0 +1,36 @@
27.4 +/**
27.5 + * Back 2 Browser Bytecode Translator
27.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
27.7 + *
27.8 + * This program is free software: you can redistribute it and/or modify
27.9 + * it under the terms of the GNU General Public License as published by
27.10 + * the Free Software Foundation, version 2 of the License.
27.11 + *
27.12 + * This program is distributed in the hope that it will be useful,
27.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
27.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27.15 + * GNU General Public License for more details.
27.16 + *
27.17 + * You should have received a copy of the GNU General Public License
27.18 + * along with this program. Look for COPYING file in the top folder.
27.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
27.20 + */
27.21 +package org.apidesign.bck2brwsr.htmlpage.api;
27.22 +
27.23 +/**
27.24 + *
27.25 + * @author Jaroslav Tulach <jtulach@netbeans.org>
27.26 + */
27.27 +public class Title extends Element {
27.28 + public Title(String id) {
27.29 + super(id);
27.30 + }
27.31 +
27.32 + @Override
27.33 + void dontSubclass() {
27.34 + }
27.35 +
27.36 + public final void setText(String text) {
27.37 + setAttribute(this, "innerHTML", text);
27.38 + }
27.39 +}
28.1 --- a/javaquery/api/src/main/resources/org/apidesign/bck2brwsr/htmlpage/knockout-2.2.1.js Tue Apr 02 15:40:51 2013 +0200
28.2 +++ b/javaquery/api/src/main/resources/org/apidesign/bck2brwsr/htmlpage/knockout-2.2.1.js Thu May 02 09:18:22 2013 +0200
28.3 @@ -2193,7 +2193,14 @@
28.4 else
28.5 element[attrName] = attrValue;
28.6 } else if (!toRemove) {
28.7 - element.setAttribute(attrName, attrValue.toString());
28.8 + try {
28.9 + element.setAttribute(attrName, attrValue.toString());
28.10 + } catch (err) {
28.11 + // ignore for now
28.12 + if (console) {
28.13 + console.log("Can't set attribute " + attrName + " to " + attrValue + " error: " + err);
28.14 + }
28.15 + }
28.16 }
28.17
28.18 // Treat "name" specially - although you can think of it as an attribute, it also needs
29.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
29.2 +++ b/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/Compile.java Thu May 02 09:18:22 2013 +0200
29.3 @@ -0,0 +1,216 @@
29.4 +/**
29.5 + * Back 2 Browser Bytecode Translator
29.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
29.7 + *
29.8 + * This program is free software: you can redistribute it and/or modify
29.9 + * it under the terms of the GNU General Public License as published by
29.10 + * the Free Software Foundation, version 2 of the License.
29.11 + *
29.12 + * This program is distributed in the hope that it will be useful,
29.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
29.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29.15 + * GNU General Public License for more details.
29.16 + *
29.17 + * You should have received a copy of the GNU General Public License
29.18 + * along with this program. Look for COPYING file in the top folder.
29.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
29.20 + */
29.21 +package org.apidesign.bck2brwsr.htmlpage;
29.22 +
29.23 +import java.io.ByteArrayInputStream;
29.24 +import java.io.ByteArrayOutputStream;
29.25 +import java.io.IOException;
29.26 +import java.io.InputStream;
29.27 +import java.io.OutputStream;
29.28 +import java.net.URI;
29.29 +import java.net.URISyntaxException;
29.30 +import java.util.ArrayList;
29.31 +import java.util.Arrays;
29.32 +import java.util.HashMap;
29.33 +import java.util.List;
29.34 +import java.util.Map;
29.35 +import java.util.regex.Matcher;
29.36 +import java.util.regex.Pattern;
29.37 +import javax.tools.Diagnostic;
29.38 +import javax.tools.DiagnosticListener;
29.39 +import javax.tools.FileObject;
29.40 +import javax.tools.ForwardingJavaFileManager;
29.41 +import javax.tools.JavaFileManager;
29.42 +import javax.tools.JavaFileObject;
29.43 +import javax.tools.JavaFileObject.Kind;
29.44 +import javax.tools.SimpleJavaFileObject;
29.45 +import javax.tools.StandardJavaFileManager;
29.46 +import javax.tools.StandardLocation;
29.47 +import javax.tools.ToolProvider;
29.48 +
29.49 +/**
29.50 + *
29.51 + * @author Jaroslav Tulach <jtulach@netbeans.org>
29.52 + */
29.53 +final class Compile implements DiagnosticListener<JavaFileObject> {
29.54 + private final List<Diagnostic<? extends JavaFileObject>> errors = new ArrayList<>();
29.55 + private final Map<String, byte[]> classes;
29.56 + private final String pkg;
29.57 + private final String cls;
29.58 + private final String html;
29.59 +
29.60 + private Compile(String html, String code) throws IOException {
29.61 + this.pkg = findPkg(code);
29.62 + this.cls = findCls(code);
29.63 + this.html = html;
29.64 + classes = compile(html, code);
29.65 + }
29.66 +
29.67 + /** Performs compilation of given HTML page and associated Java code
29.68 + */
29.69 + public static Compile create(String html, String code) throws IOException {
29.70 + return new Compile(html, code);
29.71 + }
29.72 +
29.73 + /** Checks for given class among compiled resources */
29.74 + public byte[] get(String res) {
29.75 + return classes.get(res);
29.76 + }
29.77 +
29.78 + /** Obtains errors created during compilation.
29.79 + */
29.80 + public List<Diagnostic<? extends JavaFileObject>> getErrors() {
29.81 + List<Diagnostic<? extends JavaFileObject>> err = new ArrayList<>();
29.82 + for (Diagnostic<? extends JavaFileObject> diagnostic : errors) {
29.83 + if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
29.84 + err.add(diagnostic);
29.85 + }
29.86 + }
29.87 + return err;
29.88 + }
29.89 +
29.90 + private Map<String, byte[]> compile(final String html, final String code) throws IOException {
29.91 + StandardJavaFileManager sjfm = ToolProvider.getSystemJavaCompiler().getStandardFileManager(this, null, null);
29.92 +
29.93 + final Map<String, ByteArrayOutputStream> class2BAOS = new HashMap<>();
29.94 +
29.95 + JavaFileObject file = new SimpleJavaFileObject(URI.create("mem://mem"), Kind.SOURCE) {
29.96 + @Override
29.97 + public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
29.98 + return code;
29.99 + }
29.100 + };
29.101 + final JavaFileObject htmlFile = new SimpleJavaFileObject(URI.create("mem://mem2"), Kind.OTHER) {
29.102 + @Override
29.103 + public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
29.104 + return html;
29.105 + }
29.106 +
29.107 + @Override
29.108 + public InputStream openInputStream() throws IOException {
29.109 + return new ByteArrayInputStream(html.getBytes());
29.110 + }
29.111 + };
29.112 +
29.113 + final URI scratch;
29.114 + try {
29.115 + scratch = new URI("mem://mem3");
29.116 + } catch (URISyntaxException ex) {
29.117 + throw new IOException(ex);
29.118 + }
29.119 +
29.120 + JavaFileManager jfm = new ForwardingJavaFileManager<JavaFileManager>(sjfm) {
29.121 + @Override
29.122 + public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) throws IOException {
29.123 + if (kind == Kind.CLASS) {
29.124 + final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
29.125 +
29.126 + class2BAOS.put(className.replace('.', '/') + ".class", buffer);
29.127 + return new SimpleJavaFileObject(sibling.toUri(), kind) {
29.128 + @Override
29.129 + public OutputStream openOutputStream() throws IOException {
29.130 + return buffer;
29.131 + }
29.132 + };
29.133 + }
29.134 +
29.135 + if (kind == Kind.SOURCE) {
29.136 + return new SimpleJavaFileObject(scratch/*sibling.toUri()*/, kind) {
29.137 + private final ByteArrayOutputStream data = new ByteArrayOutputStream();
29.138 + @Override
29.139 + public OutputStream openOutputStream() throws IOException {
29.140 + return data;
29.141 + }
29.142 +
29.143 + @Override
29.144 + public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
29.145 + data.close();
29.146 + return new String(data.toByteArray());
29.147 + }
29.148 + };
29.149 + }
29.150 +
29.151 + throw new IllegalStateException();
29.152 + }
29.153 +
29.154 + @Override
29.155 + public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException {
29.156 + if (location == StandardLocation.SOURCE_PATH) {
29.157 + if (packageName.equals(pkg)) {
29.158 + return htmlFile;
29.159 + }
29.160 + }
29.161 +
29.162 + return null;
29.163 + }
29.164 +
29.165 + @Override
29.166 + public boolean isSameFile(FileObject a, FileObject b) {
29.167 + if (a == null || b == null) {
29.168 + throw new NullPointerException();
29.169 + }
29.170 + if (!(a instanceof SimpleJavaFileObject)) {
29.171 + throw new IllegalArgumentException("Not supported: " + a);
29.172 + }
29.173 + if (!(b instanceof SimpleJavaFileObject)) {
29.174 + throw new IllegalArgumentException("Not supported: " + b);
29.175 + }
29.176 + return a.equals(b);
29.177 + }
29.178 + };
29.179 +
29.180 + ToolProvider.getSystemJavaCompiler().getTask(null, jfm, this, /*XXX:*/Arrays.asList("-source", "1.7", "-target", "1.7"), null, Arrays.asList(file)).call();
29.181 +
29.182 + Map<String, byte[]> result = new HashMap<>();
29.183 +
29.184 + for (Map.Entry<String, ByteArrayOutputStream> e : class2BAOS.entrySet()) {
29.185 + result.put(e.getKey(), e.getValue().toByteArray());
29.186 + }
29.187 +
29.188 + return result;
29.189 + }
29.190 +
29.191 +
29.192 + @Override
29.193 + public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
29.194 + errors.add(diagnostic);
29.195 + }
29.196 + private static String findPkg(String java) throws IOException {
29.197 + Pattern p = Pattern.compile("package\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}*;", Pattern.MULTILINE);
29.198 + Matcher m = p.matcher(java);
29.199 + if (!m.find()) {
29.200 + throw new IOException("Can't find package declaration in the java file");
29.201 + }
29.202 + String pkg = m.group(1);
29.203 + return pkg;
29.204 + }
29.205 + private static String findCls(String java) throws IOException {
29.206 + Pattern p = Pattern.compile("class\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}", Pattern.MULTILINE);
29.207 + Matcher m = p.matcher(java);
29.208 + if (!m.find()) {
29.209 + throw new IOException("Can't find package declaration in the java file");
29.210 + }
29.211 + String cls = m.group(1);
29.212 + return cls;
29.213 + }
29.214 +
29.215 + String getHtml() {
29.216 + String fqn = "'" + pkg + '.' + cls + "'";
29.217 + return html.replace("'${fqn}'", fqn);
29.218 + }
29.219 +}
30.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
30.2 +++ b/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/ConvertTypesTest.java Thu May 02 09:18:22 2013 +0200
30.3 @@ -0,0 +1,63 @@
30.4 +/**
30.5 + * Back 2 Browser Bytecode Translator
30.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
30.7 + *
30.8 + * This program is free software: you can redistribute it and/or modify
30.9 + * it under the terms of the GNU General Public License as published by
30.10 + * the Free Software Foundation, version 2 of the License.
30.11 + *
30.12 + * This program is distributed in the hope that it will be useful,
30.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
30.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30.15 + * GNU General Public License for more details.
30.16 + *
30.17 + * You should have received a copy of the GNU General Public License
30.18 + * along with this program. Look for COPYING file in the top folder.
30.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
30.20 + */
30.21 +package org.apidesign.bck2brwsr.htmlpage;
30.22 +
30.23 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
30.24 +import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
30.25 +import org.apidesign.bck2brwsr.vmtest.VMTest;
30.26 +import org.testng.annotations.Factory;
30.27 +
30.28 +/**
30.29 + *
30.30 + * @author Jaroslav Tulach <jtulach@netbeans.org>
30.31 + */
30.32 +public class ConvertTypesTest {
30.33 + @JavaScriptBody(args = { "includeSex" }, body = "var json = new Object();"
30.34 + + "json.firstName = 'son';\n"
30.35 + + "json.lastName = 'dj';\n"
30.36 + + "if (includeSex) json.sex = 'MALE';\n"
30.37 + + "return json;"
30.38 + )
30.39 + private static native Object createJSON(boolean includeSex);
30.40 +
30.41 + @BrwsrTest
30.42 + public void testConvertToPeople() throws Exception {
30.43 + final Object o = createJSON(true);
30.44 +
30.45 + Person p = new Person(o);
30.46 +
30.47 + assert "son".equals(p.getFirstName()) : "First name: " + p.getFirstName();
30.48 + assert "dj".equals(p.getLastName()) : "Last name: " + p.getLastName();
30.49 + assert Sex.MALE.equals(p.getSex()) : "Sex: " + p.getSex();
30.50 + }
30.51 +
30.52 + @BrwsrTest
30.53 + public void testConvertToPeopleWithoutSex() throws Exception {
30.54 + final Object o = createJSON(false);
30.55 +
30.56 + Person p = new Person(o);
30.57 +
30.58 + assert "son".equals(p.getFirstName()) : "First name: " + p.getFirstName();
30.59 + assert "dj".equals(p.getLastName()) : "Last name: " + p.getLastName();
30.60 + assert p.getSex() == null : "No sex: " + p.getSex();
30.61 + }
30.62 +
30.63 + @Factory public static Object[] create() {
30.64 + return VMTest.create(ConvertTypesTest.class);
30.65 + }
30.66 +}
30.67 \ No newline at end of file
31.1 --- a/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/ElementGeneratorTest.java Tue Apr 02 15:40:51 2013 +0200
31.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
31.3 @@ -1,35 +0,0 @@
31.4 -/**
31.5 - * Back 2 Browser Bytecode Translator
31.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
31.7 - *
31.8 - * This program is free software: you can redistribute it and/or modify
31.9 - * it under the terms of the GNU General Public License as published by
31.10 - * the Free Software Foundation, version 2 of the License.
31.11 - *
31.12 - * This program is distributed in the hope that it will be useful,
31.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
31.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31.15 - * GNU General Public License for more details.
31.16 - *
31.17 - * You should have received a copy of the GNU General Public License
31.18 - * along with this program. Look for COPYING file in the top folder.
31.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
31.20 - */
31.21 -package org.apidesign.bck2brwsr.htmlpage;
31.22 -
31.23 -import java.util.Map;
31.24 -import static org.testng.Assert.*;
31.25 -import org.testng.annotations.Test;
31.26 -
31.27 -/**
31.28 - *
31.29 - * @author Jan Horvath <jhorvath@netbeans.org>
31.30 - */
31.31 -public class ElementGeneratorTest {
31.32 -
31.33 - @Test public void testGetAttributes() {
31.34 - ElementGenerator gen = new ElementGenerator(null);
31.35 - Map<String, String> attrs = gen.getAttributes("input");
31.36 - assertEquals(attrs.get("width"), "Integer", "Expected type of width attribute is Integer");
31.37 - }
31.38 -}
32.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
32.2 +++ b/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/JSONTest.java Thu May 02 09:18:22 2013 +0200
32.3 @@ -0,0 +1,392 @@
32.4 +/**
32.5 + * Back 2 Browser Bytecode Translator
32.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
32.7 + *
32.8 + * This program is free software: you can redistribute it and/or modify
32.9 + * it under the terms of the GNU General Public License as published by
32.10 + * the Free Software Foundation, version 2 of the License.
32.11 + *
32.12 + * This program is distributed in the hope that it will be useful,
32.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
32.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32.15 + * GNU General Public License for more details.
32.16 + *
32.17 + * You should have received a copy of the GNU General Public License
32.18 + * along with this program. Look for COPYING file in the top folder.
32.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
32.20 + */
32.21 +package org.apidesign.bck2brwsr.htmlpage;
32.22 +
32.23 +import java.util.Arrays;
32.24 +import java.util.Iterator;
32.25 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
32.26 +import org.apidesign.bck2brwsr.htmlpage.api.OnReceive;
32.27 +import org.apidesign.bck2brwsr.htmlpage.api.Page;
32.28 +import org.apidesign.bck2brwsr.htmlpage.api.Property;
32.29 +import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
32.30 +import org.apidesign.bck2brwsr.vmtest.Http;
32.31 +import org.apidesign.bck2brwsr.vmtest.VMTest;
32.32 +import org.json.JSONException;
32.33 +import org.json.JSONObject;
32.34 +import org.json.JSONTokener;
32.35 +import org.testng.annotations.Test;
32.36 +import static org.testng.Assert.*;
32.37 +import org.testng.annotations.Factory;
32.38 +
32.39 +/** Need to verify that models produce reasonable JSON objects.
32.40 + *
32.41 + * @author Jaroslav Tulach <jtulach@netbeans.org>
32.42 + */
32.43 +@Page(xhtml = "Empty.html", className = "JSONik", properties = {
32.44 + @Property(name = "fetched", type = PersonImpl.class),
32.45 + @Property(name = "fetchedCount", type = int.class),
32.46 + @Property(name = "fetchedSex", type = Sex.class, array = true)
32.47 +})
32.48 +public class JSONTest {
32.49 + private JSONik js;
32.50 + private Integer orig;
32.51 +
32.52 + @Test public void personToString() throws JSONException {
32.53 + Person p = new Person();
32.54 + p.setSex(Sex.MALE);
32.55 + p.setFirstName("Jarda");
32.56 + p.setLastName("Tulach");
32.57 +
32.58 + JSONTokener t = new JSONTokener(p.toString());
32.59 + JSONObject o;
32.60 + try {
32.61 + o = new JSONObject(t);
32.62 + } catch (JSONException ex) {
32.63 + throw new AssertionError("Can't parse " + p.toString(), ex);
32.64 + }
32.65 +
32.66 + Iterator it = o.sortedKeys();
32.67 + assertEquals(it.next(), "firstName");
32.68 + assertEquals(it.next(), "lastName");
32.69 + assertEquals(it.next(), "sex");
32.70 +
32.71 + assertEquals(o.getString("firstName"), "Jarda");
32.72 + assertEquals(o.getString("lastName"), "Tulach");
32.73 + assertEquals(o.getString("sex"), "MALE");
32.74 + }
32.75 +
32.76 + @BrwsrTest public void toJSONInABrowser() throws Throwable {
32.77 + Person p = new Person();
32.78 + p.setSex(Sex.MALE);
32.79 + p.setFirstName("Jarda");
32.80 + p.setLastName("Tulach");
32.81 +
32.82 + Object json;
32.83 + try {
32.84 + json = parseJSON(p.toString());
32.85 + } catch (Throwable ex) {
32.86 + throw new IllegalStateException("Can't parse " + p).initCause(ex);
32.87 + }
32.88 +
32.89 + Person p2 = new Person(json);
32.90 +
32.91 + assert p2.getFirstName().equals(p.getFirstName()) :
32.92 + "Should be the same: " + p.getFirstName() + " != " + p2.getFirstName();
32.93 + }
32.94 +
32.95 + @Test public void personWithWildCharactersAndNulls() throws JSONException {
32.96 + Person p = new Person();
32.97 + p.setFirstName("'\"\n");
32.98 + p.setLastName("\t\r\u0002");
32.99 +
32.100 + JSONTokener t = new JSONTokener(p.toString());
32.101 + JSONObject o;
32.102 + try {
32.103 + o = new JSONObject(t);
32.104 + } catch (JSONException ex) {
32.105 + throw new AssertionError("Can't parse " + p.toString(), ex);
32.106 + }
32.107 +
32.108 + Iterator it = o.sortedKeys();
32.109 + assertEquals(it.next(), "firstName");
32.110 + assertEquals(it.next(), "lastName");
32.111 + assertEquals(it.next(), "sex");
32.112 +
32.113 + assertEquals(o.getString("firstName"), p.getFirstName());
32.114 + assertEquals(o.getString("lastName"), p.getLastName());
32.115 + assertEquals(o.get("sex"), JSONObject.NULL);
32.116 + }
32.117 +
32.118 + @Test public void personsInArray() throws JSONException {
32.119 + Person p1 = new Person();
32.120 + p1.setFirstName("One");
32.121 +
32.122 + Person p2 = new Person();
32.123 + p2.setFirstName("Two");
32.124 +
32.125 + People arr = new People();
32.126 + arr.getInfo().add(p1);
32.127 + arr.getInfo().add(p2);
32.128 + arr.getNicknames().add("Prvn\u00ed k\u016f\u0148");
32.129 + final String n2 = "Druh\u00fd hlem\u00fd\u017e\u010f, star\u0161\u00ed";
32.130 + arr.getNicknames().add(n2);
32.131 + arr.getAge().add(33);
32.132 + arr.getAge().add(73);
32.133 +
32.134 +
32.135 + final String json = arr.toString();
32.136 +
32.137 + JSONTokener t = new JSONTokener(json);
32.138 + JSONObject o;
32.139 + try {
32.140 + o = new JSONObject(t);
32.141 + } catch (JSONException ex) {
32.142 + throw new AssertionError("Can't parse " + json, ex);
32.143 + }
32.144 +
32.145 + assertEquals(o.getJSONArray("info").getJSONObject(0).getString("firstName"), "One");
32.146 + assertEquals(o.getJSONArray("nicknames").getString(1), n2);
32.147 + assertEquals(o.getJSONArray("age").getInt(1), 73);
32.148 + }
32.149 +
32.150 +
32.151 + @OnReceive(url="/{url}")
32.152 + static void fetch(Person p, JSONik model) {
32.153 + model.setFetched(p);
32.154 + }
32.155 +
32.156 + @OnReceive(url="/{url}")
32.157 + static void fetchArray(Person[] p, JSONik model) {
32.158 + model.setFetchedCount(p.length);
32.159 + model.setFetched(p[0]);
32.160 + }
32.161 +
32.162 + @OnReceive(url="/{url}")
32.163 + static void fetchPeople(People p, JSONik model) {
32.164 + model.setFetchedCount(p.getInfo().size());
32.165 + model.setFetched(p.getInfo().get(0));
32.166 + }
32.167 +
32.168 + @OnReceive(url="/{url}")
32.169 + static void fetchPeopleAge(People p, JSONik model) {
32.170 + int sum = 0;
32.171 + for (int a : p.getAge()) {
32.172 + sum += a;
32.173 + }
32.174 + model.setFetchedCount(sum);
32.175 + }
32.176 +
32.177 + @Http(@Http.Resource(
32.178 + content = "{'firstName': 'Sitar', 'sex': 'MALE'}",
32.179 + path="/person.json",
32.180 + mimeType = "application/json"
32.181 + ))
32.182 + @BrwsrTest public void loadAndParseJSON() throws InterruptedException {
32.183 + if (js == null) {
32.184 + js = new JSONik();
32.185 + js.applyBindings();
32.186 +
32.187 + js.fetch("person.json");
32.188 + }
32.189 +
32.190 + Person p = js.getFetched();
32.191 + if (p == null) {
32.192 + throw new InterruptedException();
32.193 + }
32.194 +
32.195 + assert "Sitar".equals(p.getFirstName()) : "Expecting Sitar: " + p.getFirstName();
32.196 + assert Sex.MALE.equals(p.getSex()) : "Expecting MALE: " + p.getSex();
32.197 + }
32.198 +
32.199 + @OnReceive(url="/{url}?callme={me}", jsonp = "me")
32.200 + static void fetchViaJSONP(Person p, JSONik model) {
32.201 + model.setFetched(p);
32.202 + }
32.203 +
32.204 + @Http(@Http.Resource(
32.205 + content = "$0({'firstName': 'Mitar', 'sex': 'MALE'})",
32.206 + path="/person.json",
32.207 + mimeType = "application/javascript",
32.208 + parameters = { "callme" }
32.209 + ))
32.210 + @BrwsrTest public void loadAndParseJSONP() throws InterruptedException {
32.211 +
32.212 + if (js == null) {
32.213 + orig = scriptElements();
32.214 + assert orig > 0 : "There should be some scripts on the page";
32.215 +
32.216 + js = new JSONik();
32.217 + js.applyBindings();
32.218 +
32.219 + js.fetchViaJSONP("person.json");
32.220 + }
32.221 +
32.222 + Person p = js.getFetched();
32.223 + if (p == null) {
32.224 + throw new InterruptedException();
32.225 + }
32.226 +
32.227 + assert "Mitar".equals(p.getFirstName()) : "Unexpected: " + p.getFirstName();
32.228 + assert Sex.MALE.equals(p.getSex()) : "Expecting MALE: " + p.getSex();
32.229 +
32.230 + int now = scriptElements();
32.231 +
32.232 + assert orig == now : "The set of elements is unchanged. Delta: " + (now - orig);
32.233 + }
32.234 +
32.235 + @JavaScriptBody(args = { }, body = "return window.document.getElementsByTagName('script').length;")
32.236 + private static native int scriptElements();
32.237 +
32.238 + @JavaScriptBody(args = { "s" }, body = "return window.JSON.parse(s);")
32.239 + private static native Object parseJSON(String s);
32.240 +
32.241 + @Http(@Http.Resource(
32.242 + content = "{'firstName': 'Sitar', 'sex': 'MALE'}",
32.243 + path="/person.json",
32.244 + mimeType = "application/json"
32.245 + ))
32.246 + @BrwsrTest public void loadAndParseJSONSentToArray() throws InterruptedException {
32.247 + if (js == null) {
32.248 + js = new JSONik();
32.249 + js.applyBindings();
32.250 +
32.251 + js.fetchArray("person.json");
32.252 + }
32.253 +
32.254 + Person p = js.getFetched();
32.255 + if (p == null) {
32.256 + throw new InterruptedException();
32.257 + }
32.258 +
32.259 + assert p != null : "We should get our person back: " + p;
32.260 + assert "Sitar".equals(p.getFirstName()) : "Expecting Sitar: " + p.getFirstName();
32.261 + assert Sex.MALE.equals(p.getSex()) : "Expecting MALE: " + p.getSex();
32.262 + }
32.263 +
32.264 + @Http(@Http.Resource(
32.265 + content = "[{'firstName': 'Gitar', 'sex': 'FEMALE'}]",
32.266 + path="/person.json",
32.267 + mimeType = "application/json"
32.268 + ))
32.269 + @BrwsrTest public void loadAndParseJSONArraySingle() throws InterruptedException {
32.270 + if (js == null) {
32.271 + js = new JSONik();
32.272 + js.applyBindings();
32.273 +
32.274 + js.fetch("person.json");
32.275 + }
32.276 +
32.277 + Person p = js.getFetched();
32.278 + if (p == null) {
32.279 + throw new InterruptedException();
32.280 + }
32.281 +
32.282 + assert p != null : "We should get our person back: " + p;
32.283 + assert "Gitar".equals(p.getFirstName()) : "Expecting Gitar: " + p.getFirstName();
32.284 + assert Sex.FEMALE.equals(p.getSex()) : "Expecting FEMALE: " + p.getSex();
32.285 + }
32.286 +
32.287 + @Http(@Http.Resource(
32.288 + content = "{'info':[{'firstName': 'Gitar', 'sex': 'FEMALE'}]}",
32.289 + path="/people.json",
32.290 + mimeType = "application/json"
32.291 + ))
32.292 + @BrwsrTest public void loadAndParseArrayInPeople() throws InterruptedException {
32.293 + if (js == null) {
32.294 + js = new JSONik();
32.295 + js.applyBindings();
32.296 +
32.297 + js.fetchPeople("people.json");
32.298 + }
32.299 +
32.300 + if (0 == js.getFetchedCount()) {
32.301 + throw new InterruptedException();
32.302 + }
32.303 +
32.304 + assert js.getFetchedCount() == 1 : "One person loaded: " + js.getFetchedCount();
32.305 +
32.306 + Person p = js.getFetched();
32.307 +
32.308 + assert p != null : "We should get our person back: " + p;
32.309 + assert "Gitar".equals(p.getFirstName()) : "Expecting Gitar: " + p.getFirstName();
32.310 + assert Sex.FEMALE.equals(p.getSex()) : "Expecting FEMALE: " + p.getSex();
32.311 + }
32.312 +
32.313 + @Http(@Http.Resource(
32.314 + content = "{'age':[1, 2, 3]}",
32.315 + path="/people.json",
32.316 + mimeType = "application/json"
32.317 + ))
32.318 + @BrwsrTest public void loadAndParseArrayOfIntegers() throws InterruptedException {
32.319 + if (js == null) {
32.320 + js = new JSONik();
32.321 + js.applyBindings();
32.322 +
32.323 + js.fetchPeopleAge("people.json");
32.324 + }
32.325 +
32.326 + if (0 == js.getFetchedCount()) {
32.327 + throw new InterruptedException();
32.328 + }
32.329 +
32.330 + assert js.getFetchedCount() == 6 : "1 + 2 + 3 is " + js.getFetchedCount();
32.331 + }
32.332 +
32.333 + @OnReceive(url="/{url}")
32.334 + static void fetchPeopleSex(People p, JSONik model) {
32.335 + model.setFetchedCount(1);
32.336 + model.getFetchedSex().addAll(p.getSex());
32.337 + }
32.338 +
32.339 +
32.340 + @Http(@Http.Resource(
32.341 + content = "{'sex':['FEMALE', 'MALE', 'MALE']}",
32.342 + path="/people.json",
32.343 + mimeType = "application/json"
32.344 + ))
32.345 + @BrwsrTest public void loadAndParseArrayOfEnums() throws InterruptedException {
32.346 + if (js == null) {
32.347 + js = new JSONik();
32.348 + js.applyBindings();
32.349 +
32.350 + js.fetchPeopleSex("people.json");
32.351 + }
32.352 +
32.353 + if (0 == js.getFetchedCount()) {
32.354 + throw new InterruptedException();
32.355 + }
32.356 +
32.357 + assert js.getFetchedCount() == 1 : "Loaded";
32.358 +
32.359 + assert js.getFetchedSex().size() == 3 : "Three values " + js.getFetchedSex();
32.360 + assert js.getFetchedSex().get(0) == Sex.FEMALE : "Female first " + js.getFetchedSex();
32.361 + assert js.getFetchedSex().get(1) == Sex.MALE : "male 2nd " + js.getFetchedSex();
32.362 + assert js.getFetchedSex().get(2) == Sex.MALE : "male 3rd " + js.getFetchedSex();
32.363 + }
32.364 +
32.365 + @Http(@Http.Resource(
32.366 + content = "[{'firstName': 'Gitar', 'sex': 'FEMALE'},"
32.367 + + "{'firstName': 'Peter', 'sex': 'MALE'}"
32.368 + + "]",
32.369 + path="/person.json",
32.370 + mimeType = "application/json"
32.371 + ))
32.372 + @BrwsrTest public void loadAndParseJSONArray() throws InterruptedException {
32.373 + if (js == null) {
32.374 + js = new JSONik();
32.375 + js.applyBindings();
32.376 + js.fetchArray("person.json");
32.377 + }
32.378 +
32.379 +
32.380 + Person p = js.getFetched();
32.381 + if (p == null) {
32.382 + throw new InterruptedException();
32.383 + }
32.384 +
32.385 + assert js.getFetchedCount() == 2 : "We got two values: " + js.getFetchedCount();
32.386 + assert p != null : "We should get our person back: " + p;
32.387 + assert "Gitar".equals(p.getFirstName()) : "Expecting Gitar: " + p.getFirstName();
32.388 + assert Sex.FEMALE.equals(p.getSex()) : "Expecting FEMALE: " + p.getSex();
32.389 + }
32.390 +
32.391 + @Factory public static Object[] create() {
32.392 + return VMTest.create(JSONTest.class);
32.393 + }
32.394 +
32.395 +}
33.1 --- a/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/KnockoutTest.java Tue Apr 02 15:40:51 2013 +0200
33.2 +++ b/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/KnockoutTest.java Thu May 02 09:18:22 2013 +0200
33.3 @@ -17,21 +17,29 @@
33.4 */
33.5 package org.apidesign.bck2brwsr.htmlpage;
33.6
33.7 +import java.util.List;
33.8 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
33.9 import org.apidesign.bck2brwsr.htmlpage.api.ComputedProperty;
33.10 import org.apidesign.bck2brwsr.htmlpage.api.OnEvent;
33.11 +import org.apidesign.bck2brwsr.htmlpage.api.OnFunction;
33.12 import org.apidesign.bck2brwsr.htmlpage.api.Page;
33.13 import org.apidesign.bck2brwsr.htmlpage.api.Property;
33.14 import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
33.15 import org.apidesign.bck2brwsr.vmtest.HtmlFragment;
33.16 import org.apidesign.bck2brwsr.vmtest.VMTest;
33.17 +import static org.testng.Assert.assertEquals;
33.18 import org.testng.annotations.Factory;
33.19 +import org.testng.annotations.Test;
33.20
33.21 /**
33.22 *
33.23 * @author Jaroslav Tulach <jtulach@netbeans.org>
33.24 */
33.25 @Page(xhtml="Knockout.xhtml", className="KnockoutModel", properties={
33.26 - @Property(name="name", type=String.class)
33.27 + @Property(name="name", type=String.class),
33.28 + @Property(name="results", type=String.class, array = true),
33.29 + @Property(name="callbackCount", type=int.class),
33.30 + @Property(name="people", type=PersonImpl.class, array = true)
33.31 })
33.32 public class KnockoutTest {
33.33
33.34 @@ -44,19 +52,207 @@
33.35 KnockoutModel m = new KnockoutModel();
33.36 m.setName("Kukuc");
33.37 m.applyBindings();
33.38 - assert "Kukuc".equals(m.INPUT.getValue()) : "Value is really kukuc: " + m.INPUT.getValue();
33.39 - m.INPUT.setValue("Jardo");
33.40 - m.triggerEvent(m.INPUT, OnEvent.CHANGE);
33.41 + assert "Kukuc".equals(m.input.getValue()) : "Value is really kukuc: " + m.input.getValue();
33.42 + m.input.setValue("Jardo");
33.43 + m.triggerEvent(m.input, OnEvent.CHANGE);
33.44 assert "Jardo".equals(m.getName()) : "Name property updated: " + m.getName();
33.45 }
33.46
33.47 + @HtmlFragment(
33.48 + "<ul id='ul' data-bind='foreach: results'>\n"
33.49 + + " <li data-bind='text: $data, click: $root.call'/>\n"
33.50 + + "</ul>\n"
33.51 + )
33.52 + @BrwsrTest public void displayContentOfArray() {
33.53 + KnockoutModel m = new KnockoutModel();
33.54 + m.getResults().add("Ahoj");
33.55 + m.applyBindings();
33.56 +
33.57 + int cnt = countChildren("ul");
33.58 + assert cnt == 1 : "One child, but was " + cnt;
33.59 +
33.60 + m.getResults().add("Hi");
33.61 +
33.62 + cnt = countChildren("ul");
33.63 + assert cnt == 2 : "Two children now, but was " + cnt;
33.64 +
33.65 + triggerChildClick("ul", 1);
33.66 +
33.67 + assert 1 == m.getCallbackCount() : "One callback " + m.getCallbackCount();
33.68 + assert "Hi".equals(m.getName()) : "We got callback from 2nd child " + m.getName();
33.69 + }
33.70 +
33.71 + @HtmlFragment(
33.72 + "<ul id='ul' data-bind='foreach: cmpResults'>\n"
33.73 + + " <li><b data-bind='text: $data'></b></li>\n"
33.74 + + "</ul>\n"
33.75 + )
33.76 + @BrwsrTest public void displayContentOfDerivedArray() {
33.77 + KnockoutModel m = new KnockoutModel();
33.78 + m.getResults().add("Ahoj");
33.79 + m.applyBindings();
33.80 +
33.81 + int cnt = countChildren("ul");
33.82 + assert cnt == 1 : "One child, but was " + cnt;
33.83 +
33.84 + m.getResults().add("hello");
33.85 +
33.86 + cnt = countChildren("ul");
33.87 + assert cnt == 2 : "Two children now, but was " + cnt;
33.88 + }
33.89 +
33.90 + @HtmlFragment(
33.91 + "<ul id='ul' data-bind='foreach: people'>\n"
33.92 + + " <li data-bind='text: $data.firstName, click: $root.removePerson'></li>\n"
33.93 + + "</ul>\n"
33.94 + )
33.95 + @BrwsrTest public void displayContentOfArrayOfPeople() {
33.96 + KnockoutModel m = new KnockoutModel();
33.97 +
33.98 + final Person first = new Person();
33.99 + first.setFirstName("first");
33.100 + m.getPeople().add(first);
33.101 +
33.102 + m.applyBindings();
33.103 +
33.104 + int cnt = countChildren("ul");
33.105 + assert cnt == 1 : "One child, but was " + cnt;
33.106 +
33.107 + final Person second = new Person();
33.108 + second.setFirstName("second");
33.109 + m.getPeople().add(second);
33.110 +
33.111 + cnt = countChildren("ul");
33.112 + assert cnt == 2 : "Two children now, but was " + cnt;
33.113 +
33.114 + triggerChildClick("ul", 1);
33.115 +
33.116 + assert 1 == m.getCallbackCount() : "One callback " + m.getCallbackCount();
33.117 +
33.118 + cnt = countChildren("ul");
33.119 + assert cnt == 1 : "Again one child, but was " + cnt;
33.120 +
33.121 + String txt = childText("ul", 0);
33.122 + assert "first".equals(txt) : "Expecting 'first': " + txt;
33.123 +
33.124 + first.setFirstName("changed");
33.125 +
33.126 + txt = childText("ul", 0);
33.127 + assert "changed".equals(txt) : "Expecting 'changed': " + txt;
33.128 + }
33.129 +
33.130 + @ComputedProperty
33.131 + static Person firstPerson(List<Person> people) {
33.132 + return people.isEmpty() ? null : people.get(0);
33.133 + }
33.134 +
33.135 + @HtmlFragment(
33.136 + "<p id='ul' data-bind='with: firstPerson'>\n"
33.137 + + " <span data-bind='text: firstName, click: changeSex'></span>\n"
33.138 + + "</p>\n"
33.139 + )
33.140 + @BrwsrTest public void accessFirstPersonWithOnFunction() {
33.141 + trasfertToFemale();
33.142 + }
33.143 +
33.144 + @HtmlFragment(
33.145 + "<ul id='ul' data-bind='foreach: people'>\n"
33.146 + + " <li data-bind='text: $data.firstName, click: changeSex'></li>\n"
33.147 + + "</ul>\n"
33.148 + )
33.149 + @BrwsrTest public void onPersonFunction() {
33.150 + trasfertToFemale();
33.151 + }
33.152 +
33.153 + private void trasfertToFemale() {
33.154 + KnockoutModel m = new KnockoutModel();
33.155 +
33.156 + final Person first = new Person();
33.157 + first.setFirstName("first");
33.158 + first.setSex(Sex.MALE);
33.159 + m.getPeople().add(first);
33.160 +
33.161 +
33.162 + m.applyBindings();
33.163 +
33.164 + int cnt = countChildren("ul");
33.165 + assert cnt == 1 : "One child, but was " + cnt;
33.166 +
33.167 +
33.168 + triggerChildClick("ul", 0);
33.169 +
33.170 + assert first.getSex() == Sex.FEMALE : "Transverted to female: " + first.getSex();
33.171 + }
33.172 +
33.173 + @Test public void cloneModel() {
33.174 + Person model = new Person();
33.175 +
33.176 + model.setFirstName("first");
33.177 + Person snd = model.clone();
33.178 + snd.setFirstName("clone");
33.179 + assertEquals("first", model.getFirstName(), "Value has not changed");
33.180 + assertEquals("clone", snd.getFirstName(), "Value has changed in clone");
33.181 + }
33.182 +
33.183 +
33.184 + @Test public void deepCopyOnClone() {
33.185 + People model = new People();
33.186 + model.getNicknames().add("Jarda");
33.187 + assertEquals(model.getNicknames().size(), 1, "One element");
33.188 + People snd = model.clone();
33.189 + snd.getNicknames().clear();
33.190 + assertEquals(snd.getNicknames().size(), 0, "Clone is empty");
33.191 + assertEquals(model.getNicknames().size(), 1, "Still one element");
33.192 + }
33.193 +
33.194 +
33.195 + @OnFunction
33.196 + static void call(KnockoutModel m, String data) {
33.197 + m.setName(data);
33.198 + m.setCallbackCount(m.getCallbackCount() + 1);
33.199 + }
33.200 +
33.201 + @OnFunction
33.202 + static void removePerson(KnockoutModel model, Person data) {
33.203 + model.setCallbackCount(model.getCallbackCount() + 1);
33.204 + model.getPeople().remove(data);
33.205 + }
33.206 +
33.207 +
33.208 @ComputedProperty
33.209 static String helloMessage(String name) {
33.210 return "Hello " + name + "!";
33.211 }
33.212
33.213 + @ComputedProperty
33.214 + static List<String> cmpResults(List<String> results) {
33.215 + return results;
33.216 + }
33.217 +
33.218 @Factory
33.219 public static Object[] create() {
33.220 return VMTest.create(KnockoutTest.class);
33.221 }
33.222 +
33.223 + @JavaScriptBody(args = { "id" }, body =
33.224 + "var e = window.document.getElementById(id);\n "
33.225 + + "if (typeof e === 'undefined') return -2;\n "
33.226 + + "return e.children.length;\n "
33.227 + )
33.228 + private static native int countChildren(String id);
33.229 +
33.230 + @JavaScriptBody(args = { "id", "pos" }, body =
33.231 + "var e = window.document.getElementById(id);\n "
33.232 + + "var ev = window.document.createEvent('MouseEvents');\n "
33.233 + + "ev.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);\n "
33.234 + + "e.children[pos].dispatchEvent(ev);\n "
33.235 + )
33.236 + private static native void triggerChildClick(String id, int pos);
33.237 +
33.238 + @JavaScriptBody(args = { "id", "pos" }, body =
33.239 + "var e = window.document.getElementById(id);\n "
33.240 + + "var t = e.children[pos].innerHTML;\n "
33.241 + + "return t ? t : null;"
33.242 + )
33.243 + private static native String childText(String id, int pos);
33.244 }
34.1 --- a/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/ModelTest.java Tue Apr 02 15:40:51 2013 +0200
34.2 +++ b/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/ModelTest.java Thu May 02 09:18:22 2013 +0200
34.3 @@ -18,8 +18,13 @@
34.4 package org.apidesign.bck2brwsr.htmlpage;
34.5
34.6 import java.util.ArrayList;
34.7 +import java.util.Collections;
34.8 +import java.util.Iterator;
34.9 import java.util.List;
34.10 +import java.util.ListIterator;
34.11 import org.apidesign.bck2brwsr.htmlpage.api.ComputedProperty;
34.12 +import org.apidesign.bck2brwsr.htmlpage.api.OnFunction;
34.13 +import org.apidesign.bck2brwsr.htmlpage.api.OnPropertyChange;
34.14 import org.apidesign.bck2brwsr.htmlpage.api.Page;
34.15 import org.apidesign.bck2brwsr.htmlpage.api.Property;
34.16 import static org.testng.Assert.*;
34.17 @@ -30,17 +35,22 @@
34.18 *
34.19 * @author Jaroslav Tulach <jtulach@netbeans.org>
34.20 */
34.21 -@Page(xhtml = "Empty.html", className = "Model", properties = {
34.22 +@Page(xhtml = "Empty.html", className = "Modelik", properties = {
34.23 @Property(name = "value", type = int.class),
34.24 - @Property(name = "unrelated", type = long.class)
34.25 + @Property(name = "count", type = int.class),
34.26 + @Property(name = "unrelated", type = long.class),
34.27 + @Property(name = "names", type = String.class, array = true),
34.28 + @Property(name = "values", type = int.class, array = true),
34.29 + @Property(name = "people", type = PersonImpl.class, array = true),
34.30 + @Property(name = "changedProperty", type=String.class)
34.31 })
34.32 public class ModelTest {
34.33 - private Model model;
34.34 - private static Model leakedModel;
34.35 + private Modelik model;
34.36 + private static Modelik leakedModel;
34.37
34.38 @BeforeMethod
34.39 public void createModel() {
34.40 - model = new Model();
34.41 + model = new Modelik();
34.42 }
34.43
34.44 @Test public void classGeneratedWithSetterGetter() {
34.45 @@ -53,6 +63,75 @@
34.46 assertEquals(16, model.getPowerValue());
34.47 }
34.48
34.49 + @Test public void arrayIsMutable() {
34.50 + assertEquals(model.getNames().size(), 0, "Is empty");
34.51 + model.getNames().add("Jarda");
34.52 + assertEquals(model.getNames().size(), 1, "One element");
34.53 + }
34.54 +
34.55 + @Test public void arrayChangesNotified() {
34.56 + MockKnockout my = new MockKnockout();
34.57 + MockKnockout.next = my;
34.58 +
34.59 + model.applyBindings();
34.60 +
34.61 + model.getNames().add("Hello");
34.62 +
34.63 + assertFalse(my.mutated.isEmpty(), "There was a change" + my.mutated);
34.64 + assertTrue(my.mutated.contains("names"), "Change in names property: " + my.mutated);
34.65 +
34.66 + my.mutated.clear();
34.67 +
34.68 + Iterator<String> it = model.getNames().iterator();
34.69 + assertEquals(it.next(), "Hello");
34.70 + it.remove();
34.71 +
34.72 + assertFalse(my.mutated.isEmpty(), "There was a change" + my.mutated);
34.73 + assertTrue(my.mutated.contains("names"), "Change in names property: " + my.mutated);
34.74 +
34.75 + my.mutated.clear();
34.76 +
34.77 + ListIterator<String> lit = model.getNames().listIterator();
34.78 + lit.add("Jarda");
34.79 +
34.80 + assertFalse(my.mutated.isEmpty(), "There was a change" + my.mutated);
34.81 + assertTrue(my.mutated.contains("names"), "Change in names property: " + my.mutated);
34.82 + }
34.83 +
34.84 + @Test public void autoboxedArray() {
34.85 + MockKnockout my = new MockKnockout();
34.86 + MockKnockout.next = my;
34.87 +
34.88 + model.applyBindings();
34.89 +
34.90 + model.getValues().add(10);
34.91 +
34.92 + assertEquals(model.getValues().get(0), Integer.valueOf(10), "Really ten");
34.93 + }
34.94 +
34.95 + @Test public void derivedArrayProp() {
34.96 + MockKnockout my = new MockKnockout();
34.97 + MockKnockout.next = my;
34.98 +
34.99 + model.applyBindings();
34.100 +
34.101 + model.setCount(10);
34.102 +
34.103 + List<String> arr = model.getRepeat();
34.104 + assertEquals(arr.size(), 10, "Ten items: " + arr);
34.105 +
34.106 + my.mutated.clear();
34.107 +
34.108 + model.setCount(5);
34.109 +
34.110 + arr = model.getRepeat();
34.111 + assertEquals(arr.size(), 5, "Five items: " + arr);
34.112 +
34.113 + assertEquals(my.mutated.size(), 2, "Two properties changed: " + my.mutated);
34.114 + assertTrue(my.mutated.contains("repeat"), "Array is in there: " + my.mutated);
34.115 + assertTrue(my.mutated.contains("count"), "Count is in there: " + my.mutated);
34.116 + }
34.117 +
34.118 @Test public void derivedPropertiesAreNotified() {
34.119 MockKnockout my = new MockKnockout();
34.120 MockKnockout.next = my;
34.121 @@ -61,6 +140,9 @@
34.122
34.123 model.setValue(33);
34.124
34.125 + // not interested in change of this property
34.126 + my.mutated.remove("changedProperty");
34.127 +
34.128 assertEquals(my.mutated.size(), 2, "Two properties changed: " + my.mutated);
34.129 assertTrue(my.mutated.contains("powerValue"), "Power value is in there: " + my.mutated);
34.130 assertTrue(my.mutated.contains("value"), "Simple value is in there: " + my.mutated);
34.131 @@ -68,7 +150,11 @@
34.132 my.mutated.clear();
34.133
34.134 model.setUnrelated(44);
34.135 - assertEquals(my.mutated.size(), 1, "One property changed");
34.136 +
34.137 +
34.138 + // not interested in change of this property
34.139 + my.mutated.remove("changedProperty");
34.140 + assertEquals(my.mutated.size(), 1, "One property changed: " + my.mutated);
34.141 assertTrue(my.mutated.contains("unrelated"), "Its name is unrelated");
34.142 }
34.143
34.144 @@ -92,11 +178,43 @@
34.145 }
34.146 }
34.147
34.148 + @OnFunction
34.149 + static void doSomething() {
34.150 + }
34.151 +
34.152 @ComputedProperty
34.153 static int powerValue(int value) {
34.154 return value * value;
34.155 }
34.156
34.157 + @OnPropertyChange({ "powerValue", "unrelated" })
34.158 + static void aPropertyChanged(Modelik m, String name) {
34.159 + m.setChangedProperty(name);
34.160 + }
34.161 +
34.162 + @OnPropertyChange({ "values" })
34.163 + static void anArrayPropertyChanged(String name, Modelik m) {
34.164 + m.setChangedProperty(name);
34.165 + }
34.166 +
34.167 + @Test public void changeAnything() {
34.168 + model.setCount(44);
34.169 + assertNull(model.getChangedProperty(), "No observed value change");
34.170 + }
34.171 + @Test public void changeValue() {
34.172 + model.setValue(33);
34.173 + assertEquals(model.getChangedProperty(), "powerValue", "power property changed");
34.174 + }
34.175 + @Test public void changeUnrelated() {
34.176 + model.setUnrelated(333);
34.177 + assertEquals(model.getChangedProperty(), "unrelated", "unrelated changed");
34.178 + }
34.179 +
34.180 + @Test public void changeInArray() {
34.181 + model.getValues().add(10);
34.182 + assertEquals(model.getChangedProperty(), "values", "Something added into the array");
34.183 + }
34.184 +
34.185 @ComputedProperty
34.186 static String notAllowedRead() {
34.187 return "Not allowed callback: " + leakedModel.getUnrelated();
34.188 @@ -108,12 +226,31 @@
34.189 return "Not allowed callback!";
34.190 }
34.191
34.192 + @ComputedProperty
34.193 + static List<String> repeat(int count) {
34.194 + return Collections.nCopies(count, "Hello");
34.195 + }
34.196 +
34.197 static class MockKnockout extends Knockout {
34.198 - List<String> mutated = new ArrayList<String>();
34.199 + List<String> mutated = new ArrayList<>();
34.200 +
34.201 + MockKnockout() {
34.202 + super(null);
34.203 + }
34.204
34.205 @Override
34.206 public void valueHasMutated(String prop) {
34.207 mutated.add(prop);
34.208 }
34.209 }
34.210 +
34.211 + public @Test void hasPersonPropertyAndComputedFullName() {
34.212 + List<Person> arr = model.getPeople();
34.213 + assertEquals(arr.size(), 0, "By default empty");
34.214 + Person p = null;
34.215 + if (p != null) {
34.216 + String fullNameGenerated = p.getFullName();
34.217 + assertNotNull(fullNameGenerated);
34.218 + }
34.219 + }
34.220 }
35.1 --- a/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/PageController.java Tue Apr 02 15:40:51 2013 +0200
35.2 +++ b/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/PageController.java Thu May 02 09:18:22 2013 +0200
35.3 @@ -50,7 +50,7 @@
35.4 if (PAGE != ref) {
35.5 throw new IllegalStateException("Both references should be the same. " + ref + " != " + PAGE);
35.6 }
35.7 - ref.PG_TITLE.setText("You want this window to be named " + ref.PG_TEXT.getValue());
35.8 + ref.pg_title.setText("You want this window to be named " + ref.pg_text.getValue());
35.9 }
35.10
35.11 @On(event = CLICK, id={ "pg.title", "pg.text" })
35.12 @@ -58,11 +58,11 @@
35.13 if (!id.equals("pg.title")) {
35.14 throw new IllegalStateException();
35.15 }
35.16 - PAGE.PG_TITLE.setText(id);
35.17 + PAGE.pg_title.setText(id);
35.18 }
35.19
35.20 @On(event = CLICK, id={ "pg.canvas" })
35.21 static void clickCanvas(String id, double layerX) {
35.22 - PAGE.PG_CANVAS.setWidth((int) layerX);
35.23 + PAGE.pg_canvas.setWidth((int) layerX);
35.24 }
35.25 }
36.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
36.2 +++ b/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/PageTest.java Thu May 02 09:18:22 2013 +0200
36.3 @@ -0,0 +1,53 @@
36.4 +/**
36.5 + * Back 2 Browser Bytecode Translator
36.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
36.7 + *
36.8 + * This program is free software: you can redistribute it and/or modify
36.9 + * it under the terms of the GNU General Public License as published by
36.10 + * the Free Software Foundation, version 2 of the License.
36.11 + *
36.12 + * This program is distributed in the hope that it will be useful,
36.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
36.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
36.15 + * GNU General Public License for more details.
36.16 + *
36.17 + * You should have received a copy of the GNU General Public License
36.18 + * along with this program. Look for COPYING file in the top folder.
36.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
36.20 + */
36.21 +package org.apidesign.bck2brwsr.htmlpage;
36.22 +
36.23 +import java.io.IOException;
36.24 +import java.util.Locale;
36.25 +import javax.tools.Diagnostic;
36.26 +import javax.tools.JavaFileObject;
36.27 +import static org.testng.Assert.*;
36.28 +import org.testng.annotations.Test;
36.29 +
36.30 +/** Verify errors emitted by the processor.
36.31 + *
36.32 + * @author Jaroslav Tulach <jtulach@netbeans.org>
36.33 + */
36.34 +public class PageTest {
36.35 + @Test public void verifyWrongType() throws IOException {
36.36 + String html = "<html><body>"
36.37 + + "</body></html>";
36.38 + String code = "package x.y.z;\n"
36.39 + + "import org.apidesign.bck2brwsr.htmlpage.api.*;\n"
36.40 + + "@Page(xhtml=\"index.xhtml\", className=\"Model\", properties={\n"
36.41 + + " @Property(name=\"prop\", type=Runnable.class)\n"
36.42 + + "})\n"
36.43 + + "class X {\n"
36.44 + + "}\n";
36.45 +
36.46 + Compile c = Compile.create(html, code);
36.47 + assertFalse(c.getErrors().isEmpty(), "One error: " + c.getErrors());
36.48 + for (Diagnostic<? extends JavaFileObject> e : c.getErrors()) {
36.49 + String msg = e.getMessage(Locale.ENGLISH);
36.50 + if (!msg.contains("Runnable")) {
36.51 + fail("Should contain warning about Runnable: " + msg);
36.52 + }
36.53 + }
36.54 + }
36.55 +
36.56 +}
37.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
37.2 +++ b/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/PersonImpl.java Thu May 02 09:18:22 2013 +0200
37.3 @@ -0,0 +1,62 @@
37.4 +/**
37.5 + * Back 2 Browser Bytecode Translator
37.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
37.7 + *
37.8 + * This program is free software: you can redistribute it and/or modify
37.9 + * it under the terms of the GNU General Public License as published by
37.10 + * the Free Software Foundation, version 2 of the License.
37.11 + *
37.12 + * This program is distributed in the hope that it will be useful,
37.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
37.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
37.15 + * GNU General Public License for more details.
37.16 + *
37.17 + * You should have received a copy of the GNU General Public License
37.18 + * along with this program. Look for COPYING file in the top folder.
37.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
37.20 + */
37.21 +package org.apidesign.bck2brwsr.htmlpage;
37.22 +
37.23 +import org.apidesign.bck2brwsr.htmlpage.api.ComputedProperty;
37.24 +import org.apidesign.bck2brwsr.htmlpage.api.Model;
37.25 +import org.apidesign.bck2brwsr.htmlpage.api.OnFunction;
37.26 +import org.apidesign.bck2brwsr.htmlpage.api.Property;
37.27 +
37.28 +/**
37.29 + *
37.30 + * @author Jaroslav Tulach <jtulach@netbeans.org>
37.31 + */
37.32 +@Model(className = "Person", properties = {
37.33 + @Property(name = "firstName", type = String.class),
37.34 + @Property(name = "lastName", type = String.class),
37.35 + @Property(name = "sex", type = Sex.class)
37.36 +})
37.37 +final class PersonImpl {
37.38 + @ComputedProperty
37.39 + public static String fullName(String firstName, String lastName) {
37.40 + return firstName + " " + lastName;
37.41 + }
37.42 +
37.43 + @ComputedProperty
37.44 + public static String sexType(Sex sex) {
37.45 + return sex == null ? "unknown" : sex.toString();
37.46 + }
37.47 +
37.48 + @OnFunction
37.49 + static void changeSex(Person p) {
37.50 + if (p.getSex() == Sex.MALE) {
37.51 + p.setSex(Sex.FEMALE);
37.52 + } else {
37.53 + p.setSex(Sex.MALE);
37.54 + }
37.55 + }
37.56 +
37.57 + @Model(className = "People", properties = {
37.58 + @Property(array = true, name = "info", type = Person.class),
37.59 + @Property(array = true, name = "nicknames", type = String.class),
37.60 + @Property(array = true, name = "age", type = int.class),
37.61 + @Property(array = true, name = "sex", type = Sex.class)
37.62 + })
37.63 + public class PeopleImpl {
37.64 + }
37.65 +}
38.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
38.2 +++ b/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/Sex.java Thu May 02 09:18:22 2013 +0200
38.3 @@ -0,0 +1,26 @@
38.4 +/**
38.5 + * Back 2 Browser Bytecode Translator
38.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
38.7 + *
38.8 + * This program is free software: you can redistribute it and/or modify
38.9 + * it under the terms of the GNU General Public License as published by
38.10 + * the Free Software Foundation, version 2 of the License.
38.11 + *
38.12 + * This program is distributed in the hope that it will be useful,
38.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
38.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38.15 + * GNU General Public License for more details.
38.16 + *
38.17 + * You should have received a copy of the GNU General Public License
38.18 + * along with this program. Look for COPYING file in the top folder.
38.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
38.20 + */
38.21 +package org.apidesign.bck2brwsr.htmlpage;
38.22 +
38.23 +/**
38.24 + *
38.25 + * @author Jaroslav Tulach <jtulach@netbeans.org>
38.26 + */
38.27 +public enum Sex {
38.28 + MALE, FEMALE;
38.29 +}
39.1 --- a/javaquery/demo-calculator-dynamic/nbactions.xml Tue Apr 02 15:40:51 2013 +0200
39.2 +++ b/javaquery/demo-calculator-dynamic/nbactions.xml Thu May 02 09:18:22 2013 +0200
39.3 @@ -23,7 +23,7 @@
39.4 <actionName>run</actionName>
39.5 <goals>
39.6 <goal>process-classes</goal>
39.7 - <goal>org.apidesign.bck2brwsr:mojo:0.5-SNAPSHOT:brwsr</goal>
39.8 + <goal>bck2brwsr:brwsr</goal>
39.9 </goals>
39.10 </action>
39.11 </actions>
40.1 --- a/javaquery/demo-calculator-dynamic/pom.xml Tue Apr 02 15:40:51 2013 +0200
40.2 +++ b/javaquery/demo-calculator-dynamic/pom.xml Thu May 02 09:18:22 2013 +0200
40.3 @@ -4,7 +4,7 @@
40.4
40.5 <groupId>org.apidesign.bck2brwsr</groupId>
40.6 <artifactId>demo.calculator</artifactId>
40.7 - <version>0.5-SNAPSHOT</version>
40.8 + <version>0.8-SNAPSHOT</version>
40.9 <packaging>jar</packaging>
40.10
40.11 <name>JavaQuery Demo - Calculator</name>
40.12 @@ -17,8 +17,8 @@
40.13 <plugins>
40.14 <plugin>
40.15 <groupId>org.apidesign.bck2brwsr</groupId>
40.16 - <artifactId>mojo</artifactId>
40.17 - <version>0.5-SNAPSHOT</version>
40.18 + <artifactId>bck2brwsr-maven-plugin</artifactId>
40.19 + <version>${project.version}</version>
40.20 <executions>
40.21 <execution>
40.22 <goals>
40.23 @@ -93,13 +93,13 @@
40.24 <dependency>
40.25 <groupId>org.apidesign.bck2brwsr</groupId>
40.26 <artifactId>emul</artifactId>
40.27 - <version>0.5-SNAPSHOT</version>
40.28 + <version>${project.version}</version>
40.29 <classifier>rt</classifier>
40.30 </dependency>
40.31 <dependency>
40.32 <groupId>org.apidesign.bck2brwsr</groupId>
40.33 <artifactId>javaquery.api</artifactId>
40.34 - <version>0.5-SNAPSHOT</version>
40.35 + <version>${project.version}</version>
40.36 </dependency>
40.37 <dependency>
40.38 <groupId>org.testng</groupId>
40.39 @@ -112,7 +112,7 @@
40.40 <artifactId>vm4brwsr</artifactId>
40.41 <classifier>js</classifier>
40.42 <type>zip</type>
40.43 - <version>0.5-SNAPSHOT</version>
40.44 + <version>${project.version}</version>
40.45 <scope>provided</scope>
40.46 </dependency>
40.47 </dependencies>
41.1 --- a/javaquery/demo-calculator-dynamic/src/main/java/org/apidesign/bck2brwsr/demo/calc/Calc.java Tue Apr 02 15:40:51 2013 +0200
41.2 +++ b/javaquery/demo-calculator-dynamic/src/main/java/org/apidesign/bck2brwsr/demo/calc/Calc.java Thu May 02 09:18:22 2013 +0200
41.3 @@ -17,9 +17,11 @@
41.4 */
41.5 package org.apidesign.bck2brwsr.demo.calc;
41.6
41.7 +import java.util.List;
41.8 import org.apidesign.bck2brwsr.htmlpage.api.ComputedProperty;
41.9 import org.apidesign.bck2brwsr.htmlpage.api.On;
41.10 import static org.apidesign.bck2brwsr.htmlpage.api.OnEvent.*;
41.11 +import org.apidesign.bck2brwsr.htmlpage.api.OnFunction;
41.12 import org.apidesign.bck2brwsr.htmlpage.api.Page;
41.13 import org.apidesign.bck2brwsr.htmlpage.api.Property;
41.14
41.15 @@ -33,11 +35,12 @@
41.16 @Property(name = "memory", type = double.class),
41.17 @Property(name = "display", type = double.class),
41.18 @Property(name = "operation", type = String.class),
41.19 - @Property(name = "hover", type = boolean.class)
41.20 + @Property(name = "hover", type = boolean.class),
41.21 + @Property(name = "history", type = HistoryImpl.class, array = true)
41.22 })
41.23 public class Calc {
41.24 static {
41.25 - new Calculator().applyBindings();
41.26 + new Calculator().applyBindings().setOperation("plus");
41.27 }
41.28
41.29 @On(event = CLICK, id="clear")
41.30 @@ -65,14 +68,31 @@
41.31
41.32 @On(event = CLICK, id="result")
41.33 static void computeTheValue(Calculator c) {
41.34 - c.setDisplay(compute(
41.35 + final double newValue = compute(
41.36 c.getOperation(),
41.37 c.getMemory(),
41.38 c.getDisplay()
41.39 - ));
41.40 + );
41.41 + c.setDisplay(newValue);
41.42 + if (!containsValue(c.getHistory(), newValue)) {
41.43 + History h = new History();
41.44 + h.setValue(newValue);
41.45 + h.setOperation(c.getOperation());
41.46 + c.getHistory().add(h);
41.47 + }
41.48 c.setMemory(0);
41.49 }
41.50
41.51 + @OnFunction
41.52 + static void recoverMemory(Calculator c, History data) {
41.53 + c.setDisplay(data.getValue());
41.54 + }
41.55 +
41.56 + @OnFunction
41.57 + static void removeMemory(Calculator c, History data) {
41.58 + c.getHistory().remove(data);
41.59 + }
41.60 +
41.61 private static double compute(String op, double memory, double display) {
41.62 switch (op) {
41.63 case "plus": return memory + display;
41.64 @@ -109,4 +129,18 @@
41.65 }
41.66 return "Attempt to compute " + memory + " " + operation + " " + display + " = " + compute(operation, memory, display);
41.67 }
41.68 +
41.69 + @ComputedProperty
41.70 + static boolean emptyHistory(List<?> history) {
41.71 + return history.isEmpty();
41.72 + }
41.73 +
41.74 + private static boolean containsValue(List<History> arr, final double newValue) {
41.75 + for (History history : arr) {
41.76 + if (history.getValue() == newValue) {
41.77 + return true;
41.78 + }
41.79 + }
41.80 + return false;
41.81 + }
41.82 }
42.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
42.2 +++ b/javaquery/demo-calculator-dynamic/src/main/java/org/apidesign/bck2brwsr/demo/calc/HistoryImpl.java Thu May 02 09:18:22 2013 +0200
42.3 @@ -0,0 +1,43 @@
42.4 +/**
42.5 + * Back 2 Browser Bytecode Translator
42.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
42.7 + *
42.8 + * This program is free software: you can redistribute it and/or modify
42.9 + * it under the terms of the GNU General Public License as published by
42.10 + * the Free Software Foundation, version 2 of the License.
42.11 + *
42.12 + * This program is distributed in the hope that it will be useful,
42.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
42.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
42.15 + * GNU General Public License for more details.
42.16 + *
42.17 + * You should have received a copy of the GNU General Public License
42.18 + * along with this program. Look for COPYING file in the top folder.
42.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
42.20 + */
42.21 +package org.apidesign.bck2brwsr.demo.calc;
42.22 +
42.23 +import org.apidesign.bck2brwsr.htmlpage.api.ComputedProperty;
42.24 +import org.apidesign.bck2brwsr.htmlpage.api.Model;
42.25 +import org.apidesign.bck2brwsr.htmlpage.api.OnFunction;
42.26 +import org.apidesign.bck2brwsr.htmlpage.api.Property;
42.27 +
42.28 +/**
42.29 + *
42.30 + * @author Jaroslav Tulach <jtulach@netbeans.org>
42.31 + */
42.32 +@Model(className = "History", properties = {
42.33 + @Property(name = "value", type = double.class),
42.34 + @Property(name = "operation", type = String.class)
42.35 +})
42.36 +public class HistoryImpl {
42.37 + @ComputedProperty
42.38 + static String resultOf(String operation) {
42.39 + return "result of " + operation;
42.40 + }
42.41 +
42.42 + @OnFunction
42.43 + static void twice(History data) {
42.44 + data.setValue(2.0 * data.getValue());
42.45 + }
42.46 +}
43.1 --- a/javaquery/demo-calculator-dynamic/src/main/resources/org/apidesign/bck2brwsr/demo/calc/Calculator.xhtml Tue Apr 02 15:40:51 2013 +0200
43.2 +++ b/javaquery/demo-calculator-dynamic/src/main/resources/org/apidesign/bck2brwsr/demo/calc/Calculator.xhtml Thu May 02 09:18:22 2013 +0200
43.3 @@ -78,82 +78,25 @@
43.4 </table>
43.5 <div data-bind="text: displayPreview"></div>
43.6
43.7 + <h4>Previous Results</h4>
43.8 +
43.9 + <div data-bind="if: emptyHistory">No results yet.</div>
43.10 + <ul data-bind="foreach: history">
43.11 + <li>
43.12 + <span data-bind="text: $data.value"></span> -
43.13 + <a href="#" data-bind="click: $root.recoverMemory">Use</a>
43.14 + <a href="#" data-bind="click: $root.removeMemory">Remove</a>
43.15 + <a href="#" data-bind="click: $data.twice">Double</a> -
43.16 + <span data-bind="text: $data.resultOf"></span>
43.17 + </li>
43.18 + </ul>
43.19 +
43.20 <script src="bck2brwsr.js"></script>
43.21 <script type="text/javascript">
43.22 - var vm = bck2brwsr('demo.calculator-0.3-SNAPSHOT.jar');
43.23 + var vm = bck2brwsr('demo.calculator-0.6.jar');
43.24 vm.loadClass('org.apidesign.bck2brwsr.demo.calc.Calc');
43.25 </script>
43.26
43.27 <hr/>
43.28 - <pre>
43.29 - <span class="keyword-directive">package</span> org.apidesign.bck2brwsr.mavenhtml;
43.30 -
43.31 - <span class="keyword-directive">import</span> org.apidesign.bck2brwsr.htmlpage.api.OnClick;
43.32 - <span class="keyword-directive">import</span> org.apidesign.bck2brwsr.htmlpage.api.Page;
43.33 -
43.34 - <span class="comment">/**</span> <span class="comment">HTML5</span><span class="comment"> & </span><span class="comment">Java</span> <span class="comment">demo</span> <span class="comment">showing</span> <span class="comment">the</span> <span class="comment">power</span> <span class="comment">of</span> <a href="http://wiki.apidesign.org/wiki/AnnotationProcessor">annotation processors</a>
43.35 - <span class="comment"> * </span><span class="comment">as</span> <span class="comment">well</span> <span class="comment">as</span> <span class="comment">other</span> <span class="comment">goodies</span><span class="comment">, including type-safe association between</span>
43.36 - <span class="comment"> * </span><span class="comment">an XHTML page and Java.</span>
43.37 - <span class="comment"> * </span>
43.38 - <span class="comment"> * </span><span class="ST1">@author</span> <span class="comment">Jaroslav</span> <span class="comment">Tulach</span> <span class="ST0"><jaroslav.tulach@apidesign.org></span>
43.39 - <span class="comment">*/</span>
43.40 - @Page(xhtml=<span class="string">"</span><span class="string">Calculator.xhtml</span><span class="string">"</span>)
43.41 - <span class="keyword-directive">public</span> <span class="keyword-directive">class</span> App {
43.42 - <span class="keyword-directive">private</span> <span class="keyword-directive">static</span> <span class="keyword-directive">double</span> memory;
43.43 - <span class="keyword-directive">private</span> <span class="keyword-directive">static</span> String operation;
43.44 -
43.45 - @OnClick(id=<span class="string">"</span><span class="string">clear</span><span class="string">"</span>)
43.46 - <span class="keyword-directive">static</span> <span class="keyword-directive">void</span> clear() {
43.47 - memory = <span class="number">0</span>;
43.48 - operation = <span class="keyword-directive">null</span>;
43.49 - Calculator.DISPLAY.setValue(<span class="string">"</span><span class="string">0</span><span class="string">"</span>);
43.50 - }
43.51 -
43.52 - @OnClick(id= { <span class="string">"</span><span class="string">plus</span><span class="string">"</span>, <span class="string">"</span><span class="string">minus</span><span class="string">"</span>, <span class="string">"</span><span class="string">mul</span><span class="string">"</span>, <span class="string">"</span><span class="string">div</span><span class="string">"</span> })
43.53 - <span class="keyword-directive">static</span> <span class="keyword-directive">void</span> applyOp(String op) {
43.54 - memory = getValue();
43.55 - operation = op;
43.56 - Calculator.DISPLAY.setValue(<span class="string">"</span><span class="string">0</span><span class="string">"</span>);
43.57 - }
43.58 -
43.59 - @OnClick(id=<span class="string">"</span><span class="string">result</span><span class="string">"</span>)
43.60 - <span class="keyword-directive">static</span> <span class="keyword-directive">void</span> computeTheValue() {
43.61 - <span class="keyword-directive">switch</span> (operation) {
43.62 - <span class="keyword-directive">case</span> <span class="string">"</span><span class="string">plus</span><span class="string">"</span>: setValue(memory + getValue()); <span class="keyword-directive">break</span>;
43.63 - <span class="keyword-directive">case</span> <span class="string">"</span><span class="string">minus</span><span class="string">"</span>: setValue(memory - getValue()); <span class="keyword-directive">break</span>;
43.64 - <span class="keyword-directive">case</span> <span class="string">"</span><span class="string">mul</span><span class="string">"</span>: setValue(memory * getValue()); <span class="keyword-directive">break</span>;
43.65 - <span class="keyword-directive">case</span> <span class="string">"</span><span class="string">div</span><span class="string">"</span>: setValue(memory / getValue()); <span class="keyword-directive">break</span>;
43.66 - <span class="keyword-directive">default</span>: <span class="keyword-directive">throw</span> <span class="keyword-directive">new</span> IllegalStateException(operation);
43.67 - }
43.68 - }
43.69 -
43.70 - @OnClick(id={<span class="string">"</span><span class="string">n0</span><span class="string">"</span>, <span class="string">"</span><span class="string">n1</span><span class="string">"</span>, <span class="string">"</span><span class="string">n2</span><span class="string">"</span>, <span class="string">"</span><span class="string">n3</span><span class="string">"</span>, <span class="string">"</span><span class="string">n4</span><span class="string">"</span>, <span class="string">"</span><span class="string">n5</span><span class="string">"</span>, <span class="string">"</span><span class="string">n6</span><span class="string">"</span>, <span class="string">"</span><span class="string">n7</span><span class="string">"</span>, <span class="string">"</span><span class="string">n8</span><span class="string">"</span>, <span class="string">"</span><span class="string">n9</span><span class="string">"</span>})
43.71 - <span class="keyword-directive">static</span> <span class="keyword-directive">void</span> addDigit(String digit) {
43.72 - digit = digit.substring(<span class="number">1</span>);
43.73 - String v = Calculator.DISPLAY.getValue();
43.74 - <span class="keyword-directive">if</span> (getValue() == <span class="number">0.0</span>) {
43.75 - Calculator.DISPLAY.setValue(digit);
43.76 - } <span class="keyword-directive">else</span> {
43.77 - Calculator.DISPLAY.setValue(v + digit);
43.78 - }
43.79 - }
43.80 -
43.81 - <span class="keyword-directive">private</span> <span class="keyword-directive">static</span> <span class="keyword-directive">void</span> setValue(<span class="keyword-directive">double</span> v) {
43.82 - StringBuilder sb = <span class="keyword-directive">new</span> StringBuilder();
43.83 - sb.append(v);
43.84 - Calculator.DISPLAY.setValue(sb.toString());
43.85 - }
43.86 -
43.87 - <span class="keyword-directive">private</span> <span class="keyword-directive">static</span> <span class="keyword-directive">double</span> getValue() {
43.88 - <span class="keyword-directive">try</span> {
43.89 - <span class="keyword-directive">return</span> Double.parseDouble(Calculator.DISPLAY.getValue());
43.90 - } <span class="keyword-directive">catch</span> (NumberFormatException ex) {
43.91 - Calculator.DISPLAY.setValue(<span class="string">"</span><span class="string">err</span><span class="string">"</span>);
43.92 - <span class="keyword-directive">return</span> <span class="number">0.0</span>;
43.93 - }
43.94 - }
43.95 - }
43.96 -
43.97 - </pre>
43.98 </body>
43.99 </html>
44.1 --- a/javaquery/demo-calculator/nbactions.xml Tue Apr 02 15:40:51 2013 +0200
44.2 +++ b/javaquery/demo-calculator/nbactions.xml Thu May 02 09:18:22 2013 +0200
44.3 @@ -23,7 +23,7 @@
44.4 <actionName>run</actionName>
44.5 <goals>
44.6 <goal>package</goal>
44.7 - <goal>org.apidesign.bck2brwsr:mojo:0.5-SNAPSHOT:brwsr</goal>
44.8 + <goal>bck2brwsr:brwsr</goal>
44.9 </goals>
44.10 <properties>
44.11 <skipTests>true</skipTests>
45.1 --- a/javaquery/demo-calculator/pom.xml Tue Apr 02 15:40:51 2013 +0200
45.2 +++ b/javaquery/demo-calculator/pom.xml Thu May 02 09:18:22 2013 +0200
45.3 @@ -4,7 +4,7 @@
45.4
45.5 <groupId>org.apidesign.bck2brwsr</groupId>
45.6 <artifactId>demo.static.calculator</artifactId>
45.7 - <version>0.5-SNAPSHOT</version>
45.8 + <version>0.8-SNAPSHOT</version>
45.9 <packaging>jar</packaging>
45.10
45.11 <name>JavaQuery Demo - Calculator - Static Compilation</name>
45.12 @@ -12,13 +12,14 @@
45.13
45.14 <properties>
45.15 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
45.16 + <bck2brwsr.obfuscationlevel>MINIMAL</bck2brwsr.obfuscationlevel>
45.17 </properties>
45.18 <build>
45.19 <plugins>
45.20 <plugin>
45.21 <groupId>org.apidesign.bck2brwsr</groupId>
45.22 - <artifactId>mojo</artifactId>
45.23 - <version>0.5-SNAPSHOT</version>
45.24 + <artifactId>bck2brwsr-maven-plugin</artifactId>
45.25 + <version>${project.version}</version>
45.26 <executions>
45.27 <execution>
45.28 <goals>
45.29 @@ -31,6 +32,7 @@
45.30 <directory>${project.build.directory}/${project.build.finalName}-bck2brwsr/public_html/</directory>
45.31 <startpage>index.xhtml</startpage>
45.32 <javascript>${project.build.directory}/bck2brwsr.js</javascript>
45.33 + <obfuscation>${bck2brwsr.obfuscationlevel}</obfuscation>
45.34 </configuration>
45.35 </plugin>
45.36 <plugin>
45.37 @@ -96,13 +98,13 @@
45.38 <dependency>
45.39 <groupId>org.apidesign.bck2brwsr</groupId>
45.40 <artifactId>emul</artifactId>
45.41 - <version>0.5-SNAPSHOT</version>
45.42 + <version>${project.version}</version>
45.43 <classifier>rt</classifier>
45.44 </dependency>
45.45 <dependency>
45.46 <groupId>org.apidesign.bck2brwsr</groupId>
45.47 <artifactId>javaquery.api</artifactId>
45.48 - <version>0.5-SNAPSHOT</version>
45.49 + <version>${project.version}</version>
45.50 </dependency>
45.51 </dependencies>
45.52 </project>
46.1 --- a/javaquery/demo-calculator/src/main/java/org/apidesign/bck2brwsr/demo/calc/staticcompilation/Calc.java Tue Apr 02 15:40:51 2013 +0200
46.2 +++ b/javaquery/demo-calculator/src/main/java/org/apidesign/bck2brwsr/demo/calc/staticcompilation/Calc.java Thu May 02 09:18:22 2013 +0200
46.3 @@ -17,9 +17,11 @@
46.4 */
46.5 package org.apidesign.bck2brwsr.demo.calc.staticcompilation;
46.6
46.7 +import java.util.List;
46.8 import org.apidesign.bck2brwsr.htmlpage.api.ComputedProperty;
46.9 import org.apidesign.bck2brwsr.htmlpage.api.On;
46.10 import static org.apidesign.bck2brwsr.htmlpage.api.OnEvent.*;
46.11 +import org.apidesign.bck2brwsr.htmlpage.api.OnFunction;
46.12 import org.apidesign.bck2brwsr.htmlpage.api.Page;
46.13 import org.apidesign.bck2brwsr.htmlpage.api.Property;
46.14
46.15 @@ -33,11 +35,12 @@
46.16 @Property(name = "memory", type = double.class),
46.17 @Property(name = "display", type = double.class),
46.18 @Property(name = "operation", type = String.class),
46.19 - @Property(name = "hover", type = boolean.class)
46.20 + @Property(name = "hover", type = boolean.class),
46.21 + @Property(name = "history", type = double.class, array = true)
46.22 })
46.23 public class Calc {
46.24 static {
46.25 - new Calculator().applyBindings();
46.26 + new Calculator().applyBindings().setOperation("plus");
46.27 }
46.28
46.29 @On(event = CLICK, id="clear")
46.30 @@ -65,14 +68,28 @@
46.31
46.32 @On(event = CLICK, id="result")
46.33 static void computeTheValue(Calculator c) {
46.34 - c.setDisplay(compute(
46.35 + final double newValue = compute(
46.36 c.getOperation(),
46.37 c.getMemory(),
46.38 c.getDisplay()
46.39 - ));
46.40 + );
46.41 + c.setDisplay(newValue);
46.42 + if (!c.getHistory().contains(newValue)) {
46.43 + c.getHistory().add(newValue);
46.44 + }
46.45 c.setMemory(0);
46.46 }
46.47
46.48 + @OnFunction
46.49 + static void recoverMemory(Calculator c, double data) {
46.50 + c.setDisplay(data);
46.51 + }
46.52 +
46.53 + @OnFunction
46.54 + static void removeMemory(Calculator c, double data) {
46.55 + c.getHistory().remove(data);
46.56 + }
46.57 +
46.58 private static double compute(String op, double memory, double display) {
46.59 switch (op) {
46.60 case "plus": return memory + display;
46.61 @@ -109,4 +126,9 @@
46.62 }
46.63 return "Attempt to compute " + memory + " " + operation + " " + display + " = " + compute(operation, memory, display);
46.64 }
46.65 +
46.66 + @ComputedProperty
46.67 + static boolean emptyHistory(List<?> history) {
46.68 + return history.isEmpty();
46.69 + }
46.70 }
47.1 --- a/javaquery/demo-calculator/src/main/resources/org/apidesign/bck2brwsr/demo/calc/staticcompilation/Calculator.xhtml Tue Apr 02 15:40:51 2013 +0200
47.2 +++ b/javaquery/demo-calculator/src/main/resources/org/apidesign/bck2brwsr/demo/calc/staticcompilation/Calculator.xhtml Thu May 02 09:18:22 2013 +0200
47.3 @@ -76,10 +76,22 @@
47.4 </tr>
47.5 </tbody>
47.6 </table>
47.7 +
47.8 + <h4>Previous Results</h4>
47.9 +
47.10 + <div data-bind="if: emptyHistory">No results yet.</div>
47.11 + <ul data-bind="foreach: history">
47.12 + <li>
47.13 + <span data-bind="text: $data"></span> -
47.14 + <a href="#" data-bind="click: $root.recoverMemory">Use</a>
47.15 + <a href="#" data-bind="click: $root.removeMemory">Remove</a>
47.16 + </li>
47.17 + </ul>
47.18 +
47.19 <div data-bind="text: displayPreview"></div>
47.20 - <script src="bck2brwsr.js"/>
47.21 + <script src="bck2brwsr.js"></script>
47.22 <script>
47.23 - var vm = bck2brwsr('demo.static.calculator-0.5-SNAPSHOT.jar');
47.24 + var vm = bck2brwsr('demo.static.calculator-0.6.jar');
47.25 vm.loadClass('org.apidesign.bck2brwsr.demo.calc.staticcompilation.Calc');
47.26 </script>
47.27 </body>
48.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
48.2 +++ b/javaquery/demo-twitter/bck2brwsr-assembly.xml Thu May 02 09:18:22 2013 +0200
48.3 @@ -0,0 +1,62 @@
48.4 +<?xml version="1.0"?>
48.5 +<!--
48.6 +
48.7 + Back 2 Browser Bytecode Translator
48.8 + Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
48.9 +
48.10 + This program is free software: you can redistribute it and/or modify
48.11 + it under the terms of the GNU General Public License as published by
48.12 + the Free Software Foundation, version 2 of the License.
48.13 +
48.14 + This program is distributed in the hope that it will be useful,
48.15 + but WITHOUT ANY WARRANTY; without even the implied warranty of
48.16 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
48.17 + GNU General Public License for more details.
48.18 +
48.19 + You should have received a copy of the GNU General Public License
48.20 + along with this program. Look for COPYING file in the top folder.
48.21 + If not, see http://opensource.org/licenses/GPL-2.0.
48.22 +
48.23 +-->
48.24 +<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
48.25 + xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
48.26 +
48.27 + <id>bck2brwsr</id>
48.28 + <formats>
48.29 + <format>zip</format>
48.30 + </formats>
48.31 + <baseDirectory>public_html</baseDirectory>
48.32 + <dependencySets>
48.33 + <dependencySet>
48.34 + <useProjectArtifact>false</useProjectArtifact>
48.35 + <scope>runtime</scope>
48.36 + <outputDirectory>lib</outputDirectory>
48.37 + <includes>
48.38 + <include>*:jar</include>
48.39 + <include>*:rt</include>
48.40 + </includes>
48.41 + </dependencySet>
48.42 + </dependencySets>
48.43 + <fileSets>
48.44 + <fileSet>
48.45 + <directory>${project.build.directory}/classes/org/apidesign/bck2brwsr/demo/twitter/</directory>
48.46 + <includes>
48.47 + <include>**/*</include>
48.48 + </includes>
48.49 + <excludes>
48.50 + <exclude>**/*.class</exclude>
48.51 + </excludes>
48.52 + <outputDirectory>/</outputDirectory>
48.53 + </fileSet>
48.54 + </fileSets>
48.55 + <files>
48.56 + <file>
48.57 + <source>${project.build.directory}/${project.build.finalName}.jar</source>
48.58 + <outputDirectory>/</outputDirectory>
48.59 + </file>
48.60 + <file>
48.61 + <source>${project.build.directory}/bck2brwsr.js</source>
48.62 + <outputDirectory>/</outputDirectory>
48.63 + </file>
48.64 + </files>
48.65 +</assembly>
48.66 \ No newline at end of file
49.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
49.2 +++ b/javaquery/demo-twitter/nb-configuration.xml Thu May 02 09:18:22 2013 +0200
49.3 @@ -0,0 +1,37 @@
49.4 +<?xml version="1.0" encoding="UTF-8"?>
49.5 +<!--
49.6 +
49.7 + Back 2 Browser Bytecode Translator
49.8 + Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
49.9 +
49.10 + This program is free software: you can redistribute it and/or modify
49.11 + it under the terms of the GNU General Public License as published by
49.12 + the Free Software Foundation, version 2 of the License.
49.13 +
49.14 + This program is distributed in the hope that it will be useful,
49.15 + but WITHOUT ANY WARRANTY; without even the implied warranty of
49.16 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
49.17 + GNU General Public License for more details.
49.18 +
49.19 + You should have received a copy of the GNU General Public License
49.20 + along with this program. Look for COPYING file in the top folder.
49.21 + If not, see http://opensource.org/licenses/GPL-2.0.
49.22 +
49.23 +-->
49.24 +<project-shared-configuration>
49.25 + <!--
49.26 +This file contains additional configuration written by modules in the NetBeans IDE.
49.27 +The configuration is intended to be shared among all the users of project and
49.28 +therefore it is assumed to be part of version control checkout.
49.29 +Without this configuration present, some functionality in the IDE may be limited or fail altogether.
49.30 +-->
49.31 + <properties xmlns="http://www.netbeans.org/ns/maven-properties-data/1">
49.32 + <!--
49.33 +Properties that influence various parts of the IDE, especially code formatting and the like.
49.34 +You can copy and paste the single properties, into the pom.xml file and the IDE will pick them up.
49.35 +That way multiple projects can share the same settings (useful for formatting rules for example).
49.36 +Any value defined here will override the pom.xml file value but is only applicable to the current project.
49.37 +-->
49.38 + <netbeans.compile.on.save>none</netbeans.compile.on.save>
49.39 + </properties>
49.40 +</project-shared-configuration>
50.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
50.2 +++ b/javaquery/demo-twitter/nbactions.xml Thu May 02 09:18:22 2013 +0200
50.3 @@ -0,0 +1,29 @@
50.4 +<?xml version="1.0" encoding="UTF-8"?>
50.5 +<!--
50.6 +
50.7 + Back 2 Browser Bytecode Translator
50.8 + Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
50.9 +
50.10 + This program is free software: you can redistribute it and/or modify
50.11 + it under the terms of the GNU General Public License as published by
50.12 + the Free Software Foundation, version 2 of the License.
50.13 +
50.14 + This program is distributed in the hope that it will be useful,
50.15 + but WITHOUT ANY WARRANTY; without even the implied warranty of
50.16 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
50.17 + GNU General Public License for more details.
50.18 +
50.19 + You should have received a copy of the GNU General Public License
50.20 + along with this program. Look for COPYING file in the top folder.
50.21 + If not, see http://opensource.org/licenses/GPL-2.0.
50.22 +
50.23 +-->
50.24 +<actions>
50.25 + <action>
50.26 + <actionName>run</actionName>
50.27 + <goals>
50.28 + <goal>process-classes</goal>
50.29 + <goal>bck2brwsr:brwsr</goal>
50.30 + </goals>
50.31 + </action>
50.32 +</actions>
51.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
51.2 +++ b/javaquery/demo-twitter/pom.xml Thu May 02 09:18:22 2013 +0200
51.3 @@ -0,0 +1,151 @@
51.4 +<?xml version="1.0" encoding="UTF-8"?>
51.5 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
51.6 + <modelVersion>4.0.0</modelVersion>
51.7 + <parent>
51.8 + <artifactId>javaquery</artifactId>
51.9 + <groupId>org.apidesign.bck2brwsr</groupId>
51.10 + <version>0.8-SNAPSHOT</version>
51.11 + </parent>
51.12 +
51.13 + <groupId>org.apidesign.bck2brwsr</groupId>
51.14 + <artifactId>demo-twitter</artifactId>
51.15 + <version>0.8-SNAPSHOT</version>
51.16 + <packaging>jar</packaging>
51.17 +
51.18 + <name>Bck2Brwsr's Twttr</name>
51.19 + <description>
51.20 + Rewrite of knockoutjs example to use model written in Java and
51.21 + execute using Bck2Brwsr virtual machine.
51.22 + </description>
51.23 +
51.24 + <repositories>
51.25 + <repository>
51.26 + <id>java.net</id>
51.27 + <name>Java.net</name>
51.28 + <url>https://maven.java.net/content/repositories/releases/</url>
51.29 + <snapshots>
51.30 + </snapshots>
51.31 + </repository>
51.32 + <repository>
51.33 + <id>netbeans</id>
51.34 + <name>NetBeans</name>
51.35 + <url>http://bits.netbeans.org/maven2/</url>
51.36 + </repository>
51.37 + </repositories>
51.38 + <pluginRepositories>
51.39 + <pluginRepository>
51.40 + <id>java.net</id>
51.41 + <name>Java.net</name>
51.42 + <url>https://maven.java.net/content/repositories/releases/</url>
51.43 + <snapshots>
51.44 + </snapshots>
51.45 + </pluginRepository>
51.46 + </pluginRepositories>
51.47 +
51.48 + <properties>
51.49 + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
51.50 + <bck2brwsr.obfuscationlevel>MINIMAL</bck2brwsr.obfuscationlevel>
51.51 + </properties>
51.52 + <build>
51.53 + <plugins>
51.54 + <plugin>
51.55 + <groupId>org.apidesign.bck2brwsr</groupId>
51.56 + <artifactId>bck2brwsr-maven-plugin</artifactId>
51.57 + <version>${project.version}</version>
51.58 + <executions>
51.59 + <execution>
51.60 + <goals>
51.61 + <goal>brwsr</goal>
51.62 + <goal>j2js</goal>
51.63 + </goals>
51.64 + </execution>
51.65 + </executions>
51.66 + <configuration>
51.67 + <startpage>org/apidesign/bck2brwsr/demo/twitter/index.html</startpage>
51.68 + <javascript>${project.build.directory}/bck2brwsr.js</javascript>
51.69 + <obfuscation>${bck2brwsr.obfuscationlevel}</obfuscation>
51.70 + </configuration>
51.71 + </plugin>
51.72 + <plugin>
51.73 + <groupId>org.apache.maven.plugins</groupId>
51.74 + <artifactId>maven-compiler-plugin</artifactId>
51.75 + <version>2.3.2</version>
51.76 + <configuration>
51.77 + <source>1.7</source>
51.78 + <target>1.7</target>
51.79 + </configuration>
51.80 + </plugin>
51.81 + <plugin>
51.82 + <groupId>org.apache.maven.plugins</groupId>
51.83 + <artifactId>maven-jar-plugin</artifactId>
51.84 + <version>2.4</version>
51.85 + <configuration>
51.86 + <archive>
51.87 + <manifest>
51.88 + <addClasspath>true</addClasspath>
51.89 + <classpathPrefix>lib/</classpathPrefix>
51.90 + </manifest>
51.91 + </archive>
51.92 + </configuration>
51.93 + </plugin>
51.94 + <plugin>
51.95 + <groupId>org.apache.maven.plugins</groupId>
51.96 + <artifactId>maven-deploy-plugin</artifactId>
51.97 + <version>2.7</version>
51.98 + <configuration>
51.99 + <skip>true</skip>
51.100 + </configuration>
51.101 + </plugin>
51.102 + <plugin>
51.103 + <artifactId>maven-assembly-plugin</artifactId>
51.104 + <version>2.4</version>
51.105 + <executions>
51.106 + <execution>
51.107 + <id>distro-assembly</id>
51.108 + <phase>package</phase>
51.109 + <goals>
51.110 + <goal>single</goal>
51.111 + </goals>
51.112 + <configuration>
51.113 + <descriptors>
51.114 + <descriptor>bck2brwsr-assembly.xml</descriptor>
51.115 + </descriptors>
51.116 + </configuration>
51.117 + </execution>
51.118 + </executions>
51.119 + </plugin>
51.120 + </plugins>
51.121 + </build>
51.122 +
51.123 + <dependencies>
51.124 + <dependency>
51.125 + <groupId>org.apidesign.bck2brwsr</groupId>
51.126 + <artifactId>emul</artifactId>
51.127 + <version>${project.version}</version>
51.128 + <classifier>rt</classifier>
51.129 + </dependency>
51.130 + <dependency>
51.131 + <groupId>org.apidesign.bck2brwsr</groupId>
51.132 + <artifactId>javaquery.api</artifactId>
51.133 + <version>${project.version}</version>
51.134 + </dependency>
51.135 + <dependency>
51.136 + <groupId>org.testng</groupId>
51.137 + <artifactId>testng</artifactId>
51.138 + <version>6.5.2</version>
51.139 + <scope>test</scope>
51.140 + </dependency>
51.141 + <dependency>
51.142 + <groupId>org.apidesign.bck2brwsr</groupId>
51.143 + <artifactId>vmtest</artifactId>
51.144 + <version>${project.version}</version>
51.145 + <scope>test</scope>
51.146 + </dependency>
51.147 + <dependency>
51.148 + <groupId>org.apidesign.bck2brwsr</groupId>
51.149 + <artifactId>launcher.http</artifactId>
51.150 + <version>${project.version}</version>
51.151 + <scope>runtime</scope>
51.152 + </dependency>
51.153 + </dependencies>
51.154 +</project>
52.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
52.2 +++ b/javaquery/demo-twitter/src/main/java/org/apidesign/bck2brwsr/demo/twitter/TwitterClient.java Thu May 02 09:18:22 2013 +0200
52.3 @@ -0,0 +1,194 @@
52.4 +/**
52.5 + * Back 2 Browser Bytecode Translator
52.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
52.7 + *
52.8 + * This program is free software: you can redistribute it and/or modify
52.9 + * it under the terms of the GNU General Public License as published by
52.10 + * the Free Software Foundation, version 2 of the License.
52.11 + *
52.12 + * This program is distributed in the hope that it will be useful,
52.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
52.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
52.15 + * GNU General Public License for more details.
52.16 + *
52.17 + * You should have received a copy of the GNU General Public License
52.18 + * along with this program. Look for COPYING file in the top folder.
52.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
52.20 + */
52.21 +package org.apidesign.bck2brwsr.demo.twitter;
52.22 +
52.23 +import java.util.Arrays;
52.24 +import java.util.List;
52.25 +import org.apidesign.bck2brwsr.htmlpage.api.*;
52.26 +import org.apidesign.bck2brwsr.htmlpage.api.Page;
52.27 +import org.apidesign.bck2brwsr.htmlpage.api.Property;
52.28 +import org.apidesign.bck2brwsr.htmlpage.api.ComputedProperty;
52.29 +
52.30 +/** Controller class for access to Twitter.
52.31 + *
52.32 + * @author Jaroslav Tulach
52.33 + */
52.34 +@Page(xhtml="index.html", className="TwitterModel", properties={
52.35 + @Property(name="savedLists", type=Tweeters.class, array = true),
52.36 + @Property(name="activeTweetersName", type=String.class),
52.37 + @Property(name="activeTweeters", type=String.class, array = true),
52.38 + @Property(name="userNameToAdd", type=String.class),
52.39 + @Property(name="currentTweets", type=Tweet.class, array = true)
52.40 +})
52.41 +public class TwitterClient {
52.42 + @Model(className = "Tweeters", properties = {
52.43 + @Property(name="name", type = String.class),
52.44 + @Property(name="userNames", type = String.class, array = true)
52.45 + })
52.46 + static class Twttrs {
52.47 + }
52.48 + @Model(className = "Tweet", properties = {
52.49 + @Property(name = "from_user", type = String.class),
52.50 + @Property(name = "from_user_id", type = int.class),
52.51 + @Property(name = "profile_image_url", type = String.class),
52.52 + @Property(name = "text", type = String.class),
52.53 + @Property(name = "created_at", type = String.class),
52.54 + })
52.55 + static final class Twt {
52.56 + @ComputedProperty static String html(String text) {
52.57 + StringBuilder sb = new StringBuilder(320);
52.58 + for (int pos = 0;;) {
52.59 + int http = text.indexOf("http", pos);
52.60 + if (http == -1) {
52.61 + sb.append(text.substring(pos));
52.62 + return sb.toString();
52.63 + }
52.64 + int spc = text.indexOf(' ', http);
52.65 + if (spc == -1) {
52.66 + spc = text.length();
52.67 + }
52.68 + sb.append(text.substring(pos, http));
52.69 + String url = text.substring(http, spc);
52.70 + sb.append("<a href='").append(url).append("'>").append(url).append("</a>");
52.71 + pos = spc;
52.72 + }
52.73 + }
52.74 +
52.75 + @ComputedProperty static String userUrl(String from_user) {
52.76 + return "http://twitter.com/" + from_user;
52.77 + }
52.78 + }
52.79 + @Model(className = "TwitterQuery", properties = {
52.80 + @Property(array = true, name = "results", type = Twt.class)
52.81 + })
52.82 + public static final class TwttrQr {
52.83 + }
52.84 +
52.85 + @OnReceive(url="{root}/search.json?{query}&callback={me}", jsonp="me")
52.86 + static void queryTweets(TwitterModel page, TwitterQuery q) {
52.87 + page.getCurrentTweets().clear();
52.88 + page.getCurrentTweets().addAll(q.getResults());
52.89 + }
52.90 +
52.91 + @OnPropertyChange("activeTweetersName")
52.92 + static void changeTweetersList(TwitterModel model) {
52.93 + Tweeters people = findByName(model.getSavedLists(), model.getActiveTweetersName());
52.94 + model.getActiveTweeters().clear();
52.95 + model.getActiveTweeters().addAll(people.getUserNames());
52.96 + }
52.97 +
52.98 + @OnPropertyChange({ "activeTweeters", "activeTweetersCount" })
52.99 + static void refreshTweets(TwitterModel model) {
52.100 + StringBuilder sb = new StringBuilder();
52.101 + sb.append("rpp=25&q=");
52.102 + String sep = "";
52.103 + for (String p : model.getActiveTweeters()) {
52.104 + sb.append(sep);
52.105 + sb.append("from:");
52.106 + sb.append(p);
52.107 + sep = " OR ";
52.108 + }
52.109 + model.queryTweets("http://search.twitter.com", sb.toString());
52.110 + }
52.111 +
52.112 + static {
52.113 + final TwitterModel model = new TwitterModel();
52.114 + final List<Tweeters> svdLst = model.getSavedLists();
52.115 + svdLst.add(newTweeters("API Design", "JaroslavTulach"));
52.116 + svdLst.add(newTweeters("Celebrities", "JohnCleese", "MCHammer", "StephenFry", "algore", "StevenSanderson"));
52.117 + svdLst.add(newTweeters("Microsoft people", "BillGates", "shanselman", "ScottGu"));
52.118 + svdLst.add(newTweeters("NetBeans", "GeertjanW","monacotoni", "NetBeans", "petrjiricka"));
52.119 + svdLst.add(newTweeters("Tech pundits", "Scobleizer", "LeoLaporte", "techcrunch", "BoingBoing", "timoreilly", "codinghorror"));
52.120 +
52.121 + model.setActiveTweetersName("NetBeans");
52.122 +
52.123 + model.applyBindings();
52.124 + }
52.125 +
52.126 + @ComputedProperty
52.127 + static boolean hasUnsavedChanges(List<String> activeTweeters, List<Tweeters> savedLists, String activeTweetersName) {
52.128 + Tweeters tw = findByName(savedLists, activeTweetersName);
52.129 + if (activeTweeters == null) {
52.130 + return false;
52.131 + }
52.132 + return !tw.getUserNames().equals(activeTweeters);
52.133 + }
52.134 +
52.135 + @ComputedProperty
52.136 + static int activeTweetersCount(List<String> activeTweeters) {
52.137 + return activeTweeters.size();
52.138 + }
52.139 +
52.140 + @ComputedProperty
52.141 + static boolean userNameToAddIsValid(
52.142 + String userNameToAdd, String activeTweetersName, List<Tweeters> savedLists, List<String> activeTweeters
52.143 + ) {
52.144 + return userNameToAdd != null &&
52.145 + userNameToAdd.matches("[a-zA-Z0-9_]{1,15}") &&
52.146 + !activeTweeters.contains(userNameToAdd);
52.147 + }
52.148 +
52.149 + @OnFunction
52.150 + static void deleteList(TwitterModel model) {
52.151 + final List<Tweeters> sl = model.getSavedLists();
52.152 + sl.remove(findByName(sl, model.getActiveTweetersName()));
52.153 + if (sl.isEmpty()) {
52.154 + final Tweeters t = new Tweeters();
52.155 + t.setName("New");
52.156 + sl.add(t);
52.157 + }
52.158 + model.setActiveTweetersName(sl.get(0).getName());
52.159 + }
52.160 +
52.161 + @OnFunction
52.162 + static void saveChanges(TwitterModel model) {
52.163 + Tweeters t = findByName(model.getSavedLists(), model.getActiveTweetersName());
52.164 + int indx = model.getSavedLists().indexOf(t);
52.165 + if (indx != -1) {
52.166 + t.setName(model.getActiveTweetersName());
52.167 + t.getUserNames().clear();
52.168 + t.getUserNames().addAll(model.getActiveTweeters());
52.169 + }
52.170 + }
52.171 +
52.172 + @OnFunction
52.173 + static void addUser(TwitterModel model) {
52.174 + String n = model.getUserNameToAdd();
52.175 + model.getActiveTweeters().add(n);
52.176 + }
52.177 + @OnFunction
52.178 + static void removeUser(String data, TwitterModel model) {
52.179 + model.getActiveTweeters().remove(data);
52.180 + }
52.181 +
52.182 + private static Tweeters findByName(List<Tweeters> list, String name) {
52.183 + for (Tweeters l : list) {
52.184 + if (l.getName() != null && l.getName().equals(name)) {
52.185 + return l;
52.186 + }
52.187 + }
52.188 + return list.isEmpty() ? new Tweeters() : list.get(0);
52.189 + }
52.190 +
52.191 + private static Tweeters newTweeters(String listName, String... userNames) {
52.192 + Tweeters t = new Tweeters();
52.193 + t.setName(listName);
52.194 + t.getUserNames().addAll(Arrays.asList(userNames));
52.195 + return t;
52.196 + }
52.197 +}
53.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
53.2 +++ b/javaquery/demo-twitter/src/main/resources/org/apidesign/bck2brwsr/demo/twitter/index.html Thu May 02 09:18:22 2013 +0200
53.3 @@ -0,0 +1,99 @@
53.4 +<?xml version="1.0" encoding="UTF-8"?>
53.5 +<!--
53.6 +
53.7 + Back 2 Browser Bytecode Translator
53.8 + Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
53.9 +
53.10 + This program is free software: you can redistribute it and/or modify
53.11 + it under the terms of the GNU General Public License as published by
53.12 + the Free Software Foundation, version 2 of the License.
53.13 +
53.14 + This program is distributed in the hope that it will be useful,
53.15 + but WITHOUT ANY WARRANTY; without even the implied warranty of
53.16 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
53.17 + GNU General Public License for more details.
53.18 +
53.19 + You should have received a copy of the GNU General Public License
53.20 + along with this program. Look for COPYING file in the top folder.
53.21 + If not, see http://opensource.org/licenses/GPL-2.0.
53.22 +
53.23 +-->
53.24 +
53.25 +<!--
53.26 + Copied from knockout.js Twitter example:
53.27 + http://knockoutjs.com/examples/twitter.html
53.28 +-->
53.29 +
53.30 +<!DOCTYPE html>
53.31 +<html xmlns="http://www.w3.org/1999/xhtml">
53.32 + <head>
53.33 + <title>Bck2Brwsr's Twitter</title>
53.34 + </head>
53.35 + <body>
53.36 + <link href='twitterExample.css' rel='Stylesheet' ></link>
53.37 +
53.38 + <style type='text/css'>
53.39 + .liveExample select { height: 1.7em; }
53.40 + .liveExample button { height: 2em; }
53.41 + </style>
53.42 +
53.43 +
53.44 + <h2>Bck2Brwsr's Twitter</h2>
53.45 +
53.46 + <p>
53.47 + This code based on original <a href="http://knockoutjs.com/examples/twitter.html">knockout.js Twitter example</a> and
53.48 + uses almost unmodified HTML code. It just changes the model. It
53.49 + is written in Java language and it is executed using <a href="http://bck2brwsr.apidesign.org">Bck2Brwsr</a>
53.50 + virtual machine. The Java source code has about 190 lines and is available
53.51 + <a href="http://source.apidesign.org/hg/bck2brwsr/file/7fc6b7e9c982/javaquery/demo-twitter/src/main/java/org/apidesign/bck2brwsr/demo/twitter/TwitterClient.java">here</a>
53.52 + - in fact it may even be more dense than the original JavaScript model.
53.53 + </p>
53.54 +
53.55 + <div class='liveExample'>
53.56 + <div class='configuration'>
53.57 + <div class='listChooser'>
53.58 + <button data-bind='click: deleteList, enable: activeTweetersName'>Delete</button>
53.59 + <button data-bind='click: saveChanges, enable: hasUnsavedChanges'>Save</button>
53.60 + <select data-bind='options: savedLists, optionsValue: "name", value: activeTweetersName'> </select>
53.61 + </div>
53.62 +
53.63 + <p>Currently viewing <span data-bind='text: activeTweetersCount'> </span> user(s):</p>
53.64 + <div class='currentUsers' >
53.65 + <ul data-bind='foreach: activeTweeters'>
53.66 + <li>
53.67 + <button data-bind='click: $root.removeUser'>Remove</button>
53.68 + <div data-bind='text: $data'> </div>
53.69 + </li>
53.70 + </ul>
53.71 + </div>
53.72 +
53.73 + <form data-bind='submit: addUser'>
53.74 + <label>Add user:</label>
53.75 + <input data-bind='value: userNameToAdd, valueUpdate: "keyup", css: { invalid: !userNameToAddIsValid() }' />
53.76 + <button data-bind='enable: userNameToAddIsValid' type='submit'>Add</button>
53.77 + </form>
53.78 + </div>
53.79 + <div class='tweets'>
53.80 + <div class='loadingIndicator'>Loading...</div>
53.81 + <table data-bind='foreach: currentTweets' width='100%'>
53.82 + <tr>
53.83 + <td><img data-bind='attr: { src: profile_image_url }' /></td>
53.84 + <td>
53.85 + <a class='twitterUser' data-bind='attr: { href: userUrl }, text: from_user'> </a>
53.86 + <span data-bind='html: html'> </span>
53.87 + <div class='tweetInfo' data-bind='text: created_at'> </div>
53.88 + </td>
53.89 + </tr>
53.90 + </table>
53.91 + </div>
53.92 + </div>
53.93 +
53.94 + <script src="bck2brwsr.js"></script>
53.95 + <script type="text/javascript">
53.96 + var vm = bck2brwsr('demo-twitter-0.8-SNAPSHOT.jar');
53.97 + vm.loadClass('org.apidesign.bck2brwsr.demo.twitter.TwitterClient');
53.98 + </script>
53.99 +
53.100 +
53.101 + </body>
53.102 +</html>
54.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
54.2 +++ b/javaquery/demo-twitter/src/main/resources/org/apidesign/bck2brwsr/demo/twitter/twitterExample.css Thu May 02 09:18:22 2013 +0200
54.3 @@ -0,0 +1,50 @@
54.4 +/**
54.5 + * Back 2 Browser Bytecode Translator
54.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
54.7 + *
54.8 + * This program is free software: you can redistribute it and/or modify
54.9 + * it under the terms of the GNU General Public License as published by
54.10 + * the Free Software Foundation, version 2 of the License.
54.11 + *
54.12 + * This program is distributed in the hope that it will be useful,
54.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
54.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
54.15 + * GNU General Public License for more details.
54.16 + *
54.17 + * You should have received a copy of the GNU General Public License
54.18 + * along with this program. Look for COPYING file in the top folder.
54.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
54.20 + */
54.21 +
54.22 +/*
54.23 + Copied from knockout.js Twitter example:
54.24 + http://knockoutjs.com/examples/twitter.html
54.25 +*/
54.26 +
54.27 +.configuration, .tweets, .tweets td { font-family: Verdana; font-size: 13px; }
54.28 +.configuration { background-color: #DEDEDE; border: 2px solid gray; float:left; height: 40em; width: 40%; padding: 0.5em; border-right-width:0; }
54.29 +.tweets { width: 55%; border: 2px solid gray; height: 40em; overflow: scroll; overflow-x: hidden; background-color: Black; color: White; padding: 0.5em; position: relative; }
54.30 +.tweets table { border-width: 0;}
54.31 +.tweets tr { vertical-align: top; }
54.32 +.tweets td { padding: 0.4em 0.3em 1em 0.4em; border-width: 0; }
54.33 +.tweets img { width: 4em; }
54.34 +.tweetInfo { color: Gray; font-size: 0.9em; }
54.35 +.twitterUser { color: #77AAFF; text-decoration: none; font-size: 1.1em; font-weight: bold; }
54.36 +input.invalid { border: 1px solid red !important; background-color: #FFAAAA !important; }
54.37 +
54.38 +.listChooser select, .listChooser button { vertical-align:top; }
54.39 +.listChooser select { width: 60%; font-size:1.2em; height:1.4em; }
54.40 +.listChooser button { width: 19%; height:1.68em; float:right; }
54.41 +
54.42 +.currentUsers { height: 28em; overflow-y: auto; overflow-x: hidden; }
54.43 +.currentUsers button { float: right; height: 2.5em; margin: 0.1em; padding-left: 1em; padding-right: 1em; }
54.44 +.currentUsers ul, .configuration li { list-style: none; margin: 0; padding: 0 }
54.45 +.currentUsers li { height: 2.4em; font-size: 1.2em; background-color: #A7D0E3; border: 1px solid gray; margin-bottom: 0.3em; -webkit-border-radius: 5px; -moz-border-radius: 5px; -webkit-box-shadow: 0 0.2em 0.5em gray; -moz-box-shadow: 0 0.2em 0.5em gray; }
54.46 +.currentUsers li div { padding: 0.6em; }
54.47 +.currentUsers li:hover { background-color: #EEC; }
54.48 +
54.49 +.configuration form label { width: 25%; display: inline-block; text-align:right; overflow: hidden; }
54.50 +.configuration form input { width:40%; font-size: 1.3em; border:1px solid silver; background-color: White; padding: 0.1em; }
54.51 +.configuration form button { width: 20%; margin-left: 0.3em; height: 2em; }
54.52 +
54.53 +.loadingIndicator { position: absolute; top: 0.1em; left: 0.1em; font: 0.8em Arial; background-color: #229; color: White; padding: 0.2em 0.5em 0.2em 0.5em; display: none; }
55.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
55.2 +++ b/javaquery/demo-twitter/src/test/java/org/apidesign/bck2brwsr/demo/twitter/TwitterClientTest.java Thu May 02 09:18:22 2013 +0200
55.3 @@ -0,0 +1,67 @@
55.4 +/**
55.5 + * Back 2 Browser Bytecode Translator
55.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
55.7 + *
55.8 + * This program is free software: you can redistribute it and/or modify
55.9 + * it under the terms of the GNU General Public License as published by
55.10 + * the Free Software Foundation, version 2 of the License.
55.11 + *
55.12 + * This program is distributed in the hope that it will be useful,
55.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
55.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
55.15 + * GNU General Public License for more details.
55.16 + *
55.17 + * You should have received a copy of the GNU General Public License
55.18 + * along with this program. Look for COPYING file in the top folder.
55.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
55.20 + */
55.21 +package org.apidesign.bck2brwsr.demo.twitter;
55.22 +
55.23 +import java.util.List;
55.24 +import static org.testng.Assert.*;
55.25 +import org.testng.annotations.BeforeMethod;
55.26 +import org.testng.annotations.Test;
55.27 +
55.28 +/** We can unit test the TwitterModel smoothly.
55.29 + *
55.30 + * @author Jaroslav Tulach <jtulach@netbeans.org>
55.31 + */
55.32 +public class TwitterClientTest {
55.33 + private TwitterModel model;
55.34 +
55.35 +
55.36 + @BeforeMethod
55.37 + public void initModel() {
55.38 + model = new TwitterModel().applyBindings();
55.39 + }
55.40 +
55.41 + @Test public void testIsValidToAdd() {
55.42 + model.setUserNameToAdd("Joe");
55.43 + Tweeters t = new Tweeters();
55.44 + t.setName("test");
55.45 + model.getSavedLists().add(t);
55.46 + model.setActiveTweetersName("test");
55.47 +
55.48 + assertTrue(model.isUserNameToAddIsValid(), "Joe is OK");
55.49 + TwitterClient.addUser(model);
55.50 + assertFalse(model.isUserNameToAddIsValid(), "Can't add Joe for the 2nd time");
55.51 + assertEquals(t.getUserNames().size(), 0, "Original tweeters list remains empty");
55.52 +
55.53 + List<String> mod = model.getActiveTweeters();
55.54 + assertTrue(model.isHasUnsavedChanges(), "We have modifications");
55.55 + assertEquals(mod.size(), 1, "One element in the list");
55.56 + assertEquals(mod.get(0), "Joe", "Its name is Joe");
55.57 +
55.58 + assertSame(model.getActiveTweeters(), mod, "Editing list is the modified one");
55.59 +
55.60 + TwitterClient.saveChanges(model);
55.61 + assertFalse(model.isHasUnsavedChanges(), "Does not have anything to save");
55.62 +
55.63 + assertSame(model.getActiveTweeters(), mod, "Still editing the old modified one");
55.64 + }
55.65 +
55.66 + @Test public void httpAtTheEnd() {
55.67 + String res = TwitterClient.Twt.html("Ahoj http://kuk");
55.68 + assertEquals(res, "Ahoj <a href='http://kuk'>http://kuk</a>");
55.69 + }
55.70 +}
56.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
56.2 +++ b/javaquery/demo-twitter/src/test/java/org/apidesign/bck2brwsr/demo/twitter/TwitterProtocolTest.java Thu May 02 09:18:22 2013 +0200
56.3 @@ -0,0 +1,94 @@
56.4 +/**
56.5 + * Back 2 Browser Bytecode Translator
56.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
56.7 + *
56.8 + * This program is free software: you can redistribute it and/or modify
56.9 + * it under the terms of the GNU General Public License as published by
56.10 + * the Free Software Foundation, version 2 of the License.
56.11 + *
56.12 + * This program is distributed in the hope that it will be useful,
56.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
56.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
56.15 + * GNU General Public License for more details.
56.16 + *
56.17 + * You should have received a copy of the GNU General Public License
56.18 + * along with this program. Look for COPYING file in the top folder.
56.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
56.20 + */
56.21 +package org.apidesign.bck2brwsr.demo.twitter;
56.22 +
56.23 +import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
56.24 +import org.apidesign.bck2brwsr.vmtest.Http;
56.25 +import org.apidesign.bck2brwsr.vmtest.VMTest;
56.26 +import org.testng.annotations.Factory;
56.27 +
56.28 +/**
56.29 + *
56.30 + * @author Jaroslav Tulach <jtulach@netbeans.org>
56.31 + */
56.32 +public class TwitterProtocolTest {
56.33 + private TwitterModel page;
56.34 + @Http(@Http.Resource(
56.35 + path = "/search.json",
56.36 + mimeType = "application/json",
56.37 + parameters = {"callback"},
56.38 + content = "$0({\"completed_in\":0.04,\"max_id\":320055706885689344,\"max_id_str\""
56.39 + + ":\"320055706885689344\",\"page\":1,\"query\":\"from%3AJaroslavTulach\",\"refresh_url\":"
56.40 + + "\"?since_id=320055706885689344&q=from%3AJaroslavTulach\","
56.41 + + "\"results\":[{\"created_at\":\"Fri, 05 Apr 2013 06:10:01 +0000\","
56.42 + + "\"from_user\":\"JaroslavTulach\",\"from_user_id\":420944648,\"from_user_id_str\":"
56.43 + + "\"420944648\",\"from_user_name\":\"Jaroslav Tulach\",\"geo\":null,\"id\":320055706885689344,"
56.44 + + "\"id_str\":\"320055706885689344\",\"iso_language_code\":\"en\",\"metadata\":{\"result_type\":"
56.45 + + "\"recent\"},\"profile_image_url\":\"http:\\/\\/a0.twimg.com\\/profile_images\\/1656828312\\/jst_normal.gif\","
56.46 + + "\"profile_image_url_https\":\"https:\\/\\/si0.twimg.com\\/profile_images\\/1656828312\\/jst_normal.gif\","
56.47 + + "\"source\":\"<a href="http:\\/\\/twitter.com\\/">web<\\/a>\",\"text\":"
56.48 + + "\"@tom_enebo Amzng! Not that I would like #ruby, but I am really glad you guys stabilized the plugin + "
56.49 + + "made it work in #netbeans 7.3! Gd wrk.\",\"to_user\":\"tom_enebo\",\"to_user_id\":14498747,"
56.50 + + "\"to_user_id_str\":\"14498747\",\"to_user_name\":\"tom_enebo\",\"in_reply_to_status_id\":319832359509839872,"
56.51 + + "\"in_reply_to_status_id_str\":\"319832359509839872\"},{\"created_at\":\"Thu, 04 Apr 2013 07:33:06 +0000\","
56.52 + + "\"from_user\":\"JaroslavTulach\",\"from_user_id\":420944648,\"from_user_id_str\":"
56.53 + + "\"420944648\",\"from_user_name\":\"Jaroslav Tulach\",\"geo\":null,\"id\":319714227088678913,"
56.54 + + "\"id_str\":\"319714227088678913\",\"iso_language_code\":\"en\",\"metadata\":{\"result_type\":"
56.55 + + "\"recent\"},\"profile_image_url\":\"http:\\/\\/a0.twimg.com\\/profile_images\\/1656828312\\/jst_normal.gif\","
56.56 + + "\"profile_image_url_https\":\"https:\\/\\/si0.twimg.com\\/profile_images\\/1656828312\\/jst_normal.gif\","
56.57 + + "\"source\":\"<a href="http:\\/\\/twitter.com\\/">web<\\/a>\",\"text\":"
56.58 + + "\"RT @drkrab: At #erlangfactory @joerl: Frameworks grow in complexity until nobody can use them.\"},"
56.59 + + "{\"created_at\":\"Tue, 02 Apr 2013 07:44:34 +0000\",\"from_user\":\"JaroslavTulach\","
56.60 + + "\"from_user_id\":420944648,\"from_user_id_str\":\"420944648\",\"from_user_name\":\"Jaroslav Tulach\","
56.61 + + "\"geo\":null,\"id\":318992336145248256,\"id_str\":\"318992336145248256\",\"iso_language_code\":\"en\","
56.62 + + "\"metadata\":{\"result_type\":\"recent\"},\"profile_image_url\":"
56.63 + + "\"http:\\/\\/a0.twimg.com\\/profile_images\\/1656828312\\/jst_normal.gif\","
56.64 + + "\"profile_image_url_https\":\"https:\\/\\/si0.twimg.com\\/profile_images\\/1656828312\\/jst_normal.gif\","
56.65 + + "\"source\":\"<a href="http:\\/\\/twitter.com\\/">web<\\/a>\",\"text\":"
56.66 + + "\"Twitter renamed to twttr http:\\/\\/t.co\\/tqaN4T1xlZ - good, I don't have to rename #bck2brwsr!\"},"
56.67 + + "{\"created_at\":\"Sun, 31 Mar 2013 03:52:04 +0000\",\"from_user\":\"JaroslavTulach\",\"from_user_id\":420944648,"
56.68 + + "\"from_user_id_str\":\"420944648\",\"from_user_name\":\"Jaroslav Tulach\",\"geo\":null,"
56.69 + + "\"id\":318209051223789568,\"id_str\":\"318209051223789568\",\"iso_language_code\":\"en\",\"metadata\":"
56.70 + + "{\"result_type\":\"recent\"},\"profile_image_url\":"
56.71 + + "\"http:\\/\\/a0.twimg.com\\/profile_images\\/1656828312\\/jst_normal.gif\","
56.72 + + "\"profile_image_url_https\":\"https:\\/\\/si0.twimg.com\\/profile_images\\/1656828312\\/jst_normal.gif\","
56.73 + + "\"source\":\"<a href="http:\\/\\/twitter.com\\/">web<\\/a>\",\"text\":"
56.74 + + "\"Math proofs without words. Ingenious: http:\\/\\/t.co\\/sz7yVbfpGw\"}],\"results_per_page\":100,"
56.75 + + "\"since_id\":0,\"since_id_str\":\"0\"})"
56.76 + ))
56.77 + @BrwsrTest public void readFromTwttr() throws InterruptedException {
56.78 + if (page == null) {
56.79 + page = new TwitterModel();
56.80 + page.applyBindings();
56.81 + page.queryTweets("", "q=xyz");
56.82 + }
56.83 +
56.84 + if (page.getCurrentTweets().isEmpty()) {
56.85 + throw new InterruptedException();
56.86 + }
56.87 +
56.88 + assert 4 == page.getCurrentTweets().size() : "Four tweets: " + page.getCurrentTweets();
56.89 +
56.90 + String firstDate = page.getCurrentTweets().get(0).getCreated_at();
56.91 + assert "Fri, 05 Apr 2013 06:10:01 +0000".equals(firstDate) : "Date is OK: " + firstDate;
56.92 + }
56.93 +
56.94 + @Factory public static Object[] create() {
56.95 + return VMTest.create(TwitterProtocolTest.class);
56.96 + }
56.97 +}
57.1 --- a/javaquery/pom.xml Tue Apr 02 15:40:51 2013 +0200
57.2 +++ b/javaquery/pom.xml Thu May 02 09:18:22 2013 +0200
57.3 @@ -4,16 +4,17 @@
57.4 <parent>
57.5 <artifactId>bck2brwsr</artifactId>
57.6 <groupId>org.apidesign</groupId>
57.7 - <version>0.5-SNAPSHOT</version>
57.8 + <version>0.8-SNAPSHOT</version>
57.9 </parent>
57.10 <groupId>org.apidesign.bck2brwsr</groupId>
57.11 <artifactId>javaquery</artifactId>
57.12 - <version>0.5-SNAPSHOT</version>
57.13 + <version>0.8-SNAPSHOT</version>
57.14 <packaging>pom</packaging>
57.15 <name>JavaQuery API and Demo</name>
57.16 <modules>
57.17 <module>api</module>
57.18 <module>demo-calculator</module>
57.19 <module>demo-calculator-dynamic</module>
57.20 - </modules>
57.21 -</project>
57.22 + <module>demo-twitter</module>
57.23 + </modules>
57.24 +</project>
57.25 \ No newline at end of file
58.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
58.2 +++ b/launcher/api/pom.xml Thu May 02 09:18:22 2013 +0200
58.3 @@ -0,0 +1,31 @@
58.4 +<?xml version="1.0"?>
58.5 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
58.6 + <modelVersion>4.0.0</modelVersion>
58.7 + <parent>
58.8 + <groupId>org.apidesign.bck2brwsr</groupId>
58.9 + <artifactId>launcher-pom</artifactId>
58.10 + <version>0.8-SNAPSHOT</version>
58.11 + </parent>
58.12 + <groupId>org.apidesign.bck2brwsr</groupId>
58.13 + <artifactId>launcher</artifactId>
58.14 + <version>0.8-SNAPSHOT</version>
58.15 + <name>Launcher API</name>
58.16 + <url>http://maven.apache.org</url>
58.17 + <properties>
58.18 + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
58.19 + </properties>
58.20 + <build>
58.21 + <plugins>
58.22 + <plugin>
58.23 + <groupId>org.apache.maven.plugins</groupId>
58.24 + <artifactId>maven-javadoc-plugin</artifactId>
58.25 + <configuration>
58.26 + <subpackages>org.apidesign.bck2brwsr.launcher</subpackages>
58.27 + <skip>false</skip>
58.28 + </configuration>
58.29 + </plugin>
58.30 + </plugins>
58.31 + </build>
58.32 + <dependencies>
58.33 + </dependencies>
58.34 +</project>
59.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
59.2 +++ b/launcher/api/src/main/java/org/apidesign/bck2brwsr/launcher/InvocationContext.java Thu May 02 09:18:22 2013 +0200
59.3 @@ -0,0 +1,115 @@
59.4 +/**
59.5 + * Back 2 Browser Bytecode Translator
59.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
59.7 + *
59.8 + * This program is free software: you can redistribute it and/or modify
59.9 + * it under the terms of the GNU General Public License as published by
59.10 + * the Free Software Foundation, version 2 of the License.
59.11 + *
59.12 + * This program is distributed in the hope that it will be useful,
59.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
59.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
59.15 + * GNU General Public License for more details.
59.16 + *
59.17 + * You should have received a copy of the GNU General Public License
59.18 + * along with this program. Look for COPYING file in the top folder.
59.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
59.20 + */
59.21 +package org.apidesign.bck2brwsr.launcher;
59.22 +
59.23 +import java.io.IOException;
59.24 +import java.io.InputStream;
59.25 +import java.util.ArrayList;
59.26 +import java.util.List;
59.27 +import java.util.concurrent.CountDownLatch;
59.28 +import java.util.concurrent.TimeUnit;
59.29 +
59.30 +/** Represents individual method invocation, its context and its result.
59.31 + *
59.32 + * @author Jaroslav Tulach <jtulach@netbeans.org>
59.33 + */
59.34 +public final class InvocationContext {
59.35 + final CountDownLatch wait = new CountDownLatch(1);
59.36 + final Class<?> clazz;
59.37 + final String methodName;
59.38 + private final Launcher launcher;
59.39 + private String result;
59.40 + private Throwable exception;
59.41 + String html;
59.42 + final List<Resource> resources = new ArrayList<>();
59.43 +
59.44 + InvocationContext(Launcher launcher, Class<?> clazz, String methodName) {
59.45 + this.launcher = launcher;
59.46 + this.clazz = clazz;
59.47 + this.methodName = methodName;
59.48 + }
59.49 +
59.50 + /** An HTML fragment to be available for the execution. Useful primarily when
59.51 + * executing in a browser via {@link Launcher#createBrowser(java.lang.String)}.
59.52 + * @param html the html fragment
59.53 + */
59.54 + public void setHtmlFragment(String html) {
59.55 + this.html = html;
59.56 + }
59.57 +
59.58 + /** HTTP resource to be available during execution. An invocation may
59.59 + * perform an HTTP query and obtain a resource relative to the page.
59.60 + */
59.61 + public void addHttpResource(String relativePath, String mimeType, String[] parameters, InputStream content) {
59.62 + if (relativePath == null || mimeType == null || content == null || parameters == null) {
59.63 + throw new NullPointerException();
59.64 + }
59.65 + resources.add(new Resource(content, mimeType, relativePath, parameters));
59.66 + }
59.67 +
59.68 + /** Invokes the associated method.
59.69 + * @return the textual result of the invocation
59.70 + */
59.71 + public String invoke() throws IOException {
59.72 + launcher.runMethod(this);
59.73 + return toString();
59.74 + }
59.75 +
59.76 + /** Obtains textual result of the invocation.
59.77 + * @return text representing the exception or result value
59.78 + */
59.79 + @Override
59.80 + public String toString() {
59.81 + if (exception != null) {
59.82 + return exception.toString();
59.83 + }
59.84 + return result;
59.85 + }
59.86 +
59.87 + /**
59.88 + * @param timeOut
59.89 + * @throws InterruptedException
59.90 + */
59.91 + void await(long timeOut) throws InterruptedException {
59.92 + wait.await(timeOut, TimeUnit.MILLISECONDS);
59.93 + }
59.94 +
59.95 + void result(String r, Throwable e) {
59.96 + this.result = r;
59.97 + this.exception = e;
59.98 + wait.countDown();
59.99 + }
59.100 +
59.101 +
59.102 + static final class Resource {
59.103 + final InputStream httpContent;
59.104 + final String httpType;
59.105 + final String httpPath;
59.106 + final String[] parameters;
59.107 +
59.108 + Resource(InputStream httpContent, String httpType, String httpPath,
59.109 + String[] parameters
59.110 + ) {
59.111 + httpContent.mark(Integer.MAX_VALUE);
59.112 + this.httpContent = httpContent;
59.113 + this.httpType = httpType;
59.114 + this.httpPath = httpPath;
59.115 + this.parameters = parameters;
59.116 + }
59.117 + }
59.118 +}
60.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
60.2 +++ b/launcher/api/src/main/java/org/apidesign/bck2brwsr/launcher/Launcher.java Thu May 02 09:18:22 2013 +0200
60.3 @@ -0,0 +1,166 @@
60.4 +/**
60.5 + * Back 2 Browser Bytecode Translator
60.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
60.7 + *
60.8 + * This program is free software: you can redistribute it and/or modify
60.9 + * it under the terms of the GNU General Public License as published by
60.10 + * the Free Software Foundation, version 2 of the License.
60.11 + *
60.12 + * This program is distributed in the hope that it will be useful,
60.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
60.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
60.15 + * GNU General Public License for more details.
60.16 + *
60.17 + * You should have received a copy of the GNU General Public License
60.18 + * along with this program. Look for COPYING file in the top folder.
60.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
60.20 + */
60.21 +package org.apidesign.bck2brwsr.launcher;
60.22 +
60.23 +import java.io.Closeable;
60.24 +import java.io.File;
60.25 +import java.io.IOException;
60.26 +import java.lang.reflect.Constructor;
60.27 +
60.28 +/** An abstraction for executing tests in a Bck2Brwsr virtual machine.
60.29 + * Either in {@link Launcher#createJavaScript JavaScript engine},
60.30 + * or in {@link Launcher#createBrowser external browser}.
60.31 + * <p>
60.32 + * There also are methods to {@link #showDir(java.io.File, java.lang.String) display pages}
60.33 + * in an external browser served by internal HTTP server.
60.34 + *
60.35 + * @author Jaroslav Tulach <jtulach@netbeans.org>
60.36 + */
60.37 +public abstract class Launcher {
60.38 +
60.39 + Launcher() {
60.40 + }
60.41 +
60.42 + /** Initializes the launcher. This may mean starting a web browser or
60.43 + * initializing execution engine.
60.44 + * @throws IOException if something goes wrong
60.45 + */
60.46 + public abstract void initialize() throws IOException;
60.47 +
60.48 + /** Shuts down the launcher.
60.49 + * @throws IOException if something goes wrong
60.50 + */
60.51 + public abstract void shutdown() throws IOException;
60.52 +
60.53 +
60.54 + /** Builds an invocation context. The context can later be customized
60.55 + * and {@link InvocationContext#invoke() invoked}.
60.56 + *
60.57 + * @param clazz the class to execute method from
60.58 + * @param method the method to execute
60.59 + * @return the context pointing to the selected method
60.60 + */
60.61 + public InvocationContext createInvocation(Class<?> clazz, String method) {
60.62 + return new InvocationContext(this, clazz, method);
60.63 + }
60.64 +
60.65 +
60.66 + /** Creates launcher that uses internal JavaScript engine (Rhino).
60.67 + * @return the launcher
60.68 + */
60.69 + public static Launcher createJavaScript() {
60.70 + try {
60.71 + Class<?> c = loadClass("org.apidesign.bck2brwsr.launcher.JSLauncher");
60.72 + return (Launcher) c.newInstance();
60.73 + } catch (Exception ex) {
60.74 + throw new IllegalStateException("Please include org.apidesign.bck2brwsr:launcher.html dependency!", ex);
60.75 + }
60.76 + }
60.77 +
60.78 + /** Creates launcher that is using external browser.
60.79 + *
60.80 + * @param cmd <code>null</code> to use <code>java.awt.Desktop</code> to show the launcher
60.81 + * or a string to execute in an external process (with a parameter to the URL)
60.82 + * @return launcher executing in external browser.
60.83 + */
60.84 + public static Launcher createBrowser(String cmd) {
60.85 + String msg = "Trying to create browser '" + cmd + "'";
60.86 + try {
60.87 + Class<?> c;
60.88 + if ("fxbrwsr".equals(cmd)) { // NOI18N
60.89 + msg = "Please include org.apidesign.bck2brwsr:launcher.fx dependency!";
60.90 + c = loadClass("org.apidesign.bck2brwsr.launcher.FXBrwsrLauncher"); // NOI18N
60.91 + } else {
60.92 + msg = "Please include org.apidesign.bck2brwsr:launcher.html dependency!";
60.93 + c = loadClass("org.apidesign.bck2brwsr.launcher.Bck2BrwsrLauncher"); // NOI18N
60.94 + if ("bck2brwsr".equals(cmd)) { // NOI18N
60.95 + // use default executable
60.96 + cmd = null;
60.97 + }
60.98 + }
60.99 + Constructor<?> cnstr = c.getConstructor(String.class);
60.100 + return (Launcher) cnstr.newInstance(cmd);
60.101 + } catch (Exception ex) {
60.102 + throw new IllegalStateException(msg, ex);
60.103 + }
60.104 + }
60.105 +
60.106 + /** Starts an HTTP server which provides access to classes and resources
60.107 + * available in the <code>classes</code> URL and shows a start page
60.108 + * available as {@link ClassLoader#getResource(java.lang.String)} from the
60.109 + * provide classloader. Opens a browser with URL showing the start page.
60.110 + *
60.111 + * @param classes classloader offering access to classes and resources
60.112 + * @param startpage page to show in the browser
60.113 + * @return interface that allows one to stop the server
60.114 + * @throws IOException if something goes wrong
60.115 + */
60.116 + public static Closeable showURL(ClassLoader classes, String startpage) throws IOException {
60.117 + return showURL(null, classes, startpage);
60.118 + }
60.119 + /** Starts an HTTP server which provides access to classes and resources
60.120 + * available in the <code>classes</code> URL and shows a start page
60.121 + * available as {@link ClassLoader#getResource(java.lang.String)} from the
60.122 + * provide classloader. Opens a browser with URL showing the start page.
60.123 + *
60.124 + * @param brwsr name of browser to use or <code>null</code>
60.125 + * @param classes classloader offering access to classes and resources
60.126 + * @param startpage page to show in the browser
60.127 + * @return interface that allows one to stop the server
60.128 + * @throws IOException if something goes wrong
60.129 + * @since 0.7
60.130 + */
60.131 + public static Closeable showURL(String brwsr, ClassLoader classes, String startpage) throws IOException {
60.132 + Launcher l = createBrowser(brwsr);
60.133 + l.addClassLoader(classes);
60.134 + l.showURL(startpage);
60.135 + return (Closeable) l;
60.136 + }
60.137 + /** Starts an HTTP server which provides access to certain directory.
60.138 + * The <code>startpage</code> should be relative location inside the root
60.139 + * directory. Opens a browser with URL showing the start page.
60.140 + *
60.141 + * @param directory the root directory on disk
60.142 + * @param startpage relative path from the root to the page
60.143 + * @exception IOException if something goes wrong.
60.144 + */
60.145 + public static Closeable showDir(File directory, String startpage) throws IOException {
60.146 + Launcher l = createBrowser(null);
60.147 + l.showDirectory(directory, startpage);
60.148 + return (Closeable) l;
60.149 + }
60.150 +
60.151 + abstract InvocationContext runMethod(InvocationContext c) throws IOException;
60.152 +
60.153 +
60.154 + private static Class<?> loadClass(String cn) throws ClassNotFoundException {
60.155 + return Launcher.class.getClassLoader().loadClass(cn);
60.156 + }
60.157 +
60.158 + void showDirectory(File directory, String startpage) throws IOException {
60.159 + throw new UnsupportedOperationException();
60.160 + }
60.161 +
60.162 + void showURL(String startpage) throws IOException {
60.163 + throw new UnsupportedOperationException();
60.164 + }
60.165 +
60.166 + void addClassLoader(ClassLoader classes) {
60.167 + throw new UnsupportedOperationException();
60.168 + }
60.169 +}
61.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
61.2 +++ b/launcher/fx/pom.xml Thu May 02 09:18:22 2013 +0200
61.3 @@ -0,0 +1,57 @@
61.4 +<?xml version="1.0"?>
61.5 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
61.6 + <modelVersion>4.0.0</modelVersion>
61.7 + <parent>
61.8 + <groupId>org.apidesign.bck2brwsr</groupId>
61.9 + <artifactId>launcher-pom</artifactId>
61.10 + <version>0.8-SNAPSHOT</version>
61.11 + </parent>
61.12 + <groupId>org.apidesign.bck2brwsr</groupId>
61.13 + <artifactId>launcher.fx</artifactId>
61.14 + <version>0.8-SNAPSHOT</version>
61.15 + <name>FXBrwsr Launcher</name>
61.16 + <url>http://maven.apache.org</url>
61.17 + <build>
61.18 + <plugins>
61.19 + <plugin>
61.20 + <groupId>org.apache.maven.plugins</groupId>
61.21 + <artifactId>maven-compiler-plugin</artifactId>
61.22 + <version>2.3.2</version>
61.23 + <configuration>
61.24 + <source>1.7</source>
61.25 + <target>1.7</target>
61.26 + </configuration>
61.27 + </plugin>
61.28 + <plugin>
61.29 + <groupId>org.apache.maven.plugins</groupId>
61.30 + <artifactId>maven-javadoc-plugin</artifactId>
61.31 + <configuration>
61.32 + <subpackages>org.apidesign.bck2brwsr.launcher.fx</subpackages>
61.33 + <skip>false</skip>
61.34 + </configuration>
61.35 + </plugin>
61.36 + </plugins>
61.37 + </build>
61.38 + <properties>
61.39 + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
61.40 + </properties>
61.41 + <dependencies>
61.42 + <dependency>
61.43 + <groupId>${project.groupId}</groupId>
61.44 + <artifactId>launcher</artifactId>
61.45 + <version>${project.version}</version>
61.46 + </dependency>
61.47 + <dependency>
61.48 + <groupId>org.glassfish.grizzly</groupId>
61.49 + <artifactId>grizzly-http-server</artifactId>
61.50 + <version>2.2.19</version>
61.51 + </dependency>
61.52 + <dependency>
61.53 + <groupId>com.oracle</groupId>
61.54 + <artifactId>javafx</artifactId>
61.55 + <version>2.2</version>
61.56 + <scope>system</scope>
61.57 + <systemPath>${java.home}/lib/jfxrt.jar</systemPath>
61.58 + </dependency>
61.59 + </dependencies>
61.60 +</project>
62.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
62.2 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/BaseHTTPLauncher.java Thu May 02 09:18:22 2013 +0200
62.3 @@ -0,0 +1,588 @@
62.4 +/**
62.5 + * Back 2 Browser Bytecode Translator
62.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
62.7 + *
62.8 + * This program is free software: you can redistribute it and/or modify
62.9 + * it under the terms of the GNU General Public License as published by
62.10 + * the Free Software Foundation, version 2 of the License.
62.11 + *
62.12 + * This program is distributed in the hope that it will be useful,
62.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
62.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
62.15 + * GNU General Public License for more details.
62.16 + *
62.17 + * You should have received a copy of the GNU General Public License
62.18 + * along with this program. Look for COPYING file in the top folder.
62.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
62.20 + */
62.21 +package org.apidesign.bck2brwsr.launcher;
62.22 +
62.23 +import java.io.Closeable;
62.24 +import java.io.File;
62.25 +import java.io.IOException;
62.26 +import java.io.InputStream;
62.27 +import java.io.InterruptedIOException;
62.28 +import java.io.OutputStream;
62.29 +import java.io.UnsupportedEncodingException;
62.30 +import java.io.Writer;
62.31 +import java.net.URI;
62.32 +import java.net.URISyntaxException;
62.33 +import java.net.URL;
62.34 +import java.util.ArrayList;
62.35 +import java.util.Arrays;
62.36 +import java.util.Enumeration;
62.37 +import java.util.LinkedHashSet;
62.38 +import java.util.List;
62.39 +import java.util.Set;
62.40 +import java.util.concurrent.BlockingQueue;
62.41 +import java.util.concurrent.CountDownLatch;
62.42 +import java.util.concurrent.LinkedBlockingQueue;
62.43 +import java.util.concurrent.TimeUnit;
62.44 +import java.util.logging.Level;
62.45 +import java.util.logging.Logger;
62.46 +import org.apidesign.bck2brwsr.launcher.InvocationContext.Resource;
62.47 +import org.glassfish.grizzly.PortRange;
62.48 +import org.glassfish.grizzly.http.server.HttpHandler;
62.49 +import org.glassfish.grizzly.http.server.HttpServer;
62.50 +import org.glassfish.grizzly.http.server.NetworkListener;
62.51 +import org.glassfish.grizzly.http.server.Request;
62.52 +import org.glassfish.grizzly.http.server.Response;
62.53 +import org.glassfish.grizzly.http.server.ServerConfiguration;
62.54 +import org.glassfish.grizzly.http.util.HttpStatus;
62.55 +
62.56 +/**
62.57 + * Lightweight server to launch Bck2Brwsr applications and tests.
62.58 + * Supports execution in native browser as well as Java's internal
62.59 + * execution engine.
62.60 + */
62.61 +abstract class BaseHTTPLauncher extends Launcher implements Closeable {
62.62 + private static final Logger LOG = Logger.getLogger(BaseHTTPLauncher.class.getName());
62.63 + private static final InvocationContext END = new InvocationContext(null, null, null);
62.64 + private final Set<ClassLoader> loaders = new LinkedHashSet<>();
62.65 + private final BlockingQueue<InvocationContext> methods = new LinkedBlockingQueue<>();
62.66 + private long timeOut;
62.67 + private final Res resources = new Res();
62.68 + private final String cmd;
62.69 + private Object[] brwsr;
62.70 + private HttpServer server;
62.71 + private CountDownLatch wait;
62.72 +
62.73 + public BaseHTTPLauncher(String cmd) {
62.74 + this.cmd = cmd;
62.75 + addClassLoader(BaseHTTPLauncher.class.getClassLoader());
62.76 + setTimeout(180000);
62.77 + }
62.78 +
62.79 + @Override
62.80 + InvocationContext runMethod(InvocationContext c) throws IOException {
62.81 + loaders.add(c.clazz.getClassLoader());
62.82 + methods.add(c);
62.83 + try {
62.84 + c.await(timeOut);
62.85 + } catch (InterruptedException ex) {
62.86 + throw new IOException(ex);
62.87 + }
62.88 + return c;
62.89 + }
62.90 +
62.91 + public void setTimeout(long ms) {
62.92 + timeOut = ms;
62.93 + }
62.94 +
62.95 + public void addClassLoader(ClassLoader url) {
62.96 + this.loaders.add(url);
62.97 + }
62.98 +
62.99 + ClassLoader[] loaders() {
62.100 + return loaders.toArray(new ClassLoader[loaders.size()]);
62.101 + }
62.102 +
62.103 + public void showURL(String startpage) throws IOException {
62.104 + if (!startpage.startsWith("/")) {
62.105 + startpage = "/" + startpage;
62.106 + }
62.107 + HttpServer s = initServer(".", true);
62.108 + int last = startpage.lastIndexOf('/');
62.109 + String prefix = startpage.substring(0, last);
62.110 + String simpleName = startpage.substring(last);
62.111 + s.getServerConfiguration().addHttpHandler(new SubTree(resources, prefix), "/");
62.112 + try {
62.113 + launchServerAndBrwsr(s, simpleName);
62.114 + } catch (URISyntaxException | InterruptedException ex) {
62.115 + throw new IOException(ex);
62.116 + }
62.117 + }
62.118 +
62.119 + void showDirectory(File dir, String startpage) throws IOException {
62.120 + if (!startpage.startsWith("/")) {
62.121 + startpage = "/" + startpage;
62.122 + }
62.123 + HttpServer s = initServer(dir.getPath(), false);
62.124 + try {
62.125 + launchServerAndBrwsr(s, startpage);
62.126 + } catch (URISyntaxException | InterruptedException ex) {
62.127 + throw new IOException(ex);
62.128 + }
62.129 + }
62.130 +
62.131 + @Override
62.132 + public void initialize() throws IOException {
62.133 + try {
62.134 + executeInBrowser();
62.135 + } catch (InterruptedException ex) {
62.136 + final InterruptedIOException iio = new InterruptedIOException(ex.getMessage());
62.137 + iio.initCause(ex);
62.138 + throw iio;
62.139 + } catch (Exception ex) {
62.140 + if (ex instanceof IOException) {
62.141 + throw (IOException)ex;
62.142 + }
62.143 + if (ex instanceof RuntimeException) {
62.144 + throw (RuntimeException)ex;
62.145 + }
62.146 + throw new IOException(ex);
62.147 + }
62.148 + }
62.149 +
62.150 + private HttpServer initServer(String path, boolean addClasses) throws IOException {
62.151 + HttpServer s = HttpServer.createSimpleServer(path, new PortRange(8080, 65535));
62.152 +
62.153 + final ServerConfiguration conf = s.getServerConfiguration();
62.154 + if (addClasses) {
62.155 + conf.addHttpHandler(new VM(), "/bck2brwsr.js");
62.156 + conf.addHttpHandler(new Classes(resources), "/classes/");
62.157 + }
62.158 + return s;
62.159 + }
62.160 +
62.161 + private void executeInBrowser() throws InterruptedException, URISyntaxException, IOException {
62.162 + wait = new CountDownLatch(1);
62.163 + server = initServer(".", true);
62.164 + final ServerConfiguration conf = server.getServerConfiguration();
62.165 +
62.166 + class DynamicResourceHandler extends HttpHandler {
62.167 + private final InvocationContext ic;
62.168 + public DynamicResourceHandler(InvocationContext ic) {
62.169 + if (ic == null || ic.resources.isEmpty()) {
62.170 + throw new NullPointerException();
62.171 + }
62.172 + this.ic = ic;
62.173 + for (Resource r : ic.resources) {
62.174 + conf.addHttpHandler(this, r.httpPath);
62.175 + }
62.176 + }
62.177 +
62.178 + public void close() {
62.179 + conf.removeHttpHandler(this);
62.180 + }
62.181 +
62.182 + @Override
62.183 + public void service(Request request, Response response) throws Exception {
62.184 + for (Resource r : ic.resources) {
62.185 + if (r.httpPath.equals(request.getRequestURI())) {
62.186 + LOG.log(Level.INFO, "Serving HttpResource for {0}", request.getRequestURI());
62.187 + response.setContentType(r.httpType);
62.188 + r.httpContent.reset();
62.189 + String[] params = null;
62.190 + if (r.parameters.length != 0) {
62.191 + params = new String[r.parameters.length];
62.192 + for (int i = 0; i < r.parameters.length; i++) {
62.193 + params[i] = request.getParameter(r.parameters[i]);
62.194 + }
62.195 + }
62.196 +
62.197 + copyStream(r.httpContent, response.getOutputStream(), null, params);
62.198 + }
62.199 + }
62.200 + }
62.201 + }
62.202 +
62.203 + conf.addHttpHandler(new Page(resources,
62.204 + "org/apidesign/bck2brwsr/launcher/fximpl/harness.xhtml"
62.205 + ), "/execute");
62.206 +
62.207 + conf.addHttpHandler(new HttpHandler() {
62.208 + int cnt;
62.209 + List<InvocationContext> cases = new ArrayList<>();
62.210 + DynamicResourceHandler prev;
62.211 + @Override
62.212 + public void service(Request request, Response response) throws Exception {
62.213 + String id = request.getParameter("request");
62.214 + String value = request.getParameter("result");
62.215 + if (value != null && value.indexOf((char)0xC5) != -1) {
62.216 + value = toUTF8(value);
62.217 + }
62.218 +
62.219 +
62.220 + InvocationContext mi = null;
62.221 + int caseNmbr = -1;
62.222 +
62.223 + if (id != null && value != null) {
62.224 + LOG.log(Level.INFO, "Received result for case {0} = {1}", new Object[]{id, value});
62.225 + value = decodeURL(value);
62.226 + int indx = Integer.parseInt(id);
62.227 + cases.get(indx).result(value, null);
62.228 + if (++indx < cases.size()) {
62.229 + mi = cases.get(indx);
62.230 + LOG.log(Level.INFO, "Re-executing case {0}", indx);
62.231 + caseNmbr = indx;
62.232 + }
62.233 + } else {
62.234 + if (!cases.isEmpty()) {
62.235 + LOG.info("Re-executing test cases");
62.236 + mi = cases.get(0);
62.237 + caseNmbr = 0;
62.238 + }
62.239 + }
62.240 +
62.241 + if (prev != null) {
62.242 + prev.close();
62.243 + prev = null;
62.244 + }
62.245 +
62.246 + if (mi == null) {
62.247 + mi = methods.take();
62.248 + caseNmbr = cnt++;
62.249 + }
62.250 + if (mi == END) {
62.251 + response.getWriter().write("");
62.252 + wait.countDown();
62.253 + cnt = 0;
62.254 + LOG.log(Level.INFO, "End of data reached. Exiting.");
62.255 + return;
62.256 + }
62.257 +
62.258 + if (!mi.resources.isEmpty()) {
62.259 + prev = new DynamicResourceHandler(mi);
62.260 + }
62.261 +
62.262 + cases.add(mi);
62.263 + final String cn = mi.clazz.getName();
62.264 + final String mn = mi.methodName;
62.265 + LOG.log(Level.INFO, "Request for {0} case. Sending {1}.{2}", new Object[]{caseNmbr, cn, mn});
62.266 + response.getWriter().write("{"
62.267 + + "className: '" + cn + "', "
62.268 + + "methodName: '" + mn + "', "
62.269 + + "request: " + caseNmbr
62.270 + );
62.271 + if (mi.html != null) {
62.272 + response.getWriter().write(", html: '");
62.273 + response.getWriter().write(encodeJSON(mi.html));
62.274 + response.getWriter().write("'");
62.275 + }
62.276 + response.getWriter().write("}");
62.277 + }
62.278 + }, "/data");
62.279 +
62.280 + this.brwsr = launchServerAndBrwsr(server, "/execute");
62.281 + }
62.282 +
62.283 + private static String encodeJSON(String in) {
62.284 + StringBuilder sb = new StringBuilder();
62.285 + for (int i = 0; i < in.length(); i++) {
62.286 + char ch = in.charAt(i);
62.287 + if (ch < 32 || ch == '\'' || ch == '"') {
62.288 + sb.append("\\u");
62.289 + String hs = "0000" + Integer.toHexString(ch);
62.290 + hs = hs.substring(hs.length() - 4);
62.291 + sb.append(hs);
62.292 + } else {
62.293 + sb.append(ch);
62.294 + }
62.295 + }
62.296 + return sb.toString();
62.297 + }
62.298 +
62.299 + @Override
62.300 + public void shutdown() throws IOException {
62.301 + methods.offer(END);
62.302 + for (;;) {
62.303 + int prev = methods.size();
62.304 + try {
62.305 + if (wait != null && wait.await(timeOut, TimeUnit.MILLISECONDS)) {
62.306 + break;
62.307 + }
62.308 + } catch (InterruptedException ex) {
62.309 + throw new IOException(ex);
62.310 + }
62.311 + if (prev == methods.size()) {
62.312 + LOG.log(
62.313 + Level.WARNING,
62.314 + "Timeout and no test has been executed meanwhile (at {0}). Giving up.",
62.315 + methods.size()
62.316 + );
62.317 + break;
62.318 + }
62.319 + LOG.log(Level.INFO,
62.320 + "Timeout, but tests got from {0} to {1}. Trying again.",
62.321 + new Object[]{prev, methods.size()}
62.322 + );
62.323 + }
62.324 + stopServerAndBrwsr(server, brwsr);
62.325 + }
62.326 +
62.327 + static void copyStream(InputStream is, OutputStream os, String baseURL, String... params) throws IOException {
62.328 + for (;;) {
62.329 + int ch = is.read();
62.330 + if (ch == -1) {
62.331 + break;
62.332 + }
62.333 + if (ch == '$' && params.length > 0) {
62.334 + int cnt = is.read() - '0';
62.335 + if (baseURL != null && cnt == 'U' - '0') {
62.336 + os.write(baseURL.getBytes("UTF-8"));
62.337 + } else {
62.338 + if (cnt >= 0 && cnt < params.length) {
62.339 + os.write(params[cnt].getBytes("UTF-8"));
62.340 + } else {
62.341 + os.write('$');
62.342 + os.write(cnt + '0');
62.343 + }
62.344 + }
62.345 + } else {
62.346 + os.write(ch);
62.347 + }
62.348 + }
62.349 + }
62.350 +
62.351 + private Object[] launchServerAndBrwsr(HttpServer server, final String page) throws IOException, URISyntaxException, InterruptedException {
62.352 + server.start();
62.353 + NetworkListener listener = server.getListeners().iterator().next();
62.354 + int port = listener.getPort();
62.355 +
62.356 + URI uri = new URI("http://localhost:" + port + page);
62.357 + return showBrwsr(uri);
62.358 + }
62.359 + private static String toUTF8(String value) throws UnsupportedEncodingException {
62.360 + byte[] arr = new byte[value.length()];
62.361 + for (int i = 0; i < arr.length; i++) {
62.362 + arr[i] = (byte)value.charAt(i);
62.363 + }
62.364 + return new String(arr, "UTF-8");
62.365 + }
62.366 +
62.367 + private static String decodeURL(String s) {
62.368 + for (;;) {
62.369 + int pos = s.indexOf('%');
62.370 + if (pos == -1) {
62.371 + return s;
62.372 + }
62.373 + int i = Integer.parseInt(s.substring(pos + 1, pos + 2), 16);
62.374 + s = s.substring(0, pos) + (char)i + s.substring(pos + 2);
62.375 + }
62.376 + }
62.377 +
62.378 + private void stopServerAndBrwsr(HttpServer server, Object[] brwsr) throws IOException {
62.379 + if (brwsr == null) {
62.380 + return;
62.381 + }
62.382 + Process process = (Process)brwsr[0];
62.383 +
62.384 + server.stop();
62.385 + InputStream stdout = process.getInputStream();
62.386 + InputStream stderr = process.getErrorStream();
62.387 + drain("StdOut", stdout);
62.388 + drain("StdErr", stderr);
62.389 + process.destroy();
62.390 + int res;
62.391 + try {
62.392 + res = process.waitFor();
62.393 + } catch (InterruptedException ex) {
62.394 + throw new IOException(ex);
62.395 + }
62.396 + LOG.log(Level.INFO, "Exit code: {0}", res);
62.397 +
62.398 + deleteTree((File)brwsr[1]);
62.399 + }
62.400 +
62.401 + private static void drain(String name, InputStream is) throws IOException {
62.402 + int av = is.available();
62.403 + if (av > 0) {
62.404 + StringBuilder sb = new StringBuilder();
62.405 + sb.append("v== ").append(name).append(" ==v\n");
62.406 + while (av-- > 0) {
62.407 + sb.append((char)is.read());
62.408 + }
62.409 + sb.append("\n^== ").append(name).append(" ==^");
62.410 + LOG.log(Level.INFO, sb.toString());
62.411 + }
62.412 + }
62.413 +
62.414 + private void deleteTree(File file) {
62.415 + if (file == null) {
62.416 + return;
62.417 + }
62.418 + File[] arr = file.listFiles();
62.419 + if (arr != null) {
62.420 + for (File s : arr) {
62.421 + deleteTree(s);
62.422 + }
62.423 + }
62.424 + file.delete();
62.425 + }
62.426 +
62.427 + @Override
62.428 + public void close() throws IOException {
62.429 + shutdown();
62.430 + }
62.431 +
62.432 + protected Object[] showBrwsr(URI uri) throws IOException {
62.433 + LOG.log(Level.INFO, "Showing {0}", uri);
62.434 + if (cmd == null) {
62.435 + try {
62.436 + LOG.log(Level.INFO, "Trying Desktop.browse on {0} {2} by {1}", new Object[] {
62.437 + System.getProperty("java.vm.name"),
62.438 + System.getProperty("java.vm.vendor"),
62.439 + System.getProperty("java.vm.version"),
62.440 + });
62.441 + java.awt.Desktop.getDesktop().browse(uri);
62.442 + LOG.log(Level.INFO, "Desktop.browse successfully finished");
62.443 + return null;
62.444 + } catch (UnsupportedOperationException ex) {
62.445 + LOG.log(Level.INFO, "Desktop.browse not supported: {0}", ex.getMessage());
62.446 + LOG.log(Level.FINE, null, ex);
62.447 + }
62.448 + }
62.449 + {
62.450 + String cmdName = cmd == null ? "xdg-open" : cmd;
62.451 + String[] cmdArr = {
62.452 + cmdName, uri.toString()
62.453 + };
62.454 + LOG.log(Level.INFO, "Launching {0}", Arrays.toString(cmdArr));
62.455 + final Process process = Runtime.getRuntime().exec(cmdArr);
62.456 + return new Object[] { process, null };
62.457 + }
62.458 + }
62.459 +
62.460 + abstract void generateBck2BrwsrJS(StringBuilder sb, Object loader) throws IOException;
62.461 +
62.462 + private class Res {
62.463 + public InputStream get(String resource) throws IOException {
62.464 + for (ClassLoader l : loaders) {
62.465 + URL u = null;
62.466 + Enumeration<URL> en = l.getResources(resource);
62.467 + while (en.hasMoreElements()) {
62.468 + u = en.nextElement();
62.469 + }
62.470 + if (u != null) {
62.471 + return u.openStream();
62.472 + }
62.473 + }
62.474 + throw new IOException("Can't find " + resource);
62.475 + }
62.476 + }
62.477 +
62.478 + private static class Page extends HttpHandler {
62.479 + final String resource;
62.480 + private final String[] args;
62.481 + private final Res res;
62.482 +
62.483 + public Page(Res res, String resource, String... args) {
62.484 + this.res = res;
62.485 + this.resource = resource;
62.486 + this.args = args.length == 0 ? new String[] { "$0" } : args;
62.487 + }
62.488 +
62.489 + @Override
62.490 + public void service(Request request, Response response) throws Exception {
62.491 + String r = computePage(request);
62.492 + if (r.startsWith("/")) {
62.493 + r = r.substring(1);
62.494 + }
62.495 + String[] replace = {};
62.496 + if (r.endsWith(".html")) {
62.497 + response.setContentType("text/html");
62.498 + LOG.info("Content type text/html");
62.499 + replace = args;
62.500 + }
62.501 + if (r.endsWith(".xhtml")) {
62.502 + response.setContentType("application/xhtml+xml");
62.503 + LOG.info("Content type application/xhtml+xml");
62.504 + replace = args;
62.505 + }
62.506 + OutputStream os = response.getOutputStream();
62.507 + try (InputStream is = res.get(r)) {
62.508 + copyStream(is, os, request.getRequestURL().toString(), replace);
62.509 + } catch (IOException ex) {
62.510 + response.setDetailMessage(ex.getLocalizedMessage());
62.511 + response.setError();
62.512 + response.setStatus(404);
62.513 + }
62.514 + }
62.515 +
62.516 + protected String computePage(Request request) {
62.517 + String r = resource;
62.518 + if (r == null) {
62.519 + r = request.getHttpHandlerPath();
62.520 + }
62.521 + return r;
62.522 + }
62.523 + }
62.524 +
62.525 + private static class SubTree extends Page {
62.526 +
62.527 + public SubTree(Res res, String resource, String... args) {
62.528 + super(res, resource, args);
62.529 + }
62.530 +
62.531 + @Override
62.532 + protected String computePage(Request request) {
62.533 + return resource + request.getHttpHandlerPath();
62.534 + }
62.535 +
62.536 +
62.537 + }
62.538 +
62.539 + private class VM extends HttpHandler {
62.540 + @Override
62.541 + public void service(Request request, Response response) throws Exception {
62.542 + response.setCharacterEncoding("UTF-8");
62.543 + response.setContentType("text/javascript");
62.544 + StringBuilder sb = new StringBuilder();
62.545 + generateBck2BrwsrJS(sb, BaseHTTPLauncher.this.resources);
62.546 + response.getWriter().write(sb.toString());
62.547 + }
62.548 + }
62.549 +
62.550 + private static class Classes extends HttpHandler {
62.551 + private final Res loader;
62.552 +
62.553 + public Classes(Res loader) {
62.554 + this.loader = loader;
62.555 + }
62.556 +
62.557 + @Override
62.558 + public void service(Request request, Response response) throws Exception {
62.559 + String res = request.getHttpHandlerPath();
62.560 + if (res.startsWith("/")) {
62.561 + res = res.substring(1);
62.562 + }
62.563 + try (InputStream is = loader.get(res)) {
62.564 + response.setContentType("text/javascript");
62.565 + Writer w = response.getWriter();
62.566 + w.append("[");
62.567 + for (int i = 0;; i++) {
62.568 + int b = is.read();
62.569 + if (b == -1) {
62.570 + break;
62.571 + }
62.572 + if (i > 0) {
62.573 + w.append(", ");
62.574 + }
62.575 + if (i % 20 == 0) {
62.576 + w.write("\n");
62.577 + }
62.578 + if (b > 127) {
62.579 + b = b - 256;
62.580 + }
62.581 + w.append(Integer.toString(b));
62.582 + }
62.583 + w.append("\n]");
62.584 + } catch (IOException ex) {
62.585 + response.setStatus(HttpStatus.NOT_FOUND_404);
62.586 + response.setError();
62.587 + response.setDetailMessage(ex.getMessage());
62.588 + }
62.589 + }
62.590 + }
62.591 +}
63.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
63.2 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/FXBrwsrLauncher.java Thu May 02 09:18:22 2013 +0200
63.3 @@ -0,0 +1,129 @@
63.4 +/**
63.5 + * Back 2 Browser Bytecode Translator
63.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
63.7 + *
63.8 + * This program is free software: you can redistribute it and/or modify
63.9 + * it under the terms of the GNU General Public License as published by
63.10 + * the Free Software Foundation, version 2 of the License.
63.11 + *
63.12 + * This program is distributed in the hope that it will be useful,
63.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
63.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
63.15 + * GNU General Public License for more details.
63.16 + *
63.17 + * You should have received a copy of the GNU General Public License
63.18 + * along with this program. Look for COPYING file in the top folder.
63.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
63.20 + */
63.21 +package org.apidesign.bck2brwsr.launcher;
63.22 +
63.23 +import org.apidesign.bck2brwsr.launcher.fximpl.FXBrwsr;
63.24 +import java.io.IOException;
63.25 +import java.io.InputStream;
63.26 +import java.lang.reflect.Method;
63.27 +import java.net.URI;
63.28 +import java.net.URL;
63.29 +import java.net.URLClassLoader;
63.30 +import java.util.Enumeration;
63.31 +
63.32 +import java.util.concurrent.Executors;
63.33 +import java.util.jar.Manifest;
63.34 +import java.util.logging.Level;
63.35 +import java.util.logging.Logger;
63.36 +import javafx.application.Platform;
63.37 +import org.apidesign.bck2brwsr.launcher.fximpl.JVMBridge;
63.38 +
63.39 +/**
63.40 + *
63.41 + * @author Jaroslav Tulach <jtulach@netbeans.org>
63.42 + */
63.43 +final class FXBrwsrLauncher extends BaseHTTPLauncher {
63.44 + private static final Logger LOG = Logger.getLogger(FXBrwsrLauncher.class.getName());
63.45 + static {
63.46 + try {
63.47 + Method m = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
63.48 + m.setAccessible(true);
63.49 + URL l = new URL("file://" + System.getProperty("java.home") + "/lib/jfxrt.jar");
63.50 + LOG.log(Level.INFO, "url : {0}", l);
63.51 + m.invoke(ClassLoader.getSystemClassLoader(), l);
63.52 + } catch (Exception ex) {
63.53 + throw new LinkageError("Can't add jfxrt.jar on the classpath", ex);
63.54 + }
63.55 + }
63.56 +
63.57 + public FXBrwsrLauncher(String ignore) {
63.58 + super(null);
63.59 + }
63.60 +
63.61 + @Override
63.62 + protected Object[] showBrwsr(final URI url) throws IOException {
63.63 + try {
63.64 + LOG.log(Level.INFO, "showBrwsr for {0}", url);
63.65 + JVMBridge.registerClassLoaders(loaders());
63.66 + LOG.info("About to launch WebView");
63.67 + Executors.newSingleThreadExecutor().submit(new Runnable() {
63.68 + @Override
63.69 + public void run() {
63.70 + LOG.log(Level.INFO, "In FX thread. Launching!");
63.71 + try {
63.72 + FXBrwsr.launch(FXBrwsr.class, url.toString());
63.73 + LOG.log(Level.INFO, "Launcher is back. Closing");
63.74 + close();
63.75 + } catch (Throwable ex) {
63.76 + LOG.log(Level.WARNING, "Error launching Web View", ex);
63.77 + }
63.78 + }
63.79 + });
63.80 + } catch (Throwable ex) {
63.81 + LOG.log(Level.WARNING, "Can't open WebView", ex);
63.82 + }
63.83 + return null;
63.84 + }
63.85 +
63.86 + @Override
63.87 + void generateBck2BrwsrJS(StringBuilder sb, Object loader) throws IOException {
63.88 + sb.append("(function() {\n"
63.89 + + " var impl = this.bck2brwsr;\n"
63.90 + + " this.bck2brwsr = function() { return impl; };\n"
63.91 + + "})(window);\n"
63.92 + );
63.93 + JVMBridge.onBck2BrwsrLoad();
63.94 + }
63.95 +
63.96 +
63.97 +
63.98 + @Override
63.99 + public void close() throws IOException {
63.100 + super.close();
63.101 + Platform.exit();
63.102 + }
63.103 +
63.104 + public static void main(String... args) throws IOException {
63.105 + String startPage = null;
63.106 +
63.107 + final ClassLoader cl = FXBrwsrLauncher.class.getClassLoader();
63.108 + startPage = findStartPage(cl, startPage);
63.109 + if (startPage == null) {
63.110 + throw new NullPointerException("Can't find StartPage tag in manifests!");
63.111 + }
63.112 +
63.113 + Launcher.showURL("fxbrwsr", cl, startPage);
63.114 + }
63.115 +
63.116 + private static String findStartPage(final ClassLoader cl, String startPage) throws IOException {
63.117 + Enumeration<URL> en = cl.getResources("META-INF/MANIFEST.MF");
63.118 + while (en.hasMoreElements()) {
63.119 + URL url = en.nextElement();
63.120 + Manifest mf;
63.121 + try (InputStream is = url.openStream()) {
63.122 + mf = new Manifest(is);
63.123 + }
63.124 + String sp = mf.getMainAttributes().getValue("StartPage");
63.125 + if (sp != null) {
63.126 + startPage = sp;
63.127 + break;
63.128 + }
63.129 + }
63.130 + return startPage;
63.131 + }
63.132 +}
64.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
64.2 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fx/LauncherFX.java Thu May 02 09:18:22 2013 +0200
64.3 @@ -0,0 +1,32 @@
64.4 +/**
64.5 + * Back 2 Browser Bytecode Translator
64.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
64.7 + *
64.8 + * This program is free software: you can redistribute it and/or modify
64.9 + * it under the terms of the GNU General Public License as published by
64.10 + * the Free Software Foundation, version 2 of the License.
64.11 + *
64.12 + * This program is distributed in the hope that it will be useful,
64.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
64.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
64.15 + * GNU General Public License for more details.
64.16 + *
64.17 + * You should have received a copy of the GNU General Public License
64.18 + * along with this program. Look for COPYING file in the top folder.
64.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
64.20 + */
64.21 +package org.apidesign.bck2brwsr.launcher.fx;
64.22 +
64.23 +import org.apidesign.bck2brwsr.launcher.Launcher;
64.24 +
64.25 +/** This is a launcher for the <a href="http://bck2brwsr.apidesign.org">Bck2Brwsr</a>
64.26 + * project that is using <b>JavaFX</b>'s WebView to display the browser inside
64.27 + * real Java virtual machine. Use {@link Launcher} methods to access this
64.28 + * functionality via public, supported methods.
64.29 + *
64.30 + * @author Jaroslav Tulach
64.31 + */
64.32 +public final class LauncherFX {
64.33 + private LauncherFX() {
64.34 + }
64.35 +}
65.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
65.2 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/Console.java Thu May 02 09:18:22 2013 +0200
65.3 @@ -0,0 +1,395 @@
65.4 +/**
65.5 + * Back 2 Browser Bytecode Translator
65.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
65.7 + *
65.8 + * This program is free software: you can redistribute it and/or modify
65.9 + * it under the terms of the GNU General Public License as published by
65.10 + * the Free Software Foundation, version 2 of the License.
65.11 + *
65.12 + * This program is distributed in the hope that it will be useful,
65.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
65.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
65.15 + * GNU General Public License for more details.
65.16 + *
65.17 + * You should have received a copy of the GNU General Public License
65.18 + * along with this program. Look for COPYING file in the top folder.
65.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
65.20 + */
65.21 +package org.apidesign.bck2brwsr.launcher.fximpl;
65.22 +
65.23 +import java.io.IOException;
65.24 +import java.io.InputStream;
65.25 +import java.io.UnsupportedEncodingException;
65.26 +import java.lang.reflect.InvocationTargetException;
65.27 +import java.lang.reflect.Method;
65.28 +import java.lang.reflect.Modifier;
65.29 +import java.net.URL;
65.30 +import java.util.Enumeration;
65.31 +import javafx.scene.web.WebEngine;
65.32 +import netscape.javascript.JSObject;
65.33 +
65.34 +/**
65.35 + *
65.36 + * @author Jaroslav Tulach <jtulach@netbeans.org>
65.37 + */
65.38 +public final class Console {
65.39 + public Console() {
65.40 + }
65.41 +
65.42 + private static Object getAttr(Object elem, String attr) {
65.43 + return InvokeJS.CObject.call("getAttr", elem, attr);
65.44 + }
65.45 +
65.46 + private static void setAttr(String id, String attr, Object value) {
65.47 + InvokeJS.CObject.call("setAttrId", id, attr, value);
65.48 + }
65.49 + private static void setAttr(Object id, String attr, Object value) {
65.50 + InvokeJS.CObject.call("setAttr", id, attr, value);
65.51 + }
65.52 +
65.53 + private static void closeWindow() {}
65.54 +
65.55 + private static Object textArea;
65.56 + private static Object statusArea;
65.57 +
65.58 + private static void log(String newText) {
65.59 + if (textArea == null) {
65.60 + return;
65.61 + }
65.62 + String attr = "value";
65.63 + setAttr(textArea, attr, getAttr(textArea, attr) + "\n" + newText);
65.64 + setAttr(textArea, "scrollTop", getAttr(textArea, "scrollHeight"));
65.65 + }
65.66 +
65.67 + private static void beginTest(Case c) {
65.68 + Object[] arr = new Object[2];
65.69 + beginTest(c.getClassName() + "." + c.getMethodName(), c, arr);
65.70 + textArea = arr[0];
65.71 + statusArea = arr[1];
65.72 + }
65.73 +
65.74 + private static void finishTest(Case c, Object res) {
65.75 + if ("null".equals(res)) {
65.76 + setAttr(statusArea, "innerHTML", "Success");
65.77 + } else {
65.78 + setAttr(statusArea, "innerHTML", "Result " + res);
65.79 + }
65.80 + statusArea = null;
65.81 + textArea = null;
65.82 + }
65.83 +
65.84 + private static final String BEGIN_TEST =
65.85 + "var ul = window.document.getElementById('bck2brwsr.result');\n"
65.86 + + "var li = window.document.createElement('li');\n"
65.87 + + "var span = window.document.createElement('span');"
65.88 + + "span.innerHTML = test + ' - ';\n"
65.89 + + "var details = window.document.createElement('a');\n"
65.90 + + "details.innerHTML = 'Details';\n"
65.91 + + "details.href = '#';\n"
65.92 + + "var p = window.document.createElement('p');\n"
65.93 + + "var status = window.document.createElement('a');\n"
65.94 + + "status.innerHTML = 'running';"
65.95 + + "details.onclick = function() { li.appendChild(p); li.removeChild(details); status.innerHTML = 'Run Again'; status.href = '#'; };\n"
65.96 + + "status.onclick = function() { c.again(arr); }\n"
65.97 + + "var pre = window.document.createElement('textarea');\n"
65.98 + + "pre.cols = 100;"
65.99 + + "pre.rows = 10;"
65.100 + + "li.appendChild(span);\n"
65.101 + + "li.appendChild(status);\n"
65.102 + + "var span = window.document.createElement('span');"
65.103 + + "span.innerHTML = ' ';\n"
65.104 + + "li.appendChild(span);\n"
65.105 + + "li.appendChild(details);\n"
65.106 + + "p.appendChild(pre);\n"
65.107 + + "ul.appendChild(li);\n"
65.108 + + "arr[0] = pre;\n"
65.109 + + "arr[1] = status;\n";
65.110 +
65.111 + private static void beginTest(String test, Case c, Object[] arr) {
65.112 + InvokeJS.CObject.call("beginTest", test, c, arr);
65.113 + }
65.114 +
65.115 + private static final String LOAD_TEXT =
65.116 + "var request = new XMLHttpRequest();\n"
65.117 + + "request.open('GET', url, true);\n"
65.118 + + "request.setRequestHeader('Content-Type', 'text/plain; charset=utf-8');\n"
65.119 + + "request.onreadystatechange = function() {\n"
65.120 + + " if (this.readyState!==4) return;\n"
65.121 + + " try {"
65.122 + + " arr[0] = this.responseText;\n"
65.123 + + " callback.run__V();\n"
65.124 + + " } catch (e) { alert(e); }"
65.125 + + "};"
65.126 + + "request.send();";
65.127 + private static void loadText(String url, Runnable callback, String[] arr) throws IOException {
65.128 + InvokeJS.CObject.call("loadText", url, new Run(callback), arr);
65.129 + }
65.130 +
65.131 + public static void runHarness(String url) throws IOException {
65.132 + new Console().harness(url);
65.133 + }
65.134 +
65.135 + public void harness(String url) throws IOException {
65.136 + log("Connecting to " + url);
65.137 + Request r = new Request(url);
65.138 + }
65.139 +
65.140 + private static class Request implements Runnable {
65.141 + private final String[] arr = { null };
65.142 + private final String url;
65.143 + private Case c;
65.144 + private int retries;
65.145 +
65.146 + private Request(String url) throws IOException {
65.147 + this.url = url;
65.148 + loadText(url, this, arr);
65.149 + }
65.150 + private Request(String url, String u) throws IOException {
65.151 + this.url = url;
65.152 + loadText(u, this, arr);
65.153 + }
65.154 +
65.155 + @Override
65.156 + public void run() {
65.157 + try {
65.158 + if (c == null) {
65.159 + String data = arr[0];
65.160 +
65.161 + if (data == null) {
65.162 + log("Some error exiting");
65.163 + closeWindow();
65.164 + return;
65.165 + }
65.166 +
65.167 + if (data.isEmpty()) {
65.168 + log("No data, exiting");
65.169 + closeWindow();
65.170 + return;
65.171 + }
65.172 +
65.173 + c = Case.parseData(data);
65.174 + beginTest(c);
65.175 + log("Got \"" + data + "\"");
65.176 + } else {
65.177 + log("Processing \"" + arr[0] + "\" for " + retries + " time");
65.178 + }
65.179 + Object result = retries++ >= 10 ? "java.lang.InterruptedException:timeout" : c.runTest();
65.180 + finishTest(c, result);
65.181 +
65.182 + String u = url + "?request=" + c.getRequestId() + "&result=" + result;
65.183 + new Request(url, u);
65.184 + } catch (Exception ex) {
65.185 + if (ex instanceof InterruptedException) {
65.186 + log("Re-scheduling in 100ms");
65.187 + schedule(this, 100);
65.188 + return;
65.189 + }
65.190 + log(ex.getClass().getName() + ":" + ex.getMessage());
65.191 + }
65.192 + }
65.193 + }
65.194 +
65.195 + private static String encodeURL(String r) throws UnsupportedEncodingException {
65.196 + final String SPECIAL = "%$&+,/:;=?@";
65.197 + StringBuilder sb = new StringBuilder();
65.198 + byte[] utf8 = r.getBytes("UTF-8");
65.199 + for (int i = 0; i < utf8.length; i++) {
65.200 + int ch = utf8[i] & 0xff;
65.201 + if (ch < 32 || ch > 127 || SPECIAL.indexOf(ch) >= 0) {
65.202 + final String numbers = "0" + Integer.toHexString(ch);
65.203 + sb.append("%").append(numbers.substring(numbers.length() - 2));
65.204 + } else {
65.205 + if (ch == 32) {
65.206 + sb.append("+");
65.207 + } else {
65.208 + sb.append((char)ch);
65.209 + }
65.210 + }
65.211 + }
65.212 + return sb.toString();
65.213 + }
65.214 +
65.215 + static String invoke(String clazz, String method) throws
65.216 + ClassNotFoundException, InvocationTargetException, IllegalAccessException,
65.217 + InstantiationException, InterruptedException {
65.218 + final Object r = new Case(null).invokeMethod(clazz, method);
65.219 + return r == null ? "null" : r.toString().toString();
65.220 + }
65.221 +
65.222 + /** Helper method that inspects the classpath and loads given resource
65.223 + * (usually a class file). Used while running tests in Rhino.
65.224 + *
65.225 + * @param name resource name to find
65.226 + * @return the array of bytes in the given resource
65.227 + * @throws IOException I/O in case something goes wrong
65.228 + */
65.229 + public static byte[] read(String name) throws IOException {
65.230 + URL u = null;
65.231 + Enumeration<URL> en = Console.class.getClassLoader().getResources(name);
65.232 + while (en.hasMoreElements()) {
65.233 + u = en.nextElement();
65.234 + }
65.235 + if (u == null) {
65.236 + throw new IOException("Can't find " + name);
65.237 + }
65.238 + try (InputStream is = u.openStream()) {
65.239 + byte[] arr;
65.240 + arr = new byte[is.available()];
65.241 + int offset = 0;
65.242 + while (offset < arr.length) {
65.243 + int len = is.read(arr, offset, arr.length - offset);
65.244 + if (len == -1) {
65.245 + throw new IOException("Can't read " + name);
65.246 + }
65.247 + offset += len;
65.248 + }
65.249 + return arr;
65.250 + }
65.251 + }
65.252 +
65.253 + private static void turnAssetionStatusOn() {
65.254 + }
65.255 +
65.256 + private static Object schedule(Runnable r, int time) {
65.257 + return InvokeJS.CObject.call("schedule", new Run(r), time);
65.258 + }
65.259 +
65.260 + private static final class Case {
65.261 + private final Object data;
65.262 + private Object inst;
65.263 +
65.264 + private Case(Object data) {
65.265 + this.data = data;
65.266 + }
65.267 +
65.268 + public static Case parseData(String s) {
65.269 + return new Case(toJSON(s));
65.270 + }
65.271 +
65.272 + public String getMethodName() {
65.273 + return (String) value("methodName", data);
65.274 + }
65.275 +
65.276 + public String getClassName() {
65.277 + return (String) value("className", data);
65.278 + }
65.279 +
65.280 + public int getRequestId() {
65.281 + Object v = value("request", data);
65.282 + if (v instanceof Number) {
65.283 + return ((Number)v).intValue();
65.284 + }
65.285 + return Integer.parseInt(v.toString());
65.286 + }
65.287 +
65.288 + public String getHtmlFragment() {
65.289 + return (String) value("html", data);
65.290 + }
65.291 +
65.292 + void again(Object[] arr) {
65.293 + try {
65.294 + textArea = arr[0];
65.295 + statusArea = arr[1];
65.296 + setAttr(textArea, "value", "");
65.297 + runTest();
65.298 + } catch (Exception ex) {
65.299 + log(ex.getClass().getName() + ":" + ex.getMessage());
65.300 + }
65.301 + }
65.302 +
65.303 + private Object runTest() throws IllegalAccessException,
65.304 + IllegalArgumentException, ClassNotFoundException, UnsupportedEncodingException,
65.305 + InvocationTargetException, InstantiationException, InterruptedException {
65.306 + if (this.getHtmlFragment() != null) {
65.307 + setAttr("bck2brwsr.fragment", "innerHTML", this.getHtmlFragment());
65.308 + }
65.309 + log("Invoking " + this.getClassName() + '.' + this.getMethodName() + " as request: " + this.getRequestId());
65.310 + Object result = invokeMethod(this.getClassName(), this.getMethodName());
65.311 + setAttr("bck2brwsr.fragment", "innerHTML", "");
65.312 + log("Result: " + result);
65.313 + result = encodeURL("" + result);
65.314 + log("Sending back: ...?request=" + this.getRequestId() + "&result=" + result);
65.315 + return result;
65.316 + }
65.317 +
65.318 + private Object invokeMethod(String clazz, String method)
65.319 + throws ClassNotFoundException, InvocationTargetException,
65.320 + InterruptedException, IllegalAccessException, IllegalArgumentException,
65.321 + InstantiationException {
65.322 + Method found = null;
65.323 + Class<?> c = Class.forName(clazz);
65.324 + for (Method m : c.getMethods()) {
65.325 + if (m.getName().equals(method)) {
65.326 + found = m;
65.327 + }
65.328 + }
65.329 + Object res;
65.330 + if (found != null) {
65.331 + try {
65.332 + if ((found.getModifiers() & Modifier.STATIC) != 0) {
65.333 + res = found.invoke(null);
65.334 + } else {
65.335 + if (inst == null) {
65.336 + inst = c.newInstance();
65.337 + }
65.338 + res = found.invoke(inst);
65.339 + }
65.340 + } catch (Throwable ex) {
65.341 + if (ex instanceof InvocationTargetException) {
65.342 + ex = ((InvocationTargetException) ex).getTargetException();
65.343 + }
65.344 + if (ex instanceof InterruptedException) {
65.345 + throw (InterruptedException)ex;
65.346 + }
65.347 + res = ex.getClass().getName() + ":" + ex.getMessage();
65.348 + }
65.349 + } else {
65.350 + res = "Can't find method " + method + " in " + clazz;
65.351 + }
65.352 + return res;
65.353 + }
65.354 +
65.355 + private static Object toJSON(String s) {
65.356 + return InvokeJS.CObject.call("toJSON", s);
65.357 + }
65.358 +
65.359 + private static Object value(String p, Object d) {
65.360 + return ((JSObject)d).getMember(p);
65.361 + }
65.362 + }
65.363 +
65.364 + private static String safe(String txt) {
65.365 + return "try {" + txt + "} catch (err) { alert(err); }";
65.366 + }
65.367 +
65.368 + static {
65.369 + turnAssetionStatusOn();
65.370 + }
65.371 +
65.372 + private static final class InvokeJS {
65.373 + static final JSObject CObject = initJS();
65.374 +
65.375 + private static JSObject initJS() {
65.376 + WebEngine web = (WebEngine) System.getProperties().get("webEngine");
65.377 + return (JSObject) web.executeScript("(function() {"
65.378 + + "var CObject = {};"
65.379 +
65.380 + + "CObject.getAttr = function(elem, attr) { return elem[attr].toString(); };"
65.381 +
65.382 + + "CObject.setAttrId = function(id, attr, value) { window.document.getElementById(id)[attr] = value; };"
65.383 + + "CObject.setAttr = function(elem, attr, value) { elem[attr] = value; };"
65.384 +
65.385 + + "CObject.beginTest = function(test, c, arr) {" + safe(BEGIN_TEST) + "};"
65.386 +
65.387 + + "CObject.loadText = function(url, callback, arr) {" + safe(LOAD_TEXT.replace("run__V", "run")) + "};"
65.388 +
65.389 + + "CObject.schedule = function(r, time) { return window.setTimeout(function() { r.run(); }, time); };"
65.390 +
65.391 + + "CObject.toJSON = function(s) { return eval('(' + s + ')'); };"
65.392 +
65.393 + + "return CObject;"
65.394 + + "})(this)");
65.395 + }
65.396 + }
65.397 +
65.398 +}
66.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
66.2 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/FXBrwsr.java Thu May 02 09:18:22 2013 +0200
66.3 @@ -0,0 +1,184 @@
66.4 +/**
66.5 + * Back 2 Browser Bytecode Translator
66.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
66.7 + *
66.8 + * This program is free software: you can redistribute it and/or modify
66.9 + * it under the terms of the GNU General Public License as published by
66.10 + * the Free Software Foundation, version 2 of the License.
66.11 + *
66.12 + * This program is distributed in the hope that it will be useful,
66.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
66.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
66.15 + * GNU General Public License for more details.
66.16 + *
66.17 + * You should have received a copy of the GNU General Public License
66.18 + * along with this program. Look for COPYING file in the top folder.
66.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
66.20 + */
66.21 +package org.apidesign.bck2brwsr.launcher.fximpl;
66.22 +
66.23 +import java.util.List;
66.24 +import java.util.TooManyListenersException;
66.25 +import java.util.logging.Level;
66.26 +import java.util.logging.Logger;
66.27 +import javafx.application.Application;
66.28 +import javafx.application.Platform;
66.29 +import javafx.beans.value.ChangeListener;
66.30 +import javafx.beans.value.ObservableValue;
66.31 +import javafx.event.ActionEvent;
66.32 +import javafx.event.EventHandler;
66.33 +import javafx.geometry.HPos;
66.34 +import javafx.geometry.Insets;
66.35 +import javafx.geometry.Pos;
66.36 +import javafx.geometry.VPos;
66.37 +import javafx.scene.Node;
66.38 +import javafx.scene.Scene;
66.39 +import javafx.scene.control.Button;
66.40 +import javafx.scene.layout.ColumnConstraints;
66.41 +import javafx.scene.layout.GridPane;
66.42 +import javafx.scene.layout.Pane;
66.43 +import javafx.scene.layout.Priority;
66.44 +import javafx.scene.layout.VBox;
66.45 +import javafx.scene.text.Text;
66.46 +import javafx.scene.web.WebEngine;
66.47 +import javafx.scene.web.WebEvent;
66.48 +import javafx.scene.web.WebView;
66.49 +import javafx.stage.Modality;
66.50 +import javafx.stage.Stage;
66.51 +import netscape.javascript.JSObject;
66.52 +
66.53 +/**
66.54 + * Demonstrates a WebView object accessing a web page.
66.55 + *
66.56 + * @see javafx.scene.web.WebView
66.57 + * @see javafx.scene.web.WebEngine
66.58 + */
66.59 +public class FXBrwsr extends Application {
66.60 + private static final Logger LOG = Logger.getLogger(FXBrwsr.class.getName());
66.61 +
66.62 + @Override
66.63 + public void start(Stage primaryStage) throws Exception {
66.64 + Pane root = new WebViewPane(getParameters().getUnnamed());
66.65 + primaryStage.setScene(new Scene(root, 1024, 768));
66.66 + LOG.info("Showing the stage");
66.67 + primaryStage.show();
66.68 + LOG.log(Level.INFO, "State shown: {0}", primaryStage.isShowing());
66.69 + }
66.70 +
66.71 + /**
66.72 + * Create a resizable WebView pane
66.73 + */
66.74 + private class WebViewPane extends Pane {
66.75 + private final JVMBridge bridge = new JVMBridge();
66.76 +
66.77 + public WebViewPane(List<String> params) {
66.78 + LOG.log(Level.INFO, "Initializing WebView with {0}", params);
66.79 + VBox.setVgrow(this, Priority.ALWAYS);
66.80 + setMaxWidth(Double.MAX_VALUE);
66.81 + setMaxHeight(Double.MAX_VALUE);
66.82 + WebView view = new WebView();
66.83 + view.setMinSize(500, 400);
66.84 + view.setPrefSize(500, 400);
66.85 + final WebEngine eng = view.getEngine();
66.86 + try {
66.87 + JVMBridge.addBck2BrwsrLoad(new InitBck2Brwsr(eng));
66.88 + } catch (TooManyListenersException ex) {
66.89 + LOG.log(Level.SEVERE, null, ex);
66.90 + }
66.91 +
66.92 + if (params.size() > 0) {
66.93 + LOG.log(Level.INFO, "loading page {0}", params.get(0));
66.94 + eng.load(params.get(0));
66.95 + LOG.fine("back from load");
66.96 + }
66.97 + eng.setOnAlert(new EventHandler<WebEvent<String>>() {
66.98 + @Override
66.99 + public void handle(WebEvent<String> t) {
66.100 + final Stage dialogStage = new Stage();
66.101 + dialogStage.initModality(Modality.WINDOW_MODAL);
66.102 + dialogStage.setTitle("Warning");
66.103 + final Button button = new Button("Close");
66.104 + final Text text = new Text(t.getData());
66.105 +
66.106 + VBox box = new VBox();
66.107 + box.setAlignment(Pos.CENTER);
66.108 + box.setSpacing(10);
66.109 + box.setPadding(new Insets(10));
66.110 + box.getChildren().addAll(text, button);
66.111 +
66.112 + dialogStage.setScene(new Scene(box));
66.113 +
66.114 + button.setCancelButton(true);
66.115 + button.setOnAction(new EventHandler<ActionEvent>() {
66.116 + @Override
66.117 + public void handle(ActionEvent t) {
66.118 + dialogStage.close();
66.119 + }
66.120 + });
66.121 +
66.122 + dialogStage.centerOnScreen();
66.123 + dialogStage.showAndWait();
66.124 + }
66.125 + });
66.126 + GridPane grid = new GridPane();
66.127 + grid.setVgap(5);
66.128 + grid.setHgap(5);
66.129 + GridPane.setConstraints(view, 0, 1, 2, 1, HPos.CENTER, VPos.CENTER, Priority.ALWAYS, Priority.ALWAYS);
66.130 + grid.getColumnConstraints().addAll(new ColumnConstraints(100, 100, Double.MAX_VALUE, Priority.ALWAYS, HPos.CENTER, true), new ColumnConstraints(40, 40, 40, Priority.NEVER, HPos.CENTER, true));
66.131 + grid.getChildren().addAll(view);
66.132 + getChildren().add(grid);
66.133 + }
66.134 +
66.135 + boolean initBck2Brwsr(WebEngine webEngine) {
66.136 + JSObject jsobj = (JSObject) webEngine.executeScript("window");
66.137 + LOG.log(Level.FINE, "window: {0}", jsobj);
66.138 + Object prev = jsobj.getMember("bck2brwsr");
66.139 + if ("undefined".equals(prev)) {
66.140 + System.getProperties().put("webEngine", webEngine);
66.141 + jsobj.setMember("bck2brwsr", bridge);
66.142 + return true;
66.143 + }
66.144 + return false;
66.145 + }
66.146 +
66.147 + @Override
66.148 + protected void layoutChildren() {
66.149 + List<Node> managed = getManagedChildren();
66.150 + double width = getWidth();
66.151 + double height = getHeight();
66.152 + double top = getInsets().getTop();
66.153 + double right = getInsets().getRight();
66.154 + double left = getInsets().getLeft();
66.155 + double bottom = getInsets().getBottom();
66.156 + for (int i = 0; i < managed.size(); i++) {
66.157 + Node child = managed.get(i);
66.158 + layoutInArea(child, left, top, width - left - right, height - top - bottom, 0, Insets.EMPTY, true, true, HPos.CENTER, VPos.CENTER);
66.159 + }
66.160 + }
66.161 +
66.162 + private class InitBck2Brwsr implements ChangeListener<Void>, Runnable {
66.163 + private final WebEngine eng;
66.164 +
66.165 + public InitBck2Brwsr(WebEngine eng) {
66.166 + this.eng = eng;
66.167 + }
66.168 +
66.169 + @Override
66.170 + public synchronized void changed(ObservableValue<? extends Void> ov, Void t, Void t1) {
66.171 + Platform.runLater(this);
66.172 + try {
66.173 + wait();
66.174 + } catch (InterruptedException ex) {
66.175 + LOG.log(Level.SEVERE, null, ex);
66.176 + }
66.177 + }
66.178 +
66.179 + @Override
66.180 + public synchronized void run() {
66.181 + initBck2Brwsr(eng);
66.182 + notifyAll();
66.183 + }
66.184 + }
66.185 + }
66.186 +
66.187 +}
67.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
67.2 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/JVMBridge.java Thu May 02 09:18:22 2013 +0200
67.3 @@ -0,0 +1,64 @@
67.4 +/**
67.5 + * Back 2 Browser Bytecode Translator
67.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
67.7 + *
67.8 + * This program is free software: you can redistribute it and/or modify
67.9 + * it under the terms of the GNU General Public License as published by
67.10 + * the Free Software Foundation, version 2 of the License.
67.11 + *
67.12 + * This program is distributed in the hope that it will be useful,
67.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
67.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
67.15 + * GNU General Public License for more details.
67.16 + *
67.17 + * You should have received a copy of the GNU General Public License
67.18 + * along with this program. Look for COPYING file in the top folder.
67.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
67.20 + */
67.21 +package org.apidesign.bck2brwsr.launcher.fximpl;
67.22 +
67.23 +import java.util.TooManyListenersException;
67.24 +import javafx.beans.value.ChangeListener;
67.25 +
67.26 +/**
67.27 + *
67.28 + * @author Jaroslav Tulach <jtulach@netbeans.org>
67.29 + */
67.30 +public final class JVMBridge {
67.31 + private static ClassLoader[] ldrs;
67.32 + private static ChangeListener<Void> onBck2BrwsrLoad;
67.33 +
67.34 + public static void registerClassLoaders(ClassLoader[] loaders) {
67.35 + ldrs = loaders.clone();
67.36 + }
67.37 +
67.38 + public static void addBck2BrwsrLoad(ChangeListener<Void> l) throws TooManyListenersException {
67.39 + if (onBck2BrwsrLoad != null) {
67.40 + throw new TooManyListenersException();
67.41 + }
67.42 + onBck2BrwsrLoad = l;
67.43 + }
67.44 +
67.45 + public static void onBck2BrwsrLoad() {
67.46 + ChangeListener<Void> l = onBck2BrwsrLoad;
67.47 + if (l != null) {
67.48 + l.changed(null, null, null);
67.49 + }
67.50 + }
67.51 +
67.52 + public Class<?> loadClass(String name) throws ClassNotFoundException {
67.53 + System.err.println("trying to load " + name);
67.54 + ClassNotFoundException ex = null;
67.55 + if (ldrs != null) for (ClassLoader l : ldrs) {
67.56 + try {
67.57 + return Class.forName(name, true, l);
67.58 + } catch (ClassNotFoundException ex2) {
67.59 + ex = ex2;
67.60 + }
67.61 + }
67.62 + if (ex == null) {
67.63 + ex = new ClassNotFoundException("No loaders");
67.64 + }
67.65 + throw ex;
67.66 + }
67.67 +}
68.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
68.2 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/Run.java Thu May 02 09:18:22 2013 +0200
68.3 @@ -0,0 +1,35 @@
68.4 +/**
68.5 + * Back 2 Browser Bytecode Translator
68.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
68.7 + *
68.8 + * This program is free software: you can redistribute it and/or modify
68.9 + * it under the terms of the GNU General Public License as published by
68.10 + * the Free Software Foundation, version 2 of the License.
68.11 + *
68.12 + * This program is distributed in the hope that it will be useful,
68.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
68.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
68.15 + * GNU General Public License for more details.
68.16 + *
68.17 + * You should have received a copy of the GNU General Public License
68.18 + * along with this program. Look for COPYING file in the top folder.
68.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
68.20 + */
68.21 +
68.22 +package org.apidesign.bck2brwsr.launcher.fximpl;
68.23 +
68.24 +/**
68.25 + *
68.26 + * @author Jaroslav Tulach <jtulach@netbeans.org>
68.27 + */
68.28 +public final class Run implements Runnable {
68.29 + private final Runnable r;
68.30 + Run(Runnable r) {
68.31 + this.r = r;
68.32 + }
68.33 +
68.34 + @Override
68.35 + public void run() {
68.36 + r.run();
68.37 + }
68.38 +}
69.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
69.2 +++ b/launcher/fx/src/main/resources/org/apidesign/bck2brwsr/launcher/fximpl/harness.xhtml Thu May 02 09:18:22 2013 +0200
69.3 @@ -0,0 +1,52 @@
69.4 +<?xml version="1.0" encoding="UTF-8"?>
69.5 +<!--
69.6 +
69.7 + Back 2 Browser Bytecode Translator
69.8 + Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
69.9 +
69.10 + This program is free software: you can redistribute it and/or modify
69.11 + it under the terms of the GNU General Public License as published by
69.12 + the Free Software Foundation, version 2 of the License.
69.13 +
69.14 + This program is distributed in the hope that it will be useful,
69.15 + but WITHOUT ANY WARRANTY; without even the implied warranty of
69.16 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
69.17 + GNU General Public License for more details.
69.18 +
69.19 + You should have received a copy of the GNU General Public License
69.20 + along with this program. Look for COPYING file in the top folder.
69.21 + If not, see http://opensource.org/licenses/GPL-2.0.
69.22 +
69.23 +-->
69.24 +<!DOCTYPE html>
69.25 +<html xmlns="http://www.w3.org/1999/xhtml">
69.26 + <head>
69.27 + <title>Bck2Brwsr Harness</title>
69.28 + </head>
69.29 + <body>
69.30 + <script src="/bck2brwsr.js"></script>
69.31 + <script>
69.32 + var vm = bck2brwsr();
69.33 + </script>
69.34 +
69.35 + <h1>Bck2Brwsr Execution Harness</h1>
69.36 +
69.37 + <ul id="bck2brwsr.result" style="width: 100%;" >
69.38 + </ul>
69.39 +
69.40 + <div id="bck2brwsr.fragment"/>
69.41 +
69.42 + <script type="text/javascript">
69.43 + try {
69.44 + (function() {
69.45 + var cls = vm.loadClass('org.apidesign.bck2brwsr.launcher.fximpl.Console');
69.46 + // fxbrwsr mangling
69.47 + var inst = cls.newInstance();
69.48 + inst.harness('$U/../data');
69.49 + })();
69.50 + } catch (err) {
69.51 + alert('Error executing harness: ' + err);
69.52 + }
69.53 + </script>
69.54 + </body>
69.55 +</html>
70.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
70.2 +++ b/launcher/http/pom.xml Thu May 02 09:18:22 2013 +0200
70.3 @@ -0,0 +1,55 @@
70.4 +<?xml version="1.0"?>
70.5 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
70.6 + <modelVersion>4.0.0</modelVersion>
70.7 + <parent>
70.8 + <groupId>org.apidesign.bck2brwsr</groupId>
70.9 + <artifactId>launcher-pom</artifactId>
70.10 + <version>0.8-SNAPSHOT</version>
70.11 + </parent>
70.12 + <groupId>org.apidesign.bck2brwsr</groupId>
70.13 + <artifactId>launcher.http</artifactId>
70.14 + <version>0.8-SNAPSHOT</version>
70.15 + <name>Bck2Brwsr Launcher</name>
70.16 + <url>http://maven.apache.org</url>
70.17 + <build>
70.18 + <plugins>
70.19 + <plugin>
70.20 + <groupId>org.apache.maven.plugins</groupId>
70.21 + <artifactId>maven-compiler-plugin</artifactId>
70.22 + <version>2.3.2</version>
70.23 + <configuration>
70.24 + <source>1.7</source>
70.25 + <target>1.7</target>
70.26 + </configuration>
70.27 + </plugin>
70.28 + <plugin>
70.29 + <groupId>org.apache.maven.plugins</groupId>
70.30 + <artifactId>maven-javadoc-plugin</artifactId>
70.31 + <configuration>
70.32 + <subpackages>org.apidesign.bck2brwsr.launcher.b2b</subpackages>
70.33 + <skip>false</skip>
70.34 + </configuration>
70.35 + </plugin>
70.36 + </plugins>
70.37 + </build>
70.38 + <properties>
70.39 + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
70.40 + </properties>
70.41 + <dependencies>
70.42 + <dependency>
70.43 + <groupId>${project.groupId}</groupId>
70.44 + <artifactId>launcher</artifactId>
70.45 + <version>${project.version}</version>
70.46 + </dependency>
70.47 + <dependency>
70.48 + <groupId>org.glassfish.grizzly</groupId>
70.49 + <artifactId>grizzly-http-server</artifactId>
70.50 + <version>2.2.19</version>
70.51 + </dependency>
70.52 + <dependency>
70.53 + <groupId>${project.groupId}</groupId>
70.54 + <artifactId>vm4brwsr</artifactId>
70.55 + <version>${project.version}</version>
70.56 + </dependency>
70.57 + </dependencies>
70.58 +</project>
71.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
71.2 +++ b/launcher/http/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java Thu May 02 09:18:22 2013 +0200
71.3 @@ -0,0 +1,604 @@
71.4 +/**
71.5 + * Back 2 Browser Bytecode Translator
71.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
71.7 + *
71.8 + * This program is free software: you can redistribute it and/or modify
71.9 + * it under the terms of the GNU General Public License as published by
71.10 + * the Free Software Foundation, version 2 of the License.
71.11 + *
71.12 + * This program is distributed in the hope that it will be useful,
71.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
71.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
71.15 + * GNU General Public License for more details.
71.16 + *
71.17 + * You should have received a copy of the GNU General Public License
71.18 + * along with this program. Look for COPYING file in the top folder.
71.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
71.20 + */
71.21 +package org.apidesign.bck2brwsr.launcher;
71.22 +
71.23 +import java.io.Closeable;
71.24 +import java.io.File;
71.25 +import java.io.IOException;
71.26 +import java.io.InputStream;
71.27 +import java.io.InterruptedIOException;
71.28 +import java.io.OutputStream;
71.29 +import java.io.UnsupportedEncodingException;
71.30 +import java.io.Writer;
71.31 +import java.net.URI;
71.32 +import java.net.URISyntaxException;
71.33 +import java.net.URL;
71.34 +import java.util.ArrayList;
71.35 +import java.util.Arrays;
71.36 +import java.util.Enumeration;
71.37 +import java.util.LinkedHashSet;
71.38 +import java.util.List;
71.39 +import java.util.Set;
71.40 +import java.util.concurrent.BlockingQueue;
71.41 +import java.util.concurrent.CountDownLatch;
71.42 +import java.util.concurrent.LinkedBlockingQueue;
71.43 +import java.util.concurrent.TimeUnit;
71.44 +import java.util.logging.Level;
71.45 +import java.util.logging.Logger;
71.46 +import org.apidesign.bck2brwsr.launcher.InvocationContext.Resource;
71.47 +import org.apidesign.vm4brwsr.Bck2Brwsr;
71.48 +import org.glassfish.grizzly.PortRange;
71.49 +import org.glassfish.grizzly.http.server.HttpHandler;
71.50 +import org.glassfish.grizzly.http.server.HttpServer;
71.51 +import org.glassfish.grizzly.http.server.NetworkListener;
71.52 +import org.glassfish.grizzly.http.server.Request;
71.53 +import org.glassfish.grizzly.http.server.Response;
71.54 +import org.glassfish.grizzly.http.server.ServerConfiguration;
71.55 +import org.glassfish.grizzly.http.util.HttpStatus;
71.56 +
71.57 +/**
71.58 + * Lightweight server to launch Bck2Brwsr applications and tests.
71.59 + * Supports execution in native browser as well as Java's internal
71.60 + * execution engine.
71.61 + */
71.62 +final class Bck2BrwsrLauncher extends Launcher implements Closeable {
71.63 + private static final Logger LOG = Logger.getLogger(Bck2BrwsrLauncher.class.getName());
71.64 + private static final InvocationContext END = new InvocationContext(null, null, null);
71.65 + private final Set<ClassLoader> loaders = new LinkedHashSet<>();
71.66 + private final BlockingQueue<InvocationContext> methods = new LinkedBlockingQueue<>();
71.67 + private long timeOut;
71.68 + private final Res resources = new Res();
71.69 + private final String cmd;
71.70 + private Object[] brwsr;
71.71 + private HttpServer server;
71.72 + private CountDownLatch wait;
71.73 +
71.74 + public Bck2BrwsrLauncher(String cmd) {
71.75 + this.cmd = cmd;
71.76 + addClassLoader(Bck2Brwsr.class.getClassLoader());
71.77 + setTimeout(180000);
71.78 + }
71.79 +
71.80 + @Override
71.81 + InvocationContext runMethod(InvocationContext c) throws IOException {
71.82 + loaders.add(c.clazz.getClassLoader());
71.83 + methods.add(c);
71.84 + try {
71.85 + c.await(timeOut);
71.86 + } catch (InterruptedException ex) {
71.87 + throw new IOException(ex);
71.88 + }
71.89 + return c;
71.90 + }
71.91 +
71.92 + public void setTimeout(long ms) {
71.93 + timeOut = ms;
71.94 + }
71.95 +
71.96 + public void addClassLoader(ClassLoader url) {
71.97 + this.loaders.add(url);
71.98 + }
71.99 +
71.100 + public void showURL(String startpage) throws IOException {
71.101 + if (!startpage.startsWith("/")) {
71.102 + startpage = "/" + startpage;
71.103 + }
71.104 + HttpServer s = initServer(".", true);
71.105 + int last = startpage.lastIndexOf('/');
71.106 + String prefix = startpage.substring(0, last);
71.107 + String simpleName = startpage.substring(last);
71.108 + s.getServerConfiguration().addHttpHandler(new SubTree(resources, prefix), "/");
71.109 + try {
71.110 + launchServerAndBrwsr(s, simpleName);
71.111 + } catch (URISyntaxException | InterruptedException ex) {
71.112 + throw new IOException(ex);
71.113 + }
71.114 + }
71.115 +
71.116 + void showDirectory(File dir, String startpage) throws IOException {
71.117 + if (!startpage.startsWith("/")) {
71.118 + startpage = "/" + startpage;
71.119 + }
71.120 + HttpServer s = initServer(dir.getPath(), false);
71.121 + try {
71.122 + launchServerAndBrwsr(s, startpage);
71.123 + } catch (URISyntaxException | InterruptedException ex) {
71.124 + throw new IOException(ex);
71.125 + }
71.126 + }
71.127 +
71.128 + @Override
71.129 + public void initialize() throws IOException {
71.130 + try {
71.131 + executeInBrowser();
71.132 + } catch (InterruptedException ex) {
71.133 + final InterruptedIOException iio = new InterruptedIOException(ex.getMessage());
71.134 + iio.initCause(ex);
71.135 + throw iio;
71.136 + } catch (Exception ex) {
71.137 + if (ex instanceof IOException) {
71.138 + throw (IOException)ex;
71.139 + }
71.140 + if (ex instanceof RuntimeException) {
71.141 + throw (RuntimeException)ex;
71.142 + }
71.143 + throw new IOException(ex);
71.144 + }
71.145 + }
71.146 +
71.147 + private HttpServer initServer(String path, boolean addClasses) throws IOException {
71.148 + HttpServer s = HttpServer.createSimpleServer(path, new PortRange(8080, 65535));
71.149 +
71.150 + final ServerConfiguration conf = s.getServerConfiguration();
71.151 + if (addClasses) {
71.152 + conf.addHttpHandler(new VM(resources), "/bck2brwsr.js");
71.153 + conf.addHttpHandler(new Classes(resources), "/classes/");
71.154 + }
71.155 + return s;
71.156 + }
71.157 +
71.158 + private void executeInBrowser() throws InterruptedException, URISyntaxException, IOException {
71.159 + wait = new CountDownLatch(1);
71.160 + server = initServer(".", true);
71.161 + final ServerConfiguration conf = server.getServerConfiguration();
71.162 +
71.163 + class DynamicResourceHandler extends HttpHandler {
71.164 + private final InvocationContext ic;
71.165 + public DynamicResourceHandler(InvocationContext ic) {
71.166 + if (ic == null || ic.resources.isEmpty()) {
71.167 + throw new NullPointerException();
71.168 + }
71.169 + this.ic = ic;
71.170 + for (Resource r : ic.resources) {
71.171 + conf.addHttpHandler(this, r.httpPath);
71.172 + }
71.173 + }
71.174 +
71.175 + public void close() {
71.176 + conf.removeHttpHandler(this);
71.177 + }
71.178 +
71.179 + @Override
71.180 + public void service(Request request, Response response) throws Exception {
71.181 + for (Resource r : ic.resources) {
71.182 + if (r.httpPath.equals(request.getRequestURI())) {
71.183 + LOG.log(Level.INFO, "Serving HttpResource for {0}", request.getRequestURI());
71.184 + response.setContentType(r.httpType);
71.185 + r.httpContent.reset();
71.186 + String[] params = null;
71.187 + if (r.parameters.length != 0) {
71.188 + params = new String[r.parameters.length];
71.189 + for (int i = 0; i < r.parameters.length; i++) {
71.190 + params[i] = request.getParameter(r.parameters[i]);
71.191 + }
71.192 + }
71.193 +
71.194 + copyStream(r.httpContent, response.getOutputStream(), null, params);
71.195 + }
71.196 + }
71.197 + }
71.198 + }
71.199 +
71.200 + conf.addHttpHandler(new Page(resources,
71.201 + "org/apidesign/bck2brwsr/launcher/harness.xhtml"
71.202 + ), "/execute");
71.203 +
71.204 + conf.addHttpHandler(new HttpHandler() {
71.205 + int cnt;
71.206 + List<InvocationContext> cases = new ArrayList<>();
71.207 + DynamicResourceHandler prev;
71.208 + @Override
71.209 + public void service(Request request, Response response) throws Exception {
71.210 + String id = request.getParameter("request");
71.211 + String value = request.getParameter("result");
71.212 + if (value != null && value.indexOf((char)0xC5) != -1) {
71.213 + value = toUTF8(value);
71.214 + }
71.215 +
71.216 +
71.217 + InvocationContext mi = null;
71.218 + int caseNmbr = -1;
71.219 +
71.220 + if (id != null && value != null) {
71.221 + LOG.log(Level.INFO, "Received result for case {0} = {1}", new Object[]{id, value});
71.222 + value = decodeURL(value);
71.223 + int indx = Integer.parseInt(id);
71.224 + cases.get(indx).result(value, null);
71.225 + if (++indx < cases.size()) {
71.226 + mi = cases.get(indx);
71.227 + LOG.log(Level.INFO, "Re-executing case {0}", indx);
71.228 + caseNmbr = indx;
71.229 + }
71.230 + } else {
71.231 + if (!cases.isEmpty()) {
71.232 + LOG.info("Re-executing test cases");
71.233 + mi = cases.get(0);
71.234 + caseNmbr = 0;
71.235 + }
71.236 + }
71.237 +
71.238 + if (prev != null) {
71.239 + prev.close();
71.240 + prev = null;
71.241 + }
71.242 +
71.243 + if (mi == null) {
71.244 + mi = methods.take();
71.245 + caseNmbr = cnt++;
71.246 + }
71.247 + if (mi == END) {
71.248 + response.getWriter().write("");
71.249 + wait.countDown();
71.250 + cnt = 0;
71.251 + LOG.log(Level.INFO, "End of data reached. Exiting.");
71.252 + return;
71.253 + }
71.254 +
71.255 + if (!mi.resources.isEmpty()) {
71.256 + prev = new DynamicResourceHandler(mi);
71.257 + }
71.258 +
71.259 + cases.add(mi);
71.260 + final String cn = mi.clazz.getName();
71.261 + final String mn = mi.methodName;
71.262 + LOG.log(Level.INFO, "Request for {0} case. Sending {1}.{2}", new Object[]{caseNmbr, cn, mn});
71.263 + response.getWriter().write("{"
71.264 + + "className: '" + cn + "', "
71.265 + + "methodName: '" + mn + "', "
71.266 + + "request: " + caseNmbr
71.267 + );
71.268 + if (mi.html != null) {
71.269 + response.getWriter().write(", html: '");
71.270 + response.getWriter().write(encodeJSON(mi.html));
71.271 + response.getWriter().write("'");
71.272 + }
71.273 + response.getWriter().write("}");
71.274 + }
71.275 + }, "/data");
71.276 +
71.277 + this.brwsr = launchServerAndBrwsr(server, "/execute");
71.278 + }
71.279 +
71.280 + private static String encodeJSON(String in) {
71.281 + StringBuilder sb = new StringBuilder();
71.282 + for (int i = 0; i < in.length(); i++) {
71.283 + char ch = in.charAt(i);
71.284 + if (ch < 32 || ch == '\'' || ch == '"') {
71.285 + sb.append("\\u");
71.286 + String hs = "0000" + Integer.toHexString(ch);
71.287 + hs = hs.substring(hs.length() - 4);
71.288 + sb.append(hs);
71.289 + } else {
71.290 + sb.append(ch);
71.291 + }
71.292 + }
71.293 + return sb.toString();
71.294 + }
71.295 +
71.296 + @Override
71.297 + public void shutdown() throws IOException {
71.298 + methods.offer(END);
71.299 + for (;;) {
71.300 + int prev = methods.size();
71.301 + try {
71.302 + if (wait != null && wait.await(timeOut, TimeUnit.MILLISECONDS)) {
71.303 + break;
71.304 + }
71.305 + } catch (InterruptedException ex) {
71.306 + throw new IOException(ex);
71.307 + }
71.308 + if (prev == methods.size()) {
71.309 + LOG.log(
71.310 + Level.WARNING,
71.311 + "Timeout and no test has been executed meanwhile (at {0}). Giving up.",
71.312 + methods.size()
71.313 + );
71.314 + break;
71.315 + }
71.316 + LOG.log(Level.INFO,
71.317 + "Timeout, but tests got from {0} to {1}. Trying again.",
71.318 + new Object[]{prev, methods.size()}
71.319 + );
71.320 + }
71.321 + stopServerAndBrwsr(server, brwsr);
71.322 + }
71.323 +
71.324 + static void copyStream(InputStream is, OutputStream os, String baseURL, String... params) throws IOException {
71.325 + for (;;) {
71.326 + int ch = is.read();
71.327 + if (ch == -1) {
71.328 + break;
71.329 + }
71.330 + if (ch == '$' && params.length > 0) {
71.331 + int cnt = is.read() - '0';
71.332 + if (baseURL != null && cnt == 'U' - '0') {
71.333 + os.write(baseURL.getBytes("UTF-8"));
71.334 + } else {
71.335 + if (cnt >= 0 && cnt < params.length) {
71.336 + os.write(params[cnt].getBytes("UTF-8"));
71.337 + } else {
71.338 + os.write('$');
71.339 + os.write(cnt + '0');
71.340 + }
71.341 + }
71.342 + } else {
71.343 + os.write(ch);
71.344 + }
71.345 + }
71.346 + }
71.347 +
71.348 + private Object[] launchServerAndBrwsr(HttpServer server, final String page) throws IOException, URISyntaxException, InterruptedException {
71.349 + server.start();
71.350 + NetworkListener listener = server.getListeners().iterator().next();
71.351 + int port = listener.getPort();
71.352 +
71.353 + URI uri = new URI("http://localhost:" + port + page);
71.354 + LOG.log(Level.INFO, "Showing {0}", uri);
71.355 + if (cmd == null) {
71.356 + try {
71.357 + LOG.log(Level.INFO, "Trying Desktop.browse on {0} {2} by {1}", new Object[] {
71.358 + System.getProperty("java.vm.name"),
71.359 + System.getProperty("java.vm.vendor"),
71.360 + System.getProperty("java.vm.version"),
71.361 + });
71.362 + java.awt.Desktop.getDesktop().browse(uri);
71.363 + LOG.log(Level.INFO, "Desktop.browse successfully finished");
71.364 + return null;
71.365 + } catch (UnsupportedOperationException ex) {
71.366 + LOG.log(Level.INFO, "Desktop.browse not supported: {0}", ex.getMessage());
71.367 + LOG.log(Level.FINE, null, ex);
71.368 + }
71.369 + }
71.370 + {
71.371 + String cmdName = cmd == null ? "xdg-open" : cmd;
71.372 + String[] cmdArr = {
71.373 + cmdName, uri.toString()
71.374 + };
71.375 + LOG.log(Level.INFO, "Launching {0}", Arrays.toString(cmdArr));
71.376 + final Process process = Runtime.getRuntime().exec(cmdArr);
71.377 + return new Object[] { process, null };
71.378 + }
71.379 + }
71.380 + private static String toUTF8(String value) throws UnsupportedEncodingException {
71.381 + byte[] arr = new byte[value.length()];
71.382 + for (int i = 0; i < arr.length; i++) {
71.383 + arr[i] = (byte)value.charAt(i);
71.384 + }
71.385 + return new String(arr, "UTF-8");
71.386 + }
71.387 +
71.388 + private static String decodeURL(String s) {
71.389 + for (;;) {
71.390 + int pos = s.indexOf('%');
71.391 + if (pos == -1) {
71.392 + return s;
71.393 + }
71.394 + int i = Integer.parseInt(s.substring(pos + 1, pos + 2), 16);
71.395 + s = s.substring(0, pos) + (char)i + s.substring(pos + 2);
71.396 + }
71.397 + }
71.398 +
71.399 + private void stopServerAndBrwsr(HttpServer server, Object[] brwsr) throws IOException {
71.400 + if (brwsr == null) {
71.401 + return;
71.402 + }
71.403 + Process process = (Process)brwsr[0];
71.404 +
71.405 + server.stop();
71.406 + InputStream stdout = process.getInputStream();
71.407 + InputStream stderr = process.getErrorStream();
71.408 + drain("StdOut", stdout);
71.409 + drain("StdErr", stderr);
71.410 + process.destroy();
71.411 + int res;
71.412 + try {
71.413 + res = process.waitFor();
71.414 + } catch (InterruptedException ex) {
71.415 + throw new IOException(ex);
71.416 + }
71.417 + LOG.log(Level.INFO, "Exit code: {0}", res);
71.418 +
71.419 + deleteTree((File)brwsr[1]);
71.420 + }
71.421 +
71.422 + private static void drain(String name, InputStream is) throws IOException {
71.423 + int av = is.available();
71.424 + if (av > 0) {
71.425 + StringBuilder sb = new StringBuilder();
71.426 + sb.append("v== ").append(name).append(" ==v\n");
71.427 + while (av-- > 0) {
71.428 + sb.append((char)is.read());
71.429 + }
71.430 + sb.append("\n^== ").append(name).append(" ==^");
71.431 + LOG.log(Level.INFO, sb.toString());
71.432 + }
71.433 + }
71.434 +
71.435 + private void deleteTree(File file) {
71.436 + if (file == null) {
71.437 + return;
71.438 + }
71.439 + File[] arr = file.listFiles();
71.440 + if (arr != null) {
71.441 + for (File s : arr) {
71.442 + deleteTree(s);
71.443 + }
71.444 + }
71.445 + file.delete();
71.446 + }
71.447 +
71.448 + @Override
71.449 + public void close() throws IOException {
71.450 + shutdown();
71.451 + }
71.452 +
71.453 + private class Res implements Bck2Brwsr.Resources {
71.454 + @Override
71.455 + public InputStream get(String resource) throws IOException {
71.456 + URL u = null;
71.457 + for (ClassLoader l : loaders) {
71.458 + Enumeration<URL> en = l.getResources(resource);
71.459 + while (en.hasMoreElements()) {
71.460 + u = en.nextElement();
71.461 + }
71.462 + }
71.463 + if (u != null) {
71.464 + return u.openStream();
71.465 + }
71.466 + throw new IOException("Can't find " + resource);
71.467 + }
71.468 + }
71.469 +
71.470 + private static class Page extends HttpHandler {
71.471 + final String resource;
71.472 + private final String[] args;
71.473 + private final Res res;
71.474 +
71.475 + public Page(Res res, String resource, String... args) {
71.476 + this.res = res;
71.477 + this.resource = resource;
71.478 + this.args = args.length == 0 ? new String[] { "$0" } : args;
71.479 + }
71.480 +
71.481 + @Override
71.482 + public void service(Request request, Response response) throws Exception {
71.483 + String r = computePage(request);
71.484 + if (r.startsWith("/")) {
71.485 + r = r.substring(1);
71.486 + }
71.487 + String[] replace = {};
71.488 + if (r.endsWith(".html")) {
71.489 + response.setContentType("text/html");
71.490 + LOG.info("Content type text/html");
71.491 + replace = args;
71.492 + }
71.493 + if (r.endsWith(".xhtml")) {
71.494 + response.setContentType("application/xhtml+xml");
71.495 + LOG.info("Content type application/xhtml+xml");
71.496 + replace = args;
71.497 + }
71.498 + OutputStream os = response.getOutputStream();
71.499 + try (InputStream is = res.get(r)) {
71.500 + copyStream(is, os, request.getRequestURL().toString(), replace);
71.501 + } catch (IOException ex) {
71.502 + response.setDetailMessage(ex.getLocalizedMessage());
71.503 + response.setError();
71.504 + response.setStatus(404);
71.505 + }
71.506 + }
71.507 +
71.508 + protected String computePage(Request request) {
71.509 + String r = resource;
71.510 + if (r == null) {
71.511 + r = request.getHttpHandlerPath();
71.512 + }
71.513 + return r;
71.514 + }
71.515 + }
71.516 +
71.517 + private static class SubTree extends Page {
71.518 +
71.519 + public SubTree(Res res, String resource, String... args) {
71.520 + super(res, resource, args);
71.521 + }
71.522 +
71.523 + @Override
71.524 + protected String computePage(Request request) {
71.525 + return resource + request.getHttpHandlerPath();
71.526 + }
71.527 +
71.528 +
71.529 + }
71.530 +
71.531 + private static class VM extends HttpHandler {
71.532 + private final String bck2brwsr;
71.533 +
71.534 + public VM(Res loader) throws IOException {
71.535 + StringBuilder sb = new StringBuilder();
71.536 + Bck2Brwsr.generate(sb, loader);
71.537 + sb.append(
71.538 + "(function WrapperVM(global) {"
71.539 + + " function ldCls(res) {\n"
71.540 + + " var request = new XMLHttpRequest();\n"
71.541 + + " request.open('GET', '/classes/' + res, false);\n"
71.542 + + " request.send();\n"
71.543 + + " if (request.status !== 200) return null;\n"
71.544 + + " var arr = eval('(' + request.responseText + ')');\n"
71.545 + + " return arr;\n"
71.546 + + " }\n"
71.547 + + " var prevvm = global.bck2brwsr;\n"
71.548 + + " global.bck2brwsr = function() {\n"
71.549 + + " var args = Array.prototype.slice.apply(arguments);\n"
71.550 + + " args.unshift(ldCls);\n"
71.551 + + " return prevvm.apply(null, args);\n"
71.552 + + " };\n"
71.553 + + "})(this);\n"
71.554 + );
71.555 + this.bck2brwsr = sb.toString();
71.556 + }
71.557 +
71.558 + @Override
71.559 + public void service(Request request, Response response) throws Exception {
71.560 + response.setCharacterEncoding("UTF-8");
71.561 + response.setContentType("text/javascript");
71.562 + response.getWriter().write(bck2brwsr);
71.563 + }
71.564 + }
71.565 +
71.566 + private static class Classes extends HttpHandler {
71.567 + private final Res loader;
71.568 +
71.569 + public Classes(Res loader) {
71.570 + this.loader = loader;
71.571 + }
71.572 +
71.573 + @Override
71.574 + public void service(Request request, Response response) throws Exception {
71.575 + String res = request.getHttpHandlerPath();
71.576 + if (res.startsWith("/")) {
71.577 + res = res.substring(1);
71.578 + }
71.579 + try (InputStream is = loader.get(res)) {
71.580 + response.setContentType("text/javascript");
71.581 + Writer w = response.getWriter();
71.582 + w.append("[");
71.583 + for (int i = 0;; i++) {
71.584 + int b = is.read();
71.585 + if (b == -1) {
71.586 + break;
71.587 + }
71.588 + if (i > 0) {
71.589 + w.append(", ");
71.590 + }
71.591 + if (i % 20 == 0) {
71.592 + w.write("\n");
71.593 + }
71.594 + if (b > 127) {
71.595 + b = b - 256;
71.596 + }
71.597 + w.append(Integer.toString(b));
71.598 + }
71.599 + w.append("\n]");
71.600 + } catch (IOException ex) {
71.601 + response.setStatus(HttpStatus.NOT_FOUND_404);
71.602 + response.setError();
71.603 + response.setDetailMessage(ex.getMessage());
71.604 + }
71.605 + }
71.606 + }
71.607 +}
72.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
72.2 +++ b/launcher/http/src/main/java/org/apidesign/bck2brwsr/launcher/JSLauncher.java Thu May 02 09:18:22 2013 +0200
72.3 @@ -0,0 +1,135 @@
72.4 +/**
72.5 + * Back 2 Browser Bytecode Translator
72.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
72.7 + *
72.8 + * This program is free software: you can redistribute it and/or modify
72.9 + * it under the terms of the GNU General Public License as published by
72.10 + * the Free Software Foundation, version 2 of the License.
72.11 + *
72.12 + * This program is distributed in the hope that it will be useful,
72.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
72.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
72.15 + * GNU General Public License for more details.
72.16 + *
72.17 + * You should have received a copy of the GNU General Public License
72.18 + * along with this program. Look for COPYING file in the top folder.
72.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
72.20 + */
72.21 +package org.apidesign.bck2brwsr.launcher;
72.22 +
72.23 +import org.apidesign.bck2brwsr.launcher.impl.Console;
72.24 +import java.io.IOException;
72.25 +import java.io.InputStream;
72.26 +import java.net.URL;
72.27 +import java.util.Enumeration;
72.28 +import java.util.LinkedHashSet;
72.29 +import java.util.Set;
72.30 +import java.util.logging.Level;
72.31 +import java.util.logging.Logger;
72.32 +import javax.script.Invocable;
72.33 +import javax.script.ScriptEngine;
72.34 +import javax.script.ScriptEngineManager;
72.35 +import javax.script.ScriptException;
72.36 +import org.apidesign.vm4brwsr.Bck2Brwsr;
72.37 +
72.38 +/**
72.39 + * Tests execution in Java's internal scripting engine.
72.40 + */
72.41 +final class JSLauncher extends Launcher {
72.42 + private static final Logger LOG = Logger.getLogger(JSLauncher.class.getName());
72.43 + private Set<ClassLoader> loaders = new LinkedHashSet<>();
72.44 + private final Res resources = new Res();
72.45 + private Invocable code;
72.46 + private StringBuilder codeSeq;
72.47 + private Object console;
72.48 +
72.49 + JSLauncher() {
72.50 + addClassLoader(Bck2Brwsr.class.getClassLoader());
72.51 + }
72.52 +
72.53 + @Override InvocationContext runMethod(InvocationContext mi) {
72.54 + loaders.add(mi.clazz.getClassLoader());
72.55 + try {
72.56 + long time = System.currentTimeMillis();
72.57 + LOG.log(Level.FINE, "Invoking {0}.{1}", new Object[]{mi.clazz.getName(), mi.methodName});
72.58 + String res = code.invokeMethod(
72.59 + console,
72.60 + "invoke__Ljava_lang_String_2Ljava_lang_String_2Ljava_lang_String_2",
72.61 + mi.clazz.getName(), mi.methodName).toString();
72.62 + time = System.currentTimeMillis() - time;
72.63 + LOG.log(Level.FINE, "Resut of {0}.{1} = {2} in {3} ms", new Object[]{mi.clazz.getName(), mi.methodName, res, time});
72.64 + mi.result(res, null);
72.65 + } catch (ScriptException | NoSuchMethodException ex) {
72.66 + mi.result(null, ex);
72.67 + }
72.68 + return mi;
72.69 + }
72.70 +
72.71 + public void addClassLoader(ClassLoader url) {
72.72 + this.loaders.add(url);
72.73 + }
72.74 +
72.75 + @Override
72.76 + public void initialize() throws IOException {
72.77 + try {
72.78 + initRhino();
72.79 + } catch (Exception ex) {
72.80 + if (ex instanceof IOException) {
72.81 + throw (IOException)ex;
72.82 + }
72.83 + if (ex instanceof RuntimeException) {
72.84 + throw (RuntimeException)ex;
72.85 + }
72.86 + throw new IOException(ex);
72.87 + }
72.88 + }
72.89 +
72.90 + private void initRhino() throws IOException, ScriptException, NoSuchMethodException {
72.91 + StringBuilder sb = new StringBuilder();
72.92 + Bck2Brwsr.generate(sb, new Res());
72.93 +
72.94 + ScriptEngineManager sem = new ScriptEngineManager();
72.95 + ScriptEngine mach = sem.getEngineByExtension("js");
72.96 +
72.97 + sb.append(
72.98 + "\nvar vm = new bck2brwsr(org.apidesign.bck2brwsr.launcher.impl.Console.read);"
72.99 + + "\nfunction initVM() { return vm; };"
72.100 + + "\n");
72.101 +
72.102 + Object res = mach.eval(sb.toString());
72.103 + if (!(mach instanceof Invocable)) {
72.104 + throw new IOException("It is invocable object: " + res);
72.105 + }
72.106 + code = (Invocable) mach;
72.107 + codeSeq = sb;
72.108 +
72.109 + Object vm = code.invokeFunction("initVM");
72.110 + console = code.invokeMethod(vm, "loadClass", Console.class.getName());
72.111 + }
72.112 +
72.113 + @Override
72.114 + public void shutdown() throws IOException {
72.115 + }
72.116 +
72.117 + @Override
72.118 + public String toString() {
72.119 + return codeSeq.toString();
72.120 + }
72.121 +
72.122 + private class Res implements Bck2Brwsr.Resources {
72.123 + @Override
72.124 + public InputStream get(String resource) throws IOException {
72.125 + for (ClassLoader l : loaders) {
72.126 + URL u = null;
72.127 + Enumeration<URL> en = l.getResources(resource);
72.128 + while (en.hasMoreElements()) {
72.129 + u = en.nextElement();
72.130 + }
72.131 + if (u != null) {
72.132 + return u.openStream();
72.133 + }
72.134 + }
72.135 + throw new IOException("Can't find " + resource);
72.136 + }
72.137 + }
72.138 +}
73.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
73.2 +++ b/launcher/http/src/main/java/org/apidesign/bck2brwsr/launcher/b2b/LauncherBck2Brwsr.java Thu May 02 09:18:22 2013 +0200
73.3 @@ -0,0 +1,33 @@
73.4 +/**
73.5 + * Back 2 Browser Bytecode Translator
73.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
73.7 + *
73.8 + * This program is free software: you can redistribute it and/or modify
73.9 + * it under the terms of the GNU General Public License as published by
73.10 + * the Free Software Foundation, version 2 of the License.
73.11 + *
73.12 + * This program is distributed in the hope that it will be useful,
73.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
73.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
73.15 + * GNU General Public License for more details.
73.16 + *
73.17 + * You should have received a copy of the GNU General Public License
73.18 + * along with this program. Look for COPYING file in the top folder.
73.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
73.20 + */
73.21 +package org.apidesign.bck2brwsr.launcher.b2b;
73.22 +
73.23 +import java.awt.Desktop;
73.24 +import org.apidesign.bck2brwsr.launcher.Launcher;
73.25 +
73.26 +/** This is a launcher for the <a href="http://bck2brwsr.apidesign.org">Bck2Brwsr</a>
73.27 + * project that is using {@link Desktop} (or {@link Process}) to display the
73.28 + * external browser in separate process. Use {@link Launcher} methods to access this
73.29 + * functionality via public, supported methods.
73.30 + *
73.31 + * @author Jaroslav Tulach
73.32 + */
73.33 +public final class LauncherBck2Brwsr {
73.34 + private LauncherBck2Brwsr() {
73.35 + }
73.36 +}
74.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
74.2 +++ b/launcher/http/src/main/java/org/apidesign/bck2brwsr/launcher/impl/Console.java Thu May 02 09:18:22 2013 +0200
74.3 @@ -0,0 +1,356 @@
74.4 +/**
74.5 + * Back 2 Browser Bytecode Translator
74.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
74.7 + *
74.8 + * This program is free software: you can redistribute it and/or modify
74.9 + * it under the terms of the GNU General Public License as published by
74.10 + * the Free Software Foundation, version 2 of the License.
74.11 + *
74.12 + * This program is distributed in the hope that it will be useful,
74.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
74.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
74.15 + * GNU General Public License for more details.
74.16 + *
74.17 + * You should have received a copy of the GNU General Public License
74.18 + * along with this program. Look for COPYING file in the top folder.
74.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
74.20 + */
74.21 +package org.apidesign.bck2brwsr.launcher.impl;
74.22 +
74.23 +import java.io.IOException;
74.24 +import java.io.InputStream;
74.25 +import java.io.UnsupportedEncodingException;
74.26 +import java.lang.reflect.InvocationTargetException;
74.27 +import java.lang.reflect.Method;
74.28 +import java.lang.reflect.Modifier;
74.29 +import java.net.URL;
74.30 +import java.util.Enumeration;
74.31 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
74.32 +
74.33 +/**
74.34 + *
74.35 + * @author Jaroslav Tulach <jtulach@netbeans.org>
74.36 + */
74.37 +public class Console {
74.38 + private Console() {
74.39 + }
74.40 + static {
74.41 + turnAssetionStatusOn();
74.42 + }
74.43 +
74.44 + @JavaScriptBody(args = {"id", "attr"}, body =
74.45 + "return window.document.getElementById(id)[attr].toString();")
74.46 + private static native Object getAttr(String id, String attr);
74.47 + @JavaScriptBody(args = {"elem", "attr"}, body =
74.48 + "return elem[attr].toString();")
74.49 + private static native Object getAttr(Object elem, String attr);
74.50 +
74.51 + @JavaScriptBody(args = {"id", "attr", "value"}, body =
74.52 + "window.document.getElementById(id)[attr] = value;")
74.53 + private static native void setAttr(String id, String attr, Object value);
74.54 + @JavaScriptBody(args = {"elem", "attr", "value"}, body =
74.55 + "elem[attr] = value;")
74.56 + private static native void setAttr(Object id, String attr, Object value);
74.57 +
74.58 + @JavaScriptBody(args = {}, body = "return; window.close();")
74.59 + private static native void closeWindow();
74.60 +
74.61 + private static Object textArea;
74.62 + private static Object statusArea;
74.63 +
74.64 + private static void log(String newText) {
74.65 + if (textArea == null) {
74.66 + return;
74.67 + }
74.68 + String attr = "value";
74.69 + setAttr(textArea, attr, getAttr(textArea, attr) + "\n" + newText);
74.70 + setAttr(textArea, "scrollTop", getAttr(textArea, "scrollHeight"));
74.71 + }
74.72 +
74.73 + private static void beginTest(Case c) {
74.74 + Object[] arr = new Object[2];
74.75 + beginTest(c.getClassName() + "." + c.getMethodName(), c, arr);
74.76 + textArea = arr[0];
74.77 + statusArea = arr[1];
74.78 + }
74.79 +
74.80 + private static void finishTest(Case c, Object res) {
74.81 + if ("null".equals(res)) {
74.82 + setAttr(statusArea, "innerHTML", "Success");
74.83 + } else {
74.84 + setAttr(statusArea, "innerHTML", "Result " + res);
74.85 + }
74.86 + statusArea = null;
74.87 + textArea = null;
74.88 + }
74.89 +
74.90 + @JavaScriptBody(args = { "test", "c", "arr" }, body =
74.91 + "var ul = window.document.getElementById('bck2brwsr.result');\n"
74.92 + + "var li = window.document.createElement('li');\n"
74.93 + + "var span = window.document.createElement('span');"
74.94 + + "span.innerHTML = test + ' - ';\n"
74.95 + + "var details = window.document.createElement('a');\n"
74.96 + + "details.innerHTML = 'Details';\n"
74.97 + + "details.href = '#';\n"
74.98 + + "var p = window.document.createElement('p');\n"
74.99 + + "var status = window.document.createElement('a');\n"
74.100 + + "status.innerHTML = 'running';"
74.101 + + "details.onclick = function() { li.appendChild(p); li.removeChild(details); status.innerHTML = 'Run Again'; status.href = '#'; };\n"
74.102 + + "status.onclick = function() { c.again__V_3Ljava_lang_Object_2(arr); }\n"
74.103 + + "var pre = window.document.createElement('textarea');\n"
74.104 + + "pre.cols = 100;"
74.105 + + "pre.rows = 10;"
74.106 + + "li.appendChild(span);\n"
74.107 + + "li.appendChild(status);\n"
74.108 + + "var span = window.document.createElement('span');"
74.109 + + "span.innerHTML = ' ';\n"
74.110 + + "li.appendChild(span);\n"
74.111 + + "li.appendChild(details);\n"
74.112 + + "p.appendChild(pre);\n"
74.113 + + "ul.appendChild(li);\n"
74.114 + + "arr[0] = pre;\n"
74.115 + + "arr[1] = status;\n"
74.116 + )
74.117 + private static native void beginTest(String test, Case c, Object[] arr);
74.118 +
74.119 + @JavaScriptBody(args = { "url", "callback", "arr" }, body = ""
74.120 + + "var request = new XMLHttpRequest();\n"
74.121 + + "request.open('GET', url, true);\n"
74.122 + + "request.setRequestHeader('Content-Type', 'text/plain; charset=utf-8');\n"
74.123 + + "request.onreadystatechange = function() {\n"
74.124 + + " if (this.readyState!==4) return;\n"
74.125 + + " arr[0] = this.responseText;\n"
74.126 + + " callback.run__V();\n"
74.127 + + "};"
74.128 + + "request.send();"
74.129 + )
74.130 + private static native void loadText(String url, Runnable callback, String[] arr) throws IOException;
74.131 +
74.132 + public static void harness(String url) throws IOException {
74.133 + log("Connecting to " + url);
74.134 + Request r = new Request(url);
74.135 + }
74.136 +
74.137 + private static class Request implements Runnable {
74.138 + private final String[] arr = { null };
74.139 + private final String url;
74.140 + private Case c;
74.141 + private int retries;
74.142 +
74.143 + private Request(String url) throws IOException {
74.144 + this.url = url;
74.145 + loadText(url, this, arr);
74.146 + }
74.147 + private Request(String url, String u) throws IOException {
74.148 + this.url = url;
74.149 + loadText(u, this, arr);
74.150 + }
74.151 +
74.152 + @Override
74.153 + public void run() {
74.154 + try {
74.155 + if (c == null) {
74.156 + String data = arr[0];
74.157 +
74.158 + if (data == null) {
74.159 + log("Some error exiting");
74.160 + closeWindow();
74.161 + return;
74.162 + }
74.163 +
74.164 + if (data.isEmpty()) {
74.165 + log("No data, exiting");
74.166 + closeWindow();
74.167 + return;
74.168 + }
74.169 +
74.170 + c = Case.parseData(data);
74.171 + beginTest(c);
74.172 + log("Got \"" + data + "\"");
74.173 + } else {
74.174 + log("Processing \"" + arr[0] + "\" for " + retries + " time");
74.175 + }
74.176 + Object result = retries++ >= 10 ? "java.lang.InterruptedException:timeout" : c.runTest();
74.177 + finishTest(c, result);
74.178 +
74.179 + String u = url + "?request=" + c.getRequestId() + "&result=" + result;
74.180 + new Request(url, u);
74.181 + } catch (Exception ex) {
74.182 + if (ex instanceof InterruptedException) {
74.183 + log("Re-scheduling in 100ms");
74.184 + schedule(this, 100);
74.185 + return;
74.186 + }
74.187 + log(ex.getClass().getName() + ":" + ex.getMessage());
74.188 + }
74.189 + }
74.190 + }
74.191 +
74.192 + private static String encodeURL(String r) throws UnsupportedEncodingException {
74.193 + final String SPECIAL = "%$&+,/:;=?@";
74.194 + StringBuilder sb = new StringBuilder();
74.195 + byte[] utf8 = r.getBytes("UTF-8");
74.196 + for (int i = 0; i < utf8.length; i++) {
74.197 + int ch = utf8[i] & 0xff;
74.198 + if (ch < 32 || ch > 127 || SPECIAL.indexOf(ch) >= 0) {
74.199 + final String numbers = "0" + Integer.toHexString(ch);
74.200 + sb.append("%").append(numbers.substring(numbers.length() - 2));
74.201 + } else {
74.202 + if (ch == 32) {
74.203 + sb.append("+");
74.204 + } else {
74.205 + sb.append((char)ch);
74.206 + }
74.207 + }
74.208 + }
74.209 + return sb.toString();
74.210 + }
74.211 +
74.212 + static String invoke(String clazz, String method) throws
74.213 + ClassNotFoundException, InvocationTargetException, IllegalAccessException,
74.214 + InstantiationException, InterruptedException {
74.215 + final Object r = new Case(null).invokeMethod(clazz, method);
74.216 + return r == null ? "null" : r.toString().toString();
74.217 + }
74.218 +
74.219 + /** Helper method that inspects the classpath and loads given resource
74.220 + * (usually a class file). Used while running tests in Rhino.
74.221 + *
74.222 + * @param name resource name to find
74.223 + * @return the array of bytes in the given resource
74.224 + * @throws IOException I/O in case something goes wrong
74.225 + */
74.226 + public static byte[] read(String name) throws IOException {
74.227 + URL u = null;
74.228 + Enumeration<URL> en = Console.class.getClassLoader().getResources(name);
74.229 + while (en.hasMoreElements()) {
74.230 + u = en.nextElement();
74.231 + }
74.232 + if (u == null) {
74.233 + throw new IOException("Can't find " + name);
74.234 + }
74.235 + try (InputStream is = u.openStream()) {
74.236 + byte[] arr;
74.237 + arr = new byte[is.available()];
74.238 + int offset = 0;
74.239 + while (offset < arr.length) {
74.240 + int len = is.read(arr, offset, arr.length - offset);
74.241 + if (len == -1) {
74.242 + throw new IOException("Can't read " + name);
74.243 + }
74.244 + offset += len;
74.245 + }
74.246 + return arr;
74.247 + }
74.248 + }
74.249 +
74.250 + @JavaScriptBody(args = {}, body = "vm.desiredAssertionStatus = true;")
74.251 + private static void turnAssetionStatusOn() {
74.252 + }
74.253 +
74.254 + @JavaScriptBody(args = {"r", "time"}, body =
74.255 + "return window.setTimeout(function() { r.run__V(); }, time);")
74.256 + private static native Object schedule(Runnable r, int time);
74.257 +
74.258 + private static final class Case {
74.259 + private final Object data;
74.260 + private Object inst;
74.261 +
74.262 + private Case(Object data) {
74.263 + this.data = data;
74.264 + }
74.265 +
74.266 + public static Case parseData(String s) {
74.267 + return new Case(toJSON(s));
74.268 + }
74.269 +
74.270 + public String getMethodName() {
74.271 + return value("methodName", data);
74.272 + }
74.273 +
74.274 + public String getClassName() {
74.275 + return value("className", data);
74.276 + }
74.277 +
74.278 + public String getRequestId() {
74.279 + return value("request", data);
74.280 + }
74.281 +
74.282 + public String getHtmlFragment() {
74.283 + return value("html", data);
74.284 + }
74.285 +
74.286 + void again(Object[] arr) {
74.287 + try {
74.288 + textArea = arr[0];
74.289 + statusArea = arr[1];
74.290 + setAttr(textArea, "value", "");
74.291 + runTest();
74.292 + } catch (Exception ex) {
74.293 + log(ex.getClass().getName() + ":" + ex.getMessage());
74.294 + }
74.295 + }
74.296 +
74.297 + private Object runTest() throws IllegalAccessException,
74.298 + IllegalArgumentException, ClassNotFoundException, UnsupportedEncodingException,
74.299 + InvocationTargetException, InstantiationException, InterruptedException {
74.300 + if (this.getHtmlFragment() != null) {
74.301 + setAttr("bck2brwsr.fragment", "innerHTML", this.getHtmlFragment());
74.302 + }
74.303 + log("Invoking " + this.getClassName() + '.' + this.getMethodName() + " as request: " + this.getRequestId());
74.304 + Object result = invokeMethod(this.getClassName(), this.getMethodName());
74.305 + setAttr("bck2brwsr.fragment", "innerHTML", "");
74.306 + log("Result: " + result);
74.307 + result = encodeURL("" + result);
74.308 + log("Sending back: ...?request=" + this.getRequestId() + "&result=" + result);
74.309 + return result;
74.310 + }
74.311 +
74.312 + private Object invokeMethod(String clazz, String method)
74.313 + throws ClassNotFoundException, InvocationTargetException,
74.314 + InterruptedException, IllegalAccessException, IllegalArgumentException,
74.315 + InstantiationException {
74.316 + Method found = null;
74.317 + Class<?> c = Class.forName(clazz);
74.318 + for (Method m : c.getMethods()) {
74.319 + if (m.getName().equals(method)) {
74.320 + found = m;
74.321 + }
74.322 + }
74.323 + Object res;
74.324 + if (found != null) {
74.325 + try {
74.326 + if ((found.getModifiers() & Modifier.STATIC) != 0) {
74.327 + res = found.invoke(null);
74.328 + } else {
74.329 + if (inst == null) {
74.330 + inst = c.newInstance();
74.331 + }
74.332 + res = found.invoke(inst);
74.333 + }
74.334 + } catch (Throwable ex) {
74.335 + if (ex instanceof InvocationTargetException) {
74.336 + ex = ((InvocationTargetException) ex).getTargetException();
74.337 + }
74.338 + if (ex instanceof InterruptedException) {
74.339 + throw (InterruptedException)ex;
74.340 + }
74.341 + res = ex.getClass().getName() + ":" + ex.getMessage();
74.342 + }
74.343 + } else {
74.344 + res = "Can't find method " + method + " in " + clazz;
74.345 + }
74.346 + return res;
74.347 + }
74.348 +
74.349 + @JavaScriptBody(args = "s", body = "return eval('(' + s + ')');")
74.350 + private static native Object toJSON(String s);
74.351 +
74.352 + @JavaScriptBody(args = {"p", "d"}, body =
74.353 + "var v = d[p];\n"
74.354 + + "if (typeof v === 'undefined') return null;\n"
74.355 + + "return v.toString();"
74.356 + )
74.357 + private static native String value(String p, Object d);
74.358 + }
74.359 +}
75.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
75.2 +++ b/launcher/http/src/main/resources/org/apidesign/bck2brwsr/launcher/harness.xhtml Thu May 02 09:18:22 2013 +0200
75.3 @@ -0,0 +1,43 @@
75.4 +<?xml version="1.0" encoding="UTF-8"?>
75.5 +<!--
75.6 +
75.7 + Back 2 Browser Bytecode Translator
75.8 + Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
75.9 +
75.10 + This program is free software: you can redistribute it and/or modify
75.11 + it under the terms of the GNU General Public License as published by
75.12 + the Free Software Foundation, version 2 of the License.
75.13 +
75.14 + This program is distributed in the hope that it will be useful,
75.15 + but WITHOUT ANY WARRANTY; without even the implied warranty of
75.16 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
75.17 + GNU General Public License for more details.
75.18 +
75.19 + You should have received a copy of the GNU General Public License
75.20 + along with this program. Look for COPYING file in the top folder.
75.21 + If not, see http://opensource.org/licenses/GPL-2.0.
75.22 +
75.23 +-->
75.24 +<!DOCTYPE html>
75.25 +<html xmlns="http://www.w3.org/1999/xhtml">
75.26 + <head>
75.27 + <title>Bck2Brwsr Harness</title>
75.28 + </head>
75.29 + <body>
75.30 + <script src="/bck2brwsr.js"></script>
75.31 + <script>
75.32 + var vm = bck2brwsr();
75.33 + </script>
75.34 +
75.35 + <h1>Bck2Brwsr Execution Harness</h1>
75.36 +
75.37 + <ul id="bck2brwsr.result" style="width: 100%;" >
75.38 + </ul>
75.39 +
75.40 + <div id="bck2brwsr.fragment"/>
75.41 +
75.42 + <script type="text/javascript">
75.43 + vm.loadClass('org.apidesign.bck2brwsr.launcher.impl.Console').harness__VLjava_lang_String_2('$U/../data');
75.44 + </script>
75.45 + </body>
75.46 +</html>
76.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
76.2 +++ b/launcher/pom.xml Thu May 02 09:18:22 2013 +0200
76.3 @@ -0,0 +1,19 @@
76.4 +<?xml version="1.0" encoding="UTF-8"?>
76.5 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
76.6 + <modelVersion>4.0.0</modelVersion>
76.7 + <parent>
76.8 + <artifactId>bck2brwsr</artifactId>
76.9 + <groupId>org.apidesign</groupId>
76.10 + <version>0.8-SNAPSHOT</version>
76.11 + </parent>
76.12 + <groupId>org.apidesign.bck2brwsr</groupId>
76.13 + <artifactId>launcher-pom</artifactId>
76.14 + <version>0.8-SNAPSHOT</version>
76.15 + <packaging>pom</packaging>
76.16 + <name>Launchers</name>
76.17 + <modules>
76.18 + <module>api</module>
76.19 + <module>http</module>
76.20 + <module>fx</module>
76.21 + </modules>
76.22 +</project>
76.23 \ No newline at end of file
77.1 --- a/pom.xml Tue Apr 02 15:40:51 2013 +0200
77.2 +++ b/pom.xml Thu May 02 09:18:22 2013 +0200
77.3 @@ -3,7 +3,7 @@
77.4 <modelVersion>4.0.0</modelVersion>
77.5 <groupId>org.apidesign</groupId>
77.6 <artifactId>bck2brwsr</artifactId>
77.7 - <version>0.5-SNAPSHOT</version>
77.8 + <version>0.8-SNAPSHOT</version>
77.9 <packaging>pom</packaging>
77.10 <name>Back 2 Browser</name>
77.11 <parent>
77.12 @@ -11,11 +11,17 @@
77.13 <artifactId>jvnet-parent</artifactId>
77.14 <version>3</version>
77.15 </parent>
77.16 + <properties>
77.17 + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
77.18 + <netbeans.version>RELEASE73</netbeans.version>
77.19 + <license>COPYING</license>
77.20 + </properties>
77.21 <modules>
77.22 <module>dew</module>
77.23 <module>javaquery</module>
77.24 <module>benchmarks</module>
77.25 <module>ide</module>
77.26 + <module>launcher</module>
77.27 <module>rt</module>
77.28 </modules>
77.29 <licenses>
77.30 @@ -80,21 +86,24 @@
77.31 <exclude>.*/**</exclude>
77.32 <exclude>rt/emul/*/src/main/**</exclude>
77.33 <exclude>rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeParser.java</exclude>
77.34 - <exclude>rt/mojo/src/main/resources/archetype-resources/**</exclude>
77.35 - <exclude>rt/vmtest/src/test/resources/**</exclude>
77.36 + <exclude>rt/archetype/src/main/resources/archetype-resources/**</exclude>
77.37 + <exclude>rt/emul/compact/src/test/resources/**</exclude>
77.38 <exclude>dew/src/main/resources/org/apidesign/bck2brwsr/dew/**</exclude>
77.39 <exclude>javaquery/api/src/main/resources/org/apidesign/bck2brwsr/htmlpage/knockout*.js</exclude>
77.40 </excludes>
77.41 </configuration>
77.42 </plugin>
77.43 - <plugin>
77.44 - <groupId>org.apache.maven.plugins</groupId>
77.45 - <artifactId>maven-release-plugin</artifactId>
77.46 - <version>2.4</version>
77.47 - <configuration>
77.48 - <tag>release-${releaseVersion}</tag>
77.49 - </configuration>
77.50 - </plugin> </plugins>
77.51 + <plugin>
77.52 + <artifactId>maven-release-plugin</artifactId>
77.53 + <version>2.4</version>
77.54 + <configuration>
77.55 + <mavenExecutorId>forked-path</mavenExecutorId>
77.56 + <useReleaseProfile>false</useReleaseProfile>
77.57 + <arguments>-Pjvnet-release -Pgpg</arguments>
77.58 + <tag>release-${releaseVersion}</tag>
77.59 + </configuration>
77.60 + </plugin>
77.61 + </plugins>
77.62 <pluginManagement>
77.63 <plugins>
77.64 <plugin>
77.65 @@ -139,26 +148,120 @@
77.66 <dependency>
77.67 <groupId>org.netbeans.api</groupId>
77.68 <artifactId>org-netbeans-modules-classfile</artifactId>
77.69 - <version>RELEASE73</version>
77.70 + <version>${netbeans.version}</version>
77.71 <type>jar</type>
77.72 </dependency>
77.73 <dependency>
77.74 <groupId>org.netbeans.api</groupId>
77.75 <artifactId>org-openide-util-lookup</artifactId>
77.76 - <version>RELEASE73</version>
77.77 + <version>${netbeans.version}</version>
77.78 <scope>compile</scope>
77.79 <type>jar</type>
77.80 </dependency>
77.81 <dependency>
77.82 + <groupId>org.netbeans.api</groupId>
77.83 + <artifactId>org-netbeans-api-annotations-common</artifactId>
77.84 + <version>${netbeans.version}</version>
77.85 + </dependency>
77.86 + <dependency>
77.87 + <groupId>org.netbeans.api</groupId>
77.88 + <artifactId>org-netbeans-modules-java-source</artifactId>
77.89 + <version>${netbeans.version}</version>
77.90 + </dependency>
77.91 + <dependency>
77.92 + <groupId>org.netbeans.api</groupId>
77.93 + <artifactId>org-netbeans-libs-javacapi</artifactId>
77.94 + <version>${netbeans.version}</version>
77.95 + </dependency>
77.96 + <dependency>
77.97 + <groupId>org.netbeans.api</groupId>
77.98 + <artifactId>org-netbeans-spi-java-hints</artifactId>
77.99 + <version>${netbeans.version}</version>
77.100 + </dependency>
77.101 + <dependency>
77.102 + <groupId>org.netbeans.api</groupId>
77.103 + <artifactId>org-netbeans-modules-parsing-api</artifactId>
77.104 + <version>${netbeans.version}</version>
77.105 + </dependency>
77.106 + <dependency>
77.107 + <groupId>org.netbeans.api</groupId>
77.108 + <artifactId>org-netbeans-spi-editor-hints</artifactId>
77.109 + <version>${netbeans.version}</version>
77.110 + </dependency>
77.111 + <dependency>
77.112 + <groupId>org.netbeans.api</groupId>
77.113 + <artifactId>org-openide-util</artifactId>
77.114 + <version>${netbeans.version}</version>
77.115 + </dependency>
77.116 + <dependency>
77.117 + <groupId>org.netbeans.api</groupId>
77.118 + <artifactId>org-netbeans-modules-java-lexer</artifactId>
77.119 + <version>${netbeans.version}</version>
77.120 + </dependency>
77.121 + <dependency>
77.122 + <groupId>org.netbeans.api</groupId>
77.123 + <artifactId>org-netbeans-modules-lexer</artifactId>
77.124 + <version>${netbeans.version}</version>
77.125 + </dependency>
77.126 + <dependency>
77.127 + <groupId>org.netbeans.api</groupId>
77.128 + <artifactId>org-netbeans-modules-java-hints-test</artifactId>
77.129 + <version>${netbeans.version}</version>
77.130 + </dependency>
77.131 + <dependency>
77.132 + <groupId>org.netbeans.api</groupId>
77.133 + <artifactId>org-netbeans-libs-junit4</artifactId>
77.134 + <version>${netbeans.version}</version>
77.135 + </dependency>
77.136 + <dependency>
77.137 + <groupId>org.netbeans.modules</groupId>
77.138 + <artifactId>org-netbeans-lib-nbjavac</artifactId>
77.139 + <version>${netbeans.version}</version>
77.140 + </dependency>
77.141 + <dependency>
77.142 + <groupId>org.netbeans.modules</groupId>
77.143 + <artifactId>org-netbeans-modules-web-browser-api</artifactId>
77.144 + <version>${netbeans.version}</version>
77.145 + <exclusions>
77.146 + <exclusion>
77.147 + <artifactId>org-netbeans-core</artifactId>
77.148 + <groupId>org.netbeans.modules</groupId>
77.149 + </exclusion>
77.150 + <exclusion>
77.151 + <artifactId>org-netbeans-core-multiview</artifactId>
77.152 + <groupId>org.netbeans.api</groupId>
77.153 + </exclusion>
77.154 + <exclusion>
77.155 + <artifactId>org-netbeans-libs-lucene</artifactId>
77.156 + <groupId>org.netbeans.api</groupId>
77.157 + </exclusion>
77.158 + <exclusion>
77.159 + <artifactId>org-netbeans-modules-diff</artifactId>
77.160 + <groupId>org.netbeans.api</groupId>
77.161 + </exclusion>
77.162 + <exclusion>
77.163 + <artifactId>org-netbeans-modules-editor-fold</artifactId>
77.164 + <groupId>org.netbeans.api</groupId>
77.165 + </exclusion>
77.166 + <exclusion>
77.167 + <artifactId>org-netbeans-modules-editor-guards</artifactId>
77.168 + <groupId>org.netbeans.api</groupId>
77.169 + </exclusion>
77.170 + </exclusions>
77.171 + </dependency>
77.172 + <dependency>
77.173 + <artifactId>org-netbeans-modules-projectapi</artifactId>
77.174 + <groupId>org.netbeans.api</groupId>
77.175 + <type>jar</type>
77.176 + <version>${netbeans.version}</version>
77.177 + </dependency>
77.178 + <dependency>
77.179 <groupId>org.netbeans.modules</groupId>
77.180 <artifactId>org-netbeans-modules-html-parser</artifactId>
77.181 - <version>RELEASE73</version>
77.182 + <version>${netbeans.version}</version>
77.183 <scope>compile</scope>
77.184 <type>jar</type>
77.185 </dependency>
77.186 </dependencies>
77.187 </dependencyManagement>
77.188 - <properties>
77.189 - <license>COPYING</license>
77.190 - </properties>
77.191 -</project>
77.192 \ No newline at end of file
77.193 +</project>
78.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
78.2 +++ b/rt/archetype/pom.xml Thu May 02 09:18:22 2013 +0200
78.3 @@ -0,0 +1,62 @@
78.4 +<?xml version="1.0" encoding="UTF-8"?>
78.5 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
78.6 + <modelVersion>4.0.0</modelVersion>
78.7 + <parent>
78.8 + <artifactId>rt</artifactId>
78.9 + <groupId>org.apidesign.bck2brwsr</groupId>
78.10 + <version>0.8-SNAPSHOT</version>
78.11 + </parent>
78.12 + <groupId>org.apidesign.bck2brwsr</groupId>
78.13 + <artifactId>bck2brwsr-archetype-html-sample</artifactId>
78.14 + <version>0.8-SNAPSHOT</version>
78.15 + <packaging>jar</packaging>
78.16 + <name>Bck2Brwsr Maven Archetype</name>
78.17 + <description>
78.18 + Creates a skeletal HTML page and associated Java controller class.
78.19 + Runs in any browser (even without Java plugin) with the help of Bck2Brwsr
78.20 + virtual machine.
78.21 + </description>
78.22 + <build>
78.23 + <plugins>
78.24 + <plugin>
78.25 + <groupId>org.apache.maven.plugins</groupId>
78.26 + <artifactId>maven-compiler-plugin</artifactId>
78.27 + <version>2.3.2</version>
78.28 + <configuration>
78.29 + <source>1.6</source>
78.30 + <target>1.6</target>
78.31 + </configuration>
78.32 + </plugin>
78.33 + <plugin>
78.34 + <groupId>org.apache.maven.plugins</groupId>
78.35 + <artifactId>maven-surefire-plugin</artifactId>
78.36 + <configuration>
78.37 + <skipTests>true</skipTests>
78.38 + </configuration>
78.39 + <executions>
78.40 + <execution>
78.41 + <id>test</id>
78.42 + <goals>
78.43 + <goal>test</goal>
78.44 + </goals>
78.45 + <phase>integration-test</phase>
78.46 + <configuration>
78.47 + <additionalClasspathElements>
78.48 + <additionalClasspathElement>${project.build.directory}/bck2brwsr-archetype-html-sample-${project.version}.jar</additionalClasspathElement>
78.49 + </additionalClasspathElements>
78.50 + <skipTests>false</skipTests>
78.51 + </configuration>
78.52 + </execution>
78.53 +
78.54 + </executions>
78.55 + </plugin>
78.56 + </plugins>
78.57 + </build>
78.58 + <dependencies>
78.59 + <dependency>
78.60 + <groupId>org.testng</groupId>
78.61 + <artifactId>testng</artifactId>
78.62 + <scope>test</scope>
78.63 + </dependency>
78.64 + </dependencies>
78.65 +</project>
79.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
79.2 +++ b/rt/archetype/src/main/java/org/apidesign/bck2brwsr/archetype/package-info.java Thu May 02 09:18:22 2013 +0200
79.3 @@ -0,0 +1,18 @@
79.4 +/**
79.5 + * Back 2 Browser Bytecode Translator
79.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
79.7 + *
79.8 + * This program is free software: you can redistribute it and/or modify
79.9 + * it under the terms of the GNU General Public License as published by
79.10 + * the Free Software Foundation, version 2 of the License.
79.11 + *
79.12 + * This program is distributed in the hope that it will be useful,
79.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
79.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
79.15 + * GNU General Public License for more details.
79.16 + *
79.17 + * You should have received a copy of the GNU General Public License
79.18 + * along with this program. Look for COPYING file in the top folder.
79.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
79.20 + */
79.21 +package org.apidesign.bck2brwsr.archetype;
80.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
80.2 +++ b/rt/archetype/src/main/resources/META-INF/maven/archetype-metadata.xml Thu May 02 09:18:22 2013 +0200
80.3 @@ -0,0 +1,55 @@
80.4 +<?xml version="1.0" encoding="UTF-8"?>
80.5 +<!--
80.6 +
80.7 + Back 2 Browser Bytecode Translator
80.8 + Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
80.9 +
80.10 + This program is free software: you can redistribute it and/or modify
80.11 + it under the terms of the GNU General Public License as published by
80.12 + the Free Software Foundation, version 2 of the License.
80.13 +
80.14 + This program is distributed in the hope that it will be useful,
80.15 + but WITHOUT ANY WARRANTY; without even the implied warranty of
80.16 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
80.17 + GNU General Public License for more details.
80.18 +
80.19 + You should have received a copy of the GNU General Public License
80.20 + along with this program. Look for COPYING file in the top folder.
80.21 + If not, see http://opensource.org/licenses/GPL-2.0.
80.22 +
80.23 +-->
80.24 +<archetype-descriptor name="Get Java Bck2Brwsr!">
80.25 + <fileSets>
80.26 + <fileSet filtered="true" packaged="true">
80.27 + <directory>src/main/java</directory>
80.28 + <includes>
80.29 + <include>**/App.java</include>
80.30 + </includes>
80.31 + </fileSet>
80.32 + <fileSet filtered="true" packaged="true">
80.33 + <directory>src/main/resources</directory>
80.34 + <includes>
80.35 + <include>**/*.xhtml</include>
80.36 + <include>**/*.html</include>
80.37 + </includes>
80.38 + </fileSet>
80.39 + <fileSet filtered="true" packaged="true">
80.40 + <directory>src/test/java</directory>
80.41 + <includes>
80.42 + <include>**/*Test.java</include>
80.43 + </includes>
80.44 + </fileSet>
80.45 + <fileSet filtered="false" packaged="false">
80.46 + <directory></directory>
80.47 + <includes>
80.48 + <include>nbactions.xml</include>
80.49 + </includes>
80.50 + </fileSet>
80.51 + <fileSet filtered="true" packaged="false">
80.52 + <directory></directory>
80.53 + <includes>
80.54 + <include>bck2brwsr-assembly.xml</include>
80.55 + </includes>
80.56 + </fileSet>
80.57 + </fileSets>
80.58 +</archetype-descriptor>
80.59 \ No newline at end of file
81.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
81.2 +++ b/rt/archetype/src/main/resources/archetype-resources/bck2brwsr-assembly.xml Thu May 02 09:18:22 2013 +0200
81.3 @@ -0,0 +1,61 @@
81.4 +<?xml version="1.0"?>
81.5 +<!--
81.6 +
81.7 + Back 2 Browser Bytecode Translator
81.8 + Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
81.9 +
81.10 + This program is free software: you can redistribute it and/or modify
81.11 + it under the terms of the GNU General Public License as published by
81.12 + the Free Software Foundation, version 2 of the License.
81.13 +
81.14 + This program is distributed in the hope that it will be useful,
81.15 + but WITHOUT ANY WARRANTY; without even the implied warranty of
81.16 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
81.17 + GNU General Public License for more details.
81.18 +
81.19 + You should have received a copy of the GNU General Public License
81.20 + along with this program. Look for COPYING file in the top folder.
81.21 + If not, see http://opensource.org/licenses/GPL-2.0.
81.22 +
81.23 +-->
81.24 +<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
81.25 + xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
81.26 +
81.27 + <id>bck2brwsr</id>
81.28 + <formats>
81.29 + <format>zip</format>
81.30 + </formats>
81.31 + <baseDirectory>public_html</baseDirectory>
81.32 + <dependencySets>
81.33 + <dependencySet>
81.34 + <useProjectArtifact>false</useProjectArtifact>
81.35 + <scope>runtime</scope>
81.36 + <outputDirectory>lib</outputDirectory>
81.37 + <includes>
81.38 + <include>*:jar</include>
81.39 + <include>*:rt</include>
81.40 + </includes>
81.41 + </dependencySet>
81.42 + <dependencySet>
81.43 + <useProjectArtifact>false</useProjectArtifact>
81.44 + <scope>provided</scope>
81.45 + <includes>
81.46 + <include>*:js</include>
81.47 + </includes>
81.48 + <unpack>true</unpack>
81.49 + <outputDirectory>/</outputDirectory>
81.50 + </dependencySet>
81.51 + </dependencySets>
81.52 + <files>
81.53 + <file>
81.54 + <source>${project.build.directory}/${project.build.finalName}.jar</source>
81.55 + <outputDirectory>/</outputDirectory>
81.56 + </file>
81.57 + <file>
81.58 + <source>${project.build.directory}/classes/${package.replace('.','/')}/index.html</source>
81.59 + <outputDirectory>/</outputDirectory>
81.60 + <destName>index.html</destName>
81.61 + </file>
81.62 + </files>
81.63 +
81.64 +</assembly>
81.65 \ No newline at end of file
82.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
82.2 +++ b/rt/archetype/src/main/resources/archetype-resources/nbactions.xml Thu May 02 09:18:22 2013 +0200
82.3 @@ -0,0 +1,10 @@
82.4 +<?xml version="1.0" encoding="UTF-8"?>
82.5 +<actions>
82.6 + <action>
82.7 + <actionName>run</actionName>
82.8 + <goals>
82.9 + <goal>process-classes</goal>
82.10 + <goal>bck2brwsr:brwsr</goal>
82.11 + </goals>
82.12 + </action>
82.13 +</actions>
83.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
83.2 +++ b/rt/archetype/src/main/resources/archetype-resources/pom.xml Thu May 02 09:18:22 2013 +0200
83.3 @@ -0,0 +1,135 @@
83.4 +<?xml version="1.0"?>
83.5 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
83.6 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
83.7 + <modelVersion>4.0.0</modelVersion>
83.8 +
83.9 + <groupId>${groupId}</groupId>
83.10 + <artifactId>${artifactId}</artifactId>
83.11 + <version>${version}</version>
83.12 + <packaging>jar</packaging>
83.13 +
83.14 + <name>${artifactId}</name>
83.15 +
83.16 + <repositories>
83.17 + <repository>
83.18 + <id>java.net</id>
83.19 + <name>Java.net</name>
83.20 + <url>https://maven.java.net/content/repositories/releases/</url>
83.21 + <snapshots>
83.22 + <enabled>true</enabled>
83.23 + </snapshots>
83.24 + </repository>
83.25 + <repository>
83.26 + <id>netbeans</id>
83.27 + <name>NetBeans</name>
83.28 + <url>http://bits.netbeans.org/maven2/</url>
83.29 + </repository>
83.30 + </repositories>
83.31 + <pluginRepositories>
83.32 + <pluginRepository>
83.33 + <id>java.net</id>
83.34 + <name>Java.net</name>
83.35 + <url>https://maven.java.net/content/repositories/releases/</url>
83.36 + <snapshots>
83.37 + <enabled>true</enabled>
83.38 + </snapshots>
83.39 + </pluginRepository>
83.40 + </pluginRepositories>
83.41 +
83.42 + <properties>
83.43 + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
83.44 + </properties>
83.45 + <build>
83.46 + <plugins>
83.47 + <plugin>
83.48 + <groupId>org.apidesign.bck2brwsr</groupId>
83.49 + <artifactId>bck2brwsr-maven-plugin</artifactId>
83.50 + <version>0.8-SNAPSHOT</version>
83.51 + <executions>
83.52 + <execution>
83.53 + <goals>
83.54 + <goal>brwsr</goal>
83.55 + </goals>
83.56 + </execution>
83.57 + </executions>
83.58 + <configuration>
83.59 + <startpage>${package.replace('.','/')}/index.html</startpage>
83.60 + </configuration>
83.61 + </plugin>
83.62 + <plugin>
83.63 + <groupId>org.apache.maven.plugins</groupId>
83.64 + <artifactId>maven-compiler-plugin</artifactId>
83.65 + <version>2.3.2</version>
83.66 + <configuration>
83.67 + <source>1.7</source>
83.68 + <target>1.7</target>
83.69 + </configuration>
83.70 + </plugin>
83.71 + <plugin>
83.72 + <groupId>org.apache.maven.plugins</groupId>
83.73 + <artifactId>maven-jar-plugin</artifactId>
83.74 + <version>2.4</version>
83.75 + <configuration>
83.76 + <archive>
83.77 + <manifest>
83.78 + <addClasspath>true</addClasspath>
83.79 + <classpathPrefix>lib/</classpathPrefix>
83.80 + </manifest>
83.81 + </archive>
83.82 + </configuration>
83.83 + </plugin>
83.84 + <plugin>
83.85 + <artifactId>maven-assembly-plugin</artifactId>
83.86 + <version>2.4</version>
83.87 + <executions>
83.88 + <execution>
83.89 + <id>distro-assembly</id>
83.90 + <phase>package</phase>
83.91 + <goals>
83.92 + <goal>single</goal>
83.93 + </goals>
83.94 + <configuration>
83.95 + <descriptors>
83.96 + <descriptor>bck2brwsr-assembly.xml</descriptor>
83.97 + </descriptors>
83.98 + </configuration>
83.99 + </execution>
83.100 + </executions>
83.101 + </plugin>
83.102 + </plugins>
83.103 + </build>
83.104 +
83.105 + <dependencies>
83.106 + <dependency>
83.107 + <groupId>org.apidesign.bck2brwsr</groupId>
83.108 + <artifactId>emul</artifactId>
83.109 + <version>0.8-SNAPSHOT</version>
83.110 + <classifier>rt</classifier>
83.111 + </dependency>
83.112 + <dependency>
83.113 + <groupId>org.apidesign.bck2brwsr</groupId>
83.114 + <artifactId>javaquery.api</artifactId>
83.115 + <version>0.8-SNAPSHOT</version>
83.116 + </dependency>
83.117 + <dependency>
83.118 + <groupId>org.testng</groupId>
83.119 + <artifactId>testng</artifactId>
83.120 + <version>6.5.2</version>
83.121 + <scope>test</scope>
83.122 + </dependency>
83.123 + <dependency>
83.124 + <groupId>org.apidesign.bck2brwsr</groupId>
83.125 + <artifactId>vm4brwsr</artifactId>
83.126 + <classifier>js</classifier>
83.127 + <type>zip</type>
83.128 + <version>0.8-SNAPSHOT</version>
83.129 + <scope>provided</scope>
83.130 + </dependency>
83.131 + <dependency>
83.132 + <groupId>org.apidesign.bck2brwsr</groupId>
83.133 + <artifactId>vmtest</artifactId>
83.134 + <version>0.8-SNAPSHOT</version>
83.135 + <scope>test</scope>
83.136 + </dependency>
83.137 + </dependencies>
83.138 +</project>
84.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
84.2 +++ b/rt/archetype/src/main/resources/archetype-resources/src/main/java/App.java Thu May 02 09:18:22 2013 +0200
84.3 @@ -0,0 +1,88 @@
84.4 +package ${package};
84.5 +
84.6 +import java.util.List;
84.7 +import org.apidesign.bck2brwsr.htmlpage.api.*;
84.8 +import static org.apidesign.bck2brwsr.htmlpage.api.OnEvent.*;
84.9 +import org.apidesign.bck2brwsr.htmlpage.api.Page;
84.10 +import org.apidesign.bck2brwsr.htmlpage.api.Property;
84.11 +import org.apidesign.bck2brwsr.htmlpage.api.ComputedProperty;
84.12 +
84.13 +/** This is the controller class for associated index.html page. The <code>Index</code>
84.14 + * is autogenerated by parsing the index.html page. It fields represent individual
84.15 + * elements annotated by "id" in the page.
84.16 + */
84.17 +@Page(xhtml="index.html", className="Index", properties={
84.18 + @Property(name="name", type=String.class),
84.19 + @Property(name="messages", type=String.class, array=true),
84.20 +})
84.21 +public class App {
84.22 + static {
84.23 + Index model = new Index();
84.24 + model.setName("World");
84.25 + model.applyBindings();
84.26 + }
84.27 +
84.28 + /**
84.29 + * @param m the model of the index page creates in static initializer
84.30 + */
84.31 + @On(event = CLICK, id="hello")
84.32 + static void hello(Index m) {
84.33 + display(m.getHelloMessage(), m);
84.34 + m.getMessages().add(m.getHelloMessage());
84.35 + }
84.36 +
84.37 + /** Reacts when mouse moves over the canvas.
84.38 + *
84.39 + * @param m the model of the page
84.40 + * @param x property "x" extracted from the event generated by the browser
84.41 + * @param y property "y" from the mouse event
84.42 + */
84.43 + @On(event = MOUSE_MOVE, id="canvas")
84.44 + static void clearPoint(Index m, int x, int y) {
84.45 + GraphicsContext g = m.canvas.getContext();
84.46 + boolean even = (x + y) % 2 == 0;
84.47 + if (even) {
84.48 + g.setFillStyle("blue");
84.49 + } else {
84.50 + g.setFillStyle("red");
84.51 + }
84.52 + g.clearRect(0, 0, 1000, 1000);
84.53 + g.setFont("italic 40px Calibri");
84.54 + g.fillText(m.getHelloMessage(), 10, 40);
84.55 + }
84.56 +
84.57 + /** Callback function called by the KnockOut/Java binding on elements
84.58 + * representing href's with individual messages being their data.
84.59 + *
84.60 + * @param data the data associated with the element
84.61 + * @param m the model of the page
84.62 + */
84.63 + @OnFunction
84.64 + static void display(String data, Index m) {
84.65 + GraphicsContext g = m.canvas.getContext();
84.66 + g.clearRect(0, 0, 1000, 1000);
84.67 + g.setFillStyle("black");
84.68 + g.setFont("italic 40px Calibri");
84.69 + g.fillText(data, 10, 40);
84.70 + }
84.71 +
84.72 + /** Callback function.
84.73 + *
84.74 + * @param data data associated with the actual element on the page
84.75 + * @param m the model of the page
84.76 + */
84.77 + @OnFunction
84.78 + static void remove(String data, Index m) {
84.79 + m.getMessages().remove(data);
84.80 + }
84.81 +
84.82 + @ComputedProperty
84.83 + static String helloMessage(String name) {
84.84 + return "Hello " + name + "!";
84.85 + }
84.86 +
84.87 + @ComputedProperty
84.88 + static boolean noMessages(List<String> messages) {
84.89 + return messages.isEmpty();
84.90 + }
84.91 +}
85.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
85.2 +++ b/rt/archetype/src/main/resources/archetype-resources/src/main/resources/index.html Thu May 02 09:18:22 2013 +0200
85.3 @@ -0,0 +1,31 @@
85.4 +<?xml version="1.0" encoding="UTF-8"?>
85.5 +<!DOCTYPE html>
85.6 +<html xmlns="http://www.w3.org/1999/xhtml">
85.7 + <head>
85.8 + <title>Bck2Brwsr's Hello World</title>
85.9 + </head>
85.10 + <body>
85.11 + <h1 data-bind="text: helloMessage">Loading Bck2Brwsr's Hello World...</h1>
85.12 + Your name: <input id='input' data-bind="value: name, valueUpdate: 'afterkeydown'"></input>
85.13 + <button id="hello">Say Hello!</button>
85.14 + <p>
85.15 + <canvas id="canvas" width="300" height="50">
85.16 + </canvas>
85.17 + </p>
85.18 +
85.19 +
85.20 + <div data-bind="if: noMessages">No message displayed yet.</div>
85.21 + <ul data-bind="foreach: messages">
85.22 + <li>
85.23 + <a href="#" data-bind="text: $data, click: $root.display"></a>
85.24 + (<a href="#" data-bind="click: $root.remove">delete</a>)
85.25 + </li>
85.26 + </ul>
85.27 +
85.28 + <script src="bck2brwsr.js"></script>
85.29 + <script type="text/javascript">
85.30 + var vm = bck2brwsr('${artifactId}-${version}.jar');
85.31 + vm.loadClass('${package}.App');
85.32 + </script>
85.33 + </body>
85.34 +</html>
86.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
86.2 +++ b/rt/archetype/src/main/resources/archetype-resources/src/test/java/AppTest.java Thu May 02 09:18:22 2013 +0200
86.3 @@ -0,0 +1,26 @@
86.4 +package ${package};
86.5 +
86.6 +import static org.testng.Assert.*;
86.7 +import org.testng.annotations.BeforeMethod;
86.8 +import org.testng.annotations.Test;
86.9 +
86.10 +/** Demonstrating POJO testing of HTML page model. Runs in good old HotSpot
86.11 + * as it does not reference any HTML elements or browser functionality. Just
86.12 + * operates on the page model.
86.13 + *
86.14 + * @author Jaroslav Tulach <jtulach@netbeans.org>
86.15 + */
86.16 +public class AppTest {
86.17 + private Index model;
86.18 +
86.19 +
86.20 + @BeforeMethod
86.21 + public void initModel() {
86.22 + model = new Index().applyBindings();
86.23 + }
86.24 +
86.25 + @Test public void testHelloMessage() {
86.26 + model.setName("Joe");
86.27 + assertEquals(model.getHelloMessage(), "Hello Joe!", "Cleared after pressing +");
86.28 + }
86.29 +}
87.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
87.2 +++ b/rt/archetype/src/main/resources/archetype-resources/src/test/java/InconsistencyTest.java Thu May 02 09:18:22 2013 +0200
87.3 @@ -0,0 +1,40 @@
87.4 +package ${package};
87.5 +
87.6 +import org.apidesign.bck2brwsr.vmtest.Compare;
87.7 +import org.apidesign.bck2brwsr.vmtest.VMTest;
87.8 +import org.testng.annotations.Factory;
87.9 +
87.10 +/** Bck2brwsr cares about compatibility with real Java. Whatever API is
87.11 + * supported by bck2brwsr, it needs to behave the same way as when running
87.12 + * in HotSpot VM.
87.13 + * <p>
87.14 + * There can be bugs, however. To help us fix them, we kindly ask you to
87.15 + * write an "inconsistency" test. A test that compares behavior of the API
87.16 + * between real VM and bck2brwsr VM. This class is skeleton of such test.
87.17 + *
87.18 + * @author Jaroslav Tulach <jtulach@netbeans.org>
87.19 + */
87.20 +public class InconsistencyTest {
87.21 + /** A method to demonstrate inconsistency between bck2brwsr and HotSpot.
87.22 + * Make calls to an API that behaves strangely, return some result at
87.23 + * the end. No need to use any <code>assert</code>.
87.24 + *
87.25 + * @return value to compare between HotSpot and bck2brwsr
87.26 + */
87.27 + @Compare
87.28 + public int checkStringHashCode() throws Exception {
87.29 + return "Is string hashCode the same?".hashCode();
87.30 + }
87.31 +
87.32 + /** Factory method that creates a three tests for each method annotated with
87.33 + * {@link org.apidesign.bck2brwsr.vmtest.Compare}. One executes the code in
87.34 + * HotSpot, one in Rhino and the last one compares the results.
87.35 + *
87.36 + * @see org.apidesign.bck2brwsr.vmtest.VMTest
87.37 + */
87.38 + @Factory
87.39 + public static Object[] create() {
87.40 + return VMTest.create(InconsistencyTest.class);
87.41 + }
87.42 +
87.43 +}
88.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
88.2 +++ b/rt/archetype/src/main/resources/archetype-resources/src/test/java/IntegrationTest.java Thu May 02 09:18:22 2013 +0200
88.3 @@ -0,0 +1,46 @@
88.4 +package ${package};
88.5 +
88.6 +import org.apidesign.bck2brwsr.htmlpage.api.OnEvent;
88.7 +import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
88.8 +import org.apidesign.bck2brwsr.vmtest.HtmlFragment;
88.9 +import org.apidesign.bck2brwsr.vmtest.VMTest;
88.10 +import org.testng.annotations.Factory;
88.11 +
88.12 +/** Sometimes it is useful to run tests inside of the real browser.
88.13 + * To do that just annotate your method with {@link org.apidesign.bck2brwsr.vmtest.BrwsrTest}
88.14 + * and that is it. If your code references elements on the HTML page,
88.15 + * you can pass in an {@link org.apidesign.bck2brwsr.vmtest.HtmlFragment} which
88.16 + * will be made available on the page before your test starts.
88.17 + *
88.18 + * @author Jaroslav Tulach <jtulach@netbeans.org>
88.19 + */
88.20 +public class IntegrationTest {
88.21 +
88.22 + /** Write to testing code here. Use <code>assert</code> (but not TestNG's
88.23 + * Assert, as TestNG is not compiled with target 1.6 yet).
88.24 + */
88.25 + @HtmlFragment(
88.26 + "<h1 data-bind=\"text: helloMessage\">Loading Bck2Brwsr's Hello World...</h1>\n" +
88.27 + "Your name: <input id='input' data-bind=\"value: name, valueUpdate: 'afterkeydown'\"></input>\n" +
88.28 + "<button id=\"hello\">Say Hello!</button>\n" +
88.29 + "<p>\n" +
88.30 + " <canvas id=\"canvas\" width=\"300\" height=\"50\"></canvas>\n" +
88.31 + "</p>\n"
88.32 + )
88.33 + @BrwsrTest
88.34 + public void modifyValueAssertChangeInModel() {
88.35 + Index m = new Index();
88.36 + m.setName("Joe Hacker");
88.37 + m.applyBindings();
88.38 + assert "Joe Hacker".equals(m.input.getValue()) : "Value is really Joe Hacker: " + m.input.getValue();
88.39 + m.input.setValue("Happy Joe");
88.40 + m.triggerEvent(m.input, OnEvent.CHANGE);
88.41 + assert "Happy Joe".equals(m.getName()) : "Name property updated to Happy Joe: " + m.getName();
88.42 + }
88.43 +
88.44 + @Factory
88.45 + public static Object[] create() {
88.46 + return VMTest.create(IntegrationTest.class);
88.47 + }
88.48 +
88.49 +}
89.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
89.2 +++ b/rt/archetype/src/test/java/org/apidesign/bck2brwsr/archetype/ArchetypeVersionTest.java Thu May 02 09:18:22 2013 +0200
89.3 @@ -0,0 +1,101 @@
89.4 +/**
89.5 + * Back 2 Browser Bytecode Translator
89.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
89.7 + *
89.8 + * This program is free software: you can redistribute it and/or modify
89.9 + * it under the terms of the GNU General Public License as published by
89.10 + * the Free Software Foundation, version 2 of the License.
89.11 + *
89.12 + * This program is distributed in the hope that it will be useful,
89.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
89.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
89.15 + * GNU General Public License for more details.
89.16 + *
89.17 + * You should have received a copy of the GNU General Public License
89.18 + * along with this program. Look for COPYING file in the top folder.
89.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
89.20 + */
89.21 +package org.apidesign.bck2brwsr.archetype;
89.22 +
89.23 +import java.net.URL;
89.24 +import javax.xml.XMLConstants;
89.25 +import javax.xml.parsers.DocumentBuilderFactory;
89.26 +import javax.xml.xpath.XPathConstants;
89.27 +import javax.xml.xpath.XPathExpression;
89.28 +import javax.xml.xpath.XPathFactory;
89.29 +import org.testng.annotations.Test;
89.30 +import static org.testng.Assert.*;
89.31 +import org.testng.annotations.BeforeClass;
89.32 +import org.w3c.dom.Document;
89.33 +import org.w3c.dom.NodeList;
89.34 +
89.35 +/**
89.36 + *
89.37 + * @author Jaroslav Tulach <jtulach@netbeans.org>
89.38 + */
89.39 +public class ArchetypeVersionTest {
89.40 + private String version;
89.41 +
89.42 + public ArchetypeVersionTest() {
89.43 + }
89.44 +
89.45 + @BeforeClass public void readCurrentVersion() throws Exception {
89.46 + final ClassLoader l = ArchetypeVersionTest.class.getClassLoader();
89.47 + URL u = l.getResource("META-INF/maven/org.apidesign.bck2brwsr/bck2brwsr-archetype-html-sample/pom.xml");
89.48 + assertNotNull(u, "Own pom found: " + System.getProperty("java.class.path"));
89.49 +
89.50 + final XPathFactory fact = XPathFactory.newInstance();
89.51 + fact.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
89.52 +
89.53 + XPathExpression xp = fact.newXPath().compile("project/version/text()");
89.54 +
89.55 + Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(u.openStream());
89.56 + version = xp.evaluate(dom);
89.57 +
89.58 + assertFalse(version.isEmpty(), "There should be some version string");
89.59 + }
89.60 +
89.61 +
89.62 + @Test public void testComparePomDepsVersions() throws Exception {
89.63 + final ClassLoader l = ArchetypeVersionTest.class.getClassLoader();
89.64 + URL r = l.getResource("archetype-resources/pom.xml");
89.65 + assertNotNull(r, "Archetype pom found");
89.66 +
89.67 + final XPathFactory fact = XPathFactory.newInstance();
89.68 + XPathExpression xp2 = fact.newXPath().compile(
89.69 + "//version[../groupId/text() = 'org.apidesign.bck2brwsr']/text()"
89.70 + );
89.71 +
89.72 + Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(r.openStream());
89.73 + NodeList arch = (NodeList) xp2.evaluate(dom, XPathConstants.NODESET);
89.74 +
89.75 + if (arch.getLength() < 3) {
89.76 + fail("There should be at least three dependencies to bck2brwsr APIs: " + arch.getLength());
89.77 + }
89.78 +
89.79 + for (int i = 0; i < arch.getLength(); i++) {
89.80 + assertEquals(arch.item(i).getTextContent(), version, i + "th dependency needs to be on latest version of bck2brwsr");
89.81 + }
89.82 + }
89.83 +
89.84 + @Test public void testNbActions() throws Exception {
89.85 + final ClassLoader l = ArchetypeVersionTest.class.getClassLoader();
89.86 + URL r = l.getResource("archetype-resources/nbactions.xml");
89.87 + assertNotNull(r, "Archetype nb file found");
89.88 +
89.89 + final XPathFactory fact = XPathFactory.newInstance();
89.90 + XPathExpression xp2 = fact.newXPath().compile(
89.91 + "//goal/text()"
89.92 + );
89.93 +
89.94 + Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(r.openStream());
89.95 + NodeList goals = (NodeList) xp2.evaluate(dom, XPathConstants.NODESET);
89.96 +
89.97 + for (int i = 0; i < goals.getLength(); i++) {
89.98 + String s = goals.item(i).getTextContent();
89.99 + if (s.contains("bck2brwsr")) {
89.100 + assertFalse(s.matches(".*bck2brwsr.*[0-9].*"), "No numbers: " + s);
89.101 + }
89.102 + }
89.103 + }
89.104 +}
90.1 --- a/rt/core/pom.xml Tue Apr 02 15:40:51 2013 +0200
90.2 +++ b/rt/core/pom.xml Thu May 02 09:18:22 2013 +0200
90.3 @@ -4,11 +4,11 @@
90.4 <parent>
90.5 <groupId>org.apidesign.bck2brwsr</groupId>
90.6 <artifactId>rt</artifactId>
90.7 - <version>0.5-SNAPSHOT</version>
90.8 + <version>0.8-SNAPSHOT</version>
90.9 </parent>
90.10 <groupId>org.apidesign.bck2brwsr</groupId>
90.11 <artifactId>core</artifactId>
90.12 - <version>0.5-SNAPSHOT</version>
90.13 + <version>0.8-SNAPSHOT</version>
90.14 <name>Bck2Brwsr Native Annotations</name>
90.15 <url>http://maven.apache.org</url>
90.16 <build>
91.1 --- a/rt/emul/brwsrtest/pom.xml Tue Apr 02 15:40:51 2013 +0200
91.2 +++ b/rt/emul/brwsrtest/pom.xml Thu May 02 09:18:22 2013 +0200
91.3 @@ -1,15 +1,14 @@
91.4 <?xml version="1.0"?>
91.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"
91.6 - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
91.7 +<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">
91.8 <modelVersion>4.0.0</modelVersion>
91.9 <parent>
91.10 <groupId>org.apidesign.bck2brwsr</groupId>
91.11 <artifactId>emul.pom</artifactId>
91.12 - <version>0.5-SNAPSHOT</version>
91.13 + <version>0.8-SNAPSHOT</version>
91.14 </parent>
91.15 <groupId>org.apidesign.bck2brwsr</groupId>
91.16 <artifactId>brwsrtest</artifactId>
91.17 - <version>0.5-SNAPSHOT</version>
91.18 + <version>0.8-SNAPSHOT</version>
91.19 <name>Tests Inside Real Browser</name>
91.20 <url>http://maven.apache.org</url>
91.21 <properties>
91.22 @@ -43,5 +42,11 @@
91.23 <version>${project.version}</version>
91.24 <scope>test</scope>
91.25 </dependency>
91.26 + <dependency>
91.27 + <groupId>${project.groupId}</groupId>
91.28 + <artifactId>launcher.http</artifactId>
91.29 + <version>${project.version}</version>
91.30 + <scope>provided</scope>
91.31 + </dependency>
91.32 </dependencies>
91.33 </project>
92.1 --- a/rt/emul/compact/pom.xml Tue Apr 02 15:40:51 2013 +0200
92.2 +++ b/rt/emul/compact/pom.xml Thu May 02 09:18:22 2013 +0200
92.3 @@ -4,11 +4,11 @@
92.4 <parent>
92.5 <groupId>org.apidesign.bck2brwsr</groupId>
92.6 <artifactId>emul.pom</artifactId>
92.7 - <version>0.5-SNAPSHOT</version>
92.8 + <version>0.8-SNAPSHOT</version>
92.9 </parent>
92.10 <groupId>org.apidesign.bck2brwsr</groupId>
92.11 <artifactId>emul</artifactId>
92.12 - <version>0.5-SNAPSHOT</version>
92.13 + <version>0.8-SNAPSHOT</version>
92.14 <name>Bck2Brwsr API Profile</name>
92.15 <url>http://maven.apache.org</url>
92.16 <properties>
92.17 @@ -28,6 +28,12 @@
92.18 <scope>test</scope>
92.19 </dependency>
92.20 <dependency>
92.21 + <groupId>${project.groupId}</groupId>
92.22 + <artifactId>launcher.http</artifactId>
92.23 + <version>${project.version}</version>
92.24 + <scope>test</scope>
92.25 + </dependency>
92.26 + <dependency>
92.27 <groupId>org.netbeans.api</groupId>
92.28 <artifactId>org-openide-util-lookup</artifactId>
92.29 <scope>test</scope>
93.1 --- a/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/compact/tck/ZipCompatibilityTest.java Tue Apr 02 15:40:51 2013 +0200
93.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/compact/tck/ZipCompatibilityTest.java Thu May 02 09:18:22 2013 +0200
93.3 @@ -30,7 +30,7 @@
93.4 public class ZipCompatibilityTest {
93.5 @Compare
93.6 public String testDemoStaticCalculator() throws IOException {
93.7 - InputStream is = getClass().getResourceAsStream("demo.static.calculator-0.3-SNAPSHOT.jar");
93.8 + InputStream is = getClass().getResourceAsStream("demo.static.calculator-TEST.jar");
93.9 ZipArchive zip = ZipArchive.createZip(is);
93.10 final String ts = zip.toString();
93.11 return ts.substring(0, 4096) + ts.hashCode();
94.1 --- a/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/compact/tck/ZipVsJzLibTest.java Tue Apr 02 15:40:51 2013 +0200
94.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/compact/tck/ZipVsJzLibTest.java Thu May 02 09:18:22 2013 +0200
94.3 @@ -27,10 +27,10 @@
94.4 */
94.5 public class ZipVsJzLibTest {
94.6 @Test public void r() throws IOException {
94.7 - InputStream is = getClass().getResourceAsStream("demo.static.calculator-0.3-SNAPSHOT.jar");
94.8 + InputStream is = getClass().getResourceAsStream("demo.static.calculator-TEST.jar");
94.9 ZipArchive zip = ZipArchive.createZip(is);
94.10
94.11 - is = getClass().getResourceAsStream("demo.static.calculator-0.3-SNAPSHOT.jar");
94.12 + is = getClass().getResourceAsStream("demo.static.calculator-TEST.jar");
94.13 ZipArchive real = ZipArchive.createReal(is);
94.14
94.15 real.assertEquals(zip, "Are they the same?");
95.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
95.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/AssertionTest.java Thu May 02 09:18:22 2013 +0200
95.3 @@ -0,0 +1,43 @@
95.4 +/**
95.5 + * Back 2 Browser Bytecode Translator
95.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
95.7 + *
95.8 + * This program is free software: you can redistribute it and/or modify
95.9 + * it under the terms of the GNU General Public License as published by
95.10 + * the Free Software Foundation, version 2 of the License.
95.11 + *
95.12 + * This program is distributed in the hope that it will be useful,
95.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
95.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
95.15 + * GNU General Public License for more details.
95.16 + *
95.17 + * You should have received a copy of the GNU General Public License
95.18 + * along with this program. Look for COPYING file in the top folder.
95.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
95.20 + */
95.21 +package org.apidesign.bck2brwsr.tck;
95.22 +
95.23 +import org.apidesign.bck2brwsr.vmtest.Compare;
95.24 +import org.apidesign.bck2brwsr.vmtest.VMTest;
95.25 +import org.testng.annotations.Factory;
95.26 +
95.27 +/**
95.28 + *
95.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
95.30 + */
95.31 +public class AssertionTest {
95.32 +
95.33 + @Compare public Object checkAssert() throws ClassNotFoundException {
95.34 + try {
95.35 + assert false : "Is assertion status on?";
95.36 + return null;
95.37 + } catch (AssertionError ex) {
95.38 + return ex.getClass().getName();
95.39 + }
95.40 + }
95.41 +
95.42 + @Factory
95.43 + public static Object[] create() {
95.44 + return VMTest.create(AssertionTest.class);
95.45 + }
95.46 +}
96.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
96.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/BrwsrCheckTest.java Thu May 02 09:18:22 2013 +0200
96.3 @@ -0,0 +1,57 @@
96.4 +/**
96.5 + * Back 2 Browser Bytecode Translator
96.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
96.7 + *
96.8 + * This program is free software: you can redistribute it and/or modify
96.9 + * it under the terms of the GNU General Public License as published by
96.10 + * the Free Software Foundation, version 2 of the License.
96.11 + *
96.12 + * This program is distributed in the hope that it will be useful,
96.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
96.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
96.15 + * GNU General Public License for more details.
96.16 + *
96.17 + * You should have received a copy of the GNU General Public License
96.18 + * along with this program. Look for COPYING file in the top folder.
96.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
96.20 + */
96.21 +package org.apidesign.bck2brwsr.tck;
96.22 +
96.23 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
96.24 +import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
96.25 +import org.apidesign.bck2brwsr.vmtest.HtmlFragment;
96.26 +import org.apidesign.bck2brwsr.vmtest.VMTest;
96.27 +import org.testng.annotations.Factory;
96.28 +
96.29 +/**
96.30 + *
96.31 + * @author Jaroslav Tulach <jtulach@netbeans.org>
96.32 + */
96.33 +public class BrwsrCheckTest {
96.34 +
96.35 + @BrwsrTest public void assertWindowObjectIsDefined() {
96.36 + assert window() != null : "No window object found!";
96.37 + }
96.38 +
96.39 +
96.40 +
96.41 +
96.42 + @HtmlFragment("<h1 id='hello'>\n"
96.43 + + "Hello!\n"
96.44 + + "</h1>\n")
96.45 + @BrwsrTest public void accessProvidedFragment() {
96.46 + assert getElementById("hello") != null : "Element with 'hello' ID found";
96.47 + }
96.48 +
96.49 + @Factory
96.50 + public static Object[] create() {
96.51 + return VMTest.create(BrwsrCheckTest.class);
96.52 + }
96.53 +
96.54 +
96.55 + @JavaScriptBody(args = {}, body = "return window;")
96.56 + private static native Object window();
96.57 +
96.58 + @JavaScriptBody(args = { "id" }, body = "return window.document.getElementById(id);")
96.59 + private static native Object getElementById(String id);
96.60 +}
97.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
97.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/ByteArithmeticTest.java Thu May 02 09:18:22 2013 +0200
97.3 @@ -0,0 +1,147 @@
97.4 +/**
97.5 + * Back 2 Browser Bytecode Translator
97.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
97.7 + *
97.8 + * This program is free software: you can redistribute it and/or modify
97.9 + * it under the terms of the GNU General Public License as published by
97.10 + * the Free Software Foundation, version 2 of the License.
97.11 + *
97.12 + * This program is distributed in the hope that it will be useful,
97.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
97.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
97.15 + * GNU General Public License for more details.
97.16 + *
97.17 + * You should have received a copy of the GNU General Public License
97.18 + * along with this program. Look for COPYING file in the top folder.
97.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
97.20 + */
97.21 +package org.apidesign.bck2brwsr.tck;
97.22 +
97.23 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
97.24 +import org.apidesign.bck2brwsr.vmtest.Compare;
97.25 +import org.apidesign.bck2brwsr.vmtest.VMTest;
97.26 +import org.testng.annotations.Factory;
97.27 +
97.28 +/**
97.29 + *
97.30 + * @author Jaroslav Tulach <jtulach@netbeans.org>
97.31 + */
97.32 +public class ByteArithmeticTest {
97.33 +
97.34 + private static byte add(byte x, byte y) {
97.35 + return (byte)(x + y);
97.36 + }
97.37 +
97.38 + private static byte sub(byte x, byte y) {
97.39 + return (byte)(x - y);
97.40 + }
97.41 +
97.42 + private static byte mul(byte x, byte y) {
97.43 + return (byte)(x * y);
97.44 + }
97.45 +
97.46 + private static byte div(byte x, byte y) {
97.47 + return (byte)(x / y);
97.48 + }
97.49 +
97.50 + private static byte mod(byte x, byte y) {
97.51 + return (byte)(x % y);
97.52 + }
97.53 +
97.54 + @Compare public byte conversion() {
97.55 + return (byte)123456;
97.56 + }
97.57 +
97.58 + @Compare public byte addOverflow() {
97.59 + return add(Byte.MAX_VALUE, (byte)1);
97.60 + }
97.61 +
97.62 + @Compare public byte subUnderflow() {
97.63 + return sub(Byte.MIN_VALUE, (byte)1);
97.64 + }
97.65 +
97.66 + @Compare public byte addMaxByteAndMaxByte() {
97.67 + return add(Byte.MAX_VALUE, Byte.MAX_VALUE);
97.68 + }
97.69 +
97.70 + @Compare public byte subMinByteAndMinByte() {
97.71 + return sub(Byte.MIN_VALUE, Byte.MIN_VALUE);
97.72 + }
97.73 +
97.74 + @Compare public byte multiplyMaxByte() {
97.75 + return mul(Byte.MAX_VALUE, (byte)2);
97.76 + }
97.77 +
97.78 + @Compare public byte multiplyMaxByteAndMaxByte() {
97.79 + return mul(Byte.MAX_VALUE, Byte.MAX_VALUE);
97.80 + }
97.81 +
97.82 + @Compare public byte multiplyMinByte() {
97.83 + return mul(Byte.MIN_VALUE, (byte)2);
97.84 + }
97.85 +
97.86 + @Compare public byte multiplyMinByteAndMinByte() {
97.87 + return mul(Byte.MIN_VALUE, Byte.MIN_VALUE);
97.88 + }
97.89 +
97.90 + @Compare public byte multiplyPrecision() {
97.91 + return mul((byte)17638, (byte)1103);
97.92 + }
97.93 +
97.94 + @Compare public byte division() {
97.95 + return div((byte)1, (byte)2);
97.96 + }
97.97 +
97.98 + @Compare public byte divisionReminder() {
97.99 + return mod((byte)1, (byte)2);
97.100 + }
97.101 +
97.102 + private static int readShort(byte[] byteCodes, int offset) {
97.103 + int signed = byteCodes[offset];
97.104 + byte b0 = (byte)signed;
97.105 + return (b0 << 8) | (byteCodes[offset + 1] & 0xff);
97.106 + }
97.107 +
97.108 + private static int readShortArg(byte[] byteCodes, int offsetInstruction) {
97.109 + return readShort(byteCodes, offsetInstruction + 1);
97.110 + }
97.111 +
97.112 + @Compare public int readIntArgs255and156() {
97.113 + final byte[] arr = new byte[] { (byte)0, (byte)255, (byte)156 };
97.114 +
97.115 + assert arr[1] == -1 : "First byte: " + arr[1];
97.116 + assert arr[2] == -100 : "Second byte: " + arr[2];
97.117 + final int ret = readShortArg(arr, 0);
97.118 + assert ret < 65000: "Value: " + ret;
97.119 + return ret;
97.120 + }
97.121 +
97.122 + @JavaScriptBody(args = { "arr" }, body = "arr[1] = 255; arr[2] = 156; return arr;")
97.123 + private static byte[] fill255and156(byte[] arr) {
97.124 + arr[1] = (byte)255;
97.125 + arr[2] = (byte)156;
97.126 + return arr;
97.127 + }
97.128 +
97.129 + @Compare public int readIntArgs255and156JSArray() {
97.130 + final byte[] arr = fill255and156(new byte[] { 0, 0, 0 });
97.131 +
97.132 + final int ret = readShortArg(arr, 0);
97.133 + assert ret < 65000: "Value: " + ret;
97.134 + return ret;
97.135 + }
97.136 +
97.137 + @Compare public int readIntArgsMinus1andMinus100() {
97.138 + final byte[] arr = new byte[] { (byte)0, (byte)-1, (byte)-100 };
97.139 +
97.140 + assert arr[1] == -1 : "First byte: " + arr[1];
97.141 + assert arr[2] == -100 : "Second byte: " + arr[2];
97.142 +
97.143 + return readShortArg(arr, 0);
97.144 + }
97.145 +
97.146 + @Factory
97.147 + public static Object[] create() {
97.148 + return VMTest.create(ByteArithmeticTest.class);
97.149 + }
97.150 +}
98.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
98.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/CloneTest.java Thu May 02 09:18:22 2013 +0200
98.3 @@ -0,0 +1,73 @@
98.4 +/**
98.5 + * Back 2 Browser Bytecode Translator
98.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
98.7 + *
98.8 + * This program is free software: you can redistribute it and/or modify
98.9 + * it under the terms of the GNU General Public License as published by
98.10 + * the Free Software Foundation, version 2 of the License.
98.11 + *
98.12 + * This program is distributed in the hope that it will be useful,
98.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
98.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
98.15 + * GNU General Public License for more details.
98.16 + *
98.17 + * You should have received a copy of the GNU General Public License
98.18 + * along with this program. Look for COPYING file in the top folder.
98.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
98.20 + */
98.21 +package org.apidesign.bck2brwsr.tck;
98.22 +
98.23 +import org.apidesign.bck2brwsr.vmtest.Compare;
98.24 +import org.apidesign.bck2brwsr.vmtest.VMTest;
98.25 +import org.testng.annotations.Factory;
98.26 +
98.27 +/**
98.28 + *
98.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
98.30 + */
98.31 +public class CloneTest {
98.32 + private int value;
98.33 +
98.34 + @Compare
98.35 + public Object notSupported() throws CloneNotSupportedException {
98.36 + return this.clone();
98.37 + }
98.38 +
98.39 + @Compare public String sameClass() throws CloneNotSupportedException {
98.40 + return new Clnbl().clone().getClass().getName();
98.41 + }
98.42 +
98.43 + @Compare public boolean differentInstance() throws CloneNotSupportedException {
98.44 + Clnbl orig = new Clnbl();
98.45 + return orig == orig.clone();
98.46 + }
98.47 +
98.48 + @Compare public int sameReference() throws CloneNotSupportedException {
98.49 + CloneTest self = this;
98.50 + Clnbl orig = new Clnbl();
98.51 + self.value = 33;
98.52 + orig.ref = self;
98.53 + return ((Clnbl)orig.clone()).ref.value;
98.54 + }
98.55 +
98.56 + @Compare public int sameValue() throws CloneNotSupportedException {
98.57 + Clnbl orig = new Clnbl();
98.58 + orig.value = 10;
98.59 + return ((Clnbl)orig.clone()).value;
98.60 + }
98.61 +
98.62 + @Factory
98.63 + public static Object[] create() {
98.64 + return VMTest.create(CloneTest.class);
98.65 + }
98.66 +
98.67 + public static final class Clnbl implements Cloneable {
98.68 + public CloneTest ref;
98.69 + private int value;
98.70 +
98.71 + @Override
98.72 + public Object clone() throws CloneNotSupportedException {
98.73 + return super.clone();
98.74 + }
98.75 + }
98.76 +}
99.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
99.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/CompareByteArrayTest.java Thu May 02 09:18:22 2013 +0200
99.3 @@ -0,0 +1,103 @@
99.4 +/**
99.5 + * Back 2 Browser Bytecode Translator
99.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
99.7 + *
99.8 + * This program is free software: you can redistribute it and/or modify
99.9 + * it under the terms of the GNU General Public License as published by
99.10 + * the Free Software Foundation, version 2 of the License.
99.11 + *
99.12 + * This program is distributed in the hope that it will be useful,
99.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
99.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
99.15 + * GNU General Public License for more details.
99.16 + *
99.17 + * You should have received a copy of the GNU General Public License
99.18 + * along with this program. Look for COPYING file in the top folder.
99.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
99.20 + */
99.21 +package org.apidesign.bck2brwsr.tck;
99.22 +
99.23 +import org.apidesign.bck2brwsr.vmtest.Compare;
99.24 +import org.apidesign.bck2brwsr.vmtest.VMTest;
99.25 +import org.testng.annotations.Factory;
99.26 +
99.27 +/**
99.28 + *
99.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
99.30 + */
99.31 +public class CompareByteArrayTest {
99.32 + @Compare public int byteArraySum() {
99.33 + byte[] arr = createArray();
99.34 + return sumByteArr(arr);
99.35 + }
99.36 +
99.37 + @Compare public int countZeros() {
99.38 + int zeros = 0;
99.39 + for (Byte b : createArray()) {
99.40 + if (b == 0) {
99.41 + zeros++;
99.42 + }
99.43 + }
99.44 + return zeros;
99.45 + }
99.46 +
99.47 + private static int sumByteArr(byte[] arr) {
99.48 + int sum = 0;
99.49 + for (int i = 0; i < arr.length; i++) {
99.50 + sum += arr[i];
99.51 + }
99.52 + return sum;
99.53 + }
99.54 +
99.55 + @Compare public String noOutOfBounds() {
99.56 + return atIndex(1);
99.57 + }
99.58 +
99.59 + @Compare public String outOfBounds() {
99.60 + return atIndex(5);
99.61 + }
99.62 +
99.63 + @Compare public String outOfBoundsMinus() {
99.64 + return atIndex(-1);
99.65 + }
99.66 +
99.67 + @Compare public String toOfBounds() {
99.68 + return toIndex(5);
99.69 + }
99.70 +
99.71 + @Compare public String toOfBoundsMinus() {
99.72 + return toIndex(-1);
99.73 + }
99.74 +
99.75 + @Compare public int multiArrayLength() {
99.76 + int[][] arr = new int[1][0];
99.77 + return arr[0].length;
99.78 + }
99.79 +
99.80 + @Compare public int multiObjectArrayLength() {
99.81 + Object[][] arr = new Object[1][0];
99.82 + return arr[0].length;
99.83 + }
99.84 +
99.85 + private static final int[] arr = { 0, 1, 2 };
99.86 + public static String atIndex(int at) {
99.87 + return "at@" + arr[at];
99.88 + }
99.89 + public static String toIndex(int at) {
99.90 + arr[at] = 10;
99.91 + return "ok";
99.92 + }
99.93 +
99.94 +
99.95 + @Factory
99.96 + public static Object[] create() {
99.97 + return VMTest.create(CompareByteArrayTest.class);
99.98 + }
99.99 +
99.100 + private byte[] createArray() {
99.101 + byte[] arr = new byte[10];
99.102 + arr[5] = 3;
99.103 + arr[7] = 8;
99.104 + return arr;
99.105 + }
99.106 +}
100.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
100.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/CompareHashTest.java Thu May 02 09:18:22 2013 +0200
100.3 @@ -0,0 +1,50 @@
100.4 +/**
100.5 + * Back 2 Browser Bytecode Translator
100.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
100.7 + *
100.8 + * This program is free software: you can redistribute it and/or modify
100.9 + * it under the terms of the GNU General Public License as published by
100.10 + * the Free Software Foundation, version 2 of the License.
100.11 + *
100.12 + * This program is distributed in the hope that it will be useful,
100.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
100.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
100.15 + * GNU General Public License for more details.
100.16 + *
100.17 + * You should have received a copy of the GNU General Public License
100.18 + * along with this program. Look for COPYING file in the top folder.
100.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
100.20 + */
100.21 +package org.apidesign.bck2brwsr.tck;
100.22 +
100.23 +import org.apidesign.bck2brwsr.vmtest.Compare;
100.24 +import org.apidesign.bck2brwsr.vmtest.VMTest;
100.25 +import org.testng.annotations.Factory;
100.26 +
100.27 +/**
100.28 + *
100.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
100.30 + */
100.31 +public class CompareHashTest {
100.32 + @Compare public int hashOfString() {
100.33 + return "Ahoj".hashCode();
100.34 + }
100.35 +
100.36 + @Compare public int hashRemainsYieldsZero() {
100.37 + Object o = new Object();
100.38 + return o.hashCode() - o.hashCode();
100.39 + }
100.40 +
100.41 + @Compare public int initializeInStatic() {
100.42 + return StaticUse.NON_NULL.hashCode() - StaticUse.NON_NULL.hashCode();
100.43 + }
100.44 +
100.45 + @Compare public int hashOfInt() {
100.46 + return Integer.valueOf(Integer.MAX_VALUE).hashCode();
100.47 + }
100.48 +
100.49 + @Factory
100.50 + public static Object[] create() {
100.51 + return VMTest.create(CompareHashTest.class);
100.52 + }
100.53 +}
101.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
101.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/CompareIntArrayTest.java Thu May 02 09:18:22 2013 +0200
101.3 @@ -0,0 +1,63 @@
101.4 +/**
101.5 + * Back 2 Browser Bytecode Translator
101.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
101.7 + *
101.8 + * This program is free software: you can redistribute it and/or modify
101.9 + * it under the terms of the GNU General Public License as published by
101.10 + * the Free Software Foundation, version 2 of the License.
101.11 + *
101.12 + * This program is distributed in the hope that it will be useful,
101.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
101.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
101.15 + * GNU General Public License for more details.
101.16 + *
101.17 + * You should have received a copy of the GNU General Public License
101.18 + * along with this program. Look for COPYING file in the top folder.
101.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
101.20 + */
101.21 +package org.apidesign.bck2brwsr.tck;
101.22 +
101.23 +import org.apidesign.bck2brwsr.vmtest.Compare;
101.24 +import org.apidesign.bck2brwsr.vmtest.VMTest;
101.25 +import org.testng.annotations.Factory;
101.26 +
101.27 +/**
101.28 + *
101.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
101.30 + */
101.31 +public class CompareIntArrayTest {
101.32 + @Compare public int integerArraySum() {
101.33 + int[] arr = createArray();
101.34 + return sumIntArr(arr);
101.35 + }
101.36 +
101.37 + @Compare public int countZeros() {
101.38 + int zeros = 0;
101.39 + for (Integer i : createArray()) {
101.40 + if (i == 0) {
101.41 + zeros++;
101.42 + }
101.43 + }
101.44 + return zeros;
101.45 + }
101.46 +
101.47 + private static int sumIntArr(int[] arr) {
101.48 + int sum = 0;
101.49 + for (int i = 0; i < arr.length; i++) {
101.50 + sum += arr[i];
101.51 + }
101.52 + return sum;
101.53 + }
101.54 +
101.55 + @Factory
101.56 + public static Object[] create() {
101.57 + return VMTest.create(CompareIntArrayTest.class);
101.58 + }
101.59 +
101.60 + private int[] createArray() {
101.61 + int[] arr = new int[10];
101.62 + arr[5] = 3;
101.63 + arr[7] = 8;
101.64 + return arr;
101.65 + }
101.66 +}
102.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
102.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/CompareStringsTest.java Thu May 02 09:18:22 2013 +0200
102.3 @@ -0,0 +1,174 @@
102.4 +/**
102.5 + * Back 2 Browser Bytecode Translator
102.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
102.7 + *
102.8 + * This program is free software: you can redistribute it and/or modify
102.9 + * it under the terms of the GNU General Public License as published by
102.10 + * the Free Software Foundation, version 2 of the License.
102.11 + *
102.12 + * This program is distributed in the hope that it will be useful,
102.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
102.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
102.15 + * GNU General Public License for more details.
102.16 + *
102.17 + * You should have received a copy of the GNU General Public License
102.18 + * along with this program. Look for COPYING file in the top folder.
102.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
102.20 + */
102.21 +package org.apidesign.bck2brwsr.tck;
102.22 +
102.23 +import java.io.UnsupportedEncodingException;
102.24 +import java.net.MalformedURLException;
102.25 +import java.net.URL;
102.26 +import org.apidesign.bck2brwsr.vmtest.Compare;
102.27 +import org.apidesign.bck2brwsr.vmtest.VMTest;
102.28 +import org.testng.annotations.Factory;
102.29 +
102.30 +/**
102.31 + *
102.32 + * @author Jaroslav Tulach <jtulach@netbeans.org>
102.33 + */
102.34 +public class CompareStringsTest {
102.35 + @Compare public String firstChar() {
102.36 + return "" + ("Hello".toCharArray()[0]);
102.37 + }
102.38 +
102.39 + @Compare public String classCast() {
102.40 + Object o = firstChar();
102.41 + return String.class.cast(o);
102.42 + }
102.43 +
102.44 + @Compare public String classCastThrown() {
102.45 + Object o = null;
102.46 + return String.class.cast(o);
102.47 + }
102.48 +
102.49 + @Compare public boolean equalToNull() {
102.50 + return "Ahoj".equals(null);
102.51 + }
102.52 +
102.53 + @Compare public int highByteLenght() {
102.54 + byte[] arr= { 77,97,110,105,102,101,115,116,45,86,101,114,115,105,111,110 };
102.55 + return new String(arr, 0).length();
102.56 + }
102.57 +
102.58 + @Compare public String highByte() {
102.59 + byte[] arr= { 77,97,110,105,102,101,115,116,45,86,101,114,115,105,111,110 };
102.60 + StringBuilder sb = new StringBuilder();
102.61 + sb.append("pref:");
102.62 + sb.append(new String(arr, 0));
102.63 + return sb.toString();
102.64 + }
102.65 +
102.66 + @Compare public static Object compareURLs() throws MalformedURLException {
102.67 + return new URL("http://apidesign.org:8080/wiki/").toExternalForm().toString();
102.68 + }
102.69 +
102.70 + @Compare public String deleteLastTwoCharacters() {
102.71 + StringBuilder sb = new StringBuilder();
102.72 + sb.append("453.0");
102.73 + if (sb.toString().endsWith(".0")) {
102.74 + final int l = sb.length();
102.75 + sb.delete(l - 2, l);
102.76 + }
102.77 + return sb.toString().toString();
102.78 + }
102.79 +
102.80 + @Compare public String nameOfStringClass() throws Exception {
102.81 + return Class.forName("java.lang.String").getName();
102.82 + }
102.83 + @Compare public String nameOfArrayClass() throws Exception {
102.84 + return Class.forName("org.apidesign.bck2brwsr.tck.CompareHashTest").getName();
102.85 + }
102.86 +
102.87 + @Compare public String lowerHello() {
102.88 + return "HeLlO".toLowerCase();
102.89 + }
102.90 +
102.91 + @Compare public String lowerA() {
102.92 + return String.valueOf(Character.toLowerCase('A')).toString();
102.93 + }
102.94 + @Compare public String upperHello() {
102.95 + return "hello".toUpperCase();
102.96 + }
102.97 +
102.98 + @Compare public String upperA() {
102.99 + return String.valueOf(Character.toUpperCase('a')).toString();
102.100 + }
102.101 +
102.102 + @Compare public boolean matchRegExp() throws Exception {
102.103 + return "58038503".matches("\\d*");
102.104 + }
102.105 +
102.106 + @Compare public boolean doesNotMatchRegExp() throws Exception {
102.107 + return "58038503GH".matches("\\d*");
102.108 + }
102.109 +
102.110 + @Compare public boolean doesNotMatchRegExpFully() throws Exception {
102.111 + return "Hello".matches("Hell");
102.112 + }
102.113 +
102.114 + @Compare public String emptyCharArray() {
102.115 + char[] arr = new char[10];
102.116 + return new String(arr);
102.117 + }
102.118 +
102.119 + @Compare public String variousCharacterTests() throws Exception {
102.120 + StringBuilder sb = new StringBuilder();
102.121 +
102.122 + sb.append(Character.isUpperCase('a'));
102.123 + sb.append(Character.isUpperCase('A'));
102.124 + sb.append(Character.isLowerCase('a'));
102.125 + sb.append(Character.isLowerCase('A'));
102.126 +
102.127 + sb.append(Character.isLetter('A'));
102.128 + sb.append(Character.isLetterOrDigit('9'));
102.129 + sb.append(Character.isLetterOrDigit('A'));
102.130 + sb.append(Character.isLetter('0'));
102.131 +
102.132 + return sb.toString().toString();
102.133 + }
102.134 +
102.135 + @Compare
102.136 + public String nullFieldInitialized() {
102.137 + NullField nf = new NullField();
102.138 + return ("" + nf.name).toString();
102.139 + }
102.140 + @Compare
102.141 + public String toUTFString() throws UnsupportedEncodingException {
102.142 + byte[] arr = {
102.143 + (byte) -59, (byte) -67, (byte) 108, (byte) 117, (byte) -59, (byte) -91,
102.144 + (byte) 111, (byte) 117, (byte) -60, (byte) -115, (byte) 107, (byte) -61,
102.145 + (byte) -67, (byte) 32, (byte) 107, (byte) -59, (byte) -81, (byte) -59,
102.146 + (byte) -120
102.147 + };
102.148 + return new String(arr, "utf-8");
102.149 + }
102.150 +
102.151 + @Compare
102.152 + public int stringToBytesLenght() throws UnsupportedEncodingException {
102.153 + return "\u017dlu\u0165ou\u010dk\u00fd k\u016f\u0148".getBytes("utf8").length;
102.154 + }
102.155 +
102.156 + @Compare public String replaceSeq() {
102.157 + return "Hello World.".replace(".", "!");
102.158 + }
102.159 + @Compare public String replaceSeqAll() {
102.160 + return "Hello World! Hello World.".replace("World", "Jarda");
102.161 + }
102.162 + @Compare public String replaceSeqAA() {
102.163 + String res = "aaa".replace("aa", "b");
102.164 + assert res.equals("ba") : "Expecting ba: " + res;
102.165 + return res;
102.166 + }
102.167 +
102.168 + @Factory
102.169 + public static Object[] create() {
102.170 + return VMTest.create(CompareStringsTest.class);
102.171 + }
102.172 +
102.173 + private static final class NullField {
102.174 +
102.175 + String name;
102.176 + }
102.177 +}
103.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
103.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/DoubleTest.java Thu May 02 09:18:22 2013 +0200
103.3 @@ -0,0 +1,65 @@
103.4 +/**
103.5 + * Back 2 Browser Bytecode Translator
103.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
103.7 + *
103.8 + * This program is free software: you can redistribute it and/or modify
103.9 + * it under the terms of the GNU General Public License as published by
103.10 + * the Free Software Foundation, version 2 of the License.
103.11 + *
103.12 + * This program is distributed in the hope that it will be useful,
103.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
103.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
103.15 + * GNU General Public License for more details.
103.16 + *
103.17 + * You should have received a copy of the GNU General Public License
103.18 + * along with this program. Look for COPYING file in the top folder.
103.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
103.20 + */
103.21 +package org.apidesign.bck2brwsr.tck;
103.22 +
103.23 +import org.apidesign.bck2brwsr.vmtest.Compare;
103.24 +import org.apidesign.bck2brwsr.vmtest.VMTest;
103.25 +import org.testng.annotations.Factory;
103.26 +
103.27 +/**
103.28 + *
103.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
103.30 + */
103.31 +public class DoubleTest {
103.32 + @Compare public String integerToString() {
103.33 + return toStr(1);
103.34 + }
103.35 +
103.36 + @Compare public String integerAndHalfToString() {
103.37 + return toStr(1.5);
103.38 + }
103.39 +
103.40 + @Compare public double longToAndBack() {
103.41 + return Double.parseDouble(toStr(Long.MAX_VALUE / 10));
103.42 + }
103.43 +
103.44 + @Compare public String negativeIntToString() {
103.45 + return toStr(-10);
103.46 + }
103.47 +
103.48 + @Compare public String negativeIntAndHalfToString() {
103.49 + return toStr(-10.5);
103.50 + }
103.51 +
103.52 + @Compare public double negativeLongAndBack() {
103.53 + return Double.parseDouble(toStr(Long.MIN_VALUE / 10));
103.54 + }
103.55 +
103.56 + @Compare public double canParseExp() {
103.57 + return Double.parseDouble(toStr(1.7976931348623157e+308));
103.58 + }
103.59 +
103.60 + private static String toStr(double d) {
103.61 + return Double.toString(d);
103.62 + }
103.63 +
103.64 + @Factory
103.65 + public static Object[] create() {
103.66 + return VMTest.create(DoubleTest.class);
103.67 + }
103.68 +}
104.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
104.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/HttpResourceTest.java Thu May 02 09:18:22 2013 +0200
104.3 @@ -0,0 +1,106 @@
104.4 +/**
104.5 + * Back 2 Browser Bytecode Translator
104.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
104.7 + *
104.8 + * This program is free software: you can redistribute it and/or modify
104.9 + * it under the terms of the GNU General Public License as published by
104.10 + * the Free Software Foundation, version 2 of the License.
104.11 + *
104.12 + * This program is distributed in the hope that it will be useful,
104.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
104.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
104.15 + * GNU General Public License for more details.
104.16 + *
104.17 + * You should have received a copy of the GNU General Public License
104.18 + * along with this program. Look for COPYING file in the top folder.
104.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
104.20 + */
104.21 +package org.apidesign.bck2brwsr.tck;
104.22 +
104.23 +import java.io.InputStream;
104.24 +import java.net.URL;
104.25 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
104.26 +import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
104.27 +import org.apidesign.bck2brwsr.vmtest.Http;
104.28 +import org.apidesign.bck2brwsr.vmtest.VMTest;
104.29 +import org.testng.annotations.Factory;
104.30 +
104.31 +/**
104.32 + *
104.33 + * @author Jaroslav Tulach <jtulach@netbeans.org>
104.34 + */
104.35 +public class HttpResourceTest {
104.36 +
104.37 + @Http({
104.38 + @Http.Resource(path = "/xhr", content = "Hello Brwsr!", mimeType = "text/plain")
104.39 + })
104.40 + @BrwsrTest
104.41 +
104.42 +
104.43 + public String testReadContentViaXHR() throws Exception {
104.44 + String msg = read("/xhr");
104.45 + assert "Hello Brwsr!".equals(msg) : "The message was " + msg;
104.46 + return msg;
104.47 + }
104.48 +
104.49 + @Http({
104.50 + @Http.Resource(path = "/url", content = "Hello via URL!", mimeType = "text/plain")
104.51 + })
104.52 + @BrwsrTest
104.53 + public String testReadContentViaURL() throws Exception {
104.54 + URL url = new URL("http:/url");
104.55 + String msg = (String) url.getContent();
104.56 + assert "Hello via URL!".equals(msg) : "The message was " + msg;
104.57 + return msg;
104.58 + }
104.59 + @Http({
104.60 + @Http.Resource(path = "/url", content = "Hello via URL!", mimeType = "text/plain")
104.61 + })
104.62 + @BrwsrTest
104.63 + public String testReadContentViaURLWithStringParam() throws Exception {
104.64 + URL url = new URL("http:/url");
104.65 + String msg = (String) url.getContent(new Class[] { String.class });
104.66 + assert "Hello via URL!".equals(msg) : "The message was " + msg;
104.67 + return msg;
104.68 + }
104.69 +
104.70 + @Http({
104.71 + @Http.Resource(path = "/bytes", content = "", resource = "0xfe", mimeType = "x-application/binary")
104.72 + })
104.73 + @BrwsrTest
104.74 + public void testReadByte() throws Exception {
104.75 + URL url = new URL("http:/bytes");
104.76 + final Object res = url.getContent(new Class[] { byte[].class });
104.77 + assert res instanceof byte[] : "Expecting byte[]: " + res;
104.78 + byte[] arr = (byte[]) res;
104.79 + assert arr.length == 1 : "One byte " + arr.length;
104.80 + assert arr[0] == 0xfe : "It is 0xfe: " + Integer.toHexString(arr[0]);
104.81 + }
104.82 +
104.83 + @Http({
104.84 + @Http.Resource(path = "/bytes", content = "", resource = "0xfe", mimeType = "x-application/binary")
104.85 + })
104.86 + @BrwsrTest
104.87 + public void testReadByteViaInputStream() throws Exception {
104.88 + URL url = new URL("http:/bytes");
104.89 + InputStream is = url.openStream();
104.90 + byte[] arr = new byte[10];
104.91 + int len = is.read(arr);
104.92 + assert len == 1 : "One byte " + len;
104.93 + assert arr[0] == 0xfe : "It is 0xfe: " + Integer.toHexString(arr[0]);
104.94 + }
104.95 +
104.96 + @JavaScriptBody(args = { "url" }, body =
104.97 + "var req = new XMLHttpRequest();\n"
104.98 + + "req.open('GET', url, false);\n"
104.99 + + "req.send();\n"
104.100 + + "return req.responseText;"
104.101 + )
104.102 + private static native String read(String url);
104.103 +
104.104 +
104.105 + @Factory
104.106 + public static Object[] create() {
104.107 + return VMTest.create(HttpResourceTest.class);
104.108 + }
104.109 +}
105.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
105.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/InheritanceA.java Thu May 02 09:18:22 2013 +0200
105.3 @@ -0,0 +1,34 @@
105.4 +/**
105.5 + * Back 2 Browser Bytecode Translator
105.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
105.7 + *
105.8 + * This program is free software: you can redistribute it and/or modify
105.9 + * it under the terms of the GNU General Public License as published by
105.10 + * the Free Software Foundation, version 2 of the License.
105.11 + *
105.12 + * This program is distributed in the hope that it will be useful,
105.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
105.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
105.15 + * GNU General Public License for more details.
105.16 + *
105.17 + * You should have received a copy of the GNU General Public License
105.18 + * along with this program. Look for COPYING file in the top folder.
105.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
105.20 + */
105.21 +package org.apidesign.bck2brwsr.tck;
105.22 +
105.23 +/**
105.24 + *
105.25 + * @author Jaroslav Tulach <jtulach@netbeans.org>
105.26 + */
105.27 +public class InheritanceA {
105.28 + private String name;
105.29 +
105.30 + public void setA(String n) {
105.31 + this.name = n;
105.32 + }
105.33 +
105.34 + public String getA() {
105.35 + return name;
105.36 + }
105.37 +}
106.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
106.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/InheritanceB.java Thu May 02 09:18:22 2013 +0200
106.3 @@ -0,0 +1,34 @@
106.4 +/**
106.5 + * Back 2 Browser Bytecode Translator
106.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
106.7 + *
106.8 + * This program is free software: you can redistribute it and/or modify
106.9 + * it under the terms of the GNU General Public License as published by
106.10 + * the Free Software Foundation, version 2 of the License.
106.11 + *
106.12 + * This program is distributed in the hope that it will be useful,
106.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
106.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
106.15 + * GNU General Public License for more details.
106.16 + *
106.17 + * You should have received a copy of the GNU General Public License
106.18 + * along with this program. Look for COPYING file in the top folder.
106.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
106.20 + */
106.21 +package org.apidesign.bck2brwsr.tck;
106.22 +
106.23 +/**
106.24 + *
106.25 + * @author Jaroslav Tulach <jtulach@netbeans.org>
106.26 + */
106.27 +public class InheritanceB extends InheritanceA {
106.28 + private String name;
106.29 +
106.30 + public void setB(String n) {
106.31 + this.name = n;
106.32 + }
106.33 +
106.34 + public String getB() {
106.35 + return name;
106.36 + }
106.37 +}
107.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
107.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/InheritanceTest.java Thu May 02 09:18:22 2013 +0200
107.3 @@ -0,0 +1,41 @@
107.4 +/**
107.5 + * Back 2 Browser Bytecode Translator
107.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
107.7 + *
107.8 + * This program is free software: you can redistribute it and/or modify
107.9 + * it under the terms of the GNU General Public License as published by
107.10 + * the Free Software Foundation, version 2 of the License.
107.11 + *
107.12 + * This program is distributed in the hope that it will be useful,
107.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
107.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
107.15 + * GNU General Public License for more details.
107.16 + *
107.17 + * You should have received a copy of the GNU General Public License
107.18 + * along with this program. Look for COPYING file in the top folder.
107.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
107.20 + */
107.21 +package org.apidesign.bck2brwsr.tck;
107.22 +
107.23 +import org.apidesign.bck2brwsr.vmtest.Compare;
107.24 +import org.apidesign.bck2brwsr.vmtest.VMTest;
107.25 +import org.testng.annotations.Factory;
107.26 +
107.27 +/**
107.28 + *
107.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
107.30 + */
107.31 +public class InheritanceTest {
107.32 +
107.33 + @Compare public String checkFieldsIndependent() throws ClassNotFoundException {
107.34 + InheritanceB ib = new InheritanceB();
107.35 + ib.setA("A");
107.36 + ib.setB("B");
107.37 + return "A: " + ib.getA() + " B: " + ib.getB();
107.38 + }
107.39 +
107.40 + @Factory
107.41 + public static Object[] create() {
107.42 + return VMTest.create(InheritanceTest.class);
107.43 + }
107.44 +}
108.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
108.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/IntegerArithmeticTest.java Thu May 02 09:18:22 2013 +0200
108.3 @@ -0,0 +1,166 @@
108.4 +/**
108.5 + * Back 2 Browser Bytecode Translator
108.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
108.7 + *
108.8 + * This program is free software: you can redistribute it and/or modify
108.9 + * it under the terms of the GNU General Public License as published by
108.10 + * the Free Software Foundation, version 2 of the License.
108.11 + *
108.12 + * This program is distributed in the hope that it will be useful,
108.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
108.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
108.15 + * GNU General Public License for more details.
108.16 + *
108.17 + * You should have received a copy of the GNU General Public License
108.18 + * along with this program. Look for COPYING file in the top folder.
108.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
108.20 + */
108.21 +package org.apidesign.bck2brwsr.tck;
108.22 +
108.23 +import org.apidesign.bck2brwsr.vmtest.Compare;
108.24 +import org.apidesign.bck2brwsr.vmtest.VMTest;
108.25 +import org.testng.annotations.Factory;
108.26 +
108.27 +/**
108.28 + *
108.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
108.30 + */
108.31 +public class IntegerArithmeticTest {
108.32 +
108.33 + private static int add(int x, int y) {
108.34 + return x + y;
108.35 + }
108.36 +
108.37 + private static int sub(int x, int y) {
108.38 + return x - y;
108.39 + }
108.40 +
108.41 + private static int mul(int x, int y) {
108.42 + return x * y;
108.43 + }
108.44 +
108.45 + private static int div(int x, int y) {
108.46 + return x / y;
108.47 + }
108.48 +
108.49 + private static int mod(int x, int y) {
108.50 + return x % y;
108.51 + }
108.52 +
108.53 + private static int neg(int x) {
108.54 + return (-x);
108.55 + }
108.56 +
108.57 + private static float fadd(float x, float y) {
108.58 + return x + y;
108.59 + }
108.60 +
108.61 + private static double dadd(double x, double y) {
108.62 + return x + y;
108.63 + }
108.64 +
108.65 + @Compare public int addOverflow() {
108.66 + return add(Integer.MAX_VALUE, 1);
108.67 + }
108.68 +
108.69 + @Compare public int subUnderflow() {
108.70 + return sub(Integer.MIN_VALUE, 1);
108.71 + }
108.72 +
108.73 + @Compare public int addMaxIntAndMaxInt() {
108.74 + return add(Integer.MAX_VALUE, Integer.MAX_VALUE);
108.75 + }
108.76 +
108.77 + @Compare public int subMinIntAndMinInt() {
108.78 + return sub(Integer.MIN_VALUE, Integer.MIN_VALUE);
108.79 + }
108.80 +
108.81 + @Compare public int multiplyMaxInt() {
108.82 + return mul(Integer.MAX_VALUE, 2);
108.83 + }
108.84 +
108.85 + @Compare public int multiplyMaxIntAndMaxInt() {
108.86 + return mul(Integer.MAX_VALUE, Integer.MAX_VALUE);
108.87 + }
108.88 +
108.89 + @Compare public int multiplyMinInt() {
108.90 + return mul(Integer.MIN_VALUE, 2);
108.91 + }
108.92 +
108.93 + @Compare public int multiplyMinIntAndMinInt() {
108.94 + return mul(Integer.MIN_VALUE, Integer.MIN_VALUE);
108.95 + }
108.96 +
108.97 + @Compare public int multiplyPrecision() {
108.98 + return mul(119106029, 1103515245);
108.99 + }
108.100 +
108.101 + @Compare public int division() {
108.102 + return div(1, 2);
108.103 + }
108.104 +
108.105 + @Compare public int divisionReminder() {
108.106 + return mod(1, 2);
108.107 + }
108.108 +
108.109 + @Compare public int negativeDivision() {
108.110 + return div(-7, 3);
108.111 + }
108.112 +
108.113 + @Compare public int negativeDivisionReminder() {
108.114 + return mod(-7, 3);
108.115 + }
108.116 +
108.117 + @Compare public int conversionFromFloat() {
108.118 + return (int) fadd(-2, -0.6f);
108.119 + }
108.120 +
108.121 + @Compare public int conversionFromDouble() {
108.122 + return (int) dadd(-2, -0.6);
108.123 + }
108.124 +
108.125 + @Compare public boolean divByZeroThrowsArithmeticException() {
108.126 + try {
108.127 + div(1, 0);
108.128 + return false;
108.129 + } catch (final ArithmeticException e) {
108.130 + return true;
108.131 + }
108.132 + }
108.133 +
108.134 + @Compare public boolean modByZeroThrowsArithmeticException() {
108.135 + try {
108.136 + mod(1, 0);
108.137 + return false;
108.138 + } catch (final ArithmeticException e) {
108.139 + return true;
108.140 + }
108.141 + }
108.142 +
108.143 + @Compare public int negate() {
108.144 + return neg(123456);
108.145 + }
108.146 +
108.147 + @Compare public int negateMaxInt() {
108.148 + return neg(Integer.MAX_VALUE);
108.149 + }
108.150 +
108.151 + @Compare public int negateMinInt() {
108.152 + return neg(Integer.MIN_VALUE);
108.153 + }
108.154 +
108.155 + @Compare public int sumTwoDimensions() {
108.156 + int[][] matrix = createMatrix(4, 3);
108.157 + matrix[0][0] += 10;
108.158 + return matrix[0][0];
108.159 + }
108.160 +
108.161 + static int[][] createMatrix(int x, int y) {
108.162 + return new int[x][y];
108.163 + }
108.164 +
108.165 + @Factory
108.166 + public static Object[] create() {
108.167 + return VMTest.create(IntegerArithmeticTest.class);
108.168 + }
108.169 +}
109.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
109.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/LongArithmeticTest.java Thu May 02 09:18:22 2013 +0200
109.3 @@ -0,0 +1,376 @@
109.4 +/**
109.5 + * Back 2 Browser Bytecode Translator
109.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
109.7 + *
109.8 + * This program is free software: you can redistribute it and/or modify
109.9 + * it under the terms of the GNU General Public License as published by
109.10 + * the Free Software Foundation, version 2 of the License.
109.11 + *
109.12 + * This program is distributed in the hope that it will be useful,
109.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
109.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
109.15 + * GNU General Public License for more details.
109.16 + *
109.17 + * You should have received a copy of the GNU General Public License
109.18 + * along with this program. Look for COPYING file in the top folder.
109.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
109.20 + */
109.21 +package org.apidesign.bck2brwsr.tck;
109.22 +
109.23 +import org.apidesign.bck2brwsr.vmtest.Compare;
109.24 +import org.apidesign.bck2brwsr.vmtest.VMTest;
109.25 +import org.testng.annotations.Factory;
109.26 +
109.27 +/**
109.28 + *
109.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
109.30 + */
109.31 +public class LongArithmeticTest {
109.32 +
109.33 + private static long add(long x, long y) {
109.34 + return (x + y);
109.35 + }
109.36 +
109.37 + private static long sub(long x, long y) {
109.38 + return (x - y);
109.39 + }
109.40 +
109.41 + private static long mul(long x, long y) {
109.42 + return (x * y);
109.43 + }
109.44 +
109.45 + private static long div(long x, long y) {
109.46 + return (x / y);
109.47 + }
109.48 +
109.49 + private static long mod(long x, long y) {
109.50 + return (x % y);
109.51 + }
109.52 +
109.53 + private static long neg(long x) {
109.54 + return (-x);
109.55 + }
109.56 +
109.57 + private static long shl(long x, int b) {
109.58 + return (x << b);
109.59 + }
109.60 +
109.61 + private static long shr(long x, int b) {
109.62 + return (x >> b);
109.63 + }
109.64 +
109.65 + private static long ushr(long x, int b) {
109.66 + return (x >>> b);
109.67 + }
109.68 +
109.69 + private static long and(long x, long y) {
109.70 + return (x & y);
109.71 + }
109.72 +
109.73 + private static long or(long x, long y) {
109.74 + return (x | y);
109.75 + }
109.76 +
109.77 + private static long xor(long x, long y) {
109.78 + return (x ^ y);
109.79 + }
109.80 +
109.81 + private static float fadd(float x, float y) {
109.82 + return x + y;
109.83 + }
109.84 +
109.85 + private static double dadd(double x, double y) {
109.86 + return x + y;
109.87 + }
109.88 +
109.89 + public static int compare(long x, long y, int zero) {
109.90 + final int xyResult = compareL(x, y, zero);
109.91 + final int yxResult = compareL(y, x, zero);
109.92 +
109.93 + return ((xyResult + yxResult) == 0) ? xyResult : -2;
109.94 + }
109.95 +
109.96 + private static int compareL(long x, long y, int zero) {
109.97 + int result = -2;
109.98 + int trueCount = 0;
109.99 +
109.100 + x += zero;
109.101 + if (x == y) {
109.102 + result = 0;
109.103 + ++trueCount;
109.104 + }
109.105 +
109.106 + x += zero;
109.107 + if (x < y) {
109.108 + result = -1;
109.109 + ++trueCount;
109.110 + }
109.111 +
109.112 + x += zero;
109.113 + if (x > y) {
109.114 + result = 1;
109.115 + ++trueCount;
109.116 + }
109.117 +
109.118 + return (trueCount == 1) ? result : -2;
109.119 + }
109.120 +
109.121 + @Compare public long conversion() {
109.122 + return Long.MAX_VALUE;
109.123 + }
109.124 +
109.125 + @Compare public long negate1() {
109.126 + return neg(0x00fa37d7763e0ca1l);
109.127 + }
109.128 +
109.129 + @Compare public long negate2() {
109.130 + return neg(0x80fa37d7763e0ca1l);
109.131 + }
109.132 +
109.133 + @Compare public long negate3() {
109.134 + return neg(0xfffffffffffffeddl);
109.135 + }
109.136 +
109.137 + @Compare public long addOverflow() {
109.138 + return add(Long.MAX_VALUE, 1l);
109.139 + }
109.140 +
109.141 + @Compare public long subUnderflow() {
109.142 + return sub(Long.MIN_VALUE, 1l);
109.143 + }
109.144 +
109.145 + @Compare public long addMaxLongAndMaxLong() {
109.146 + return add(Long.MAX_VALUE, Long.MAX_VALUE);
109.147 + }
109.148 +
109.149 + @Compare public long subMinLongAndMinLong() {
109.150 + return sub(Long.MIN_VALUE, Long.MIN_VALUE);
109.151 + }
109.152 +
109.153 + @Compare public long subMinLongAndMaxLong() {
109.154 + return sub(Long.MIN_VALUE, Long.MAX_VALUE);
109.155 + }
109.156 +
109.157 + @Compare public long multiplyMaxLong() {
109.158 + return mul(Long.MAX_VALUE, 2l);
109.159 + }
109.160 +
109.161 + @Compare public long multiplyMaxLongAndMaxLong() {
109.162 + return mul(Long.MAX_VALUE, Long.MAX_VALUE);
109.163 + }
109.164 +
109.165 + @Compare public long multiplyMinLong() {
109.166 + return mul(Long.MIN_VALUE, 2l);
109.167 + }
109.168 +
109.169 + @Compare public long multiplyMinLongAndMinLong() {
109.170 + return mul(Long.MIN_VALUE, Long.MIN_VALUE);
109.171 + }
109.172 +
109.173 + @Compare public long multiplyPrecision() {
109.174 + return mul(0x00fa37d7763e0ca1l, 0xa7b3432fff00123el);
109.175 + }
109.176 +
109.177 + @Compare public long divideSmallPositiveNumbers() {
109.178 + return div(0xabcdef, 0x123);
109.179 + }
109.180 +
109.181 + @Compare public long divideSmallNegativeNumbers() {
109.182 + return div(-0xabcdef, -0x123);
109.183 + }
109.184 +
109.185 + @Compare public long divideSmallMixedNumbers() {
109.186 + return div(0xabcdef, -0x123);
109.187 + }
109.188 +
109.189 + @Compare public long dividePositiveNumbersOneDigitDenom() {
109.190 + return div(0xabcdef0102ffffl, 0x654);
109.191 + }
109.192 +
109.193 + @Compare public long divideNegativeNumbersOneDigitDenom() {
109.194 + return div(-0xabcdef0102ffffl, -0x654);
109.195 + }
109.196 +
109.197 + @Compare public long divideMixedNumbersOneDigitDenom() {
109.198 + return div(-0xabcdef0102ffffl, 0x654);
109.199 + }
109.200 +
109.201 + @Compare public long dividePositiveNumbersMultiDigitDenom() {
109.202 + return div(0x7ffefc003322aabbl, 0x89ab1000l);
109.203 + }
109.204 +
109.205 + @Compare public long divideNegativeNumbersMultiDigitDenom() {
109.206 + return div(-0x7ffefc003322aabbl, -0x123489ab1001l);
109.207 + }
109.208 +
109.209 + @Compare public long divideMixedNumbersMultiDigitDenom() {
109.210 + return div(0x7ffefc003322aabbl, -0x38f49b0b7574e36l);
109.211 + }
109.212 +
109.213 + @Compare public long divideWithOverflow() {
109.214 + return div(0x8000fffe0000l, 0x8000ffffl);
109.215 + }
109.216 +
109.217 + @Compare public long divideWithCorrection() {
109.218 + return div(0x7fff800000000000l, 0x800000000001l);
109.219 + }
109.220 +
109.221 + @Compare public long moduloSmallPositiveNumbers() {
109.222 + return mod(0xabcdef, 0x123);
109.223 + }
109.224 +
109.225 + @Compare public long moduloSmallNegativeNumbers() {
109.226 + return mod(-0xabcdef, -0x123);
109.227 + }
109.228 +
109.229 + @Compare public long moduloSmallMixedNumbers() {
109.230 + return mod(0xabcdef, -0x123);
109.231 + }
109.232 +
109.233 + @Compare public long moduloPositiveNumbersOneDigitDenom() {
109.234 + return mod(0xabcdef0102ffffl, 0x654);
109.235 + }
109.236 +
109.237 + @Compare public long moduloNegativeNumbersOneDigitDenom() {
109.238 + return mod(-0xabcdef0102ffffl, -0x654);
109.239 + }
109.240 +
109.241 + @Compare public long moduloMixedNumbersOneDigitDenom() {
109.242 + return mod(-0xabcdef0102ffffl, 0x654);
109.243 + }
109.244 +
109.245 + @Compare public long moduloPositiveNumbersMultiDigitDenom() {
109.246 + return mod(0x7ffefc003322aabbl, 0x89ab1000l);
109.247 + }
109.248 +
109.249 + @Compare public long moduloNegativeNumbersMultiDigitDenom() {
109.250 + return mod(-0x7ffefc003322aabbl, -0x123489ab1001l);
109.251 + }
109.252 +
109.253 + @Compare public long moduloMixedNumbersMultiDigitDenom() {
109.254 + return mod(0x7ffefc003322aabbl, -0x38f49b0b7574e36l);
109.255 + }
109.256 +
109.257 + @Compare public long moduloWithOverflow() {
109.258 + return mod(0x8000fffe0000l, 0x8000ffffl);
109.259 + }
109.260 +
109.261 + @Compare public long moduloWithCorrection() {
109.262 + return mod(0x7fff800000000000l, 0x800000000001l);
109.263 + }
109.264 +
109.265 + @Compare public long conversionFromFloatPositive() {
109.266 + return (long) fadd(2, 0.6f);
109.267 + }
109.268 +
109.269 + @Compare public long conversionFromFloatNegative() {
109.270 + return (long) fadd(-2, -0.6f);
109.271 + }
109.272 +
109.273 + @Compare public long conversionFromDoublePositive() {
109.274 + return (long) dadd(0x20ffff0000L, 0.6);
109.275 + }
109.276 +
109.277 + @Compare public long conversionFromDoubleNegative() {
109.278 + return (long) dadd(-0x20ffff0000L, -0.6);
109.279 + }
109.280 +
109.281 + @Compare public boolean divByZeroThrowsArithmeticException() {
109.282 + try {
109.283 + div(1, 0);
109.284 + return false;
109.285 + } catch (final ArithmeticException e) {
109.286 + return true;
109.287 + }
109.288 + }
109.289 +
109.290 + @Compare public boolean modByZeroThrowsArithmeticException() {
109.291 + try {
109.292 + mod(1, 0);
109.293 + return false;
109.294 + } catch (final ArithmeticException e) {
109.295 + return true;
109.296 + }
109.297 + }
109.298 +
109.299 + @Compare public long shiftL1() {
109.300 + return shl(0x00fa37d7763e0ca1l, 5);
109.301 + }
109.302 +
109.303 + @Compare public long shiftL2() {
109.304 + return shl(0x00fa37d7763e0ca1l, 32);
109.305 + }
109.306 +
109.307 + @Compare public long shiftL3() {
109.308 + return shl(0x00fa37d7763e0ca1l, 45);
109.309 + }
109.310 +
109.311 + @Compare public long shiftR1() {
109.312 + return shr(0x00fa37d7763e0ca1l, 5);
109.313 + }
109.314 +
109.315 + @Compare public long shiftR2() {
109.316 + return shr(0x00fa37d7763e0ca1l, 32);
109.317 + }
109.318 +
109.319 + @Compare public long shiftR3() {
109.320 + return shr(0x00fa37d7763e0ca1l, 45);
109.321 + }
109.322 +
109.323 + @Compare public long uShiftR1() {
109.324 + return ushr(0x00fa37d7763e0ca1l, 5);
109.325 + }
109.326 +
109.327 + @Compare public long uShiftR2() {
109.328 + return ushr(0x00fa37d7763e0ca1l, 45);
109.329 + }
109.330 +
109.331 + @Compare public long uShiftR3() {
109.332 + return ushr(0xf0fa37d7763e0ca1l, 5);
109.333 + }
109.334 +
109.335 + @Compare public long uShiftR4() {
109.336 + return ushr(0xf0fa37d7763e0ca1l, 45);
109.337 + }
109.338 +
109.339 + @Compare public long and1() {
109.340 + return and(0x00fa37d7763e0ca1l, 0xa7b3432fff00123el);
109.341 + }
109.342 +
109.343 + @Compare public long or1() {
109.344 + return or(0x00fa37d7763e0ca1l, 0xa7b3432fff00123el);
109.345 + }
109.346 +
109.347 + @Compare public long xor1() {
109.348 + return xor(0x00fa37d7763e0ca1l, 0xa7b3432fff00123el);
109.349 + }
109.350 +
109.351 + @Compare public long xor2() {
109.352 + return xor(0x00fa37d7763e0ca1l, 0x00000000ff00123el);
109.353 + }
109.354 +
109.355 + @Compare public long xor3() {
109.356 + return xor(0x00000000763e0ca1l, 0x00000000ff00123el);
109.357 + }
109.358 +
109.359 + @Compare public int compareSameNumbers() {
109.360 + return compare(0x0000000000000000l, 0x0000000000000000l, 0);
109.361 + }
109.362 +
109.363 + @Compare public int comparePositiveNumbers() {
109.364 + return compare(0x0000000000200000l, 0x0000000010000000l, 0);
109.365 + }
109.366 +
109.367 + @Compare public int compareNegativeNumbers() {
109.368 + return compare(0xffffffffffffffffl, 0xffffffff00000000l, 0);
109.369 + }
109.370 +
109.371 + @Compare public int compareMixedNumbers() {
109.372 + return compare(0x8000000000000000l, 0x7fffffffffffffffl, 0);
109.373 + }
109.374 +
109.375 + @Factory
109.376 + public static Object[] create() {
109.377 + return VMTest.create(LongArithmeticTest.class);
109.378 + }
109.379 +}
110.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
110.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/ReflectionArrayTest.java Thu May 02 09:18:22 2013 +0200
110.3 @@ -0,0 +1,161 @@
110.4 +/**
110.5 + * Back 2 Browser Bytecode Translator
110.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
110.7 + *
110.8 + * This program is free software: you can redistribute it and/or modify
110.9 + * it under the terms of the GNU General Public License as published by
110.10 + * the Free Software Foundation, version 2 of the License.
110.11 + *
110.12 + * This program is distributed in the hope that it will be useful,
110.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
110.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
110.15 + * GNU General Public License for more details.
110.16 + *
110.17 + * You should have received a copy of the GNU General Public License
110.18 + * along with this program. Look for COPYING file in the top folder.
110.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
110.20 + */
110.21 +package org.apidesign.bck2brwsr.tck;
110.22 +
110.23 +import java.lang.reflect.Array;
110.24 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
110.25 +import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
110.26 +import org.apidesign.bck2brwsr.vmtest.Compare;
110.27 +import org.apidesign.bck2brwsr.vmtest.VMTest;
110.28 +import org.testng.annotations.Factory;
110.29 +
110.30 +/**
110.31 + *
110.32 + * @author Jaroslav Tulach <jtulach@netbeans.org>
110.33 + */
110.34 +public class ReflectionArrayTest {
110.35 + @Compare public int lengthOfStringArray() {
110.36 + String[] arr = (String[]) Array.newInstance(String.class, 10);
110.37 + return arr.length;
110.38 + }
110.39 +
110.40 + @Compare public int reflectiveLengthOfStringArray() {
110.41 + Object arr = Array.newInstance(String.class, 10);
110.42 + return Array.getLength(arr);
110.43 + }
110.44 +
110.45 + @Compare public int reflectiveLengthOneNonArray() {
110.46 + Object arr = "non-array";
110.47 + return Array.getLength(arr);
110.48 + }
110.49 +
110.50 + @Compare public String compTypeOfStringArray() {
110.51 + String[] arr = (String[]) Array.newInstance(String.class, 10);
110.52 + return arr.getClass().getComponentType().getName();
110.53 + }
110.54 +
110.55 + @Compare public Object negativeArrayExcp() {
110.56 + return Array.newInstance(String.class, -5);
110.57 + }
110.58 +
110.59 + @Compare public int lengthOfIntArray() {
110.60 + int[] arr = (int[]) Array.newInstance(Integer.TYPE, 10);
110.61 + return arr.length;
110.62 + }
110.63 +
110.64 + @Compare public int reflectiveLengthOfIntArray() {
110.65 + Object arr = Array.newInstance(Integer.TYPE, 10);
110.66 + return Array.getLength(arr);
110.67 + }
110.68 +
110.69 + @Compare public String compTypeOfIntArray() {
110.70 + int[] arr = (int[]) Array.newInstance(int.class, 10);
110.71 + return arr.getClass().getComponentType().getName();
110.72 + }
110.73 +
110.74 + @Compare public Object intNegativeArrayExcp() {
110.75 + return Array.newInstance(int.class, -5);
110.76 + }
110.77 +
110.78 + @Compare public Integer verifyAutobox() {
110.79 + int[] arr = (int[]) Array.newInstance(int.class, 5);
110.80 + return (Integer) Array.get(arr, 0);
110.81 + }
110.82 + @Compare public String verifyObjectArray() {
110.83 + String[] arr = (String[]) Array.newInstance(String.class, 5);
110.84 + Array.set(arr, 0, "Hello");
110.85 + return (String) Array.get(arr, 0);
110.86 + }
110.87 + @Compare public int verifyInt() {
110.88 + int[] arr = (int[]) Array.newInstance(int.class, 5);
110.89 + return Array.getInt(arr, 0);
110.90 + }
110.91 + @Compare public long verifyConvertToLong() {
110.92 + int[] arr = (int[]) Array.newInstance(int.class, 5);
110.93 + return Array.getLong(arr, 0);
110.94 + }
110.95 +
110.96 + @Compare public Object verifySetIntToObject() {
110.97 + try {
110.98 + Object[] arr = (Object[]) Array.newInstance(Object.class, 5);
110.99 + Array.setInt(arr, 0, 10);
110.100 + return Array.get(arr, 0);
110.101 + } catch (Exception exception) {
110.102 + return exception.getClass().getName();
110.103 + }
110.104 + }
110.105 + @Compare public long verifySetShort() {
110.106 + int[] arr = (int[]) Array.newInstance(int.class, 5);
110.107 + Array.setShort(arr, 0, (short)10);
110.108 + return Array.getLong(arr, 0);
110.109 + }
110.110 + @Compare public long verifyCantSetLong() {
110.111 + int[] arr = (int[]) Array.newInstance(int.class, 5);
110.112 + Array.setLong(arr, 0, 10);
110.113 + return Array.getLong(arr, 0);
110.114 + }
110.115 + @Compare public float verifyLongToFloat() {
110.116 + Object arr = Array.newInstance(float.class, 5);
110.117 + Array.setLong(arr, 0, 10);
110.118 + return Array.getFloat(arr, 0);
110.119 + }
110.120 +
110.121 + @Compare public double verifyConvertToDouble() {
110.122 + int[] arr = (int[]) Array.newInstance(int.class, 5);
110.123 + return Array.getDouble(arr, 0);
110.124 + }
110.125 +
110.126 + @Compare public int multiIntArray() {
110.127 + int[][][] arr = (int[][][]) Array.newInstance(int.class, 3, 3, 3);
110.128 + return arr[0][1][2] + 5 + arr[2][2][0];
110.129 + }
110.130 +
110.131 + @Compare public String multiIntArrayCompType() {
110.132 + return Array.newInstance(int.class, 3, 3, 3).getClass().getName();
110.133 + }
110.134 +
110.135 + @JavaScriptBody(args = {}, body = "return [1, 2];")
110.136 + private static native Object crtarr();
110.137 +
110.138 + @JavaScriptBody(args = {}, body = "return new Object();")
110.139 + private static native Object newobj();
110.140 +
110.141 + @BrwsrTest
110.142 + public static void toStringArray() {
110.143 + final Object arr = crtarr();
110.144 + final Object real = new Object[2];
110.145 + assert arr instanceof Object[] : "Any array is Java array: " + arr;
110.146 + assert arr.getClass() == real.getClass() : "Same classes " + arr + " and " + real.getClass();
110.147 + final String str = arr.toString();
110.148 + assert str != null;
110.149 + assert str.startsWith("[Ljava.lang.Object;@") : str;
110.150 + }
110.151 +
110.152 + @BrwsrTest
110.153 + public static void objectToString() {
110.154 + String s = newobj().toString();
110.155 + assert s != null : "Some string computed";
110.156 + assert s.startsWith("java.lang.Object@") : "Regular object toString(): " + s;
110.157 + }
110.158 +
110.159 +
110.160 + @Factory
110.161 + public static Object[] create() {
110.162 + return VMTest.create(ReflectionArrayTest.class);
110.163 + }
110.164 +}
111.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
111.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/ReflectionTest.java Thu May 02 09:18:22 2013 +0200
111.3 @@ -0,0 +1,272 @@
111.4 +/**
111.5 + * Back 2 Browser Bytecode Translator
111.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
111.7 + *
111.8 + * This program is free software: you can redistribute it and/or modify
111.9 + * it under the terms of the GNU General Public License as published by
111.10 + * the Free Software Foundation, version 2 of the License.
111.11 + *
111.12 + * This program is distributed in the hope that it will be useful,
111.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
111.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
111.15 + * GNU General Public License for more details.
111.16 + *
111.17 + * You should have received a copy of the GNU General Public License
111.18 + * along with this program. Look for COPYING file in the top folder.
111.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
111.20 + */
111.21 +package org.apidesign.bck2brwsr.tck;
111.22 +
111.23 +import java.lang.annotation.Retention;
111.24 +import java.lang.annotation.RetentionPolicy;
111.25 +import java.lang.reflect.Method;
111.26 +import java.util.Arrays;
111.27 +import java.util.Collections;
111.28 +import java.util.List;
111.29 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
111.30 +import org.apidesign.bck2brwsr.vmtest.Compare;
111.31 +import org.apidesign.bck2brwsr.vmtest.VMTest;
111.32 +import org.testng.annotations.Factory;
111.33 +
111.34 +/**
111.35 + *
111.36 + * @author Jaroslav Tulach <jtulach@netbeans.org>
111.37 + */
111.38 +public class ReflectionTest {
111.39 + @Compare public boolean nonNullThis() {
111.40 + return this == null;
111.41 + }
111.42 +
111.43 + @Compare public String intType() {
111.44 + return Integer.TYPE.toString();
111.45 + }
111.46 +
111.47 + @Compare public String voidType() throws Exception {
111.48 + return void.class.toString();
111.49 + }
111.50 +
111.51 + @Compare public String longClass() {
111.52 + return long.class.toString();
111.53 + }
111.54 +
111.55 + @Compare public boolean isRunnableInterface() {
111.56 + return Runnable.class.isInterface();
111.57 + }
111.58 +
111.59 + @Compare public boolean isAssignableToPrimitiveType() {
111.60 + return boolean.class.isAssignableFrom(Runnable.class);
111.61 + }
111.62 +
111.63 + @Compare public boolean isAssignableFromPrimitiveType() {
111.64 + return Runnable.class.isAssignableFrom(boolean.class);
111.65 + }
111.66 +
111.67 + @Compare public boolean isAssignableLongFromInt() {
111.68 + return long.class.isAssignableFrom(int.class);
111.69 + }
111.70 +
111.71 + @Compare public boolean isAssignableIntFromLong() {
111.72 + return int.class.isAssignableFrom(long.class);
111.73 + }
111.74 +
111.75 + @Compare public String isRunnableHasRunMethod() throws NoSuchMethodException {
111.76 + return Runnable.class.getMethod("run").getName();
111.77 + }
111.78 +
111.79 + @Compare public String namesOfMethods() {
111.80 + StringBuilder sb = new StringBuilder();
111.81 + String[] arr = new String[20];
111.82 + int i = 0;
111.83 + for (Method m : StaticUse.class.getMethods()) {
111.84 + arr[i++] = m.getName();
111.85 + }
111.86 + for (String s : sort(arr, i)) {
111.87 + sb.append(s).append("\n");
111.88 + }
111.89 + return sb.toString();
111.90 + }
111.91 +
111.92 + @Compare public String namesOfDeclaringClassesOfMethods() {
111.93 + StringBuilder sb = new StringBuilder();
111.94 + String[] arr = new String[20];
111.95 + int i = 0;
111.96 + for (Method m : StaticUse.class.getMethods()) {
111.97 + arr[i++] = m.getName() + "@" + m.getDeclaringClass().getName();
111.98 + }
111.99 + for (String s : sort(arr, i)) {
111.100 + sb.append(s).append("\n");
111.101 + }
111.102 + return sb.toString();
111.103 + }
111.104 +
111.105 + @Compare public String cannotCallNonStaticMethodWithNull() throws Exception {
111.106 + StaticUse.class.getMethod("instanceMethod").invoke(null);
111.107 + return "should not happen";
111.108 + }
111.109 +
111.110 + @Compare public String classCastException() {
111.111 + try {
111.112 + Integer i = (Integer)StaticUseSub.getNonNull();
111.113 + return "" + i.intValue();
111.114 + } catch (ClassCastException ex) {
111.115 + return ex.getClass().getName();
111.116 + }
111.117 + }
111.118 +
111.119 + @Compare public String methodThatThrowsException() throws Exception {
111.120 + StaticUse.class.getMethod("instanceMethod").invoke(new StaticUse());
111.121 + return "should not happen";
111.122 + }
111.123 +
111.124 + @Compare public Object voidReturnType() throws Exception {
111.125 + return StaticUse.class.getMethod("instanceMethod").getReturnType();
111.126 + }
111.127 +
111.128 + @Retention(RetentionPolicy.RUNTIME)
111.129 + @interface Ann {
111.130 + }
111.131 +
111.132 + @Compare public String annoClass() throws Exception {
111.133 + Retention r = Ann.class.getAnnotation(Retention.class);
111.134 + assert r != null : "Annotation is present";
111.135 + assert r.value() == RetentionPolicy.RUNTIME : "Policy value is OK: " + r.value();
111.136 + return r.annotationType().getName();
111.137 + }
111.138 +
111.139 + @Compare public boolean isAnnotation() {
111.140 + return Ann.class.isAnnotation();
111.141 + }
111.142 + @Compare public boolean isNotAnnotation() {
111.143 + return String.class.isAnnotation();
111.144 + }
111.145 + @Compare public boolean isNotAnnotationEnum() {
111.146 + return E.class.isAnnotation();
111.147 + }
111.148 + enum E { A, B };
111.149 + @Compare public boolean isEnum() {
111.150 + return E.A.getClass().isEnum();
111.151 + }
111.152 +
111.153 + @Compare public boolean isNotEnum() {
111.154 + return "".getClass().isEnum();
111.155 + }
111.156 +
111.157 + @Compare public String newInstanceFails() throws InstantiationException {
111.158 + try {
111.159 + return "success: " + StaticUseSub.class.newInstance();
111.160 + } catch (IllegalAccessException ex) {
111.161 + return ex.getClass().getName();
111.162 + }
111.163 + }
111.164 +
111.165 + @Compare public String paramTypes() throws Exception {
111.166 + Method plus = StaticUse.class.getMethod("plus", int.class, Integer.TYPE);
111.167 + final Class[] pt = plus.getParameterTypes();
111.168 + return pt[0].getName();
111.169 + }
111.170 + @Compare public String paramTypesNotFound() throws Exception {
111.171 + return StaticUse.class.getMethod("plus", int.class, double.class).toString();
111.172 + }
111.173 + @Compare public int methodWithArgs() throws Exception {
111.174 + Method plus = StaticUse.class.getMethod("plus", int.class, Integer.TYPE);
111.175 + return (Integer)plus.invoke(null, 2, 3);
111.176 + }
111.177 +
111.178 + @Compare public String classGetNameForByte() {
111.179 + return byte.class.getName();
111.180 + }
111.181 + @Compare public String classGetNameForBaseObject() {
111.182 + return newObject().getClass().getName();
111.183 + }
111.184 + @Compare public String classGetNameForJavaObject() {
111.185 + return new Object().getClass().getName();
111.186 + }
111.187 + @Compare public String classGetNameForObjectArray() {
111.188 + return (new Object[3]).getClass().getName();
111.189 + }
111.190 + @Compare public String classGetNameForSimpleIntArray() {
111.191 + return (new int[3]).getClass().getName();
111.192 + }
111.193 + @Compare public boolean sameClassGetNameForSimpleCharArray() {
111.194 + return (new char[3]).getClass() == (new char[34]).getClass();
111.195 + }
111.196 + @Compare public String classGetNameForMultiIntArray() {
111.197 + return (new int[3][4][5][6][7][8][9]).getClass().getName();
111.198 + }
111.199 + @Compare public String classGetNameForMultiIntArrayInner() {
111.200 + final int[][][][][][][] arr = new int[3][4][5][6][7][8][9];
111.201 + int[][][][][][] subarr = arr[0];
111.202 + int[][][][][] subsubarr = subarr[0];
111.203 + return subsubarr.getClass().getName();
111.204 + }
111.205 + @Compare public String classGetNameForMultiStringArray() {
111.206 + return (new String[3][4][5][6][7][8][9]).getClass().getName();
111.207 + }
111.208 +
111.209 + @Compare public String classForByte() throws Exception {
111.210 + return Class.forName("[Z").getName();
111.211 + }
111.212 +
111.213 + @Compare public String classForUnknownArray() {
111.214 + try {
111.215 + return Class.forName("[W").getName();
111.216 + } catch (Exception ex) {
111.217 + return ex.getClass().getName();
111.218 + }
111.219 + }
111.220 +
111.221 + @Compare public String classForUnknownDeepArray() {
111.222 + try {
111.223 + return Class.forName("[[[[[W").getName();
111.224 + } catch (Exception ex) {
111.225 + return ex.getClass().getName();
111.226 + }
111.227 + }
111.228 +
111.229 + @Compare public String componentGetNameForObjectArray() {
111.230 + return (new Object[3]).getClass().getComponentType().getName();
111.231 + }
111.232 + @Compare public boolean sameComponentGetNameForObjectArray() {
111.233 + return (new Object[3]).getClass().getComponentType() == Object.class;
111.234 + }
111.235 + @Compare public String componentGetNameForSimpleIntArray() {
111.236 + return (new int[3]).getClass().getComponentType().getName();
111.237 + }
111.238 + @Compare public String componentGetNameForMultiIntArray() {
111.239 + return (new int[3][4][5][6][7][8][9]).getClass().getComponentType().getName();
111.240 + }
111.241 + @Compare public String componentGetNameForMultiStringArray() {
111.242 + Class<?> c = (new String[3][4][5][6][7][8][9]).getClass();
111.243 + StringBuilder sb = new StringBuilder();
111.244 + for (;;) {
111.245 + sb.append(c.getName()).append("\n");
111.246 + c = c.getComponentType();
111.247 + if (c == null) {
111.248 + break;
111.249 + }
111.250 + }
111.251 + return sb.toString();
111.252 + }
111.253 +
111.254 + @Compare public boolean isArray() {
111.255 + return new Object[0].getClass().isArray();
111.256 + }
111.257 +
111.258 + @JavaScriptBody(args = { "arr", "len" }, body="var a = arr.slice(0, len); a.sort(); return a;")
111.259 + private static String[] sort(String[] arr, int len) {
111.260 + List<String> list = Arrays.asList(arr).subList(0, len);
111.261 + Collections.sort(list);
111.262 + return list.toArray(new String[0]);
111.263 + }
111.264 +
111.265 + @JavaScriptBody(args = {}, body = "return new Object();")
111.266 + private static Object newObject() {
111.267 + return new Object();
111.268 + }
111.269 +
111.270 + @Factory
111.271 + public static Object[] create() {
111.272 + return VMTest.create(ReflectionTest.class);
111.273 + }
111.274 +
111.275 +}
112.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
112.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/ResourcesTest.java Thu May 02 09:18:22 2013 +0200
112.3 @@ -0,0 +1,45 @@
112.4 +/**
112.5 + * Back 2 Browser Bytecode Translator
112.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
112.7 + *
112.8 + * This program is free software: you can redistribute it and/or modify
112.9 + * it under the terms of the GNU General Public License as published by
112.10 + * the Free Software Foundation, version 2 of the License.
112.11 + *
112.12 + * This program is distributed in the hope that it will be useful,
112.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
112.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
112.15 + * GNU General Public License for more details.
112.16 + *
112.17 + * You should have received a copy of the GNU General Public License
112.18 + * along with this program. Look for COPYING file in the top folder.
112.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
112.20 + */
112.21 +package org.apidesign.bck2brwsr.tck;
112.22 +
112.23 +import java.io.InputStream;
112.24 +import org.apidesign.bck2brwsr.vmtest.Compare;
112.25 +import org.apidesign.bck2brwsr.vmtest.VMTest;
112.26 +import org.testng.annotations.Factory;
112.27 +
112.28 +/**
112.29 + *
112.30 + * @author Jaroslav Tulach <jtulach@netbeans.org>
112.31 + */
112.32 +public class ResourcesTest {
112.33 +
112.34 + @Compare public String readResourceAsStream() throws Exception {
112.35 + InputStream is = getClass().getResourceAsStream("Resources.txt");
112.36 + byte[] b = new byte[30];
112.37 + int len = is.read(b);
112.38 + StringBuilder sb = new StringBuilder();
112.39 + for (int i = 0; i < len; i++) {
112.40 + sb.append((char)b[i]);
112.41 + }
112.42 + return sb.toString();
112.43 + }
112.44 +
112.45 + @Factory public static Object[] create() {
112.46 + return VMTest.create(ResourcesTest.class);
112.47 + }
112.48 +}
113.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
113.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/ShortArithmeticTest.java Thu May 02 09:18:22 2013 +0200
113.3 @@ -0,0 +1,102 @@
113.4 +/**
113.5 + * Back 2 Browser Bytecode Translator
113.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
113.7 + *
113.8 + * This program is free software: you can redistribute it and/or modify
113.9 + * it under the terms of the GNU General Public License as published by
113.10 + * the Free Software Foundation, version 2 of the License.
113.11 + *
113.12 + * This program is distributed in the hope that it will be useful,
113.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
113.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
113.15 + * GNU General Public License for more details.
113.16 + *
113.17 + * You should have received a copy of the GNU General Public License
113.18 + * along with this program. Look for COPYING file in the top folder.
113.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
113.20 + */
113.21 +package org.apidesign.bck2brwsr.tck;
113.22 +
113.23 +import org.apidesign.bck2brwsr.vmtest.Compare;
113.24 +import org.apidesign.bck2brwsr.vmtest.VMTest;
113.25 +import org.testng.annotations.Factory;
113.26 +
113.27 +/**
113.28 + *
113.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
113.30 + */
113.31 +public class ShortArithmeticTest {
113.32 +
113.33 + private static short add(short x, short y) {
113.34 + return (short)(x + y);
113.35 + }
113.36 +
113.37 + private static short sub(short x, short y) {
113.38 + return (short)(x - y);
113.39 + }
113.40 +
113.41 + private static short mul(short x, short y) {
113.42 + return (short)(x * y);
113.43 + }
113.44 +
113.45 + private static short div(short x, short y) {
113.46 + return (short)(x / y);
113.47 + }
113.48 +
113.49 + private static short mod(short x, short y) {
113.50 + return (short)(x % y);
113.51 + }
113.52 +
113.53 + @Compare public short conversion() {
113.54 + return (short)123456;
113.55 + }
113.56 +
113.57 + @Compare public short addOverflow() {
113.58 + return add(Short.MAX_VALUE, (short)1);
113.59 + }
113.60 +
113.61 + @Compare public short subUnderflow() {
113.62 + return sub(Short.MIN_VALUE, (short)1);
113.63 + }
113.64 +
113.65 + @Compare public short addMaxShortAndMaxShort() {
113.66 + return add(Short.MAX_VALUE, Short.MAX_VALUE);
113.67 + }
113.68 +
113.69 + @Compare public short subMinShortAndMinShort() {
113.70 + return sub(Short.MIN_VALUE, Short.MIN_VALUE);
113.71 + }
113.72 +
113.73 + @Compare public short multiplyMaxShort() {
113.74 + return mul(Short.MAX_VALUE, (short)2);
113.75 + }
113.76 +
113.77 + @Compare public short multiplyMaxShortAndMaxShort() {
113.78 + return mul(Short.MAX_VALUE, Short.MAX_VALUE);
113.79 + }
113.80 +
113.81 + @Compare public short multiplyMinShort() {
113.82 + return mul(Short.MIN_VALUE, (short)2);
113.83 + }
113.84 +
113.85 + @Compare public short multiplyMinShortAndMinShort() {
113.86 + return mul(Short.MIN_VALUE, Short.MIN_VALUE);
113.87 + }
113.88 +
113.89 + @Compare public short multiplyPrecision() {
113.90 + return mul((short)17638, (short)1103);
113.91 + }
113.92 +
113.93 + @Compare public short division() {
113.94 + return div((short)1, (short)2);
113.95 + }
113.96 +
113.97 + @Compare public short divisionReminder() {
113.98 + return mod((short)1, (short)2);
113.99 + }
113.100 +
113.101 + @Factory
113.102 + public static Object[] create() {
113.103 + return VMTest.create(ShortArithmeticTest.class);
113.104 + }
113.105 +}
114.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
114.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/StaticUse.java Thu May 02 09:18:22 2013 +0200
114.3 @@ -0,0 +1,39 @@
114.4 +/**
114.5 + * Back 2 Browser Bytecode Translator
114.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
114.7 + *
114.8 + * This program is free software: you can redistribute it and/or modify
114.9 + * it under the terms of the GNU General Public License as published by
114.10 + * the Free Software Foundation, version 2 of the License.
114.11 + *
114.12 + * This program is distributed in the hope that it will be useful,
114.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
114.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
114.15 + * GNU General Public License for more details.
114.16 + *
114.17 + * You should have received a copy of the GNU General Public License
114.18 + * along with this program. Look for COPYING file in the top folder.
114.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
114.20 + */
114.21 +package org.apidesign.bck2brwsr.tck;
114.22 +
114.23 +class StaticUse {
114.24 + public static final Object NON_NULL = new Object();
114.25 + public static int cnt;
114.26 + static {
114.27 + if (cnt++ != 0) {
114.28 + throw new IllegalStateException("Multiple initialization of a <cinit>");
114.29 + }
114.30 + }
114.31 +
114.32 + StaticUse() {
114.33 + }
114.34 +
114.35 + public void instanceMethod() {
114.36 + throw new IllegalStateException();
114.37 + }
114.38 +
114.39 + public static int plus(int a, int b) {
114.40 + return a + b;
114.41 + }
114.42 +}
115.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
115.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/StaticUseSub.java Thu May 02 09:18:22 2013 +0200
115.3 @@ -0,0 +1,30 @@
115.4 +/**
115.5 + * Back 2 Browser Bytecode Translator
115.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
115.7 + *
115.8 + * This program is free software: you can redistribute it and/or modify
115.9 + * it under the terms of the GNU General Public License as published by
115.10 + * the Free Software Foundation, version 2 of the License.
115.11 + *
115.12 + * This program is distributed in the hope that it will be useful,
115.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
115.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
115.15 + * GNU General Public License for more details.
115.16 + *
115.17 + * You should have received a copy of the GNU General Public License
115.18 + * along with this program. Look for COPYING file in the top folder.
115.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
115.20 + */
115.21 +package org.apidesign.bck2brwsr.tck;
115.22 +
115.23 +public class StaticUseSub extends StaticUse {
115.24 + private StaticUseSub() {
115.25 + }
115.26 +
115.27 + public static Object getNonNull() {
115.28 + return NON_NULL;
115.29 + }
115.30 + static Object getNull() {
115.31 + return null;
115.32 + }
115.33 +}
116.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
116.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/StaticUseSubTest.java Thu May 02 09:18:22 2013 +0200
116.3 @@ -0,0 +1,45 @@
116.4 +/**
116.5 + * Back 2 Browser Bytecode Translator
116.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
116.7 + *
116.8 + * This program is free software: you can redistribute it and/or modify
116.9 + * it under the terms of the GNU General Public License as published by
116.10 + * the Free Software Foundation, version 2 of the License.
116.11 + *
116.12 + * This program is distributed in the hope that it will be useful,
116.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
116.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
116.15 + * GNU General Public License for more details.
116.16 + *
116.17 + * You should have received a copy of the GNU General Public License
116.18 + * along with this program. Look for COPYING file in the top folder.
116.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
116.20 + */
116.21 +package org.apidesign.bck2brwsr.tck;
116.22 +
116.23 +import org.apidesign.bck2brwsr.vmtest.Compare;
116.24 +import org.apidesign.bck2brwsr.vmtest.VMTest;
116.25 +import org.testng.annotations.Factory;
116.26 +
116.27 +/**
116.28 + *
116.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
116.30 + */
116.31 +public class StaticUseSubTest {
116.32 + @Compare public String staticFieldInitializationInSuperClass() throws Exception {
116.33 + Object ret = StaticUseSub.getNonNull();
116.34 + return ret.getClass().getName();
116.35 + }
116.36 +
116.37 + @Compare public String isNullPointerTheSame() throws Exception {
116.38 + try {
116.39 + return StaticUseSub.getNull().getClass().toString();
116.40 + } catch (NullPointerException ex) {
116.41 + return ex.getClass().getName();
116.42 + }
116.43 + }
116.44 +
116.45 + @Factory public static Object[] create() {
116.46 + return VMTest.create(StaticUseSubTest.class);
116.47 + }
116.48 +}
117.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
117.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/CRC32Test.java Thu May 02 09:18:22 2013 +0200
117.3 @@ -0,0 +1,41 @@
117.4 +/**
117.5 + * Back 2 Browser Bytecode Translator
117.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
117.7 + *
117.8 + * This program is free software: you can redistribute it and/or modify
117.9 + * it under the terms of the GNU General Public License as published by
117.10 + * the Free Software Foundation, version 2 of the License.
117.11 + *
117.12 + * This program is distributed in the hope that it will be useful,
117.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
117.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
117.15 + * GNU General Public License for more details.
117.16 + *
117.17 + * You should have received a copy of the GNU General Public License
117.18 + * along with this program. Look for COPYING file in the top folder.
117.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
117.20 + */
117.21 +package org.apidesign.bck2brwsr.vmtest.impl;
117.22 +
117.23 +import java.io.UnsupportedEncodingException;
117.24 +import java.util.zip.CRC32;
117.25 +import org.apidesign.bck2brwsr.vmtest.Compare;
117.26 +import org.apidesign.bck2brwsr.vmtest.VMTest;
117.27 +import org.testng.annotations.Factory;
117.28 +
117.29 +/**
117.30 + *
117.31 + * @author Jaroslav Tulach <jtulach@netbeans.org>
117.32 + */
117.33 +public class CRC32Test {
117.34 +
117.35 + @Compare public long crc1() throws UnsupportedEncodingException {
117.36 + CRC32 crc = new CRC32();
117.37 + crc.update("Hello World!".getBytes("UTF-8"));
117.38 + return crc.getValue();
117.39 + }
117.40 +
117.41 + @Factory public static Object[] create() {
117.42 + return VMTest.create(CRC32Test.class);
117.43 + }
117.44 +}
118.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
118.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/CallMeTwiceTest.java Thu May 02 09:18:22 2013 +0200
118.3 @@ -0,0 +1,43 @@
118.4 +/**
118.5 + * Back 2 Browser Bytecode Translator
118.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
118.7 + *
118.8 + * This program is free software: you can redistribute it and/or modify
118.9 + * it under the terms of the GNU General Public License as published by
118.10 + * the Free Software Foundation, version 2 of the License.
118.11 + *
118.12 + * This program is distributed in the hope that it will be useful,
118.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
118.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
118.15 + * GNU General Public License for more details.
118.16 + *
118.17 + * You should have received a copy of the GNU General Public License
118.18 + * along with this program. Look for COPYING file in the top folder.
118.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
118.20 + */
118.21 +package org.apidesign.bck2brwsr.vmtest.impl;
118.22 +
118.23 +import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
118.24 +import org.apidesign.bck2brwsr.vmtest.VMTest;
118.25 +import org.testng.annotations.Factory;
118.26 +
118.27 +/**
118.28 + *
118.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
118.30 + */
118.31 +public class CallMeTwiceTest {
118.32 + int cnt;
118.33 +
118.34 + @BrwsrTest public void callMeTwice() throws InterruptedException {
118.35 + if (cnt++ == 0) {
118.36 + throw new InterruptedException();
118.37 + }
118.38 + int prevCnt = cnt;
118.39 + cnt = 0;
118.40 + assert prevCnt == 2 : "We need to receive two calls " + prevCnt;
118.41 + }
118.42 +
118.43 + @Factory public static Object[] create() {
118.44 + return VMTest.create(CallMeTwiceTest.class);
118.45 + }
118.46 +}
119.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
119.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/ZipEntryTest.java Thu May 02 09:18:22 2013 +0200
119.3 @@ -0,0 +1,67 @@
119.4 +/**
119.5 + * Back 2 Browser Bytecode Translator
119.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
119.7 + *
119.8 + * This program is free software: you can redistribute it and/or modify
119.9 + * it under the terms of the GNU General Public License as published by
119.10 + * the Free Software Foundation, version 2 of the License.
119.11 + *
119.12 + * This program is distributed in the hope that it will be useful,
119.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
119.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
119.15 + * GNU General Public License for more details.
119.16 + *
119.17 + * You should have received a copy of the GNU General Public License
119.18 + * along with this program. Look for COPYING file in the top folder.
119.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
119.20 + */
119.21 +package org.apidesign.bck2brwsr.vmtest.impl;
119.22 +
119.23 +import java.io.ByteArrayInputStream;
119.24 +import java.io.IOException;
119.25 +import java.io.InputStream;
119.26 +import org.apidesign.bck2brwsr.emul.zip.FastJar;
119.27 +import org.testng.annotations.Test;
119.28 +import static org.testng.Assert.*;
119.29 +
119.30 +/**
119.31 + *
119.32 + * @author Jaroslav Tulach <jtulach@netbeans.org>
119.33 + */
119.34 +@GenerateZip(name = "five.zip", contents = {
119.35 + "1.txt", "one",
119.36 + "2.txt", "duo",
119.37 + "3.txt", "three",
119.38 + "4.txt", "four",
119.39 + "5.txt", "five"
119.40 +})
119.41 +public class ZipEntryTest {
119.42 + @Test
119.43 + public void readEntriesEffectively() throws IOException {
119.44 + InputStream is = ZipEntryTest.class.getResourceAsStream("five.zip");
119.45 + byte[] arr = new byte[is.available()];
119.46 + int len = is.read(arr);
119.47 + assertEquals(len, arr.length, "Read fully");
119.48 +
119.49 + FastJar fj = new FastJar(arr);
119.50 + FastJar.Entry[] entrs = fj.list();
119.51 +
119.52 + assertEquals(5, entrs.length, "Five entries");
119.53 +
119.54 + for (int i = 1; i <= 5; i++) {
119.55 + FastJar.Entry en = entrs[i - 1];
119.56 + assertEquals(en.name, i + ".txt");
119.57 +// assertEquals(cis.cnt, 0, "Content of the file should be skipped, not read");
119.58 + }
119.59 +
119.60 + assertContent("three", fj.getInputStream(entrs[3 - 1]), "read OK");
119.61 + assertContent("five", fj.getInputStream(entrs[5 - 1]), "read OK");
119.62 + }
119.63 +
119.64 + private static void assertContent(String exp, InputStream is, String msg) throws IOException {
119.65 + byte[] arr = new byte[512];
119.66 + int len = is.read(arr);
119.67 + String s = new String(arr, 0, len);
119.68 + assertEquals(exp, s, msg);
119.69 + }
119.70 +}
120.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
120.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/ZipFileTest.java Thu May 02 09:18:22 2013 +0200
120.3 @@ -0,0 +1,108 @@
120.4 +/**
120.5 + * Back 2 Browser Bytecode Translator
120.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
120.7 + *
120.8 + * This program is free software: you can redistribute it and/or modify
120.9 + * it under the terms of the GNU General Public License as published by
120.10 + * the Free Software Foundation, version 2 of the License.
120.11 + *
120.12 + * This program is distributed in the hope that it will be useful,
120.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
120.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
120.15 + * GNU General Public License for more details.
120.16 + *
120.17 + * You should have received a copy of the GNU General Public License
120.18 + * along with this program. Look for COPYING file in the top folder.
120.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
120.20 + */
120.21 +package org.apidesign.bck2brwsr.vmtest.impl;
120.22 +
120.23 +import java.io.IOException;
120.24 +import java.io.InputStream;
120.25 +import java.util.Objects;
120.26 +import java.util.zip.ZipEntry;
120.27 +import java.util.zip.ZipInputStream;
120.28 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
120.29 +import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
120.30 +import org.apidesign.bck2brwsr.vmtest.Compare;
120.31 +import org.apidesign.bck2brwsr.vmtest.Http;
120.32 +import org.apidesign.bck2brwsr.vmtest.VMTest;
120.33 +import org.testng.annotations.Factory;
120.34 +
120.35 +/**
120.36 + *
120.37 + * @author Jaroslav Tulach <jtulach@netbeans.org>
120.38 + */
120.39 +@GenerateZip(name = "readAnEntry.zip", contents = {
120.40 + "my/main/file.txt", "Hello World!"
120.41 +})
120.42 +public class ZipFileTest {
120.43 +
120.44 + @Compare public String readAnEntry() throws IOException {
120.45 + InputStream is = ZipFileTest.class.getResourceAsStream("readAnEntry.zip");
120.46 + ZipInputStream zip = new ZipInputStream(is);
120.47 + ZipEntry entry = zip.getNextEntry();
120.48 + assertEquals(entry.getName(), "my/main/file.txt", "Correct entry");
120.49 +
120.50 + byte[] arr = new byte[4096];
120.51 + int len = zip.read(arr);
120.52 +
120.53 + assertEquals(zip.getNextEntry(), null, "No next entry");
120.54 +
120.55 + final String ret = new String(arr, 0, len, "UTF-8");
120.56 + return ret;
120.57 + }
120.58 +
120.59 + @JavaScriptBody(args = { "res", "path" }, body =
120.60 + "var myvm = bck2brwsr.apply(null, path);\n"
120.61 + + "var cls = myvm.loadClass('java.lang.String');\n"
120.62 + + "return cls.getClass__Ljava_lang_Class_2().getResourceAsStream__Ljava_io_InputStream_2Ljava_lang_String_2(res);\n"
120.63 + )
120.64 + private static native Object loadVMResource(String res, String...path);
120.65 +
120.66 + @Http({
120.67 + @Http.Resource(path = "/readAnEntry.jar", mimeType = "x-application/zip", content = "", resource="readAnEntry.zip")
120.68 + })
120.69 + @BrwsrTest public void canVmLoadResourceFromZip() throws IOException {
120.70 + Object res = loadVMResource("/my/main/file.txt", "/readAnEntry.jar");
120.71 + assert res instanceof InputStream : "Got array of bytes: " + res;
120.72 + InputStream is = (InputStream)res;
120.73 +
120.74 + byte[] arr = new byte[4096];
120.75 + int len = is.read(arr);
120.76 +
120.77 + final String ret = new String(arr, 0, len, "UTF-8");
120.78 +
120.79 + assertEquals(ret, "Hello World!", "Can read the bytes");
120.80 + }
120.81 +
120.82 + @GenerateZip(name = "cpattr.zip", contents = {
120.83 + "META-INF/MANIFEST.MF", "Manifest-Version: 1.0\n"
120.84 + + "Created-By: hand\n"
120.85 + + "Class-Path: realJar.jar\n\n\n"
120.86 + })
120.87 + @Http({
120.88 + @Http.Resource(path = "/readComplexEntry.jar", mimeType = "x-application/zip", content = "", resource="cpattr.zip"),
120.89 + @Http.Resource(path = "/realJar.jar", mimeType = "x-application/zip", content = "", resource="readAnEntry.zip"),
120.90 + })
120.91 + @BrwsrTest public void understandsClassPathAttr() throws IOException {
120.92 + Object res = loadVMResource("/my/main/file.txt", "/readComplexEntry.jar");
120.93 + assert res instanceof InputStream : "Got array of bytes: " + res;
120.94 + InputStream is = (InputStream)res;
120.95 +
120.96 + byte[] arr = new byte[4096];
120.97 + int len = is.read(arr);
120.98 +
120.99 + final String ret = new String(arr, 0, len, "UTF-8");
120.100 +
120.101 + assertEquals(ret, "Hello World!", "Can read the bytes from secondary JAR");
120.102 + }
120.103 +
120.104 + private static void assertEquals(Object real, Object exp, String msg) {
120.105 + assert Objects.equals(exp, real) : msg + " exp: " + exp + " real: " + real;
120.106 + }
120.107 +
120.108 + @Factory public static Object[] create() {
120.109 + return VMTest.create(ZipFileTest.class);
120.110 + }
120.111 +}
121.1 Binary file rt/emul/compact/src/test/resources/org/apidesign/bck2brwsr/compact/tck/demo.static.calculator-0.3-SNAPSHOT.jar has changed
122.1 Binary file rt/emul/compact/src/test/resources/org/apidesign/bck2brwsr/compact/tck/demo.static.calculator-TEST.jar has changed
123.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
123.2 +++ b/rt/emul/compact/src/test/resources/org/apidesign/bck2brwsr/tck/0xfe Thu May 02 09:18:22 2013 +0200
123.3 @@ -0,0 +1,1 @@
123.4 +þ
123.5 \ No newline at end of file
124.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
124.2 +++ b/rt/emul/compact/src/test/resources/org/apidesign/bck2brwsr/tck/Resources.txt Thu May 02 09:18:22 2013 +0200
124.3 @@ -0,0 +1,1 @@
124.4 +Ahoj
125.1 --- a/rt/emul/mini/pom.xml Tue Apr 02 15:40:51 2013 +0200
125.2 +++ b/rt/emul/mini/pom.xml Thu May 02 09:18:22 2013 +0200
125.3 @@ -4,11 +4,11 @@
125.4 <parent>
125.5 <groupId>org.apidesign.bck2brwsr</groupId>
125.6 <artifactId>emul.pom</artifactId>
125.7 - <version>0.5-SNAPSHOT</version>
125.8 + <version>0.8-SNAPSHOT</version>
125.9 </parent>
125.10 <groupId>org.apidesign.bck2brwsr</groupId>
125.11 <artifactId>emul.mini</artifactId>
125.12 - <version>0.5-SNAPSHOT</version>
125.13 + <version>0.8-SNAPSHOT</version>
125.14 <name>Minimal API Profile</name>
125.15 <url>http://maven.apache.org</url>
125.16 <properties>
125.17 @@ -18,7 +18,7 @@
125.18 <dependency>
125.19 <groupId>org.apidesign.bck2brwsr</groupId>
125.20 <artifactId>core</artifactId>
125.21 - <version>0.5-SNAPSHOT</version>
125.22 + <version>0.8-SNAPSHOT</version>
125.23 <type>jar</type>
125.24 </dependency>
125.25 <dependency>
126.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
126.2 +++ b/rt/emul/mini/src/main/java/java/lang/ArithmeticException.java Thu May 02 09:18:22 2013 +0200
126.3 @@ -0,0 +1,61 @@
126.4 +/*
126.5 + * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved.
126.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
126.7 + *
126.8 + * This code is free software; you can redistribute it and/or modify it
126.9 + * under the terms of the GNU General Public License version 2 only, as
126.10 + * published by the Free Software Foundation. Oracle designates this
126.11 + * particular file as subject to the "Classpath" exception as provided
126.12 + * by Oracle in the LICENSE file that accompanied this code.
126.13 + *
126.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
126.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
126.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
126.17 + * version 2 for more details (a copy is included in the LICENSE file that
126.18 + * accompanied this code).
126.19 + *
126.20 + * You should have received a copy of the GNU General Public License version
126.21 + * 2 along with this work; if not, write to the Free Software Foundation,
126.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
126.23 + *
126.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
126.25 + * or visit www.oracle.com if you need additional information or have any
126.26 + * questions.
126.27 + */
126.28 +
126.29 +package java.lang;
126.30 +
126.31 +/**
126.32 + * Thrown when an exceptional arithmetic condition has occurred. For
126.33 + * example, an integer "divide by zero" throws an
126.34 + * instance of this class.
126.35 + *
126.36 + * {@code ArithmeticException} objects may be constructed by the
126.37 + * virtual machine as if {@linkplain Throwable#Throwable(String,
126.38 + * Throwable, boolean, boolean) suppression were disabled and/or the
126.39 + * stack trace was not writable}.
126.40 + *
126.41 + * @author unascribed
126.42 + * @since JDK1.0
126.43 + */
126.44 +public class ArithmeticException extends RuntimeException {
126.45 + private static final long serialVersionUID = 2256477558314496007L;
126.46 +
126.47 + /**
126.48 + * Constructs an {@code ArithmeticException} with no detail
126.49 + * message.
126.50 + */
126.51 + public ArithmeticException() {
126.52 + super();
126.53 + }
126.54 +
126.55 + /**
126.56 + * Constructs an {@code ArithmeticException} with the specified
126.57 + * detail message.
126.58 + *
126.59 + * @param s the detail message.
126.60 + */
126.61 + public ArithmeticException(String s) {
126.62 + super(s);
126.63 + }
126.64 +}
127.1 --- a/rt/emul/mini/src/main/java/java/lang/Class.java Tue Apr 02 15:40:51 2013 +0200
127.2 +++ b/rt/emul/mini/src/main/java/java/lang/Class.java Thu May 02 09:18:22 2013 +0200
127.3 @@ -402,8 +402,15 @@
127.4 }
127.5 return cmpType != null && getComponentType().isAssignableFrom(cmpType);
127.6 }
127.7 - String prop = "$instOf_" + getName().replace('.', '_');
127.8 - return hasCnstrProperty(cls, prop);
127.9 + if (isPrimitive()) {
127.10 + return false;
127.11 + } else {
127.12 + if (cls.isPrimitive()) {
127.13 + return false;
127.14 + }
127.15 + String prop = "$instOf_" + getName().replace('.', '_');
127.16 + return hasCnstrProperty(cls, prop);
127.17 + }
127.18 }
127.19
127.20 @JavaScriptBody(args = { "who", "prop" }, body =
127.21 @@ -1245,6 +1252,7 @@
127.22 }
127.23
127.24 @JavaScriptBody(args = { "sig" }, body =
127.25 + "if (!sig) sig = '[Ljava/lang/Object;';\n" +
127.26 "var c = Array[sig];\n" +
127.27 "if (c) return c;\n" +
127.28 "c = vm.java_lang_Class(true);\n" +
128.1 --- a/rt/emul/mini/src/main/java/java/lang/Enum.java Tue Apr 02 15:40:51 2013 +0200
128.2 +++ b/rt/emul/mini/src/main/java/java/lang/Enum.java Thu May 02 09:18:22 2013 +0200
128.3 @@ -27,6 +27,7 @@
128.4
128.5 import java.io.Serializable;
128.6 import java.io.IOException;
128.7 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
128.8
128.9 /**
128.10 * This is the common base class of all Java language enumeration types.
128.11 @@ -225,15 +226,17 @@
128.12 */
128.13 public static <T extends Enum<T>> T valueOf(Class<T> enumType,
128.14 String name) {
128.15 - throw new UnsupportedOperationException();
128.16 -// T result = enumType.enumConstantDirectory().get(name);
128.17 -// if (result != null)
128.18 -// return result;
128.19 -// if (name == null)
128.20 -// throw new NullPointerException("Name is null");
128.21 -// throw new IllegalArgumentException(
128.22 -// "No enum constant " + enumType.getCanonicalName() + "." + name);
128.23 + for (Object o : values(enumType)) {
128.24 + T t = enumType.cast(o);
128.25 + if (name.equals(((Enum)t).name)) {
128.26 + return t;
128.27 + }
128.28 + }
128.29 + throw new IllegalArgumentException();
128.30 }
128.31 +
128.32 + @JavaScriptBody(args = { "enumType" }, body = "return enumType.cnstr.$VALUES;")
128.33 + private static native Object[] values(Class<?> enumType);
128.34
128.35 /**
128.36 * enum classes cannot have finalize methods.
129.1 --- a/rt/emul/mini/src/main/java/java/lang/String.java Tue Apr 02 15:40:51 2013 +0200
129.2 +++ b/rt/emul/mini/src/main/java/java/lang/String.java Thu May 02 09:18:22 2013 +0200
129.3 @@ -2220,9 +2220,19 @@
129.4 * <code>replacement</code> is <code>null</code>.
129.5 * @since 1.5
129.6 */
129.7 - public String replace(CharSequence target, CharSequence replacement) {
129.8 - throw new UnsupportedOperationException("This one should be supported, but without dep on rest of regexp");
129.9 - }
129.10 + @JavaScriptBody(args = { "target", "replacement" }, body =
129.11 + "var s = this.toString();\n"
129.12 + + "target = target.toString();\n"
129.13 + + "replacement = replacement.toString();\n"
129.14 + + "for (;;) {\n"
129.15 + + " var ret = s.replace(target, replacement);\n"
129.16 + + " if (ret === s) {\n"
129.17 + + " return ret;\n"
129.18 + + " }\n"
129.19 + + " s = ret;\n"
129.20 + + "}"
129.21 + )
129.22 + public native String replace(CharSequence target, CharSequence replacement);
129.23
129.24 /**
129.25 * Splits this string around matches of the given
130.1 --- a/rt/emul/mini/src/main/java/java/lang/Throwable.java Tue Apr 02 15:40:51 2013 +0200
130.2 +++ b/rt/emul/mini/src/main/java/java/lang/Throwable.java Thu May 02 09:18:22 2013 +0200
130.3 @@ -1085,4 +1085,22 @@
130.4 // else
130.5 // return suppressedExceptions.toArray(EMPTY_THROWABLE_ARRAY);
130.6 }
130.7 +
130.8 + private static Object bck2BrwsrCnvrt(Object o) {
130.9 + if (o instanceof Throwable) {
130.10 + return o;
130.11 + }
130.12 + final String msg = msg(o);
130.13 + if (msg == null || msg.startsWith("TypeError")) {
130.14 + return new NullPointerException(msg);
130.15 + }
130.16 + return new Throwable(msg);
130.17 + }
130.18 +
130.19 + @JavaScriptBody(args = { "o" }, body = "return o ? o.toString() : null;")
130.20 + private static native String msg(Object o);
130.21 +
130.22 + @JavaScriptOnly(name = "bck2BrwsrCnvrt", value = "c.bck2BrwsrCnvrt__Ljava_lang_Object_2Ljava_lang_Object_2")
130.23 + private static void bck2BrwsrCnvrtVM() {
130.24 + }
130.25 }
131.1 --- a/rt/emul/mini/src/main/java/java/lang/reflect/Array.java Tue Apr 02 15:40:51 2013 +0200
131.2 +++ b/rt/emul/mini/src/main/java/java/lang/reflect/Array.java Thu May 02 09:18:22 2013 +0200
131.3 @@ -636,9 +636,9 @@
131.4 + "arr.jvmName = sig;\n"
131.5 + "return arr;"
131.6 )
131.7 - private static native Object newArray(boolean primitive, String sig, int length);
131.8 + static native Object newArray(boolean primitive, String sig, int length);
131.9
131.10 - private static Object multiNewArray(String sig, int[] dims, int index)
131.11 + static Object multiNewArray(String sig, int[] dims, int index)
131.12 throws IllegalArgumentException, NegativeArraySizeException {
131.13 if (dims.length == index + 1) {
131.14 return newArray(sig.length() == 2, sig, dims[index]);
132.1 --- a/rt/emul/mini/src/main/java/java/lang/reflect/Method.java Tue Apr 02 15:40:51 2013 +0200
132.2 +++ b/rt/emul/mini/src/main/java/java/lang/reflect/Method.java Thu May 02 09:18:22 2013 +0200
132.3 @@ -501,8 +501,8 @@
132.4 throws IllegalAccessException, IllegalArgumentException,
132.5 InvocationTargetException
132.6 {
132.7 - final boolean isStatic = (getModifiers() & Modifier.STATIC) == 0;
132.8 - if (isStatic && obj == null) {
132.9 + final boolean nonStatic = (getModifiers() & Modifier.STATIC) == 0;
132.10 + if (nonStatic && obj == null) {
132.11 throw new NullPointerException();
132.12 }
132.13 Class[] types = getParameterTypes();
132.14 @@ -517,7 +517,7 @@
132.15 }
132.16 }
132.17 }
132.18 - Object res = invoke0(isStatic, this, obj, args);
132.19 + Object res = invokeTry(nonStatic, this, obj, args);
132.20 if (getReturnType().isPrimitive()) {
132.21 res = fromPrimitive(getReturnType(), res);
132.22 }
132.23 @@ -536,6 +536,15 @@
132.24 + "return method._data().apply(self, p);\n"
132.25 )
132.26 private static native Object invoke0(boolean isStatic, Method m, Object self, Object[] args);
132.27 +
132.28 + private static Object invokeTry(boolean isStatic, Method m, Object self, Object[] args)
132.29 + throws InvocationTargetException {
132.30 + try {
132.31 + return invoke0(isStatic, m, self, args);
132.32 + } catch (Throwable ex) {
132.33 + throw new InvocationTargetException(ex, ex.getMessage());
132.34 + }
132.35 + }
132.36
132.37 static Object fromPrimitive(Class<?> type, Object o) {
132.38 if (type == Integer.TYPE) {
133.1 --- a/rt/emul/mini/src/main/resources/org/apidesign/vm4brwsr/emul/lang/java_lang_Number.js Tue Apr 02 15:40:51 2013 +0200
133.2 +++ b/rt/emul/mini/src/main/resources/org/apidesign/vm4brwsr/emul/lang/java_lang_Number.js Thu May 02 09:18:22 2013 +0200
133.3 @@ -1,226 +1,244 @@
133.4 // empty line needed here
133.5 -Number.prototype.add32 = function(x) { return (this + x) | 0; };
133.6 -Number.prototype.sub32 = function(x) { return (this - x) | 0; };
133.7 -Number.prototype.mul32 = function(x) {
133.8 - return (((this * (x >> 16)) << 16) + this * (x & 0xFFFF)) | 0;
133.9 -};
133.10 -Number.prototype.neg32 = function() { return (-this) | 0; };
133.11
133.12 -Number.prototype.toInt8 = function() { return (this << 24) >> 24; };
133.13 -Number.prototype.toInt16 = function() { return (this << 16) >> 16; };
133.14 +(function(numberPrototype) {
133.15 + numberPrototype.add32 = function(x) {
133.16 + return (this + x) | 0;
133.17 + };
133.18 + numberPrototype.sub32 = function(x) {
133.19 + return (this - x) | 0;
133.20 + };
133.21 + numberPrototype.mul32 = function(x) {
133.22 + return (((this * (x >> 16)) << 16) + this * (x & 0xFFFF)) | 0;
133.23 + };
133.24 + numberPrototype.neg32 = function() {
133.25 + return (-this) | 0;
133.26 + };
133.27
133.28 -var __m32 = 0xFFFFFFFF;
133.29 + numberPrototype.toInt8 = function() {
133.30 + return (this << 24) >> 24;
133.31 + };
133.32 + numberPrototype.toInt16 = function() {
133.33 + return (this << 16) >> 16;
133.34 + };
133.35
133.36 -Number.prototype.next32 = function(low) {
133.37 - if (this === 0) {
133.38 - return low;
133.39 - }
133.40 - var l = new Number(low);
133.41 - l.hi = this | 0;
133.42 - return l;
133.43 -};
133.44 + var __m32 = 0xFFFFFFFF;
133.45
133.46 -Number.prototype.high32 = function() {
133.47 - return this.hi ? this.hi : (Math.floor(this / (__m32+1))) | 0;
133.48 -};
133.49 -Number.prototype.toInt32 = function() { return this | 0; };
133.50 -Number.prototype.toFP = function() {
133.51 - return this.hi ? this.hi * (__m32+1) + this : this;
133.52 -};
133.53 -Number.prototype.toLong = function() {
133.54 - var hi = (this / (__m32+1)) | 0;
133.55 - var low = (this % (__m32+1)) | 0;
133.56 - if (low < 0) {
133.57 - low += __m32+1;
133.58 - }
133.59 -
133.60 - if (this < 0) {
133.61 - hi -= 1;
133.62 - }
133.63 + numberPrototype.next32 = function(low) {
133.64 + if (this === 0) {
133.65 + return low;
133.66 + }
133.67 + var l = new Number(low);
133.68 + l.hi = this | 0;
133.69 + return l;
133.70 + };
133.71
133.72 - return hi.next32(low);
133.73 -};
133.74 + numberPrototype.high32 = function() {
133.75 + return this.hi ? this.hi : (Math.floor(this / (__m32 + 1))) | 0;
133.76 + };
133.77 + numberPrototype.toInt32 = function() {
133.78 + return this | 0;
133.79 + };
133.80 + numberPrototype.toFP = function() {
133.81 + return this.hi ? this.hi * (__m32 + 1) + this : this;
133.82 + };
133.83 + numberPrototype.toLong = function() {
133.84 + var hi = (this / (__m32 + 1)) | 0;
133.85 + var low = (this % (__m32 + 1)) | 0;
133.86 + if (low < 0) {
133.87 + low += __m32 + 1;
133.88 + }
133.89
133.90 -Number.prototype.toExactString = function() {
133.91 - if (this.hi) {
133.92 - // check for Long.MIN_VALUE
133.93 - if ((this.hi == (0x80000000 | 0)) && (this == 0)) {
133.94 - return '-9223372036854775808';
133.95 + if (this < 0) {
133.96 + hi -= 1;
133.97 }
133.98 - var res = 0;
133.99 - var a = [ 6,9,2,7,6,9,4,9,2,4 ];
133.100 - var s = '';
133.101 - var digit;
133.102 - var neg = this.hi < 0;
133.103 - if (neg) {
133.104 - var x = this.neg64();
133.105 - var hi = x.hi;
133.106 - var low = x;
133.107 - } else {
133.108 - var hi = this.hi;
133.109 - var low = this;
133.110 - }
133.111 - for (var i = 0; i < a.length; i++) {
133.112 - res += hi * a[i];
133.113 - var low_digit = low % 10;
133.114 - digit = (res % 10) + low_digit;
133.115
133.116 - low = Math.floor(low / 10);
133.117 - res = Math.floor(res / 10);
133.118 -
133.119 - if (digit >= 10) {
133.120 - digit -= 10;
133.121 - res++;
133.122 - }
133.123 - s = String(digit).concat(s);
133.124 - }
133.125 - s = String(res).concat(s).replace(/^0+/, '');
133.126 - return (neg ? '-' : '').concat(s);
133.127 - }
133.128 - return String(this);
133.129 -};
133.130 -
133.131 -Number.prototype.add64 = function(x) {
133.132 - var low = this + x;
133.133 - carry = 0;
133.134 - if (low > __m32) {
133.135 - carry = 1;
133.136 - low -= (__m32+1);
133.137 - }
133.138 - var hi = (this.high32() + x.high32() + carry) | 0;
133.139 - return hi.next32(low);
133.140 -};
133.141 -
133.142 -Number.prototype.sub64 = function(x) {
133.143 - var low = this - x;
133.144 - carry = 0;
133.145 - if (low < 0) {
133.146 - carry = 1;
133.147 - low += (__m32+1);
133.148 - }
133.149 - var hi = (this.high32() - x.high32() - carry) | 0;
133.150 - return hi.next32(low);
133.151 -};
133.152 -
133.153 -Number.prototype.mul64 = function(x) {
133.154 - var low = this.mul32(x);
133.155 - low += (low < 0) ? (__m32+1) : 0;
133.156 - // first count upper 32 bits of (this.low * x.low)
133.157 - var hi_hi = 0;
133.158 - var hi_low = 0;
133.159 - var m = 1;
133.160 - for (var i = 0; i < 32; i++) {
133.161 - if (x & m) {
133.162 - hi_hi += this >>> 16;
133.163 - hi_low += this & 0xFFFF
133.164 - }
133.165 - hi_low >>= 1;
133.166 - hi_low += (hi_hi & 1) ? 0x8000 : 0;
133.167 - hi_hi >>= 1;
133.168 - m <<= 1;
133.169 - }
133.170 - var hi = (hi_hi << 16) + hi_low;
133.171 -
133.172 - var m1 = this.high32().mul32(x);
133.173 - var m2 = this.mul32(x.high32());
133.174 - hi = hi.add32(m1).add32(m2);
133.175 -
133.176 - return hi.next32(low);
133.177 -};
133.178 -
133.179 -Number.prototype.and64 = function(x) {
133.180 - var low = this & x;
133.181 - low += (low < 0) ? (__m32+1) : 0;
133.182 - if (this.hi && x.hi) {
133.183 - var hi = this.hi & x.hi;
133.184 return hi.next32(low);
133.185 };
133.186 - return low;
133.187 -};
133.188
133.189 -Number.prototype.or64 = function(x) {
133.190 - var low = this | x;
133.191 - low += (low < 0) ? (__m32+1) : 0;
133.192 - if (this.hi || x.hi) {
133.193 - var hi = this.hi | x.hi;
133.194 + numberPrototype.toExactString = function() {
133.195 + if (this.hi) {
133.196 + // check for Long.MIN_VALUE
133.197 + if ((this.hi == (0x80000000 | 0)) && (this == 0)) {
133.198 + return '-9223372036854775808';
133.199 + }
133.200 + var res = 0;
133.201 + var a = [6, 9, 2, 7, 6, 9, 4, 9, 2, 4];
133.202 + var s = '';
133.203 + var digit;
133.204 + var neg = this.hi < 0;
133.205 + if (neg) {
133.206 + var x = this.neg64();
133.207 + var hi = x.hi;
133.208 + var low = x;
133.209 + } else {
133.210 + var hi = this.hi;
133.211 + var low = this;
133.212 + }
133.213 + for (var i = 0; i < a.length; i++) {
133.214 + res += hi * a[i];
133.215 + var low_digit = low % 10;
133.216 + digit = (res % 10) + low_digit;
133.217 +
133.218 + low = Math.floor(low / 10);
133.219 + res = Math.floor(res / 10);
133.220 +
133.221 + if (digit >= 10) {
133.222 + digit -= 10;
133.223 + res++;
133.224 + }
133.225 + s = String(digit).concat(s);
133.226 + }
133.227 + s = String(res).concat(s).replace(/^0+/, '');
133.228 + return (neg ? '-' : '').concat(s);
133.229 + }
133.230 + return String(this);
133.231 + };
133.232 +
133.233 + numberPrototype.add64 = function(x) {
133.234 + var low = this + x;
133.235 + carry = 0;
133.236 + if (low > __m32) {
133.237 + carry = 1;
133.238 + low -= (__m32 + 1);
133.239 + }
133.240 + var hi = (this.high32() + x.high32() + carry) | 0;
133.241 return hi.next32(low);
133.242 };
133.243 - return low;
133.244 -};
133.245
133.246 -Number.prototype.xor64 = function(x) {
133.247 - var low = this ^ x;
133.248 - low += (low < 0) ? (__m32+1) : 0;
133.249 - if (this.hi || x.hi) {
133.250 - var hi = this.hi ^ x.hi;
133.251 + numberPrototype.sub64 = function(x) {
133.252 + var low = this - x;
133.253 + carry = 0;
133.254 + if (low < 0) {
133.255 + carry = 1;
133.256 + low += (__m32 + 1);
133.257 + }
133.258 + var hi = (this.high32() - x.high32() - carry) | 0;
133.259 return hi.next32(low);
133.260 };
133.261 - return low;
133.262 -};
133.263
133.264 -Number.prototype.shl64 = function(x) {
133.265 - if (x >= 32) {
133.266 - var hi = this << (x - 32);
133.267 - return hi.next32(0);
133.268 - } else {
133.269 - var hi = this.high32() << x;
133.270 - var low_reminder = this >> (32 - x);
133.271 - hi |= low_reminder;
133.272 - var low = this << x;
133.273 - low += (low < 0) ? (__m32+1) : 0;
133.274 + numberPrototype.mul64 = function(x) {
133.275 + var low = this.mul32(x);
133.276 + low += (low < 0) ? (__m32 + 1) : 0;
133.277 + // first count upper 32 bits of (this.low * x.low)
133.278 + var hi_hi = 0;
133.279 + var hi_low = 0;
133.280 + var m = 1;
133.281 + for (var i = 0; i < 32; i++) {
133.282 + if (x & m) {
133.283 + hi_hi += this >>> 16;
133.284 + hi_low += this & 0xFFFF
133.285 + }
133.286 + hi_low >>= 1;
133.287 + hi_low += (hi_hi & 1) ? 0x8000 : 0;
133.288 + hi_hi >>= 1;
133.289 + m <<= 1;
133.290 + }
133.291 + var hi = (hi_hi << 16) + hi_low;
133.292 +
133.293 + var m1 = this.high32().mul32(x);
133.294 + var m2 = this.mul32(x.high32());
133.295 + hi = hi.add32(m1).add32(m2);
133.296 +
133.297 return hi.next32(low);
133.298 - }
133.299 -};
133.300 + };
133.301
133.302 -Number.prototype.shr64 = function(x) {
133.303 - if (x >= 32) {
133.304 - var low = this.high32() >> (x - 32);
133.305 - low += (low < 0) ? (__m32+1) : 0;
133.306 + numberPrototype.and64 = function(x) {
133.307 + var low = this & x;
133.308 + low += (low < 0) ? (__m32 + 1) : 0;
133.309 + if (this.hi && x.hi) {
133.310 + var hi = this.hi & x.hi;
133.311 + return hi.next32(low);
133.312 + }
133.313 + ;
133.314 return low;
133.315 - } else {
133.316 - var low = this >> x;
133.317 - var hi_reminder = this.high32() << (32 - x);
133.318 - low |= hi_reminder;
133.319 - low += (low < 0) ? (__m32+1) : 0;
133.320 - var hi = this.high32() >> x;
133.321 - return hi.next32(low);
133.322 - }
133.323 -};
133.324 + };
133.325
133.326 -Number.prototype.ushr64 = function(x) {
133.327 - if (x >= 32) {
133.328 - var low = this.high32() >>> (x - 32);
133.329 - low += (low < 0) ? (__m32+1) : 0;
133.330 + numberPrototype.or64 = function(x) {
133.331 + var low = this | x;
133.332 + low += (low < 0) ? (__m32 + 1) : 0;
133.333 + if (this.hi || x.hi) {
133.334 + var hi = this.hi | x.hi;
133.335 + return hi.next32(low);
133.336 + }
133.337 + ;
133.338 return low;
133.339 - } else {
133.340 - var low = this >>> x;
133.341 - var hi_reminder = this.high32() << (32 - x);
133.342 - low |= hi_reminder;
133.343 - low += (low < 0) ? (__m32+1) : 0;
133.344 - var hi = this.high32() >>> x;
133.345 - return hi.next32(low);
133.346 - }
133.347 -};
133.348 + };
133.349
133.350 -Number.prototype.compare64 = function(x) {
133.351 - if (this.high32() === x.high32()) {
133.352 - return (this < x) ? -1 : ((this > x) ? 1 : 0);
133.353 - }
133.354 - return (this.high32() < x.high32()) ? -1 : 1;
133.355 -};
133.356 + numberPrototype.xor64 = function(x) {
133.357 + var low = this ^ x;
133.358 + low += (low < 0) ? (__m32 + 1) : 0;
133.359 + if (this.hi || x.hi) {
133.360 + var hi = this.hi ^ x.hi;
133.361 + return hi.next32(low);
133.362 + }
133.363 + ;
133.364 + return low;
133.365 + };
133.366
133.367 -Number.prototype.neg64 = function() {
133.368 - var hi = this.high32();
133.369 - var low = this;
133.370 - if ((hi === 0) && (low < 0)) { return -low; }
133.371 - hi = ~hi;
133.372 - low = ~low;
133.373 - low += (low < 0) ? (__m32+1) : 0;
133.374 - var ret = hi.next32(low);
133.375 - return ret.add64(1);
133.376 -};
133.377 + numberPrototype.shl64 = function(x) {
133.378 + if (x >= 32) {
133.379 + var hi = this << (x - 32);
133.380 + return hi.next32(0);
133.381 + } else {
133.382 + var hi = this.high32() << x;
133.383 + var low_reminder = this >> (32 - x);
133.384 + hi |= low_reminder;
133.385 + var low = this << x;
133.386 + low += (low < 0) ? (__m32 + 1) : 0;
133.387 + return hi.next32(low);
133.388 + }
133.389 + };
133.390
133.391 -(function(numberPrototype) {
133.392 + numberPrototype.shr64 = function(x) {
133.393 + if (x >= 32) {
133.394 + var low = this.high32() >> (x - 32);
133.395 + low += (low < 0) ? (__m32 + 1) : 0;
133.396 + return low;
133.397 + } else {
133.398 + var low = this >> x;
133.399 + var hi_reminder = this.high32() << (32 - x);
133.400 + low |= hi_reminder;
133.401 + low += (low < 0) ? (__m32 + 1) : 0;
133.402 + var hi = this.high32() >> x;
133.403 + return hi.next32(low);
133.404 + }
133.405 + };
133.406 +
133.407 + numberPrototype.ushr64 = function(x) {
133.408 + if (x >= 32) {
133.409 + var low = this.high32() >>> (x - 32);
133.410 + low += (low < 0) ? (__m32 + 1) : 0;
133.411 + return low;
133.412 + } else {
133.413 + var low = this >>> x;
133.414 + var hi_reminder = this.high32() << (32 - x);
133.415 + low |= hi_reminder;
133.416 + low += (low < 0) ? (__m32 + 1) : 0;
133.417 + var hi = this.high32() >>> x;
133.418 + return hi.next32(low);
133.419 + }
133.420 + };
133.421 +
133.422 + numberPrototype.compare64 = function(x) {
133.423 + if (this.high32() === x.high32()) {
133.424 + return (this < x) ? -1 : ((this > x) ? 1 : 0);
133.425 + }
133.426 + return (this.high32() < x.high32()) ? -1 : 1;
133.427 + };
133.428 +
133.429 + numberPrototype.neg64 = function() {
133.430 + var hi = this.high32();
133.431 + var low = this;
133.432 + if ((hi === 0) && (low < 0)) {
133.433 + return -low;
133.434 + }
133.435 + hi = ~hi;
133.436 + low = ~low;
133.437 + low += (low < 0) ? (__m32 + 1) : 0;
133.438 + var ret = hi.next32(low);
133.439 + return ret.add64(1);
133.440 + };
133.441 +
133.442 function __handleDivByZero() {
133.443 var exception = new vm.java_lang_ArithmeticException;
133.444 vm.java_lang_ArithmeticException(false).constructor
134.1 --- a/rt/emul/pom.xml Tue Apr 02 15:40:51 2013 +0200
134.2 +++ b/rt/emul/pom.xml Thu May 02 09:18:22 2013 +0200
134.3 @@ -4,11 +4,11 @@
134.4 <parent>
134.5 <groupId>org.apidesign.bck2brwsr</groupId>
134.6 <artifactId>rt</artifactId>
134.7 - <version>0.5-SNAPSHOT</version>
134.8 + <version>0.8-SNAPSHOT</version>
134.9 </parent>
134.10 <groupId>org.apidesign.bck2brwsr</groupId>
134.11 <artifactId>emul.pom</artifactId>
134.12 - <version>0.5-SNAPSHOT</version>
134.13 + <version>0.8-SNAPSHOT</version>
134.14 <packaging>pom</packaging>
134.15 <name>Emulation of Core Libraries</name>
134.16 <modules>
135.1 --- a/rt/launcher/pom.xml Tue Apr 02 15:40:51 2013 +0200
135.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
135.3 @@ -1,56 +0,0 @@
135.4 -<?xml version="1.0"?>
135.5 -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
135.6 - <modelVersion>4.0.0</modelVersion>
135.7 - <parent>
135.8 - <groupId>org.apidesign.bck2brwsr</groupId>
135.9 - <artifactId>rt</artifactId>
135.10 - <version>0.5-SNAPSHOT</version>
135.11 - </parent>
135.12 - <groupId>org.apidesign.bck2brwsr</groupId>
135.13 - <artifactId>launcher</artifactId>
135.14 - <version>0.5-SNAPSHOT</version>
135.15 - <name>Bck2Brwsr Launcher</name>
135.16 - <url>http://maven.apache.org</url>
135.17 - <build>
135.18 - <plugins>
135.19 - <plugin>
135.20 - <groupId>org.apache.maven.plugins</groupId>
135.21 - <artifactId>maven-compiler-plugin</artifactId>
135.22 - <version>2.3.2</version>
135.23 - <configuration>
135.24 - <source>1.7</source>
135.25 - <target>1.7</target>
135.26 - </configuration>
135.27 - </plugin>
135.28 - <plugin>
135.29 - <groupId>org.apache.maven.plugins</groupId>
135.30 - <artifactId>maven-javadoc-plugin</artifactId>
135.31 - <configuration>
135.32 - <excludePackageNames>org.apidesign.bck2brwsr.launcher.impl</excludePackageNames>
135.33 - <skip>false</skip>
135.34 - </configuration>
135.35 - </plugin>
135.36 - </plugins>
135.37 - </build>
135.38 - <properties>
135.39 - <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
135.40 - </properties>
135.41 - <dependencies>
135.42 - <dependency>
135.43 - <groupId>junit</groupId>
135.44 - <artifactId>junit</artifactId>
135.45 - <version>3.8.1</version>
135.46 - <scope>test</scope>
135.47 - </dependency>
135.48 - <dependency>
135.49 - <groupId>org.glassfish.grizzly</groupId>
135.50 - <artifactId>grizzly-http-server</artifactId>
135.51 - <version>2.2.19</version>
135.52 - </dependency>
135.53 - <dependency>
135.54 - <groupId>${project.groupId}</groupId>
135.55 - <artifactId>vm4brwsr</artifactId>
135.56 - <version>${project.version}</version>
135.57 - </dependency>
135.58 - </dependencies>
135.59 -</project>
136.1 --- a/rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java Tue Apr 02 15:40:51 2013 +0200
136.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
136.3 @@ -1,570 +0,0 @@
136.4 -/**
136.5 - * Back 2 Browser Bytecode Translator
136.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
136.7 - *
136.8 - * This program is free software: you can redistribute it and/or modify
136.9 - * it under the terms of the GNU General Public License as published by
136.10 - * the Free Software Foundation, version 2 of the License.
136.11 - *
136.12 - * This program is distributed in the hope that it will be useful,
136.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
136.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
136.15 - * GNU General Public License for more details.
136.16 - *
136.17 - * You should have received a copy of the GNU General Public License
136.18 - * along with this program. Look for COPYING file in the top folder.
136.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
136.20 - */
136.21 -package org.apidesign.bck2brwsr.launcher;
136.22 -
136.23 -import java.io.Closeable;
136.24 -import java.io.File;
136.25 -import java.io.IOException;
136.26 -import java.io.InputStream;
136.27 -import java.io.InterruptedIOException;
136.28 -import java.io.OutputStream;
136.29 -import java.io.UnsupportedEncodingException;
136.30 -import java.io.Writer;
136.31 -import java.net.URI;
136.32 -import java.net.URISyntaxException;
136.33 -import java.net.URL;
136.34 -import java.util.ArrayList;
136.35 -import java.util.Arrays;
136.36 -import java.util.Enumeration;
136.37 -import java.util.LinkedHashSet;
136.38 -import java.util.List;
136.39 -import java.util.Set;
136.40 -import java.util.concurrent.BlockingQueue;
136.41 -import java.util.concurrent.CountDownLatch;
136.42 -import java.util.concurrent.LinkedBlockingQueue;
136.43 -import java.util.concurrent.TimeUnit;
136.44 -import java.util.logging.Level;
136.45 -import java.util.logging.Logger;
136.46 -import org.apidesign.bck2brwsr.launcher.InvocationContext.Resource;
136.47 -import org.apidesign.vm4brwsr.Bck2Brwsr;
136.48 -import org.glassfish.grizzly.PortRange;
136.49 -import org.glassfish.grizzly.http.server.HttpHandler;
136.50 -import org.glassfish.grizzly.http.server.HttpServer;
136.51 -import org.glassfish.grizzly.http.server.NetworkListener;
136.52 -import org.glassfish.grizzly.http.server.Request;
136.53 -import org.glassfish.grizzly.http.server.Response;
136.54 -import org.glassfish.grizzly.http.server.ServerConfiguration;
136.55 -import org.glassfish.grizzly.http.util.HttpStatus;
136.56 -
136.57 -/**
136.58 - * Lightweight server to launch Bck2Brwsr applications and tests.
136.59 - * Supports execution in native browser as well as Java's internal
136.60 - * execution engine.
136.61 - */
136.62 -final class Bck2BrwsrLauncher extends Launcher implements Closeable {
136.63 - private static final Logger LOG = Logger.getLogger(Bck2BrwsrLauncher.class.getName());
136.64 - private static final InvocationContext END = new InvocationContext(null, null, null);
136.65 - private final Set<ClassLoader> loaders = new LinkedHashSet<>();
136.66 - private final BlockingQueue<InvocationContext> methods = new LinkedBlockingQueue<>();
136.67 - private long timeOut;
136.68 - private final Res resources = new Res();
136.69 - private final String cmd;
136.70 - private Object[] brwsr;
136.71 - private HttpServer server;
136.72 - private CountDownLatch wait;
136.73 -
136.74 - public Bck2BrwsrLauncher(String cmd) {
136.75 - this.cmd = cmd;
136.76 - }
136.77 -
136.78 - @Override
136.79 - InvocationContext runMethod(InvocationContext c) throws IOException {
136.80 - loaders.add(c.clazz.getClassLoader());
136.81 - methods.add(c);
136.82 - try {
136.83 - c.await(timeOut);
136.84 - } catch (InterruptedException ex) {
136.85 - throw new IOException(ex);
136.86 - }
136.87 - return c;
136.88 - }
136.89 -
136.90 - public void setTimeout(long ms) {
136.91 - timeOut = ms;
136.92 - }
136.93 -
136.94 - public void addClassLoader(ClassLoader url) {
136.95 - this.loaders.add(url);
136.96 - }
136.97 -
136.98 - public void showURL(String startpage) throws IOException {
136.99 - if (!startpage.startsWith("/")) {
136.100 - startpage = "/" + startpage;
136.101 - }
136.102 - HttpServer s = initServer(".", true);
136.103 - int last = startpage.lastIndexOf('/');
136.104 - String simpleName = startpage.substring(last);
136.105 - s.getServerConfiguration().addHttpHandler(new Page(resources, startpage), simpleName);
136.106 - s.getServerConfiguration().addHttpHandler(new Page(resources, null), "/");
136.107 - try {
136.108 - launchServerAndBrwsr(s, simpleName);
136.109 - } catch (URISyntaxException | InterruptedException ex) {
136.110 - throw new IOException(ex);
136.111 - }
136.112 - }
136.113 -
136.114 - void showDirectory(File dir, String startpage) throws IOException {
136.115 - if (!startpage.startsWith("/")) {
136.116 - startpage = "/" + startpage;
136.117 - }
136.118 - HttpServer s = initServer(dir.getPath(), false);
136.119 - try {
136.120 - launchServerAndBrwsr(s, startpage);
136.121 - } catch (URISyntaxException | InterruptedException ex) {
136.122 - throw new IOException(ex);
136.123 - }
136.124 - }
136.125 -
136.126 - @Override
136.127 - public void initialize() throws IOException {
136.128 - try {
136.129 - executeInBrowser();
136.130 - } catch (InterruptedException ex) {
136.131 - final InterruptedIOException iio = new InterruptedIOException(ex.getMessage());
136.132 - iio.initCause(ex);
136.133 - throw iio;
136.134 - } catch (Exception ex) {
136.135 - if (ex instanceof IOException) {
136.136 - throw (IOException)ex;
136.137 - }
136.138 - if (ex instanceof RuntimeException) {
136.139 - throw (RuntimeException)ex;
136.140 - }
136.141 - throw new IOException(ex);
136.142 - }
136.143 - }
136.144 -
136.145 - private HttpServer initServer(String path, boolean addClasses) throws IOException {
136.146 - HttpServer s = HttpServer.createSimpleServer(path, new PortRange(8080, 65535));
136.147 -
136.148 - final ServerConfiguration conf = s.getServerConfiguration();
136.149 - if (addClasses) {
136.150 - conf.addHttpHandler(new VM(resources), "/bck2brwsr.js");
136.151 - conf.addHttpHandler(new Classes(resources), "/classes/");
136.152 - }
136.153 - return s;
136.154 - }
136.155 -
136.156 - private void executeInBrowser() throws InterruptedException, URISyntaxException, IOException {
136.157 - wait = new CountDownLatch(1);
136.158 - server = initServer(".", true);
136.159 - final ServerConfiguration conf = server.getServerConfiguration();
136.160 -
136.161 - class DynamicResourceHandler extends HttpHandler {
136.162 - private final InvocationContext ic;
136.163 - public DynamicResourceHandler(InvocationContext ic) {
136.164 - if (ic == null || ic.resources.isEmpty()) {
136.165 - throw new NullPointerException();
136.166 - }
136.167 - this.ic = ic;
136.168 - for (Resource r : ic.resources) {
136.169 - conf.addHttpHandler(this, r.httpPath);
136.170 - }
136.171 - }
136.172 -
136.173 - public void close() {
136.174 - conf.removeHttpHandler(this);
136.175 - }
136.176 -
136.177 - @Override
136.178 - public void service(Request request, Response response) throws Exception {
136.179 - for (Resource r : ic.resources) {
136.180 - if (r.httpPath.equals(request.getRequestURI())) {
136.181 - LOG.log(Level.INFO, "Serving HttpResource for {0}", request.getRequestURI());
136.182 - response.setContentType(r.httpType);
136.183 - copyStream(r.httpContent, response.getOutputStream(), null);
136.184 - }
136.185 - }
136.186 - }
136.187 - }
136.188 -
136.189 - conf.addHttpHandler(new Page(resources,
136.190 - "org/apidesign/bck2brwsr/launcher/harness.xhtml"
136.191 - ), "/execute");
136.192 -
136.193 - conf.addHttpHandler(new HttpHandler() {
136.194 - int cnt;
136.195 - List<InvocationContext> cases = new ArrayList<>();
136.196 - DynamicResourceHandler prev;
136.197 - @Override
136.198 - public void service(Request request, Response response) throws Exception {
136.199 - String id = request.getParameter("request");
136.200 - String value = request.getParameter("result");
136.201 - if (value != null && value.indexOf((char)0xC5) != -1) {
136.202 - value = toUTF8(value);
136.203 - }
136.204 -
136.205 -
136.206 - InvocationContext mi = null;
136.207 - int caseNmbr = -1;
136.208 -
136.209 - if (id != null && value != null) {
136.210 - LOG.log(Level.INFO, "Received result for case {0} = {1}", new Object[]{id, value});
136.211 - value = decodeURL(value);
136.212 - int indx = Integer.parseInt(id);
136.213 - cases.get(indx).result(value, null);
136.214 - if (++indx < cases.size()) {
136.215 - mi = cases.get(indx);
136.216 - LOG.log(Level.INFO, "Re-executing case {0}", indx);
136.217 - caseNmbr = indx;
136.218 - }
136.219 - } else {
136.220 - if (!cases.isEmpty()) {
136.221 - LOG.info("Re-executing test cases");
136.222 - mi = cases.get(0);
136.223 - caseNmbr = 0;
136.224 - }
136.225 - }
136.226 -
136.227 - if (prev != null) {
136.228 - prev.close();
136.229 - prev = null;
136.230 - }
136.231 -
136.232 - if (mi == null) {
136.233 - mi = methods.take();
136.234 - caseNmbr = cnt++;
136.235 - }
136.236 - if (mi == END) {
136.237 - response.getWriter().write("");
136.238 - wait.countDown();
136.239 - cnt = 0;
136.240 - LOG.log(Level.INFO, "End of data reached. Exiting.");
136.241 - return;
136.242 - }
136.243 -
136.244 - if (!mi.resources.isEmpty()) {
136.245 - prev = new DynamicResourceHandler(mi);
136.246 - }
136.247 -
136.248 - cases.add(mi);
136.249 - final String cn = mi.clazz.getName();
136.250 - final String mn = mi.methodName;
136.251 - LOG.log(Level.INFO, "Request for {0} case. Sending {1}.{2}", new Object[]{caseNmbr, cn, mn});
136.252 - response.getWriter().write("{"
136.253 - + "className: '" + cn + "', "
136.254 - + "methodName: '" + mn + "', "
136.255 - + "request: " + caseNmbr
136.256 - );
136.257 - if (mi.html != null) {
136.258 - response.getWriter().write(", html: '");
136.259 - response.getWriter().write(encodeJSON(mi.html));
136.260 - response.getWriter().write("'");
136.261 - }
136.262 - response.getWriter().write("}");
136.263 - }
136.264 - }, "/data");
136.265 -
136.266 - this.brwsr = launchServerAndBrwsr(server, "/execute");
136.267 - }
136.268 -
136.269 - private static String encodeJSON(String in) {
136.270 - StringBuilder sb = new StringBuilder();
136.271 - for (int i = 0; i < in.length(); i++) {
136.272 - char ch = in.charAt(i);
136.273 - if (ch < 32 || ch == '\'' || ch == '"') {
136.274 - sb.append("\\u");
136.275 - String hs = "0000" + Integer.toHexString(ch);
136.276 - hs = hs.substring(hs.length() - 4);
136.277 - sb.append(hs);
136.278 - } else {
136.279 - sb.append(ch);
136.280 - }
136.281 - }
136.282 - return sb.toString();
136.283 - }
136.284 -
136.285 - @Override
136.286 - public void shutdown() throws IOException {
136.287 - methods.offer(END);
136.288 - for (;;) {
136.289 - int prev = methods.size();
136.290 - try {
136.291 - if (wait != null && wait.await(timeOut, TimeUnit.MILLISECONDS)) {
136.292 - break;
136.293 - }
136.294 - } catch (InterruptedException ex) {
136.295 - throw new IOException(ex);
136.296 - }
136.297 - if (prev == methods.size()) {
136.298 - LOG.log(
136.299 - Level.WARNING,
136.300 - "Timeout and no test has been executed meanwhile (at {0}). Giving up.",
136.301 - methods.size()
136.302 - );
136.303 - break;
136.304 - }
136.305 - LOG.log(Level.INFO,
136.306 - "Timeout, but tests got from {0} to {1}. Trying again.",
136.307 - new Object[]{prev, methods.size()}
136.308 - );
136.309 - }
136.310 - stopServerAndBrwsr(server, brwsr);
136.311 - }
136.312 -
136.313 - static void copyStream(InputStream is, OutputStream os, String baseURL, String... params) throws IOException {
136.314 - for (;;) {
136.315 - int ch = is.read();
136.316 - if (ch == -1) {
136.317 - break;
136.318 - }
136.319 - if (ch == '$' && params.length > 0) {
136.320 - int cnt = is.read() - '0';
136.321 - if (cnt == 'U' - '0') {
136.322 - os.write(baseURL.getBytes("UTF-8"));
136.323 - }
136.324 - if (cnt >= 0 && cnt < params.length) {
136.325 - os.write(params[cnt].getBytes("UTF-8"));
136.326 - }
136.327 - } else {
136.328 - os.write(ch);
136.329 - }
136.330 - }
136.331 - }
136.332 -
136.333 - private Object[] launchServerAndBrwsr(HttpServer server, final String page) throws IOException, URISyntaxException, InterruptedException {
136.334 - server.start();
136.335 - NetworkListener listener = server.getListeners().iterator().next();
136.336 - int port = listener.getPort();
136.337 -
136.338 - URI uri = new URI("http://localhost:" + port + page);
136.339 - LOG.log(Level.INFO, "Showing {0}", uri);
136.340 - if (cmd == null) {
136.341 - try {
136.342 - LOG.log(Level.INFO, "Trying Desktop.browse on {0} {2} by {1}", new Object[] {
136.343 - System.getProperty("java.vm.name"),
136.344 - System.getProperty("java.vm.vendor"),
136.345 - System.getProperty("java.vm.version"),
136.346 - });
136.347 - java.awt.Desktop.getDesktop().browse(uri);
136.348 - LOG.log(Level.INFO, "Desktop.browse successfully finished");
136.349 - return null;
136.350 - } catch (UnsupportedOperationException ex) {
136.351 - LOG.log(Level.INFO, "Desktop.browse not supported: {0}", ex.getMessage());
136.352 - LOG.log(Level.FINE, null, ex);
136.353 - }
136.354 - }
136.355 - {
136.356 - String cmdName = cmd == null ? "xdg-open" : cmd;
136.357 - String[] cmdArr = {
136.358 - cmdName, uri.toString()
136.359 - };
136.360 - LOG.log(Level.INFO, "Launching {0}", Arrays.toString(cmdArr));
136.361 - final Process process = Runtime.getRuntime().exec(cmdArr);
136.362 - return new Object[] { process, null };
136.363 - }
136.364 - }
136.365 - private static String toUTF8(String value) throws UnsupportedEncodingException {
136.366 - byte[] arr = new byte[value.length()];
136.367 - for (int i = 0; i < arr.length; i++) {
136.368 - arr[i] = (byte)value.charAt(i);
136.369 - }
136.370 - return new String(arr, "UTF-8");
136.371 - }
136.372 -
136.373 - private static String decodeURL(String s) {
136.374 - for (;;) {
136.375 - int pos = s.indexOf('%');
136.376 - if (pos == -1) {
136.377 - return s;
136.378 - }
136.379 - int i = Integer.parseInt(s.substring(pos + 1, pos + 2), 16);
136.380 - s = s.substring(0, pos) + (char)i + s.substring(pos + 2);
136.381 - }
136.382 - }
136.383 -
136.384 - private void stopServerAndBrwsr(HttpServer server, Object[] brwsr) throws IOException {
136.385 - if (brwsr == null) {
136.386 - return;
136.387 - }
136.388 - Process process = (Process)brwsr[0];
136.389 -
136.390 - server.stop();
136.391 - InputStream stdout = process.getInputStream();
136.392 - InputStream stderr = process.getErrorStream();
136.393 - drain("StdOut", stdout);
136.394 - drain("StdErr", stderr);
136.395 - process.destroy();
136.396 - int res;
136.397 - try {
136.398 - res = process.waitFor();
136.399 - } catch (InterruptedException ex) {
136.400 - throw new IOException(ex);
136.401 - }
136.402 - LOG.log(Level.INFO, "Exit code: {0}", res);
136.403 -
136.404 - deleteTree((File)brwsr[1]);
136.405 - }
136.406 -
136.407 - private static void drain(String name, InputStream is) throws IOException {
136.408 - int av = is.available();
136.409 - if (av > 0) {
136.410 - StringBuilder sb = new StringBuilder();
136.411 - sb.append("v== ").append(name).append(" ==v\n");
136.412 - while (av-- > 0) {
136.413 - sb.append((char)is.read());
136.414 - }
136.415 - sb.append("\n^== ").append(name).append(" ==^");
136.416 - LOG.log(Level.INFO, sb.toString());
136.417 - }
136.418 - }
136.419 -
136.420 - private void deleteTree(File file) {
136.421 - if (file == null) {
136.422 - return;
136.423 - }
136.424 - File[] arr = file.listFiles();
136.425 - if (arr != null) {
136.426 - for (File s : arr) {
136.427 - deleteTree(s);
136.428 - }
136.429 - }
136.430 - file.delete();
136.431 - }
136.432 -
136.433 - @Override
136.434 - public void close() throws IOException {
136.435 - shutdown();
136.436 - }
136.437 -
136.438 - private class Res implements Bck2Brwsr.Resources {
136.439 - @Override
136.440 - public InputStream get(String resource) throws IOException {
136.441 - for (ClassLoader l : loaders) {
136.442 - URL u = null;
136.443 - Enumeration<URL> en = l.getResources(resource);
136.444 - while (en.hasMoreElements()) {
136.445 - u = en.nextElement();
136.446 - }
136.447 - if (u != null) {
136.448 - return u.openStream();
136.449 - }
136.450 - }
136.451 - throw new IOException("Can't find " + resource);
136.452 - }
136.453 - }
136.454 -
136.455 - private static class Page extends HttpHandler {
136.456 - private final String resource;
136.457 - private final String[] args;
136.458 - private final Res res;
136.459 -
136.460 - public Page(Res res, String resource, String... args) {
136.461 - this.res = res;
136.462 - this.resource = resource;
136.463 - this.args = args.length == 0 ? new String[] { "$0" } : args;
136.464 - }
136.465 -
136.466 - @Override
136.467 - public void service(Request request, Response response) throws Exception {
136.468 - String r = resource;
136.469 - if (r == null) {
136.470 - r = request.getHttpHandlerPath();
136.471 - }
136.472 - if (r.startsWith("/")) {
136.473 - r = r.substring(1);
136.474 - }
136.475 - String[] replace = {};
136.476 - if (r.endsWith(".html")) {
136.477 - response.setContentType("text/html");
136.478 - LOG.info("Content type text/html");
136.479 - replace = args;
136.480 - }
136.481 - if (r.endsWith(".xhtml")) {
136.482 - response.setContentType("application/xhtml+xml");
136.483 - LOG.info("Content type application/xhtml+xml");
136.484 - replace = args;
136.485 - }
136.486 - OutputStream os = response.getOutputStream();
136.487 - try (InputStream is = res.get(r)) {
136.488 - copyStream(is, os, request.getRequestURL().toString(), replace);
136.489 - } catch (IOException ex) {
136.490 - response.setDetailMessage(ex.getLocalizedMessage());
136.491 - response.setError();
136.492 - response.setStatus(404);
136.493 - }
136.494 - }
136.495 - }
136.496 -
136.497 - private static class VM extends HttpHandler {
136.498 - private final String bck2brwsr;
136.499 -
136.500 - public VM(Res loader) throws IOException {
136.501 - StringBuilder sb = new StringBuilder();
136.502 - Bck2Brwsr.generate(sb, loader);
136.503 - sb.append(
136.504 - "(function WrapperVM(global) {"
136.505 - + " function ldCls(res) {\n"
136.506 - + " var request = new XMLHttpRequest();\n"
136.507 - + " request.open('GET', '/classes/' + res, false);\n"
136.508 - + " request.send();\n"
136.509 - + " if (request.status !== 200) return null;\n"
136.510 - + " var arr = eval('(' + request.responseText + ')');\n"
136.511 - + " return arr;\n"
136.512 - + " }\n"
136.513 - + " var prevvm = global.bck2brwsr;\n"
136.514 - + " global.bck2brwsr = function() {\n"
136.515 - + " var args = Array.prototype.slice.apply(arguments);\n"
136.516 - + " args.unshift(ldCls);\n"
136.517 - + " return prevvm.apply(null, args);\n"
136.518 - + " };\n"
136.519 - + "})(this);\n"
136.520 - );
136.521 - this.bck2brwsr = sb.toString();
136.522 - }
136.523 -
136.524 - @Override
136.525 - public void service(Request request, Response response) throws Exception {
136.526 - response.setCharacterEncoding("UTF-8");
136.527 - response.setContentType("text/javascript");
136.528 - response.getWriter().write(bck2brwsr);
136.529 - }
136.530 - }
136.531 -
136.532 - private static class Classes extends HttpHandler {
136.533 - private final Res loader;
136.534 -
136.535 - public Classes(Res loader) {
136.536 - this.loader = loader;
136.537 - }
136.538 -
136.539 - @Override
136.540 - public void service(Request request, Response response) throws Exception {
136.541 - String res = request.getHttpHandlerPath();
136.542 - if (res.startsWith("/")) {
136.543 - res = res.substring(1);
136.544 - }
136.545 - try (InputStream is = loader.get(res)) {
136.546 - response.setContentType("text/javascript");
136.547 - Writer w = response.getWriter();
136.548 - w.append("[");
136.549 - for (int i = 0;; i++) {
136.550 - int b = is.read();
136.551 - if (b == -1) {
136.552 - break;
136.553 - }
136.554 - if (i > 0) {
136.555 - w.append(", ");
136.556 - }
136.557 - if (i % 20 == 0) {
136.558 - w.write("\n");
136.559 - }
136.560 - if (b > 127) {
136.561 - b = b - 256;
136.562 - }
136.563 - w.append(Integer.toString(b));
136.564 - }
136.565 - w.append("\n]");
136.566 - } catch (IOException ex) {
136.567 - response.setStatus(HttpStatus.NOT_FOUND_404);
136.568 - response.setError();
136.569 - response.setDetailMessage(ex.getMessage());
136.570 - }
136.571 - }
136.572 - }
136.573 -}
137.1 --- a/rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/InvocationContext.java Tue Apr 02 15:40:51 2013 +0200
137.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
137.3 @@ -1,110 +0,0 @@
137.4 -/**
137.5 - * Back 2 Browser Bytecode Translator
137.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
137.7 - *
137.8 - * This program is free software: you can redistribute it and/or modify
137.9 - * it under the terms of the GNU General Public License as published by
137.10 - * the Free Software Foundation, version 2 of the License.
137.11 - *
137.12 - * This program is distributed in the hope that it will be useful,
137.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
137.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
137.15 - * GNU General Public License for more details.
137.16 - *
137.17 - * You should have received a copy of the GNU General Public License
137.18 - * along with this program. Look for COPYING file in the top folder.
137.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
137.20 - */
137.21 -package org.apidesign.bck2brwsr.launcher;
137.22 -
137.23 -import java.io.IOException;
137.24 -import java.io.InputStream;
137.25 -import java.util.ArrayList;
137.26 -import java.util.List;
137.27 -import java.util.concurrent.CountDownLatch;
137.28 -import java.util.concurrent.TimeUnit;
137.29 -
137.30 -/** Represents individual method invocation, its context and its result.
137.31 - *
137.32 - * @author Jaroslav Tulach <jtulach@netbeans.org>
137.33 - */
137.34 -public final class InvocationContext {
137.35 - final CountDownLatch wait = new CountDownLatch(1);
137.36 - final Class<?> clazz;
137.37 - final String methodName;
137.38 - private final Launcher launcher;
137.39 - private String result;
137.40 - private Throwable exception;
137.41 - String html;
137.42 - final List<Resource> resources = new ArrayList<>();
137.43 -
137.44 - InvocationContext(Launcher launcher, Class<?> clazz, String methodName) {
137.45 - this.launcher = launcher;
137.46 - this.clazz = clazz;
137.47 - this.methodName = methodName;
137.48 - }
137.49 -
137.50 - /** An HTML fragment to be available for the execution. Useful primarily when
137.51 - * executing in a browser via {@link Launcher#createBrowser(java.lang.String)}.
137.52 - * @param html the html fragment
137.53 - */
137.54 - public void setHtmlFragment(String html) {
137.55 - this.html = html;
137.56 - }
137.57 -
137.58 - /** HTTP resource to be available during execution. An invocation may
137.59 - * perform an HTTP query and obtain a resource relative to the page.
137.60 - */
137.61 - public void addHttpResource(String relativePath, String mimeType, InputStream content) {
137.62 - if (relativePath == null || mimeType == null || content == null) {
137.63 - throw new NullPointerException();
137.64 - }
137.65 - resources.add(new Resource(content, mimeType, relativePath));
137.66 - }
137.67 -
137.68 - /** Invokes the associated method.
137.69 - * @return the textual result of the invocation
137.70 - */
137.71 - public String invoke() throws IOException {
137.72 - launcher.runMethod(this);
137.73 - return toString();
137.74 - }
137.75 -
137.76 - /** Obtains textual result of the invocation.
137.77 - * @return text representing the exception or result value
137.78 - */
137.79 - @Override
137.80 - public String toString() {
137.81 - if (exception != null) {
137.82 - return exception.toString();
137.83 - }
137.84 - return result;
137.85 - }
137.86 -
137.87 - /**
137.88 - * @param timeOut
137.89 - * @throws InterruptedException
137.90 - */
137.91 - void await(long timeOut) throws InterruptedException {
137.92 - wait.await(timeOut, TimeUnit.MILLISECONDS);
137.93 - }
137.94 -
137.95 - void result(String r, Throwable e) {
137.96 - this.result = r;
137.97 - this.exception = e;
137.98 - wait.countDown();
137.99 - }
137.100 -
137.101 -
137.102 - static final class Resource {
137.103 - final InputStream httpContent;
137.104 - final String httpType;
137.105 - final String httpPath;
137.106 -
137.107 - Resource(InputStream httpContent, String httpType, String httpPath) {
137.108 - this.httpContent = httpContent;
137.109 - this.httpType = httpType;
137.110 - this.httpPath = httpPath;
137.111 - }
137.112 - }
137.113 -}
138.1 --- a/rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/JSLauncher.java Tue Apr 02 15:40:51 2013 +0200
138.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
138.3 @@ -1,132 +0,0 @@
138.4 -/**
138.5 - * Back 2 Browser Bytecode Translator
138.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
138.7 - *
138.8 - * This program is free software: you can redistribute it and/or modify
138.9 - * it under the terms of the GNU General Public License as published by
138.10 - * the Free Software Foundation, version 2 of the License.
138.11 - *
138.12 - * This program is distributed in the hope that it will be useful,
138.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
138.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
138.15 - * GNU General Public License for more details.
138.16 - *
138.17 - * You should have received a copy of the GNU General Public License
138.18 - * along with this program. Look for COPYING file in the top folder.
138.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
138.20 - */
138.21 -package org.apidesign.bck2brwsr.launcher;
138.22 -
138.23 -import org.apidesign.bck2brwsr.launcher.impl.Console;
138.24 -import java.io.IOException;
138.25 -import java.io.InputStream;
138.26 -import java.net.URL;
138.27 -import java.util.Enumeration;
138.28 -import java.util.LinkedHashSet;
138.29 -import java.util.Set;
138.30 -import java.util.logging.Level;
138.31 -import java.util.logging.Logger;
138.32 -import javax.script.Invocable;
138.33 -import javax.script.ScriptEngine;
138.34 -import javax.script.ScriptEngineManager;
138.35 -import javax.script.ScriptException;
138.36 -import org.apidesign.vm4brwsr.Bck2Brwsr;
138.37 -
138.38 -/**
138.39 - * Tests execution in Java's internal scripting engine.
138.40 - */
138.41 -final class JSLauncher extends Launcher {
138.42 - private static final Logger LOG = Logger.getLogger(JSLauncher.class.getName());
138.43 - private Set<ClassLoader> loaders = new LinkedHashSet<>();
138.44 - private final Res resources = new Res();
138.45 - private Invocable code;
138.46 - private StringBuilder codeSeq;
138.47 - private Object console;
138.48 -
138.49 -
138.50 - @Override InvocationContext runMethod(InvocationContext mi) {
138.51 - loaders.add(mi.clazz.getClassLoader());
138.52 - try {
138.53 - long time = System.currentTimeMillis();
138.54 - LOG.log(Level.FINE, "Invoking {0}.{1}", new Object[]{mi.clazz.getName(), mi.methodName});
138.55 - String res = code.invokeMethod(
138.56 - console,
138.57 - "invoke__Ljava_lang_String_2Ljava_lang_String_2Ljava_lang_String_2",
138.58 - mi.clazz.getName(), mi.methodName).toString();
138.59 - time = System.currentTimeMillis() - time;
138.60 - LOG.log(Level.FINE, "Resut of {0}.{1} = {2} in {3} ms", new Object[]{mi.clazz.getName(), mi.methodName, res, time});
138.61 - mi.result(res, null);
138.62 - } catch (ScriptException | NoSuchMethodException ex) {
138.63 - mi.result(null, ex);
138.64 - }
138.65 - return mi;
138.66 - }
138.67 -
138.68 - public void addClassLoader(ClassLoader url) {
138.69 - this.loaders.add(url);
138.70 - }
138.71 -
138.72 - @Override
138.73 - public void initialize() throws IOException {
138.74 - try {
138.75 - initRhino();
138.76 - } catch (Exception ex) {
138.77 - if (ex instanceof IOException) {
138.78 - throw (IOException)ex;
138.79 - }
138.80 - if (ex instanceof RuntimeException) {
138.81 - throw (RuntimeException)ex;
138.82 - }
138.83 - throw new IOException(ex);
138.84 - }
138.85 - }
138.86 -
138.87 - private void initRhino() throws IOException, ScriptException, NoSuchMethodException {
138.88 - StringBuilder sb = new StringBuilder();
138.89 - Bck2Brwsr.generate(sb, new Res());
138.90 -
138.91 - ScriptEngineManager sem = new ScriptEngineManager();
138.92 - ScriptEngine mach = sem.getEngineByExtension("js");
138.93 -
138.94 - sb.append(
138.95 - "\nvar vm = new bck2brwsr(org.apidesign.bck2brwsr.launcher.impl.Console.read);"
138.96 - + "\nfunction initVM() { return vm; };"
138.97 - + "\n");
138.98 -
138.99 - Object res = mach.eval(sb.toString());
138.100 - if (!(mach instanceof Invocable)) {
138.101 - throw new IOException("It is invocable object: " + res);
138.102 - }
138.103 - code = (Invocable) mach;
138.104 - codeSeq = sb;
138.105 -
138.106 - Object vm = code.invokeFunction("initVM");
138.107 - console = code.invokeMethod(vm, "loadClass", Console.class.getName());
138.108 - }
138.109 -
138.110 - @Override
138.111 - public void shutdown() throws IOException {
138.112 - }
138.113 -
138.114 - @Override
138.115 - public String toString() {
138.116 - return codeSeq.toString();
138.117 - }
138.118 -
138.119 - private class Res implements Bck2Brwsr.Resources {
138.120 - @Override
138.121 - public InputStream get(String resource) throws IOException {
138.122 - for (ClassLoader l : loaders) {
138.123 - URL u = null;
138.124 - Enumeration<URL> en = l.getResources(resource);
138.125 - while (en.hasMoreElements()) {
138.126 - u = en.nextElement();
138.127 - }
138.128 - if (u != null) {
138.129 - return u.openStream();
138.130 - }
138.131 - }
138.132 - throw new IOException("Can't find " + resource);
138.133 - }
138.134 - }
138.135 -}
139.1 --- a/rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Launcher.java Tue Apr 02 15:40:51 2013 +0200
139.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
139.3 @@ -1,116 +0,0 @@
139.4 -/**
139.5 - * Back 2 Browser Bytecode Translator
139.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
139.7 - *
139.8 - * This program is free software: you can redistribute it and/or modify
139.9 - * it under the terms of the GNU General Public License as published by
139.10 - * the Free Software Foundation, version 2 of the License.
139.11 - *
139.12 - * This program is distributed in the hope that it will be useful,
139.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
139.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
139.15 - * GNU General Public License for more details.
139.16 - *
139.17 - * You should have received a copy of the GNU General Public License
139.18 - * along with this program. Look for COPYING file in the top folder.
139.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
139.20 - */
139.21 -package org.apidesign.bck2brwsr.launcher;
139.22 -
139.23 -import java.io.Closeable;
139.24 -import java.io.File;
139.25 -import java.io.IOException;
139.26 -import org.apidesign.vm4brwsr.Bck2Brwsr;
139.27 -
139.28 -/** An abstraction for executing tests in a Bck2Brwsr virtual machine.
139.29 - * Either in {@linkm Launcher#createJavaScript JavaScript engine},
139.30 - * or in {@linkm Launcher#createBrowser external browser}.
139.31 - * <p>
139.32 - * There also are methods to {@link #showDir(java.io.File, java.lang.String) display pages}
139.33 - * in an external browser served by internal HTTP server.
139.34 - *
139.35 - * @author Jaroslav Tulach <jtulach@netbeans.org>
139.36 - */
139.37 -public abstract class Launcher {
139.38 -
139.39 - Launcher() {
139.40 - }
139.41 -
139.42 - /** Initializes the launcher. This may mean starting a web browser or
139.43 - * initializing execution engine.
139.44 - * @throws IOException if something goes wrong
139.45 - */
139.46 - public abstract void initialize() throws IOException;
139.47 -
139.48 - /** Shuts down the launcher.
139.49 - * @throws IOException if something goes wrong
139.50 - */
139.51 - public abstract void shutdown() throws IOException;
139.52 -
139.53 -
139.54 - /** Builds an invocation context. The context can later be customized
139.55 - * and {@link InvocationContext#invoke() invoked}.
139.56 - *
139.57 - * @param clazz the class to execute method from
139.58 - * @param method the method to execute
139.59 - * @return the context pointing to the selected method
139.60 - */
139.61 - public InvocationContext createInvocation(Class<?> clazz, String method) {
139.62 - return new InvocationContext(this, clazz, method);
139.63 - }
139.64 -
139.65 -
139.66 - /** Creates launcher that uses internal JavaScript engine (Rhino).
139.67 - * @return the launcher
139.68 - */
139.69 - public static Launcher createJavaScript() {
139.70 - final JSLauncher l = new JSLauncher();
139.71 - l.addClassLoader(Bck2Brwsr.class.getClassLoader());
139.72 - return l;
139.73 - }
139.74 -
139.75 - /** Creates launcher that is using external browser.
139.76 - *
139.77 - * @param cmd <code>null</code> to use <code>java.awt.Desktop</code> to show the launcher
139.78 - * or a string to execute in an external process (with a parameter to the URL)
139.79 - * @return launcher executing in external browser.
139.80 - */
139.81 - public static Launcher createBrowser(String cmd) {
139.82 - final Bck2BrwsrLauncher l = new Bck2BrwsrLauncher(cmd);
139.83 - l.addClassLoader(Bck2Brwsr.class.getClassLoader());
139.84 - l.setTimeout(180000);
139.85 - return l;
139.86 - }
139.87 -
139.88 - /** Starts an HTTP server which provides access to classes and resources
139.89 - * available in the <code>classes</code> URL and shows a start page
139.90 - * available as {@link ClassLoader#getResource(java.lang.String)} from the
139.91 - * provide classloader. Opens a browser with URL showing the start page.
139.92 - *
139.93 - * @param classes classloader offering access to classes and resources
139.94 - * @param startpage page to show in the browser
139.95 - * @return interface that allows one to stop the server
139.96 - * @throws IOException if something goes wrong
139.97 - */
139.98 - public static Closeable showURL(ClassLoader classes, String startpage) throws IOException {
139.99 - Bck2BrwsrLauncher l = new Bck2BrwsrLauncher(null);
139.100 - l.addClassLoader(classes);
139.101 - l.showURL(startpage);
139.102 - return l;
139.103 - }
139.104 - /** Starts an HTTP server which provides access to certain directory.
139.105 - * The <code>startpage</code> should be relative location inside the root
139.106 - * directory. Opens a browser with URL showing the start page.
139.107 - *
139.108 - * @param directory the root directory on disk
139.109 - * @param startpage relative path from the root to the page
139.110 - * @exception IOException if something goes wrong.
139.111 - */
139.112 - public static Closeable showDir(File directory, String startpage) throws IOException {
139.113 - Bck2BrwsrLauncher l = new Bck2BrwsrLauncher(null);
139.114 - l.showDirectory(directory, startpage);
139.115 - return l;
139.116 - }
139.117 -
139.118 - abstract InvocationContext runMethod(InvocationContext c) throws IOException;
139.119 -}
140.1 --- a/rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/impl/Console.java Tue Apr 02 15:40:51 2013 +0200
140.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
140.3 @@ -1,260 +0,0 @@
140.4 -/**
140.5 - * Back 2 Browser Bytecode Translator
140.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
140.7 - *
140.8 - * This program is free software: you can redistribute it and/or modify
140.9 - * it under the terms of the GNU General Public License as published by
140.10 - * the Free Software Foundation, version 2 of the License.
140.11 - *
140.12 - * This program is distributed in the hope that it will be useful,
140.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
140.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
140.15 - * GNU General Public License for more details.
140.16 - *
140.17 - * You should have received a copy of the GNU General Public License
140.18 - * along with this program. Look for COPYING file in the top folder.
140.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
140.20 - */
140.21 -package org.apidesign.bck2brwsr.launcher.impl;
140.22 -
140.23 -import java.io.IOException;
140.24 -import java.io.InputStream;
140.25 -import java.io.UnsupportedEncodingException;
140.26 -import java.lang.reflect.InvocationTargetException;
140.27 -import java.lang.reflect.Method;
140.28 -import java.lang.reflect.Modifier;
140.29 -import java.net.URL;
140.30 -import java.util.Enumeration;
140.31 -import org.apidesign.bck2brwsr.core.JavaScriptBody;
140.32 -
140.33 -/**
140.34 - *
140.35 - * @author Jaroslav Tulach <jtulach@netbeans.org>
140.36 - */
140.37 -public class Console {
140.38 - private Console() {
140.39 - }
140.40 - static {
140.41 - turnAssetionStatusOn();
140.42 - }
140.43 -
140.44 - @JavaScriptBody(args = {"id", "attr"}, body =
140.45 - "return window.document.getElementById(id)[attr].toString();")
140.46 - private static native Object getAttr(String id, String attr);
140.47 -
140.48 - @JavaScriptBody(args = {"id", "attr", "value"}, body =
140.49 - "window.document.getElementById(id)[attr] = value;")
140.50 - private static native void setAttr(String id, String attr, Object value);
140.51 -
140.52 - @JavaScriptBody(args = {}, body = "return; window.close();")
140.53 - private static native void closeWindow();
140.54 -
140.55 - private static void log(String newText) {
140.56 - String id = "bck2brwsr.result";
140.57 - String attr = "value";
140.58 - setAttr(id, attr, getAttr(id, attr) + "\n" + newText);
140.59 - setAttr(id, "scrollTop", getAttr(id, "scrollHeight"));
140.60 - }
140.61 -
140.62 - public static void execute() throws Exception {
140.63 - String clazz = (String) getAttr("clazz", "value");
140.64 - String method = (String) getAttr("method", "value");
140.65 - Object res = invokeMethod(clazz, method);
140.66 - setAttr("bck2brwsr.result", "value", res);
140.67 - }
140.68 -
140.69 - @JavaScriptBody(args = { "url", "callback", "arr" }, body = ""
140.70 - + "var request = new XMLHttpRequest();\n"
140.71 - + "request.open('GET', url, true);\n"
140.72 - + "request.setRequestHeader('Content-Type', 'text/plain; charset=utf-8');\n"
140.73 - + "request.onreadystatechange = function() {\n"
140.74 - + " if (this.readyState!==4) return;\n"
140.75 - + " arr[0] = this.responseText;\n"
140.76 - + " callback.run__V();\n"
140.77 - + "};"
140.78 - + "request.send();"
140.79 - )
140.80 - private static native void loadText(String url, Runnable callback, String[] arr) throws IOException;
140.81 -
140.82 - public static void harness(String url) throws IOException {
140.83 - log("Connecting to " + url);
140.84 - Request r = new Request(url);
140.85 - }
140.86 -
140.87 - private static class Request implements Runnable {
140.88 - private final String[] arr = { null };
140.89 - private final String url;
140.90 -
140.91 - private Request(String url) throws IOException {
140.92 - this.url = url;
140.93 - loadText(url, this, arr);
140.94 - }
140.95 -
140.96 - @Override
140.97 - public void run() {
140.98 - try {
140.99 - String data = arr[0];
140.100 - log("\nGot \"" + data + "\"");
140.101 -
140.102 - if (data == null) {
140.103 - log("Some error exiting");
140.104 - closeWindow();
140.105 - return;
140.106 - }
140.107 -
140.108 - if (data.isEmpty()) {
140.109 - log("No data, exiting");
140.110 - closeWindow();
140.111 - return;
140.112 - }
140.113 -
140.114 - Case c = Case.parseData(data);
140.115 - if (c.getHtmlFragment() != null) {
140.116 - setAttr("bck2brwsr.fragment", "innerHTML", c.getHtmlFragment());
140.117 - }
140.118 - log("Invoking " + c.getClassName() + '.' + c.getMethodName() + " as request: " + c.getRequestId());
140.119 -
140.120 - Object result = invokeMethod(c.getClassName(), c.getMethodName());
140.121 -
140.122 - setAttr("bck2brwsr.fragment", "innerHTML", "");
140.123 - log("Result: " + result);
140.124 -
140.125 - result = encodeURL("" + result);
140.126 -
140.127 - log("Sending back: " + url + "?request=" + c.getRequestId() + "&result=" + result);
140.128 - String u = url + "?request=" + c.getRequestId() + "&result=" + result;
140.129 -
140.130 - loadText(u, this, arr);
140.131 -
140.132 - } catch (Exception ex) {
140.133 - log(ex.getClass().getName() + ":" + ex.getMessage());
140.134 - }
140.135 - }
140.136 - }
140.137 -
140.138 - private static String encodeURL(String r) throws UnsupportedEncodingException {
140.139 - final String SPECIAL = "%$&+,/:;=?@";
140.140 - StringBuilder sb = new StringBuilder();
140.141 - byte[] utf8 = r.getBytes("UTF-8");
140.142 - for (int i = 0; i < utf8.length; i++) {
140.143 - int ch = utf8[i] & 0xff;
140.144 - if (ch < 32 || ch > 127 || SPECIAL.indexOf(ch) >= 0) {
140.145 - final String numbers = "0" + Integer.toHexString(ch);
140.146 - sb.append("%").append(numbers.substring(numbers.length() - 2));
140.147 - } else {
140.148 - if (ch == 32) {
140.149 - sb.append("+");
140.150 - } else {
140.151 - sb.append((char)ch);
140.152 - }
140.153 - }
140.154 - }
140.155 - return sb.toString();
140.156 - }
140.157 -
140.158 - static String invoke(String clazz, String method) throws ClassNotFoundException, InvocationTargetException, IllegalAccessException, InstantiationException {
140.159 - final Object r = invokeMethod(clazz, method);
140.160 - return r == null ? "null" : r.toString().toString();
140.161 - }
140.162 -
140.163 - /** Helper method that inspects the classpath and loads given resource
140.164 - * (usually a class file). Used while running tests in Rhino.
140.165 - *
140.166 - * @param name resource name to find
140.167 - * @return the array of bytes in the given resource
140.168 - * @throws IOException I/O in case something goes wrong
140.169 - */
140.170 - public static byte[] read(String name) throws IOException {
140.171 - URL u = null;
140.172 - Enumeration<URL> en = Console.class.getClassLoader().getResources(name);
140.173 - while (en.hasMoreElements()) {
140.174 - u = en.nextElement();
140.175 - }
140.176 - if (u == null) {
140.177 - throw new IOException("Can't find " + name);
140.178 - }
140.179 - try (InputStream is = u.openStream()) {
140.180 - byte[] arr;
140.181 - arr = new byte[is.available()];
140.182 - int offset = 0;
140.183 - while (offset < arr.length) {
140.184 - int len = is.read(arr, offset, arr.length - offset);
140.185 - if (len == -1) {
140.186 - throw new IOException("Can't read " + name);
140.187 - }
140.188 - offset += len;
140.189 - }
140.190 - return arr;
140.191 - }
140.192 - }
140.193 -
140.194 - private static Object invokeMethod(String clazz, String method)
140.195 - throws ClassNotFoundException, InvocationTargetException,
140.196 - SecurityException, IllegalAccessException, IllegalArgumentException,
140.197 - InstantiationException {
140.198 - Method found = null;
140.199 - Class<?> c = Class.forName(clazz);
140.200 - for (Method m : c.getMethods()) {
140.201 - if (m.getName().equals(method)) {
140.202 - found = m;
140.203 - }
140.204 - }
140.205 - Object res;
140.206 - if (found != null) {
140.207 - try {
140.208 - if ((found.getModifiers() & Modifier.STATIC) != 0) {
140.209 - res = found.invoke(null);
140.210 - } else {
140.211 - res = found.invoke(c.newInstance());
140.212 - }
140.213 - } catch (Throwable ex) {
140.214 - res = ex.getClass().getName() + ":" + ex.getMessage();
140.215 - }
140.216 - } else {
140.217 - res = "Can't find method " + method + " in " + clazz;
140.218 - }
140.219 - return res;
140.220 - }
140.221 -
140.222 - @JavaScriptBody(args = {}, body = "vm.desiredAssertionStatus = true;")
140.223 - private static void turnAssetionStatusOn() {
140.224 - }
140.225 -
140.226 - private static final class Case {
140.227 - private final Object data;
140.228 -
140.229 - private Case(Object data) {
140.230 - this.data = data;
140.231 - }
140.232 -
140.233 - public static Case parseData(String s) {
140.234 - return new Case(toJSON(s));
140.235 - }
140.236 -
140.237 - public String getMethodName() {
140.238 - return value("methodName", data);
140.239 - }
140.240 -
140.241 - public String getClassName() {
140.242 - return value("className", data);
140.243 - }
140.244 -
140.245 - public String getRequestId() {
140.246 - return value("request", data);
140.247 - }
140.248 -
140.249 - public String getHtmlFragment() {
140.250 - return value("html", data);
140.251 - }
140.252 -
140.253 - @JavaScriptBody(args = "s", body = "return eval('(' + s + ')');")
140.254 - private static native Object toJSON(String s);
140.255 -
140.256 - @JavaScriptBody(args = {"p", "d"}, body =
140.257 - "var v = d[p];\n"
140.258 - + "if (typeof v === 'undefined') return null;\n"
140.259 - + "return v.toString();"
140.260 - )
140.261 - private static native String value(String p, Object d);
140.262 - }
140.263 -}
141.1 --- a/rt/launcher/src/main/resources/org/apidesign/bck2brwsr/launcher/harness.xhtml Tue Apr 02 15:40:51 2013 +0200
141.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
141.3 @@ -1,43 +0,0 @@
141.4 -<?xml version="1.0" encoding="UTF-8"?>
141.5 -<!--
141.6 -
141.7 - Back 2 Browser Bytecode Translator
141.8 - Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
141.9 -
141.10 - This program is free software: you can redistribute it and/or modify
141.11 - it under the terms of the GNU General Public License as published by
141.12 - the Free Software Foundation, version 2 of the License.
141.13 -
141.14 - This program is distributed in the hope that it will be useful,
141.15 - but WITHOUT ANY WARRANTY; without even the implied warranty of
141.16 - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
141.17 - GNU General Public License for more details.
141.18 -
141.19 - You should have received a copy of the GNU General Public License
141.20 - along with this program. Look for COPYING file in the top folder.
141.21 - If not, see http://opensource.org/licenses/GPL-2.0.
141.22 -
141.23 --->
141.24 -<!DOCTYPE html>
141.25 -<html xmlns="http://www.w3.org/1999/xhtml">
141.26 - <head>
141.27 - <title>Bck2Brwsr Harness</title>
141.28 - </head>
141.29 - <body>
141.30 - <script src="/bck2brwsr.js"></script>
141.31 - <script>
141.32 - var vm = bck2brwsr();
141.33 - </script>
141.34 -
141.35 - <h1>Bck2Brwsr Execution Harness</h1>
141.36 -
141.37 - <textarea id="bck2brwsr.result" rows="25" style="width: 100%;" disabled="">
141.38 - </textarea>
141.39 -
141.40 - <div id="bck2brwsr.fragment"/>
141.41 -
141.42 - <script type="text/javascript">
141.43 - vm.loadClass('org.apidesign.bck2brwsr.launcher.impl.Console').harness__VLjava_lang_String_2('$U/../data');
141.44 - </script>
141.45 - </body>
141.46 -</html>
142.1 --- a/rt/mojo/pom.xml Tue Apr 02 15:40:51 2013 +0200
142.2 +++ b/rt/mojo/pom.xml Thu May 02 09:18:22 2013 +0200
142.3 @@ -4,14 +4,14 @@
142.4 <parent>
142.5 <groupId>org.apidesign.bck2brwsr</groupId>
142.6 <artifactId>rt</artifactId>
142.7 - <version>0.5-SNAPSHOT</version>
142.8 + <version>0.8-SNAPSHOT</version>
142.9 </parent>
142.10 <groupId>org.apidesign.bck2brwsr</groupId>
142.11 - <artifactId>mojo</artifactId>
142.12 - <version>0.5-SNAPSHOT</version>
142.13 + <artifactId>bck2brwsr-maven-plugin</artifactId>
142.14 + <version>0.8-SNAPSHOT</version>
142.15 <packaging>maven-plugin</packaging>
142.16 - <name>Bck2Brwsr Maven Project</name>
142.17 - <url>http://maven.apache.org</url>
142.18 + <name>Bck2Brwsr Maven Plugin</name>
142.19 + <url>http://bck2brwsr.apidesign.org/</url>
142.20 <build>
142.21 <plugins>
142.22 <plugin>
142.23 @@ -62,7 +62,7 @@
142.24 <dependency>
142.25 <groupId>${project.groupId}</groupId>
142.26 <artifactId>vm4brwsr</artifactId>
142.27 - <version>0.5-SNAPSHOT</version>
142.28 + <version>${project.version}</version>
142.29 <exclusions>
142.30 <exclusion>
142.31 <artifactId>emul.mini</artifactId>
142.32 @@ -82,10 +82,14 @@
142.33 <version>${project.version}</version>
142.34 </dependency>
142.35 <dependency>
142.36 - <groupId>org.testng</groupId>
142.37 - <artifactId>testng</artifactId>
142.38 - <version>6.5.2</version>
142.39 - <scope>test</scope>
142.40 + <groupId>${project.groupId}</groupId>
142.41 + <artifactId>launcher.http</artifactId>
142.42 + <version>${project.version}</version>
142.43 + </dependency>
142.44 + <dependency>
142.45 + <groupId>${project.groupId}</groupId>
142.46 + <artifactId>launcher.fx</artifactId>
142.47 + <version>${project.version}</version>
142.48 </dependency>
142.49 </dependencies>
142.50 </project>
143.1 --- a/rt/mojo/src/main/java/org/apidesign/bck2brwsr/mojo/BrswrMojo.java Tue Apr 02 15:40:51 2013 +0200
143.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
143.3 @@ -1,99 +0,0 @@
143.4 -/**
143.5 - * Back 2 Browser Bytecode Translator
143.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
143.7 - *
143.8 - * This program is free software: you can redistribute it and/or modify
143.9 - * it under the terms of the GNU General Public License as published by
143.10 - * the Free Software Foundation, version 2 of the License.
143.11 - *
143.12 - * This program is distributed in the hope that it will be useful,
143.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
143.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
143.15 - * GNU General Public License for more details.
143.16 - *
143.17 - * You should have received a copy of the GNU General Public License
143.18 - * along with this program. Look for COPYING file in the top folder.
143.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
143.20 - */
143.21 -package org.apidesign.bck2brwsr.mojo;
143.22 -
143.23 -import java.io.Closeable;
143.24 -import org.apache.maven.plugin.AbstractMojo;
143.25 -
143.26 -import java.io.File;
143.27 -import java.io.IOException;
143.28 -import java.net.MalformedURLException;
143.29 -import java.net.URL;
143.30 -import java.net.URLClassLoader;
143.31 -import java.util.ArrayList;
143.32 -import java.util.Collection;
143.33 -import java.util.List;
143.34 -import org.apache.maven.artifact.Artifact;
143.35 -import org.apache.maven.plugin.MojoExecutionException;
143.36 -import org.apache.maven.plugins.annotations.LifecyclePhase;
143.37 -import org.apache.maven.plugins.annotations.Mojo;
143.38 -import org.apache.maven.plugins.annotations.Parameter;
143.39 -import org.apache.maven.project.MavenProject;
143.40 -import org.apidesign.bck2brwsr.launcher.Launcher;
143.41 -
143.42 -/** Executes given HTML page in a browser. */
143.43 -@Mojo(name="brwsr", defaultPhase=LifecyclePhase.NONE)
143.44 -public class BrswrMojo extends AbstractMojo {
143.45 - public BrswrMojo() {
143.46 - }
143.47 - /** Resource to show as initial page */
143.48 - @Parameter
143.49 - private String startpage;
143.50 -
143.51 - @Parameter(defaultValue="${project}")
143.52 - private MavenProject prj;
143.53 -
143.54 - /** Root of the class files */
143.55 - @Parameter(defaultValue="${project.build.directory}/classes")
143.56 - private File classes;
143.57 -
143.58 - /** Root of all pages, and files, etc. */
143.59 - @Parameter
143.60 - private File directory;
143.61 -
143.62 - @Override
143.63 - public void execute() throws MojoExecutionException {
143.64 - if (startpage == null) {
143.65 - throw new MojoExecutionException("You have to provide a start page");
143.66 - }
143.67 -
143.68 - try {
143.69 - Closeable httpServer;
143.70 - if (directory != null) {
143.71 - httpServer = Launcher.showDir(directory, startpage);
143.72 - } else {
143.73 - URLClassLoader url = buildClassLoader(classes, prj.getDependencyArtifacts());
143.74 - try {
143.75 - httpServer = Launcher.showURL(url, startpage());
143.76 - } catch (Exception ex) {
143.77 - throw new MojoExecutionException("Can't open " + startpage(), ex);
143.78 - }
143.79 - }
143.80 - System.in.read();
143.81 - httpServer.close();
143.82 - } catch (IOException ex) {
143.83 - throw new MojoExecutionException("Can't show the browser", ex);
143.84 - }
143.85 - }
143.86 -
143.87 - private String startpage() {
143.88 - return startpage;
143.89 - }
143.90 -
143.91 - private static URLClassLoader buildClassLoader(File root, Collection<Artifact> deps) throws MalformedURLException {
143.92 - List<URL> arr = new ArrayList<URL>();
143.93 - arr.add(root.toURI().toURL());
143.94 - for (Artifact a : deps) {
143.95 - final File f = a.getFile();
143.96 - if (f != null) {
143.97 - arr.add(f.toURI().toURL());
143.98 - }
143.99 - }
143.100 - return new URLClassLoader(arr.toArray(new URL[0]), BrswrMojo.class.getClassLoader());
143.101 - }
143.102 -}
144.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
144.2 +++ b/rt/mojo/src/main/java/org/apidesign/bck2brwsr/mojo/BrwsrMojo.java Thu May 02 09:18:22 2013 +0200
144.3 @@ -0,0 +1,108 @@
144.4 +/**
144.5 + * Back 2 Browser Bytecode Translator
144.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
144.7 + *
144.8 + * This program is free software: you can redistribute it and/or modify
144.9 + * it under the terms of the GNU General Public License as published by
144.10 + * the Free Software Foundation, version 2 of the License.
144.11 + *
144.12 + * This program is distributed in the hope that it will be useful,
144.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
144.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
144.15 + * GNU General Public License for more details.
144.16 + *
144.17 + * You should have received a copy of the GNU General Public License
144.18 + * along with this program. Look for COPYING file in the top folder.
144.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
144.20 + */
144.21 +package org.apidesign.bck2brwsr.mojo;
144.22 +
144.23 +import java.io.Closeable;
144.24 +import org.apache.maven.plugin.AbstractMojo;
144.25 +
144.26 +import java.io.File;
144.27 +import java.io.IOException;
144.28 +import java.net.MalformedURLException;
144.29 +import java.net.URL;
144.30 +import java.net.URLClassLoader;
144.31 +import java.util.ArrayList;
144.32 +import java.util.Collection;
144.33 +import java.util.List;
144.34 +import org.apache.maven.artifact.Artifact;
144.35 +import org.apache.maven.plugin.MojoExecutionException;
144.36 +import org.apache.maven.plugins.annotations.LifecyclePhase;
144.37 +import org.apache.maven.plugins.annotations.Mojo;
144.38 +import org.apache.maven.plugins.annotations.Parameter;
144.39 +import org.apache.maven.project.MavenProject;
144.40 +import org.apidesign.bck2brwsr.launcher.Launcher;
144.41 +
144.42 +/** Executes given HTML page in a browser. */
144.43 +@Mojo(name="brwsr", defaultPhase=LifecyclePhase.NONE)
144.44 +public class BrwsrMojo extends AbstractMojo {
144.45 + public BrwsrMojo() {
144.46 + }
144.47 +
144.48 + /** The identification of a launcher to use. Known values <code>fxbrwsr</code>,
144.49 + * <code>bck2brwsr</code>, or
144.50 + * name of an external process to execute.
144.51 + */
144.52 + @Parameter
144.53 + private String launcher;
144.54 +
144.55 +
144.56 + /** Resource to show as initial page */
144.57 + @Parameter
144.58 + private String startpage;
144.59 +
144.60 + @Parameter(defaultValue="${project}")
144.61 + private MavenProject prj;
144.62 +
144.63 + /** Root of the class files */
144.64 + @Parameter(defaultValue="${project.build.directory}/classes")
144.65 + private File classes;
144.66 +
144.67 + /** Root of all pages, and files, etc. */
144.68 + @Parameter
144.69 + private File directory;
144.70 +
144.71 + @Override
144.72 + public void execute() throws MojoExecutionException {
144.73 + if (startpage == null) {
144.74 + throw new MojoExecutionException("You have to provide a start page");
144.75 + }
144.76 +
144.77 + try {
144.78 + Closeable httpServer;
144.79 + if (directory != null) {
144.80 + httpServer = Launcher.showDir(directory, startpage);
144.81 + } else {
144.82 + URLClassLoader url = buildClassLoader(classes, prj.getDependencyArtifacts());
144.83 + try {
144.84 + httpServer = Launcher.showURL(launcher, url, startpage());
144.85 + } catch (Exception ex) {
144.86 + throw new MojoExecutionException("Can't open " + startpage(), ex);
144.87 + }
144.88 + }
144.89 + System.in.read();
144.90 + httpServer.close();
144.91 + } catch (IOException ex) {
144.92 + throw new MojoExecutionException("Can't show the browser", ex);
144.93 + }
144.94 + }
144.95 +
144.96 + private String startpage() {
144.97 + return startpage;
144.98 + }
144.99 +
144.100 + private static URLClassLoader buildClassLoader(File root, Collection<Artifact> deps) throws MalformedURLException {
144.101 + List<URL> arr = new ArrayList<URL>();
144.102 + arr.add(root.toURI().toURL());
144.103 + for (Artifact a : deps) {
144.104 + final File f = a.getFile();
144.105 + if (f != null) {
144.106 + arr.add(f.toURI().toURL());
144.107 + }
144.108 + }
144.109 + return new URLClassLoader(arr.toArray(new URL[0]), BrwsrMojo.class.getClassLoader());
144.110 + }
144.111 +}
145.1 --- a/rt/mojo/src/main/java/org/apidesign/bck2brwsr/mojo/Java2JavaScript.java Tue Apr 02 15:40:51 2013 +0200
145.2 +++ b/rt/mojo/src/main/java/org/apidesign/bck2brwsr/mojo/Java2JavaScript.java Thu May 02 09:18:22 2013 +0200
145.3 @@ -35,6 +35,7 @@
145.4 import org.apache.maven.plugins.annotations.Parameter;
145.5 import org.apache.maven.project.MavenProject;
145.6 import org.apidesign.vm4brwsr.Bck2Brwsr;
145.7 +import org.apidesign.vm4brwsr.ObfuscationLevel;
145.8
145.9 /** Compiles classes into JavaScript. */
145.10 @Mojo(name="j2js", defaultPhase=LifecyclePhase.PROCESS_CLASSES)
145.11 @@ -47,7 +48,7 @@
145.12 /** JavaScript file to generate */
145.13 @Parameter
145.14 private File javascript;
145.15 -
145.16 +
145.17 /** Additional classes that should be pre-compiled into the javascript
145.18 * file. By default compiles all classes found under <code>classes</code>
145.19 * directory and their transitive closure.
145.20 @@ -57,8 +58,14 @@
145.21
145.22 @Parameter(defaultValue="${project}")
145.23 private MavenProject prj;
145.24 -
145.25 -
145.26 +
145.27 + /**
145.28 + * The obfuscation level for the generated JavaScript file.
145.29 + *
145.30 + * @since 0.5
145.31 + */
145.32 + @Parameter(defaultValue="NONE")
145.33 + private ObfuscationLevel obfuscation;
145.34
145.35 @Override
145.36 public void execute() throws MojoExecutionException {
145.37 @@ -81,7 +88,11 @@
145.38 try {
145.39 URLClassLoader url = buildClassLoader(classes, prj.getDependencyArtifacts());
145.40 FileWriter w = new FileWriter(javascript);
145.41 - Bck2Brwsr.generate(w, url, arr.toArray(new String[0]));
145.42 + Bck2Brwsr.newCompiler().
145.43 + obfuscation(obfuscation).
145.44 + resources(url).
145.45 + addRootClasses(arr.toArray(new String[0])).
145.46 + generate(w);
145.47 w.close();
145.48 } catch (IOException ex) {
145.49 throw new MojoExecutionException("Can't compile", ex);
146.1 --- a/rt/mojo/src/main/resources/META-INF/maven/archetype-metadata.xml Tue Apr 02 15:40:51 2013 +0200
146.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
146.3 @@ -1,55 +0,0 @@
146.4 -<?xml version="1.0" encoding="UTF-8"?>
146.5 -<!--
146.6 -
146.7 - Back 2 Browser Bytecode Translator
146.8 - Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
146.9 -
146.10 - This program is free software: you can redistribute it and/or modify
146.11 - it under the terms of the GNU General Public License as published by
146.12 - the Free Software Foundation, version 2 of the License.
146.13 -
146.14 - This program is distributed in the hope that it will be useful,
146.15 - but WITHOUT ANY WARRANTY; without even the implied warranty of
146.16 - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
146.17 - GNU General Public License for more details.
146.18 -
146.19 - You should have received a copy of the GNU General Public License
146.20 - along with this program. Look for COPYING file in the top folder.
146.21 - If not, see http://opensource.org/licenses/GPL-2.0.
146.22 -
146.23 --->
146.24 -<archetype-descriptor name="Get Java Bck2Brwsr!">
146.25 - <fileSets>
146.26 - <fileSet filtered="true" packaged="true">
146.27 - <directory>src/main/java</directory>
146.28 - <includes>
146.29 - <include>**/App.java</include>
146.30 - </includes>
146.31 - </fileSet>
146.32 - <fileSet filtered="true" packaged="true">
146.33 - <directory>src/main/resources</directory>
146.34 - <includes>
146.35 - <include>**/*.xhtml</include>
146.36 - <include>**/*.html</include>
146.37 - </includes>
146.38 - </fileSet>
146.39 - <fileSet filtered="true" packaged="true">
146.40 - <directory>src/test/java</directory>
146.41 - <includes>
146.42 - <include>**/*Test.java</include>
146.43 - </includes>
146.44 - </fileSet>
146.45 - <fileSet filtered="false" packaged="false">
146.46 - <directory></directory>
146.47 - <includes>
146.48 - <include>nbactions.xml</include>
146.49 - </includes>
146.50 - </fileSet>
146.51 - <fileSet filtered="true" packaged="false">
146.52 - <directory></directory>
146.53 - <includes>
146.54 - <include>bck2brwsr-assembly.xml</include>
146.55 - </includes>
146.56 - </fileSet>
146.57 - </fileSets>
146.58 -</archetype-descriptor>
146.59 \ No newline at end of file
147.1 --- a/rt/mojo/src/main/resources/archetype-resources/bck2brwsr-assembly.xml Tue Apr 02 15:40:51 2013 +0200
147.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
147.3 @@ -1,61 +0,0 @@
147.4 -<?xml version="1.0"?>
147.5 -<!--
147.6 -
147.7 - Back 2 Browser Bytecode Translator
147.8 - Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
147.9 -
147.10 - This program is free software: you can redistribute it and/or modify
147.11 - it under the terms of the GNU General Public License as published by
147.12 - the Free Software Foundation, version 2 of the License.
147.13 -
147.14 - This program is distributed in the hope that it will be useful,
147.15 - but WITHOUT ANY WARRANTY; without even the implied warranty of
147.16 - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
147.17 - GNU General Public License for more details.
147.18 -
147.19 - You should have received a copy of the GNU General Public License
147.20 - along with this program. Look for COPYING file in the top folder.
147.21 - If not, see http://opensource.org/licenses/GPL-2.0.
147.22 -
147.23 --->
147.24 -<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
147.25 - xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
147.26 -
147.27 - <id>bck2brwsr</id>
147.28 - <formats>
147.29 - <format>zip</format>
147.30 - </formats>
147.31 - <baseDirectory>public_html</baseDirectory>
147.32 - <dependencySets>
147.33 - <dependencySet>
147.34 - <useProjectArtifact>false</useProjectArtifact>
147.35 - <scope>runtime</scope>
147.36 - <outputDirectory>lib</outputDirectory>
147.37 - <includes>
147.38 - <include>*:jar</include>
147.39 - <include>*:rt</include>
147.40 - </includes>
147.41 - </dependencySet>
147.42 - <dependencySet>
147.43 - <useProjectArtifact>false</useProjectArtifact>
147.44 - <scope>provided</scope>
147.45 - <includes>
147.46 - <include>*:js</include>
147.47 - </includes>
147.48 - <unpack>true</unpack>
147.49 - <outputDirectory>/</outputDirectory>
147.50 - </dependencySet>
147.51 - </dependencySets>
147.52 - <files>
147.53 - <file>
147.54 - <source>${project.build.directory}/${project.build.finalName}.jar</source>
147.55 - <outputDirectory>/</outputDirectory>
147.56 - </file>
147.57 - <file>
147.58 - <source>${project.build.directory}/classes/${package.replace('.','/')}/index.html</source>
147.59 - <outputDirectory>/</outputDirectory>
147.60 - <destName>index.html</destName>
147.61 - </file>
147.62 - </files>
147.63 -
147.64 -</assembly>
147.65 \ No newline at end of file
148.1 --- a/rt/mojo/src/main/resources/archetype-resources/nbactions.xml Tue Apr 02 15:40:51 2013 +0200
148.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
148.3 @@ -1,10 +0,0 @@
148.4 -<?xml version="1.0" encoding="UTF-8"?>
148.5 -<actions>
148.6 - <action>
148.7 - <actionName>run</actionName>
148.8 - <goals>
148.9 - <goal>process-classes</goal>
148.10 - <goal>org.apidesign.bck2brwsr:mojo:0.5-SNAPSHOT:brwsr</goal>
148.11 - </goals>
148.12 - </action>
148.13 -</actions>
149.1 --- a/rt/mojo/src/main/resources/archetype-resources/pom.xml Tue Apr 02 15:40:51 2013 +0200
149.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
149.3 @@ -1,135 +0,0 @@
149.4 -<?xml version="1.0"?>
149.5 -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
149.6 - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
149.7 - <modelVersion>4.0.0</modelVersion>
149.8 -
149.9 - <groupId>${groupId}</groupId>
149.10 - <artifactId>${artifactId}</artifactId>
149.11 - <version>${version}</version>
149.12 - <packaging>jar</packaging>
149.13 -
149.14 - <name>${artifactId}</name>
149.15 -
149.16 - <repositories>
149.17 - <repository>
149.18 - <id>java.net</id>
149.19 - <name>Java.net</name>
149.20 - <url>https://maven.java.net/content/repositories/releases/</url>
149.21 - <snapshots>
149.22 - <enabled>true</enabled>
149.23 - </snapshots>
149.24 - </repository>
149.25 - <repository>
149.26 - <id>netbeans</id>
149.27 - <name>NetBeans</name>
149.28 - <url>http://bits.netbeans.org/maven2/</url>
149.29 - </repository>
149.30 - </repositories>
149.31 - <pluginRepositories>
149.32 - <pluginRepository>
149.33 - <id>java.net</id>
149.34 - <name>Java.net</name>
149.35 - <url>https://maven.java.net/content/repositories/releases/</url>
149.36 - <snapshots>
149.37 - <enabled>true</enabled>
149.38 - </snapshots>
149.39 - </pluginRepository>
149.40 - </pluginRepositories>
149.41 -
149.42 - <properties>
149.43 - <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
149.44 - </properties>
149.45 - <build>
149.46 - <plugins>
149.47 - <plugin>
149.48 - <groupId>org.apidesign.bck2brwsr</groupId>
149.49 - <artifactId>mojo</artifactId>
149.50 - <version>0.5-SNAPSHOT</version>
149.51 - <executions>
149.52 - <execution>
149.53 - <goals>
149.54 - <goal>brwsr</goal>
149.55 - </goals>
149.56 - </execution>
149.57 - </executions>
149.58 - <configuration>
149.59 - <startpage>${package.replace('.','/')}/index.html</startpage>
149.60 - </configuration>
149.61 - </plugin>
149.62 - <plugin>
149.63 - <groupId>org.apache.maven.plugins</groupId>
149.64 - <artifactId>maven-compiler-plugin</artifactId>
149.65 - <version>2.3.2</version>
149.66 - <configuration>
149.67 - <source>1.7</source>
149.68 - <target>1.7</target>
149.69 - </configuration>
149.70 - </plugin>
149.71 - <plugin>
149.72 - <groupId>org.apache.maven.plugins</groupId>
149.73 - <artifactId>maven-jar-plugin</artifactId>
149.74 - <version>2.4</version>
149.75 - <configuration>
149.76 - <archive>
149.77 - <manifest>
149.78 - <addClasspath>true</addClasspath>
149.79 - <classpathPrefix>lib/</classpathPrefix>
149.80 - </manifest>
149.81 - </archive>
149.82 - </configuration>
149.83 - </plugin>
149.84 - <plugin>
149.85 - <artifactId>maven-assembly-plugin</artifactId>
149.86 - <version>2.4</version>
149.87 - <executions>
149.88 - <execution>
149.89 - <id>distro-assembly</id>
149.90 - <phase>package</phase>
149.91 - <goals>
149.92 - <goal>single</goal>
149.93 - </goals>
149.94 - <configuration>
149.95 - <descriptors>
149.96 - <descriptor>bck2brwsr-assembly.xml</descriptor>
149.97 - </descriptors>
149.98 - </configuration>
149.99 - </execution>
149.100 - </executions>
149.101 - </plugin>
149.102 - </plugins>
149.103 - </build>
149.104 -
149.105 - <dependencies>
149.106 - <dependency>
149.107 - <groupId>org.apidesign.bck2brwsr</groupId>
149.108 - <artifactId>emul</artifactId>
149.109 - <version>0.5-SNAPSHOT</version>
149.110 - <classifier>rt</classifier>
149.111 - </dependency>
149.112 - <dependency>
149.113 - <groupId>org.apidesign.bck2brwsr</groupId>
149.114 - <artifactId>javaquery.api</artifactId>
149.115 - <version>0.5-SNAPSHOT</version>
149.116 - </dependency>
149.117 - <dependency>
149.118 - <groupId>org.testng</groupId>
149.119 - <artifactId>testng</artifactId>
149.120 - <version>6.5.2</version>
149.121 - <scope>test</scope>
149.122 - </dependency>
149.123 - <dependency>
149.124 - <groupId>org.apidesign.bck2brwsr</groupId>
149.125 - <artifactId>vm4brwsr</artifactId>
149.126 - <classifier>js</classifier>
149.127 - <type>zip</type>
149.128 - <version>0.5-SNAPSHOT</version>
149.129 - <scope>provided</scope>
149.130 - </dependency>
149.131 - <dependency>
149.132 - <groupId>org.apidesign.bck2brwsr</groupId>
149.133 - <artifactId>vmtest</artifactId>
149.134 - <version>0.5-SNAPSHOT</version>
149.135 - <scope>test</scope>
149.136 - </dependency>
149.137 - </dependencies>
149.138 -</project>
150.1 --- a/rt/mojo/src/main/resources/archetype-resources/src/main/java/App.java Tue Apr 02 15:40:51 2013 +0200
150.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
150.3 @@ -1,34 +0,0 @@
150.4 -package ${package};
150.5 -
150.6 -import org.apidesign.bck2brwsr.htmlpage.api.*;
150.7 -import static org.apidesign.bck2brwsr.htmlpage.api.OnEvent.*;
150.8 -import org.apidesign.bck2brwsr.htmlpage.api.Page;
150.9 -import org.apidesign.bck2brwsr.htmlpage.api.Property;
150.10 -import org.apidesign.bck2brwsr.htmlpage.api.ComputedProperty;
150.11 -
150.12 -/** Edit the index.xhtml file. Use 'id' to name certain HTML elements.
150.13 - * Use this class to define behavior of the elements.
150.14 - */
150.15 -@Page(xhtml="index.html", className="Index", properties={
150.16 - @Property(name="name", type=String.class)
150.17 -})
150.18 -public class App {
150.19 - static {
150.20 - Index model = new Index();
150.21 - model.setName("World");
150.22 - model.applyBindings();
150.23 - }
150.24 -
150.25 - @On(event = CLICK, id="hello")
150.26 - static void hello(Index m) {
150.27 - GraphicsContext g = m.CANVAS.getContext();
150.28 - g.clearRect(0, 0, 1000, 1000);
150.29 - g.setFont("italic 40px Calibri");
150.30 - g.fillText(m.getHelloMessage(), 10, 40);
150.31 - }
150.32 -
150.33 - @ComputedProperty
150.34 - static String helloMessage(String name) {
150.35 - return "Hello " + name + "!";
150.36 - }
150.37 -}
151.1 --- a/rt/mojo/src/main/resources/archetype-resources/src/main/resources/index.html Tue Apr 02 15:40:51 2013 +0200
151.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
151.3 @@ -1,22 +0,0 @@
151.4 -<?xml version="1.0" encoding="UTF-8"?>
151.5 -<!DOCTYPE html>
151.6 -<html xmlns="http://www.w3.org/1999/xhtml">
151.7 - <head>
151.8 - <title>Bck2Brwsr's Hello World</title>
151.9 - </head>
151.10 - <body>
151.11 - <h1 data-bind="text: helloMessage">Loading Bck2Brwsr's Hello World...</h1>
151.12 - Your name: <input id='input' data-bind="value: name, valueUpdate: 'afterkeydown'"></input>
151.13 - <button id="hello">Say Hello!</button>
151.14 - <p>
151.15 - <canvas id="canvas" width="300" height="50">
151.16 - </canvas>
151.17 - </p>
151.18 -
151.19 - <script src="bck2brwsr.js"></script>
151.20 - <script type="text/javascript">
151.21 - var vm = bck2brwsr('${artifactId}-${version}.jar');
151.22 - vm.loadClass('${package}.App');
151.23 - </script>
151.24 - </body>
151.25 -</html>
152.1 --- a/rt/mojo/src/main/resources/archetype-resources/src/test/java/AppTest.java Tue Apr 02 15:40:51 2013 +0200
152.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
152.3 @@ -1,26 +0,0 @@
152.4 -package ${package};
152.5 -
152.6 -import static org.testng.Assert.*;
152.7 -import org.testng.annotations.BeforeMethod;
152.8 -import org.testng.annotations.Test;
152.9 -
152.10 -/** Demonstrating POJO testing of HTML page model. Runs in good old HotSpot
152.11 - * as it does not reference any HTML elements or browser functionality. Just
152.12 - * operates on the page model.
152.13 - *
152.14 - * @author Jaroslav Tulach <jtulach@netbeans.org>
152.15 - */
152.16 -public class AppTest {
152.17 - private Index model;
152.18 -
152.19 -
152.20 - @BeforeMethod
152.21 - public void initModel() {
152.22 - model = new Index().applyBindings();
152.23 - }
152.24 -
152.25 - @Test public void testHelloMessage() {
152.26 - model.setName("Joe");
152.27 - assertEquals(model.getHelloMessage(), "Hello Joe!", "Cleared after pressing +");
152.28 - }
152.29 -}
153.1 --- a/rt/mojo/src/main/resources/archetype-resources/src/test/java/InconsistencyTest.java Tue Apr 02 15:40:51 2013 +0200
153.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
153.3 @@ -1,40 +0,0 @@
153.4 -package ${package};
153.5 -
153.6 -import org.apidesign.bck2brwsr.vmtest.Compare;
153.7 -import org.apidesign.bck2brwsr.vmtest.VMTest;
153.8 -import org.testng.annotations.Factory;
153.9 -
153.10 -/** Bck2brwsr cares about compatibility with real Java. Whatever API is
153.11 - * supported by bck2brwsr, it needs to behave the same way as when running
153.12 - * in HotSpot VM.
153.13 - * <p>
153.14 - * There can be bugs, however. To help us fix them, we kindly ask you to
153.15 - * write an "inconsistency" test. A test that compares behavior of the API
153.16 - * between real VM and bck2brwsr VM. This class is skeleton of such test.
153.17 - *
153.18 - * @author Jaroslav Tulach <jtulach@netbeans.org>
153.19 - */
153.20 -public class InconsistencyTest {
153.21 - /** A method to demonstrate inconsistency between bck2brwsr and HotSpot.
153.22 - * Make calls to an API that behaves strangely, return some result at
153.23 - * the end. No need to use any <code>assert</code>.
153.24 - *
153.25 - * @return value to compare between HotSpot and bck2brwsr
153.26 - */
153.27 - @Compare
153.28 - public int checkStringHashCode() throws Exception {
153.29 - return "Is string hashCode the same?".hashCode();
153.30 - }
153.31 -
153.32 - /** Factory method that creates a three tests for each method annotated with
153.33 - * {@link org.apidesign.bck2brwsr.vmtest.Compare}. One executes the code in
153.34 - * HotSpot, one in Rhino and the last one compares the results.
153.35 - *
153.36 - * @see org.apidesign.bck2brwsr.vmtest.VMTest
153.37 - */
153.38 - @Factory
153.39 - public static Object[] create() {
153.40 - return VMTest.create(InconsistencyTest.class);
153.41 - }
153.42 -
153.43 -}
154.1 --- a/rt/mojo/src/main/resources/archetype-resources/src/test/java/IntegrationTest.java Tue Apr 02 15:40:51 2013 +0200
154.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
154.3 @@ -1,46 +0,0 @@
154.4 -package ${package};
154.5 -
154.6 -import org.apidesign.bck2brwsr.htmlpage.api.OnEvent;
154.7 -import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
154.8 -import org.apidesign.bck2brwsr.vmtest.HtmlFragment;
154.9 -import org.apidesign.bck2brwsr.vmtest.VMTest;
154.10 -import org.testng.annotations.Factory;
154.11 -
154.12 -/** Sometimes it is useful to run tests inside of the real browser.
154.13 - * To do that just annotate your method with {@link org.apidesign.bck2brwsr.vmtest.BrwsrTest}
154.14 - * and that is it. If your code references elements on the HTML page,
154.15 - * you can pass in an {@link org.apidesign.bck2brwsr.vmtest.HtmlFragment} which
154.16 - * will be made available on the page before your test starts.
154.17 - *
154.18 - * @author Jaroslav Tulach <jtulach@netbeans.org>
154.19 - */
154.20 -public class IntegrationTest {
154.21 -
154.22 - /** Write to testing code here. Use <code>assert</code> (but not TestNG's
154.23 - * Assert, as TestNG is not compiled with target 1.6 yet).
154.24 - */
154.25 - @HtmlFragment(
154.26 - "<h1 data-bind=\"text: helloMessage\">Loading Bck2Brwsr's Hello World...</h1>\n" +
154.27 - "Your name: <input id='input' data-bind=\"value: name, valueUpdate: 'afterkeydown'\"></input>\n" +
154.28 - "<button id=\"hello\">Say Hello!</button>\n" +
154.29 - "<p>\n" +
154.30 - " <canvas id=\"canvas\" width=\"300\" height=\"50\"></canvas>\n" +
154.31 - "</p>\n"
154.32 - )
154.33 - @BrwsrTest
154.34 - public void modifyValueAssertChangeInModel() {
154.35 - Index m = new Index();
154.36 - m.setName("Joe Hacker");
154.37 - m.applyBindings();
154.38 - assert "Joe Hacker".equals(m.INPUT.getValue()) : "Value is really Joe Hacker: " + m.INPUT.getValue();
154.39 - m.INPUT.setValue("Happy Joe");
154.40 - m.triggerEvent(m.INPUT, OnEvent.CHANGE);
154.41 - assert "Happy Joe".equals(m.getName()) : "Name property updated to Happy Joe: " + m.getName();
154.42 - }
154.43 -
154.44 - @Factory
154.45 - public static Object[] create() {
154.46 - return VMTest.create(IntegrationTest.class);
154.47 - }
154.48 -
154.49 -}
155.1 --- a/rt/mojo/src/test/java/org/apidesign/bck2brwsr/mojo/ArchetypeVersionTest.java Tue Apr 02 15:40:51 2013 +0200
155.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
155.3 @@ -1,102 +0,0 @@
155.4 -/**
155.5 - * Back 2 Browser Bytecode Translator
155.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
155.7 - *
155.8 - * This program is free software: you can redistribute it and/or modify
155.9 - * it under the terms of the GNU General Public License as published by
155.10 - * the Free Software Foundation, version 2 of the License.
155.11 - *
155.12 - * This program is distributed in the hope that it will be useful,
155.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
155.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
155.15 - * GNU General Public License for more details.
155.16 - *
155.17 - * You should have received a copy of the GNU General Public License
155.18 - * along with this program. Look for COPYING file in the top folder.
155.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
155.20 - */
155.21 -package org.apidesign.bck2brwsr.mojo;
155.22 -
155.23 -import java.net.URL;
155.24 -import javax.xml.XMLConstants;
155.25 -import javax.xml.parsers.DocumentBuilderFactory;
155.26 -import javax.xml.xpath.XPathConstants;
155.27 -import javax.xml.xpath.XPathExpression;
155.28 -import javax.xml.xpath.XPathFactory;
155.29 -import org.testng.annotations.Test;
155.30 -import org.xml.sax.InputSource;
155.31 -import static org.testng.Assert.*;
155.32 -import org.testng.annotations.BeforeClass;
155.33 -import org.w3c.dom.Document;
155.34 -import org.w3c.dom.NodeList;
155.35 -
155.36 -/**
155.37 - *
155.38 - * @author Jaroslav Tulach <jtulach@netbeans.org>
155.39 - */
155.40 -public class ArchetypeVersionTest {
155.41 - private String version;
155.42 -
155.43 - public ArchetypeVersionTest() {
155.44 - }
155.45 -
155.46 - @BeforeClass public void readCurrentVersion() throws Exception {
155.47 - final ClassLoader l = ArchetypeVersionTest.class.getClassLoader();
155.48 - URL u = l.getResource("META-INF/maven/org.apidesign.bck2brwsr/mojo/plugin-help.xml");
155.49 - assertNotNull(u, "Own pom found");
155.50 -
155.51 - final XPathFactory fact = XPathFactory.newInstance();
155.52 - fact.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
155.53 -
155.54 - XPathExpression xp = fact.newXPath().compile("plugin/version/text()");
155.55 - version = xp.evaluate(new InputSource(u.openStream()));
155.56 -
155.57 - assertFalse(version.isEmpty(), "There should be some version string");
155.58 - }
155.59 -
155.60 -
155.61 - @Test public void testComparePomDepsVersions() throws Exception {
155.62 - final ClassLoader l = ArchetypeVersionTest.class.getClassLoader();
155.63 - URL r = l.getResource("archetype-resources/pom.xml");
155.64 - assertNotNull(r, "Archetype pom found");
155.65 -
155.66 - final XPathFactory fact = XPathFactory.newInstance();
155.67 - XPathExpression xp2 = fact.newXPath().compile(
155.68 - "//version[../groupId/text() = 'org.apidesign.bck2brwsr']/text()"
155.69 - );
155.70 -
155.71 - Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(r.openStream());
155.72 - NodeList arch = (NodeList) xp2.evaluate(dom, XPathConstants.NODESET);
155.73 -
155.74 - if (arch.getLength() < 3) {
155.75 - fail("There should be at least three dependencies to bck2brwsr APIs: " + arch.getLength());
155.76 - }
155.77 -
155.78 - for (int i = 0; i < arch.getLength(); i++) {
155.79 - assertEquals(arch.item(i).getTextContent(), version, i + "th dependency needs to be on latest version of bck2brwsr");
155.80 - }
155.81 - }
155.82 -
155.83 - @Test public void testNbActions() throws Exception {
155.84 - final ClassLoader l = ArchetypeVersionTest.class.getClassLoader();
155.85 - URL r = l.getResource("archetype-resources/nbactions.xml");
155.86 - assertNotNull(r, "Archetype nb file found");
155.87 -
155.88 - final XPathFactory fact = XPathFactory.newInstance();
155.89 - XPathExpression xp2 = fact.newXPath().compile(
155.90 - "//goal/text()"
155.91 - );
155.92 -
155.93 - Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(r.openStream());
155.94 - NodeList goals = (NodeList) xp2.evaluate(dom, XPathConstants.NODESET);
155.95 -
155.96 - for (int i = 0; i < goals.getLength(); i++) {
155.97 - String s = goals.item(i).getTextContent();
155.98 - if (s.contains("bck2brwsr")) {
155.99 - String[] arr = s.split(":");
155.100 - assertEquals(arr.length, 4, "Three :");
155.101 - assertEquals(arr[2], version, "Proper version is used");
155.102 - }
155.103 - }
155.104 - }
155.105 -}
156.1 --- a/rt/pom.xml Tue Apr 02 15:40:51 2013 +0200
156.2 +++ b/rt/pom.xml Thu May 02 09:18:22 2013 +0200
156.3 @@ -3,18 +3,18 @@
156.4 <modelVersion>4.0.0</modelVersion>
156.5 <groupId>org.apidesign.bck2brwsr</groupId>
156.6 <artifactId>rt</artifactId>
156.7 - <version>0.5-SNAPSHOT</version>
156.8 + <version>0.8-SNAPSHOT</version>
156.9 <packaging>pom</packaging>
156.10 <name>Bck2Brwsr Runtime</name>
156.11 <parent>
156.12 <groupId>org.apidesign</groupId>
156.13 <artifactId>bck2brwsr</artifactId>
156.14 - <version>0.5-SNAPSHOT</version>
156.15 + <version>0.8-SNAPSHOT</version>
156.16 </parent>
156.17 <modules>
156.18 <module>core</module>
156.19 <module>emul</module>
156.20 - <module>launcher</module>
156.21 + <module>archetype</module>
156.22 <module>mojo</module>
156.23 <module>vm</module>
156.24 <module>vmtest</module>
157.1 --- a/rt/vm/pom.xml Tue Apr 02 15:40:51 2013 +0200
157.2 +++ b/rt/vm/pom.xml Thu May 02 09:18:22 2013 +0200
157.3 @@ -3,12 +3,12 @@
157.4 <parent>
157.5 <groupId>org.apidesign.bck2brwsr</groupId>
157.6 <artifactId>rt</artifactId>
157.7 - <version>0.5-SNAPSHOT</version>
157.8 + <version>0.8-SNAPSHOT</version>
157.9 </parent>
157.10
157.11 <groupId>org.apidesign.bck2brwsr</groupId>
157.12 <artifactId>vm4brwsr</artifactId>
157.13 - <version>0.5-SNAPSHOT</version>
157.14 + <version>0.8-SNAPSHOT</version>
157.15 <packaging>jar</packaging>
157.16
157.17 <name>Virtual Machine for Browser</name>
157.18 @@ -83,18 +83,24 @@
157.19 <execution>
157.20 <id>generate-js</id>
157.21 <phase>process-classes</phase>
157.22 + <configuration>
157.23 + <executable>java</executable>
157.24 + <arguments>
157.25 + <argument>-Dskip.if.exists=true</argument>
157.26 + <argument>-cp</argument>
157.27 + <classpath />
157.28 + <argument>org.apidesign.vm4brwsr.Main</argument>
157.29 + <argument>--obfuscatelevel</argument>
157.30 + <argument>MINIMAL</argument>
157.31 + <argument>${project.build.directory}/bck2brwsr.js</argument>
157.32 + <argument>org/apidesign/vm4brwsr/Bck2Brwsr</argument>
157.33 + </arguments>
157.34 + </configuration>
157.35 <goals>
157.36 - <goal>java</goal>
157.37 + <goal>exec</goal>
157.38 </goals>
157.39 </execution>
157.40 </executions>
157.41 - <configuration>
157.42 - <mainClass>org.apidesign.vm4brwsr.Main</mainClass>
157.43 - <arguments>
157.44 - <argument>${project.build.directory}/bck2brwsr.js</argument>
157.45 - <argument>org/apidesign/vm4brwsr/Bck2Brwsr</argument>
157.46 - </arguments>
157.47 - </configuration>
157.48 </plugin>
157.49 <plugin>
157.50 <artifactId>maven-assembly-plugin</artifactId>
157.51 @@ -140,5 +146,11 @@
157.52 <version>${project.version}</version>
157.53 <scope>compile</scope>
157.54 </dependency>
157.55 + <dependency>
157.56 + <groupId>com.google.javascript</groupId>
157.57 + <artifactId>closure-compiler</artifactId>
157.58 + <version>r2388</version>
157.59 + <scope>compile</scope>
157.60 + </dependency>
157.61 </dependencies>
157.62 </project>
158.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/Bck2Brwsr.java Tue Apr 02 15:40:51 2013 +0200
158.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/Bck2Brwsr.java Thu May 02 09:18:22 2013 +0200
158.3 @@ -54,46 +54,127 @@
158.4 * @author Jaroslav Tulach <jtulach@netbeans.org>
158.5 */
158.6 public final class Bck2Brwsr {
158.7 - private Bck2Brwsr() {
158.8 + private final ObfuscationLevel level;
158.9 + private final StringArray classes;
158.10 + private final Resources res;
158.11 +
158.12 + private Bck2Brwsr(ObfuscationLevel level, StringArray classes, Resources resources) {
158.13 + this.level = level;
158.14 + this.classes = classes;
158.15 + this.res = resources;
158.16 }
158.17
158.18 - /** Generates virtual machine from bytes served by a <code>resources</code>
158.19 + /** Helper method to generate virtual machine from bytes served by a <code>resources</code>
158.20 * provider.
158.21 - *
158.22 + *
158.23 * @param out the output to write the generated JavaScript to
158.24 * @param resources provider of class files to use
158.25 * @param classes additional classes to include in the generated script
158.26 * @throws IOException I/O exception can be thrown when something goes wrong
158.27 */
158.28 public static void generate(Appendable out, Resources resources, String... classes) throws IOException {
158.29 - StringArray arr = StringArray.asList(classes);
158.30 - arr.add(VM.class.getName().replace('.', '/'));
158.31 - VM.compile(resources, out, arr);
158.32 + newCompiler().resources(resources).addRootClasses(classes).generate(out);
158.33 }
158.34 -
158.35 - /** Generates virtual machine from bytes served by a class loader.
158.36 - *
158.37 +
158.38 + /** Helper method to generate virtual machine from bytes served by a class loader.
158.39 + *
158.40 * @param out the output to write the generated JavaScript to
158.41 * @param loader class loader to load needed classes from
158.42 * @param classes additional classes to include in the generated script
158.43 * @throws IOException I/O exception can be thrown when something goes wrong
158.44 */
158.45 - public static void generate(Appendable out, final ClassLoader loader, String... classes) throws IOException {
158.46 - class R implements Resources {
158.47 - @Override
158.48 - public InputStream get(String name) throws IOException {
158.49 - Enumeration<URL> en = loader.getResources(name);
158.50 - URL u = null;
158.51 - while (en.hasMoreElements()) {
158.52 - u = en.nextElement();
158.53 - }
158.54 - if (u == null) {
158.55 - throw new IOException("Can't find " + name);
158.56 - }
158.57 - return u.openStream();
158.58 + public static void generate(Appendable out, ClassLoader loader, String... classes) throws IOException {
158.59 + newCompiler().resources(loader).addRootClasses(classes).generate(out);
158.60 + }
158.61 +
158.62 + /** Creates new instance of Bck2Brwsr compiler which is ready to generate
158.63 + * empty Bck2Brwsr virtual machine. The instance can be further
158.64 + * configured by calling chain of methods. For example:
158.65 + * <pre>
158.66 + * {@link #createCompiler()}.{@link #resources(org.apidesign.vm4brwsr.Bck2Brwsr.Resources) resources(loader)}.{@link #addRootClasses(java.lang.String[]) addRootClasses("your/Clazz")}.{@link #generate(java.lang.Appendable) generate(out)};
158.67 + * </pre>
158.68 + *
158.69 + * @return new instance of the Bck2Brwsr compiler
158.70 + * @since 0.5
158.71 + */
158.72 + public static Bck2Brwsr newCompiler() {
158.73 + StringArray arr = StringArray.asList(VM.class.getName().replace('.', '/'));
158.74 + return new Bck2Brwsr(ObfuscationLevel.NONE, arr, null);
158.75 + }
158.76 +
158.77 + /** Creates new instance of the Bck2Brwsr compiler which inherits
158.78 + * all values from <code>this</code> instance and adds additional classes
158.79 + * to the list of those that should be compiled by the {@link #generate(java.lang.Appendable)}
158.80 + * method.
158.81 + *
158.82 + * @param classes the classes to add to the compilation
158.83 + * @return new instance of the compiler
158.84 + */
158.85 + public Bck2Brwsr addRootClasses(String... classes) {
158.86 + if (classes.length == 0) {
158.87 + return this;
158.88 + } else {
158.89 + return new Bck2Brwsr(level, this.classes.addAndNew(classes), res);
158.90 + }
158.91 + }
158.92 +
158.93 + /** Changes the obfuscation level for the compiler by creating new instance
158.94 + * which inherits all values from <code>this</code> and adjust the level
158.95 + * of obfuscation.
158.96 + *
158.97 + * @param level the new level of obfuscation
158.98 + * @return new instance of the compiler with changed level of obfuscation
158.99 + * @since 0.5
158.100 + */
158.101 + public Bck2Brwsr obfuscation(ObfuscationLevel level) {
158.102 + return new Bck2Brwsr(level, classes, res);
158.103 + }
158.104 +
158.105 + /** A way to change the provider of additional resources (classes) for the
158.106 + * compiler.
158.107 + *
158.108 + * @param res the implementation of resources provider
158.109 + * @return new instance of the compiler with all values remaining the same, just
158.110 + * with different resources provider
158.111 + * @since 0.5
158.112 + */
158.113 + public Bck2Brwsr resources(Resources res) {
158.114 + return new Bck2Brwsr(level, classes, res);
158.115 + }
158.116 +
158.117 + /** A way to change the provider of additional resources (classes) for the
158.118 + * compiler by specifying classloader to use for loading them.
158.119 + *
158.120 + * @param loader class loader to load the resources from
158.121 + * @return new instance of the compiler with all values being the same, just
158.122 + * different resources provider
158.123 + * @since 0.5
158.124 + */
158.125 + public Bck2Brwsr resources(final ClassLoader loader) {
158.126 + return resources(new LdrRsrcs(loader));
158.127 + }
158.128 +
158.129 + /** Generates virtual machine based on previous configuration of the
158.130 + * compiler.
158.131 + *
158.132 + * @param out the output to write the generated JavaScript to
158.133 + * @since 0.5
158.134 + */
158.135 + public void generate(Appendable out) throws IOException {
158.136 + Resources r = res != null ? res : new LdrRsrcs(Bck2Brwsr.class.getClassLoader());
158.137 + if (level != ObfuscationLevel.NONE) {
158.138 + try {
158.139 + ClosureWrapper.produceTo(out, level, r, classes);
158.140 + return;
158.141 + } catch (IOException ex) {
158.142 + throw ex;
158.143 + } catch (Throwable ex) {
158.144 + out.append("/* Failed to obfuscate: " + ex.getMessage()
158.145 + + " */\n");
158.146 }
158.147 }
158.148 - generate(out, new R(), classes);
158.149 +
158.150 + VM.compile(r, out, classes);
158.151 }
158.152
158.153 /** Provider of resources (classes and other files). The
159.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Tue Apr 02 15:40:51 2013 +0200
159.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Thu May 02 09:18:22 2013 +0200
159.3 @@ -28,9 +28,16 @@
159.4 abstract class ByteCodeToJavaScript {
159.5 private ClassData jc;
159.6 final Appendable out;
159.7 + final ObfuscationDelegate obfuscationDelegate;
159.8
159.9 protected ByteCodeToJavaScript(Appendable out) {
159.10 + this(out, ObfuscationDelegate.NULL);
159.11 + }
159.12 +
159.13 + protected ByteCodeToJavaScript(
159.14 + Appendable out, ObfuscationDelegate obfuscationDelegate) {
159.15 this.out = out;
159.16 + this.obfuscationDelegate = obfuscationDelegate;
159.17 }
159.18
159.19 /* Collects additional required resources.
159.20 @@ -58,7 +65,9 @@
159.21 /* protected */ String accessClass(String classOperation) {
159.22 return classOperation;
159.23 }
159.24 -
159.25 +
159.26 + abstract String getVMObject();
159.27 +
159.28 /** Prints out a debug message.
159.29 *
159.30 * @param msg the message
159.31 @@ -92,7 +101,9 @@
159.32 "resource", "processByteCode"
159.33 );
159.34 if (arr != null) {
159.35 - requireScript(arr[0]);
159.36 + if (!arr[0].isEmpty()) {
159.37 + requireScript(arr[0]);
159.38 + }
159.39 if ("0".equals(arr[1])) {
159.40 return null;
159.41 }
159.42 @@ -104,7 +115,8 @@
159.43 StringArray toInitilize = new StringArray();
159.44 final String className = className(jc);
159.45 out.append("\n\n").append(assignClass(className));
159.46 - out.append("function CLS() {");
159.47 + out.append("function ").append(className).append("() {");
159.48 + out.append("\n var CLS = ").append(className).append(';');
159.49 out.append("\n if (!CLS.$class) {");
159.50 if (proto == null) {
159.51 String sc = jc.getSuperClassName(); // with _
159.52 @@ -136,6 +148,8 @@
159.53 append(className).append('_').append(v.getName())
159.54 .append("; };");
159.55 }
159.56 +
159.57 + obfuscationDelegate.exportField(out, "c", "_" + v.getName(), v);
159.58 }
159.59 for (MethodData m : jc.getMethods()) {
159.60 byte[] onlyArr = m.findAnnotationData(true);
159.61 @@ -150,33 +164,39 @@
159.62 }
159.63 continue;
159.64 }
159.65 - String prefix;
159.66 + String destObject;
159.67 String mn;
159.68 + out.append("\n ");
159.69 if (m.isStatic()) {
159.70 - prefix = "\n c.";
159.71 - mn = generateStaticMethod(prefix, m, toInitilize);
159.72 + destObject = "c";
159.73 + mn = generateStaticMethod(destObject, m, toInitilize);
159.74 } else {
159.75 if (m.isConstructor()) {
159.76 - prefix = "\n CLS.";
159.77 - mn = generateInstanceMethod(prefix, m);
159.78 + destObject = "CLS";
159.79 + mn = generateInstanceMethod(destObject, m);
159.80 } else {
159.81 - prefix = "\n c.";
159.82 - mn = generateInstanceMethod(prefix, m);
159.83 + destObject = "c";
159.84 + mn = generateInstanceMethod(destObject, m);
159.85 }
159.86 }
159.87 + obfuscationDelegate.exportMethod(out, destObject, mn, m);
159.88 byte[] runAnno = m.findAnnotationData(false);
159.89 if (runAnno != null) {
159.90 - out.append(prefix).append(mn).append(".anno = {");
159.91 + out.append("\n ").append(destObject).append(".").append(mn).append(".anno = {");
159.92 generateAnno(jc, out, runAnno);
159.93 out.append("\n };");
159.94 }
159.95 - out.append(prefix).append(mn).append(".access = " + m.getAccess()).append(";");
159.96 - out.append(prefix).append(mn).append(".cls = CLS;");
159.97 + out.append("\n ").append(destObject).append(".").append(mn).append(".access = " + m.getAccess()).append(";");
159.98 + out.append("\n ").append(destObject).append(".").append(mn).append(".cls = CLS;");
159.99 }
159.100 out.append("\n c.constructor = CLS;");
159.101 - out.append("\n c.$instOf_").append(className).append(" = true;");
159.102 + String instOfName = "$instOf_" + className;
159.103 + out.append("\n c.").append(instOfName).append(" = true;");
159.104 + obfuscationDelegate.exportJSProperty(out, "c", instOfName);
159.105 for (String superInterface : jc.getSuperInterfaces()) {
159.106 - out.append("\n c.$instOf_").append(superInterface.replace('/', '_')).append(" = true;");
159.107 + instOfName = "$instOf_" + superInterface.replace('/', '_');
159.108 + out.append("\n c.").append(instOfName).append(" = true;");
159.109 + obfuscationDelegate.exportJSProperty(out, "c", instOfName);
159.110 }
159.111 out.append("\n CLS.$class = 'temp';");
159.112 out.append("\n CLS.$class = ");
159.113 @@ -222,14 +242,17 @@
159.114 out.append("\n }");
159.115 out.append("\n return arguments[0] ? new CLS() : CLS.prototype;");
159.116 out.append("\n};");
159.117 +
159.118 + obfuscationDelegate.exportClass(out, getVMObject(), className, jc);
159.119 +
159.120 // StringBuilder sb = new StringBuilder();
159.121 // for (String init : toInitilize.toArray()) {
159.122 // sb.append("\n").append(init).append("();");
159.123 // }
159.124 return "";
159.125 }
159.126 - private String generateStaticMethod(String prefix, MethodData m, StringArray toInitilize) throws IOException {
159.127 - String jsb = javaScriptBody(prefix, m, true);
159.128 + private String generateStaticMethod(String destObject, MethodData m, StringArray toInitilize) throws IOException {
159.129 + String jsb = javaScriptBody(destObject, m, true);
159.130 if (jsb != null) {
159.131 return jsb;
159.132 }
159.133 @@ -237,28 +260,28 @@
159.134 if (mn.equals("class__V")) {
159.135 toInitilize.add(accessClass(className(jc)) + "(false)." + mn);
159.136 }
159.137 - generateMethod(prefix, mn, m);
159.138 + generateMethod(destObject, mn, m);
159.139 return mn;
159.140 }
159.141
159.142 - private String generateInstanceMethod(String prefix, MethodData m) throws IOException {
159.143 - String jsb = javaScriptBody(prefix, m, false);
159.144 + private String generateInstanceMethod(String destObject, MethodData m) throws IOException {
159.145 + String jsb = javaScriptBody(destObject, m, false);
159.146 if (jsb != null) {
159.147 return jsb;
159.148 }
159.149 final String mn = findMethodName(m, new StringBuilder());
159.150 - generateMethod(prefix, mn, m);
159.151 + generateMethod(destObject, mn, m);
159.152 return mn;
159.153 }
159.154
159.155 - private void generateMethod(String prefix, String name, MethodData m)
159.156 + private void generateMethod(String destObject, String name, MethodData m)
159.157 throws IOException {
159.158 final StackMapIterator stackMapIterator = m.createStackMapIterator();
159.159 TrapDataIterator trap = m.getTrapDataIterator();
159.160 final LocalsMapper lmapper =
159.161 new LocalsMapper(stackMapIterator.getArguments());
159.162
159.163 - out.append(prefix).append(name).append(" = function(");
159.164 + out.append(destObject).append(".").append(name).append(" = function(");
159.165 lmapper.outputArguments(out, m.isStatic());
159.166 out.append(") {").append("\n");
159.167
159.168 @@ -1546,7 +1569,7 @@
159.169 return s;
159.170 }
159.171
159.172 - private String javaScriptBody(String prefix, MethodData m, boolean isStatic) throws IOException {
159.173 + private String javaScriptBody(String destObject, MethodData m, boolean isStatic) throws IOException {
159.174 byte[] arr = m.findAnnotationData(true);
159.175 if (arr == null) {
159.176 return null;
159.177 @@ -1581,7 +1604,7 @@
159.178 }
159.179 StringBuilder cnt = new StringBuilder();
159.180 final String mn = findMethodName(m, cnt);
159.181 - out.append(prefix).append(mn);
159.182 + out.append(destObject).append(".").append(mn);
159.183 out.append(" = function(");
159.184 String space = "";
159.185 int index = 0;
159.186 @@ -1764,20 +1787,11 @@
159.187 if (e.catch_cpx != 0) { //not finally
159.188 final String classInternalName = jc.getClassName(e.catch_cpx);
159.189 addReference(classInternalName);
159.190 - if ("java/lang/Throwable".equals(classInternalName)) {
159.191 - out.append("if (e.$instOf_java_lang_Throwable) {");
159.192 - out.append(" var stA0 = e;");
159.193 - out.append("} else {");
159.194 - out.append(" var stA0 = vm.java_lang_Throwable(true);");
159.195 - out.append(" vm.java_lang_Throwable.cons__VLjava_lang_String_2.call(stA0, e.toString());");
159.196 - out.append("}");
159.197 - goTo(out, current, e.handler_pc, topMostLabel);
159.198 - } else {
159.199 - out.append("if (e.$instOf_" + classInternalName.replace('/', '_') + ") {");
159.200 - out.append("var stA0 = e;");
159.201 - goTo(out, current, e.handler_pc, topMostLabel);
159.202 - out.append("}\n");
159.203 - }
159.204 + out.append("e = vm.java_lang_Throwable(false).bck2BrwsrCnvrt(e);");
159.205 + out.append("if (e.$instOf_" + classInternalName.replace('/', '_') + ") {");
159.206 + out.append("var stA0 = e;");
159.207 + goTo(out, current, e.handler_pc, topMostLabel);
159.208 + out.append("}\n");
159.209 } else {
159.210 finallyPC = e.handler_pc;
159.211 }
159.212 @@ -1917,7 +1931,7 @@
159.213 final String type = jc.getClassName(indx);
159.214 if (!type.startsWith("[")) {
159.215 emit(out,
159.216 - "if (@1 !== null && !@1.$instOf_@2) throw {};",
159.217 + "if (@1 !== null && !@1.$instOf_@2) throw vm.java_lang_ClassCastException(true);",
159.218 smapper.getA(0), type.replace('/', '_'));
159.219 } else {
159.220 emit(out, "vm.java_lang_Class(false).forName__Ljava_lang_Class_2Ljava_lang_String_2('@2').cast__Ljava_lang_Object_2Ljava_lang_Object_2(@1);",
160.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
160.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/ClosureWrapper.java Thu May 02 09:18:22 2013 +0200
160.3 @@ -0,0 +1,334 @@
160.4 +/**
160.5 + * Back 2 Browser Bytecode Translator
160.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
160.7 + *
160.8 + * This program is free software: you can redistribute it and/or modify
160.9 + * it under the terms of the GNU General Public License as published by
160.10 + * the Free Software Foundation, version 2 of the License.
160.11 + *
160.12 + * This program is distributed in the hope that it will be useful,
160.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
160.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
160.15 + * GNU General Public License for more details.
160.16 + *
160.17 + * You should have received a copy of the GNU General Public License
160.18 + * along with this program. Look for COPYING file in the top folder.
160.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
160.20 + */
160.21 +package org.apidesign.vm4brwsr;
160.22 +
160.23 +import com.google.javascript.jscomp.CommandLineRunner;
160.24 +import com.google.javascript.jscomp.SourceFile;
160.25 +import java.io.IOException;
160.26 +import java.io.OutputStream;
160.27 +import java.io.PrintStream;
160.28 +import java.util.ArrayList;
160.29 +import java.util.Arrays;
160.30 +import java.util.Collection;
160.31 +import java.util.Collections;
160.32 +import java.util.List;
160.33 +import org.apidesign.bck2brwsr.core.ExtraJavaScript;
160.34 +import org.apidesign.vm4brwsr.ByteCodeParser.ClassData;
160.35 +import org.apidesign.vm4brwsr.ByteCodeParser.FieldData;
160.36 +import org.apidesign.vm4brwsr.ByteCodeParser.MethodData;
160.37 +
160.38 +/**
160.39 + *
160.40 + * @author Jaroslav Tulach <jtulach@netbeans.org>
160.41 + */
160.42 +@ExtraJavaScript(processByteCode = false, resource="")
160.43 +final class ClosureWrapper extends CommandLineRunner {
160.44 + private static final String[] ARGS = { "--compilation_level", "SIMPLE_OPTIMIZATIONS", "--js", "bck2brwsr-raw.js" /*, "--debug", "--formatting", "PRETTY_PRINT" */ };
160.45 +
160.46 + private final ClosuresObfuscationDelegate obfuscationDelegate;
160.47 + private final Bck2Brwsr.Resources res;
160.48 + private final StringArray classes;
160.49 +
160.50 + private String compiledCode;
160.51 + private String externsCode;
160.52 +
160.53 + private ClosureWrapper(Appendable out,
160.54 + String compilationLevel,
160.55 + ClosuresObfuscationDelegate obfuscationDelegate,
160.56 + Bck2Brwsr.Resources res, StringArray classes) {
160.57 + super(
160.58 + generateArguments(compilationLevel),
160.59 + new PrintStream(new APS(out)), System.err
160.60 + );
160.61 + this.obfuscationDelegate = obfuscationDelegate;
160.62 + this.res = res;
160.63 + this.classes = classes;
160.64 + }
160.65 +
160.66 + @Override
160.67 + protected List<SourceFile> createInputs(List<String> files, boolean allowStdIn) throws FlagUsageException, IOException {
160.68 + if (files.size() != 1 || !"bck2brwsr-raw.js".equals(files.get(0))) {
160.69 + throw new IOException("Unexpected files: " + files);
160.70 + }
160.71 + return Collections.nCopies(
160.72 + 1,
160.73 + SourceFile.fromGenerator(
160.74 + "bck2brwsr-raw.js",
160.75 + new SourceFile.Generator() {
160.76 + @Override
160.77 + public String getCode() {
160.78 + return getCompiledCode();
160.79 + }
160.80 + }));
160.81 + }
160.82 +
160.83 +
160.84 + @Override
160.85 + protected List<SourceFile> createExterns()
160.86 + throws FlagUsageException, IOException {
160.87 + final List<SourceFile> externsFiles =
160.88 + new ArrayList<SourceFile>(super.createExterns());
160.89 +
160.90 + externsFiles.add(
160.91 + SourceFile.fromGenerator(
160.92 + "bck2brwsr_externs.js",
160.93 + new SourceFile.Generator() {
160.94 + @Override
160.95 + public String getCode() {
160.96 + return getExternsCode();
160.97 + }
160.98 + }));
160.99 + return externsFiles;
160.100 + }
160.101 +
160.102 + private String getCompiledCode() {
160.103 + if (compiledCode == null) {
160.104 + StringBuilder sb = new StringBuilder();
160.105 + try {
160.106 + VM.compile(res, sb, classes, obfuscationDelegate);
160.107 + compiledCode = sb.toString();
160.108 + } catch (IOException ex) {
160.109 + compiledCode = ex.getMessage();
160.110 + }
160.111 + }
160.112 + return compiledCode;
160.113 + }
160.114 +
160.115 + private String getExternsCode() {
160.116 + if (externsCode == null) {
160.117 + // need compiled code at this point
160.118 + getCompiledCode();
160.119 +
160.120 + final StringBuilder sb = new StringBuilder("function RAW() {};\n");
160.121 + for (final String extern: obfuscationDelegate.getExterns()) {
160.122 + sb.append("RAW.prototype.").append(extern).append(";\n");
160.123 + }
160.124 + externsCode = sb.toString();
160.125 + }
160.126 + return externsCode;
160.127 + }
160.128 +
160.129 + private static final class APS extends OutputStream {
160.130 + private final Appendable out;
160.131 +
160.132 + public APS(Appendable out) {
160.133 + this.out = out;
160.134 + }
160.135 + @Override
160.136 + public void write(int b) throws IOException {
160.137 + out.append((char)b);
160.138 + }
160.139 + }
160.140 +
160.141 + private static String[] generateArguments(String compilationLevel) {
160.142 + String[] finalArgs = ARGS.clone();
160.143 + finalArgs[1] = compilationLevel;
160.144 +
160.145 + return finalArgs;
160.146 + }
160.147 +
160.148 + static int produceTo(Appendable w, ObfuscationLevel obfuscationLevel, Bck2Brwsr.Resources resources, StringArray arr) throws IOException {
160.149 + ClosureWrapper cw = create(w, obfuscationLevel, resources, arr);
160.150 + try {
160.151 + return cw.doRun();
160.152 + } catch (FlagUsageException ex) {
160.153 + throw new IOException(ex);
160.154 + }
160.155 + }
160.156 +
160.157 + private static ClosureWrapper create(Appendable w,
160.158 + ObfuscationLevel obfuscationLevel,
160.159 + Bck2Brwsr.Resources resources,
160.160 + StringArray arr) {
160.161 + switch (obfuscationLevel) {
160.162 + case MINIMAL:
160.163 + return new ClosureWrapper(w, "SIMPLE_OPTIMIZATIONS",
160.164 + new SimpleObfuscationDelegate(),
160.165 + resources, arr);
160.166 +/*
160.167 + case MEDIUM:
160.168 + return new ClosureWrapper(w, "ADVANCED_OPTIMIZATIONS",
160.169 + new MediumObfuscationDelegate(),
160.170 + resources, arr);
160.171 +*/
160.172 + case FULL:
160.173 + return new ClosureWrapper(w, "ADVANCED_OPTIMIZATIONS",
160.174 + new FullObfuscationDelegate(),
160.175 + resources, arr);
160.176 + default:
160.177 + throw new IllegalArgumentException(
160.178 + "Unsupported level: " + obfuscationLevel);
160.179 + }
160.180 + }
160.181 +
160.182 + private static abstract class ClosuresObfuscationDelegate
160.183 + extends ObfuscationDelegate {
160.184 + public abstract Collection<String> getExterns();
160.185 + }
160.186 +
160.187 + private static final class SimpleObfuscationDelegate
160.188 + extends ClosuresObfuscationDelegate {
160.189 + @Override
160.190 + public void exportJSProperty(Appendable out,
160.191 + String destObject,
160.192 + String propertyName) throws IOException {
160.193 + }
160.194 +
160.195 + @Override
160.196 + public void exportClass(Appendable out,
160.197 + String destObject,
160.198 + String mangledName,
160.199 + ClassData classData) throws IOException {
160.200 + }
160.201 +
160.202 + @Override
160.203 + public void exportMethod(Appendable out,
160.204 + String destObject,
160.205 + String mangledName,
160.206 + MethodData methodData) throws IOException {
160.207 + }
160.208 +
160.209 + @Override
160.210 + public void exportField(Appendable out,
160.211 + String destObject,
160.212 + String mangledName,
160.213 + FieldData fieldData) throws IOException {
160.214 + }
160.215 +
160.216 + @Override
160.217 + public Collection<String> getExterns() {
160.218 + return Collections.EMPTY_LIST;
160.219 + }
160.220 + }
160.221 +
160.222 + private static abstract class AdvancedObfuscationDelegate
160.223 + extends ClosuresObfuscationDelegate {
160.224 + private static final String[] INITIAL_EXTERNS = {
160.225 + "bck2brwsr",
160.226 + "$class",
160.227 + "anno",
160.228 + "array",
160.229 + "access",
160.230 + "cls",
160.231 + "vm",
160.232 + "loadClass",
160.233 + "loadBytes",
160.234 + "jvmName",
160.235 + "primitive",
160.236 + "superclass",
160.237 + "cnstr",
160.238 + "add32",
160.239 + "sub32",
160.240 + "mul32",
160.241 + "neg32",
160.242 + "toInt8",
160.243 + "toInt16",
160.244 + "next32",
160.245 + "high32",
160.246 + "toInt32",
160.247 + "toFP",
160.248 + "toLong",
160.249 + "toExactString",
160.250 + "add64",
160.251 + "sub64",
160.252 + "mul64",
160.253 + "and64",
160.254 + "or64",
160.255 + "xor64",
160.256 + "shl64",
160.257 + "shr64",
160.258 + "ushr64",
160.259 + "compare64",
160.260 + "neg64",
160.261 + "div32",
160.262 + "mod32",
160.263 + "div64",
160.264 + "mod64",
160.265 + "at",
160.266 + "getClass__Ljava_lang_Class_2",
160.267 + "clone__Ljava_lang_Object_2"
160.268 + };
160.269 +
160.270 + private final Collection<String> externs;
160.271 +
160.272 + protected AdvancedObfuscationDelegate() {
160.273 + externs = new ArrayList<String>(Arrays.asList(INITIAL_EXTERNS));
160.274 + }
160.275 +
160.276 + @Override
160.277 + public void exportClass(Appendable out,
160.278 + String destObject,
160.279 + String mangledName,
160.280 + ClassData classData) throws IOException {
160.281 + exportJSProperty(out, destObject, mangledName);
160.282 + }
160.283 +
160.284 + @Override
160.285 + public void exportMethod(Appendable out,
160.286 + String destObject,
160.287 + String mangledName,
160.288 + MethodData methodData) throws IOException {
160.289 + if ((methodData.access & ByteCodeParser.ACC_PRIVATE) == 0) {
160.290 + exportJSProperty(out, destObject, mangledName);
160.291 + }
160.292 + }
160.293 +
160.294 + @Override
160.295 + public void exportField(Appendable out,
160.296 + String destObject,
160.297 + String mangledName,
160.298 + FieldData fieldData) throws IOException {
160.299 + if ((fieldData.access & ByteCodeParser.ACC_PRIVATE) == 0) {
160.300 + exportJSProperty(out, destObject, mangledName);
160.301 + }
160.302 + }
160.303 +
160.304 + @Override
160.305 + public Collection<String> getExterns() {
160.306 + return externs;
160.307 + }
160.308 +
160.309 + protected void addExtern(String extern) {
160.310 + externs.add(extern);
160.311 + }
160.312 + }
160.313 +
160.314 + private static final class MediumObfuscationDelegate
160.315 + extends AdvancedObfuscationDelegate {
160.316 + @Override
160.317 + public void exportJSProperty(Appendable out,
160.318 + String destObject,
160.319 + String propertyName) {
160.320 + addExtern(propertyName);
160.321 + }
160.322 + }
160.323 +
160.324 + private static final class FullObfuscationDelegate
160.325 + extends AdvancedObfuscationDelegate {
160.326 + @Override
160.327 + public void exportJSProperty(Appendable out,
160.328 + String destObject,
160.329 + String propertyName) throws IOException {
160.330 + out.append("\n").append(destObject).append("['")
160.331 + .append(propertyName)
160.332 + .append("'] = ")
160.333 + .append(destObject).append(".").append(propertyName)
160.334 + .append(";\n");
160.335 + }
160.336 + }
160.337 +}
161.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
161.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/LdrRsrcs.java Thu May 02 09:18:22 2013 +0200
161.3 @@ -0,0 +1,48 @@
161.4 +/**
161.5 + * Back 2 Browser Bytecode Translator
161.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
161.7 + *
161.8 + * This program is free software: you can redistribute it and/or modify
161.9 + * it under the terms of the GNU General Public License as published by
161.10 + * the Free Software Foundation, version 2 of the License.
161.11 + *
161.12 + * This program is distributed in the hope that it will be useful,
161.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
161.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
161.15 + * GNU General Public License for more details.
161.16 + *
161.17 + * You should have received a copy of the GNU General Public License
161.18 + * along with this program. Look for COPYING file in the top folder.
161.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
161.20 + */
161.21 +package org.apidesign.vm4brwsr;
161.22 +
161.23 +import java.io.IOException;
161.24 +import java.io.InputStream;
161.25 +import java.net.URL;
161.26 +import java.util.Enumeration;
161.27 +
161.28 +/** Implementation of Resources that delegates to some class loader.
161.29 + *
161.30 + * @author Jaroslav Tulach <jtulach@netbeans.org>
161.31 + */
161.32 +final class LdrRsrcs implements Bck2Brwsr.Resources {
161.33 + private final ClassLoader loader;
161.34 +
161.35 + LdrRsrcs(ClassLoader loader) {
161.36 + this.loader = loader;
161.37 + }
161.38 +
161.39 + @Override
161.40 + public InputStream get(String name) throws IOException {
161.41 + Enumeration<URL> en = loader.getResources(name);
161.42 + URL u = null;
161.43 + while (en.hasMoreElements()) {
161.44 + u = en.nextElement();
161.45 + }
161.46 + if (u == null) {
161.47 + throw new IOException("Can't find " + name);
161.48 + }
161.49 + return u.openStream();
161.50 + }
161.51 +}
162.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/Main.java Tue Apr 02 15:40:51 2013 +0200
162.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/Main.java Thu May 02 09:18:22 2013 +0200
162.3 @@ -18,6 +18,7 @@
162.4 package org.apidesign.vm4brwsr;
162.5
162.6 import java.io.BufferedWriter;
162.7 +import java.io.File;
162.8 import java.io.FileWriter;
162.9 import java.io.IOException;
162.10 import java.io.Writer;
162.11 @@ -31,20 +32,69 @@
162.12 private Main() {}
162.13
162.14 public static void main(String... args) throws IOException {
162.15 + final String obfuscate = "--obfuscatelevel";
162.16 +
162.17 if (args.length < 2) {
162.18 System.err.println("Bck2Brwsr Translator from Java(tm) to JavaScript, (c) Jaroslav Tulach 2012");
162.19 - System.err.println("Usage: java -cp ... -jar ... <file_to_generate_js_code_to> java/lang/Class org/your/App ...");
162.20 - return;
162.21 + System.err.println("Usage: java -cp ... -jar ... [");
162.22 + System.err.print(obfuscate);
162.23 + System.err.print(" [");
162.24 + boolean first = true;
162.25 + for (ObfuscationLevel l : ObfuscationLevel.values()) {
162.26 + if (!first) {
162.27 + System.err.print('|');
162.28 + }
162.29 + System.err.print(l.name());
162.30 + first = false;
162.31 + }
162.32 +
162.33 + System.err.println("] <file_to_generate_js_code_to> java/lang/Class org/your/App ...");
162.34 + System.exit(9);
162.35 }
162.36
162.37 - Writer w = new BufferedWriter(new FileWriter(args[0]));
162.38 - StringArray classes = StringArray.asList(args);
162.39 - classes.delete(0);
162.40 - try {
162.41 - Bck2Brwsr.generate(w, Main.class.getClassLoader(),
162.42 - classes.toArray());
162.43 - } finally {
162.44 - w.close();
162.45 + ObfuscationLevel obfLevel = ObfuscationLevel.NONE;
162.46 + StringArray classes = new StringArray();
162.47 + String generateTo = null;
162.48 + for (int i = 0; i < args.length; i++) {
162.49 + if (obfuscate.equals(args[i])) { // NOI18N
162.50 + i++;
162.51 + try {
162.52 + obfLevel = ObfuscationLevel.valueOf(args[i]);
162.53 + } catch (Exception e) {
162.54 + System.err.print(obfuscate);
162.55 + System.err.print(" parameter needs to be followed by one of ");
162.56 + boolean first = true;
162.57 + for (ObfuscationLevel l : ObfuscationLevel.values()) {
162.58 + if (!first) {
162.59 + System.err.print(", ");
162.60 + }
162.61 + System.err.print(l.name());
162.62 + first = false;
162.63 + }
162.64 + System.err.println();
162.65 + System.exit(1);
162.66 + }
162.67 + continue;
162.68 + }
162.69 + if (generateTo == null) {
162.70 + generateTo = args[i];
162.71 + } else {
162.72 + classes = classes.addAndNew(args[i]);
162.73 + }
162.74 + }
162.75 +
162.76 + File gt = new File(generateTo);
162.77 + if (Boolean.getBoolean("skip.if.exists") && gt.isFile()) {
162.78 + System.err.println("Skipping as " + gt + " exists.");
162.79 + System.exit(0);
162.80 + }
162.81 +
162.82 + try (Writer w = new BufferedWriter(new FileWriter(gt))) {
162.83 + Bck2Brwsr.newCompiler().
162.84 + obfuscation(obfLevel).
162.85 + addRootClasses(classes.toArray()).
162.86 + resources(Main.class.getClassLoader()).
162.87 + generate(w);
162.88 }
162.89 }
162.90 }
163.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
163.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/ObfuscationDelegate.java Thu May 02 09:18:22 2013 +0200
163.3 @@ -0,0 +1,75 @@
163.4 +/**
163.5 + * Back 2 Browser Bytecode Translator
163.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
163.7 + *
163.8 + * This program is free software: you can redistribute it and/or modify
163.9 + * it under the terms of the GNU General Public License as published by
163.10 + * the Free Software Foundation, version 2 of the License.
163.11 + *
163.12 + * This program is distributed in the hope that it will be useful,
163.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
163.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
163.15 + * GNU General Public License for more details.
163.16 + *
163.17 + * You should have received a copy of the GNU General Public License
163.18 + * along with this program. Look for COPYING file in the top folder.
163.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
163.20 + */
163.21 +package org.apidesign.vm4brwsr;
163.22 +
163.23 +import java.io.IOException;
163.24 +import org.apidesign.vm4brwsr.ByteCodeParser.ClassData;
163.25 +import org.apidesign.vm4brwsr.ByteCodeParser.FieldData;
163.26 +import org.apidesign.vm4brwsr.ByteCodeParser.MethodData;
163.27 +
163.28 +abstract class ObfuscationDelegate {
163.29 + static ObfuscationDelegate NULL =
163.30 + new ObfuscationDelegate() {
163.31 + @Override
163.32 + public void exportJSProperty(Appendable out,
163.33 + String destObject,
163.34 + String propertyName)
163.35 + throws IOException {
163.36 + }
163.37 +
163.38 + @Override
163.39 + public void exportClass(Appendable out,
163.40 + String destObject,
163.41 + String mangledName,
163.42 + ClassData classData)
163.43 + throws IOException {
163.44 + }
163.45 +
163.46 + @Override
163.47 + public void exportMethod(Appendable out,
163.48 + String destObject,
163.49 + String mangledName,
163.50 + MethodData methodData)
163.51 + throws IOException {
163.52 + }
163.53 +
163.54 + @Override
163.55 + public void exportField(Appendable out,
163.56 + String destObject,
163.57 + String mangledName,
163.58 + FieldData fieldData)
163.59 + throws IOException {
163.60 + }
163.61 + };
163.62 +
163.63 + public abstract void exportJSProperty(
163.64 + Appendable out, String destObject, String propertyName)
163.65 + throws IOException;
163.66 +
163.67 + public abstract void exportClass(
163.68 + Appendable out, String destObject, String mangledName,
163.69 + ClassData classData) throws IOException;
163.70 +
163.71 + public abstract void exportMethod(
163.72 + Appendable out, String destObject, String mangledName,
163.73 + MethodData methodData) throws IOException;
163.74 +
163.75 + public abstract void exportField(
163.76 + Appendable out, String destObject, String mangledName,
163.77 + FieldData fieldData) throws IOException;
163.78 +}
164.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
164.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/ObfuscationLevel.java Thu May 02 09:18:22 2013 +0200
164.3 @@ -0,0 +1,41 @@
164.4 +/**
164.5 + * Back 2 Browser Bytecode Translator
164.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
164.7 + *
164.8 + * This program is free software: you can redistribute it and/or modify
164.9 + * it under the terms of the GNU General Public License as published by
164.10 + * the Free Software Foundation, version 2 of the License.
164.11 + *
164.12 + * This program is distributed in the hope that it will be useful,
164.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
164.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
164.15 + * GNU General Public License for more details.
164.16 + *
164.17 + * You should have received a copy of the GNU General Public License
164.18 + * along with this program. Look for COPYING file in the top folder.
164.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
164.20 + */
164.21 +package org.apidesign.vm4brwsr;
164.22 +
164.23 +/**
164.24 + * Defines obfuscation level of produced JavaScript files.
164.25 + *
164.26 + * @since 0.5
164.27 + */
164.28 +public enum ObfuscationLevel {
164.29 + /** Generated JavaScript is (sort of) human readable. Useful for debugging.
164.30 + * Dynamic capabilities of the virtual machine work on all classes.
164.31 + */
164.32 + NONE,
164.33 + /** White spaces are removed. Names of external symbols remain unchanged.
164.34 + * Dynamic capabilities of the virtual machine work on all classes.
164.35 + */
164.36 + MINIMAL,
164.37 +// temporarily commented out before merge. not well defined yet:
164.38 +// MEDIUM,
164.39 + /** Aggressive obfuscation of everything. Compact, unreadable "one-liner".
164.40 + * One cannot load classes dynamically. Useful mostly for static compilation
164.41 + * of self contained application.
164.42 + */
164.43 + FULL
164.44 +}
165.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/StringArray.java Tue Apr 02 15:40:51 2013 +0200
165.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/StringArray.java Thu May 02 09:18:22 2013 +0200
165.3 @@ -43,6 +43,25 @@
165.4 }
165.5 arr[arr.length - 1] = s;
165.6 }
165.7 +
165.8 + StringArray addAndNew(String... values) {
165.9 + int j;
165.10 + String[] tmp;
165.11 + if (arr == null) {
165.12 + tmp = new String[values.length];
165.13 + j = 0;
165.14 + } else {
165.15 + tmp = new String[arr.length + values.length];
165.16 + for (int i = 0; i < arr.length; i++) {
165.17 + tmp[i] = arr[i];
165.18 + }
165.19 + j = arr.length;
165.20 + }
165.21 + for (int i = 0; i < values.length;) {
165.22 + tmp[j++] = values[i++];
165.23 + }
165.24 + return new StringArray(tmp);
165.25 + }
165.26
165.27 public String[] toArray() {
165.28 return arr == null ? new String[0] : arr;
165.29 @@ -93,5 +112,4 @@
165.30 }
165.31 return -1;
165.32 }
165.33 -
165.34 }
166.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/VM.java Tue Apr 02 15:40:51 2013 +0200
166.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/VM.java Thu May 02 09:18:22 2013 +0200
166.3 @@ -28,7 +28,11 @@
166.4 public VM(Appendable out) {
166.5 super(out);
166.6 }
166.7 -
166.8 +
166.9 + private VM(Appendable out, ObfuscationDelegate obfuscationDelegate) {
166.10 + super(out, obfuscationDelegate);
166.11 + }
166.12 +
166.13 static {
166.14 // uses VMLazy to load dynamic classes
166.15 boolean assertsOn = false;
166.16 @@ -47,6 +51,12 @@
166.17 static void compile(Bck2Brwsr.Resources l, Appendable out, StringArray names) throws IOException {
166.18 new VM(out).doCompile(l, names);
166.19 }
166.20 +
166.21 + static void compile(Bck2Brwsr.Resources l, Appendable out, StringArray names,
166.22 + ObfuscationDelegate obfuscationDelegate) throws IOException {
166.23 + new VM(out, obfuscationDelegate).doCompile(l, names);
166.24 + }
166.25 +
166.26 protected void doCompile(Bck2Brwsr.Resources l, StringArray names) throws IOException {
166.27 out.append("(function VM(global) {var fillInVMSkeleton = function(vm) {");
166.28 StringArray processed = new StringArray();
166.29 @@ -230,4 +240,9 @@
166.30 String accessClass(String className) {
166.31 return "vm." + className;
166.32 }
166.33 +
166.34 + @Override
166.35 + String getVMObject() {
166.36 + return "vm";
166.37 + }
166.38 }
167.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/VMLazy.java Tue Apr 02 15:40:51 2013 +0200
167.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/VMLazy.java Thu May 02 09:18:22 2013 +0200
167.3 @@ -151,5 +151,10 @@
167.4 String accessClass(String classOperation) {
167.5 return "vm." + classOperation;
167.6 }
167.7 +
167.8 + @Override
167.9 + String getVMObject() {
167.10 + return "vm";
167.11 + }
167.12 }
167.13 }
168.1 --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/ClassTest.java Tue Apr 02 15:40:51 2013 +0200
168.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/ClassTest.java Thu May 02 09:18:22 2013 +0200
168.3 @@ -207,5 +207,12 @@
168.4 true
168.5 );
168.6 }
168.7 +
168.8 + @Test public void valueOfEnum() throws Exception {
168.9 + assertExec("can get value of enum", Classes.class,
168.10 + "valueEnum__Ljava_lang_String_2Ljava_lang_String_2",
168.11 + "TWO", "TWO"
168.12 + );
168.13 + }
168.14
168.15 }
169.1 --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/Classes.java Tue Apr 02 15:40:51 2013 +0200
169.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/Classes.java Thu May 02 09:18:22 2013 +0200
169.3 @@ -230,4 +230,7 @@
169.4 return Application.class.isAssignableFrom(MyApplication.class);
169.5 }
169.6
169.7 + public static String valueEnum(String v) {
169.8 + return ClassesMarker.E.valueOf(v).toString();
169.9 + }
169.10 }
170.1 --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/StringSample.java Tue Apr 02 15:40:51 2013 +0200
170.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/StringSample.java Thu May 02 09:18:22 2013 +0200
170.3 @@ -18,6 +18,7 @@
170.4 package org.apidesign.vm4brwsr;
170.5
170.6 import java.io.UnsupportedEncodingException;
170.7 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
170.8
170.9 /**
170.10 *
170.11 @@ -129,4 +130,20 @@
170.12 public String toString() {
170.13 return HELLO + cnt;
170.14 }
170.15 +
170.16 + @JavaScriptBody(args = {}, body = "return [1, 2];")
170.17 + private static native Object crtarr();
170.18 + @JavaScriptBody(args = { "o" }, body = "return o.toString();")
170.19 + private static native String toStrng(Object o);
170.20 +
170.21 + public static String toStringArray(boolean fakeArr, boolean toString) {
170.22 + final Object arr = fakeArr ? crtarr() : new Object[2];
170.23 + final String whole = toString ? arr.toString() : toStrng(arr);
170.24 + int zav = whole.indexOf('@');
170.25 + if (zav <= 0) {
170.26 + zav = whole.length();
170.27 + }
170.28 + return whole.substring(0, zav).toString().toString();
170.29 + }
170.30 +
170.31 }
171.1 --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/StringTest.java Tue Apr 02 15:40:51 2013 +0200
171.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/StringTest.java Thu May 02 09:18:22 2013 +0200
171.3 @@ -194,6 +194,34 @@
171.4
171.5 }
171.6
171.7 + @Test public void toStringOnJSArray() throws Exception {
171.8 + String exp = StringSample.toStringArray(false, true);
171.9 +
171.10 + assertExec(
171.11 + "Treated as Java Object array",
171.12 + StringSample.class, "toStringArray__Ljava_lang_String_2ZZ",
171.13 + exp, true, true
171.14 + );
171.15 + }
171.16 +
171.17 + @Test public void toStringOnRealArray() throws Exception {
171.18 + String exp = StringSample.toStringArray(false, true);
171.19 +
171.20 + assertExec(
171.21 + "Is Java Object array",
171.22 + StringSample.class, "toStringArray__Ljava_lang_String_2ZZ",
171.23 + exp, false, true
171.24 + );
171.25 + }
171.26 +
171.27 + @Test public void valueOfOnJSArray() throws Exception {
171.28 + assertExec(
171.29 + "Treated as classical JavaScript array",
171.30 + StringSample.class, "toStringArray__Ljava_lang_String_2ZZ",
171.31 + "1,2", true, false
171.32 + );
171.33 + }
171.34 +
171.35 private static TestVM code;
171.36
171.37 @BeforeClass
172.1 --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/VMinVM.java Tue Apr 02 15:40:51 2013 +0200
172.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/VMinVM.java Thu May 02 09:18:22 2013 +0200
172.3 @@ -43,4 +43,9 @@
172.4 @Override
172.5 protected void requireScript(String resourcePath) {
172.6 }
172.7 +
172.8 + @Override
172.9 + String getVMObject() {
172.10 + return "global";
172.11 + }
172.12 }
173.1 --- a/rt/vmtest/pom.xml Tue Apr 02 15:40:51 2013 +0200
173.2 +++ b/rt/vmtest/pom.xml Thu May 02 09:18:22 2013 +0200
173.3 @@ -4,11 +4,11 @@
173.4 <parent>
173.5 <groupId>org.apidesign.bck2brwsr</groupId>
173.6 <artifactId>rt</artifactId>
173.7 - <version>0.5-SNAPSHOT</version>
173.8 + <version>0.8-SNAPSHOT</version>
173.9 </parent>
173.10 <groupId>org.apidesign.bck2brwsr</groupId>
173.11 <artifactId>vmtest</artifactId>
173.12 - <version>0.5-SNAPSHOT</version>
173.13 + <version>0.8-SNAPSHOT</version>
173.14
173.15 <name>VM Testing APIs</name>
173.16 <url>http://bck2brwsr.apidesign.org</url>
173.17 @@ -50,18 +50,6 @@
173.18 </dependency>
173.19 <dependency>
173.20 <groupId>${project.groupId}</groupId>
173.21 - <artifactId>vm4brwsr</artifactId>
173.22 - <version>${project.version}</version>
173.23 - <type>jar</type>
173.24 - </dependency>
173.25 - <dependency>
173.26 - <groupId>${project.groupId}</groupId>
173.27 - <artifactId>emul.mini</artifactId>
173.28 - <version>${project.version}</version>
173.29 - <scope>test</scope>
173.30 - </dependency>
173.31 - <dependency>
173.32 - <groupId>${project.groupId}</groupId>
173.33 <artifactId>launcher</artifactId>
173.34 <version>${project.version}</version>
173.35 </dependency>
174.1 --- a/rt/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/BrwsrTest.java Tue Apr 02 15:40:51 2013 +0200
174.2 +++ b/rt/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/BrwsrTest.java Thu May 02 09:18:22 2013 +0200
174.3 @@ -29,6 +29,10 @@
174.4 * The browser to is by default executed via {@link java.awt.Desktop#browse(java.net.URI)},
174.5 * but one can change that by specifying <code>-Dvmtest.brwsrs=firefox,google-chrome</code>
174.6 * property.
174.7 + * <p>
174.8 + * If the annotated method throws {@link InterruptedException}, it will return
174.9 + * the processing to the browser and after 100ms, called again. This is useful
174.10 + * for testing asynchronous communication, etc.
174.11 *
174.12 * @author Jaroslav Tulach <jtulach@netbeans.org>
174.13 */
175.1 --- a/rt/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/Http.java Tue Apr 02 15:40:51 2013 +0200
175.2 +++ b/rt/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/Http.java Thu May 02 09:18:22 2013 +0200
175.3 @@ -53,5 +53,10 @@
175.4 String resource() default "";
175.5 /** mime type of the resource */
175.6 String mimeType();
175.7 + /** query parameters. Can be referenced from the {@link #content} as
175.8 + * <code>$0</code>, <code>$1</code>, etc. The values will be extracted
175.9 + * from URL parameters of the request.
175.10 + */
175.11 + String[] parameters() default {};
175.12 }
175.13 }
176.1 --- a/rt/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/VMTest.java Tue Apr 02 15:40:51 2013 +0200
176.2 +++ b/rt/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/VMTest.java Thu May 02 09:18:22 2013 +0200
176.3 @@ -17,6 +17,9 @@
176.4 */
176.5 package org.apidesign.bck2brwsr.vmtest;
176.6
176.7 +import java.util.ArrayList;
176.8 +import java.util.Arrays;
176.9 +import java.util.List;
176.10 import org.apidesign.bck2brwsr.launcher.Launcher;
176.11 import org.apidesign.bck2brwsr.vmtest.impl.CompareCase;
176.12 import org.testng.annotations.Factory;
176.13 @@ -34,6 +37,9 @@
176.14 * @author Jaroslav Tulach <jtulach@netbeans.org>
176.15 */
176.16 public final class VMTest {
176.17 + private final List<Class> classes = new ArrayList<>();
176.18 + private final List<String> launcher = new ArrayList<>();
176.19 +
176.20 private VMTest() {
176.21 }
176.22
176.23 @@ -47,10 +53,66 @@
176.24 * Each {@link BrwsrTest} annotated method is executed once in {@link Launcher started
176.25 * browser}.
176.26 *
176.27 - * @param clazz the class to inspect
176.28 + * @param clazz the class (or classes) to inspect
176.29 * @return the set of created tests
176.30 */
176.31 - public static Object[] create(Class<?> clazz) {
176.32 - return CompareCase.create(clazz);
176.33 + public static Object[] create(Class clazz) {
176.34 + return newTests().withClasses(clazz).build();
176.35 + }
176.36 +
176.37 + /** Creates new builder for test execution. Continue with methods
176.38 + * like {@link #withClasses(java.lang.Class[])} or {@link #withLaunchers(java.lang.String[])}.
176.39 + * Finish the process by calling {@link #build()}.
176.40 + *
176.41 + * @return new instance of a builder
176.42 + * @since 0.7
176.43 + */
176.44 + public static VMTest newTests() {
176.45 + return new VMTest();
176.46 + }
176.47 +
176.48 + /** Adds class (or classes) to the test execution. The classes are inspected
176.49 + * to contain methods annotated by
176.50 + * {@link Compare} or {@link BrwsrTest}. Appropriate set of TestNG test
176.51 + * cases is then created.
176.52 + * <p>
176.53 + * Each {@link Compare} instance runs the test in different virtual
176.54 + * machine and at the end they compare the results.
176.55 + * <p>
176.56 + * Each {@link BrwsrTest} annotated method is executed once in {@link Launcher started
176.57 + * browser}.
176.58 + *
176.59 + * @param classes one or more classes to inspect
176.60 + * @since 0.7
176.61 + */
176.62 + public final VMTest withClasses(Class... classes) {
176.63 + this.classes.addAll(Arrays.asList(classes));
176.64 + return this;
176.65 + }
176.66 +
176.67 + /** Adds list of launchers that should be used to execute tests defined
176.68 + * by {@link Compare} and {@link BrwsrTest} annotations. This value
176.69 + * can be overrided by using <code>vmtest.brwsrs</code> property.
176.70 + * List of supported launchers is available in the documentation of
176.71 + * {@link Launcher}.
176.72 + *
176.73 + * @param launcher names of one or more launchers to use for the execution
176.74 + * of tests
176.75 + * @since 0.7
176.76 + */
176.77 + public final VMTest withLaunchers(String... launcher) {
176.78 + this.launcher.addAll(Arrays.asList(launcher));
176.79 + return this;
176.80 + }
176.81 +
176.82 + /** Assembles the provided information into the final array of tests.
176.83 + * @return array of TestNG tests
176.84 + * @since 0.7
176.85 + */
176.86 + public final Object[] build() {
176.87 + return CompareCase.create(
176.88 + launcher.toArray(new String[0]),
176.89 + classes.toArray(new Class[0])
176.90 + );
176.91 }
176.92 }
177.1 --- a/rt/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/Bck2BrwsrCase.java Tue Apr 02 15:40:51 2013 +0200
177.2 +++ b/rt/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/Bck2BrwsrCase.java Thu May 02 09:18:22 2013 +0200
177.3 @@ -65,17 +65,17 @@
177.4 for (Http.Resource r : http) {
177.5 if (!r.content().isEmpty()) {
177.6 InputStream is = new ByteArrayInputStream(r.content().getBytes("UTF-8"));
177.7 - c.addHttpResource(r.path(), r.mimeType(), is);
177.8 + c.addHttpResource(r.path(), r.mimeType(), r.parameters(), is);
177.9 } else {
177.10 InputStream is = m.getDeclaringClass().getResourceAsStream(r.resource());
177.11 - c.addHttpResource(r.path(), r.mimeType(), is);
177.12 + c.addHttpResource(r.path(), r.mimeType(), r.parameters(), is);
177.13 }
177.14 }
177.15 }
177.16 String res = c.invoke();
177.17 value = res;
177.18 if (fail) {
177.19 - int idx = res.indexOf(':');
177.20 + int idx = res == null ? -1 : res.indexOf(':');
177.21 if (idx >= 0) {
177.22 Class<? extends Throwable> thrwbl = null;
177.23 try {
178.1 --- a/rt/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/CompareCase.java Tue Apr 02 15:40:51 2013 +0200
178.2 +++ b/rt/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/CompareCase.java Thu May 02 09:18:22 2013 +0200
178.3 @@ -53,26 +53,25 @@
178.4 * @param clazz the class to inspect
178.5 * @return the set of created tests
178.6 */
178.7 - public static Object[] create(Class<?> clazz) {
178.8 - Method[] arr = clazz.getMethods();
178.9 + public static Object[] create(String[] brwsr, Class[] classes) {
178.10 List<Object> ret = new ArrayList<>();
178.11
178.12 final LaunchSetup l = LaunchSetup.INSTANCE;
178.13 ret.add(l);
178.14
178.15 - String[] brwsr;
178.16 {
178.17 String p = System.getProperty("vmtest.brwsrs");
178.18 if (p != null) {
178.19 brwsr = p.split(",");
178.20 - } else {
178.21 - brwsr = new String[0];
178.22 }
178.23 }
178.24
178.25 - for (Method m : arr) {
178.26 - registerCompareCases(m, l, ret, brwsr);
178.27 - registerBrwsrCases(m, l, ret, brwsr);
178.28 + for (Class clazz : classes) {
178.29 + Method[] arr = clazz.getMethods();
178.30 + for (Method m : arr) {
178.31 + registerCompareCases(m, l, ret, brwsr);
178.32 + registerBrwsrCases(m, l, ret, brwsr);
178.33 + }
178.34 }
178.35 return ret.toArray();
178.36 }
179.1 --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/AssertionTest.java Tue Apr 02 15:40:51 2013 +0200
179.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
179.3 @@ -1,43 +0,0 @@
179.4 -/**
179.5 - * Back 2 Browser Bytecode Translator
179.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
179.7 - *
179.8 - * This program is free software: you can redistribute it and/or modify
179.9 - * it under the terms of the GNU General Public License as published by
179.10 - * the Free Software Foundation, version 2 of the License.
179.11 - *
179.12 - * This program is distributed in the hope that it will be useful,
179.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
179.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
179.15 - * GNU General Public License for more details.
179.16 - *
179.17 - * You should have received a copy of the GNU General Public License
179.18 - * along with this program. Look for COPYING file in the top folder.
179.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
179.20 - */
179.21 -package org.apidesign.bck2brwsr.tck;
179.22 -
179.23 -import org.apidesign.bck2brwsr.vmtest.Compare;
179.24 -import org.apidesign.bck2brwsr.vmtest.VMTest;
179.25 -import org.testng.annotations.Factory;
179.26 -
179.27 -/**
179.28 - *
179.29 - * @author Jaroslav Tulach <jtulach@netbeans.org>
179.30 - */
179.31 -public class AssertionTest {
179.32 -
179.33 - @Compare public Object checkAssert() throws ClassNotFoundException {
179.34 - try {
179.35 - assert false : "Is assertion status on?";
179.36 - return null;
179.37 - } catch (AssertionError ex) {
179.38 - return ex.getClass().getName();
179.39 - }
179.40 - }
179.41 -
179.42 - @Factory
179.43 - public static Object[] create() {
179.44 - return VMTest.create(AssertionTest.class);
179.45 - }
179.46 -}
180.1 --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/BrwsrCheckTest.java Tue Apr 02 15:40:51 2013 +0200
180.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
180.3 @@ -1,57 +0,0 @@
180.4 -/**
180.5 - * Back 2 Browser Bytecode Translator
180.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
180.7 - *
180.8 - * This program is free software: you can redistribute it and/or modify
180.9 - * it under the terms of the GNU General Public License as published by
180.10 - * the Free Software Foundation, version 2 of the License.
180.11 - *
180.12 - * This program is distributed in the hope that it will be useful,
180.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
180.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
180.15 - * GNU General Public License for more details.
180.16 - *
180.17 - * You should have received a copy of the GNU General Public License
180.18 - * along with this program. Look for COPYING file in the top folder.
180.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
180.20 - */
180.21 -package org.apidesign.bck2brwsr.tck;
180.22 -
180.23 -import org.apidesign.bck2brwsr.core.JavaScriptBody;
180.24 -import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
180.25 -import org.apidesign.bck2brwsr.vmtest.HtmlFragment;
180.26 -import org.apidesign.bck2brwsr.vmtest.VMTest;
180.27 -import org.testng.annotations.Factory;
180.28 -
180.29 -/**
180.30 - *
180.31 - * @author Jaroslav Tulach <jtulach@netbeans.org>
180.32 - */
180.33 -public class BrwsrCheckTest {
180.34 -
180.35 - @BrwsrTest public void assertWindowObjectIsDefined() {
180.36 - assert window() != null : "No window object found!";
180.37 - }
180.38 -
180.39 -
180.40 -
180.41 -
180.42 - @HtmlFragment("<h1 id='hello'>\n"
180.43 - + "Hello!\n"
180.44 - + "</h1>\n")
180.45 - @BrwsrTest public void accessProvidedFragment() {
180.46 - assert getElementById("hello") != null : "Element with 'hello' ID found";
180.47 - }
180.48 -
180.49 - @Factory
180.50 - public static Object[] create() {
180.51 - return VMTest.create(BrwsrCheckTest.class);
180.52 - }
180.53 -
180.54 -
180.55 - @JavaScriptBody(args = {}, body = "return window;")
180.56 - private static native Object window();
180.57 -
180.58 - @JavaScriptBody(args = { "id" }, body = "return window.document.getElementById(id);")
180.59 - private static native Object getElementById(String id);
180.60 -}
181.1 --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ByteArithmeticTest.java Tue Apr 02 15:40:51 2013 +0200
181.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
181.3 @@ -1,147 +0,0 @@
181.4 -/**
181.5 - * Back 2 Browser Bytecode Translator
181.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
181.7 - *
181.8 - * This program is free software: you can redistribute it and/or modify
181.9 - * it under the terms of the GNU General Public License as published by
181.10 - * the Free Software Foundation, version 2 of the License.
181.11 - *
181.12 - * This program is distributed in the hope that it will be useful,
181.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
181.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
181.15 - * GNU General Public License for more details.
181.16 - *
181.17 - * You should have received a copy of the GNU General Public License
181.18 - * along with this program. Look for COPYING file in the top folder.
181.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
181.20 - */
181.21 -package org.apidesign.bck2brwsr.tck;
181.22 -
181.23 -import org.apidesign.bck2brwsr.core.JavaScriptBody;
181.24 -import org.apidesign.bck2brwsr.vmtest.Compare;
181.25 -import org.apidesign.bck2brwsr.vmtest.VMTest;
181.26 -import org.testng.annotations.Factory;
181.27 -
181.28 -/**
181.29 - *
181.30 - * @author Jaroslav Tulach <jtulach@netbeans.org>
181.31 - */
181.32 -public class ByteArithmeticTest {
181.33 -
181.34 - private static byte add(byte x, byte y) {
181.35 - return (byte)(x + y);
181.36 - }
181.37 -
181.38 - private static byte sub(byte x, byte y) {
181.39 - return (byte)(x - y);
181.40 - }
181.41 -
181.42 - private static byte mul(byte x, byte y) {
181.43 - return (byte)(x * y);
181.44 - }
181.45 -
181.46 - private static byte div(byte x, byte y) {
181.47 - return (byte)(x / y);
181.48 - }
181.49 -
181.50 - private static byte mod(byte x, byte y) {
181.51 - return (byte)(x % y);
181.52 - }
181.53 -
181.54 - @Compare public byte conversion() {
181.55 - return (byte)123456;
181.56 - }
181.57 -
181.58 - @Compare public byte addOverflow() {
181.59 - return add(Byte.MAX_VALUE, (byte)1);
181.60 - }
181.61 -
181.62 - @Compare public byte subUnderflow() {
181.63 - return sub(Byte.MIN_VALUE, (byte)1);
181.64 - }
181.65 -
181.66 - @Compare public byte addMaxByteAndMaxByte() {
181.67 - return add(Byte.MAX_VALUE, Byte.MAX_VALUE);
181.68 - }
181.69 -
181.70 - @Compare public byte subMinByteAndMinByte() {
181.71 - return sub(Byte.MIN_VALUE, Byte.MIN_VALUE);
181.72 - }
181.73 -
181.74 - @Compare public byte multiplyMaxByte() {
181.75 - return mul(Byte.MAX_VALUE, (byte)2);
181.76 - }
181.77 -
181.78 - @Compare public byte multiplyMaxByteAndMaxByte() {
181.79 - return mul(Byte.MAX_VALUE, Byte.MAX_VALUE);
181.80 - }
181.81 -
181.82 - @Compare public byte multiplyMinByte() {
181.83 - return mul(Byte.MIN_VALUE, (byte)2);
181.84 - }
181.85 -
181.86 - @Compare public byte multiplyMinByteAndMinByte() {
181.87 - return mul(Byte.MIN_VALUE, Byte.MIN_VALUE);
181.88 - }
181.89 -
181.90 - @Compare public byte multiplyPrecision() {
181.91 - return mul((byte)17638, (byte)1103);
181.92 - }
181.93 -
181.94 - @Compare public byte division() {
181.95 - return div((byte)1, (byte)2);
181.96 - }
181.97 -
181.98 - @Compare public byte divisionReminder() {
181.99 - return mod((byte)1, (byte)2);
181.100 - }
181.101 -
181.102 - private static int readShort(byte[] byteCodes, int offset) {
181.103 - int signed = byteCodes[offset];
181.104 - byte b0 = (byte)signed;
181.105 - return (b0 << 8) | (byteCodes[offset + 1] & 0xff);
181.106 - }
181.107 -
181.108 - private static int readShortArg(byte[] byteCodes, int offsetInstruction) {
181.109 - return readShort(byteCodes, offsetInstruction + 1);
181.110 - }
181.111 -
181.112 - @Compare public int readIntArgs255and156() {
181.113 - final byte[] arr = new byte[] { (byte)0, (byte)255, (byte)156 };
181.114 -
181.115 - assert arr[1] == -1 : "First byte: " + arr[1];
181.116 - assert arr[2] == -100 : "Second byte: " + arr[2];
181.117 - final int ret = readShortArg(arr, 0);
181.118 - assert ret < 65000: "Value: " + ret;
181.119 - return ret;
181.120 - }
181.121 -
181.122 - @JavaScriptBody(args = { "arr" }, body = "arr[1] = 255; arr[2] = 156; return arr;")
181.123 - private static byte[] fill255and156(byte[] arr) {
181.124 - arr[1] = (byte)255;
181.125 - arr[2] = (byte)156;
181.126 - return arr;
181.127 - }
181.128 -
181.129 - @Compare public int readIntArgs255and156JSArray() {
181.130 - final byte[] arr = fill255and156(new byte[] { 0, 0, 0 });
181.131 -
181.132 - final int ret = readShortArg(arr, 0);
181.133 - assert ret < 65000: "Value: " + ret;
181.134 - return ret;
181.135 - }
181.136 -
181.137 - @Compare public int readIntArgsMinus1andMinus100() {
181.138 - final byte[] arr = new byte[] { (byte)0, (byte)-1, (byte)-100 };
181.139 -
181.140 - assert arr[1] == -1 : "First byte: " + arr[1];
181.141 - assert arr[2] == -100 : "Second byte: " + arr[2];
181.142 -
181.143 - return readShortArg(arr, 0);
181.144 - }
181.145 -
181.146 - @Factory
181.147 - public static Object[] create() {
181.148 - return VMTest.create(ByteArithmeticTest.class);
181.149 - }
181.150 -}
182.1 --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CloneTest.java Tue Apr 02 15:40:51 2013 +0200
182.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
182.3 @@ -1,73 +0,0 @@
182.4 -/**
182.5 - * Back 2 Browser Bytecode Translator
182.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
182.7 - *
182.8 - * This program is free software: you can redistribute it and/or modify
182.9 - * it under the terms of the GNU General Public License as published by
182.10 - * the Free Software Foundation, version 2 of the License.
182.11 - *
182.12 - * This program is distributed in the hope that it will be useful,
182.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
182.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
182.15 - * GNU General Public License for more details.
182.16 - *
182.17 - * You should have received a copy of the GNU General Public License
182.18 - * along with this program. Look for COPYING file in the top folder.
182.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
182.20 - */
182.21 -package org.apidesign.bck2brwsr.tck;
182.22 -
182.23 -import org.apidesign.bck2brwsr.vmtest.Compare;
182.24 -import org.apidesign.bck2brwsr.vmtest.VMTest;
182.25 -import org.testng.annotations.Factory;
182.26 -
182.27 -/**
182.28 - *
182.29 - * @author Jaroslav Tulach <jtulach@netbeans.org>
182.30 - */
182.31 -public class CloneTest {
182.32 - private int value;
182.33 -
182.34 - @Compare
182.35 - public Object notSupported() throws CloneNotSupportedException {
182.36 - return this.clone();
182.37 - }
182.38 -
182.39 - @Compare public String sameClass() throws CloneNotSupportedException {
182.40 - return new Clnbl().clone().getClass().getName();
182.41 - }
182.42 -
182.43 - @Compare public boolean differentInstance() throws CloneNotSupportedException {
182.44 - Clnbl orig = new Clnbl();
182.45 - return orig == orig.clone();
182.46 - }
182.47 -
182.48 - @Compare public int sameReference() throws CloneNotSupportedException {
182.49 - CloneTest self = this;
182.50 - Clnbl orig = new Clnbl();
182.51 - self.value = 33;
182.52 - orig.ref = self;
182.53 - return ((Clnbl)orig.clone()).ref.value;
182.54 - }
182.55 -
182.56 - @Compare public int sameValue() throws CloneNotSupportedException {
182.57 - Clnbl orig = new Clnbl();
182.58 - orig.value = 10;
182.59 - return ((Clnbl)orig.clone()).value;
182.60 - }
182.61 -
182.62 - @Factory
182.63 - public static Object[] create() {
182.64 - return VMTest.create(CloneTest.class);
182.65 - }
182.66 -
182.67 - public static final class Clnbl implements Cloneable {
182.68 - public CloneTest ref;
182.69 - private int value;
182.70 -
182.71 - @Override
182.72 - public Object clone() throws CloneNotSupportedException {
182.73 - return super.clone();
182.74 - }
182.75 - }
182.76 -}
183.1 --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareByteArrayTest.java Tue Apr 02 15:40:51 2013 +0200
183.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
183.3 @@ -1,103 +0,0 @@
183.4 -/**
183.5 - * Back 2 Browser Bytecode Translator
183.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
183.7 - *
183.8 - * This program is free software: you can redistribute it and/or modify
183.9 - * it under the terms of the GNU General Public License as published by
183.10 - * the Free Software Foundation, version 2 of the License.
183.11 - *
183.12 - * This program is distributed in the hope that it will be useful,
183.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
183.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
183.15 - * GNU General Public License for more details.
183.16 - *
183.17 - * You should have received a copy of the GNU General Public License
183.18 - * along with this program. Look for COPYING file in the top folder.
183.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
183.20 - */
183.21 -package org.apidesign.bck2brwsr.tck;
183.22 -
183.23 -import org.apidesign.bck2brwsr.vmtest.Compare;
183.24 -import org.apidesign.bck2brwsr.vmtest.VMTest;
183.25 -import org.testng.annotations.Factory;
183.26 -
183.27 -/**
183.28 - *
183.29 - * @author Jaroslav Tulach <jtulach@netbeans.org>
183.30 - */
183.31 -public class CompareByteArrayTest {
183.32 - @Compare public int byteArraySum() {
183.33 - byte[] arr = createArray();
183.34 - return sumByteArr(arr);
183.35 - }
183.36 -
183.37 - @Compare public int countZeros() {
183.38 - int zeros = 0;
183.39 - for (Byte b : createArray()) {
183.40 - if (b == 0) {
183.41 - zeros++;
183.42 - }
183.43 - }
183.44 - return zeros;
183.45 - }
183.46 -
183.47 - private static int sumByteArr(byte[] arr) {
183.48 - int sum = 0;
183.49 - for (int i = 0; i < arr.length; i++) {
183.50 - sum += arr[i];
183.51 - }
183.52 - return sum;
183.53 - }
183.54 -
183.55 - @Compare public String noOutOfBounds() {
183.56 - return atIndex(1);
183.57 - }
183.58 -
183.59 - @Compare public String outOfBounds() {
183.60 - return atIndex(5);
183.61 - }
183.62 -
183.63 - @Compare public String outOfBoundsMinus() {
183.64 - return atIndex(-1);
183.65 - }
183.66 -
183.67 - @Compare public String toOfBounds() {
183.68 - return toIndex(5);
183.69 - }
183.70 -
183.71 - @Compare public String toOfBoundsMinus() {
183.72 - return toIndex(-1);
183.73 - }
183.74 -
183.75 - @Compare public int multiArrayLength() {
183.76 - int[][] arr = new int[1][0];
183.77 - return arr[0].length;
183.78 - }
183.79 -
183.80 - @Compare public int multiObjectArrayLength() {
183.81 - Object[][] arr = new Object[1][0];
183.82 - return arr[0].length;
183.83 - }
183.84 -
183.85 - private static final int[] arr = { 0, 1, 2 };
183.86 - public static String atIndex(int at) {
183.87 - return "at@" + arr[at];
183.88 - }
183.89 - public static String toIndex(int at) {
183.90 - arr[at] = 10;
183.91 - return "ok";
183.92 - }
183.93 -
183.94 -
183.95 - @Factory
183.96 - public static Object[] create() {
183.97 - return VMTest.create(CompareByteArrayTest.class);
183.98 - }
183.99 -
183.100 - private byte[] createArray() {
183.101 - byte[] arr = new byte[10];
183.102 - arr[5] = 3;
183.103 - arr[7] = 8;
183.104 - return arr;
183.105 - }
183.106 -}
184.1 --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareHashTest.java Tue Apr 02 15:40:51 2013 +0200
184.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
184.3 @@ -1,50 +0,0 @@
184.4 -/**
184.5 - * Back 2 Browser Bytecode Translator
184.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
184.7 - *
184.8 - * This program is free software: you can redistribute it and/or modify
184.9 - * it under the terms of the GNU General Public License as published by
184.10 - * the Free Software Foundation, version 2 of the License.
184.11 - *
184.12 - * This program is distributed in the hope that it will be useful,
184.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
184.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
184.15 - * GNU General Public License for more details.
184.16 - *
184.17 - * You should have received a copy of the GNU General Public License
184.18 - * along with this program. Look for COPYING file in the top folder.
184.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
184.20 - */
184.21 -package org.apidesign.bck2brwsr.tck;
184.22 -
184.23 -import org.apidesign.bck2brwsr.vmtest.Compare;
184.24 -import org.apidesign.bck2brwsr.vmtest.VMTest;
184.25 -import org.testng.annotations.Factory;
184.26 -
184.27 -/**
184.28 - *
184.29 - * @author Jaroslav Tulach <jtulach@netbeans.org>
184.30 - */
184.31 -public class CompareHashTest {
184.32 - @Compare public int hashOfString() {
184.33 - return "Ahoj".hashCode();
184.34 - }
184.35 -
184.36 - @Compare public int hashRemainsYieldsZero() {
184.37 - Object o = new Object();
184.38 - return o.hashCode() - o.hashCode();
184.39 - }
184.40 -
184.41 - @Compare public int initializeInStatic() {
184.42 - return StaticUse.NON_NULL.hashCode() - StaticUse.NON_NULL.hashCode();
184.43 - }
184.44 -
184.45 - @Compare public int hashOfInt() {
184.46 - return Integer.valueOf(Integer.MAX_VALUE).hashCode();
184.47 - }
184.48 -
184.49 - @Factory
184.50 - public static Object[] create() {
184.51 - return VMTest.create(CompareHashTest.class);
184.52 - }
184.53 -}
185.1 --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareIntArrayTest.java Tue Apr 02 15:40:51 2013 +0200
185.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
185.3 @@ -1,63 +0,0 @@
185.4 -/**
185.5 - * Back 2 Browser Bytecode Translator
185.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
185.7 - *
185.8 - * This program is free software: you can redistribute it and/or modify
185.9 - * it under the terms of the GNU General Public License as published by
185.10 - * the Free Software Foundation, version 2 of the License.
185.11 - *
185.12 - * This program is distributed in the hope that it will be useful,
185.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
185.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
185.15 - * GNU General Public License for more details.
185.16 - *
185.17 - * You should have received a copy of the GNU General Public License
185.18 - * along with this program. Look for COPYING file in the top folder.
185.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
185.20 - */
185.21 -package org.apidesign.bck2brwsr.tck;
185.22 -
185.23 -import org.apidesign.bck2brwsr.vmtest.Compare;
185.24 -import org.apidesign.bck2brwsr.vmtest.VMTest;
185.25 -import org.testng.annotations.Factory;
185.26 -
185.27 -/**
185.28 - *
185.29 - * @author Jaroslav Tulach <jtulach@netbeans.org>
185.30 - */
185.31 -public class CompareIntArrayTest {
185.32 - @Compare public int integerArraySum() {
185.33 - int[] arr = createArray();
185.34 - return sumIntArr(arr);
185.35 - }
185.36 -
185.37 - @Compare public int countZeros() {
185.38 - int zeros = 0;
185.39 - for (Integer i : createArray()) {
185.40 - if (i == 0) {
185.41 - zeros++;
185.42 - }
185.43 - }
185.44 - return zeros;
185.45 - }
185.46 -
185.47 - private static int sumIntArr(int[] arr) {
185.48 - int sum = 0;
185.49 - for (int i = 0; i < arr.length; i++) {
185.50 - sum += arr[i];
185.51 - }
185.52 - return sum;
185.53 - }
185.54 -
185.55 - @Factory
185.56 - public static Object[] create() {
185.57 - return VMTest.create(CompareIntArrayTest.class);
185.58 - }
185.59 -
185.60 - private int[] createArray() {
185.61 - int[] arr = new int[10];
185.62 - arr[5] = 3;
185.63 - arr[7] = 8;
185.64 - return arr;
185.65 - }
185.66 -}
186.1 --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareStringsTest.java Tue Apr 02 15:40:51 2013 +0200
186.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
186.3 @@ -1,162 +0,0 @@
186.4 -/**
186.5 - * Back 2 Browser Bytecode Translator
186.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
186.7 - *
186.8 - * This program is free software: you can redistribute it and/or modify
186.9 - * it under the terms of the GNU General Public License as published by
186.10 - * the Free Software Foundation, version 2 of the License.
186.11 - *
186.12 - * This program is distributed in the hope that it will be useful,
186.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
186.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
186.15 - * GNU General Public License for more details.
186.16 - *
186.17 - * You should have received a copy of the GNU General Public License
186.18 - * along with this program. Look for COPYING file in the top folder.
186.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
186.20 - */
186.21 -package org.apidesign.bck2brwsr.tck;
186.22 -
186.23 -import java.io.UnsupportedEncodingException;
186.24 -import java.net.MalformedURLException;
186.25 -import java.net.URL;
186.26 -import org.apidesign.bck2brwsr.vmtest.Compare;
186.27 -import org.apidesign.bck2brwsr.vmtest.VMTest;
186.28 -import org.testng.annotations.Factory;
186.29 -
186.30 -/**
186.31 - *
186.32 - * @author Jaroslav Tulach <jtulach@netbeans.org>
186.33 - */
186.34 -public class CompareStringsTest {
186.35 - @Compare public String firstChar() {
186.36 - return "" + ("Hello".toCharArray()[0]);
186.37 - }
186.38 -
186.39 - @Compare public String classCast() {
186.40 - Object o = firstChar();
186.41 - return String.class.cast(o);
186.42 - }
186.43 -
186.44 - @Compare public String classCastThrown() {
186.45 - Object o = null;
186.46 - return String.class.cast(o);
186.47 - }
186.48 -
186.49 - @Compare public boolean equalToNull() {
186.50 - return "Ahoj".equals(null);
186.51 - }
186.52 -
186.53 - @Compare public int highByteLenght() {
186.54 - byte[] arr= { 77,97,110,105,102,101,115,116,45,86,101,114,115,105,111,110 };
186.55 - return new String(arr, 0).length();
186.56 - }
186.57 -
186.58 - @Compare public String highByte() {
186.59 - byte[] arr= { 77,97,110,105,102,101,115,116,45,86,101,114,115,105,111,110 };
186.60 - StringBuilder sb = new StringBuilder();
186.61 - sb.append("pref:");
186.62 - sb.append(new String(arr, 0));
186.63 - return sb.toString();
186.64 - }
186.65 -
186.66 - @Compare public static Object compareURLs() throws MalformedURLException {
186.67 - return new URL("http://apidesign.org:8080/wiki/").toExternalForm().toString();
186.68 - }
186.69 -
186.70 - @Compare public String deleteLastTwoCharacters() {
186.71 - StringBuilder sb = new StringBuilder();
186.72 - sb.append("453.0");
186.73 - if (sb.toString().endsWith(".0")) {
186.74 - final int l = sb.length();
186.75 - sb.delete(l - 2, l);
186.76 - }
186.77 - return sb.toString().toString();
186.78 - }
186.79 -
186.80 - @Compare public String nameOfStringClass() throws Exception {
186.81 - return Class.forName("java.lang.String").getName();
186.82 - }
186.83 - @Compare public String nameOfArrayClass() throws Exception {
186.84 - return Class.forName("org.apidesign.bck2brwsr.tck.CompareHashTest").getName();
186.85 - }
186.86 -
186.87 - @Compare public String lowerHello() {
186.88 - return "HeLlO".toLowerCase();
186.89 - }
186.90 -
186.91 - @Compare public String lowerA() {
186.92 - return String.valueOf(Character.toLowerCase('A')).toString();
186.93 - }
186.94 - @Compare public String upperHello() {
186.95 - return "hello".toUpperCase();
186.96 - }
186.97 -
186.98 - @Compare public String upperA() {
186.99 - return String.valueOf(Character.toUpperCase('a')).toString();
186.100 - }
186.101 -
186.102 - @Compare public boolean matchRegExp() throws Exception {
186.103 - return "58038503".matches("\\d*");
186.104 - }
186.105 -
186.106 - @Compare public boolean doesNotMatchRegExp() throws Exception {
186.107 - return "58038503GH".matches("\\d*");
186.108 - }
186.109 -
186.110 - @Compare public boolean doesNotMatchRegExpFully() throws Exception {
186.111 - return "Hello".matches("Hell");
186.112 - }
186.113 -
186.114 - @Compare public String emptyCharArray() {
186.115 - char[] arr = new char[10];
186.116 - return new String(arr);
186.117 - }
186.118 -
186.119 - @Compare public String variousCharacterTests() throws Exception {
186.120 - StringBuilder sb = new StringBuilder();
186.121 -
186.122 - sb.append(Character.isUpperCase('a'));
186.123 - sb.append(Character.isUpperCase('A'));
186.124 - sb.append(Character.isLowerCase('a'));
186.125 - sb.append(Character.isLowerCase('A'));
186.126 -
186.127 - sb.append(Character.isLetter('A'));
186.128 - sb.append(Character.isLetterOrDigit('9'));
186.129 - sb.append(Character.isLetterOrDigit('A'));
186.130 - sb.append(Character.isLetter('0'));
186.131 -
186.132 - return sb.toString().toString();
186.133 - }
186.134 -
186.135 - @Compare
186.136 - public String nullFieldInitialized() {
186.137 - NullField nf = new NullField();
186.138 - return ("" + nf.name).toString();
186.139 - }
186.140 - @Compare
186.141 - public String toUTFString() throws UnsupportedEncodingException {
186.142 - byte[] arr = {
186.143 - (byte) -59, (byte) -67, (byte) 108, (byte) 117, (byte) -59, (byte) -91,
186.144 - (byte) 111, (byte) 117, (byte) -60, (byte) -115, (byte) 107, (byte) -61,
186.145 - (byte) -67, (byte) 32, (byte) 107, (byte) -59, (byte) -81, (byte) -59,
186.146 - (byte) -120
186.147 - };
186.148 - return new String(arr, "utf-8");
186.149 - }
186.150 -
186.151 - @Compare
186.152 - public int stringToBytesLenght() throws UnsupportedEncodingException {
186.153 - return "\u017dlu\u0165ou\u010dk\u00fd k\u016f\u0148".getBytes("utf8").length;
186.154 - }
186.155 -
186.156 - @Factory
186.157 - public static Object[] create() {
186.158 - return VMTest.create(CompareStringsTest.class);
186.159 - }
186.160 -
186.161 - private static final class NullField {
186.162 -
186.163 - String name;
186.164 - }
186.165 -}
187.1 --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/DoubleTest.java Tue Apr 02 15:40:51 2013 +0200
187.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
187.3 @@ -1,65 +0,0 @@
187.4 -/**
187.5 - * Back 2 Browser Bytecode Translator
187.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
187.7 - *
187.8 - * This program is free software: you can redistribute it and/or modify
187.9 - * it under the terms of the GNU General Public License as published by
187.10 - * the Free Software Foundation, version 2 of the License.
187.11 - *
187.12 - * This program is distributed in the hope that it will be useful,
187.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
187.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
187.15 - * GNU General Public License for more details.
187.16 - *
187.17 - * You should have received a copy of the GNU General Public License
187.18 - * along with this program. Look for COPYING file in the top folder.
187.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
187.20 - */
187.21 -package org.apidesign.bck2brwsr.tck;
187.22 -
187.23 -import org.apidesign.bck2brwsr.vmtest.Compare;
187.24 -import org.apidesign.bck2brwsr.vmtest.VMTest;
187.25 -import org.testng.annotations.Factory;
187.26 -
187.27 -/**
187.28 - *
187.29 - * @author Jaroslav Tulach <jtulach@netbeans.org>
187.30 - */
187.31 -public class DoubleTest {
187.32 - @Compare public String integerToString() {
187.33 - return toStr(1);
187.34 - }
187.35 -
187.36 - @Compare public String integerAndHalfToString() {
187.37 - return toStr(1.5);
187.38 - }
187.39 -
187.40 - @Compare public double longToAndBack() {
187.41 - return Double.parseDouble(toStr(Long.MAX_VALUE / 10));
187.42 - }
187.43 -
187.44 - @Compare public String negativeIntToString() {
187.45 - return toStr(-10);
187.46 - }
187.47 -
187.48 - @Compare public String negativeIntAndHalfToString() {
187.49 - return toStr(-10.5);
187.50 - }
187.51 -
187.52 - @Compare public double negativeLongAndBack() {
187.53 - return Double.parseDouble(toStr(Long.MIN_VALUE / 10));
187.54 - }
187.55 -
187.56 - @Compare public double canParseExp() {
187.57 - return Double.parseDouble(toStr(1.7976931348623157e+308));
187.58 - }
187.59 -
187.60 - private static String toStr(double d) {
187.61 - return Double.toString(d);
187.62 - }
187.63 -
187.64 - @Factory
187.65 - public static Object[] create() {
187.66 - return VMTest.create(DoubleTest.class);
187.67 - }
187.68 -}
188.1 --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/HttpResourceTest.java Tue Apr 02 15:40:51 2013 +0200
188.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
188.3 @@ -1,106 +0,0 @@
188.4 -/**
188.5 - * Back 2 Browser Bytecode Translator
188.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
188.7 - *
188.8 - * This program is free software: you can redistribute it and/or modify
188.9 - * it under the terms of the GNU General Public License as published by
188.10 - * the Free Software Foundation, version 2 of the License.
188.11 - *
188.12 - * This program is distributed in the hope that it will be useful,
188.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
188.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
188.15 - * GNU General Public License for more details.
188.16 - *
188.17 - * You should have received a copy of the GNU General Public License
188.18 - * along with this program. Look for COPYING file in the top folder.
188.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
188.20 - */
188.21 -package org.apidesign.bck2brwsr.tck;
188.22 -
188.23 -import java.io.InputStream;
188.24 -import java.net.URL;
188.25 -import org.apidesign.bck2brwsr.core.JavaScriptBody;
188.26 -import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
188.27 -import org.apidesign.bck2brwsr.vmtest.Http;
188.28 -import org.apidesign.bck2brwsr.vmtest.VMTest;
188.29 -import org.testng.annotations.Factory;
188.30 -
188.31 -/**
188.32 - *
188.33 - * @author Jaroslav Tulach <jtulach@netbeans.org>
188.34 - */
188.35 -public class HttpResourceTest {
188.36 -
188.37 - @Http({
188.38 - @Http.Resource(path = "/xhr", content = "Hello Brwsr!", mimeType = "text/plain")
188.39 - })
188.40 - @BrwsrTest
188.41 -
188.42 -
188.43 - public String testReadContentViaXHR() throws Exception {
188.44 - String msg = read("/xhr");
188.45 - assert "Hello Brwsr!".equals(msg) : "The message was " + msg;
188.46 - return msg;
188.47 - }
188.48 -
188.49 - @Http({
188.50 - @Http.Resource(path = "/url", content = "Hello via URL!", mimeType = "text/plain")
188.51 - })
188.52 - @BrwsrTest
188.53 - public String testReadContentViaURL() throws Exception {
188.54 - URL url = new URL("http:/url");
188.55 - String msg = (String) url.getContent();
188.56 - assert "Hello via URL!".equals(msg) : "The message was " + msg;
188.57 - return msg;
188.58 - }
188.59 - @Http({
188.60 - @Http.Resource(path = "/url", content = "Hello via URL!", mimeType = "text/plain")
188.61 - })
188.62 - @BrwsrTest
188.63 - public String testReadContentViaURLWithStringParam() throws Exception {
188.64 - URL url = new URL("http:/url");
188.65 - String msg = (String) url.getContent(new Class[] { String.class });
188.66 - assert "Hello via URL!".equals(msg) : "The message was " + msg;
188.67 - return msg;
188.68 - }
188.69 -
188.70 - @Http({
188.71 - @Http.Resource(path = "/bytes", content = "", resource = "0xfe", mimeType = "x-application/binary")
188.72 - })
188.73 - @BrwsrTest
188.74 - public void testReadByte() throws Exception {
188.75 - URL url = new URL("http:/bytes");
188.76 - final Object res = url.getContent(new Class[] { byte[].class });
188.77 - assert res instanceof byte[] : "Expecting byte[]: " + res;
188.78 - byte[] arr = (byte[]) res;
188.79 - assert arr.length == 1 : "One byte " + arr.length;
188.80 - assert arr[0] == 0xfe : "It is 0xfe: " + Integer.toHexString(arr[0]);
188.81 - }
188.82 -
188.83 - @Http({
188.84 - @Http.Resource(path = "/bytes", content = "", resource = "0xfe", mimeType = "x-application/binary")
188.85 - })
188.86 - @BrwsrTest
188.87 - public void testReadByteViaInputStream() throws Exception {
188.88 - URL url = new URL("http:/bytes");
188.89 - InputStream is = url.openStream();
188.90 - byte[] arr = new byte[10];
188.91 - int len = is.read(arr);
188.92 - assert len == 1 : "One byte " + len;
188.93 - assert arr[0] == 0xfe : "It is 0xfe: " + Integer.toHexString(arr[0]);
188.94 - }
188.95 -
188.96 - @JavaScriptBody(args = { "url" }, body =
188.97 - "var req = new XMLHttpRequest();\n"
188.98 - + "req.open('GET', url, false);\n"
188.99 - + "req.send();\n"
188.100 - + "return req.responseText;"
188.101 - )
188.102 - private static native String read(String url);
188.103 -
188.104 -
188.105 - @Factory
188.106 - public static Object[] create() {
188.107 - return VMTest.create(HttpResourceTest.class);
188.108 - }
188.109 -}
189.1 --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/InheritanceA.java Tue Apr 02 15:40:51 2013 +0200
189.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
189.3 @@ -1,34 +0,0 @@
189.4 -/**
189.5 - * Back 2 Browser Bytecode Translator
189.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
189.7 - *
189.8 - * This program is free software: you can redistribute it and/or modify
189.9 - * it under the terms of the GNU General Public License as published by
189.10 - * the Free Software Foundation, version 2 of the License.
189.11 - *
189.12 - * This program is distributed in the hope that it will be useful,
189.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
189.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
189.15 - * GNU General Public License for more details.
189.16 - *
189.17 - * You should have received a copy of the GNU General Public License
189.18 - * along with this program. Look for COPYING file in the top folder.
189.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
189.20 - */
189.21 -package org.apidesign.bck2brwsr.tck;
189.22 -
189.23 -/**
189.24 - *
189.25 - * @author Jaroslav Tulach <jtulach@netbeans.org>
189.26 - */
189.27 -public class InheritanceA {
189.28 - private String name;
189.29 -
189.30 - public void setA(String n) {
189.31 - this.name = n;
189.32 - }
189.33 -
189.34 - public String getA() {
189.35 - return name;
189.36 - }
189.37 -}
190.1 --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/InheritanceB.java Tue Apr 02 15:40:51 2013 +0200
190.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
190.3 @@ -1,34 +0,0 @@
190.4 -/**
190.5 - * Back 2 Browser Bytecode Translator
190.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
190.7 - *
190.8 - * This program is free software: you can redistribute it and/or modify
190.9 - * it under the terms of the GNU General Public License as published by
190.10 - * the Free Software Foundation, version 2 of the License.
190.11 - *
190.12 - * This program is distributed in the hope that it will be useful,
190.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
190.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
190.15 - * GNU General Public License for more details.
190.16 - *
190.17 - * You should have received a copy of the GNU General Public License
190.18 - * along with this program. Look for COPYING file in the top folder.
190.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
190.20 - */
190.21 -package org.apidesign.bck2brwsr.tck;
190.22 -
190.23 -/**
190.24 - *
190.25 - * @author Jaroslav Tulach <jtulach@netbeans.org>
190.26 - */
190.27 -public class InheritanceB extends InheritanceA {
190.28 - private String name;
190.29 -
190.30 - public void setB(String n) {
190.31 - this.name = n;
190.32 - }
190.33 -
190.34 - public String getB() {
190.35 - return name;
190.36 - }
190.37 -}
191.1 --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/InheritanceTest.java Tue Apr 02 15:40:51 2013 +0200
191.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
191.3 @@ -1,41 +0,0 @@
191.4 -/**
191.5 - * Back 2 Browser Bytecode Translator
191.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
191.7 - *
191.8 - * This program is free software: you can redistribute it and/or modify
191.9 - * it under the terms of the GNU General Public License as published by
191.10 - * the Free Software Foundation, version 2 of the License.
191.11 - *
191.12 - * This program is distributed in the hope that it will be useful,
191.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
191.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
191.15 - * GNU General Public License for more details.
191.16 - *
191.17 - * You should have received a copy of the GNU General Public License
191.18 - * along with this program. Look for COPYING file in the top folder.
191.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
191.20 - */
191.21 -package org.apidesign.bck2brwsr.tck;
191.22 -
191.23 -import org.apidesign.bck2brwsr.vmtest.Compare;
191.24 -import org.apidesign.bck2brwsr.vmtest.VMTest;
191.25 -import org.testng.annotations.Factory;
191.26 -
191.27 -/**
191.28 - *
191.29 - * @author Jaroslav Tulach <jtulach@netbeans.org>
191.30 - */
191.31 -public class InheritanceTest {
191.32 -
191.33 - @Compare public String checkFieldsIndependent() throws ClassNotFoundException {
191.34 - InheritanceB ib = new InheritanceB();
191.35 - ib.setA("A");
191.36 - ib.setB("B");
191.37 - return "A: " + ib.getA() + " B: " + ib.getB();
191.38 - }
191.39 -
191.40 - @Factory
191.41 - public static Object[] create() {
191.42 - return VMTest.create(InheritanceTest.class);
191.43 - }
191.44 -}
192.1 --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/IntegerArithmeticTest.java Tue Apr 02 15:40:51 2013 +0200
192.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
192.3 @@ -1,166 +0,0 @@
192.4 -/**
192.5 - * Back 2 Browser Bytecode Translator
192.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
192.7 - *
192.8 - * This program is free software: you can redistribute it and/or modify
192.9 - * it under the terms of the GNU General Public License as published by
192.10 - * the Free Software Foundation, version 2 of the License.
192.11 - *
192.12 - * This program is distributed in the hope that it will be useful,
192.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
192.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
192.15 - * GNU General Public License for more details.
192.16 - *
192.17 - * You should have received a copy of the GNU General Public License
192.18 - * along with this program. Look for COPYING file in the top folder.
192.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
192.20 - */
192.21 -package org.apidesign.bck2brwsr.tck;
192.22 -
192.23 -import org.apidesign.bck2brwsr.vmtest.Compare;
192.24 -import org.apidesign.bck2brwsr.vmtest.VMTest;
192.25 -import org.testng.annotations.Factory;
192.26 -
192.27 -/**
192.28 - *
192.29 - * @author Jaroslav Tulach <jtulach@netbeans.org>
192.30 - */
192.31 -public class IntegerArithmeticTest {
192.32 -
192.33 - private static int add(int x, int y) {
192.34 - return x + y;
192.35 - }
192.36 -
192.37 - private static int sub(int x, int y) {
192.38 - return x - y;
192.39 - }
192.40 -
192.41 - private static int mul(int x, int y) {
192.42 - return x * y;
192.43 - }
192.44 -
192.45 - private static int div(int x, int y) {
192.46 - return x / y;
192.47 - }
192.48 -
192.49 - private static int mod(int x, int y) {
192.50 - return x % y;
192.51 - }
192.52 -
192.53 - private static int neg(int x) {
192.54 - return (-x);
192.55 - }
192.56 -
192.57 - private static float fadd(float x, float y) {
192.58 - return x + y;
192.59 - }
192.60 -
192.61 - private static double dadd(double x, double y) {
192.62 - return x + y;
192.63 - }
192.64 -
192.65 - @Compare public int addOverflow() {
192.66 - return add(Integer.MAX_VALUE, 1);
192.67 - }
192.68 -
192.69 - @Compare public int subUnderflow() {
192.70 - return sub(Integer.MIN_VALUE, 1);
192.71 - }
192.72 -
192.73 - @Compare public int addMaxIntAndMaxInt() {
192.74 - return add(Integer.MAX_VALUE, Integer.MAX_VALUE);
192.75 - }
192.76 -
192.77 - @Compare public int subMinIntAndMinInt() {
192.78 - return sub(Integer.MIN_VALUE, Integer.MIN_VALUE);
192.79 - }
192.80 -
192.81 - @Compare public int multiplyMaxInt() {
192.82 - return mul(Integer.MAX_VALUE, 2);
192.83 - }
192.84 -
192.85 - @Compare public int multiplyMaxIntAndMaxInt() {
192.86 - return mul(Integer.MAX_VALUE, Integer.MAX_VALUE);
192.87 - }
192.88 -
192.89 - @Compare public int multiplyMinInt() {
192.90 - return mul(Integer.MIN_VALUE, 2);
192.91 - }
192.92 -
192.93 - @Compare public int multiplyMinIntAndMinInt() {
192.94 - return mul(Integer.MIN_VALUE, Integer.MIN_VALUE);
192.95 - }
192.96 -
192.97 - @Compare public int multiplyPrecision() {
192.98 - return mul(119106029, 1103515245);
192.99 - }
192.100 -
192.101 - @Compare public int division() {
192.102 - return div(1, 2);
192.103 - }
192.104 -
192.105 - @Compare public int divisionReminder() {
192.106 - return mod(1, 2);
192.107 - }
192.108 -
192.109 - @Compare public int negativeDivision() {
192.110 - return div(-7, 3);
192.111 - }
192.112 -
192.113 - @Compare public int negativeDivisionReminder() {
192.114 - return mod(-7, 3);
192.115 - }
192.116 -
192.117 - @Compare public int conversionFromFloat() {
192.118 - return (int) fadd(-2, -0.6f);
192.119 - }
192.120 -
192.121 - @Compare public int conversionFromDouble() {
192.122 - return (int) dadd(-2, -0.6);
192.123 - }
192.124 -
192.125 - @Compare public boolean divByZeroThrowsArithmeticException() {
192.126 - try {
192.127 - div(1, 0);
192.128 - return false;
192.129 - } catch (final ArithmeticException e) {
192.130 - return true;
192.131 - }
192.132 - }
192.133 -
192.134 - @Compare public boolean modByZeroThrowsArithmeticException() {
192.135 - try {
192.136 - mod(1, 0);
192.137 - return false;
192.138 - } catch (final ArithmeticException e) {
192.139 - return true;
192.140 - }
192.141 - }
192.142 -
192.143 - @Compare public int negate() {
192.144 - return neg(123456);
192.145 - }
192.146 -
192.147 - @Compare public int negateMaxInt() {
192.148 - return neg(Integer.MAX_VALUE);
192.149 - }
192.150 -
192.151 - @Compare public int negateMinInt() {
192.152 - return neg(Integer.MIN_VALUE);
192.153 - }
192.154 -
192.155 - @Compare public int sumTwoDimensions() {
192.156 - int[][] matrix = createMatrix(4, 3);
192.157 - matrix[0][0] += 10;
192.158 - return matrix[0][0];
192.159 - }
192.160 -
192.161 - static int[][] createMatrix(int x, int y) {
192.162 - return new int[x][y];
192.163 - }
192.164 -
192.165 - @Factory
192.166 - public static Object[] create() {
192.167 - return VMTest.create(IntegerArithmeticTest.class);
192.168 - }
192.169 -}
193.1 --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/LongArithmeticTest.java Tue Apr 02 15:40:51 2013 +0200
193.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
193.3 @@ -1,376 +0,0 @@
193.4 -/**
193.5 - * Back 2 Browser Bytecode Translator
193.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
193.7 - *
193.8 - * This program is free software: you can redistribute it and/or modify
193.9 - * it under the terms of the GNU General Public License as published by
193.10 - * the Free Software Foundation, version 2 of the License.
193.11 - *
193.12 - * This program is distributed in the hope that it will be useful,
193.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
193.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
193.15 - * GNU General Public License for more details.
193.16 - *
193.17 - * You should have received a copy of the GNU General Public License
193.18 - * along with this program. Look for COPYING file in the top folder.
193.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
193.20 - */
193.21 -package org.apidesign.bck2brwsr.tck;
193.22 -
193.23 -import org.apidesign.bck2brwsr.vmtest.Compare;
193.24 -import org.apidesign.bck2brwsr.vmtest.VMTest;
193.25 -import org.testng.annotations.Factory;
193.26 -
193.27 -/**
193.28 - *
193.29 - * @author Jaroslav Tulach <jtulach@netbeans.org>
193.30 - */
193.31 -public class LongArithmeticTest {
193.32 -
193.33 - private static long add(long x, long y) {
193.34 - return (x + y);
193.35 - }
193.36 -
193.37 - private static long sub(long x, long y) {
193.38 - return (x - y);
193.39 - }
193.40 -
193.41 - private static long mul(long x, long y) {
193.42 - return (x * y);
193.43 - }
193.44 -
193.45 - private static long div(long x, long y) {
193.46 - return (x / y);
193.47 - }
193.48 -
193.49 - private static long mod(long x, long y) {
193.50 - return (x % y);
193.51 - }
193.52 -
193.53 - private static long neg(long x) {
193.54 - return (-x);
193.55 - }
193.56 -
193.57 - private static long shl(long x, int b) {
193.58 - return (x << b);
193.59 - }
193.60 -
193.61 - private static long shr(long x, int b) {
193.62 - return (x >> b);
193.63 - }
193.64 -
193.65 - private static long ushr(long x, int b) {
193.66 - return (x >>> b);
193.67 - }
193.68 -
193.69 - private static long and(long x, long y) {
193.70 - return (x & y);
193.71 - }
193.72 -
193.73 - private static long or(long x, long y) {
193.74 - return (x | y);
193.75 - }
193.76 -
193.77 - private static long xor(long x, long y) {
193.78 - return (x ^ y);
193.79 - }
193.80 -
193.81 - private static float fadd(float x, float y) {
193.82 - return x + y;
193.83 - }
193.84 -
193.85 - private static double dadd(double x, double y) {
193.86 - return x + y;
193.87 - }
193.88 -
193.89 - public static int compare(long x, long y, int zero) {
193.90 - final int xyResult = compareL(x, y, zero);
193.91 - final int yxResult = compareL(y, x, zero);
193.92 -
193.93 - return ((xyResult + yxResult) == 0) ? xyResult : -2;
193.94 - }
193.95 -
193.96 - private static int compareL(long x, long y, int zero) {
193.97 - int result = -2;
193.98 - int trueCount = 0;
193.99 -
193.100 - x += zero;
193.101 - if (x == y) {
193.102 - result = 0;
193.103 - ++trueCount;
193.104 - }
193.105 -
193.106 - x += zero;
193.107 - if (x < y) {
193.108 - result = -1;
193.109 - ++trueCount;
193.110 - }
193.111 -
193.112 - x += zero;
193.113 - if (x > y) {
193.114 - result = 1;
193.115 - ++trueCount;
193.116 - }
193.117 -
193.118 - return (trueCount == 1) ? result : -2;
193.119 - }
193.120 -
193.121 - @Compare public long conversion() {
193.122 - return Long.MAX_VALUE;
193.123 - }
193.124 -
193.125 - @Compare public long negate1() {
193.126 - return neg(0x00fa37d7763e0ca1l);
193.127 - }
193.128 -
193.129 - @Compare public long negate2() {
193.130 - return neg(0x80fa37d7763e0ca1l);
193.131 - }
193.132 -
193.133 - @Compare public long negate3() {
193.134 - return neg(0xfffffffffffffeddl);
193.135 - }
193.136 -
193.137 - @Compare public long addOverflow() {
193.138 - return add(Long.MAX_VALUE, 1l);
193.139 - }
193.140 -
193.141 - @Compare public long subUnderflow() {
193.142 - return sub(Long.MIN_VALUE, 1l);
193.143 - }
193.144 -
193.145 - @Compare public long addMaxLongAndMaxLong() {
193.146 - return add(Long.MAX_VALUE, Long.MAX_VALUE);
193.147 - }
193.148 -
193.149 - @Compare public long subMinLongAndMinLong() {
193.150 - return sub(Long.MIN_VALUE, Long.MIN_VALUE);
193.151 - }
193.152 -
193.153 - @Compare public long subMinLongAndMaxLong() {
193.154 - return sub(Long.MIN_VALUE, Long.MAX_VALUE);
193.155 - }
193.156 -
193.157 - @Compare public long multiplyMaxLong() {
193.158 - return mul(Long.MAX_VALUE, 2l);
193.159 - }
193.160 -
193.161 - @Compare public long multiplyMaxLongAndMaxLong() {
193.162 - return mul(Long.MAX_VALUE, Long.MAX_VALUE);
193.163 - }
193.164 -
193.165 - @Compare public long multiplyMinLong() {
193.166 - return mul(Long.MIN_VALUE, 2l);
193.167 - }
193.168 -
193.169 - @Compare public long multiplyMinLongAndMinLong() {
193.170 - return mul(Long.MIN_VALUE, Long.MIN_VALUE);
193.171 - }
193.172 -
193.173 - @Compare public long multiplyPrecision() {
193.174 - return mul(0x00fa37d7763e0ca1l, 0xa7b3432fff00123el);
193.175 - }
193.176 -
193.177 - @Compare public long divideSmallPositiveNumbers() {
193.178 - return div(0xabcdef, 0x123);
193.179 - }
193.180 -
193.181 - @Compare public long divideSmallNegativeNumbers() {
193.182 - return div(-0xabcdef, -0x123);
193.183 - }
193.184 -
193.185 - @Compare public long divideSmallMixedNumbers() {
193.186 - return div(0xabcdef, -0x123);
193.187 - }
193.188 -
193.189 - @Compare public long dividePositiveNumbersOneDigitDenom() {
193.190 - return div(0xabcdef0102ffffl, 0x654);
193.191 - }
193.192 -
193.193 - @Compare public long divideNegativeNumbersOneDigitDenom() {
193.194 - return div(-0xabcdef0102ffffl, -0x654);
193.195 - }
193.196 -
193.197 - @Compare public long divideMixedNumbersOneDigitDenom() {
193.198 - return div(-0xabcdef0102ffffl, 0x654);
193.199 - }
193.200 -
193.201 - @Compare public long dividePositiveNumbersMultiDigitDenom() {
193.202 - return div(0x7ffefc003322aabbl, 0x89ab1000l);
193.203 - }
193.204 -
193.205 - @Compare public long divideNegativeNumbersMultiDigitDenom() {
193.206 - return div(-0x7ffefc003322aabbl, -0x123489ab1001l);
193.207 - }
193.208 -
193.209 - @Compare public long divideMixedNumbersMultiDigitDenom() {
193.210 - return div(0x7ffefc003322aabbl, -0x38f49b0b7574e36l);
193.211 - }
193.212 -
193.213 - @Compare public long divideWithOverflow() {
193.214 - return div(0x8000fffe0000l, 0x8000ffffl);
193.215 - }
193.216 -
193.217 - @Compare public long divideWithCorrection() {
193.218 - return div(0x7fff800000000000l, 0x800000000001l);
193.219 - }
193.220 -
193.221 - @Compare public long moduloSmallPositiveNumbers() {
193.222 - return mod(0xabcdef, 0x123);
193.223 - }
193.224 -
193.225 - @Compare public long moduloSmallNegativeNumbers() {
193.226 - return mod(-0xabcdef, -0x123);
193.227 - }
193.228 -
193.229 - @Compare public long moduloSmallMixedNumbers() {
193.230 - return mod(0xabcdef, -0x123);
193.231 - }
193.232 -
193.233 - @Compare public long moduloPositiveNumbersOneDigitDenom() {
193.234 - return mod(0xabcdef0102ffffl, 0x654);
193.235 - }
193.236 -
193.237 - @Compare public long moduloNegativeNumbersOneDigitDenom() {
193.238 - return mod(-0xabcdef0102ffffl, -0x654);
193.239 - }
193.240 -
193.241 - @Compare public long moduloMixedNumbersOneDigitDenom() {
193.242 - return mod(-0xabcdef0102ffffl, 0x654);
193.243 - }
193.244 -
193.245 - @Compare public long moduloPositiveNumbersMultiDigitDenom() {
193.246 - return mod(0x7ffefc003322aabbl, 0x89ab1000l);
193.247 - }
193.248 -
193.249 - @Compare public long moduloNegativeNumbersMultiDigitDenom() {
193.250 - return mod(-0x7ffefc003322aabbl, -0x123489ab1001l);
193.251 - }
193.252 -
193.253 - @Compare public long moduloMixedNumbersMultiDigitDenom() {
193.254 - return mod(0x7ffefc003322aabbl, -0x38f49b0b7574e36l);
193.255 - }
193.256 -
193.257 - @Compare public long moduloWithOverflow() {
193.258 - return mod(0x8000fffe0000l, 0x8000ffffl);
193.259 - }
193.260 -
193.261 - @Compare public long moduloWithCorrection() {
193.262 - return mod(0x7fff800000000000l, 0x800000000001l);
193.263 - }
193.264 -
193.265 - @Compare public long conversionFromFloatPositive() {
193.266 - return (long) fadd(2, 0.6f);
193.267 - }
193.268 -
193.269 - @Compare public long conversionFromFloatNegative() {
193.270 - return (long) fadd(-2, -0.6f);
193.271 - }
193.272 -
193.273 - @Compare public long conversionFromDoublePositive() {
193.274 - return (long) dadd(0x20ffff0000L, 0.6);
193.275 - }
193.276 -
193.277 - @Compare public long conversionFromDoubleNegative() {
193.278 - return (long) dadd(-0x20ffff0000L, -0.6);
193.279 - }
193.280 -
193.281 - @Compare public boolean divByZeroThrowsArithmeticException() {
193.282 - try {
193.283 - div(1, 0);
193.284 - return false;
193.285 - } catch (final ArithmeticException e) {
193.286 - return true;
193.287 - }
193.288 - }
193.289 -
193.290 - @Compare public boolean modByZeroThrowsArithmeticException() {
193.291 - try {
193.292 - mod(1, 0);
193.293 - return false;
193.294 - } catch (final ArithmeticException e) {
193.295 - return true;
193.296 - }
193.297 - }
193.298 -
193.299 - @Compare public long shiftL1() {
193.300 - return shl(0x00fa37d7763e0ca1l, 5);
193.301 - }
193.302 -
193.303 - @Compare public long shiftL2() {
193.304 - return shl(0x00fa37d7763e0ca1l, 32);
193.305 - }
193.306 -
193.307 - @Compare public long shiftL3() {
193.308 - return shl(0x00fa37d7763e0ca1l, 45);
193.309 - }
193.310 -
193.311 - @Compare public long shiftR1() {
193.312 - return shr(0x00fa37d7763e0ca1l, 5);
193.313 - }
193.314 -
193.315 - @Compare public long shiftR2() {
193.316 - return shr(0x00fa37d7763e0ca1l, 32);
193.317 - }
193.318 -
193.319 - @Compare public long shiftR3() {
193.320 - return shr(0x00fa37d7763e0ca1l, 45);
193.321 - }
193.322 -
193.323 - @Compare public long uShiftR1() {
193.324 - return ushr(0x00fa37d7763e0ca1l, 5);
193.325 - }
193.326 -
193.327 - @Compare public long uShiftR2() {
193.328 - return ushr(0x00fa37d7763e0ca1l, 45);
193.329 - }
193.330 -
193.331 - @Compare public long uShiftR3() {
193.332 - return ushr(0xf0fa37d7763e0ca1l, 5);
193.333 - }
193.334 -
193.335 - @Compare public long uShiftR4() {
193.336 - return ushr(0xf0fa37d7763e0ca1l, 45);
193.337 - }
193.338 -
193.339 - @Compare public long and1() {
193.340 - return and(0x00fa37d7763e0ca1l, 0xa7b3432fff00123el);
193.341 - }
193.342 -
193.343 - @Compare public long or1() {
193.344 - return or(0x00fa37d7763e0ca1l, 0xa7b3432fff00123el);
193.345 - }
193.346 -
193.347 - @Compare public long xor1() {
193.348 - return xor(0x00fa37d7763e0ca1l, 0xa7b3432fff00123el);
193.349 - }
193.350 -
193.351 - @Compare public long xor2() {
193.352 - return xor(0x00fa37d7763e0ca1l, 0x00000000ff00123el);
193.353 - }
193.354 -
193.355 - @Compare public long xor3() {
193.356 - return xor(0x00000000763e0ca1l, 0x00000000ff00123el);
193.357 - }
193.358 -
193.359 - @Compare public int compareSameNumbers() {
193.360 - return compare(0x0000000000000000l, 0x0000000000000000l, 0);
193.361 - }
193.362 -
193.363 - @Compare public int comparePositiveNumbers() {
193.364 - return compare(0x0000000000200000l, 0x0000000010000000l, 0);
193.365 - }
193.366 -
193.367 - @Compare public int compareNegativeNumbers() {
193.368 - return compare(0xffffffffffffffffl, 0xffffffff00000000l, 0);
193.369 - }
193.370 -
193.371 - @Compare public int compareMixedNumbers() {
193.372 - return compare(0x8000000000000000l, 0x7fffffffffffffffl, 0);
193.373 - }
193.374 -
193.375 - @Factory
193.376 - public static Object[] create() {
193.377 - return VMTest.create(LongArithmeticTest.class);
193.378 - }
193.379 -}
194.1 --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ReflectionArrayTest.java Tue Apr 02 15:40:51 2013 +0200
194.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
194.3 @@ -1,135 +0,0 @@
194.4 -/**
194.5 - * Back 2 Browser Bytecode Translator
194.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
194.7 - *
194.8 - * This program is free software: you can redistribute it and/or modify
194.9 - * it under the terms of the GNU General Public License as published by
194.10 - * the Free Software Foundation, version 2 of the License.
194.11 - *
194.12 - * This program is distributed in the hope that it will be useful,
194.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
194.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
194.15 - * GNU General Public License for more details.
194.16 - *
194.17 - * You should have received a copy of the GNU General Public License
194.18 - * along with this program. Look for COPYING file in the top folder.
194.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
194.20 - */
194.21 -package org.apidesign.bck2brwsr.tck;
194.22 -
194.23 -import java.lang.reflect.Array;
194.24 -import org.apidesign.bck2brwsr.vmtest.Compare;
194.25 -import org.apidesign.bck2brwsr.vmtest.VMTest;
194.26 -import org.testng.annotations.Factory;
194.27 -
194.28 -/**
194.29 - *
194.30 - * @author Jaroslav Tulach <jtulach@netbeans.org>
194.31 - */
194.32 -public class ReflectionArrayTest {
194.33 - @Compare public int lengthOfStringArray() {
194.34 - String[] arr = (String[]) Array.newInstance(String.class, 10);
194.35 - return arr.length;
194.36 - }
194.37 -
194.38 - @Compare public int reflectiveLengthOfStringArray() {
194.39 - Object arr = Array.newInstance(String.class, 10);
194.40 - return Array.getLength(arr);
194.41 - }
194.42 -
194.43 - @Compare public int reflectiveLengthOneNonArray() {
194.44 - Object arr = "non-array";
194.45 - return Array.getLength(arr);
194.46 - }
194.47 -
194.48 - @Compare public String compTypeOfStringArray() {
194.49 - String[] arr = (String[]) Array.newInstance(String.class, 10);
194.50 - return arr.getClass().getComponentType().getName();
194.51 - }
194.52 -
194.53 - @Compare public Object negativeArrayExcp() {
194.54 - return Array.newInstance(String.class, -5);
194.55 - }
194.56 -
194.57 - @Compare public int lengthOfIntArray() {
194.58 - int[] arr = (int[]) Array.newInstance(Integer.TYPE, 10);
194.59 - return arr.length;
194.60 - }
194.61 -
194.62 - @Compare public int reflectiveLengthOfIntArray() {
194.63 - Object arr = Array.newInstance(Integer.TYPE, 10);
194.64 - return Array.getLength(arr);
194.65 - }
194.66 -
194.67 - @Compare public String compTypeOfIntArray() {
194.68 - int[] arr = (int[]) Array.newInstance(int.class, 10);
194.69 - return arr.getClass().getComponentType().getName();
194.70 - }
194.71 -
194.72 - @Compare public Object intNegativeArrayExcp() {
194.73 - return Array.newInstance(int.class, -5);
194.74 - }
194.75 -
194.76 - @Compare public Integer verifyAutobox() {
194.77 - int[] arr = (int[]) Array.newInstance(int.class, 5);
194.78 - return (Integer) Array.get(arr, 0);
194.79 - }
194.80 - @Compare public String verifyObjectArray() {
194.81 - String[] arr = (String[]) Array.newInstance(String.class, 5);
194.82 - Array.set(arr, 0, "Hello");
194.83 - return (String) Array.get(arr, 0);
194.84 - }
194.85 - @Compare public int verifyInt() {
194.86 - int[] arr = (int[]) Array.newInstance(int.class, 5);
194.87 - return Array.getInt(arr, 0);
194.88 - }
194.89 - @Compare public long verifyConvertToLong() {
194.90 - int[] arr = (int[]) Array.newInstance(int.class, 5);
194.91 - return Array.getLong(arr, 0);
194.92 - }
194.93 -
194.94 - @Compare public Object verifySetIntToObject() {
194.95 - try {
194.96 - Object[] arr = (Object[]) Array.newInstance(Object.class, 5);
194.97 - Array.setInt(arr, 0, 10);
194.98 - return Array.get(arr, 0);
194.99 - } catch (Exception exception) {
194.100 - return exception.getClass().getName();
194.101 - }
194.102 - }
194.103 - @Compare public long verifySetShort() {
194.104 - int[] arr = (int[]) Array.newInstance(int.class, 5);
194.105 - Array.setShort(arr, 0, (short)10);
194.106 - return Array.getLong(arr, 0);
194.107 - }
194.108 - @Compare public long verifyCantSetLong() {
194.109 - int[] arr = (int[]) Array.newInstance(int.class, 5);
194.110 - Array.setLong(arr, 0, 10);
194.111 - return Array.getLong(arr, 0);
194.112 - }
194.113 - @Compare public float verifyLongToFloat() {
194.114 - Object arr = Array.newInstance(float.class, 5);
194.115 - Array.setLong(arr, 0, 10);
194.116 - return Array.getFloat(arr, 0);
194.117 - }
194.118 -
194.119 - @Compare public double verifyConvertToDouble() {
194.120 - int[] arr = (int[]) Array.newInstance(int.class, 5);
194.121 - return Array.getDouble(arr, 0);
194.122 - }
194.123 -
194.124 - @Compare public int multiIntArray() {
194.125 - int[][][] arr = (int[][][]) Array.newInstance(int.class, 3, 3, 3);
194.126 - return arr[0][1][2] + 5 + arr[2][2][0];
194.127 - }
194.128 -
194.129 - @Compare public String multiIntArrayCompType() {
194.130 - return Array.newInstance(int.class, 3, 3, 3).getClass().getName();
194.131 - }
194.132 -
194.133 -
194.134 - @Factory
194.135 - public static Object[] create() {
194.136 - return VMTest.create(ReflectionArrayTest.class);
194.137 - }
194.138 -}
195.1 --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ReflectionTest.java Tue Apr 02 15:40:51 2013 +0200
195.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
195.3 @@ -1,242 +0,0 @@
195.4 -/**
195.5 - * Back 2 Browser Bytecode Translator
195.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
195.7 - *
195.8 - * This program is free software: you can redistribute it and/or modify
195.9 - * it under the terms of the GNU General Public License as published by
195.10 - * the Free Software Foundation, version 2 of the License.
195.11 - *
195.12 - * This program is distributed in the hope that it will be useful,
195.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
195.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
195.15 - * GNU General Public License for more details.
195.16 - *
195.17 - * You should have received a copy of the GNU General Public License
195.18 - * along with this program. Look for COPYING file in the top folder.
195.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
195.20 - */
195.21 -package org.apidesign.bck2brwsr.tck;
195.22 -
195.23 -import java.lang.annotation.Retention;
195.24 -import java.lang.annotation.RetentionPolicy;
195.25 -import java.lang.reflect.Method;
195.26 -import java.util.Arrays;
195.27 -import java.util.Collections;
195.28 -import java.util.List;
195.29 -import org.apidesign.bck2brwsr.core.JavaScriptBody;
195.30 -import org.apidesign.bck2brwsr.vmtest.Compare;
195.31 -import org.apidesign.bck2brwsr.vmtest.VMTest;
195.32 -import org.testng.annotations.Factory;
195.33 -
195.34 -/**
195.35 - *
195.36 - * @author Jaroslav Tulach <jtulach@netbeans.org>
195.37 - */
195.38 -public class ReflectionTest {
195.39 - @Compare public boolean nonNullThis() {
195.40 - return this == null;
195.41 - }
195.42 -
195.43 - @Compare public String intType() {
195.44 - return Integer.TYPE.toString();
195.45 - }
195.46 -
195.47 - @Compare public String voidType() throws Exception {
195.48 - return void.class.toString();
195.49 - }
195.50 -
195.51 - @Compare public String longClass() {
195.52 - return long.class.toString();
195.53 - }
195.54 -
195.55 - @Compare public boolean isRunnableInterface() {
195.56 - return Runnable.class.isInterface();
195.57 - }
195.58 -
195.59 - @Compare public String isRunnableHasRunMethod() throws NoSuchMethodException {
195.60 - return Runnable.class.getMethod("run").getName();
195.61 - }
195.62 -
195.63 - @Compare public String namesOfMethods() {
195.64 - StringBuilder sb = new StringBuilder();
195.65 - String[] arr = new String[20];
195.66 - int i = 0;
195.67 - for (Method m : StaticUse.class.getMethods()) {
195.68 - arr[i++] = m.getName();
195.69 - }
195.70 - for (String s : sort(arr, i)) {
195.71 - sb.append(s).append("\n");
195.72 - }
195.73 - return sb.toString();
195.74 - }
195.75 -
195.76 - @Compare public String namesOfDeclaringClassesOfMethods() {
195.77 - StringBuilder sb = new StringBuilder();
195.78 - String[] arr = new String[20];
195.79 - int i = 0;
195.80 - for (Method m : StaticUse.class.getMethods()) {
195.81 - arr[i++] = m.getName() + "@" + m.getDeclaringClass().getName();
195.82 - }
195.83 - for (String s : sort(arr, i)) {
195.84 - sb.append(s).append("\n");
195.85 - }
195.86 - return sb.toString();
195.87 - }
195.88 -
195.89 - @Compare public String cannotCallNonStaticMethodWithNull() throws Exception {
195.90 - StaticUse.class.getMethod("instanceMethod").invoke(null);
195.91 - return "should not happen";
195.92 - }
195.93 -
195.94 - @Compare public Object voidReturnType() throws Exception {
195.95 - return StaticUse.class.getMethod("instanceMethod").getReturnType();
195.96 - }
195.97 -
195.98 - @Retention(RetentionPolicy.RUNTIME)
195.99 - @interface Ann {
195.100 - }
195.101 -
195.102 - @Compare public String annoClass() throws Exception {
195.103 - Retention r = Ann.class.getAnnotation(Retention.class);
195.104 - assert r != null : "Annotation is present";
195.105 - assert r.value() == RetentionPolicy.RUNTIME : "Policy value is OK: " + r.value();
195.106 - return r.annotationType().getName();
195.107 - }
195.108 -
195.109 - @Compare public boolean isAnnotation() {
195.110 - return Ann.class.isAnnotation();
195.111 - }
195.112 - @Compare public boolean isNotAnnotation() {
195.113 - return String.class.isAnnotation();
195.114 - }
195.115 - @Compare public boolean isNotAnnotationEnum() {
195.116 - return E.class.isAnnotation();
195.117 - }
195.118 - enum E { A, B };
195.119 - @Compare public boolean isEnum() {
195.120 - return E.A.getClass().isEnum();
195.121 - }
195.122 -
195.123 - @Compare public boolean isNotEnum() {
195.124 - return "".getClass().isEnum();
195.125 - }
195.126 -
195.127 - @Compare public String newInstanceFails() throws InstantiationException {
195.128 - try {
195.129 - return "success: " + StaticUseSub.class.newInstance();
195.130 - } catch (IllegalAccessException ex) {
195.131 - return ex.getClass().getName();
195.132 - }
195.133 - }
195.134 -
195.135 - @Compare public String paramTypes() throws Exception {
195.136 - Method plus = StaticUse.class.getMethod("plus", int.class, Integer.TYPE);
195.137 - final Class[] pt = plus.getParameterTypes();
195.138 - return pt[0].getName();
195.139 - }
195.140 - @Compare public String paramTypesNotFound() throws Exception {
195.141 - return StaticUse.class.getMethod("plus", int.class, double.class).toString();
195.142 - }
195.143 - @Compare public int methodWithArgs() throws Exception {
195.144 - Method plus = StaticUse.class.getMethod("plus", int.class, Integer.TYPE);
195.145 - return (Integer)plus.invoke(null, 2, 3);
195.146 - }
195.147 -
195.148 - @Compare public String classGetNameForByte() {
195.149 - return byte.class.getName();
195.150 - }
195.151 - @Compare public String classGetNameForBaseObject() {
195.152 - return newObject().getClass().getName();
195.153 - }
195.154 - @Compare public String classGetNameForJavaObject() {
195.155 - return new Object().getClass().getName();
195.156 - }
195.157 - @Compare public String classGetNameForObjectArray() {
195.158 - return (new Object[3]).getClass().getName();
195.159 - }
195.160 - @Compare public String classGetNameForSimpleIntArray() {
195.161 - return (new int[3]).getClass().getName();
195.162 - }
195.163 - @Compare public boolean sameClassGetNameForSimpleCharArray() {
195.164 - return (new char[3]).getClass() == (new char[34]).getClass();
195.165 - }
195.166 - @Compare public String classGetNameForMultiIntArray() {
195.167 - return (new int[3][4][5][6][7][8][9]).getClass().getName();
195.168 - }
195.169 - @Compare public String classGetNameForMultiIntArrayInner() {
195.170 - final int[][][][][][][] arr = new int[3][4][5][6][7][8][9];
195.171 - int[][][][][][] subarr = arr[0];
195.172 - int[][][][][] subsubarr = subarr[0];
195.173 - return subsubarr.getClass().getName();
195.174 - }
195.175 - @Compare public String classGetNameForMultiStringArray() {
195.176 - return (new String[3][4][5][6][7][8][9]).getClass().getName();
195.177 - }
195.178 -
195.179 - @Compare public String classForByte() throws Exception {
195.180 - return Class.forName("[Z").getName();
195.181 - }
195.182 -
195.183 - @Compare public String classForUnknownArray() {
195.184 - try {
195.185 - return Class.forName("[W").getName();
195.186 - } catch (Exception ex) {
195.187 - return ex.getClass().getName();
195.188 - }
195.189 - }
195.190 -
195.191 - @Compare public String classForUnknownDeepArray() {
195.192 - try {
195.193 - return Class.forName("[[[[[W").getName();
195.194 - } catch (Exception ex) {
195.195 - return ex.getClass().getName();
195.196 - }
195.197 - }
195.198 -
195.199 - @Compare public String componentGetNameForObjectArray() {
195.200 - return (new Object[3]).getClass().getComponentType().getName();
195.201 - }
195.202 - @Compare public boolean sameComponentGetNameForObjectArray() {
195.203 - return (new Object[3]).getClass().getComponentType() == Object.class;
195.204 - }
195.205 - @Compare public String componentGetNameForSimpleIntArray() {
195.206 - return (new int[3]).getClass().getComponentType().getName();
195.207 - }
195.208 - @Compare public String componentGetNameForMultiIntArray() {
195.209 - return (new int[3][4][5][6][7][8][9]).getClass().getComponentType().getName();
195.210 - }
195.211 - @Compare public String componentGetNameForMultiStringArray() {
195.212 - Class<?> c = (new String[3][4][5][6][7][8][9]).getClass();
195.213 - StringBuilder sb = new StringBuilder();
195.214 - for (;;) {
195.215 - sb.append(c.getName()).append("\n");
195.216 - c = c.getComponentType();
195.217 - if (c == null) {
195.218 - break;
195.219 - }
195.220 - }
195.221 - return sb.toString();
195.222 - }
195.223 -
195.224 - @Compare public boolean isArray() {
195.225 - return new Object[0].getClass().isArray();
195.226 - }
195.227 -
195.228 - @JavaScriptBody(args = { "arr", "len" }, body="var a = arr.slice(0, len); a.sort(); return a;")
195.229 - private static String[] sort(String[] arr, int len) {
195.230 - List<String> list = Arrays.asList(arr).subList(0, len);
195.231 - Collections.sort(list);
195.232 - return list.toArray(new String[0]);
195.233 - }
195.234 -
195.235 - @JavaScriptBody(args = {}, body = "return new Object();")
195.236 - private static Object newObject() {
195.237 - return new Object();
195.238 - }
195.239 -
195.240 - @Factory
195.241 - public static Object[] create() {
195.242 - return VMTest.create(ReflectionTest.class);
195.243 - }
195.244 -
195.245 -}
196.1 --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ResourcesTest.java Tue Apr 02 15:40:51 2013 +0200
196.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
196.3 @@ -1,45 +0,0 @@
196.4 -/**
196.5 - * Back 2 Browser Bytecode Translator
196.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
196.7 - *
196.8 - * This program is free software: you can redistribute it and/or modify
196.9 - * it under the terms of the GNU General Public License as published by
196.10 - * the Free Software Foundation, version 2 of the License.
196.11 - *
196.12 - * This program is distributed in the hope that it will be useful,
196.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
196.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
196.15 - * GNU General Public License for more details.
196.16 - *
196.17 - * You should have received a copy of the GNU General Public License
196.18 - * along with this program. Look for COPYING file in the top folder.
196.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
196.20 - */
196.21 -package org.apidesign.bck2brwsr.tck;
196.22 -
196.23 -import java.io.InputStream;
196.24 -import org.apidesign.bck2brwsr.vmtest.Compare;
196.25 -import org.apidesign.bck2brwsr.vmtest.VMTest;
196.26 -import org.testng.annotations.Factory;
196.27 -
196.28 -/**
196.29 - *
196.30 - * @author Jaroslav Tulach <jtulach@netbeans.org>
196.31 - */
196.32 -public class ResourcesTest {
196.33 -
196.34 - @Compare public String readResourceAsStream() throws Exception {
196.35 - InputStream is = getClass().getResourceAsStream("Resources.txt");
196.36 - byte[] b = new byte[30];
196.37 - int len = is.read(b);
196.38 - StringBuilder sb = new StringBuilder();
196.39 - for (int i = 0; i < len; i++) {
196.40 - sb.append((char)b[i]);
196.41 - }
196.42 - return sb.toString();
196.43 - }
196.44 -
196.45 - @Factory public static Object[] create() {
196.46 - return VMTest.create(ResourcesTest.class);
196.47 - }
196.48 -}
197.1 --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ShortArithmeticTest.java Tue Apr 02 15:40:51 2013 +0200
197.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
197.3 @@ -1,102 +0,0 @@
197.4 -/**
197.5 - * Back 2 Browser Bytecode Translator
197.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
197.7 - *
197.8 - * This program is free software: you can redistribute it and/or modify
197.9 - * it under the terms of the GNU General Public License as published by
197.10 - * the Free Software Foundation, version 2 of the License.
197.11 - *
197.12 - * This program is distributed in the hope that it will be useful,
197.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
197.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
197.15 - * GNU General Public License for more details.
197.16 - *
197.17 - * You should have received a copy of the GNU General Public License
197.18 - * along with this program. Look for COPYING file in the top folder.
197.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
197.20 - */
197.21 -package org.apidesign.bck2brwsr.tck;
197.22 -
197.23 -import org.apidesign.bck2brwsr.vmtest.Compare;
197.24 -import org.apidesign.bck2brwsr.vmtest.VMTest;
197.25 -import org.testng.annotations.Factory;
197.26 -
197.27 -/**
197.28 - *
197.29 - * @author Jaroslav Tulach <jtulach@netbeans.org>
197.30 - */
197.31 -public class ShortArithmeticTest {
197.32 -
197.33 - private static short add(short x, short y) {
197.34 - return (short)(x + y);
197.35 - }
197.36 -
197.37 - private static short sub(short x, short y) {
197.38 - return (short)(x - y);
197.39 - }
197.40 -
197.41 - private static short mul(short x, short y) {
197.42 - return (short)(x * y);
197.43 - }
197.44 -
197.45 - private static short div(short x, short y) {
197.46 - return (short)(x / y);
197.47 - }
197.48 -
197.49 - private static short mod(short x, short y) {
197.50 - return (short)(x % y);
197.51 - }
197.52 -
197.53 - @Compare public short conversion() {
197.54 - return (short)123456;
197.55 - }
197.56 -
197.57 - @Compare public short addOverflow() {
197.58 - return add(Short.MAX_VALUE, (short)1);
197.59 - }
197.60 -
197.61 - @Compare public short subUnderflow() {
197.62 - return sub(Short.MIN_VALUE, (short)1);
197.63 - }
197.64 -
197.65 - @Compare public short addMaxShortAndMaxShort() {
197.66 - return add(Short.MAX_VALUE, Short.MAX_VALUE);
197.67 - }
197.68 -
197.69 - @Compare public short subMinShortAndMinShort() {
197.70 - return sub(Short.MIN_VALUE, Short.MIN_VALUE);
197.71 - }
197.72 -
197.73 - @Compare public short multiplyMaxShort() {
197.74 - return mul(Short.MAX_VALUE, (short)2);
197.75 - }
197.76 -
197.77 - @Compare public short multiplyMaxShortAndMaxShort() {
197.78 - return mul(Short.MAX_VALUE, Short.MAX_VALUE);
197.79 - }
197.80 -
197.81 - @Compare public short multiplyMinShort() {
197.82 - return mul(Short.MIN_VALUE, (short)2);
197.83 - }
197.84 -
197.85 - @Compare public short multiplyMinShortAndMinShort() {
197.86 - return mul(Short.MIN_VALUE, Short.MIN_VALUE);
197.87 - }
197.88 -
197.89 - @Compare public short multiplyPrecision() {
197.90 - return mul((short)17638, (short)1103);
197.91 - }
197.92 -
197.93 - @Compare public short division() {
197.94 - return div((short)1, (short)2);
197.95 - }
197.96 -
197.97 - @Compare public short divisionReminder() {
197.98 - return mod((short)1, (short)2);
197.99 - }
197.100 -
197.101 - @Factory
197.102 - public static Object[] create() {
197.103 - return VMTest.create(ShortArithmeticTest.class);
197.104 - }
197.105 -}
198.1 --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/StaticUse.java Tue Apr 02 15:40:51 2013 +0200
198.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
198.3 @@ -1,38 +0,0 @@
198.4 -/**
198.5 - * Back 2 Browser Bytecode Translator
198.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
198.7 - *
198.8 - * This program is free software: you can redistribute it and/or modify
198.9 - * it under the terms of the GNU General Public License as published by
198.10 - * the Free Software Foundation, version 2 of the License.
198.11 - *
198.12 - * This program is distributed in the hope that it will be useful,
198.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
198.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
198.15 - * GNU General Public License for more details.
198.16 - *
198.17 - * You should have received a copy of the GNU General Public License
198.18 - * along with this program. Look for COPYING file in the top folder.
198.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
198.20 - */
198.21 -package org.apidesign.bck2brwsr.tck;
198.22 -
198.23 -class StaticUse {
198.24 - public static final Object NON_NULL = new Object();
198.25 - public static int cnt;
198.26 - static {
198.27 - if (cnt++ != 0) {
198.28 - throw new IllegalStateException("Multiple initialization of a <cinit>");
198.29 - }
198.30 - }
198.31 -
198.32 - StaticUse() {
198.33 - }
198.34 -
198.35 - public void instanceMethod() {
198.36 - }
198.37 -
198.38 - public static int plus(int a, int b) {
198.39 - return a + b;
198.40 - }
198.41 -}
199.1 --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/StaticUseSub.java Tue Apr 02 15:40:51 2013 +0200
199.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
199.3 @@ -1,27 +0,0 @@
199.4 -/**
199.5 - * Back 2 Browser Bytecode Translator
199.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
199.7 - *
199.8 - * This program is free software: you can redistribute it and/or modify
199.9 - * it under the terms of the GNU General Public License as published by
199.10 - * the Free Software Foundation, version 2 of the License.
199.11 - *
199.12 - * This program is distributed in the hope that it will be useful,
199.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
199.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
199.15 - * GNU General Public License for more details.
199.16 - *
199.17 - * You should have received a copy of the GNU General Public License
199.18 - * along with this program. Look for COPYING file in the top folder.
199.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
199.20 - */
199.21 -package org.apidesign.bck2brwsr.tck;
199.22 -
199.23 -public class StaticUseSub extends StaticUse {
199.24 - private StaticUseSub() {
199.25 - }
199.26 -
199.27 - public static Object getNonNull() {
199.28 - return NON_NULL;
199.29 - }
199.30 -}
200.1 --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/StaticUseSubTest.java Tue Apr 02 15:40:51 2013 +0200
200.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
200.3 @@ -1,37 +0,0 @@
200.4 -/**
200.5 - * Back 2 Browser Bytecode Translator
200.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
200.7 - *
200.8 - * This program is free software: you can redistribute it and/or modify
200.9 - * it under the terms of the GNU General Public License as published by
200.10 - * the Free Software Foundation, version 2 of the License.
200.11 - *
200.12 - * This program is distributed in the hope that it will be useful,
200.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
200.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
200.15 - * GNU General Public License for more details.
200.16 - *
200.17 - * You should have received a copy of the GNU General Public License
200.18 - * along with this program. Look for COPYING file in the top folder.
200.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
200.20 - */
200.21 -package org.apidesign.bck2brwsr.tck;
200.22 -
200.23 -import org.apidesign.bck2brwsr.vmtest.Compare;
200.24 -import org.apidesign.bck2brwsr.vmtest.VMTest;
200.25 -import org.testng.annotations.Factory;
200.26 -
200.27 -/**
200.28 - *
200.29 - * @author Jaroslav Tulach <jtulach@netbeans.org>
200.30 - */
200.31 -public class StaticUseSubTest {
200.32 - @Compare public String staticFieldInitializationInSuperClass() throws Exception {
200.33 - Object ret = StaticUseSub.getNonNull();
200.34 - return ret.getClass().getName();
200.35 - }
200.36 -
200.37 - @Factory public static Object[] create() {
200.38 - return VMTest.create(StaticUseSubTest.class);
200.39 - }
200.40 -}
201.1 --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/CRC32Test.java Tue Apr 02 15:40:51 2013 +0200
201.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
201.3 @@ -1,41 +0,0 @@
201.4 -/**
201.5 - * Back 2 Browser Bytecode Translator
201.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
201.7 - *
201.8 - * This program is free software: you can redistribute it and/or modify
201.9 - * it under the terms of the GNU General Public License as published by
201.10 - * the Free Software Foundation, version 2 of the License.
201.11 - *
201.12 - * This program is distributed in the hope that it will be useful,
201.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
201.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
201.15 - * GNU General Public License for more details.
201.16 - *
201.17 - * You should have received a copy of the GNU General Public License
201.18 - * along with this program. Look for COPYING file in the top folder.
201.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
201.20 - */
201.21 -package org.apidesign.bck2brwsr.vmtest.impl;
201.22 -
201.23 -import java.io.UnsupportedEncodingException;
201.24 -import java.util.zip.CRC32;
201.25 -import org.apidesign.bck2brwsr.vmtest.Compare;
201.26 -import org.apidesign.bck2brwsr.vmtest.VMTest;
201.27 -import org.testng.annotations.Factory;
201.28 -
201.29 -/**
201.30 - *
201.31 - * @author Jaroslav Tulach <jtulach@netbeans.org>
201.32 - */
201.33 -public class CRC32Test {
201.34 -
201.35 - @Compare public long crc1() throws UnsupportedEncodingException {
201.36 - CRC32 crc = new CRC32();
201.37 - crc.update("Hello World!".getBytes("UTF-8"));
201.38 - return crc.getValue();
201.39 - }
201.40 -
201.41 - @Factory public static Object[] create() {
201.42 - return VMTest.create(CRC32Test.class);
201.43 - }
201.44 -}
202.1 --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/ZipEntryTest.java Tue Apr 02 15:40:51 2013 +0200
202.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
202.3 @@ -1,67 +0,0 @@
202.4 -/**
202.5 - * Back 2 Browser Bytecode Translator
202.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
202.7 - *
202.8 - * This program is free software: you can redistribute it and/or modify
202.9 - * it under the terms of the GNU General Public License as published by
202.10 - * the Free Software Foundation, version 2 of the License.
202.11 - *
202.12 - * This program is distributed in the hope that it will be useful,
202.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
202.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
202.15 - * GNU General Public License for more details.
202.16 - *
202.17 - * You should have received a copy of the GNU General Public License
202.18 - * along with this program. Look for COPYING file in the top folder.
202.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
202.20 - */
202.21 -package org.apidesign.bck2brwsr.vmtest.impl;
202.22 -
202.23 -import java.io.ByteArrayInputStream;
202.24 -import java.io.IOException;
202.25 -import java.io.InputStream;
202.26 -import org.apidesign.bck2brwsr.emul.zip.FastJar;
202.27 -import org.testng.annotations.Test;
202.28 -import static org.testng.Assert.*;
202.29 -
202.30 -/**
202.31 - *
202.32 - * @author Jaroslav Tulach <jtulach@netbeans.org>
202.33 - */
202.34 -@GenerateZip(name = "five.zip", contents = {
202.35 - "1.txt", "one",
202.36 - "2.txt", "duo",
202.37 - "3.txt", "three",
202.38 - "4.txt", "four",
202.39 - "5.txt", "five"
202.40 -})
202.41 -public class ZipEntryTest {
202.42 - @Test
202.43 - public void readEntriesEffectively() throws IOException {
202.44 - InputStream is = ZipEntryTest.class.getResourceAsStream("five.zip");
202.45 - byte[] arr = new byte[is.available()];
202.46 - int len = is.read(arr);
202.47 - assertEquals(len, arr.length, "Read fully");
202.48 -
202.49 - FastJar fj = new FastJar(arr);
202.50 - FastJar.Entry[] entrs = fj.list();
202.51 -
202.52 - assertEquals(5, entrs.length, "Five entries");
202.53 -
202.54 - for (int i = 1; i <= 5; i++) {
202.55 - FastJar.Entry en = entrs[i - 1];
202.56 - assertEquals(en.name, i + ".txt");
202.57 -// assertEquals(cis.cnt, 0, "Content of the file should be skipped, not read");
202.58 - }
202.59 -
202.60 - assertContent("three", fj.getInputStream(entrs[3 - 1]), "read OK");
202.61 - assertContent("five", fj.getInputStream(entrs[5 - 1]), "read OK");
202.62 - }
202.63 -
202.64 - private static void assertContent(String exp, InputStream is, String msg) throws IOException {
202.65 - byte[] arr = new byte[512];
202.66 - int len = is.read(arr);
202.67 - String s = new String(arr, 0, len);
202.68 - assertEquals(exp, s, msg);
202.69 - }
202.70 -}
203.1 --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/ZipFileTest.java Tue Apr 02 15:40:51 2013 +0200
203.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
203.3 @@ -1,108 +0,0 @@
203.4 -/**
203.5 - * Back 2 Browser Bytecode Translator
203.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
203.7 - *
203.8 - * This program is free software: you can redistribute it and/or modify
203.9 - * it under the terms of the GNU General Public License as published by
203.10 - * the Free Software Foundation, version 2 of the License.
203.11 - *
203.12 - * This program is distributed in the hope that it will be useful,
203.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
203.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
203.15 - * GNU General Public License for more details.
203.16 - *
203.17 - * You should have received a copy of the GNU General Public License
203.18 - * along with this program. Look for COPYING file in the top folder.
203.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
203.20 - */
203.21 -package org.apidesign.bck2brwsr.vmtest.impl;
203.22 -
203.23 -import java.io.IOException;
203.24 -import java.io.InputStream;
203.25 -import java.util.Objects;
203.26 -import java.util.zip.ZipEntry;
203.27 -import java.util.zip.ZipInputStream;
203.28 -import org.apidesign.bck2brwsr.core.JavaScriptBody;
203.29 -import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
203.30 -import org.apidesign.bck2brwsr.vmtest.Compare;
203.31 -import org.apidesign.bck2brwsr.vmtest.Http;
203.32 -import org.apidesign.bck2brwsr.vmtest.VMTest;
203.33 -import org.testng.annotations.Factory;
203.34 -
203.35 -/**
203.36 - *
203.37 - * @author Jaroslav Tulach <jtulach@netbeans.org>
203.38 - */
203.39 -@GenerateZip(name = "readAnEntry.zip", contents = {
203.40 - "my/main/file.txt", "Hello World!"
203.41 -})
203.42 -public class ZipFileTest {
203.43 -
203.44 - @Compare public String readAnEntry() throws IOException {
203.45 - InputStream is = ZipFileTest.class.getResourceAsStream("readAnEntry.zip");
203.46 - ZipInputStream zip = new ZipInputStream(is);
203.47 - ZipEntry entry = zip.getNextEntry();
203.48 - assertEquals(entry.getName(), "my/main/file.txt", "Correct entry");
203.49 -
203.50 - byte[] arr = new byte[4096];
203.51 - int len = zip.read(arr);
203.52 -
203.53 - assertEquals(zip.getNextEntry(), null, "No next entry");
203.54 -
203.55 - final String ret = new String(arr, 0, len, "UTF-8");
203.56 - return ret;
203.57 - }
203.58 -
203.59 - @JavaScriptBody(args = { "res", "path" }, body =
203.60 - "var myvm = bck2brwsr.apply(null, path);\n"
203.61 - + "var cls = myvm.loadClass('java.lang.String');\n"
203.62 - + "return cls.getClass__Ljava_lang_Class_2().getResourceAsStream__Ljava_io_InputStream_2Ljava_lang_String_2(res);\n"
203.63 - )
203.64 - private static native Object loadVMResource(String res, String...path);
203.65 -
203.66 - @Http({
203.67 - @Http.Resource(path = "/readAnEntry.jar", mimeType = "x-application/zip", content = "", resource="readAnEntry.zip")
203.68 - })
203.69 - @BrwsrTest public void canVmLoadResourceFromZip() throws IOException {
203.70 - Object res = loadVMResource("/my/main/file.txt", "/readAnEntry.jar");
203.71 - assert res instanceof InputStream : "Got array of bytes: " + res;
203.72 - InputStream is = (InputStream)res;
203.73 -
203.74 - byte[] arr = new byte[4096];
203.75 - int len = is.read(arr);
203.76 -
203.77 - final String ret = new String(arr, 0, len, "UTF-8");
203.78 -
203.79 - assertEquals(ret, "Hello World!", "Can read the bytes");
203.80 - }
203.81 -
203.82 - @GenerateZip(name = "cpattr.zip", contents = {
203.83 - "META-INF/MANIFEST.MF", "Manifest-Version: 1.0\n"
203.84 - + "Created-By: hand\n"
203.85 - + "Class-Path: realJar.jar\n\n\n"
203.86 - })
203.87 - @Http({
203.88 - @Http.Resource(path = "/readComplexEntry.jar", mimeType = "x-application/zip", content = "", resource="cpattr.zip"),
203.89 - @Http.Resource(path = "/realJar.jar", mimeType = "x-application/zip", content = "", resource="readAnEntry.zip"),
203.90 - })
203.91 - @BrwsrTest public void understandsClassPathAttr() throws IOException {
203.92 - Object res = loadVMResource("/my/main/file.txt", "/readComplexEntry.jar");
203.93 - assert res instanceof InputStream : "Got array of bytes: " + res;
203.94 - InputStream is = (InputStream)res;
203.95 -
203.96 - byte[] arr = new byte[4096];
203.97 - int len = is.read(arr);
203.98 -
203.99 - final String ret = new String(arr, 0, len, "UTF-8");
203.100 -
203.101 - assertEquals(ret, "Hello World!", "Can read the bytes from secondary JAR");
203.102 - }
203.103 -
203.104 - private static void assertEquals(Object real, Object exp, String msg) {
203.105 - assert Objects.equals(exp, real) : msg + " exp: " + exp + " real: " + real;
203.106 - }
203.107 -
203.108 - @Factory public static Object[] create() {
203.109 - return VMTest.create(ZipFileTest.class);
203.110 - }
203.111 -}
204.1 --- a/rt/vmtest/src/test/resources/org/apidesign/bck2brwsr/tck/0xfe Tue Apr 02 15:40:51 2013 +0200
204.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
204.3 @@ -1,1 +0,0 @@
204.4 -þ
204.5 \ No newline at end of file
205.1 --- a/rt/vmtest/src/test/resources/org/apidesign/bck2brwsr/tck/Resources.txt Tue Apr 02 15:40:51 2013 +0200
205.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
205.3 @@ -1,1 +0,0 @@
205.4 -Ahoj