Turning the launcher into an API launcher
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Tue, 18 Dec 2012 12:43:18 +0100
branchlauncher
changeset 3484e9d576780ca
parent 347 6f964a88e6c5
child 349 3fe5a86bd123
Turning the launcher into an API
launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java
     1.1 --- a/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java	Mon Dec 17 17:51:05 2012 +0100
     1.2 +++ b/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java	Tue Dec 18 12:43:18 2012 +0100
     1.3 @@ -23,8 +23,13 @@
     1.4  import java.io.OutputStream;
     1.5  import java.io.Writer;
     1.6  import java.net.URI;
     1.7 +import java.net.URISyntaxException;
     1.8  import java.net.URL;
     1.9 +import java.util.ArrayList;
    1.10  import java.util.Enumeration;
    1.11 +import java.util.LinkedHashSet;
    1.12 +import java.util.List;
    1.13 +import java.util.Set;
    1.14  import java.util.concurrent.CountDownLatch;
    1.15  import static org.apidesign.bck2brwsr.launcher.Bck2BrwsrLauncher.copyStream;
    1.16  import org.apidesign.vm4brwsr.Bck2Brwsr;
    1.17 @@ -40,39 +45,50 @@
    1.18   * Lightweight server to launch Bck2Brwsr applications in real browser.
    1.19   */
    1.20  public class Bck2BrwsrLauncher {
    1.21 +    private Set<ClassLoader> loaders = new LinkedHashSet<>();
    1.22 +    private List<MethodInvocation> methods = new ArrayList<>();
    1.23 +    
    1.24 +    
    1.25 +    public MethodInvocation addMethod(Class<?> clazz, String method) {
    1.26 +        loaders.add(clazz.getClassLoader());
    1.27 +        MethodInvocation c = new MethodInvocation(clazz.getName(), method);
    1.28 +        methods.add(c);
    1.29 +        return c;
    1.30 +    }
    1.31 +    
    1.32 +    
    1.33 +    
    1.34      public static void main( String[] args ) throws Exception {
    1.35 -        final Case[] cases = { 
    1.36 -            new Case("org.apidesign.bck2brwsr.launcher.Console", "welcome"),
    1.37 -            new Case("org.apidesign.bck2brwsr.launcher.Console", "multiply")
    1.38 +        Bck2BrwsrLauncher l = new Bck2BrwsrLauncher();
    1.39 +        
    1.40 +        final MethodInvocation[] cases = { 
    1.41 +            l.addMethod(Console.class, "welcome"),
    1.42 +            l.addMethod(Console.class, "multiply"),
    1.43          };
    1.44 +        
    1.45 +        l.execute();
    1.46 +        
    1.47 +        for (MethodInvocation c : cases) {
    1.48 +            System.err.println(c.className + "." + c.methodName + " = " + c.result);
    1.49 +        }
    1.50 +    }
    1.51 +
    1.52 +
    1.53 +    public void execute() throws URISyntaxException, IOException, InterruptedException {
    1.54          final CountDownLatch wait = new CountDownLatch(1);
    1.55 +        final MethodInvocation[] cases = this.methods.toArray(new MethodInvocation[0]);
    1.56          
    1.57          HttpServer server = HttpServer.createSimpleServer(".", new PortRange(8080, 65535));
    1.58 -        final ClassLoader loader = Bck2BrwsrLauncher.class.getClassLoader();
    1.59 +        
    1.60 +        Res resources = new Res();
    1.61          
    1.62          final ServerConfiguration conf = server.getServerConfiguration();
    1.63          conf.addHttpHandler(new Page("console.xhtml", 
    1.64              "org.apidesign.bck2brwsr.launcher.Console", "welcome", "false"
    1.65          ), "/console");
    1.66 -        conf.addHttpHandler(new VM(loader), "/bck2brwsr.js");
    1.67 +        conf.addHttpHandler(new VM(resources), "/bck2brwsr.js");
    1.68          conf.addHttpHandler(new VMInit(), "/vm.js");
    1.69 -        conf.addHttpHandler(new Classes(loader), "/classes/");
    1.70 -        conf.addHttpHandler(new HttpHandler() {
    1.71 -            @Override
    1.72 -            public void service(Request request, Response response) throws Exception {
    1.73 -                String clazz = request.getParameter("class");
    1.74 -                String method = request.getParameter("method");
    1.75 -                if (clazz == null || method == null) {
    1.76 -                    response.setError();
    1.77 -                    response.setDetailMessage("Need two parameters: class and method name!");
    1.78 -                    return;
    1.79 -                }
    1.80 -                response.setContentType("text/html");
    1.81 -                OutputStream os = response.getOutputStream();
    1.82 -                InputStream is = Bck2BrwsrLauncher.class.getResourceAsStream("console.xhtml");
    1.83 -                copyStream(is, os, clazz, method, "true");
    1.84 -            }
    1.85 -        }, "/");
    1.86 +        conf.addHttpHandler(new Classes(resources), "/classes/");
    1.87          conf.addHttpHandler(new HttpHandler() {
    1.88              int cnt;
    1.89              @Override
    1.90 @@ -99,7 +115,7 @@
    1.91                  cnt++;
    1.92              }
    1.93          }, "/data");
    1.94 -        conf.addHttpHandler(new Page("harness.xhtml"), "/execute");
    1.95 +        conf.addHttpHandler(new Page("harness.xhtml"), "/");
    1.96          
    1.97          server.start();
    1.98          NetworkListener listener = server.getListeners().iterator().next();
    1.99 @@ -116,10 +132,6 @@
   1.100          }
   1.101          
   1.102          wait.await();
   1.103 -        
   1.104 -        for (Case c : cases) {
   1.105 -            System.err.println(c.className + "." + c.methodName + " = " + c.result);
   1.106 -        }
   1.107      }
   1.108      
   1.109      static void copyStream(InputStream is, OutputStream os, String baseURL, String... params) throws IOException {
   1.110 @@ -141,6 +153,23 @@
   1.111              }
   1.112          }
   1.113      }
   1.114 +    
   1.115 +    private class Res implements Bck2Brwsr.Resources {
   1.116 +        @Override
   1.117 +        public InputStream get(String resource) throws IOException {
   1.118 +            for (ClassLoader l : loaders) {
   1.119 +                URL u = null;
   1.120 +                Enumeration<URL> en = l.getResources(resource);
   1.121 +                while (en.hasMoreElements()) {
   1.122 +                    u = en.nextElement();
   1.123 +                }
   1.124 +                if (u != null) {
   1.125 +                    return u.openStream();
   1.126 +                }
   1.127 +            }
   1.128 +            throw new IOException("Can't find " + resource);
   1.129 +        }
   1.130 +    }
   1.131  
   1.132      private static class Page extends HttpHandler {
   1.133          private final String resource;
   1.134 @@ -161,9 +190,9 @@
   1.135      }
   1.136  
   1.137      private static class VM extends HttpHandler {
   1.138 -        private final ClassLoader loader;
   1.139 +        private final Res loader;
   1.140  
   1.141 -        public VM(ClassLoader loader) {
   1.142 +        public VM(Res loader) {
   1.143              this.loader = loader;
   1.144          }
   1.145  
   1.146 @@ -195,9 +224,9 @@
   1.147      }
   1.148  
   1.149      private static class Classes extends HttpHandler {
   1.150 -        private final ClassLoader loader;
   1.151 +        private final Res loader;
   1.152  
   1.153 -        public Classes(ClassLoader loader) {
   1.154 +        public Classes(Res loader) {
   1.155              this.loader = loader;
   1.156          }
   1.157  
   1.158 @@ -207,47 +236,47 @@
   1.159              if (res.startsWith("/")) {
   1.160                  res = res.substring(1);
   1.161              }
   1.162 -            Enumeration<URL> en = loader.getResources(res);
   1.163 -            URL u = null;
   1.164 -            while (en.hasMoreElements()) {
   1.165 -                u = en.nextElement();
   1.166 +            try (InputStream is = loader.get(res)) {
   1.167 +                response.setContentType("text/javascript");
   1.168 +                Writer w = response.getWriter();
   1.169 +                w.append("[");
   1.170 +                for (int i = 0;; i++) {
   1.171 +                    int b = is.read();
   1.172 +                    if (b == -1) {
   1.173 +                        break;
   1.174 +                    }
   1.175 +                    if (i > 0) {
   1.176 +                        w.append(", ");
   1.177 +                    }
   1.178 +                    if (i % 20 == 0) {
   1.179 +                        w.write("\n");
   1.180 +                    }
   1.181 +                    if (b > 127) {
   1.182 +                        b = b - 256;
   1.183 +                    }
   1.184 +                    w.append(Integer.toString(b));
   1.185 +                }
   1.186 +                w.append("\n]");
   1.187 +            } catch (IOException ex) {
   1.188 +                response.setError();
   1.189 +                response.setDetailMessage(ex.getMessage());
   1.190              }
   1.191 -            if (u == null) {
   1.192 -                response.setError();
   1.193 -                response.setDetailMessage("Can't find resource " + res);
   1.194 -            }
   1.195 -            response.setContentType("text/javascript");
   1.196 -            InputStream is = u.openStream();
   1.197 -            Writer w = response.getWriter();
   1.198 -            w.append("[");
   1.199 -            for (int i = 0;; i++) {
   1.200 -                int b = is.read();
   1.201 -                if (b == -1) {
   1.202 -                    break;
   1.203 -                }
   1.204 -                if (i > 0) {
   1.205 -                    w.append(", ");
   1.206 -                }
   1.207 -                if (i % 20 == 0) {
   1.208 -                    w.write("\n");
   1.209 -                }
   1.210 -                if (b > 127) {
   1.211 -                    b = b - 256;
   1.212 -                }
   1.213 -                w.append(Integer.toString(b));
   1.214 -            }
   1.215 -            w.append("\n]");
   1.216          }
   1.217      }
   1.218      
   1.219 -    private static final class Case {
   1.220 +    public static final class MethodInvocation {
   1.221          final String className;
   1.222          final String methodName;
   1.223          String result;
   1.224  
   1.225 -        public Case(String className, String methodName) {
   1.226 +        MethodInvocation(String className, String methodName) {
   1.227              this.className = className;
   1.228              this.methodName = methodName;
   1.229          }
   1.230 +
   1.231 +        @Override
   1.232 +        public String toString() {
   1.233 +            return result;
   1.234 +        }
   1.235      }
   1.236  }