1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/dew/src/main/java/org/apidesign/bck2brwsr/dew/DewLauncher.java Wed Jan 23 14:10:15 2013 +0100
1.3 @@ -0,0 +1,201 @@
1.4 +/**
1.5 + * Back 2 Browser Bytecode Translator
1.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
1.7 + *
1.8 + * This program is free software: you can redistribute it and/or modify
1.9 + * it under the terms of the GNU General Public License as published by
1.10 + * the Free Software Foundation, version 2 of the License.
1.11 + *
1.12 + * This program is distributed in the hope that it will be useful,
1.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.15 + * GNU General Public License for more details.
1.16 + *
1.17 + * You should have received a copy of the GNU General Public License
1.18 + * along with this program. Look for COPYING file in the top folder.
1.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
1.20 + */
1.21 +package org.apidesign.bck2brwsr.dew;
1.22 +
1.23 +import java.io.IOException;
1.24 +import java.io.InputStream;
1.25 +import java.io.Writer;
1.26 +import java.net.URI;
1.27 +import java.net.URISyntaxException;
1.28 +import java.net.URL;
1.29 +import java.util.Arrays;
1.30 +import java.util.Enumeration;
1.31 +import java.util.LinkedHashSet;
1.32 +import java.util.Set;
1.33 +import java.util.logging.Level;
1.34 +import java.util.logging.Logger;
1.35 +import org.apidesign.vm4brwsr.Bck2Brwsr;
1.36 +import org.glassfish.grizzly.PortRange;
1.37 +import org.glassfish.grizzly.http.server.HttpHandler;
1.38 +import org.glassfish.grizzly.http.server.HttpServer;
1.39 +import org.glassfish.grizzly.http.server.NetworkListener;
1.40 +import org.glassfish.grizzly.http.server.Request;
1.41 +import org.glassfish.grizzly.http.server.Response;
1.42 +import org.glassfish.grizzly.http.server.ServerConfiguration;
1.43 +
1.44 +/**
1.45 + * Lightweight server to launch dew - the Development Environment for Web.
1.46 + */
1.47 +final class DewLauncher {
1.48 + private static final Logger LOG = Logger.getLogger(DewLauncher.class.getName());
1.49 + private Set<ClassLoader> loaders = new LinkedHashSet<>();
1.50 + private Set<Bck2Brwsr.Resources> xRes = new LinkedHashSet<>();
1.51 + private final Res resources = new Res();
1.52 + private final String cmd;
1.53 +
1.54 + public DewLauncher(String cmd) {
1.55 + this.cmd = cmd;
1.56 + }
1.57 +
1.58 + public void addClassLoader(ClassLoader url) {
1.59 + this.loaders.add(url);
1.60 + }
1.61 +
1.62 + final HttpServer initServer(Bck2Brwsr.Resources... extraResources) {
1.63 + xRes.addAll(Arrays.asList(extraResources));
1.64 +
1.65 + HttpServer s = HttpServer.createSimpleServer(".", new PortRange(8080, 65535));
1.66 +
1.67 + final ServerConfiguration conf = s.getServerConfiguration();
1.68 + conf.addHttpHandler(new VM(resources), "/bck2brwsr.js");
1.69 + conf.addHttpHandler(new VMInit(), "/vm.js");
1.70 + conf.addHttpHandler(new Classes(resources), "/classes/");
1.71 + return s;
1.72 + }
1.73 +
1.74 + final Object[] launchServerAndBrwsr(HttpServer server, final String page) throws IOException, URISyntaxException, InterruptedException {
1.75 + server.start();
1.76 + NetworkListener listener = server.getListeners().iterator().next();
1.77 + int port = listener.getPort();
1.78 +
1.79 + URI uri = new URI("http://localhost:" + port + page);
1.80 + LOG.log(Level.INFO, "Showing {0}", uri);
1.81 + if (cmd == null) {
1.82 + try {
1.83 + LOG.log(Level.INFO, "Trying Desktop.browse on {0} {2} by {1}", new Object[] {
1.84 + System.getProperty("java.vm.name"),
1.85 + System.getProperty("java.vm.vendor"),
1.86 + System.getProperty("java.vm.version"),
1.87 + });
1.88 + java.awt.Desktop.getDesktop().browse(uri);
1.89 + LOG.log(Level.INFO, "Desktop.browse successfully finished");
1.90 + return null;
1.91 + } catch (UnsupportedOperationException ex) {
1.92 + LOG.log(Level.INFO, "Desktop.browse not supported: {0}", ex.getMessage());
1.93 + LOG.log(Level.FINE, null, ex);
1.94 + }
1.95 + }
1.96 + {
1.97 + String cmdName = cmd == null ? "xdg-open" : cmd;
1.98 + String[] cmdArr = {
1.99 + cmdName, uri.toString()
1.100 + };
1.101 + LOG.log(Level.INFO, "Launching {0}", Arrays.toString(cmdArr));
1.102 + final Process process = Runtime.getRuntime().exec(cmdArr);
1.103 + return new Object[] { process, null };
1.104 + }
1.105 + }
1.106 +
1.107 + private class Res implements Bck2Brwsr.Resources {
1.108 + @Override
1.109 + public InputStream get(String resource) throws IOException {
1.110 + for (ClassLoader l : loaders) {
1.111 + URL u = null;
1.112 + Enumeration<URL> en = l.getResources(resource);
1.113 + while (en.hasMoreElements()) {
1.114 + u = en.nextElement();
1.115 + }
1.116 + if (u != null) {
1.117 + return u.openStream();
1.118 + }
1.119 + }
1.120 + for (Bck2Brwsr.Resources r : xRes) {
1.121 + InputStream is = r.get(resource);
1.122 + if (is != null) {
1.123 + return is;
1.124 + }
1.125 + }
1.126 + throw new IOException("Can't find " + resource);
1.127 + }
1.128 + }
1.129 +
1.130 + private static class VM extends HttpHandler {
1.131 + private final Res loader;
1.132 +
1.133 + public VM(Res loader) {
1.134 + this.loader = loader;
1.135 + }
1.136 +
1.137 + @Override
1.138 + public void service(Request request, Response response) throws Exception {
1.139 + response.setCharacterEncoding("UTF-8");
1.140 + response.setContentType("text/javascript");
1.141 + Bck2Brwsr.generate(response.getWriter(), loader);
1.142 + }
1.143 + }
1.144 + private static class VMInit extends HttpHandler {
1.145 + public VMInit() {
1.146 + }
1.147 +
1.148 + @Override
1.149 + public void service(Request request, Response response) throws Exception {
1.150 + response.setCharacterEncoding("UTF-8");
1.151 + response.setContentType("text/javascript");
1.152 + response.getWriter().append(
1.153 + "function ldCls(res) {\n"
1.154 + + " var request = new XMLHttpRequest();\n"
1.155 + + " request.open('GET', '/classes/' + res, false);\n"
1.156 + + " request.send();\n"
1.157 + + " var arr = eval('(' + request.responseText + ')');\n"
1.158 + + " return arr;\n"
1.159 + + "}\n"
1.160 + + "var vm = new bck2brwsr(ldCls);\n");
1.161 + }
1.162 + }
1.163 +
1.164 + private static class Classes extends HttpHandler {
1.165 + private final Res loader;
1.166 +
1.167 + public Classes(Res loader) {
1.168 + this.loader = loader;
1.169 + }
1.170 +
1.171 + @Override
1.172 + public void service(Request request, Response response) throws Exception {
1.173 + String res = request.getHttpHandlerPath();
1.174 + if (res.startsWith("/")) {
1.175 + res = res.substring(1);
1.176 + }
1.177 + try (InputStream is = loader.get(res)) {
1.178 + response.setContentType("text/javascript");
1.179 + Writer w = response.getWriter();
1.180 + w.append("[");
1.181 + for (int i = 0;; i++) {
1.182 + int b = is.read();
1.183 + if (b == -1) {
1.184 + break;
1.185 + }
1.186 + if (i > 0) {
1.187 + w.append(", ");
1.188 + }
1.189 + if (i % 20 == 0) {
1.190 + w.write("\n");
1.191 + }
1.192 + if (b > 127) {
1.193 + b = b - 256;
1.194 + }
1.195 + w.append(Integer.toString(b));
1.196 + }
1.197 + w.append("\n]");
1.198 + } catch (IOException ex) {
1.199 + response.setError();
1.200 + response.setDetailMessage(ex.getMessage());
1.201 + }
1.202 + }
1.203 + }
1.204 +}