# HG changeset patch # User Jaroslav Tulach # Date 1355830998 -3600 # Node ID 4e9d576780cad27137c9e3fef7e62d2d0059f0d8 # Parent 6f964a88e6c5af1fc9d04295a056f66c391f539b Turning the launcher into an API diff -r 6f964a88e6c5 -r 4e9d576780ca launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java --- a/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java Mon Dec 17 17:51:05 2012 +0100 +++ b/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java Tue Dec 18 12:43:18 2012 +0100 @@ -23,8 +23,13 @@ import java.io.OutputStream; import java.io.Writer; import java.net.URI; +import java.net.URISyntaxException; import java.net.URL; +import java.util.ArrayList; import java.util.Enumeration; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; import java.util.concurrent.CountDownLatch; import static org.apidesign.bck2brwsr.launcher.Bck2BrwsrLauncher.copyStream; import org.apidesign.vm4brwsr.Bck2Brwsr; @@ -40,39 +45,50 @@ * Lightweight server to launch Bck2Brwsr applications in real browser. */ public class Bck2BrwsrLauncher { + private Set loaders = new LinkedHashSet<>(); + private List methods = new ArrayList<>(); + + + public MethodInvocation addMethod(Class clazz, String method) { + loaders.add(clazz.getClassLoader()); + MethodInvocation c = new MethodInvocation(clazz.getName(), method); + methods.add(c); + return c; + } + + + public static void main( String[] args ) throws Exception { - final Case[] cases = { - new Case("org.apidesign.bck2brwsr.launcher.Console", "welcome"), - new Case("org.apidesign.bck2brwsr.launcher.Console", "multiply") + Bck2BrwsrLauncher l = new Bck2BrwsrLauncher(); + + final MethodInvocation[] cases = { + l.addMethod(Console.class, "welcome"), + l.addMethod(Console.class, "multiply"), }; + + l.execute(); + + for (MethodInvocation c : cases) { + System.err.println(c.className + "." + c.methodName + " = " + c.result); + } + } + + + public void execute() throws URISyntaxException, IOException, InterruptedException { final CountDownLatch wait = new CountDownLatch(1); + final MethodInvocation[] cases = this.methods.toArray(new MethodInvocation[0]); HttpServer server = HttpServer.createSimpleServer(".", new PortRange(8080, 65535)); - final ClassLoader loader = Bck2BrwsrLauncher.class.getClassLoader(); + + Res resources = new Res(); final ServerConfiguration conf = server.getServerConfiguration(); conf.addHttpHandler(new Page("console.xhtml", "org.apidesign.bck2brwsr.launcher.Console", "welcome", "false" ), "/console"); - conf.addHttpHandler(new VM(loader), "/bck2brwsr.js"); + conf.addHttpHandler(new VM(resources), "/bck2brwsr.js"); conf.addHttpHandler(new VMInit(), "/vm.js"); - conf.addHttpHandler(new Classes(loader), "/classes/"); - conf.addHttpHandler(new HttpHandler() { - @Override - public void service(Request request, Response response) throws Exception { - String clazz = request.getParameter("class"); - String method = request.getParameter("method"); - if (clazz == null || method == null) { - response.setError(); - response.setDetailMessage("Need two parameters: class and method name!"); - return; - } - response.setContentType("text/html"); - OutputStream os = response.getOutputStream(); - InputStream is = Bck2BrwsrLauncher.class.getResourceAsStream("console.xhtml"); - copyStream(is, os, clazz, method, "true"); - } - }, "/"); + conf.addHttpHandler(new Classes(resources), "/classes/"); conf.addHttpHandler(new HttpHandler() { int cnt; @Override @@ -99,7 +115,7 @@ cnt++; } }, "/data"); - conf.addHttpHandler(new Page("harness.xhtml"), "/execute"); + conf.addHttpHandler(new Page("harness.xhtml"), "/"); server.start(); NetworkListener listener = server.getListeners().iterator().next(); @@ -116,10 +132,6 @@ } wait.await(); - - for (Case c : cases) { - System.err.println(c.className + "." + c.methodName + " = " + c.result); - } } static void copyStream(InputStream is, OutputStream os, String baseURL, String... params) throws IOException { @@ -141,6 +153,23 @@ } } } + + private class Res implements Bck2Brwsr.Resources { + @Override + public InputStream get(String resource) throws IOException { + for (ClassLoader l : loaders) { + URL u = null; + Enumeration en = l.getResources(resource); + while (en.hasMoreElements()) { + u = en.nextElement(); + } + if (u != null) { + return u.openStream(); + } + } + throw new IOException("Can't find " + resource); + } + } private static class Page extends HttpHandler { private final String resource; @@ -161,9 +190,9 @@ } private static class VM extends HttpHandler { - private final ClassLoader loader; + private final Res loader; - public VM(ClassLoader loader) { + public VM(Res loader) { this.loader = loader; } @@ -195,9 +224,9 @@ } private static class Classes extends HttpHandler { - private final ClassLoader loader; + private final Res loader; - public Classes(ClassLoader loader) { + public Classes(Res loader) { this.loader = loader; } @@ -207,47 +236,47 @@ if (res.startsWith("/")) { res = res.substring(1); } - Enumeration en = loader.getResources(res); - URL u = null; - while (en.hasMoreElements()) { - u = en.nextElement(); + try (InputStream is = loader.get(res)) { + response.setContentType("text/javascript"); + Writer w = response.getWriter(); + w.append("["); + for (int i = 0;; i++) { + int b = is.read(); + if (b == -1) { + break; + } + if (i > 0) { + w.append(", "); + } + if (i % 20 == 0) { + w.write("\n"); + } + if (b > 127) { + b = b - 256; + } + w.append(Integer.toString(b)); + } + w.append("\n]"); + } catch (IOException ex) { + response.setError(); + response.setDetailMessage(ex.getMessage()); } - if (u == null) { - response.setError(); - response.setDetailMessage("Can't find resource " + res); - } - response.setContentType("text/javascript"); - InputStream is = u.openStream(); - Writer w = response.getWriter(); - w.append("["); - for (int i = 0;; i++) { - int b = is.read(); - if (b == -1) { - break; - } - if (i > 0) { - w.append(", "); - } - if (i % 20 == 0) { - w.write("\n"); - } - if (b > 127) { - b = b - 256; - } - w.append(Integer.toString(b)); - } - w.append("\n]"); } } - private static final class Case { + public static final class MethodInvocation { final String className; final String methodName; String result; - public Case(String className, String methodName) { + MethodInvocation(String className, String methodName) { this.className = className; this.methodName = methodName; } + + @Override + public String toString() { + return result; + } } }