1.1 --- a/launcher/api/src/main/java/org/apidesign/bck2brwsr/launcher/Launcher.java Mon Apr 18 05:15:11 2016 +0200
1.2 +++ b/launcher/api/src/main/java/org/apidesign/bck2brwsr/launcher/Launcher.java Mon Apr 18 07:32:35 2016 +0200
1.3 @@ -79,6 +79,18 @@
1.4 * @return launcher executing in external browser.
1.5 */
1.6 public static Launcher createBrowser(String cmd) {
1.7 + return createBrowser(cmd, null, null);
1.8 + }
1.9 +
1.10 + /** Creates launcher that is using external browser.
1.11 + *
1.12 + * @param classes classloader offering access to classes and resources
1.13 + * @param startpage page to show in the browser
1.14 + * @param cmd <code>null</code> to use <code>java.awt.Desktop</code> to show the launcher
1.15 + * or a string to execute in an external process (with a parameter to the URL)
1.16 + * @return launcher executing in external browser.
1.17 + */
1.18 + public static Launcher createBrowser(String cmd, ClassLoader classes, String startpage) {
1.19 String msg = "Trying to create browser '" + cmd + "'";
1.20 try {
1.21 Class<?> c;
1.22 @@ -94,7 +106,12 @@
1.23 }
1.24 }
1.25 Constructor<?> cnstr = c.getConstructor(String.class);
1.26 - return (Launcher) cnstr.newInstance(cmd);
1.27 + final Launcher launcher = (Launcher) cnstr.newInstance(cmd);
1.28 + if (classes != null) {
1.29 + launcher.addClassLoader(classes);
1.30 + }
1.31 + launcher.rootPage(startpage);
1.32 + return launcher;
1.33 } catch (Exception ex) {
1.34 throw new IllegalStateException(msg, ex);
1.35 }
1.36 @@ -183,4 +200,8 @@
1.37 void addClassLoader(ClassLoader classes) {
1.38 throw new UnsupportedOperationException();
1.39 }
1.40 +
1.41 + void rootPage(String startpage) {
1.42 + throw new UnsupportedOperationException();
1.43 + }
1.44 }
2.1 --- a/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/BaseHTTPLauncher.java Mon Apr 18 05:15:11 2016 +0200
2.2 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/BaseHTTPLauncher.java Mon Apr 18 07:32:35 2016 +0200
2.3 @@ -87,6 +87,7 @@
2.4 private HttpServer server;
2.5 private CountDownLatch wait;
2.6 private Thread flushing;
2.7 + private String rootPage;
2.8
2.9 public BaseHTTPLauncher(String cmd) {
2.10 this.cmd = cmd;
2.11 @@ -118,6 +119,12 @@
2.12 return loaders.toArray(new ClassLoader[loaders.size()]);
2.13 }
2.14
2.15 + @Override
2.16 + void rootPage(String startpage) {
2.17 + this.rootPage = startpage;
2.18 + }
2.19 +
2.20 + @Override
2.21 public void showURL(String startpage) throws IOException {
2.22 if (!startpage.startsWith("/")) {
2.23 startpage = "/" + startpage;
2.24 @@ -201,6 +208,12 @@
2.25 if (addClasses) {
2.26 conf.addHttpHandler(new Classes(resources), "/classes/");
2.27 }
2.28 + if (rootPage != null) {
2.29 + int last = rootPage.lastIndexOf('/');
2.30 + String prefix = rootPage.substring(0, last);
2.31 + String page = rootPage.substring(last);
2.32 + s.getServerConfiguration().addHttpHandler(new SubTree("/pages" + page, resources, prefix), "/pages/");
2.33 + }
2.34 final WebSocketAddOn addon = new WebSocketAddOn();
2.35 for (NetworkListener listener : s.getListeners()) {
2.36 listener.registerAddOn(addon);
2.37 @@ -423,7 +436,13 @@
2.38 }
2.39 }, "/data");
2.40
2.41 - this.brwsr = launchServerAndBrwsr(server, "/execute");
2.42 + String page = "/execute";
2.43 + if (rootPage != null) {
2.44 + int last = rootPage.lastIndexOf('/');
2.45 + page = "/pages" + rootPage.substring(last);
2.46 + }
2.47 +
2.48 + this.brwsr = launchServerAndBrwsr(server, page);
2.49 }
2.50
2.51 private static String encodeJSON(String in) {
2.52 @@ -781,8 +800,14 @@
2.53 final String resource;
2.54 private final String[] args;
2.55 private final Res res;
2.56 + private final String ensureBck2Brwsr;
2.57
2.58 public Page(Res res, String resource, String... args) {
2.59 + this(null, res, resource, args);
2.60 + }
2.61 +
2.62 + Page(String ensureBck2Brwsr, Res res, String resource, String... args) {
2.63 + this.ensureBck2Brwsr = ensureBck2Brwsr;
2.64 this.res = res;
2.65 this.resource = resource;
2.66 this.args = args.length == 0 ? new String[] { "$0" } : args;
2.67 @@ -805,10 +830,26 @@
2.68 LOG.info("Content type application/xhtml+xml");
2.69 replace = args;
2.70 }
2.71 - OutputStream os = response.getOutputStream();
2.72 try {
2.73 InputStream is = res.get(r, 0).openStream();
2.74 - copyStream(is, os, request.getRequestURL().toString(), replace);
2.75 + if (ensureBck2Brwsr != null && ensureBck2Brwsr.equals(request.getRequestURI())) {
2.76 + ByteArrayOutputStream tmp = new ByteArrayOutputStream();
2.77 + copyStream(is, tmp, request.getRequestURL().toString(), replace);
2.78 + String pageText = tmp.toString("UTF-8");
2.79 + if (!pageText.contains("bck2brwsr.js")) {
2.80 + int last = pageText.toLowerCase().indexOf("</body>");
2.81 + if (last == -1) {
2.82 + last = pageText.length();
2.83 + }
2.84 + pageText = pageText.substring(0, last) +
2.85 + "\n<script src='/bck2brwsr.js'></script>\n\n" +
2.86 + pageText.substring(last);
2.87 + }
2.88 + response.getWriter().write(pageText);
2.89 + } else {
2.90 + OutputStream os = response.getOutputStream();
2.91 + copyStream(is, os, request.getRequestURL().toString(), replace);
2.92 + }
2.93 } catch (IOException ex) {
2.94 response.setDetailMessage(ex.getLocalizedMessage());
2.95 response.setError();
2.96 @@ -830,6 +871,9 @@
2.97 public SubTree(Res res, String resource, String... args) {
2.98 super(res, resource, args);
2.99 }
2.100 + public SubTree(String ensureBck2Brwsr, Res res, String resource, String... args) {
2.101 + super(ensureBck2Brwsr, res, resource, args);
2.102 + }
2.103
2.104 @Override
2.105 protected String computePage(Request request) {
3.1 --- a/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/Console.java Mon Apr 18 05:15:11 2016 +0200
3.2 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/Console.java Mon Apr 18 07:32:35 2016 +0200
3.3 @@ -39,7 +39,10 @@
3.4 @JavaScriptBody(args = { "elem", "attr" }, body = "return elem[attr].toString();")
3.5 private static native Object getAttr(Object elem, String attr);
3.6
3.7 - @JavaScriptBody(args = { "id", "attr", "value" }, body = "window.document.getElementById(id)[attr] = value;")
3.8 + @JavaScriptBody(args = { "id", "attr", "value" }, body = "\n"
3.9 + + "var e = window.document.getElementById(id);\n"
3.10 + + "if (e) e[attr] = value;\n"
3.11 + )
3.12 private static native void setAttr(String id, String attr, Object value);
3.13
3.14 @JavaScriptBody(args = { "elem", "attr", "value" }, body = "elem[attr] = value;")
4.1 --- a/launcher/http/src/main/java/org/apidesign/bck2brwsr/launcher/impl/Console.java Mon Apr 18 05:15:11 2016 +0200
4.2 +++ b/launcher/http/src/main/java/org/apidesign/bck2brwsr/launcher/impl/Console.java Mon Apr 18 07:32:35 2016 +0200
4.3 @@ -40,24 +40,29 @@
4.4 }
4.5
4.6 @JavaScriptBody(args = {"id", "attr"}, body =
4.7 - "return window.document.getElementById(id)[attr].toString();")
4.8 + "var e = window.document.getElementById(id);" +
4.9 + "return e ? e[attr].toString() : null;"
4.10 + )
4.11 private static native Object getAttr(String id, String attr);
4.12 @JavaScriptBody(args = {"elem", "attr"}, body =
4.13 - "return elem[attr].toString();")
4.14 + "return elem ? elem[attr].toString() : null;")
4.15 private static native Object getAttr(Object elem, String attr);
4.16
4.17 @JavaScriptBody(args = {"id", "attr", "value"}, body =
4.18 - "window.document.getElementById(id)[attr] = value;")
4.19 + "var e = window.document.getElementById(id);\n"
4.20 + + "if (e) e[attr] = value;"
4.21 + )
4.22 private static native void setAttr(String id, String attr, Object value);
4.23 @JavaScriptBody(args = {"elem", "attr", "value"}, body =
4.24 - "elem[attr] = value;")
4.25 + "if (elem) elem[attr] = value;")
4.26 private static native void setAttr(Object id, String attr, Object value);
4.27
4.28 @net.java.html.js.JavaScriptBody(args = {}, body = "return new Date().getTime()")
4.29 private static native double getTime();
4.30
4.31 @net.java.html.js.JavaScriptBody(args = { }, body =
4.32 - "var a = document.createElement('a');"
4.33 + "if (!document.getElementById('bck2brwsr.fragment')) return;\b"
4.34 + + "var a = document.createElement('a');\n"
4.35 + "a.innerHTML = 'Cancel: closing in 10s...';\n"
4.36 + "a.href = '#';\n"
4.37 + "var closing = window.setTimeout(function() { window.close(); }, 10000);\n"
4.38 @@ -119,7 +124,7 @@
4.39 + "li.appendChild(span);\n"
4.40 + "li.appendChild(details);\n"
4.41 + "p.appendChild(pre);\n"
4.42 - + "ul.appendChild(li);\n"
4.43 + + "if (ul) ul.appendChild(li);\n"
4.44 + "arr[0] = pre;\n"
4.45 + "arr[1] = status;\n"
4.46 )