Merging launcher branch to default - seems to work reliably well
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Mon, 24 Dec 2012 07:57:33 +0100
changeset 374e5b4bd29f268
parent 373 52386a70f9d9
parent 372 3485327d3080
child 375 5751fe604e6b
Merging launcher branch to default - seems to work reliably well
emul/src/main/java/java/net/URL.java
javaquery/demo-static-calculator/nbactions.xml
javaquery/demo-static-calculator/pom.xml
javaquery/demo-static-calculator/src/main/resources/org/apidesign/bck2brwsr/mavenhtml/Calculator.xhtml
vm/src/test/java/org/apidesign/vm4brwsr/Compare.java
vm/src/test/java/org/apidesign/vm4brwsr/CompareVMs.java
vm/src/test/java/org/apidesign/vm4brwsr/tck/CompareHashTest.java
vm/src/test/java/org/apidesign/vm4brwsr/tck/CompareStringsTest.java
     1.1 --- a/emul/src/main/java/java/lang/Class.java	Mon Dec 24 07:51:15 2012 +0100
     1.2 +++ b/emul/src/main/java/java/lang/Class.java	Mon Dec 24 07:57:33 2012 +0100
     1.3 @@ -287,7 +287,12 @@
     1.4       * @return  {@code true} if this object represents an interface;
     1.5       *          {@code false} otherwise.
     1.6       */
     1.7 -    public native boolean isInterface();
     1.8 +    public boolean isInterface() {
     1.9 +        return (getAccess() & 0x200) != 0;
    1.10 +    }
    1.11 +    
    1.12 +    @JavaScriptBody(args = "self", body = "return self.access;")
    1.13 +    private native int getAccess();
    1.14  
    1.15  
    1.16      /**
    1.17 @@ -330,6 +335,10 @@
    1.18       * @see     java.lang.Void#TYPE
    1.19       * @since JDK1.1
    1.20       */
    1.21 +    @JavaScriptBody(args = "self", body = 
    1.22 +           "if (self.primitive) return true;"
    1.23 +        + "else return false;"
    1.24 +    )
    1.25      public native boolean isPrimitive();
    1.26  
    1.27      /**
    1.28 @@ -1090,10 +1099,13 @@
    1.29          throw new UnsupportedOperationException();
    1.30      }
    1.31  
    1.32 -    static Class getPrimitiveClass(String type) {
    1.33 -        // XXX
    1.34 -        return Object.class;
    1.35 -    }
    1.36 +    @JavaScriptBody(args = "type", body = ""
    1.37 +        + "var c = vm.java_lang_Class(true);"
    1.38 +        + "c.jvmName = type;"
    1.39 +        + "c.primitive = true;"
    1.40 +        + "return c;"
    1.41 +    )
    1.42 +    native static Class getPrimitiveClass(String type);
    1.43  
    1.44      public boolean desiredAssertionStatus() {
    1.45          return false;
     2.1 --- a/emul/src/main/java/java/lang/reflect/Method.java	Mon Dec 24 07:51:15 2012 +0100
     2.2 +++ b/emul/src/main/java/java/lang/reflect/Method.java	Mon Dec 24 07:57:33 2012 +0100
     2.3 @@ -137,7 +137,24 @@
     2.4       * @return the return type for the method this object represents
     2.5       */
     2.6      public Class<?> getReturnType() {
     2.7 -        throw new UnsupportedOperationException();
     2.8 +        switch (sig.charAt(0)) {
     2.9 +            case 'I': return Integer.TYPE;
    2.10 +            case 'J': return Long.TYPE;
    2.11 +            case 'D': return Double.TYPE;
    2.12 +            case 'F': return Float.TYPE;
    2.13 +            case 'B': return Byte.TYPE;
    2.14 +            case 'Z': return Boolean.TYPE;
    2.15 +            case 'S': return Short.TYPE;
    2.16 +//            case 'V': return Void.TYPE;
    2.17 +            case 'L': try {
    2.18 +                int up = sig.indexOf("_2");
    2.19 +                String type = sig.substring(1, up);
    2.20 +                return Class.forName(type);
    2.21 +            } catch (ClassNotFoundException ex) {
    2.22 +                // should not happen
    2.23 +            }
    2.24 +        }
    2.25 +        throw new UnsupportedOperationException(sig);
    2.26      }
    2.27  
    2.28      /**
    2.29 @@ -488,17 +505,54 @@
    2.30       * @exception ExceptionInInitializerError if the initialization
    2.31       * provoked by this method fails.
    2.32       */
    2.33 +    public Object invoke(Object obj, Object... args)
    2.34 +        throws IllegalAccessException, IllegalArgumentException,
    2.35 +           InvocationTargetException
    2.36 +    {
    2.37 +        Object res = invoke0(this, obj, args);
    2.38 +        if (getReturnType().isPrimitive()) {
    2.39 +            res = fromPrimitive(getReturnType(), res);
    2.40 +        }
    2.41 +        return res;
    2.42 +    }
    2.43 +    
    2.44      @JavaScriptBody(args = { "method", "self", "args" }, body =
    2.45            "if (args.length > 0) throw 'unsupported now';"
    2.46          + "return method.fld_data(self);"
    2.47      )
    2.48 -    public Object invoke(Object obj, Object... args)
    2.49 -        throws IllegalAccessException, IllegalArgumentException,
    2.50 -           InvocationTargetException
    2.51 -    {
    2.52 -        throw new UnsupportedOperationException();
    2.53 +    private static native Object invoke0(Method m, Object self, Object[] args);
    2.54 +
    2.55 +    private static Object fromPrimitive(Class<?> type, Object o) {
    2.56 +        if (type == Integer.TYPE) {
    2.57 +            return fromRaw(Integer.class, "valueOf__Ljava_lang_Integer_2I", o);
    2.58 +        }
    2.59 +        if (type == Long.TYPE) {
    2.60 +            return fromRaw(Long.class, "valueOf__Ljava_lang_Long_2J", o);
    2.61 +        }
    2.62 +        if (type == Double.TYPE) {
    2.63 +            return fromRaw(Double.class, "valueOf__Ljava_lang_Double_2D", o);
    2.64 +        }
    2.65 +        if (type == Float.TYPE) {
    2.66 +            return fromRaw(Float.class, "valueOf__Ljava_lang_Float_2F", o);
    2.67 +        }
    2.68 +        if (type == Byte.TYPE) {
    2.69 +            return fromRaw(Byte.class, "valueOf__Ljava_lang_Byte_2B", o);
    2.70 +        }
    2.71 +        if (type == Boolean.TYPE) {
    2.72 +            return fromRaw(Boolean.class, "valueOf__Ljava_lang_Boolean_2Z", o);
    2.73 +        }
    2.74 +        if (type == Short.TYPE) {
    2.75 +            return fromRaw(Short.class, "valueOf__Ljava_lang_Short_2S", o);
    2.76 +        }
    2.77 +//            case 'V': return Void.TYPE;
    2.78 +        throw new IllegalStateException("Can't convert " + o);
    2.79      }
    2.80 -
    2.81 +    
    2.82 +    @JavaScriptBody(args = { "cls", "m", "o" }, 
    2.83 +        body = "return cls.cnstr(false)[m](o);"
    2.84 +    )
    2.85 +    private static native Integer fromRaw(Class<?> cls, String m, Object o);
    2.86 +    
    2.87      /**
    2.88       * Returns {@code true} if this method is a bridge
    2.89       * method; returns {@code false} otherwise.
     3.1 --- a/emul/src/main/java/java/net/URL.java	Mon Dec 24 07:51:15 2012 +0100
     3.2 +++ b/emul/src/main/java/java/net/URL.java	Mon Dec 24 07:57:33 2012 +0100
     3.3 @@ -27,6 +27,7 @@
     3.4  
     3.5  import java.io.IOException;
     3.6  import java.io.InputStream;
     3.7 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
     3.8  
     3.9  /**
    3.10   * Class <code>URL</code> represents a Uniform Resource
    3.11 @@ -964,9 +965,16 @@
    3.12       * @see        java.net.URLConnection#getContent()
    3.13       */
    3.14      public final Object getContent() throws java.io.IOException {
    3.15 -        throw new IOException();
    3.16 -//        return openConnection().getContent();
    3.17 +        return loadText(toExternalForm());
    3.18      }
    3.19 +    
    3.20 +    @JavaScriptBody(args = "url", body = ""
    3.21 +        + "var request = new XMLHttpRequest();\n"
    3.22 +        + "request.open('GET', url, false);\n"
    3.23 +        + "request.send();\n"
    3.24 +        + "return request.responseText;\n"
    3.25 +    )
    3.26 +    private static native String loadText(String url) throws IOException;
    3.27  
    3.28      /**
    3.29       * Gets the contents of this URL. This method is a shorthand for:
    3.30 @@ -984,8 +992,12 @@
    3.31       */
    3.32      public final Object getContent(Class[] classes)
    3.33      throws java.io.IOException {
    3.34 -        throw new IOException();
    3.35 -//        return openConnection().getContent(classes);
    3.36 +        for (Class<?> c : classes) {
    3.37 +            if (c == String.class) {
    3.38 +                return getContent();
    3.39 +            }
    3.40 +        }
    3.41 +        return null;
    3.42      }
    3.43  
    3.44      static URLStreamHandler getURLStreamHandler(String protocol) {
     4.1 --- a/javap/src/main/java/org/apidesign/javap/ClassData.java	Mon Dec 24 07:51:15 2012 +0100
     4.2 +++ b/javap/src/main/java/org/apidesign/javap/ClassData.java	Mon Dec 24 07:57:33 2012 +0100
     4.3 @@ -326,6 +326,10 @@
     4.4              return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
     4.5          }
     4.6      }
     4.7 +    
     4.8 +    public int getAccessFlags() {
     4.9 +        return access;
    4.10 +    }
    4.11  
    4.12      /**
    4.13       * Returns true if it is a class
     5.1 --- a/javaquery/demo-calculator/nbactions.xml	Mon Dec 24 07:51:15 2012 +0100
     5.2 +++ b/javaquery/demo-calculator/nbactions.xml	Mon Dec 24 07:57:33 2012 +0100
     5.3 @@ -23,7 +23,7 @@
     5.4              <actionName>run</actionName>
     5.5              <goals>
     5.6                  <goal>process-classes</goal>
     5.7 -                <goal>org.codehaus.mojo:exec-maven-plugin:1.2.1:exec</goal>
     5.8 +                <goal>org.apidesign.bck2brwsr:mojo:0.3-SNAPSHOT:brwsr</goal>
     5.9              </goals>
    5.10          </action>
    5.11      </actions>
     6.1 --- a/javaquery/demo-calculator/pom.xml	Mon Dec 24 07:51:15 2012 +0100
     6.2 +++ b/javaquery/demo-calculator/pom.xml	Mon Dec 24 07:57:33 2012 +0100
     6.3 @@ -16,34 +16,19 @@
     6.4    </properties>
     6.5    <build>
     6.6        <plugins>
     6.7 -          <plugin>
     6.8 -              <groupId>org.apidesign.bck2brwsr</groupId>
     6.9 -              <artifactId>mojo</artifactId>
    6.10 -              <version>0.3-SNAPSHOT</version>
    6.11 -              <executions>
    6.12 -                  <execution>
    6.13 -                      <goals>
    6.14 -                          <goal>j2js</goal>
    6.15 -                      </goals>
    6.16 -                  </execution>
    6.17 -              </executions>
    6.18 -          </plugin>
    6.19              <plugin>
    6.20 -                <groupId>org.codehaus.mojo</groupId>
    6.21 -                <artifactId>exec-maven-plugin</artifactId>
    6.22 -                <version>1.2.1</version>
    6.23 +                <groupId>org.apidesign.bck2brwsr</groupId>
    6.24 +                <artifactId>mojo</artifactId>
    6.25 +                <version>0.3-SNAPSHOT</version>
    6.26                  <executions>
    6.27                      <execution>
    6.28                          <goals>
    6.29 -                            <goal>exec</goal>
    6.30 +                            <goal>brwsr</goal>
    6.31                          </goals>
    6.32                      </execution>
    6.33                  </executions>
    6.34                  <configuration>
    6.35 -                    <executable>xdg-open</executable>
    6.36 -                    <arguments>
    6.37 -                        <argument>${project.build.directory}/classes/org/apidesign/bck2brwsr/mavenhtml/Calculator.xhtml</argument>
    6.38 -                    </arguments>
    6.39 +                    <startpage>org/apidesign/bck2brwsr/mavenhtml/Calculator.xhtml</startpage>
    6.40                  </configuration>
    6.41              </plugin>
    6.42           <plugin>
     7.1 --- a/javaquery/demo-calculator/src/main/resources/org/apidesign/bck2brwsr/mavenhtml/Calculator.xhtml	Mon Dec 24 07:51:15 2012 +0100
     7.2 +++ b/javaquery/demo-calculator/src/main/resources/org/apidesign/bck2brwsr/mavenhtml/Calculator.xhtml	Mon Dec 24 07:57:33 2012 +0100
     7.3 @@ -77,7 +77,11 @@
     7.4              </tbody>
     7.5          </table>
     7.6  
     7.7 -        <script src="bootjava.js"/>
     7.8 +        <script src="/bck2brwsr.js"></script>
     7.9 +        <script src="/vm.js"></script>
    7.10 +        <script type="text/javascript">
    7.11 +            vm.loadClass('org.apidesign.bck2brwsr.mavenhtml.Calculator');
    7.12 +        </script>
    7.13          
    7.14          <hr/>
    7.15      <pre>
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/launcher/pom.xml	Mon Dec 24 07:57:33 2012 +0100
     8.3 @@ -0,0 +1,49 @@
     8.4 +<?xml version="1.0"?>
     8.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"
     8.6 +    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
     8.7 +  <modelVersion>4.0.0</modelVersion>
     8.8 +  <parent>
     8.9 +    <groupId>org.apidesign</groupId>
    8.10 +    <artifactId>bck2brwsr</artifactId>
    8.11 +    <version>0.3-SNAPSHOT</version>
    8.12 +  </parent>
    8.13 +  <groupId>org.apidesign.bck2brwsr</groupId>
    8.14 +  <artifactId>launcher</artifactId>
    8.15 +  <version>0.3-SNAPSHOT</version>
    8.16 +  <name>Bck2Brwsr Launcher</name>
    8.17 +  <url>http://maven.apache.org</url>
    8.18 +    <build>
    8.19 +        <plugins>
    8.20 +            <plugin>
    8.21 +                <groupId>org.apache.maven.plugins</groupId>
    8.22 +                <artifactId>maven-compiler-plugin</artifactId>
    8.23 +                <version>2.3.2</version>
    8.24 +                <configuration>
    8.25 +                    <source>1.7</source>
    8.26 +                    <target>1.7</target>
    8.27 +                </configuration>
    8.28 +            </plugin>
    8.29 +        </plugins>
    8.30 +    </build>
    8.31 +    <properties>
    8.32 +    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    8.33 +  </properties>
    8.34 +  <dependencies>
    8.35 +    <dependency>
    8.36 +      <groupId>junit</groupId>
    8.37 +      <artifactId>junit</artifactId>
    8.38 +      <version>3.8.1</version>
    8.39 +      <scope>test</scope>
    8.40 +    </dependency>
    8.41 +    <dependency>
    8.42 +      <groupId>org.glassfish.grizzly</groupId>
    8.43 +      <artifactId>grizzly-http-server</artifactId>
    8.44 +      <version>2.2.19</version>
    8.45 +    </dependency>
    8.46 +    <dependency>
    8.47 +      <groupId>${project.groupId}</groupId>
    8.48 +      <artifactId>vm4brwsr</artifactId>
    8.49 +      <version>${project.version}</version>
    8.50 +    </dependency>
    8.51 +  </dependencies>
    8.52 +</project>
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java	Mon Dec 24 07:57:33 2012 +0100
     9.3 @@ -0,0 +1,422 @@
     9.4 +/**
     9.5 + * Back 2 Browser Bytecode Translator
     9.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     9.7 + *
     9.8 + * This program is free software: you can redistribute it and/or modify
     9.9 + * it under the terms of the GNU General Public License as published by
    9.10 + * the Free Software Foundation, version 2 of the License.
    9.11 + *
    9.12 + * This program is distributed in the hope that it will be useful,
    9.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    9.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    9.15 + * GNU General Public License for more details.
    9.16 + *
    9.17 + * You should have received a copy of the GNU General Public License
    9.18 + * along with this program. Look for COPYING file in the top folder.
    9.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
    9.20 + */
    9.21 +package org.apidesign.bck2brwsr.launcher;
    9.22 +
    9.23 +import java.io.File;
    9.24 +import java.io.IOException;
    9.25 +import java.io.InputStream;
    9.26 +import java.io.InterruptedIOException;
    9.27 +import java.io.OutputStream;
    9.28 +import java.io.Writer;
    9.29 +import java.net.URI;
    9.30 +import java.net.URISyntaxException;
    9.31 +import java.net.URL;
    9.32 +import java.util.ArrayList;
    9.33 +import java.util.Arrays;
    9.34 +import java.util.Enumeration;
    9.35 +import java.util.LinkedHashSet;
    9.36 +import java.util.List;
    9.37 +import java.util.Set;
    9.38 +import java.util.concurrent.BlockingQueue;
    9.39 +import java.util.concurrent.CountDownLatch;
    9.40 +import java.util.concurrent.LinkedBlockingQueue;
    9.41 +import java.util.concurrent.TimeUnit;
    9.42 +import java.util.logging.Level;
    9.43 +import java.util.logging.Logger;
    9.44 +import org.apidesign.vm4brwsr.Bck2Brwsr;
    9.45 +import org.glassfish.grizzly.PortRange;
    9.46 +import org.glassfish.grizzly.http.server.HttpHandler;
    9.47 +import org.glassfish.grizzly.http.server.HttpServer;
    9.48 +import org.glassfish.grizzly.http.server.NetworkListener;
    9.49 +import org.glassfish.grizzly.http.server.Request;
    9.50 +import org.glassfish.grizzly.http.server.Response;
    9.51 +import org.glassfish.grizzly.http.server.ServerConfiguration;
    9.52 +
    9.53 +/**
    9.54 + * Lightweight server to launch Bck2Brwsr applications and tests.
    9.55 + * Supports execution in native browser as well as Java's internal 
    9.56 + * execution engine.
    9.57 + */
    9.58 +public class Bck2BrwsrLauncher {
    9.59 +    private static final Logger LOG = Logger.getLogger(Bck2BrwsrLauncher.class.getName());
    9.60 +    private static final MethodInvocation END = new MethodInvocation(null, null);
    9.61 +    private Set<ClassLoader> loaders = new LinkedHashSet<>();
    9.62 +    private BlockingQueue<MethodInvocation> methods = new LinkedBlockingQueue<>();
    9.63 +    private long timeOut;
    9.64 +    private final Res resources = new Res();
    9.65 +    private Object[] brwsr;
    9.66 +    private HttpServer server;
    9.67 +    private CountDownLatch wait;
    9.68 +    
    9.69 +    
    9.70 +    public MethodInvocation addMethod(Class<?> clazz, String method) throws IOException {
    9.71 +        loaders.add(clazz.getClassLoader());
    9.72 +        MethodInvocation c = new MethodInvocation(clazz.getName(), method);
    9.73 +        methods.add(c);
    9.74 +        try {
    9.75 +            c.await(timeOut);
    9.76 +        } catch (InterruptedException ex) {
    9.77 +            throw new IOException(ex);
    9.78 +        }
    9.79 +        return c;
    9.80 +    }
    9.81 +    
    9.82 +    public void setTimeout(long ms) {
    9.83 +        timeOut = ms;
    9.84 +    }
    9.85 +    
    9.86 +    public void addClassLoader(ClassLoader url) {
    9.87 +        this.loaders.add(url);
    9.88 +    }
    9.89 +    
    9.90 +    public static void main( String[] args ) throws Exception {
    9.91 +        Bck2BrwsrLauncher l = new Bck2BrwsrLauncher();
    9.92 +        l.addClassLoader(Bck2BrwsrLauncher.class.getClassLoader());
    9.93 +        l.showURL("org/apidesign/bck2brwsr/launcher/console.xhtml");
    9.94 +        System.in.read();
    9.95 +    }
    9.96 +
    9.97 +    public void showURL(String startpage) throws URISyntaxException, InterruptedException, IOException {
    9.98 +        if (!startpage.startsWith("/")) {
    9.99 +            startpage = "/" + startpage;
   9.100 +        }
   9.101 +        HttpServer s = initServer();
   9.102 +        s.getServerConfiguration().addHttpHandler(new Page(resources, null), "/");
   9.103 +        launchServerAndBrwsr(s, startpage);
   9.104 +    }
   9.105 +
   9.106 +    public void initialize() throws IOException {
   9.107 +        try {
   9.108 +            executeInBrowser();
   9.109 +        } catch (InterruptedException ex) {
   9.110 +            final InterruptedIOException iio = new InterruptedIOException(ex.getMessage());
   9.111 +            iio.initCause(ex);
   9.112 +            throw iio;
   9.113 +        } catch (Exception ex) {
   9.114 +            if (ex instanceof IOException) {
   9.115 +                throw (IOException)ex;
   9.116 +            }
   9.117 +            if (ex instanceof RuntimeException) {
   9.118 +                throw (RuntimeException)ex;
   9.119 +            }
   9.120 +            throw new IOException(ex);
   9.121 +        }
   9.122 +    }
   9.123 +    
   9.124 +    private HttpServer initServer() {
   9.125 +        HttpServer s = HttpServer.createSimpleServer(".", new PortRange(8080, 65535));
   9.126 +
   9.127 +        final ServerConfiguration conf = s.getServerConfiguration();
   9.128 +        conf.addHttpHandler(new Page(resources, 
   9.129 +            "org/apidesign/bck2brwsr/launcher/console.xhtml",
   9.130 +            "org.apidesign.bck2brwsr.launcher.Console", "welcome", "false"
   9.131 +        ), "/console");
   9.132 +        conf.addHttpHandler(new VM(resources), "/bck2brwsr.js");
   9.133 +        conf.addHttpHandler(new VMInit(), "/vm.js");
   9.134 +        conf.addHttpHandler(new Classes(resources), "/classes/");
   9.135 +        return s;
   9.136 +    }
   9.137 +    
   9.138 +    private void executeInBrowser() throws InterruptedException, URISyntaxException, IOException {
   9.139 +        wait = new CountDownLatch(1);
   9.140 +        server = initServer();
   9.141 +        ServerConfiguration conf = server.getServerConfiguration();
   9.142 +        conf.addHttpHandler(new Page(resources, 
   9.143 +            "org/apidesign/bck2brwsr/launcher/harness.xhtml"
   9.144 +        ), "/execute");
   9.145 +        conf.addHttpHandler(new HttpHandler() {
   9.146 +            int cnt;
   9.147 +            List<MethodInvocation> cases = new ArrayList<>();
   9.148 +            @Override
   9.149 +            public void service(Request request, Response response) throws Exception {
   9.150 +                String id = request.getParameter("request");
   9.151 +                String value = request.getParameter("result");
   9.152 +                
   9.153 +                if (id != null && value != null) {
   9.154 +                    LOG.log(Level.INFO, "Received result for case {0} = {1}", new Object[]{id, value});
   9.155 +                    value = value.replace("%20", " ");
   9.156 +                    cases.get(Integer.parseInt(id)).result(value, null);
   9.157 +                }
   9.158 +                
   9.159 +                MethodInvocation mi = methods.take();
   9.160 +                if (mi == END) {
   9.161 +                    response.getWriter().write("");
   9.162 +                    wait.countDown();
   9.163 +                    cnt = 0;
   9.164 +                    LOG.log(Level.INFO, "End of data reached. Exiting.");
   9.165 +                    return;
   9.166 +                }
   9.167 +                
   9.168 +                cases.add(mi);
   9.169 +                final String cn = mi.className;
   9.170 +                final String mn = mi.methodName;
   9.171 +                LOG.log(Level.INFO, "Request for {0} case. Sending {1}.{2}", new Object[]{cnt, cn, mn});
   9.172 +                response.getWriter().write("{"
   9.173 +                    + "className: '" + cn + "', "
   9.174 +                    + "methodName: '" + mn + "', "
   9.175 +                    + "request: " + cnt
   9.176 +                    + "}");
   9.177 +                cnt++;
   9.178 +            }
   9.179 +        }, "/data");
   9.180 +
   9.181 +        this.brwsr = launchServerAndBrwsr(server, "/execute");
   9.182 +    }
   9.183 +    
   9.184 +    public void shutdown() throws InterruptedException, IOException {
   9.185 +        methods.offer(END);
   9.186 +        for (;;) {
   9.187 +            int prev = methods.size();
   9.188 +            if (wait.await(timeOut, TimeUnit.MILLISECONDS)) {
   9.189 +                break;
   9.190 +            }
   9.191 +            if (prev == methods.size()) {
   9.192 +                LOG.log(
   9.193 +                    Level.WARNING, 
   9.194 +                    "Timeout and no test has been executed meanwhile (at {0}). Giving up.", 
   9.195 +                    methods.size()
   9.196 +                );
   9.197 +                break;
   9.198 +            }
   9.199 +            LOG.log(Level.INFO, 
   9.200 +                "Timeout, but tests got from {0} to {1}. Trying again.", 
   9.201 +                new Object[]{prev, methods.size()}
   9.202 +            );
   9.203 +        }
   9.204 +        stopServerAndBrwsr(server, brwsr);
   9.205 +    }
   9.206 +    
   9.207 +    static void copyStream(InputStream is, OutputStream os, String baseURL, String... params) throws IOException {
   9.208 +        for (;;) {
   9.209 +            int ch = is.read();
   9.210 +            if (ch == -1) {
   9.211 +                break;
   9.212 +            }
   9.213 +            if (ch == '$') {
   9.214 +                int cnt = is.read() - '0';
   9.215 +                if (cnt == 'U' - '0') {
   9.216 +                    os.write(baseURL.getBytes());
   9.217 +                }
   9.218 +                if (cnt < params.length) {
   9.219 +                    os.write(params[cnt].getBytes());
   9.220 +                }
   9.221 +            } else {
   9.222 +                os.write(ch);
   9.223 +            }
   9.224 +        }
   9.225 +    }
   9.226 +
   9.227 +    private Object[] launchServerAndBrwsr(HttpServer server, final String page) throws IOException, URISyntaxException, InterruptedException {
   9.228 +        server.start();
   9.229 +        NetworkListener listener = server.getListeners().iterator().next();
   9.230 +        int port = listener.getPort();
   9.231 +        
   9.232 +        URI uri = new URI("http://localhost:" + port + page);
   9.233 +        LOG.log(Level.INFO, "Showing {0}", uri);
   9.234 +//        try {
   9.235 +//            Desktop.getDesktop().browse(uri);
   9.236 +//            return null;
   9.237 +//        } catch (UnsupportedOperationException ex)
   9.238 +        {
   9.239 +//            File dir = File.createTempFile("chrome", ".dir");
   9.240 +//            dir.delete();
   9.241 +//            dir.mkdirs();
   9.242 +//            String[] cmd = { 
   9.243 +//                "google-chrome", "--user-data-dir=" + dir, "--app=" + uri.toString()
   9.244 +//            };
   9.245 +//            LOG.log(Level.INFO, "Launching {0}", Arrays.toString(cmd));
   9.246 +//            final Process process = Runtime.getRuntime().exec(cmd);
   9.247 +//            return new Object[] { process, dir };
   9.248 +        }
   9.249 +        {
   9.250 +            String[] cmd = { 
   9.251 +                "xdg-open", uri.toString()
   9.252 +            };
   9.253 +            LOG.log(Level.INFO, "Launching {0}", Arrays.toString(cmd));
   9.254 +            final Process process = Runtime.getRuntime().exec(cmd);
   9.255 +            return new Object[] { process, null };
   9.256 +        }
   9.257 +    }
   9.258 +    
   9.259 +    private void stopServerAndBrwsr(HttpServer server, Object[] brwsr) throws IOException, InterruptedException {
   9.260 +        Process process = (Process)brwsr[0];
   9.261 +        
   9.262 +        server.stop();
   9.263 +        InputStream stdout = process.getInputStream();
   9.264 +        InputStream stderr = process.getErrorStream();
   9.265 +        drain("StdOut", stdout);
   9.266 +        drain("StdErr", stderr);
   9.267 +        process.destroy();
   9.268 +        int res = process.waitFor();
   9.269 +        LOG.log(Level.INFO, "Exit code: {0}", res);
   9.270 +
   9.271 +        deleteTree((File)brwsr[1]);
   9.272 +    }
   9.273 +    
   9.274 +    private static void drain(String name, InputStream is) throws IOException {
   9.275 +        int av = is.available();
   9.276 +        if (av > 0) {
   9.277 +            StringBuilder sb = new StringBuilder();
   9.278 +            sb.append("v== ").append(name).append(" ==v\n");
   9.279 +            while (av-- > 0) {
   9.280 +                sb.append((char)is.read());
   9.281 +            }
   9.282 +            sb.append("\n^== ").append(name).append(" ==^");
   9.283 +            LOG.log(Level.INFO, sb.toString());
   9.284 +        }
   9.285 +    }
   9.286 +
   9.287 +    private void deleteTree(File file) {
   9.288 +        if (file == null) {
   9.289 +            return;
   9.290 +        }
   9.291 +        File[] arr = file.listFiles();
   9.292 +        if (arr != null) {
   9.293 +            for (File s : arr) {
   9.294 +                deleteTree(s);
   9.295 +            }
   9.296 +        }
   9.297 +        file.delete();
   9.298 +    }
   9.299 +
   9.300 +    private class Res implements Bck2Brwsr.Resources {
   9.301 +        @Override
   9.302 +        public InputStream get(String resource) throws IOException {
   9.303 +            for (ClassLoader l : loaders) {
   9.304 +                URL u = null;
   9.305 +                Enumeration<URL> en = l.getResources(resource);
   9.306 +                while (en.hasMoreElements()) {
   9.307 +                    u = en.nextElement();
   9.308 +                }
   9.309 +                if (u != null) {
   9.310 +                    return u.openStream();
   9.311 +                }
   9.312 +            }
   9.313 +            throw new IOException("Can't find " + resource);
   9.314 +        }
   9.315 +    }
   9.316 +
   9.317 +    private static class Page extends HttpHandler {
   9.318 +        private final String resource;
   9.319 +        private final String[] args;
   9.320 +        private final Res res;
   9.321 +        
   9.322 +        public Page(Res res, String resource, String... args) {
   9.323 +            this.res = res;
   9.324 +            this.resource = resource;
   9.325 +            this.args = args;
   9.326 +        }
   9.327 +
   9.328 +        @Override
   9.329 +        public void service(Request request, Response response) throws Exception {
   9.330 +            String r = resource;
   9.331 +            if (r == null) {
   9.332 +                r = request.getHttpHandlerPath();
   9.333 +                if (r.startsWith("/")) {
   9.334 +                    r = r.substring(1);
   9.335 +                }
   9.336 +            }
   9.337 +            if (r.endsWith(".html") || r.endsWith(".xhtml")) {
   9.338 +                response.setContentType("text/html");
   9.339 +            }
   9.340 +            OutputStream os = response.getOutputStream();
   9.341 +            try (InputStream is = res.get(r)) {
   9.342 +                copyStream(is, os, request.getRequestURL().toString(), args);
   9.343 +            } catch (IOException ex) {
   9.344 +                response.setDetailMessage(ex.getLocalizedMessage());
   9.345 +                response.setError();
   9.346 +                response.setStatus(404);
   9.347 +            }
   9.348 +        }
   9.349 +    }
   9.350 +
   9.351 +    private static class VM extends HttpHandler {
   9.352 +        private final Res loader;
   9.353 +
   9.354 +        public VM(Res loader) {
   9.355 +            this.loader = loader;
   9.356 +        }
   9.357 +
   9.358 +        @Override
   9.359 +        public void service(Request request, Response response) throws Exception {
   9.360 +            response.setCharacterEncoding("UTF-8");
   9.361 +            response.setContentType("text/javascript");
   9.362 +            Bck2Brwsr.generate(response.getWriter(), loader);
   9.363 +        }
   9.364 +    }
   9.365 +    private static class VMInit extends HttpHandler {
   9.366 +        public VMInit() {
   9.367 +        }
   9.368 +
   9.369 +        @Override
   9.370 +        public void service(Request request, Response response) throws Exception {
   9.371 +            response.setCharacterEncoding("UTF-8");
   9.372 +            response.setContentType("text/javascript");
   9.373 +            response.getWriter().append(
   9.374 +                "function ldCls(res) {\n"
   9.375 +                + "  var request = new XMLHttpRequest();\n"
   9.376 +                + "  request.open('GET', '/classes/' + res, false);\n"
   9.377 +                + "  request.send();\n"
   9.378 +                + "  var arr = eval('(' + request.responseText + ')');\n"
   9.379 +                + "  return arr;\n"
   9.380 +                + "}\n"
   9.381 +                + "var vm = new bck2brwsr(ldCls);\n");
   9.382 +        }
   9.383 +    }
   9.384 +
   9.385 +    private static class Classes extends HttpHandler {
   9.386 +        private final Res loader;
   9.387 +
   9.388 +        public Classes(Res loader) {
   9.389 +            this.loader = loader;
   9.390 +        }
   9.391 +
   9.392 +        @Override
   9.393 +        public void service(Request request, Response response) throws Exception {
   9.394 +            String res = request.getHttpHandlerPath();
   9.395 +            if (res.startsWith("/")) {
   9.396 +                res = res.substring(1);
   9.397 +            }
   9.398 +            try (InputStream is = loader.get(res)) {
   9.399 +                response.setContentType("text/javascript");
   9.400 +                Writer w = response.getWriter();
   9.401 +                w.append("[");
   9.402 +                for (int i = 0;; i++) {
   9.403 +                    int b = is.read();
   9.404 +                    if (b == -1) {
   9.405 +                        break;
   9.406 +                    }
   9.407 +                    if (i > 0) {
   9.408 +                        w.append(", ");
   9.409 +                    }
   9.410 +                    if (i % 20 == 0) {
   9.411 +                        w.write("\n");
   9.412 +                    }
   9.413 +                    if (b > 127) {
   9.414 +                        b = b - 256;
   9.415 +                    }
   9.416 +                    w.append(Integer.toString(b));
   9.417 +                }
   9.418 +                w.append("\n]");
   9.419 +            } catch (IOException ex) {
   9.420 +                response.setError();
   9.421 +                response.setDetailMessage(ex.getMessage());
   9.422 +            }
   9.423 +        }
   9.424 +    }
   9.425 +}
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Console.java	Mon Dec 24 07:57:33 2012 +0100
    10.3 @@ -0,0 +1,178 @@
    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.launcher;
   10.22 +
   10.23 +import java.io.IOException;
   10.24 +import java.io.InputStream;
   10.25 +import java.lang.reflect.InvocationTargetException;
   10.26 +import java.lang.reflect.Method;
   10.27 +import java.net.URL;
   10.28 +import java.util.Enumeration;
   10.29 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
   10.30 +
   10.31 +/**
   10.32 + *
   10.33 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   10.34 + */
   10.35 +public class Console {
   10.36 +    public static String welcome() {
   10.37 +        return "HellofromBck2Brwsr";
   10.38 +    }
   10.39 +    public static String multiply() {
   10.40 +        return String.valueOf(Integer.MAX_VALUE / 2 + Integer.MAX_VALUE);
   10.41 +    }
   10.42 +    
   10.43 +    @JavaScriptBody(args = {"id", "attr"}, body = 
   10.44 +        "return window.document.getElementById(id)[attr].toString();")
   10.45 +    private static native Object getAttr(String id, String attr);
   10.46 +
   10.47 +    @JavaScriptBody(args = {"id", "attr", "value"}, body = 
   10.48 +        "window.document.getElementById(id)[attr] = value;")
   10.49 +    private static native void setAttr(String id, String attr, Object value);
   10.50 +    
   10.51 +    @JavaScriptBody(args = {}, body = "window.close();")
   10.52 +    private static native void closeWindow();
   10.53 +
   10.54 +    private static void log(String newText) {
   10.55 +        String id = "result";
   10.56 +        String attr = "value";
   10.57 +        setAttr(id, attr, getAttr(id, attr) + "\n" + newText);
   10.58 +        setAttr(id, "scrollTop", getAttr(id, "scrollHeight"));
   10.59 +    }
   10.60 +    
   10.61 +    public static void execute() throws Exception {
   10.62 +        String clazz = (String) getAttr("clazz", "value");
   10.63 +        String method = (String) getAttr("method", "value");
   10.64 +        Object res = invokeMethod(clazz, method);
   10.65 +        setAttr("result", "value", res);
   10.66 +    }
   10.67 +    
   10.68 +    public static void harness(String url) {
   10.69 +        log("Connecting to " + url);
   10.70 +        try {
   10.71 +            URL u = new URL(url);
   10.72 +            for (;;) {
   10.73 +                String data = (String) u.getContent(new Class[] { String.class });
   10.74 +                log("\nGot \"" + data + "\"");
   10.75 +                if (data.isEmpty()) {
   10.76 +                    log("No data, exiting");
   10.77 +                    closeWindow();
   10.78 +                    break;
   10.79 +                }
   10.80 +                
   10.81 +                Case c = Case.parseData(data);
   10.82 +                log("Invoking " + c.getClassName() + '.' + c.getMethodName() + " as request: " + c.getRequestId());
   10.83 +
   10.84 +                Object result = invokeMethod(c.getClassName(), c.getMethodName());
   10.85 +                
   10.86 +                log("Result: " + result);
   10.87 +                log("Sending back: " + url + "?request=" + c.getRequestId() + "&result=" + result);
   10.88 +                u = new URL(url + "?request=" + c.getRequestId() + "&result=" + result);
   10.89 +            }
   10.90 +            
   10.91 +            
   10.92 +        } catch (Exception ex) {
   10.93 +            log(ex.getMessage());
   10.94 +        }
   10.95 +    }
   10.96 +    
   10.97 +    static String invoke(String clazz, String method) throws ClassNotFoundException, InvocationTargetException, IllegalAccessException {
   10.98 +        final Object r = invokeMethod(clazz, method);
   10.99 +        return r == null ? "null" : r.toString().toString();
  10.100 +    }
  10.101 +
  10.102 +    /** Helper method that inspects the classpath and loads given resource
  10.103 +     * (usually a class file). Used while running tests in Rhino.
  10.104 +     * 
  10.105 +     * @param name resource name to find
  10.106 +     * @return the array of bytes in the given resource
  10.107 +     * @throws IOException I/O in case something goes wrong
  10.108 +     */
  10.109 +    public static byte[] read(String name) throws IOException {
  10.110 +        URL u = null;
  10.111 +        Enumeration<URL> en = Console.class.getClassLoader().getResources(name);
  10.112 +        while (en.hasMoreElements()) {
  10.113 +            u = en.nextElement();
  10.114 +        }
  10.115 +        if (u == null) {
  10.116 +            throw new IOException("Can't find " + name);
  10.117 +        }
  10.118 +        try (InputStream is = u.openStream()) {
  10.119 +            byte[] arr;
  10.120 +            arr = new byte[is.available()];
  10.121 +            int offset = 0;
  10.122 +            while (offset < arr.length) {
  10.123 +                int len = is.read(arr, offset, arr.length - offset);
  10.124 +                if (len == -1) {
  10.125 +                    throw new IOException("Can't read " + name);
  10.126 +                }
  10.127 +                offset += len;
  10.128 +            }
  10.129 +            return arr;
  10.130 +        }
  10.131 +    }
  10.132 +   
  10.133 +    private static Object invokeMethod(String clazz, String method) 
  10.134 +    throws ClassNotFoundException, InvocationTargetException, 
  10.135 +    SecurityException, IllegalAccessException, IllegalArgumentException {
  10.136 +        Method found = null;
  10.137 +        Class<?> c = Class.forName(clazz);
  10.138 +        for (Method m : c.getMethods()) {
  10.139 +            if (m.getName().equals(method)) {
  10.140 +                found = m;
  10.141 +            }
  10.142 +        }
  10.143 +        Object res;
  10.144 +        if (found != null) {
  10.145 +            res = found.invoke(null);
  10.146 +        } else {
  10.147 +            res = "Can't find method " + method + " in " + clazz;
  10.148 +        }
  10.149 +        return res;
  10.150 +    }
  10.151 +    
  10.152 +    private static final class Case {
  10.153 +        private final Object data;
  10.154 +
  10.155 +        private Case(Object data) {
  10.156 +            this.data = data;
  10.157 +        }
  10.158 +        
  10.159 +        public static Case parseData(String s) {
  10.160 +            return new Case(toJSON(s));
  10.161 +        }
  10.162 +        
  10.163 +        public String getMethodName() {
  10.164 +            return value("methodName", data);
  10.165 +        }
  10.166 +
  10.167 +        public String getClassName() {
  10.168 +            return value("className", data);
  10.169 +        }
  10.170 +        
  10.171 +        public String getRequestId() {
  10.172 +            return value("request", data);
  10.173 +        }
  10.174 +        
  10.175 +        @JavaScriptBody(args = "s", body = "return eval('(' + s + ')');")
  10.176 +        private static native Object toJSON(String s);
  10.177 +        
  10.178 +        @JavaScriptBody(args = {"p", "d"}, body = "return d[p].toString();")
  10.179 +        private static native String value(String p, Object d);
  10.180 +    }
  10.181 +}
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/JSLauncher.java	Mon Dec 24 07:57:33 2012 +0100
    11.3 @@ -0,0 +1,114 @@
    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.launcher;
   11.22 +
   11.23 +import java.io.IOException;
   11.24 +import java.io.InputStream;
   11.25 +import java.net.URL;
   11.26 +import java.util.Enumeration;
   11.27 +import java.util.LinkedHashSet;
   11.28 +import java.util.Set;
   11.29 +import java.util.logging.Logger;
   11.30 +import javax.script.Invocable;
   11.31 +import javax.script.ScriptEngine;
   11.32 +import javax.script.ScriptEngineManager;
   11.33 +import javax.script.ScriptException;
   11.34 +import org.apidesign.vm4brwsr.Bck2Brwsr;
   11.35 +
   11.36 +/**
   11.37 + * Tests execution in Java's internal scripting engine.
   11.38 + */
   11.39 +public final class JSLauncher {
   11.40 +    private static final Logger LOG = Logger.getLogger(JSLauncher.class.getName());
   11.41 +    private Set<ClassLoader> loaders = new LinkedHashSet<>();
   11.42 +    private final Res resources = new Res();
   11.43 +    private Invocable code;
   11.44 +    private Object console;
   11.45 +    
   11.46 +    
   11.47 +    public MethodInvocation addMethod(Class<?> clazz, String method) {
   11.48 +        loaders.add(clazz.getClassLoader());
   11.49 +        MethodInvocation mi = new MethodInvocation(clazz.getName(), method);
   11.50 +        try {
   11.51 +            mi.result(code.invokeMethod(
   11.52 +                console,
   11.53 +                "invoke__Ljava_lang_String_2Ljava_lang_String_2Ljava_lang_String_2",
   11.54 +                mi.className, mi.methodName).toString(), null);
   11.55 +        } catch (ScriptException | NoSuchMethodException ex) {
   11.56 +            mi.result(null, ex);
   11.57 +        }
   11.58 +        return mi;
   11.59 +    }
   11.60 +    
   11.61 +    public void addClassLoader(ClassLoader url) {
   11.62 +        this.loaders.add(url);
   11.63 +    }
   11.64 +
   11.65 +    public void initialize() throws IOException {
   11.66 +        try {
   11.67 +            initRhino();
   11.68 +        } catch (Exception ex) {
   11.69 +            if (ex instanceof IOException) {
   11.70 +                throw (IOException)ex;
   11.71 +            }
   11.72 +            if (ex instanceof RuntimeException) {
   11.73 +                throw (RuntimeException)ex;
   11.74 +            }
   11.75 +            throw new IOException(ex);
   11.76 +        }
   11.77 +    }
   11.78 +    
   11.79 +    private void initRhino() throws IOException, ScriptException, NoSuchMethodException {
   11.80 +        StringBuilder sb = new StringBuilder();
   11.81 +        Bck2Brwsr.generate(sb, new Res());
   11.82 +
   11.83 +        ScriptEngineManager sem = new ScriptEngineManager();
   11.84 +        ScriptEngine mach = sem.getEngineByExtension("js");
   11.85 +
   11.86 +        sb.append(
   11.87 +              "\nvar vm = new bck2brwsr(org.apidesign.bck2brwsr.launcher.Console.read);"
   11.88 +            + "\nfunction initVM() { return vm; };"
   11.89 +            + "\n");
   11.90 +
   11.91 +        Object res = mach.eval(sb.toString());
   11.92 +        if (!(mach instanceof Invocable)) {
   11.93 +            throw new IOException("It is invocable object: " + res);
   11.94 +        }
   11.95 +        code = (Invocable) mach;
   11.96 +        
   11.97 +        Object vm = code.invokeFunction("initVM");
   11.98 +        console = code.invokeMethod(vm, "loadClass", Console.class.getName());
   11.99 +    }
  11.100 +    
  11.101 +    private class Res implements Bck2Brwsr.Resources {
  11.102 +        @Override
  11.103 +        public InputStream get(String resource) throws IOException {
  11.104 +            for (ClassLoader l : loaders) {
  11.105 +                URL u = null;
  11.106 +                Enumeration<URL> en = l.getResources(resource);
  11.107 +                while (en.hasMoreElements()) {
  11.108 +                    u = en.nextElement();
  11.109 +                }
  11.110 +                if (u != null) {
  11.111 +                    return u.openStream();
  11.112 +                }
  11.113 +            }
  11.114 +            throw new IOException("Can't find " + resource);
  11.115 +        }
  11.116 +    }
  11.117 +}
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/MethodInvocation.java	Mon Dec 24 07:57:33 2012 +0100
    12.3 @@ -0,0 +1,57 @@
    12.4 +/**
    12.5 + * Back 2 Browser Bytecode Translator
    12.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    12.7 + *
    12.8 + * This program is free software: you can redistribute it and/or modify
    12.9 + * it under the terms of the GNU General Public License as published by
   12.10 + * the Free Software Foundation, version 2 of the License.
   12.11 + *
   12.12 + * This program is distributed in the hope that it will be useful,
   12.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   12.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   12.15 + * GNU General Public License for more details.
   12.16 + *
   12.17 + * You should have received a copy of the GNU General Public License
   12.18 + * along with this program. Look for COPYING file in the top folder.
   12.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   12.20 + */
   12.21 +package org.apidesign.bck2brwsr.launcher;
   12.22 +
   12.23 +import java.util.concurrent.CountDownLatch;
   12.24 +import java.util.concurrent.TimeUnit;
   12.25 +
   12.26 +/**
   12.27 + *
   12.28 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   12.29 + */
   12.30 +public final class MethodInvocation {
   12.31 +    final CountDownLatch wait = new CountDownLatch(1);
   12.32 +    final String className;
   12.33 +    final String methodName;
   12.34 +    private String result;
   12.35 +    private Exception exception;
   12.36 +
   12.37 +    MethodInvocation(String className, String methodName) {
   12.38 +        this.className = className;
   12.39 +        this.methodName = methodName;
   12.40 +    }
   12.41 +    
   12.42 +    void await(long timeOut) throws InterruptedException {
   12.43 +        wait.await(timeOut, TimeUnit.MILLISECONDS);
   12.44 +    }
   12.45 +    
   12.46 +    void result(String r, Exception e) {
   12.47 +        this.result = r;
   12.48 +        this.exception = e;
   12.49 +        wait.countDown();
   12.50 +    }
   12.51 +
   12.52 +    @Override
   12.53 +    public String toString() {
   12.54 +        if (exception != null) {
   12.55 +            return exception.toString();
   12.56 +        }
   12.57 +        return result;
   12.58 +    }
   12.59 +    
   12.60 +}
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/launcher/src/main/resources/org/apidesign/bck2brwsr/launcher/console.xhtml	Mon Dec 24 07:57:33 2012 +0100
    13.3 @@ -0,0 +1,52 @@
    13.4 +<?xml version="1.0" encoding="UTF-8"?>
    13.5 +<!--
    13.6 +
    13.7 +    Back 2 Browser Bytecode Translator
    13.8 +    Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    13.9 +
   13.10 +    This program is free software: you can redistribute it and/or modify
   13.11 +    it under the terms of the GNU General Public License as published by
   13.12 +    the Free Software Foundation, version 2 of the License.
   13.13 +
   13.14 +    This program is distributed in the hope that it will be useful,
   13.15 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
   13.16 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   13.17 +    GNU General Public License for more details.
   13.18 +
   13.19 +    You should have received a copy of the GNU General Public License
   13.20 +    along with this program. Look for COPYING file in the top folder.
   13.21 +    If not, see http://opensource.org/licenses/GPL-2.0.
   13.22 +
   13.23 +-->
   13.24 +<!DOCTYPE html>
   13.25 +<html xmlns="http://www.w3.org/1999/xhtml">
   13.26 +    <head>
   13.27 +        <title>Bck2Brwsr Launcher</title>
   13.28 +    </head>
   13.29 +    <body>
   13.30 +        <script src="/bck2brwsr.js"></script>
   13.31 +        <script src="/vm.js"></script>
   13.32 +        
   13.33 +        <h1>Bck2Browser Console Launcher</h1>
   13.34 +        
   13.35 +        Class Name:
   13.36 +        <input id="clazz" value="$0"/>
   13.37 +        <br/>
   13.38 +        Method Name:
   13.39 +
   13.40 +        <input id="method" value="$1"/>
   13.41 +        <br/>
   13.42 +        
   13.43 +        <button onclick="vm.loadClass('org.apidesign.bck2brwsr.launcher.Console').execute__V();">Execute!</button>
   13.44 +        
   13.45 +        <hr/>
   13.46 +        <textarea id="result" rows="10" cols="80" disabled="">
   13.47 +        </textarea>
   13.48 +        
   13.49 +        <script type="text/javascript">
   13.50 +            if ($2) {
   13.51 +                vm.loadClass('org.apidesign.bck2brwsr.launcher.Console').execute__V();
   13.52 +            }
   13.53 +        </script>
   13.54 +    </body>
   13.55 +</html>
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/launcher/src/main/resources/org/apidesign/bck2brwsr/launcher/harness.xhtml	Mon Dec 24 07:57:33 2012 +0100
    14.3 @@ -0,0 +1,39 @@
    14.4 +<?xml version="1.0" encoding="UTF-8"?>
    14.5 +<!--
    14.6 +
    14.7 +    Back 2 Browser Bytecode Translator
    14.8 +    Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    14.9 +
   14.10 +    This program is free software: you can redistribute it and/or modify
   14.11 +    it under the terms of the GNU General Public License as published by
   14.12 +    the Free Software Foundation, version 2 of the License.
   14.13 +
   14.14 +    This program is distributed in the hope that it will be useful,
   14.15 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
   14.16 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14.17 +    GNU General Public License for more details.
   14.18 +
   14.19 +    You should have received a copy of the GNU General Public License
   14.20 +    along with this program. Look for COPYING file in the top folder.
   14.21 +    If not, see http://opensource.org/licenses/GPL-2.0.
   14.22 +
   14.23 +-->
   14.24 +<!DOCTYPE html>
   14.25 +<html xmlns="http://www.w3.org/1999/xhtml">
   14.26 +    <head>
   14.27 +        <title>Bck2Brwsr Harness</title>
   14.28 +    </head>
   14.29 +    <body>
   14.30 +        <script src="/bck2brwsr.js"></script>
   14.31 +        <script src="/vm.js"></script>
   14.32 +        
   14.33 +        <h1>Bck2Browser Execution Harness</h1>
   14.34 +        
   14.35 +        <textarea id="result" rows="25" style="width: 100%;" disabled="">
   14.36 +        </textarea>
   14.37 +        
   14.38 +        <script type="text/javascript">
   14.39 +            vm.loadClass('org.apidesign.bck2brwsr.launcher.Console').harness__VLjava_lang_String_2('$U/../data');
   14.40 +        </script>
   14.41 +    </body>
   14.42 +</html>
    15.1 --- a/mojo/pom.xml	Mon Dec 24 07:51:15 2012 +0100
    15.2 +++ b/mojo/pom.xml	Mon Dec 24 07:57:33 2012 +0100
    15.3 @@ -77,5 +77,10 @@
    15.4        <version>3.0.2</version>
    15.5        <type>jar</type>
    15.6      </dependency>
    15.7 +    <dependency>
    15.8 +        <groupId>${project.groupId}</groupId>
    15.9 +        <artifactId>launcher</artifactId>
   15.10 +      <version>${project.version}</version>
   15.11 +    </dependency>
   15.12  </dependencies>
   15.13  </project>
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/mojo/src/main/java/org/apidesign/bck2brwsr/mojo/BrswrMojo.java	Mon Dec 24 07:57:33 2012 +0100
    16.3 @@ -0,0 +1,118 @@
    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.mojo;
   16.22 +
   16.23 +import org.apache.maven.plugin.AbstractMojo;
   16.24 +
   16.25 +import java.io.File;
   16.26 +import java.io.IOException;
   16.27 +import java.net.MalformedURLException;
   16.28 +import java.net.URISyntaxException;
   16.29 +import java.net.URL;
   16.30 +import java.net.URLClassLoader;
   16.31 +import java.util.ArrayList;
   16.32 +import java.util.Collection;
   16.33 +import java.util.List;
   16.34 +import java.util.logging.Level;
   16.35 +import java.util.logging.Logger;
   16.36 +import org.apache.maven.artifact.Artifact;
   16.37 +import org.apache.maven.plugin.MojoExecutionException;
   16.38 +import org.apache.maven.plugins.annotations.LifecyclePhase;
   16.39 +import org.apache.maven.plugins.annotations.Mojo;
   16.40 +import org.apache.maven.plugins.annotations.Parameter;
   16.41 +import org.apache.maven.project.MavenProject;
   16.42 +import org.apidesign.bck2brwsr.launcher.Bck2BrwsrLauncher;
   16.43 +
   16.44 +/** Executes given HTML page in a browser. */
   16.45 +@Mojo(name="brwsr", defaultPhase=LifecyclePhase.DEPLOY)
   16.46 +public class BrswrMojo extends AbstractMojo {
   16.47 +    public BrswrMojo() {
   16.48 +    }
   16.49 +    /** Resource to show as initial page */
   16.50 +    @Parameter
   16.51 +    private String startpage;
   16.52 +    
   16.53 +    @Parameter(defaultValue="${project}")
   16.54 +    private MavenProject prj;
   16.55 +    
   16.56 +    /** Root of the class files */
   16.57 +    @Parameter(defaultValue="${project.build.directory}/classes")
   16.58 +    private File classes;
   16.59 +
   16.60 +    @Override
   16.61 +    public void execute() throws MojoExecutionException {
   16.62 +        if (startpage == null) {
   16.63 +            throw new MojoExecutionException("You have to provide a start page");
   16.64 +        }
   16.65 +
   16.66 +        try {
   16.67 +            URLClassLoader url = buildClassLoader(classes, prj.getDependencyArtifacts());
   16.68 +            
   16.69 +            Bck2BrwsrLauncher httpServer = new Bck2BrwsrLauncher();
   16.70 +            httpServer.addClassLoader(url);
   16.71 +            try {
   16.72 +                httpServer.showURL(startpage);
   16.73 +            } catch (Exception ex) {
   16.74 +                throw new MojoExecutionException("Can't open " + startpage, ex);
   16.75 +            }
   16.76 +            
   16.77 +            System.in.read();
   16.78 +        } catch (IOException ex) {
   16.79 +            throw new MojoExecutionException("Can't show the browser", ex);
   16.80 +        }
   16.81 +    }
   16.82 +
   16.83 +    private static File findNonEmptyFolder(File dir) throws MojoExecutionException {
   16.84 +        if (!dir.isDirectory()) {
   16.85 +            throw new MojoExecutionException("Not a directory " + dir);
   16.86 +        }
   16.87 +        File[] arr = dir.listFiles();
   16.88 +        if (arr.length == 1 && arr[0].isDirectory()) {
   16.89 +            return findNonEmptyFolder(arr[0]);
   16.90 +        }
   16.91 +        return dir;
   16.92 +    }
   16.93 +
   16.94 +    private static long collectAllClasses(String prefix, File toCheck, List<String> arr) {
   16.95 +        File[] files = toCheck.listFiles();
   16.96 +        if (files != null) {
   16.97 +            long newest = 0L;
   16.98 +            for (File f : files) {
   16.99 +                long lastModified = collectAllClasses(prefix + f.getName() + "/", f, arr);
  16.100 +                if (newest < lastModified) {
  16.101 +                    newest = lastModified;
  16.102 +                }
  16.103 +            }
  16.104 +            return newest;
  16.105 +        } else if (toCheck.getName().endsWith(".class")) {
  16.106 +            arr.add(prefix.substring(0, prefix.length() - 7));
  16.107 +            return toCheck.lastModified();
  16.108 +        } else {
  16.109 +            return 0L;
  16.110 +        }
  16.111 +    }
  16.112 +
  16.113 +    private static URLClassLoader buildClassLoader(File root, Collection<Artifact> deps) throws MalformedURLException {
  16.114 +        List<URL> arr = new ArrayList<URL>();
  16.115 +        arr.add(root.toURI().toURL());
  16.116 +        for (Artifact a : deps) {
  16.117 +            arr.add(a.getFile().toURI().toURL());
  16.118 +        }
  16.119 +        return new URLClassLoader(arr.toArray(new URL[0]), BrswrMojo.class.getClassLoader());
  16.120 +    }
  16.121 +}
    17.1 --- a/pom.xml	Mon Dec 24 07:51:15 2012 +0100
    17.2 +++ b/pom.xml	Mon Dec 24 07:57:33 2012 +0100
    17.3 @@ -14,6 +14,8 @@
    17.4      <module>javaquery</module>
    17.5      <module>javap</module>
    17.6      <module>benchmarks</module>
    17.7 +    <module>launcher</module>
    17.8 +    <module>vmtest</module>
    17.9    </modules>
   17.10    <licenses>
   17.11        <license>
   17.12 @@ -108,4 +110,4 @@
   17.13    <properties>
   17.14        <license>COPYING</license>
   17.15    </properties>
   17.16 -</project>
   17.17 +</project>
   17.18 \ No newline at end of file
    18.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java	Mon Dec 24 07:51:15 2012 +0100
    18.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java	Mon Dec 24 07:57:33 2012 +0100
    18.3 @@ -155,6 +155,7 @@
    18.4          out.append(accessClass("java_lang_Class(true);"));
    18.5          out.append("\n    CLS.$class.jvmName = '").append(jc.getClassName()).append("';");
    18.6          out.append("\n    CLS.$class.superclass = sprcls;");
    18.7 +        out.append("\n    CLS.$class.access = ").append(jc.getAccessFlags()+";");
    18.8          out.append("\n    CLS.$class.cnstr = CLS;");
    18.9          byte[] classAnno = jc.findAnnotationData(false);
   18.10          if (classAnno != null) {
   18.11 @@ -1028,7 +1029,7 @@
   18.12                      int indx = readIntArg(byteCodes, i);
   18.13                      String[] fi = jc.getFieldInfoName(indx);
   18.14                      final int type = VarType.fromFieldType(fi[2].charAt(0));
   18.15 -                    emit(out, "@1 = @2.@3;",
   18.16 +                    emit(out, "@1 = @2(false).constructor.@3;",
   18.17                           smapper.pushT(type),
   18.18                           accessClass(fi[0].replace('/', '_')), fi[1]);
   18.19                      i += 2;
   18.20 @@ -1048,7 +1049,7 @@
   18.21                      int indx = readIntArg(byteCodes, i);
   18.22                      String[] fi = jc.getFieldInfoName(indx);
   18.23                      final int type = VarType.fromFieldType(fi[2].charAt(0));
   18.24 -                    emit(out, "@1.@2 = @3;",
   18.25 +                    emit(out, "@1(false).constructor.@2 = @3;",
   18.26                           accessClass(fi[0].replace('/', '_')), fi[1],
   18.27                           smapper.popT(type));
   18.28                      i += 2;
    19.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/VMLazy.java	Mon Dec 24 07:51:15 2012 +0100
    19.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/VMLazy.java	Mon Dec 24 07:57:33 2012 +0100
    19.3 @@ -61,10 +61,27 @@
    19.4          StringBuilder out = new StringBuilder();
    19.5          out.append("var loader = arguments[0];\n");
    19.6          out.append("var vm = loader.vm;\n");
    19.7 -        new Gen(this, out).compile(new ByteArrayInputStream(arr));
    19.8 +        int prelude = out.length();
    19.9 +        String initCode = new Gen(this, out).compile(new ByteArrayInputStream(arr));
   19.10          String code = out.toString().toString();
   19.11 +//        dump("Loading " + name);
   19.12 +        dump(code);
   19.13          String under = name.replace('.', '_');
   19.14 -        return applyCode(loader, under, code, instance);
   19.15 +        Object fn = applyCode(loader, under, code, instance);
   19.16 +        
   19.17 +        if (!initCode.isEmpty()) {
   19.18 +            out.setLength(prelude);
   19.19 +            out.append(initCode);
   19.20 +            code = out.toString().toString();
   19.21 +            dump(code);
   19.22 +            applyCode(loader, null, code, false);
   19.23 +        }            
   19.24 +        
   19.25 +        return fn;
   19.26 +    }
   19.27 +
   19.28 +//    @JavaScriptBody(args = "s", body = "java.lang.System.out.println(s.toString());")
   19.29 +    static void dump(String s) {
   19.30      }
   19.31  
   19.32  /* possibly not needed:
   19.33 @@ -82,7 +99,7 @@
   19.34          "} catch (ex) {\n" +
   19.35          "  throw 'Cannot compile ' + ex + ' line: ' + ex.lineNumber + ' script:\\n' + script;\n" +
   19.36          "}\n" +
   19.37 -        "return vm[name](instance);\n"
   19.38 +        "return name != null ? vm[name](instance) : null;\n"
   19.39      )
   19.40      private static native Object applyCode(Object loader, String name, String script, boolean instance);
   19.41      
    20.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/ClassTest.java	Mon Dec 24 07:51:15 2012 +0100
    20.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/ClassTest.java	Mon Dec 24 07:57:33 2012 +0100
    20.3 @@ -101,6 +101,18 @@
    20.4              "java.io.IOException", false, "name"
    20.5          );
    20.6      }
    20.7 +    @Test public void primitiveReturnType() throws Exception {
    20.8 +        assertExec("Tries to get an integer via reflection", Classes.class, 
    20.9 +            "primitiveType__Ljava_lang_String_2Ljava_lang_String_2", 
   20.10 +            Classes.primitiveType("primitive"), "primitive"
   20.11 +        );
   20.12 +    }
   20.13 +    @Test public void primitiveBoolReturnType() throws Exception {
   20.14 +        assertExec("Tries to get an integer via reflection", Classes.class, 
   20.15 +            "primitiveType__Ljava_lang_String_2Ljava_lang_String_2", 
   20.16 +            Classes.primitiveType("primitiveB"), "primitiveB"
   20.17 +        );
   20.18 +    }
   20.19      @Test public void javaAnnotatedMethod() throws Exception {
   20.20          assertEquals(Classes.reflectiveMethodCall(false, null), "java.io.IOException", "Calls the name() method via reflection");
   20.21      }
   20.22 @@ -116,6 +128,26 @@
   20.23              "java.io.IOException"
   20.24          );
   20.25      }
   20.26 +    @Test public void noInterface() throws Exception {
   20.27 +        assertExec("Calls Class.isInterface", Classes.class, 
   20.28 +            "isInterface__ZLjava_lang_String_2", 
   20.29 +            0.0, "java.lang.String"
   20.30 +        );
   20.31 +    }
   20.32 +    /*
   20.33 +    @Test public void isInterface() throws Exception {
   20.34 +        assertExec("Calls Class.isInterface", Classes.class, 
   20.35 +            "isInterface__ZLjava_lang_String_2", 
   20.36 +            1.0, "java.lang.Runnable"
   20.37 +        );
   20.38 +    }
   20.39 +    */
   20.40 +    @Test public void integerType() throws Exception {
   20.41 +        assertExec("Computes the type", Classes.class, 
   20.42 +            "intType__Ljava_lang_String_2", 
   20.43 +            Classes.intType()
   20.44 +        );
   20.45 +    }
   20.46      
   20.47      private static CharSequence codeSeq;
   20.48      private static Invocable code;
    21.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/Classes.java	Mon Dec 24 07:51:15 2012 +0100
    21.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/Classes.java	Mon Dec 24 07:57:33 2012 +0100
    21.3 @@ -38,6 +38,10 @@
    21.4          return c.getName();
    21.5      }
    21.6      
    21.7 +    public static boolean isInterface(String s) throws ClassNotFoundException {
    21.8 +        return Class.forName(s).isInterface();
    21.9 +    }
   21.10 +    
   21.11      public static boolean equalsClassesOfExceptions() {
   21.12          return MalformedURLException.class.getSuperclass() == IOException.class;
   21.13      }
   21.14 @@ -88,6 +92,21 @@
   21.15          return null;
   21.16      }
   21.17      
   21.18 +    public static String intType() {
   21.19 +        return Integer.TYPE.getName();
   21.20 +    }
   21.21 +    
   21.22 +    public static int primitive() {
   21.23 +        return 1;
   21.24 +    }
   21.25 +    public static boolean primitiveB() {
   21.26 +        return true;
   21.27 +    }
   21.28 +    
   21.29 +    public static String primitiveType(String method) throws Exception {
   21.30 +        return reflectiveMethodCall(false, method).getClass().getName();
   21.31 +    }
   21.32 +    
   21.33      @JavaScriptBody(args = "msg", body = "throw msg;")
   21.34      private static native void thrw(String msg);
   21.35      
    22.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/Compare.java	Mon Dec 24 07:51:15 2012 +0100
    22.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.3 @@ -1,36 +0,0 @@
    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.vm4brwsr;
   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 -/** Can be applied on a method that yields a return value. 
   22.29 - * Together with {@link VMCompare#create} it can be used to write
   22.30 - * methods which are executed in real as well as JavaScript VMs and
   22.31 - * their results are compared.
   22.32 - *
   22.33 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   22.34 - */
   22.35 -@Retention(RetentionPolicy.RUNTIME)
   22.36 -@Target(ElementType.METHOD)
   22.37 -public @interface Compare {
   22.38 -    
   22.39 -}
    23.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/CompareVMs.java	Mon Dec 24 07:51:15 2012 +0100
    23.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.3 @@ -1,197 +0,0 @@
    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.vm4brwsr;
   23.22 -
   23.23 -import java.lang.reflect.Method;
   23.24 -import java.util.Map;
   23.25 -import java.util.WeakHashMap;
   23.26 -import javax.script.Invocable;
   23.27 -import javax.script.ScriptContext;
   23.28 -import javax.script.ScriptEngine;
   23.29 -import javax.script.ScriptEngineManager;
   23.30 -import org.testng.Assert;
   23.31 -import org.testng.ITest;
   23.32 -import org.testng.annotations.Factory;
   23.33 -import org.testng.annotations.Test;
   23.34 -
   23.35 -/** A TestNG {@link Factory} that seeks for {@link Compare} annotations
   23.36 - * in provided class and builds set of tests that compare the computations
   23.37 - * in real as well as JavaScript virtual machines. Use as:<pre>
   23.38 - * {@code @}{@link Factory} public static create() {
   23.39 - *   return @{link CompareVMs}.{@link #create(YourClass.class);
   23.40 - * }</pre>
   23.41 - *
   23.42 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   23.43 - */
   23.44 -public final class CompareVMs implements ITest {
   23.45 -    private final Run first, second;
   23.46 -    private final Method m;
   23.47 -    
   23.48 -    private CompareVMs(Method m, Run first, Run second) {
   23.49 -        this.first = first;
   23.50 -        this.second = second;
   23.51 -        this.m = m;
   23.52 -    }
   23.53 -
   23.54 -    public static Object[] create(Class<?> clazz) {
   23.55 -        Method[] arr = clazz.getMethods();
   23.56 -        Object[] ret = new Object[3 * arr.length];
   23.57 -        int cnt = 0;
   23.58 -        for (Method m : arr) {
   23.59 -            Compare c = m.getAnnotation(Compare.class);
   23.60 -            if (c == null) {
   23.61 -                continue;
   23.62 -            }
   23.63 -            final Run real = new Run(m, false);
   23.64 -            final Run js = new Run(m, true);
   23.65 -            ret[cnt++] = real;
   23.66 -            ret[cnt++] = js;
   23.67 -            ret[cnt++] = new CompareVMs(m, real, js);
   23.68 -        }
   23.69 -        Object[] r = new Object[cnt];
   23.70 -        for (int i = 0; i < cnt; i++) {
   23.71 -            r[i] = ret[i];
   23.72 -        }
   23.73 -        return r;
   23.74 -    }
   23.75 -    
   23.76 -    @Test(dependsOnGroups = "run") public void compareResults() throws Throwable {
   23.77 -        Object v1 = first.value;
   23.78 -        Object v2 = second.value;
   23.79 -        if (v1 instanceof Number) {
   23.80 -            v1 = ((Number)v1).doubleValue();
   23.81 -        }
   23.82 -        Assert.assertEquals(v2, v1, "Comparing results");
   23.83 -    }
   23.84 -    
   23.85 -    @Override
   23.86 -    public String getTestName() {
   23.87 -        return m.getName() + "[Compare]";
   23.88 -    }
   23.89 -    
   23.90 -    public static final class Run implements ITest {
   23.91 -        private final Method m;
   23.92 -        private final boolean js;
   23.93 -        Object value;
   23.94 -        private Invocable code;
   23.95 -        private CharSequence codeSeq;
   23.96 -        private static final Map<Class,Object[]> compiled = new WeakHashMap<Class,Object[]>();
   23.97 -
   23.98 -        private Run(Method m, boolean js) {
   23.99 -            this.m = m;
  23.100 -            this.js = js;
  23.101 -        }
  23.102 -
  23.103 -        private void compileTheCode(Class<?> clazz) throws Exception {
  23.104 -            final Object[] data = compiled.get(clazz);
  23.105 -            if (data != null) {
  23.106 -                code = (Invocable) data[0];
  23.107 -                codeSeq = (CharSequence) data[1];
  23.108 -                return;
  23.109 -            }
  23.110 -            StringBuilder sb = new StringBuilder();
  23.111 -            Bck2Brwsr.generate(sb, CompareVMs.class.getClassLoader());
  23.112 -
  23.113 -            ScriptEngineManager sem = new ScriptEngineManager();
  23.114 -            ScriptEngine js = sem.getEngineByExtension("js");
  23.115 -            js.getContext().setAttribute("loader", new BytesLoader(), ScriptContext.ENGINE_SCOPE);
  23.116 -            
  23.117 -            sb.append("\nfunction initVM() {"
  23.118 -                + "\n  return bck2brwsr("
  23.119 -                + "\n    function(name) { return loader.get(name);}"
  23.120 -                + "\n  );"
  23.121 -                + "\n};");
  23.122 -
  23.123 -            Object res = js.eval(sb.toString());
  23.124 -            Assert.assertTrue(js instanceof Invocable, "It is invocable object: " + res);
  23.125 -            code = (Invocable) js;
  23.126 -            codeSeq = sb;
  23.127 -            compiled.put(clazz, new Object[] { code, codeSeq });
  23.128 -        }
  23.129 -
  23.130 -        @Test(groups = "run") public void executeCode() throws Throwable {
  23.131 -            if (js) {
  23.132 -                try {
  23.133 -                    compileTheCode(m.getDeclaringClass());
  23.134 -                    Object vm = code.invokeFunction("initVM");
  23.135 -                    Object inst = code.invokeMethod(vm, "loadClass", m.getDeclaringClass().getName());
  23.136 -                    value = code.invokeMethod(inst, m.getName() + "__" + computeSignature(m));
  23.137 -                } catch (Exception ex) {
  23.138 -                    throw new AssertionError(StaticMethodTest.dumpJS(codeSeq)).initCause(ex);
  23.139 -                }
  23.140 -            } else {
  23.141 -                value = m.invoke(m.getDeclaringClass().newInstance());
  23.142 -            }
  23.143 -        }
  23.144 -        @Override
  23.145 -        public String getTestName() {
  23.146 -            return m.getName() + (js ? "[JavaScript]" : "[Java]");
  23.147 -        }
  23.148 -        
  23.149 -        private static String computeSignature(Method m) {
  23.150 -            StringBuilder sb = new StringBuilder();
  23.151 -            appendType(sb, m.getReturnType());
  23.152 -            for (Class<?> c : m.getParameterTypes()) {
  23.153 -                appendType(sb, c);
  23.154 -            }
  23.155 -            return sb.toString();
  23.156 -        }
  23.157 -        
  23.158 -        private static void appendType(StringBuilder sb, Class<?> t) {
  23.159 -            if (t == null) {
  23.160 -                sb.append('V');
  23.161 -                return;
  23.162 -            }
  23.163 -            if (t.isPrimitive()) {
  23.164 -                int ch = -1;
  23.165 -                if (t == int.class) {
  23.166 -                    ch = 'I';
  23.167 -                }
  23.168 -                if (t == short.class) {
  23.169 -                    ch = 'S';
  23.170 -                }
  23.171 -                if (t == byte.class) {
  23.172 -                    ch = 'B';
  23.173 -                }
  23.174 -                if (t == boolean.class) {
  23.175 -                    ch = 'Z';
  23.176 -                }
  23.177 -                if (t == long.class) {
  23.178 -                    ch = 'J';
  23.179 -                }
  23.180 -                if (t == float.class) {
  23.181 -                    ch = 'F';
  23.182 -                }
  23.183 -                if (t == double.class) {
  23.184 -                    ch = 'D';
  23.185 -                }
  23.186 -                assert ch != -1 : "Unknown primitive type " + t;
  23.187 -                sb.append((char)ch);
  23.188 -                return;
  23.189 -            }
  23.190 -            if (t.isArray()) {
  23.191 -                sb.append("_3");
  23.192 -                appendType(sb, t.getComponentType());
  23.193 -                return;
  23.194 -            }
  23.195 -            sb.append('L');
  23.196 -            sb.append(t.getName().replace('.', '_'));
  23.197 -            sb.append("_2");
  23.198 -        }
  23.199 -    }
  23.200 -}
    24.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/tck/CompareHashTest.java	Mon Dec 24 07:51:15 2012 +0100
    24.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.3 @@ -1,42 +0,0 @@
    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.vm4brwsr.tck;
   24.22 -
   24.23 -import org.apidesign.vm4brwsr.Compare;
   24.24 -import org.apidesign.vm4brwsr.CompareVMs;
   24.25 -import org.testng.annotations.Factory;
   24.26 -
   24.27 -/**
   24.28 - *
   24.29 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   24.30 - */
   24.31 -public class CompareHashTest {
   24.32 -    @Compare public int hashOfString() {
   24.33 -        return "Ahoj".hashCode();
   24.34 -    }
   24.35 -    
   24.36 -    @Compare public int hashRemainsYieldsZero() {
   24.37 -        Object o = new Object();
   24.38 -        return o.hashCode() - o.hashCode();
   24.39 -    }
   24.40 -    
   24.41 -    @Factory
   24.42 -    public static Object[] create() {
   24.43 -        return CompareVMs.create(CompareHashTest.class);
   24.44 -    }
   24.45 -}
    25.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/tck/CompareStringsTest.java	Mon Dec 24 07:51:15 2012 +0100
    25.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.3 @@ -1,110 +0,0 @@
    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.vm4brwsr.tck;
   25.22 -
   25.23 -import java.net.MalformedURLException;
   25.24 -import java.net.URL;
   25.25 -import org.apidesign.vm4brwsr.Compare;
   25.26 -import org.apidesign.vm4brwsr.CompareVMs;
   25.27 -import org.testng.annotations.Factory;
   25.28 -
   25.29 -/**
   25.30 - *
   25.31 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   25.32 - */
   25.33 -public class CompareStringsTest {
   25.34 -    @Compare public static Object compareURLs() throws MalformedURLException {
   25.35 -        return new URL("http://apidesign.org:8080/wiki/").toExternalForm().toString();
   25.36 -    }
   25.37 -    
   25.38 -    @Compare public String deleteLastTwoCharacters() {
   25.39 -        StringBuilder sb = new StringBuilder();
   25.40 -        sb.append("453.0");
   25.41 -        if (sb.toString().endsWith(".0")) {
   25.42 -            final int l = sb.length();
   25.43 -            sb.delete(l - 2, l);
   25.44 -        }
   25.45 -        return sb.toString().toString();
   25.46 -    }
   25.47 -    
   25.48 -    @Compare public String nameOfStringClass() throws Exception {
   25.49 -        return Class.forName("java.lang.String").getName();
   25.50 -    }
   25.51 -    @Compare public String nameOfArrayClass() throws Exception {
   25.52 -        return Class.forName("org.apidesign.vm4brwsr.Array").getName();
   25.53 -    }
   25.54 -    
   25.55 -    @Compare public String lowerHello() {
   25.56 -        return "HeLlO".toLowerCase();
   25.57 -    }
   25.58 -    
   25.59 -    @Compare public String lowerA() {
   25.60 -        return String.valueOf(Character.toLowerCase('A')).toString();
   25.61 -    }
   25.62 -    @Compare public String upperHello() {
   25.63 -        return "hello".toUpperCase();
   25.64 -    }
   25.65 -    
   25.66 -    @Compare public String upperA() {
   25.67 -        return String.valueOf(Character.toUpperCase('a')).toString();
   25.68 -    }
   25.69 -    
   25.70 -    @Compare public boolean matchRegExp() throws Exception {
   25.71 -        return "58038503".matches("\\d*");
   25.72 -    }
   25.73 -
   25.74 -    @Compare public boolean doesNotMatchRegExp() throws Exception {
   25.75 -        return "58038503GH".matches("\\d*");
   25.76 -    }
   25.77 -
   25.78 -    @Compare public boolean doesNotMatchRegExpFully() throws Exception {
   25.79 -        return "Hello".matches("Hell");
   25.80 -    }
   25.81 -    
   25.82 -    @Compare public String variousCharacterTests() throws Exception {
   25.83 -        StringBuilder sb = new StringBuilder();
   25.84 -        
   25.85 -        sb.append(Character.isUpperCase('a'));
   25.86 -        sb.append(Character.isUpperCase('A'));
   25.87 -        sb.append(Character.isLowerCase('a'));
   25.88 -        sb.append(Character.isLowerCase('A'));
   25.89 -        
   25.90 -        sb.append(Character.isLetter('A'));
   25.91 -        sb.append(Character.isLetterOrDigit('9'));
   25.92 -        sb.append(Character.isLetterOrDigit('A'));
   25.93 -        sb.append(Character.isLetter('0'));
   25.94 -        
   25.95 -        return sb.toString().toString();
   25.96 -    }
   25.97 -        
   25.98 -    @Compare
   25.99 -    public String nullFieldInitialized() {
  25.100 -        NullField nf = new NullField();
  25.101 -        return ("" + nf.name).toString();
  25.102 -    }
  25.103 -
  25.104 -    @Factory
  25.105 -    public static Object[] create() {
  25.106 -        return CompareVMs.create(CompareStringsTest.class);
  25.107 -    }
  25.108 -
  25.109 -    private static final class NullField {
  25.110 -
  25.111 -        String name;
  25.112 -    }
  25.113 -}
    26.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.2 +++ b/vmtest/pom.xml	Mon Dec 24 07:57:33 2012 +0100
    26.3 @@ -0,0 +1,61 @@
    26.4 +<?xml version="1.0"?>
    26.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"
    26.6 +    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    26.7 +  <modelVersion>4.0.0</modelVersion>
    26.8 +  <parent>
    26.9 +    <groupId>org.apidesign</groupId>
   26.10 +    <artifactId>bck2brwsr</artifactId>
   26.11 +    <version>0.3-SNAPSHOT</version>
   26.12 +  </parent>
   26.13 +  <groupId>org.apidesign.bck2brwsr</groupId>
   26.14 +  <artifactId>vmtest</artifactId>
   26.15 +  <version>0.3-SNAPSHOT</version>
   26.16 +  
   26.17 +  <name>VM Testing APIs</name>
   26.18 +  <url>http://bck2brwsr.apidesign.org</url>
   26.19 +    <build>
   26.20 +        <plugins>
   26.21 +            <plugin>
   26.22 +                <groupId>org.apache.maven.plugins</groupId>
   26.23 +                <artifactId>maven-compiler-plugin</artifactId>
   26.24 +                <version>2.3.2</version>
   26.25 +                <configuration>
   26.26 +                    <source>1.7</source>
   26.27 +                    <target>1.7</target>
   26.28 +                </configuration>
   26.29 +            </plugin>
   26.30 +        </plugins>
   26.31 +    </build>
   26.32 +    <properties>
   26.33 +    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
   26.34 +  </properties>
   26.35 +  <dependencies>
   26.36 +    <dependency>
   26.37 +      <groupId>org.testng</groupId>
   26.38 +      <artifactId>testng</artifactId>
   26.39 +      <scope>compile</scope>
   26.40 +      <exclusions>
   26.41 +        <exclusion>
   26.42 +          <artifactId>junit</artifactId>
   26.43 +          <groupId>junit</groupId>
   26.44 +        </exclusion>
   26.45 +      </exclusions>
   26.46 +    </dependency>
   26.47 +    <dependency>
   26.48 +      <groupId>${project.groupId}</groupId>
   26.49 +      <artifactId>vm4brwsr</artifactId>
   26.50 +      <version>0.3-SNAPSHOT</version>
   26.51 +      <type>jar</type>
   26.52 +    </dependency>
   26.53 +    <dependency>
   26.54 +      <groupId>${project.groupId}</groupId>
   26.55 +      <artifactId>emul</artifactId>
   26.56 +      <version>0.3-SNAPSHOT</version>
   26.57 +    </dependency>
   26.58 +    <dependency>
   26.59 +      <groupId>${project.groupId}</groupId>
   26.60 +      <artifactId>launcher</artifactId>
   26.61 +      <version>${project.version}</version>
   26.62 +    </dependency>
   26.63 +  </dependencies>
   26.64 +</project>
    27.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.2 +++ b/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/Compare.java	Mon Dec 24 07:57:33 2012 +0100
    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.vmtest;
   27.22 +
   27.23 +import java.lang.annotation.ElementType;
   27.24 +import java.lang.annotation.Retention;
   27.25 +import java.lang.annotation.RetentionPolicy;
   27.26 +import java.lang.annotation.Target;
   27.27 +
   27.28 +/** Can be applied on a method that yields a return value. 
   27.29 + * Together with {@link VMTest#create} it can be used to write
   27.30 + * methods which are executed in real as well as JavaScript VMs and
   27.31 + * their results are compared.
   27.32 + *
   27.33 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   27.34 + */
   27.35 +@Retention(RetentionPolicy.RUNTIME)
   27.36 +@Target(ElementType.METHOD)
   27.37 +public @interface Compare {
   27.38 +    
   27.39 +}
    28.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.2 +++ b/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/VMTest.java	Mon Dec 24 07:57:33 2012 +0100
    28.3 @@ -0,0 +1,43 @@
    28.4 +/**
    28.5 + * Back 2 Browser Bytecode Translator
    28.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    28.7 + *
    28.8 + * This program is free software: you can redistribute it and/or modify
    28.9 + * it under the terms of the GNU General Public License as published by
   28.10 + * the Free Software Foundation, version 2 of the License.
   28.11 + *
   28.12 + * This program is distributed in the hope that it will be useful,
   28.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   28.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   28.15 + * GNU General Public License for more details.
   28.16 + *
   28.17 + * You should have received a copy of the GNU General Public License
   28.18 + * along with this program. Look for COPYING file in the top folder.
   28.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   28.20 + */
   28.21 +package org.apidesign.bck2brwsr.vmtest;
   28.22 +
   28.23 +import org.apidesign.bck2brwsr.vmtest.impl.CompareCase;
   28.24 +import org.testng.annotations.Factory;
   28.25 +
   28.26 +/** A TestNG {@link Factory} that seeks for {@link Compare} annotations
   28.27 + * in provided class and builds set of tests that compare the computations
   28.28 + * in real as well as JavaScript virtual machines. Use as:<pre>
   28.29 + * {@code @}{@link Factory} public static create() {
   28.30 + *   return @{link VMTest}.{@link #create(YourClass.class);
   28.31 + * }</pre>
   28.32 + *
   28.33 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   28.34 + */
   28.35 +public final class VMTest {
   28.36 +    /** Inspects <code>clazz</code> and for each {@lik Compare} method creates
   28.37 +     * instances of tests. Each instance runs the test in different virtual
   28.38 +     * machine and at the end they compare the results.
   28.39 +     * 
   28.40 +     * @param clazz the class to inspect
   28.41 +     * @return the set of created tests
   28.42 +     */
   28.43 +    public static Object[] create(Class<?> clazz) {
   28.44 +        return CompareCase.create(clazz);
   28.45 +    }
   28.46 +}
    29.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.2 +++ b/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/Bck2BrwsrCase.java	Mon Dec 24 07:57:33 2012 +0100
    29.3 @@ -0,0 +1,130 @@
    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.vmtest.impl;
   29.22 +
   29.23 +import java.lang.reflect.Method;
   29.24 +import java.util.Map;
   29.25 +import java.util.WeakHashMap;
   29.26 +import javax.script.Invocable;
   29.27 +import org.apidesign.bck2brwsr.launcher.MethodInvocation;
   29.28 +import org.testng.ITest;
   29.29 +import org.testng.annotations.Test;
   29.30 +
   29.31 +/**
   29.32 + *
   29.33 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   29.34 + */
   29.35 +public final class Bck2BrwsrCase implements ITest {
   29.36 +    private final Method m;
   29.37 +    private final Launchers l;
   29.38 +    private final int type;
   29.39 +    Object value;
   29.40 +    private Invocable code;
   29.41 +    private CharSequence codeSeq;
   29.42 +    private static final Map<Class, Object[]> compiled = new WeakHashMap<>();
   29.43 +    private Object inst;
   29.44 +
   29.45 +    Bck2BrwsrCase(Method m, int type, Launchers l) {
   29.46 +        this.l = l;
   29.47 +        this.m = m;
   29.48 +        this.type = type;
   29.49 +    }
   29.50 +
   29.51 +    @Test(groups = "run")
   29.52 +    public void executeCode() throws Throwable {
   29.53 +        if (type == 1) {
   29.54 +            MethodInvocation c = l.addMethod(m.getDeclaringClass(), m.getName(), false);
   29.55 +            value = c.toString();
   29.56 +        } else if (type == 2) {
   29.57 +            MethodInvocation c = l.addMethod(m.getDeclaringClass(), m.getName(), true);
   29.58 +            value = c.toString();
   29.59 +        } else {
   29.60 +            value = m.invoke(m.getDeclaringClass().newInstance());
   29.61 +        }
   29.62 +    }
   29.63 +
   29.64 +    @Override
   29.65 +    public String getTestName() {
   29.66 +        return m.getName() + "[" + typeName() + "]";
   29.67 +    }
   29.68 +
   29.69 +    final String typeName() {
   29.70 +        switch (type) {
   29.71 +            case 0:
   29.72 +                return "Java";
   29.73 +            case 1:
   29.74 +                return "JavaScript";
   29.75 +            case 2:
   29.76 +                return "Browser";
   29.77 +            default:
   29.78 +                return "Unknown type " + type;
   29.79 +        }
   29.80 +    }
   29.81 +
   29.82 +    private static String computeSignature(Method m) {
   29.83 +        StringBuilder sb = new StringBuilder();
   29.84 +        appendType(sb, m.getReturnType());
   29.85 +        for (Class<?> c : m.getParameterTypes()) {
   29.86 +            appendType(sb, c);
   29.87 +        }
   29.88 +        return sb.toString();
   29.89 +    }
   29.90 +
   29.91 +    private static void appendType(StringBuilder sb, Class<?> t) {
   29.92 +        if (t == null) {
   29.93 +            sb.append('V');
   29.94 +            return;
   29.95 +        }
   29.96 +        if (t.isPrimitive()) {
   29.97 +            int ch = -1;
   29.98 +            if (t == int.class) {
   29.99 +                ch = 'I';
  29.100 +            }
  29.101 +            if (t == short.class) {
  29.102 +                ch = 'S';
  29.103 +            }
  29.104 +            if (t == byte.class) {
  29.105 +                ch = 'B';
  29.106 +            }
  29.107 +            if (t == boolean.class) {
  29.108 +                ch = 'Z';
  29.109 +            }
  29.110 +            if (t == long.class) {
  29.111 +                ch = 'J';
  29.112 +            }
  29.113 +            if (t == float.class) {
  29.114 +                ch = 'F';
  29.115 +            }
  29.116 +            if (t == double.class) {
  29.117 +                ch = 'D';
  29.118 +            }
  29.119 +            assert ch != -1 : "Unknown primitive type " + t;
  29.120 +            sb.append((char) ch);
  29.121 +            return;
  29.122 +        }
  29.123 +        if (t.isArray()) {
  29.124 +            sb.append("_3");
  29.125 +            appendType(sb, t.getComponentType());
  29.126 +            return;
  29.127 +        }
  29.128 +        sb.append('L');
  29.129 +        sb.append(t.getName().replace('.', '_'));
  29.130 +        sb.append("_2");
  29.131 +    }
  29.132 +    
  29.133 +}
    30.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    30.2 +++ b/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/CompareCase.java	Mon Dec 24 07:57:33 2012 +0100
    30.3 @@ -0,0 +1,114 @@
    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.vmtest.impl;
   30.22 +
   30.23 +import org.apidesign.bck2brwsr.vmtest.*;
   30.24 +import java.io.File;
   30.25 +import java.io.FileWriter;
   30.26 +import java.io.IOException;
   30.27 +import java.lang.reflect.Method;
   30.28 +import java.util.ArrayList;
   30.29 +import java.util.List;
   30.30 +import org.testng.Assert;
   30.31 +import org.testng.ITest;
   30.32 +import org.testng.annotations.Factory;
   30.33 +import org.testng.annotations.Test;
   30.34 +
   30.35 +/** A TestNG {@link Factory} that seeks for {@link Compare} annotations
   30.36 + * in provided class and builds set of tests that compare the computations
   30.37 + * in real as well as JavaScript virtual machines. Use as:<pre>
   30.38 + * {@code @}{@link Factory} public static create() {
   30.39 + *   return @{link VMTest}.{@link #create(YourClass.class);
   30.40 + * }</pre>
   30.41 + *
   30.42 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   30.43 + */
   30.44 +public final class CompareCase implements ITest {
   30.45 +    private final Bck2BrwsrCase first, second;
   30.46 +    private final Method m;
   30.47 +    
   30.48 +    private CompareCase(Method m, Bck2BrwsrCase first, Bck2BrwsrCase second) {
   30.49 +        this.first = first;
   30.50 +        this.second = second;
   30.51 +        this.m = m;
   30.52 +    }
   30.53 +
   30.54 +    /** Inspects <code>clazz</code> and for each {@lik Compare} method creates
   30.55 +     * instances of tests. Each instance runs the test in different virtual
   30.56 +     * machine and at the end they compare the results.
   30.57 +     * 
   30.58 +     * @param clazz the class to inspect
   30.59 +     * @return the set of created tests
   30.60 +     */
   30.61 +    public static Object[] create(Class<?> clazz) {
   30.62 +        Method[] arr = clazz.getMethods();
   30.63 +        List<Object> ret = new ArrayList<>();
   30.64 +        
   30.65 +        final Launchers l = Launchers.INSTANCE;
   30.66 +    
   30.67 +        ret.add(l);
   30.68 +        
   30.69 +        for (Method m : arr) {
   30.70 +            Compare c = m.getAnnotation(Compare.class);
   30.71 +            if (c == null) {
   30.72 +                continue;
   30.73 +            }
   30.74 +            final Bck2BrwsrCase real = new Bck2BrwsrCase(m, 0, null);
   30.75 +            final Bck2BrwsrCase js = new Bck2BrwsrCase(m, 1, l);
   30.76 +            final Bck2BrwsrCase brwsr = new Bck2BrwsrCase(m, 2, l);
   30.77 +            
   30.78 +            ret.add(real);
   30.79 +            ret.add(js);
   30.80 +            ret.add(brwsr);
   30.81 +            
   30.82 +            ret.add(new CompareCase(m, real, js));
   30.83 +            ret.add(new CompareCase(m, real, brwsr));
   30.84 +        }
   30.85 +        return ret.toArray();
   30.86 +    }
   30.87 +
   30.88 +    /** Test that compares the previous results.
   30.89 +     * @throws Throwable 
   30.90 +     */
   30.91 +    @Test(dependsOnGroups = "run") public void compareResults() throws Throwable {
   30.92 +        Object v1 = first.value;
   30.93 +        Object v2 = second.value;
   30.94 +        if (v1 != null) {
   30.95 +            v1 = v1.toString();
   30.96 +        } else {
   30.97 +            v1 = "null";
   30.98 +        }
   30.99 +        Assert.assertEquals(v2, v1, "Comparing results");
  30.100 +    }
  30.101 +    
  30.102 +    /** Test name.
  30.103 +     * @return name of the tested method followed by a suffix
  30.104 +     */
  30.105 +    @Override
  30.106 +    public String getTestName() {
  30.107 +        return m.getName() + "[Compare " + second.typeName() + "]";
  30.108 +    }
  30.109 +    
  30.110 +    static StringBuilder dumpJS(CharSequence sb) throws IOException {
  30.111 +        File f = File.createTempFile("execution", ".js");
  30.112 +        try (FileWriter w = new FileWriter(f)) {
  30.113 +            w.append(sb);
  30.114 +        }
  30.115 +        return new StringBuilder(f.getPath());
  30.116 +    }
  30.117 +}
    31.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    31.2 +++ b/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/Launchers.java	Mon Dec 24 07:57:33 2012 +0100
    31.3 @@ -0,0 +1,67 @@
    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.vmtest.impl;
   31.22 +
   31.23 +import java.io.IOException;
   31.24 +import org.apidesign.bck2brwsr.launcher.Bck2BrwsrLauncher;
   31.25 +import org.apidesign.bck2brwsr.launcher.JSLauncher;
   31.26 +import org.apidesign.bck2brwsr.launcher.MethodInvocation;
   31.27 +import org.apidesign.vm4brwsr.Bck2Brwsr;
   31.28 +import org.testng.annotations.AfterGroups;
   31.29 +import org.testng.annotations.AfterSuite;
   31.30 +import org.testng.annotations.BeforeGroups;
   31.31 +import org.testng.annotations.BeforeSuite;
   31.32 +
   31.33 +/**
   31.34 + *
   31.35 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   31.36 + */
   31.37 +public final class Launchers {
   31.38 +    public static final Launchers INSTANCE = new Launchers();
   31.39 +    
   31.40 +    private JSLauncher jsl;
   31.41 +    private Bck2BrwsrLauncher brwsr;
   31.42 +    
   31.43 +    private Launchers() {
   31.44 +    }
   31.45 +
   31.46 +    @BeforeGroups("run")
   31.47 +    public void initializeLauncher() throws IOException {
   31.48 +        jsl = new JSLauncher();
   31.49 +        jsl.addClassLoader(Bck2Brwsr.class.getClassLoader());
   31.50 +        jsl.initialize();
   31.51 +        Bck2BrwsrLauncher l = new Bck2BrwsrLauncher();
   31.52 +        l.addClassLoader(Bck2Brwsr.class.getClassLoader());
   31.53 +        l.initialize();
   31.54 +        l.setTimeout(180000);
   31.55 +        brwsr = l;
   31.56 +    }
   31.57 +
   31.58 +    @AfterGroups("run")
   31.59 +    public void shutDownLauncher() throws IOException, InterruptedException {
   31.60 +        brwsr.shutdown();
   31.61 +    }
   31.62 +
   31.63 +    public MethodInvocation addMethod(Class<?> clazz, String name, boolean inBrwsr) throws IOException {
   31.64 +        if (!inBrwsr) {
   31.65 +            return jsl.addMethod(clazz, name);
   31.66 +        } else {
   31.67 +            return brwsr.addMethod(clazz, name);
   31.68 +        }
   31.69 +    }
   31.70 +}
    32.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    32.2 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareHashTest.java	Mon Dec 24 07:57:33 2012 +0100
    32.3 @@ -0,0 +1,46 @@
    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.tck;
   32.22 +
   32.23 +import org.apidesign.bck2brwsr.vmtest.Compare;
   32.24 +import org.apidesign.bck2brwsr.vmtest.VMTest;
   32.25 +import org.testng.annotations.Factory;
   32.26 +
   32.27 +/**
   32.28 + *
   32.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   32.30 + */
   32.31 +public class CompareHashTest {
   32.32 +    @Compare public int hashOfString() {
   32.33 +        return "Ahoj".hashCode();
   32.34 +    }
   32.35 +    
   32.36 +    @Compare public int hashRemainsYieldsZero() {
   32.37 +        Object o = new Object();
   32.38 +        return o.hashCode() - o.hashCode();
   32.39 +    }
   32.40 +    
   32.41 +    @Compare public int initializeInStatic() {
   32.42 +        return StaticUse.NON_NULL.hashCode() - StaticUse.NON_NULL.hashCode();
   32.43 +    }
   32.44 +    
   32.45 +    @Factory
   32.46 +    public static Object[] create() {
   32.47 +        return VMTest.create(CompareHashTest.class);
   32.48 +    }
   32.49 +}
    33.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    33.2 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareStringsTest.java	Mon Dec 24 07:57:33 2012 +0100
    33.3 @@ -0,0 +1,110 @@
    33.4 +/**
    33.5 + * Back 2 Browser Bytecode Translator
    33.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    33.7 + *
    33.8 + * This program is free software: you can redistribute it and/or modify
    33.9 + * it under the terms of the GNU General Public License as published by
   33.10 + * the Free Software Foundation, version 2 of the License.
   33.11 + *
   33.12 + * This program is distributed in the hope that it will be useful,
   33.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   33.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   33.15 + * GNU General Public License for more details.
   33.16 + *
   33.17 + * You should have received a copy of the GNU General Public License
   33.18 + * along with this program. Look for COPYING file in the top folder.
   33.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   33.20 + */
   33.21 +package org.apidesign.bck2brwsr.tck;
   33.22 +
   33.23 +import java.net.MalformedURLException;
   33.24 +import java.net.URL;
   33.25 +import org.apidesign.bck2brwsr.vmtest.Compare;
   33.26 +import org.apidesign.bck2brwsr.vmtest.VMTest;
   33.27 +import org.testng.annotations.Factory;
   33.28 +
   33.29 +/**
   33.30 + *
   33.31 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   33.32 + */
   33.33 +public class CompareStringsTest {
   33.34 +    @Compare public static Object compareURLs() throws MalformedURLException {
   33.35 +        return new URL("http://apidesign.org:8080/wiki/").toExternalForm().toString();
   33.36 +    }
   33.37 +    
   33.38 +    @Compare public String deleteLastTwoCharacters() {
   33.39 +        StringBuilder sb = new StringBuilder();
   33.40 +        sb.append("453.0");
   33.41 +        if (sb.toString().endsWith(".0")) {
   33.42 +            final int l = sb.length();
   33.43 +            sb.delete(l - 2, l);
   33.44 +        }
   33.45 +        return sb.toString().toString();
   33.46 +    }
   33.47 +    
   33.48 +    @Compare public String nameOfStringClass() throws Exception {
   33.49 +        return Class.forName("java.lang.String").getName();
   33.50 +    }
   33.51 +    @Compare public String nameOfArrayClass() throws Exception {
   33.52 +        return Class.forName("org.apidesign.bck2brwsr.tck.CompareHashTest").getName();
   33.53 +    }
   33.54 +    
   33.55 +    @Compare public String lowerHello() {
   33.56 +        return "HeLlO".toLowerCase();
   33.57 +    }
   33.58 +    
   33.59 +    @Compare public String lowerA() {
   33.60 +        return String.valueOf(Character.toLowerCase('A')).toString();
   33.61 +    }
   33.62 +    @Compare public String upperHello() {
   33.63 +        return "hello".toUpperCase();
   33.64 +    }
   33.65 +    
   33.66 +    @Compare public String upperA() {
   33.67 +        return String.valueOf(Character.toUpperCase('a')).toString();
   33.68 +    }
   33.69 +    
   33.70 +    @Compare public boolean matchRegExp() throws Exception {
   33.71 +        return "58038503".matches("\\d*");
   33.72 +    }
   33.73 +
   33.74 +    @Compare public boolean doesNotMatchRegExp() throws Exception {
   33.75 +        return "58038503GH".matches("\\d*");
   33.76 +    }
   33.77 +
   33.78 +    @Compare public boolean doesNotMatchRegExpFully() throws Exception {
   33.79 +        return "Hello".matches("Hell");
   33.80 +    }
   33.81 +    
   33.82 +    @Compare public String variousCharacterTests() throws Exception {
   33.83 +        StringBuilder sb = new StringBuilder();
   33.84 +        
   33.85 +        sb.append(Character.isUpperCase('a'));
   33.86 +        sb.append(Character.isUpperCase('A'));
   33.87 +        sb.append(Character.isLowerCase('a'));
   33.88 +        sb.append(Character.isLowerCase('A'));
   33.89 +        
   33.90 +        sb.append(Character.isLetter('A'));
   33.91 +        sb.append(Character.isLetterOrDigit('9'));
   33.92 +        sb.append(Character.isLetterOrDigit('A'));
   33.93 +        sb.append(Character.isLetter('0'));
   33.94 +        
   33.95 +        return sb.toString().toString();
   33.96 +    }
   33.97 +        
   33.98 +    @Compare
   33.99 +    public String nullFieldInitialized() {
  33.100 +        NullField nf = new NullField();
  33.101 +        return ("" + nf.name).toString();
  33.102 +    }
  33.103 +
  33.104 +    @Factory
  33.105 +    public static Object[] create() {
  33.106 +        return VMTest.create(CompareStringsTest.class);
  33.107 +    }
  33.108 +
  33.109 +    private static final class NullField {
  33.110 +
  33.111 +        String name;
  33.112 +    }
  33.113 +}
    34.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.2 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ReflectionTest.java	Mon Dec 24 07:57:33 2012 +0100
    34.3 @@ -0,0 +1,43 @@
    34.4 +/**
    34.5 + * Back 2 Browser Bytecode Translator
    34.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    34.7 + *
    34.8 + * This program is free software: you can redistribute it and/or modify
    34.9 + * it under the terms of the GNU General Public License as published by
   34.10 + * the Free Software Foundation, version 2 of the License.
   34.11 + *
   34.12 + * This program is distributed in the hope that it will be useful,
   34.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   34.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   34.15 + * GNU General Public License for more details.
   34.16 + *
   34.17 + * You should have received a copy of the GNU General Public License
   34.18 + * along with this program. Look for COPYING file in the top folder.
   34.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   34.20 + */
   34.21 +package org.apidesign.bck2brwsr.tck;
   34.22 +
   34.23 +import org.apidesign.bck2brwsr.vmtest.Compare;
   34.24 +import org.apidesign.bck2brwsr.vmtest.VMTest;
   34.25 +import org.testng.annotations.Factory;
   34.26 +
   34.27 +/**
   34.28 + *
   34.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   34.30 + */
   34.31 +public class ReflectionTest {
   34.32 +    @Compare public String intType() {
   34.33 +        return Integer.TYPE.toString();
   34.34 +    }
   34.35 +
   34.36 +    @Compare public String longClass() {
   34.37 +        return long.class.toString();
   34.38 +    }
   34.39 +    
   34.40 +    
   34.41 +    @Factory
   34.42 +    public static Object[] create() {
   34.43 +        return VMTest.create(ReflectionTest.class);
   34.44 +    }
   34.45 +    
   34.46 +}
    35.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    35.2 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/StaticUse.java	Mon Dec 24 07:57:33 2012 +0100
    35.3 @@ -0,0 +1,22 @@
    35.4 +/**
    35.5 + * Back 2 Browser Bytecode Translator
    35.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    35.7 + *
    35.8 + * This program is free software: you can redistribute it and/or modify
    35.9 + * it under the terms of the GNU General Public License as published by
   35.10 + * the Free Software Foundation, version 2 of the License.
   35.11 + *
   35.12 + * This program is distributed in the hope that it will be useful,
   35.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   35.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   35.15 + * GNU General Public License for more details.
   35.16 + *
   35.17 + * You should have received a copy of the GNU General Public License
   35.18 + * along with this program. Look for COPYING file in the top folder.
   35.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   35.20 + */
   35.21 +package org.apidesign.bck2brwsr.tck;
   35.22 +
   35.23 +class StaticUse {
   35.24 +    public static final Object NON_NULL = new Object();
   35.25 +}