launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/JVMBridge.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Mon, 17 Jun 2013 17:40:30 +0200
branchclassloader
changeset 1179 2fee889b9830
parent 1175 15c6903c8612
child 1181 b703d9d71f25
permissions -rw-r--r--
Console using JavaScriptBody
jaroslav@1041
     1
/**
jaroslav@1041
     2
 * Back 2 Browser Bytecode Translator
jaroslav@1041
     3
 * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
jaroslav@1041
     4
 *
jaroslav@1041
     5
 * This program is free software: you can redistribute it and/or modify
jaroslav@1041
     6
 * it under the terms of the GNU General Public License as published by
jaroslav@1041
     7
 * the Free Software Foundation, version 2 of the License.
jaroslav@1041
     8
 *
jaroslav@1041
     9
 * This program is distributed in the hope that it will be useful,
jaroslav@1041
    10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
jaroslav@1041
    11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
jaroslav@1041
    12
 * GNU General Public License for more details.
jaroslav@1041
    13
 *
jaroslav@1041
    14
 * You should have received a copy of the GNU General Public License
jaroslav@1041
    15
 * along with this program. Look for COPYING file in the top folder.
jaroslav@1041
    16
 * If not, see http://opensource.org/licenses/GPL-2.0.
jaroslav@1041
    17
 */
jaroslav@1041
    18
package org.apidesign.bck2brwsr.launcher.fximpl;
jaroslav@1041
    19
jaroslav@1174
    20
import java.net.URL;
jaroslav@1175
    21
import java.util.ArrayList;
jaroslav@1175
    22
import java.util.Collections;
jaroslav@1175
    23
import java.util.Enumeration;
jaroslav@1175
    24
import java.util.List;
jaroslav@1041
    25
import java.util.TooManyListenersException;
jaroslav@1041
    26
import javafx.beans.value.ChangeListener;
jaroslav@1174
    27
import javafx.scene.web.WebEngine;
jaroslav@1174
    28
import netscape.javascript.JSObject;
jaroslav@1041
    29
jaroslav@1041
    30
/**
jaroslav@1041
    31
 *
jaroslav@1041
    32
 * @author Jaroslav Tulach <jtulach@netbeans.org>
jaroslav@1041
    33
 */
jaroslav@1041
    34
public final class JVMBridge {
jaroslav@1174
    35
    private final WebEngine engine;
jaroslav@1174
    36
    private final WebClassLoader cl;
jaroslav@1174
    37
    
jaroslav@1041
    38
    private static ClassLoader[] ldrs;
jaroslav@1041
    39
    private static ChangeListener<Void> onBck2BrwsrLoad;
jaroslav@1174
    40
    
jaroslav@1174
    41
    JVMBridge(WebEngine eng) {
jaroslav@1174
    42
        this.engine = eng;
jaroslav@1179
    43
        this.cl = new WebClassLoader(JVMBridge.class.getClassLoader().getParent());
jaroslav@1174
    44
    }
jaroslav@1041
    45
        
jaroslav@1041
    46
    public static void registerClassLoaders(ClassLoader[] loaders) {
jaroslav@1041
    47
        ldrs = loaders.clone();
jaroslav@1041
    48
    }
jaroslav@1041
    49
    
jaroslav@1041
    50
    public static void addBck2BrwsrLoad(ChangeListener<Void> l) throws TooManyListenersException {
jaroslav@1041
    51
        if (onBck2BrwsrLoad != null) {
jaroslav@1041
    52
            throw new TooManyListenersException();
jaroslav@1041
    53
        }
jaroslav@1041
    54
        onBck2BrwsrLoad = l;
jaroslav@1041
    55
    }
jaroslav@1041
    56
jaroslav@1041
    57
    public static void onBck2BrwsrLoad() {
jaroslav@1041
    58
        ChangeListener<Void> l = onBck2BrwsrLoad;
jaroslav@1041
    59
        if (l != null) {
jaroslav@1041
    60
            l.changed(null, null, null);
jaroslav@1041
    61
        }
jaroslav@1041
    62
    }
jaroslav@1041
    63
    
jaroslav@1041
    64
    public Class<?> loadClass(String name) throws ClassNotFoundException {
jaroslav@1174
    65
        return Class.forName(name, true, cl);
jaroslav@1174
    66
    }
jaroslav@1174
    67
    
jaroslav@1174
    68
    private final class WebClassLoader extends JsClassLoader {
jaroslav@1174
    69
        public WebClassLoader(ClassLoader parent) {
jaroslav@1174
    70
            super(parent);
jaroslav@1174
    71
        }
jaroslav@1174
    72
jaroslav@1174
    73
        @Override
jaroslav@1174
    74
        protected URL findResource(String name) {
jaroslav@1174
    75
            if (ldrs != null) for (ClassLoader l : ldrs) {
jaroslav@1174
    76
                URL u = l.getResource(name);
jaroslav@1174
    77
                if (u != null) {
jaroslav@1174
    78
                    return u;
jaroslav@1174
    79
                }
jaroslav@1041
    80
            }
jaroslav@1174
    81
            return null;
jaroslav@1041
    82
        }
jaroslav@1175
    83
        
jaroslav@1175
    84
        @Override
jaroslav@1175
    85
        protected Enumeration<URL> findResources(String name) {
jaroslav@1175
    86
            List<URL> arr = new ArrayList<URL>();
jaroslav@1175
    87
            if (ldrs != null) {
jaroslav@1175
    88
                for (ClassLoader l : ldrs) {
jaroslav@1175
    89
                    URL u = l.getResource(name);
jaroslav@1175
    90
                    if (u != null) {
jaroslav@1175
    91
                        arr.add(u);
jaroslav@1175
    92
                    }
jaroslav@1175
    93
                }
jaroslav@1175
    94
            }
jaroslav@1175
    95
            return Collections.enumeration(arr);
jaroslav@1175
    96
        }
jaroslav@1174
    97
jaroslav@1174
    98
        @Override
jaroslav@1174
    99
        protected Fn defineFn(String code, String... names) {
jaroslav@1174
   100
            StringBuilder sb = new StringBuilder();
jaroslav@1174
   101
            sb.append("(function() {");
jaroslav@1174
   102
            sb.append("  var x = {};");
jaroslav@1174
   103
            sb.append("  x.fn = function(");
jaroslav@1174
   104
            String sep = "";
jaroslav@1174
   105
            for (String n : names) {
jaroslav@1174
   106
                sb.append(sep).append(n);
jaroslav@1174
   107
                sep = ",";
jaroslav@1174
   108
            }
jaroslav@1174
   109
            sb.append(") {\n");
jaroslav@1174
   110
            sb.append(code);
jaroslav@1174
   111
            sb.append("};");
jaroslav@1174
   112
            sb.append("return x;");
jaroslav@1174
   113
            sb.append("})()");
jaroslav@1174
   114
            
jaroslav@1174
   115
            JSObject x = (JSObject) engine.executeScript(sb.toString());
jaroslav@1174
   116
            return new JSFn(x);
jaroslav@1041
   117
        }
jaroslav@1174
   118
    }
jaroslav@1174
   119
    
jaroslav@1174
   120
    private static final class JSFn extends Fn {
jaroslav@1174
   121
        private final JSObject fn;
jaroslav@1174
   122
jaroslav@1174
   123
        public JSFn(JSObject fn) {
jaroslav@1174
   124
            this.fn = fn;
jaroslav@1174
   125
        }
jaroslav@1174
   126
        
jaroslav@1174
   127
        @Override
jaroslav@1174
   128
        public Object invoke(Object... args) throws Exception {
jaroslav@1179
   129
            try {
jaroslav@1179
   130
                return fn.call("fn", args); // NOI18N
jaroslav@1179
   131
            } catch (Error t) {
jaroslav@1179
   132
                t.printStackTrace();
jaroslav@1179
   133
                throw t;
jaroslav@1179
   134
            } catch (Exception t) {
jaroslav@1179
   135
                t.printStackTrace();
jaroslav@1179
   136
                throw t;
jaroslav@1179
   137
            }
jaroslav@1174
   138
        }
jaroslav@1041
   139
    }
jaroslav@1041
   140
}