1.1 --- a/javaquery/demo-calculator/nbactions.xml Thu Dec 20 11:03:34 2012 +0100
1.2 +++ b/javaquery/demo-calculator/nbactions.xml Thu Dec 20 16:17:31 2012 +0100
1.3 @@ -23,7 +23,7 @@
1.4 <actionName>run</actionName>
1.5 <goals>
1.6 <goal>process-classes</goal>
1.7 - <goal>org.codehaus.mojo:exec-maven-plugin:1.2.1:exec</goal>
1.8 + <goal>org.apidesign.bck2brwsr:mojo:0.3-SNAPSHOT:brwsr</goal>
1.9 </goals>
1.10 </action>
1.11 </actions>
2.1 --- a/javaquery/demo-calculator/pom.xml Thu Dec 20 11:03:34 2012 +0100
2.2 +++ b/javaquery/demo-calculator/pom.xml Thu Dec 20 16:17:31 2012 +0100
2.3 @@ -16,34 +16,19 @@
2.4 </properties>
2.5 <build>
2.6 <plugins>
2.7 - <plugin>
2.8 - <groupId>org.apidesign.bck2brwsr</groupId>
2.9 - <artifactId>mojo</artifactId>
2.10 - <version>0.3-SNAPSHOT</version>
2.11 - <executions>
2.12 - <execution>
2.13 - <goals>
2.14 - <goal>j2js</goal>
2.15 - </goals>
2.16 - </execution>
2.17 - </executions>
2.18 - </plugin>
2.19 <plugin>
2.20 - <groupId>org.codehaus.mojo</groupId>
2.21 - <artifactId>exec-maven-plugin</artifactId>
2.22 - <version>1.2.1</version>
2.23 + <groupId>org.apidesign.bck2brwsr</groupId>
2.24 + <artifactId>mojo</artifactId>
2.25 + <version>0.3-SNAPSHOT</version>
2.26 <executions>
2.27 <execution>
2.28 <goals>
2.29 - <goal>exec</goal>
2.30 + <goal>brwsr</goal>
2.31 </goals>
2.32 </execution>
2.33 </executions>
2.34 <configuration>
2.35 - <executable>xdg-open</executable>
2.36 - <arguments>
2.37 - <argument>${project.build.directory}/classes/org/apidesign/bck2brwsr/mavenhtml/Calculator.xhtml</argument>
2.38 - </arguments>
2.39 + <startpage>org/apidesign/bck2brwsr/mavenhtml/Calculator.xhtml</startpage>
2.40 </configuration>
2.41 </plugin>
2.42 <plugin>
3.1 --- a/javaquery/demo-calculator/src/main/resources/org/apidesign/bck2brwsr/mavenhtml/Calculator.xhtml Thu Dec 20 11:03:34 2012 +0100
3.2 +++ b/javaquery/demo-calculator/src/main/resources/org/apidesign/bck2brwsr/mavenhtml/Calculator.xhtml Thu Dec 20 16:17:31 2012 +0100
3.3 @@ -77,7 +77,11 @@
3.4 </tbody>
3.5 </table>
3.6
3.7 - <script src="bootjava.js"/>
3.8 + <script src="/bck2brwsr.js"></script>
3.9 + <script src="/vm.js"></script>
3.10 + <script type="text/javascript">
3.11 + vm.loadClass('org.apidesign.bck2brwsr.mavenhtml.Calculator').class__V();
3.12 + </script>
3.13
3.14 <hr/>
3.15 <pre>
4.1 --- a/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java Thu Dec 20 11:03:34 2012 +0100
4.2 +++ b/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java Thu Dec 20 16:17:31 2012 +0100
4.3 @@ -33,8 +33,6 @@
4.4 import java.util.Set;
4.5 import java.util.concurrent.CountDownLatch;
4.6 import java.util.concurrent.TimeUnit;
4.7 -import java.util.logging.Level;
4.8 -import java.util.logging.Logger;
4.9 import javax.script.Invocable;
4.10 import javax.script.ScriptEngine;
4.11 import javax.script.ScriptEngineManager;
4.12 @@ -50,13 +48,17 @@
4.13 import org.glassfish.grizzly.http.server.ServerConfiguration;
4.14
4.15 /**
4.16 - * Lightweight server to launch Bck2Brwsr applications in real browser.
4.17 + * Lightweight server to launch Bck2Brwsr applications and tests.
4.18 + * Supports execution in native browser as well as Java's internal
4.19 + * execution engine.
4.20 */
4.21 public class Bck2BrwsrLauncher {
4.22 private Set<ClassLoader> loaders = new LinkedHashSet<>();
4.23 private List<MethodInvocation> methods = new ArrayList<>();
4.24 private long timeOut;
4.25 private String sen;
4.26 + private String showURL;
4.27 + private final Res resources = new Res();
4.28
4.29
4.30 public MethodInvocation addMethod(Class<?> clazz, String method) {
4.31 @@ -73,20 +75,24 @@
4.32 public void setScriptEngineName(String sen) {
4.33 this.sen = sen;
4.34 }
4.35 +
4.36 + public void setStartPage(String startpage) {
4.37 + if (!startpage.startsWith("/")) {
4.38 + startpage = "/" + startpage;
4.39 + }
4.40 + this.showURL = startpage;
4.41 + }
4.42 +
4.43 + public void addClassLoader(ClassLoader url) {
4.44 + this.loaders.add(url);
4.45 + }
4.46
4.47 public static void main( String[] args ) throws Exception {
4.48 Bck2BrwsrLauncher l = new Bck2BrwsrLauncher();
4.49 -
4.50 - final MethodInvocation[] cases = {
4.51 - l.addMethod(Console.class, "welcome"),
4.52 - l.addMethod(Console.class, "multiply"),
4.53 - };
4.54 -
4.55 + l.setStartPage("org/apidesign/bck2brwsr/launcher/console.xhtml");
4.56 + l.addClassLoader(Bck2BrwsrLauncher.class.getClassLoader());
4.57 l.execute();
4.58 -
4.59 - for (MethodInvocation c : cases) {
4.60 - System.err.println(c.className + "." + c.methodName + " = " + c.result);
4.61 - }
4.62 + System.in.read();
4.63 }
4.64
4.65
4.66 @@ -94,6 +100,10 @@
4.67 try {
4.68 if (sen != null) {
4.69 executeRhino();
4.70 + } else if (showURL != null) {
4.71 + HttpServer server = initServer();
4.72 + server.getServerConfiguration().addHttpHandler(new Page(resources, null), "/");
4.73 + launchServerAndBrwsr(server, showURL);
4.74 } else {
4.75 executeInBrowser();
4.76 }
4.77 @@ -142,21 +152,29 @@
4.78 }
4.79 }
4.80
4.81 - private void executeInBrowser() throws InterruptedException, URISyntaxException, IOException {
4.82 - final CountDownLatch wait = new CountDownLatch(1);
4.83 - final MethodInvocation[] cases = this.methods.toArray(new MethodInvocation[0]);
4.84 -
4.85 + private HttpServer initServer() {
4.86 HttpServer server = HttpServer.createSimpleServer(".", new PortRange(8080, 65535));
4.87 -
4.88 - Res resources = new Res();
4.89 -
4.90 +
4.91 final ServerConfiguration conf = server.getServerConfiguration();
4.92 - conf.addHttpHandler(new Page("console.xhtml",
4.93 + conf.addHttpHandler(new Page(resources,
4.94 + "org/apidesign/bck2brwsr/launcher/console.xhtml",
4.95 "org.apidesign.bck2brwsr.launcher.Console", "welcome", "false"
4.96 ), "/console");
4.97 conf.addHttpHandler(new VM(resources), "/bck2brwsr.js");
4.98 conf.addHttpHandler(new VMInit(), "/vm.js");
4.99 conf.addHttpHandler(new Classes(resources), "/classes/");
4.100 + return server;
4.101 + }
4.102 +
4.103 + private void executeInBrowser() throws InterruptedException, URISyntaxException, IOException {
4.104 + final CountDownLatch wait = new CountDownLatch(1);
4.105 + final MethodInvocation[] cases = this.methods.toArray(new MethodInvocation[0]);
4.106 +
4.107 + HttpServer server = initServer();
4.108 + ServerConfiguration conf = server.getServerConfiguration();
4.109 + conf.addHttpHandler(new Page(resources,
4.110 + "org/apidesign/bck2brwsr/launcher/harness.xhtml"
4.111 + ), "/execute");
4.112 conf.addHttpHandler(new HttpHandler() {
4.113 int cnt;
4.114 @Override
4.115 @@ -183,21 +201,8 @@
4.116 cnt++;
4.117 }
4.118 }, "/data");
4.119 - conf.addHttpHandler(new Page("harness.xhtml"), "/");
4.120 -
4.121 - server.start();
4.122 - NetworkListener listener = server.getListeners().iterator().next();
4.123 - int port = listener.getPort();
4.124 -
4.125 - URI uri = new URI("http://localhost:" + port + "/execute");
4.126 - try {
4.127 - Desktop.getDesktop().browse(uri);
4.128 - } catch (UnsupportedOperationException ex) {
4.129 - String[] cmd = {
4.130 - "xdg-open", uri.toString()
4.131 - };
4.132 - Runtime.getRuntime().exec(cmd).waitFor();
4.133 - }
4.134 +
4.135 + launchServerAndBrwsr(server, "/execute");
4.136
4.137 wait.await(timeOut, TimeUnit.MILLISECONDS);
4.138 server.stop();
4.139 @@ -223,6 +228,23 @@
4.140 }
4.141 }
4.142
4.143 + private void launchServerAndBrwsr(HttpServer server, final String page) throws IOException, URISyntaxException, InterruptedException {
4.144 + server.start();
4.145 + NetworkListener listener = server.getListeners().iterator().next();
4.146 + int port = listener.getPort();
4.147 +
4.148 + URI uri = new URI("http://localhost:" + port + page);
4.149 + try {
4.150 + Desktop.getDesktop().browse(uri);
4.151 + } catch (UnsupportedOperationException ex) {
4.152 + String[] cmd = {
4.153 + "xdg-open", uri.toString()
4.154 + };
4.155 + Runtime.getRuntime().exec(cmd).waitFor();
4.156 + }
4.157 + System.err.println("Showing " + uri);
4.158 + }
4.159 +
4.160 private class Res implements Bck2Brwsr.Resources {
4.161 @Override
4.162 public InputStream get(String resource) throws IOException {
4.163 @@ -243,18 +265,34 @@
4.164 private static class Page extends HttpHandler {
4.165 private final String resource;
4.166 private final String[] args;
4.167 + private final Res res;
4.168
4.169 - public Page(String resource, String... args) {
4.170 + public Page(Res res, String resource, String... args) {
4.171 + this.res = res;
4.172 this.resource = resource;
4.173 this.args = args;
4.174 }
4.175
4.176 @Override
4.177 public void service(Request request, Response response) throws Exception {
4.178 - response.setContentType("text/html");
4.179 + String r = resource;
4.180 + if (r == null) {
4.181 + r = request.getHttpHandlerPath();
4.182 + if (r.startsWith("/")) {
4.183 + r = r.substring(1);
4.184 + }
4.185 + }
4.186 + if (r.endsWith(".html") || r.endsWith(".xhtml")) {
4.187 + response.setContentType("text/html");
4.188 + }
4.189 OutputStream os = response.getOutputStream();
4.190 - InputStream is = Bck2BrwsrLauncher.class.getResourceAsStream(resource);
4.191 - copyStream(is, os, request.getRequestURL().toString(), args);
4.192 + try (InputStream is = res.get(r)) {
4.193 + copyStream(is, os, request.getRequestURL().toString(), args);
4.194 + } catch (IOException ex) {
4.195 + response.setDetailMessage(ex.getLocalizedMessage());
4.196 + response.setError();
4.197 + response.setStatus(404);
4.198 + }
4.199 }
4.200 }
4.201
4.202 @@ -283,7 +321,7 @@
4.203 response.getWriter().append(
4.204 "function ldCls(res) {\n"
4.205 + " var request = new XMLHttpRequest();\n"
4.206 - + " request.open('GET', 'classes/' + res, false);\n"
4.207 + + " request.open('GET', '/classes/' + res, false);\n"
4.208 + " request.send();\n"
4.209 + " var arr = eval('(' + request.responseText + ')');\n"
4.210 + " return arr;\n"
5.1 --- a/mojo/pom.xml Thu Dec 20 11:03:34 2012 +0100
5.2 +++ b/mojo/pom.xml Thu Dec 20 16:17:31 2012 +0100
5.3 @@ -77,5 +77,10 @@
5.4 <version>3.0.2</version>
5.5 <type>jar</type>
5.6 </dependency>
5.7 + <dependency>
5.8 + <groupId>${project.groupId}</groupId>
5.9 + <artifactId>launcher</artifactId>
5.10 + <version>${project.version}</version>
5.11 + </dependency>
5.12 </dependencies>
5.13 </project>
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/mojo/src/main/java/org/apidesign/bck2brwsr/mojo/BrswrMojo.java Thu Dec 20 16:17:31 2012 +0100
6.3 @@ -0,0 +1,114 @@
6.4 +/**
6.5 + * Back 2 Browser Bytecode Translator
6.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
6.7 + *
6.8 + * This program is free software: you can redistribute it and/or modify
6.9 + * it under the terms of the GNU General Public License as published by
6.10 + * the Free Software Foundation, version 2 of the License.
6.11 + *
6.12 + * This program is distributed in the hope that it will be useful,
6.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
6.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6.15 + * GNU General Public License for more details.
6.16 + *
6.17 + * You should have received a copy of the GNU General Public License
6.18 + * along with this program. Look for COPYING file in the top folder.
6.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
6.20 + */
6.21 +package org.apidesign.bck2brwsr.mojo;
6.22 +
6.23 +import org.apache.maven.plugin.AbstractMojo;
6.24 +
6.25 +import java.io.File;
6.26 +import java.io.FileWriter;
6.27 +import java.io.IOException;
6.28 +import java.net.MalformedURLException;
6.29 +import java.net.URL;
6.30 +import java.net.URLClassLoader;
6.31 +import java.util.ArrayList;
6.32 +import java.util.Collection;
6.33 +import java.util.List;
6.34 +import org.apache.maven.artifact.Artifact;
6.35 +import org.apache.maven.plugin.MojoExecutionException;
6.36 +import org.apache.maven.plugins.annotations.LifecyclePhase;
6.37 +import org.apache.maven.plugins.annotations.Mojo;
6.38 +import org.apache.maven.plugins.annotations.Parameter;
6.39 +import org.apache.maven.project.MavenProject;
6.40 +import org.apidesign.bck2brwsr.launcher.Bck2BrwsrLauncher;
6.41 +import org.apidesign.vm4brwsr.Bck2Brwsr;
6.42 +
6.43 +/** Executes given HTML page in a browser. */
6.44 +@Mojo(name="brwsr", defaultPhase=LifecyclePhase.DEPLOY)
6.45 +public class BrswrMojo extends AbstractMojo {
6.46 + public BrswrMojo() {
6.47 + }
6.48 + /** Resource to show as initial page */
6.49 + @Parameter
6.50 + private String startpage;
6.51 +
6.52 + @Parameter(defaultValue="${project}")
6.53 + private MavenProject prj;
6.54 +
6.55 + /** Root of the class files */
6.56 + @Parameter(defaultValue="${project.build.directory}/classes")
6.57 + private File classes;
6.58 +
6.59 + @Override
6.60 + public void execute() throws MojoExecutionException {
6.61 + if (startpage == null) {
6.62 + throw new MojoExecutionException("You have to provide a start page");
6.63 + }
6.64 +
6.65 + try {
6.66 + URLClassLoader url = buildClassLoader(classes, prj.getDependencyArtifacts());
6.67 +
6.68 + Bck2BrwsrLauncher httpServer = new Bck2BrwsrLauncher();
6.69 + httpServer.setStartPage(startpage);
6.70 + httpServer.addClassLoader(url);
6.71 + httpServer.execute();
6.72 +
6.73 + System.in.read();
6.74 + } catch (IOException ex) {
6.75 + throw new MojoExecutionException("Can't show the browser", ex);
6.76 + }
6.77 + }
6.78 +
6.79 + private static File findNonEmptyFolder(File dir) throws MojoExecutionException {
6.80 + if (!dir.isDirectory()) {
6.81 + throw new MojoExecutionException("Not a directory " + dir);
6.82 + }
6.83 + File[] arr = dir.listFiles();
6.84 + if (arr.length == 1 && arr[0].isDirectory()) {
6.85 + return findNonEmptyFolder(arr[0]);
6.86 + }
6.87 + return dir;
6.88 + }
6.89 +
6.90 + private static long collectAllClasses(String prefix, File toCheck, List<String> arr) {
6.91 + File[] files = toCheck.listFiles();
6.92 + if (files != null) {
6.93 + long newest = 0L;
6.94 + for (File f : files) {
6.95 + long lastModified = collectAllClasses(prefix + f.getName() + "/", f, arr);
6.96 + if (newest < lastModified) {
6.97 + newest = lastModified;
6.98 + }
6.99 + }
6.100 + return newest;
6.101 + } else if (toCheck.getName().endsWith(".class")) {
6.102 + arr.add(prefix.substring(0, prefix.length() - 7));
6.103 + return toCheck.lastModified();
6.104 + } else {
6.105 + return 0L;
6.106 + }
6.107 + }
6.108 +
6.109 + private static URLClassLoader buildClassLoader(File root, Collection<Artifact> deps) throws MalformedURLException {
6.110 + List<URL> arr = new ArrayList<URL>();
6.111 + arr.add(root.toURI().toURL());
6.112 + for (Artifact a : deps) {
6.113 + arr.add(a.getFile().toURI().toURL());
6.114 + }
6.115 + return new URLClassLoader(arr.toArray(new URL[0]), BrswrMojo.class.getClassLoader());
6.116 + }
6.117 +}