Launcher.createBrowser can specify its own page
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Mon, 18 Apr 2016 07:32:35 +0200
changeset 1927cff680298793
parent 1926 789849cabcc7
child 1928 b5ac0a273dfe
Launcher.createBrowser can specify its own page
launcher/api/src/main/java/org/apidesign/bck2brwsr/launcher/Launcher.java
launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/BaseHTTPLauncher.java
launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/Console.java
launcher/http/src/main/java/org/apidesign/bck2brwsr/launcher/impl/Console.java
     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      )