launcher/http/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Mon, 28 Mar 2016 05:55:43 +0200
changeset 1914 88b00e03fc8f
parent 1787 ea12a3bb4b33
child 1920 6cfab6c60fba
permissions -rw-r--r--
Introducing vmtest.precompiled=<regexp> to verify that bck2brwsr generated resources are really used
     1 /**
     2  * Back 2 Browser Bytecode Translator
     3  * Copyright (C) 2012-2015 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.io.File;
    21 import java.io.IOException;
    22 import java.io.InputStreamReader;
    23 import java.io.Reader;
    24 import java.net.MalformedURLException;
    25 import java.net.URISyntaxException;
    26 import java.net.URL;
    27 import java.util.HashSet;
    28 import java.util.Set;
    29 import java.util.logging.Level;
    30 import java.util.regex.Pattern;
    31 
    32 /**
    33  * Lightweight server to launch Bck2Brwsr applications and tests.
    34  * Supports execution in native browser as well as Java's internal 
    35  * execution engine.
    36  */
    37 final class Bck2BrwsrLauncher extends BaseHTTPLauncher {
    38     private Set<String> testClasses = new HashSet<String>();
    39     
    40     public Bck2BrwsrLauncher(String cmd) {
    41         super(cmd);
    42     }
    43     
    44     @Override
    45     String harnessResource() {
    46         return "org/apidesign/bck2brwsr/launcher/harness.xhtml";
    47     }
    48 
    49     @Override
    50     Object compileJar(URL jar, URL precompiled) throws IOException {
    51         if (precompiled != null) {
    52             LOG.log(Level.INFO, "Found precompiled JAR version of {0} at {1}. Using.", new Object[]{jar, precompiled});
    53             return precompiled.openStream();
    54         }
    55         File f;
    56         try {
    57             f = new File(jar.toURI());
    58         } catch (URISyntaxException ex) {
    59             throw new IOException(ex);
    60         }
    61         final String precompile = System.getProperty("vmtest.precompiled");
    62         if (precompile != null && Pattern.compile(precompile).matcher(jar.toString()).find()) {
    63             throw new IOException("Compilation of " + jar + " forbidden");
    64         }
    65         LOG.log(Level.INFO, "No precompiled version for {0} found. Compiling.", jar);
    66         return CompileCP.compileJAR(f, testClasses);
    67     }
    68 
    69     @Override
    70     public InvocationContext createInvocation(Class<?> clazz, String method) {
    71         testClasses.add(clazz.getName().replace('.', '/'));
    72         return super.createInvocation(clazz, method);
    73     }
    74 
    75     @Override String compileFromClassPath(URL f, Res loader) throws IOException {
    76         return CompileCP.compileFromClassPath(f, loader);
    77     }
    78     
    79     @Override
    80     void generateBck2BrwsrJS(StringBuilder sb, final Res loader) throws IOException {
    81         String b2b = System.getProperty("bck2brwsr.js");
    82         if (b2b != null) {
    83             LOG.log(Level.INFO, "Serving bck2brwsr.js from {0}", b2b);
    84             URL bu;
    85             try {
    86                 bu = new URL(b2b);
    87             } catch (MalformedURLException ex) {
    88                 File f = new File(b2b);
    89                 if (f.exists()) {
    90                     bu = f.toURI().toURL();
    91                 } else {
    92                     throw ex;
    93                 }
    94             }
    95             try (Reader r = new InputStreamReader(bu.openStream())) {
    96                 char[] arr = new char[4096];
    97                 for (;;) {
    98                    int len = r.read(arr);
    99                    if (len == -1) {
   100                        break;
   101                    }
   102                    sb.append(arr, 0, len);
   103                 }
   104             }
   105         } else {
   106             LOG.log(Level.INFO, "Generating bck2brwsr.js from scratch", b2b);
   107             CompileCP.compileVM(sb, loader);
   108         }
   109         sb.append(
   110               "(function WrapperVM(global) {\n"
   111             + "  var cache = {};\n"
   112             + "  var empty = {};\n"
   113             + "  function ldCls(res, skip) {\n"
   114             + "    var c = cache[res];\n"
   115             + "    if (c) {\n"
   116             + "      if (c[skip] === empty) return null;\n"
   117             + "      if (c[skip]) return c[skip];\n"
   118             + "    } else {\n"
   119             + "      cache[res] = c = new Array();\n"
   120             + "    }\n"
   121             + "    var request = new XMLHttpRequest();\n"
   122             + "    request.open('GET', '/classes/' + res + '?skip=' + skip, false);\n"
   123             + "    request.send();\n"
   124             + "    if (request.status !== 200) {\n"
   125             + "      c[skip] = null;\n"
   126             + "      return null;\n"
   127             + "    }\n"
   128             + "    var arr = eval(request.responseText);\n"
   129             + "    if (arr === null) c[skip] = empty;\n"
   130             + "    else c[skip] = arr;\n"
   131             + "    return arr;\n"
   132             + "  }\n"
   133             + "  var prevvm = global.bck2brwsr;\n"
   134             + "  global.bck2brwsr = function() {\n"
   135             + "    var args = Array.prototype.slice.apply(arguments);\n"
   136             + "    args.unshift(ldCls);\n"
   137             + "    return prevvm.apply(null, args);\n"
   138             + "  };\n"
   139             + "  global.bck2brwsr.register = prevvm.register;\n"
   140             + "})(this);\n"
   141         );
   142         LOG.log(Level.INFO, "Serving bck2brwsr.js", b2b);
   143     }
   144 
   145 }