jaroslav@323: /** jaroslav@323: * Back 2 Browser Bytecode Translator jaroslav@323: * Copyright (C) 2012 Jaroslav Tulach jaroslav@323: * jaroslav@323: * This program is free software: you can redistribute it and/or modify jaroslav@323: * it under the terms of the GNU General Public License as published by jaroslav@323: * the Free Software Foundation, version 2 of the License. jaroslav@323: * jaroslav@323: * This program is distributed in the hope that it will be useful, jaroslav@323: * but WITHOUT ANY WARRANTY; without even the implied warranty of jaroslav@323: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the jaroslav@323: * GNU General Public License for more details. jaroslav@323: * jaroslav@323: * You should have received a copy of the GNU General Public License jaroslav@323: * along with this program. Look for COPYING file in the top folder. jaroslav@323: * If not, see http://opensource.org/licenses/GPL-2.0. jaroslav@323: */ jaroslav@546: package org.apidesign.bck2brwsr.dew; jaroslav@323: jaroslav@331: import java.io.IOException; jaroslav@323: import java.io.InputStream; jaroslav@323: import java.io.Writer; jaroslav@323: import java.net.URI; jaroslav@348: import java.net.URISyntaxException; jaroslav@323: import java.net.URL; jaroslav@361: import java.util.Arrays; jaroslav@323: import java.util.Enumeration; jaroslav@348: import java.util.LinkedHashSet; jaroslav@348: import java.util.Set; jaroslav@362: import java.util.logging.Level; jaroslav@362: import java.util.logging.Logger; jaroslav@323: import org.apidesign.vm4brwsr.Bck2Brwsr; jaroslav@323: import org.glassfish.grizzly.PortRange; jaroslav@323: import org.glassfish.grizzly.http.server.HttpHandler; jaroslav@323: import org.glassfish.grizzly.http.server.HttpServer; jaroslav@323: import org.glassfish.grizzly.http.server.NetworkListener; jaroslav@323: import org.glassfish.grizzly.http.server.Request; jaroslav@323: import org.glassfish.grizzly.http.server.Response; jaroslav@323: import org.glassfish.grizzly.http.server.ServerConfiguration; jaroslav@323: jaroslav@323: /** jaroslav@546: * Lightweight server to launch dew - the Development Environment for Web. jaroslav@323: */ jaroslav@546: final class DewLauncher { jaroslav@546: private static final Logger LOG = Logger.getLogger(DewLauncher.class.getName()); jaroslav@348: private Set loaders = new LinkedHashSet<>(); jaroslav@471: private Set xRes = new LinkedHashSet<>(); jaroslav@357: private final Res resources = new Res(); jaroslav@382: private final String cmd; jaroslav@382: jaroslav@546: public DewLauncher(String cmd) { jaroslav@382: this.cmd = cmd; jaroslav@382: } jaroslav@348: jaroslav@357: public void addClassLoader(ClassLoader url) { jaroslav@357: this.loaders.add(url); jaroslav@357: } jaroslav@348: jaroslav@546: final HttpServer initServer(Bck2Brwsr.Resources... extraResources) { jaroslav@546: xRes.addAll(Arrays.asList(extraResources)); jaroslav@546: jaroslav@371: HttpServer s = HttpServer.createSimpleServer(".", new PortRange(8080, 65535)); jaroslav@357: jaroslav@371: final ServerConfiguration conf = s.getServerConfiguration(); jaroslav@348: conf.addHttpHandler(new VM(resources), "/bck2brwsr.js"); jaroslav@332: conf.addHttpHandler(new VMInit(), "/vm.js"); jaroslav@348: conf.addHttpHandler(new Classes(resources), "/classes/"); jaroslav@371: return s; jaroslav@357: } jaroslav@357: jaroslav@546: final Object[] launchServerAndBrwsr(HttpServer server, final String page) throws IOException, URISyntaxException, InterruptedException { jaroslav@357: server.start(); jaroslav@357: NetworkListener listener = server.getListeners().iterator().next(); jaroslav@357: int port = listener.getPort(); jaroslav@357: jaroslav@357: URI uri = new URI("http://localhost:" + port + page); jaroslav@362: LOG.log(Level.INFO, "Showing {0}", uri); jaroslav@433: if (cmd == null) { jaroslav@433: try { jaroslav@536: LOG.log(Level.INFO, "Trying Desktop.browse on {0} {2} by {1}", new Object[] { jaroslav@536: System.getProperty("java.vm.name"), jaroslav@536: System.getProperty("java.vm.vendor"), jaroslav@536: System.getProperty("java.vm.version"), jaroslav@536: }); jaroslav@433: java.awt.Desktop.getDesktop().browse(uri); jaroslav@433: LOG.log(Level.INFO, "Desktop.browse successfully finished"); jaroslav@433: return null; jaroslav@433: } catch (UnsupportedOperationException ex) { jaroslav@518: LOG.log(Level.INFO, "Desktop.browse not supported: {0}", ex.getMessage()); jaroslav@518: LOG.log(Level.FINE, null, ex); jaroslav@433: } jaroslav@369: } jaroslav@369: { jaroslav@382: String cmdName = cmd == null ? "xdg-open" : cmd; jaroslav@382: String[] cmdArr = { jaroslav@382: cmdName, uri.toString() jaroslav@357: }; jaroslav@382: LOG.log(Level.INFO, "Launching {0}", Arrays.toString(cmdArr)); jaroslav@382: final Process process = Runtime.getRuntime().exec(cmdArr); jaroslav@369: return new Object[] { process, null }; jaroslav@357: } jaroslav@361: } jaroslav@382: jaroslav@348: private class Res implements Bck2Brwsr.Resources { jaroslav@348: @Override jaroslav@348: public InputStream get(String resource) throws IOException { jaroslav@348: for (ClassLoader l : loaders) { jaroslav@348: URL u = null; jaroslav@348: Enumeration en = l.getResources(resource); jaroslav@348: while (en.hasMoreElements()) { jaroslav@348: u = en.nextElement(); jaroslav@348: } jaroslav@348: if (u != null) { jaroslav@348: return u.openStream(); jaroslav@348: } jaroslav@348: } jaroslav@471: for (Bck2Brwsr.Resources r : xRes) { jaroslav@471: InputStream is = r.get(resource); jaroslav@471: if (is != null) { jaroslav@471: return is; jaroslav@471: } jaroslav@471: } jaroslav@348: throw new IOException("Can't find " + resource); jaroslav@348: } jaroslav@348: } jaroslav@330: jaroslav@330: private static class VM extends HttpHandler { jaroslav@348: private final Res loader; jaroslav@330: jaroslav@348: public VM(Res loader) { jaroslav@330: this.loader = loader; jaroslav@330: } jaroslav@330: jaroslav@330: @Override jaroslav@330: public void service(Request request, Response response) throws Exception { jaroslav@330: response.setCharacterEncoding("UTF-8"); jaroslav@330: response.setContentType("text/javascript"); jaroslav@330: Bck2Brwsr.generate(response.getWriter(), loader); jaroslav@330: } jaroslav@330: } jaroslav@332: private static class VMInit extends HttpHandler { jaroslav@332: public VMInit() { jaroslav@332: } jaroslav@332: jaroslav@332: @Override jaroslav@332: public void service(Request request, Response response) throws Exception { jaroslav@332: response.setCharacterEncoding("UTF-8"); jaroslav@332: response.setContentType("text/javascript"); jaroslav@332: response.getWriter().append( jaroslav@332: "function ldCls(res) {\n" jaroslav@332: + " var request = new XMLHttpRequest();\n" jaroslav@357: + " request.open('GET', '/classes/' + res, false);\n" jaroslav@332: + " request.send();\n" jaroslav@332: + " var arr = eval('(' + request.responseText + ')');\n" jaroslav@332: + " return arr;\n" jaroslav@332: + "}\n" jaroslav@332: + "var vm = new bck2brwsr(ldCls);\n"); jaroslav@332: } jaroslav@332: } jaroslav@330: jaroslav@330: private static class Classes extends HttpHandler { jaroslav@348: private final Res loader; jaroslav@330: jaroslav@348: public Classes(Res loader) { jaroslav@330: this.loader = loader; jaroslav@330: } jaroslav@330: jaroslav@330: @Override jaroslav@330: public void service(Request request, Response response) throws Exception { jaroslav@330: String res = request.getHttpHandlerPath(); jaroslav@330: if (res.startsWith("/")) { jaroslav@330: res = res.substring(1); jaroslav@330: } jaroslav@348: try (InputStream is = loader.get(res)) { jaroslav@348: response.setContentType("text/javascript"); jaroslav@348: Writer w = response.getWriter(); jaroslav@348: w.append("["); jaroslav@348: for (int i = 0;; i++) { jaroslav@348: int b = is.read(); jaroslav@348: if (b == -1) { jaroslav@348: break; jaroslav@348: } jaroslav@348: if (i > 0) { jaroslav@348: w.append(", "); jaroslav@348: } jaroslav@348: if (i % 20 == 0) { jaroslav@348: w.write("\n"); jaroslav@348: } jaroslav@348: if (b > 127) { jaroslav@348: b = b - 256; jaroslav@348: } jaroslav@348: w.append(Integer.toString(b)); jaroslav@348: } jaroslav@348: w.append("\n]"); jaroslav@348: } catch (IOException ex) { jaroslav@348: response.setError(); jaroslav@348: response.setDetailMessage(ex.getMessage()); jaroslav@330: } jaroslav@330: } jaroslav@330: } jaroslav@323: }