launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Console.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Sat, 22 Dec 2012 21:35:14 +0100
branchlauncher
changeset 366 ca2be963f3b9
parent 360 86f3ea771e24
child 381 70d15cf323ba
permissions -rw-r--r--
Closing the window when data are processed.
     1 /**
     2  * Back 2 Browser Bytecode Translator
     3  * Copyright (C) 2012 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.IOException;
    21 import java.io.InputStream;
    22 import java.lang.reflect.InvocationTargetException;
    23 import java.lang.reflect.Method;
    24 import java.net.URL;
    25 import java.util.Enumeration;
    26 import org.apidesign.bck2brwsr.core.JavaScriptBody;
    27 
    28 /**
    29  *
    30  * @author Jaroslav Tulach <jtulach@netbeans.org>
    31  */
    32 public class Console {
    33     public static String welcome() {
    34         return "HellofromBck2Brwsr";
    35     }
    36     public static String multiply() {
    37         return String.valueOf(Integer.MAX_VALUE / 2 + Integer.MAX_VALUE);
    38     }
    39     
    40     @JavaScriptBody(args = {"id", "attr"}, body = 
    41         "return window.document.getElementById(id)[attr].toString();")
    42     private static native Object getAttr(String id, String attr);
    43 
    44     @JavaScriptBody(args = {"id", "attr", "value"}, body = 
    45         "window.document.getElementById(id)[attr] = value;")
    46     private static native void setAttr(String id, String attr, Object value);
    47     
    48     @JavaScriptBody(args = {}, body = "window.close();")
    49     private static native void closeWindow();
    50 
    51     private static void log(String newText) {
    52         String id = "result";
    53         String attr = "value";
    54         setAttr(id, attr, getAttr(id, attr) + "\n" + newText);
    55         setAttr(id, "scrollTop", getAttr(id, "scrollHeight"));
    56     }
    57     
    58     public static void execute() throws Exception {
    59         String clazz = (String) getAttr("clazz", "value");
    60         String method = (String) getAttr("method", "value");
    61         Object res = invokeMethod(clazz, method);
    62         setAttr("result", "value", res);
    63     }
    64     
    65     public static void harness(String url) {
    66         log("Connecting to " + url);
    67         try {
    68             URL u = new URL(url);
    69             for (;;) {
    70                 String data = (String) u.getContent(new Class[] { String.class });
    71                 log("\nGot \"" + data + "\"");
    72                 if (data.isEmpty()) {
    73                     log("No data, exiting");
    74                     closeWindow();
    75                     break;
    76                 }
    77                 
    78                 Case c = Case.parseData(data);
    79                 log("Invoking " + c.getClassName() + '.' + c.getMethodName() + " as request: " + c.getRequestId());
    80 
    81                 Object result = invokeMethod(c.getClassName(), c.getMethodName());
    82                 
    83                 log("Result: " + result);
    84                 log("Sending back: " + url + "?request=" + c.getRequestId() + "&result=" + result);
    85                 u = new URL(url + "?request=" + c.getRequestId() + "&result=" + result);
    86             }
    87             
    88             
    89         } catch (Exception ex) {
    90             log(ex.getMessage());
    91         }
    92     }
    93     
    94     static String invoke(String clazz, String method) throws ClassNotFoundException, InvocationTargetException, IllegalAccessException {
    95         final Object r = invokeMethod(clazz, method);
    96         return r == null ? "null" : r.toString().toString();
    97     }
    98 
    99     /** Helper method that inspects the classpath and loads given resource
   100      * (usually a class file). Used while running tests in Rhino.
   101      * 
   102      * @param name resource name to find
   103      * @return the array of bytes in the given resource
   104      * @throws IOException I/O in case something goes wrong
   105      */
   106     public static byte[] read(String name) throws IOException {
   107         URL u = null;
   108         Enumeration<URL> en = Console.class.getClassLoader().getResources(name);
   109         while (en.hasMoreElements()) {
   110             u = en.nextElement();
   111         }
   112         if (u == null) {
   113             throw new IOException("Can't find " + name);
   114         }
   115         try (InputStream is = u.openStream()) {
   116             byte[] arr;
   117             arr = new byte[is.available()];
   118             int offset = 0;
   119             while (offset < arr.length) {
   120                 int len = is.read(arr, offset, arr.length - offset);
   121                 if (len == -1) {
   122                     throw new IOException("Can't read " + name);
   123                 }
   124                 offset += len;
   125             }
   126             return arr;
   127         }
   128     }
   129    
   130     private static Object invokeMethod(String clazz, String method) 
   131     throws ClassNotFoundException, InvocationTargetException, 
   132     SecurityException, IllegalAccessException, IllegalArgumentException {
   133         Method found = null;
   134         Class<?> c = Class.forName(clazz);
   135         for (Method m : c.getMethods()) {
   136             if (m.getName().equals(method)) {
   137                 found = m;
   138             }
   139         }
   140         Object res;
   141         if (found != null) {
   142             res = found.invoke(null);
   143         } else {
   144             res = "Can't find method " + method + " in " + clazz;
   145         }
   146         return res;
   147     }
   148     
   149     private static final class Case {
   150         private final Object data;
   151 
   152         private Case(Object data) {
   153             this.data = data;
   154         }
   155         
   156         public static Case parseData(String s) {
   157             return new Case(toJSON(s));
   158         }
   159         
   160         public String getMethodName() {
   161             return value("methodName", data);
   162         }
   163 
   164         public String getClassName() {
   165             return value("className", data);
   166         }
   167         
   168         public String getRequestId() {
   169             return value("request", data);
   170         }
   171         
   172         @JavaScriptBody(args = "s", body = "return eval('(' + s + ')');")
   173         private static native Object toJSON(String s);
   174         
   175         @JavaScriptBody(args = {"p", "d"}, body = "return d[p].toString();")
   176         private static native String value(String p, Object d);
   177     }
   178 }