launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/JVMBridge.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Sun, 15 Sep 2013 18:24:48 +0200
changeset 1283 1d0e583ac981
parent 1233 43fba26ba0c0
child 1418 b8ff900a542d
permissions -rw-r--r--
Use the new netbeans.inspect property to connect to the IDE
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@1233
    20
import java.io.BufferedReader;
jaroslav@1227
    21
import java.io.Reader;
jaroslav@1184
    22
import org.apidesign.html.boot.spi.Fn;
jaroslav@1174
    23
import java.net.URL;
jaroslav@1175
    24
import java.util.ArrayList;
jaroslav@1183
    25
import java.util.Arrays;
jaroslav@1184
    26
import java.util.Collection;
jaroslav@1175
    27
import java.util.List;
jaroslav@1041
    28
import java.util.TooManyListenersException;
jaroslav@1041
    29
import javafx.beans.value.ChangeListener;
jaroslav@1174
    30
import javafx.scene.web.WebEngine;
jaroslav@1174
    31
import netscape.javascript.JSObject;
jaroslav@1184
    32
import org.apidesign.html.boot.impl.FindResources;
jaroslav@1184
    33
import org.apidesign.html.boot.impl.FnUtils;
jaroslav@1041
    34
jaroslav@1041
    35
/**
jaroslav@1041
    36
 *
jaroslav@1041
    37
 * @author Jaroslav Tulach <jtulach@netbeans.org>
jaroslav@1041
    38
 */
jaroslav@1041
    39
public final class JVMBridge {
jaroslav@1174
    40
    private final WebEngine engine;
jaroslav@1184
    41
    private final ClassLoader cl;
jaroslav@1282
    42
    private final WebPresenter presenter;
jaroslav@1174
    43
    
jaroslav@1041
    44
    private static ClassLoader[] ldrs;
jaroslav@1041
    45
    private static ChangeListener<Void> onBck2BrwsrLoad;
jaroslav@1174
    46
    
jaroslav@1174
    47
    JVMBridge(WebEngine eng) {
jaroslav@1174
    48
        this.engine = eng;
jaroslav@1184
    49
        final ClassLoader p = JVMBridge.class.getClassLoader().getParent();
jaroslav@1282
    50
        this.presenter = new WebPresenter();
jaroslav@1282
    51
        this.cl = FnUtils.newLoader(presenter, presenter, p);
jaroslav@1174
    52
    }
jaroslav@1041
    53
        
jaroslav@1041
    54
    public static void registerClassLoaders(ClassLoader[] loaders) {
jaroslav@1041
    55
        ldrs = loaders.clone();
jaroslav@1041
    56
    }
jaroslav@1041
    57
    
jaroslav@1041
    58
    public static void addBck2BrwsrLoad(ChangeListener<Void> l) throws TooManyListenersException {
jaroslav@1041
    59
        if (onBck2BrwsrLoad != null) {
jaroslav@1041
    60
            throw new TooManyListenersException();
jaroslav@1041
    61
        }
jaroslav@1041
    62
        onBck2BrwsrLoad = l;
jaroslav@1041
    63
    }
jaroslav@1041
    64
jaroslav@1041
    65
    public static void onBck2BrwsrLoad() {
jaroslav@1041
    66
        ChangeListener<Void> l = onBck2BrwsrLoad;
jaroslav@1041
    67
        if (l != null) {
jaroslav@1041
    68
            l.changed(null, null, null);
jaroslav@1041
    69
        }
jaroslav@1041
    70
    }
jaroslav@1041
    71
    
jaroslav@1041
    72
    public Class<?> loadClass(String name) throws ClassNotFoundException {
jaroslav@1282
    73
        FnUtils.currentPresenter(presenter);
jaroslav@1174
    74
        return Class.forName(name, true, cl);
jaroslav@1174
    75
    }
jaroslav@1174
    76
    
jaroslav@1282
    77
    private final class WebPresenter implements FindResources, Fn.Presenter {
jaroslav@1174
    78
        @Override
jaroslav@1184
    79
        public void findResources(String name, Collection<? super URL> results, boolean oneIsEnough) {
jaroslav@1174
    80
            if (ldrs != null) for (ClassLoader l : ldrs) {
jaroslav@1174
    81
                URL u = l.getResource(name);
jaroslav@1174
    82
                if (u != null) {
jaroslav@1184
    83
                    results.add(u);
jaroslav@1174
    84
                }
jaroslav@1041
    85
            }
jaroslav@1175
    86
        }
jaroslav@1174
    87
jaroslav@1174
    88
        @Override
jaroslav@1184
    89
        public Fn defineFn(String code, String... names) {
jaroslav@1174
    90
            StringBuilder sb = new StringBuilder();
jaroslav@1174
    91
            sb.append("(function() {");
jaroslav@1183
    92
            sb.append("  return function(");
jaroslav@1174
    93
            String sep = "";
jaroslav@1174
    94
            for (String n : names) {
jaroslav@1174
    95
                sb.append(sep).append(n);
jaroslav@1174
    96
                sep = ",";
jaroslav@1174
    97
            }
jaroslav@1174
    98
            sb.append(") {\n");
jaroslav@1174
    99
            sb.append(code);
jaroslav@1174
   100
            sb.append("};");
jaroslav@1174
   101
            sb.append("})()");
jaroslav@1174
   102
            
jaroslav@1174
   103
            JSObject x = (JSObject) engine.executeScript(sb.toString());
jaroslav@1282
   104
            return new JSFn(this, x);
jaroslav@1041
   105
        }
jaroslav@1184
   106
jaroslav@1184
   107
        @Override
jaroslav@1184
   108
        public void displayPage(URL page, Runnable onPageLoad) {
jaroslav@1233
   109
            throw new UnsupportedOperationException("Not supported yet.");
jaroslav@1184
   110
        }
jaroslav@1227
   111
jaroslav@1227
   112
        @Override
jaroslav@1227
   113
        public void loadScript(Reader code) throws Exception {
jaroslav@1233
   114
            BufferedReader r = new BufferedReader(code);
jaroslav@1233
   115
            StringBuilder sb = new StringBuilder();
jaroslav@1233
   116
            for (;;) {
jaroslav@1233
   117
                String l = r.readLine();
jaroslav@1233
   118
                if (l == null) {
jaroslav@1233
   119
                    break;
jaroslav@1233
   120
                }
jaroslav@1233
   121
                sb.append(l).append('\n');
jaroslav@1233
   122
            }
jaroslav@1233
   123
            engine.executeScript(sb.toString());
jaroslav@1227
   124
        }
jaroslav@1174
   125
    }
jaroslav@1174
   126
    
jaroslav@1174
   127
    private static final class JSFn extends Fn {
jaroslav@1174
   128
        private final JSObject fn;
jaroslav@1174
   129
jaroslav@1282
   130
        private JSFn(WebPresenter cl, JSObject fn) {
jaroslav@1282
   131
            super(cl);
jaroslav@1174
   132
            this.fn = fn;
jaroslav@1174
   133
        }
jaroslav@1282
   134
jaroslav@1174
   135
        @Override
jaroslav@1181
   136
        public Object invoke(Object thiz, Object... args) throws Exception {
jaroslav@1179
   137
            try {
jaroslav@1183
   138
                List<Object> all = new ArrayList<Object>(args.length + 1);
jaroslav@1183
   139
                all.add(thiz == null ? fn : thiz);
jaroslav@1183
   140
                all.addAll(Arrays.asList(args));
jaroslav@1183
   141
                Object ret = fn.call("call", all.toArray()); // NOI18N
jaroslav@1183
   142
                return ret == fn ? null : ret;
jaroslav@1179
   143
            } catch (Error t) {
jaroslav@1179
   144
                t.printStackTrace();
jaroslav@1179
   145
                throw t;
jaroslav@1179
   146
            } catch (Exception t) {
jaroslav@1179
   147
                t.printStackTrace();
jaroslav@1179
   148
                throw t;
jaroslav@1179
   149
            }
jaroslav@1174
   150
        }
jaroslav@1041
   151
    }
jaroslav@1041
   152
}