rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/JSLauncher.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Wed, 17 Apr 2013 17:04:40 +0200
branchfx
changeset 1004 04efef2a9c1e
parent 622 a07253cf2ca4
child 1020 a6bacea2518f
permissions -rw-r--r--
Rather than piggybacking on first alert call, use the fact that the server and FX Web View are in the same VM and notify the view that bck2brwsr.js is about to be served from the server.
jaroslav@323
     1
/**
jaroslav@323
     2
 * Back 2 Browser Bytecode Translator
jaroslav@323
     3
 * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
jaroslav@323
     4
 *
jaroslav@323
     5
 * This program is free software: you can redistribute it and/or modify
jaroslav@323
     6
 * it under the terms of the GNU General Public License as published by
jaroslav@323
     7
 * the Free Software Foundation, version 2 of the License.
jaroslav@323
     8
 *
jaroslav@323
     9
 * This program is distributed in the hope that it will be useful,
jaroslav@323
    10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
jaroslav@323
    11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
jaroslav@323
    12
 * GNU General Public License for more details.
jaroslav@323
    13
 *
jaroslav@323
    14
 * You should have received a copy of the GNU General Public License
jaroslav@323
    15
 * along with this program. Look for COPYING file in the top folder.
jaroslav@323
    16
 * If not, see http://opensource.org/licenses/GPL-2.0.
jaroslav@323
    17
 */
jaroslav@323
    18
package org.apidesign.bck2brwsr.launcher;
jaroslav@323
    19
jaroslav@622
    20
import org.apidesign.bck2brwsr.launcher.impl.Console;
jaroslav@331
    21
import java.io.IOException;
jaroslav@323
    22
import java.io.InputStream;
jaroslav@323
    23
import java.net.URL;
jaroslav@323
    24
import java.util.Enumeration;
jaroslav@348
    25
import java.util.LinkedHashSet;
jaroslav@348
    26
import java.util.Set;
jaroslav@595
    27
import java.util.logging.Level;
jaroslav@362
    28
import java.util.logging.Logger;
jaroslav@356
    29
import javax.script.Invocable;
jaroslav@356
    30
import javax.script.ScriptEngine;
jaroslav@356
    31
import javax.script.ScriptEngineManager;
jaroslav@356
    32
import javax.script.ScriptException;
jaroslav@323
    33
import org.apidesign.vm4brwsr.Bck2Brwsr;
jaroslav@323
    34
jaroslav@323
    35
/**
jaroslav@370
    36
 * Tests execution in Java's internal scripting engine.
jaroslav@323
    37
 */
jaroslav@382
    38
final class JSLauncher extends Launcher {
jaroslav@370
    39
    private static final Logger LOG = Logger.getLogger(JSLauncher.class.getName());
jaroslav@348
    40
    private Set<ClassLoader> loaders = new LinkedHashSet<>();
jaroslav@357
    41
    private final Res resources = new Res();
jaroslav@370
    42
    private Invocable code;
jaroslav@396
    43
    private StringBuilder codeSeq;
jaroslav@370
    44
    private Object console;
jaroslav@348
    45
    
jaroslav@348
    46
    
jaroslav@622
    47
    @Override InvocationContext runMethod(InvocationContext mi) {
jaroslav@622
    48
        loaders.add(mi.clazz.getClassLoader());
jaroslav@370
    49
        try {
jaroslav@595
    50
            long time = System.currentTimeMillis();
jaroslav@622
    51
            LOG.log(Level.FINE, "Invoking {0}.{1}", new Object[]{mi.clazz.getName(), mi.methodName});
jaroslav@595
    52
            String res = code.invokeMethod(
jaroslav@370
    53
                console,
jaroslav@370
    54
                "invoke__Ljava_lang_String_2Ljava_lang_String_2Ljava_lang_String_2",
jaroslav@622
    55
                mi.clazz.getName(), mi.methodName).toString();
jaroslav@595
    56
            time = System.currentTimeMillis() - time;
jaroslav@622
    57
            LOG.log(Level.FINE, "Resut of {0}.{1} = {2} in {3} ms", new Object[]{mi.clazz.getName(), mi.methodName, res, time});
jaroslav@595
    58
            mi.result(res, null);
jaroslav@371
    59
        } catch (ScriptException | NoSuchMethodException ex) {
jaroslav@371
    60
            mi.result(null, ex);
jaroslav@370
    61
        }
jaroslav@370
    62
        return mi;
jaroslav@348
    63
    }
jaroslav@348
    64
    
jaroslav@357
    65
    public void addClassLoader(ClassLoader url) {
jaroslav@357
    66
        this.loaders.add(url);
jaroslav@357
    67
    }
jaroslav@348
    68
jaroslav@382
    69
    @Override
jaroslav@370
    70
    public void initialize() throws IOException {
jaroslav@356
    71
        try {
jaroslav@370
    72
            initRhino();
jaroslav@356
    73
        } catch (Exception ex) {
jaroslav@356
    74
            if (ex instanceof IOException) {
jaroslav@356
    75
                throw (IOException)ex;
jaroslav@356
    76
            }
jaroslav@356
    77
            if (ex instanceof RuntimeException) {
jaroslav@356
    78
                throw (RuntimeException)ex;
jaroslav@356
    79
            }
jaroslav@356
    80
            throw new IOException(ex);
jaroslav@356
    81
        }
jaroslav@356
    82
    }
jaroslav@356
    83
    
jaroslav@370
    84
    private void initRhino() throws IOException, ScriptException, NoSuchMethodException {
jaroslav@356
    85
        StringBuilder sb = new StringBuilder();
jaroslav@356
    86
        Bck2Brwsr.generate(sb, new Res());
jaroslav@356
    87
jaroslav@356
    88
        ScriptEngineManager sem = new ScriptEngineManager();
jaroslav@370
    89
        ScriptEngine mach = sem.getEngineByExtension("js");
jaroslav@356
    90
jaroslav@356
    91
        sb.append(
jaroslav@622
    92
              "\nvar vm = new bck2brwsr(org.apidesign.bck2brwsr.launcher.impl.Console.read);"
jaroslav@356
    93
            + "\nfunction initVM() { return vm; };"
jaroslav@356
    94
            + "\n");
jaroslav@356
    95
jaroslav@356
    96
        Object res = mach.eval(sb.toString());
jaroslav@356
    97
        if (!(mach instanceof Invocable)) {
jaroslav@356
    98
            throw new IOException("It is invocable object: " + res);
jaroslav@356
    99
        }
jaroslav@370
   100
        code = (Invocable) mach;
jaroslav@396
   101
        codeSeq = sb;
jaroslav@356
   102
        
jaroslav@356
   103
        Object vm = code.invokeFunction("initVM");
jaroslav@370
   104
        console = code.invokeMethod(vm, "loadClass", Console.class.getName());
jaroslav@356
   105
    }
jaroslav@382
   106
jaroslav@382
   107
    @Override
jaroslav@382
   108
    public void shutdown() throws IOException {
jaroslav@382
   109
    }
jaroslav@396
   110
jaroslav@396
   111
    @Override
jaroslav@396
   112
    public String toString() {
jaroslav@396
   113
        return codeSeq.toString();
jaroslav@396
   114
    }
jaroslav@356
   115
    
jaroslav@348
   116
    private class Res implements Bck2Brwsr.Resources {
jaroslav@348
   117
        @Override
jaroslav@348
   118
        public InputStream get(String resource) throws IOException {
jaroslav@348
   119
            for (ClassLoader l : loaders) {
jaroslav@348
   120
                URL u = null;
jaroslav@348
   121
                Enumeration<URL> en = l.getResources(resource);
jaroslav@348
   122
                while (en.hasMoreElements()) {
jaroslav@348
   123
                    u = en.nextElement();
jaroslav@348
   124
                }
jaroslav@348
   125
                if (u != null) {
jaroslav@348
   126
                    return u.openStream();
jaroslav@348
   127
                }
jaroslav@348
   128
            }
jaroslav@348
   129
            throw new IOException("Can't find " + resource);
jaroslav@348
   130
        }
jaroslav@348
   131
    }
jaroslav@323
   132
}