launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Sun, 16 Dec 2012 20:11:18 +0100
branchlauncher
changeset 332 6949044415df
parent 331 7328b7ba2fa4
child 342 60f9aad12731
permissions -rw-r--r--
First steps towards execution harness
     1 /**
     2  * Back 2 Browser Bytecode Translator
     3  * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     4  *
     5  * This program is free software: you can redistribute it and/or modify
     6  * it under the terms of the GNU General Public License as published by
     7  * the Free Software Foundation, version 2 of the License.
     8  *
     9  * This program is distributed in the hope that it will be useful,
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12  * GNU General Public License for more details.
    13  *
    14  * You should have received a copy of the GNU General Public License
    15  * along with this program. Look for COPYING file in the top folder.
    16  * If not, see http://opensource.org/licenses/GPL-2.0.
    17  */
    18 package org.apidesign.bck2brwsr.launcher;
    19 
    20 import java.awt.Desktop;
    21 import java.io.IOException;
    22 import java.io.InputStream;
    23 import java.io.OutputStream;
    24 import java.io.Writer;
    25 import java.net.URI;
    26 import java.net.URL;
    27 import java.util.Enumeration;
    28 import static org.apidesign.bck2brwsr.launcher.Bck2BrwsrLauncher.copyStream;
    29 import org.apidesign.vm4brwsr.Bck2Brwsr;
    30 import org.glassfish.grizzly.PortRange;
    31 import org.glassfish.grizzly.http.server.HttpHandler;
    32 import org.glassfish.grizzly.http.server.HttpServer;
    33 import org.glassfish.grizzly.http.server.NetworkListener;
    34 import org.glassfish.grizzly.http.server.Request;
    35 import org.glassfish.grizzly.http.server.Response;
    36 import org.glassfish.grizzly.http.server.ServerConfiguration;
    37 
    38 /**
    39  * Lightweight server to launch Bck2Brwsr applications in real browser.
    40  */
    41 public class Bck2BrwsrLauncher {
    42     public static void main( String[] args ) throws Exception {
    43         HttpServer server = HttpServer.createSimpleServer(".", new PortRange(8080, 65535));
    44         final ClassLoader loader = Bck2BrwsrLauncher.class.getClassLoader();
    45         
    46         final ServerConfiguration conf = server.getServerConfiguration();
    47         conf.addHttpHandler(new Page("console.xhtml", 
    48             "org.apidesign.bck2brwsr.launcher.Console", "welcome", "false"
    49         ), "/console");
    50         conf.addHttpHandler(new VM(loader), "/bck2brwsr.js");
    51         conf.addHttpHandler(new VMInit(), "/vm.js");
    52         conf.addHttpHandler(new Classes(loader), "/classes/");
    53         conf.addHttpHandler(new HttpHandler() {
    54             @Override
    55             public void service(Request request, Response response) throws Exception {
    56                 String clazz = request.getParameter("class");
    57                 String method = request.getParameter("method");
    58                 if (clazz == null || method == null) {
    59                     response.setError();
    60                     response.setDetailMessage("Need two parameters: class and method name!");
    61                     return;
    62                 }
    63                 response.setContentType("text/html");
    64                 OutputStream os = response.getOutputStream();
    65                 InputStream is = Bck2BrwsrLauncher.class.getResourceAsStream("console.xhtml");
    66                 copyStream(is, os, clazz, method, "true");
    67             }
    68         }, "/");
    69         conf.addHttpHandler(new HttpHandler() {
    70             int cnt;
    71             @Override
    72             public void service(Request request, Response response) throws Exception {
    73                 response.getWriter().write("{"
    74                     + "className: 'org.apidesign.bck2brwsr.launcher.Console',"
    75                     + "methodName: 'welcome',"
    76                     + "request: " + cnt
    77                     + "}");
    78             }
    79         }, "execute/data");
    80         conf.addHttpHandler(new Page("harness.xhtml"), "/execute");
    81         
    82         server.start();
    83         NetworkListener listener = server.getListeners().iterator().next();
    84         int port = listener.getPort();
    85         
    86         URI uri = new URI("http://localhost:" + port + "/execute");
    87         try {
    88             Desktop.getDesktop().browse(uri);
    89         } catch (UnsupportedOperationException ex) {
    90             String[] cmd = { 
    91                 "xdg-open", uri.toString()
    92             };
    93             Runtime.getRuntime().exec(cmd).waitFor();
    94         }
    95         
    96         System.in.read();
    97     }
    98     
    99     static void copyStream(InputStream is, OutputStream os, String... params) throws IOException {
   100         for (;;) {
   101             int ch = is.read();
   102             if (ch == -1) {
   103                 break;
   104             }
   105             if (ch == '$') {
   106                 int cnt = is.read() - '0';
   107                 if (cnt < params.length) {
   108                     os.write(params[cnt].getBytes());
   109                 }
   110             } else {
   111                 os.write(ch);
   112             }
   113         }
   114     }
   115 
   116     private static class Page extends HttpHandler {
   117         private final String resource;
   118         private final String[] args;
   119         
   120         public Page(String resource, String... args) {
   121             this.resource = resource;
   122             this.args = args;
   123         }
   124 
   125         @Override
   126         public void service(Request request, Response response) throws Exception {
   127             response.setContentType("text/html");
   128             OutputStream os = response.getOutputStream();
   129             InputStream is = Bck2BrwsrLauncher.class.getResourceAsStream(resource);
   130             copyStream(is, os, args);
   131         }
   132     }
   133 
   134     private static class VM extends HttpHandler {
   135         private final ClassLoader loader;
   136 
   137         public VM(ClassLoader loader) {
   138             this.loader = loader;
   139         }
   140 
   141         @Override
   142         public void service(Request request, Response response) throws Exception {
   143             response.setCharacterEncoding("UTF-8");
   144             response.setContentType("text/javascript");
   145             Bck2Brwsr.generate(response.getWriter(), loader);
   146         }
   147     }
   148     private static class VMInit extends HttpHandler {
   149         public VMInit() {
   150         }
   151 
   152         @Override
   153         public void service(Request request, Response response) throws Exception {
   154             response.setCharacterEncoding("UTF-8");
   155             response.setContentType("text/javascript");
   156             response.getWriter().append(
   157                 "function ldCls(res) {\n"
   158                 + "  var request = new XMLHttpRequest();\n"
   159                 + "  request.open('GET', 'classes/' + res, false);\n"
   160                 + "  request.send();\n"
   161                 + "  var arr = eval('(' + request.responseText + ')');\n"
   162                 + "  return arr;\n"
   163                 + "}\n"
   164                 + "var vm = new bck2brwsr(ldCls);\n");
   165         }
   166     }
   167 
   168     private static class Classes extends HttpHandler {
   169         private final ClassLoader loader;
   170 
   171         public Classes(ClassLoader loader) {
   172             this.loader = loader;
   173         }
   174 
   175         @Override
   176         public void service(Request request, Response response) throws Exception {
   177             String res = request.getHttpHandlerPath();
   178             if (res.startsWith("/")) {
   179                 res = res.substring(1);
   180             }
   181             Enumeration<URL> en = loader.getResources(res);
   182             URL u = null;
   183             while (en.hasMoreElements()) {
   184                 u = en.nextElement();
   185             }
   186             if (u == null) {
   187                 response.setError();
   188                 response.setDetailMessage("Can't find resource " + res);
   189             }
   190             response.setContentType("text/javascript");
   191             InputStream is = u.openStream();
   192             Writer w = response.getWriter();
   193             w.append("[");
   194             for (int i = 0;; i++) {
   195                 int b = is.read();
   196                 if (b == -1) {
   197                     break;
   198                 }
   199                 if (i > 0) {
   200                     w.append(", ");
   201                 }
   202                 if (i % 20 == 0) {
   203                     w.write("\n");
   204                 }
   205                 if (b > 127) {
   206                     b = b - 256;
   207                 }
   208                 w.append(Integer.toString(b));
   209             }
   210             w.append("\n]");
   211         }
   212     }
   213 }