Merging with latest state - e.g. 0.7 version elements
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Thu, 02 May 2013 09:18:22 +0200
branchelements
changeset 10723800d11c0bdb
parent 913 146ae7b52b64
parent 1071 2894b9a9dbfc
child 1073 9321b4016d5c
Merging with latest state - e.g. 0.7 version
javaquery/api/pom.xml
javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/Attributes.java
javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/ElementGenerator.java
javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/PredefinedFields.java
javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/Compile.java
javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/ElementGeneratorTest.java
pom.xml
rt/emul/compact/src/test/resources/org/apidesign/bck2brwsr/compact/tck/demo.static.calculator-0.3-SNAPSHOT.jar
rt/launcher/pom.xml
rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java
rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/InvocationContext.java
rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/JSLauncher.java
rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Launcher.java
rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/impl/Console.java
rt/launcher/src/main/resources/org/apidesign/bck2brwsr/launcher/harness.xhtml
rt/mojo/src/main/java/org/apidesign/bck2brwsr/mojo/BrswrMojo.java
rt/mojo/src/main/resources/META-INF/maven/archetype-metadata.xml
rt/mojo/src/main/resources/archetype-resources/bck2brwsr-assembly.xml
rt/mojo/src/main/resources/archetype-resources/nbactions.xml
rt/mojo/src/main/resources/archetype-resources/pom.xml
rt/mojo/src/main/resources/archetype-resources/src/main/java/App.java
rt/mojo/src/main/resources/archetype-resources/src/main/resources/index.html
rt/mojo/src/main/resources/archetype-resources/src/test/java/AppTest.java
rt/mojo/src/main/resources/archetype-resources/src/test/java/InconsistencyTest.java
rt/mojo/src/main/resources/archetype-resources/src/test/java/IntegrationTest.java
rt/mojo/src/test/java/org/apidesign/bck2brwsr/mojo/ArchetypeVersionTest.java
rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/AssertionTest.java
rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/BrwsrCheckTest.java
rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ByteArithmeticTest.java
rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CloneTest.java
rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareByteArrayTest.java
rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareHashTest.java
rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareIntArrayTest.java
rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareStringsTest.java
rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/DoubleTest.java
rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/HttpResourceTest.java
rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/InheritanceA.java
rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/InheritanceB.java
rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/InheritanceTest.java
rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/IntegerArithmeticTest.java
rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/LongArithmeticTest.java
rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ReflectionArrayTest.java
rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ReflectionTest.java
rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ResourcesTest.java
rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ShortArithmeticTest.java
rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/StaticUse.java
rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/StaticUseSub.java
rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/StaticUseSubTest.java
rt/vmtest/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/CRC32Test.java
rt/vmtest/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/ZipEntryTest.java
rt/vmtest/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/ZipFileTest.java
rt/vmtest/src/test/resources/org/apidesign/bck2brwsr/tck/0xfe
rt/vmtest/src/test/resources/org/apidesign/bck2brwsr/tck/Resources.txt
     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"> &amp; </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">&lt;jaroslav.tulach@apidesign.org&gt;</span>
   43.39 -     <span class="comment">*/</span>
   43.40 -    @Page(xhtml=<span class="string">&quot;</span><span class="string">Calculator.xhtml</span><span class="string">&quot;</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">&quot;</span><span class="string">clear</span><span class="string">&quot;</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">&quot;</span><span class="string">0</span><span class="string">&quot;</span>);
   43.50 -        }
   43.51 -
   43.52 -        @OnClick(id= { <span class="string">&quot;</span><span class="string">plus</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">minus</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">mul</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">div</span><span class="string">&quot;</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">&quot;</span><span class="string">0</span><span class="string">&quot;</span>);
   43.57 -        }
   43.58 -
   43.59 -        @OnClick(id=<span class="string">&quot;</span><span class="string">result</span><span class="string">&quot;</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">&quot;</span><span class="string">plus</span><span class="string">&quot;</span>: setValue(memory + getValue()); <span class="keyword-directive">break</span>;
   43.63 -                <span class="keyword-directive">case</span> <span class="string">&quot;</span><span class="string">minus</span><span class="string">&quot;</span>: setValue(memory - getValue()); <span class="keyword-directive">break</span>;
   43.64 -                <span class="keyword-directive">case</span> <span class="string">&quot;</span><span class="string">mul</span><span class="string">&quot;</span>: setValue(memory * getValue()); <span class="keyword-directive">break</span>;
   43.65 -                <span class="keyword-directive">case</span> <span class="string">&quot;</span><span class="string">div</span><span class="string">&quot;</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">&quot;</span><span class="string">n0</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">n1</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">n2</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">n3</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">n4</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">n5</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">n6</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">n7</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">n8</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">n9</span><span class="string">&quot;</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">&quot;</span><span class="string">err</span><span class="string">&quot;</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\":\"&lt;a href=&quot;http:\\/\\/twitter.com\\/&quot;&gt;web&lt;\\/a&gt;\",\"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\":\"&lt;a href=&quot;http:\\/\\/twitter.com\\/&quot;&gt;web&lt;\\/a&gt;\",\"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\":\"&lt;a href=&quot;http:\\/\\/twitter.com\\/&quot;&gt;web&lt;\\/a&gt;\",\"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\":\"&lt;a href=&quot;http:\\/\\/twitter.com\\/&quot;&gt;web&lt;\\/a&gt;\",\"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