/** * Copyright (c) 2013-2016 Angelo ZERR. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Angelo Zerr <angelo.zerr@gmail.com> - initial API and implementation */ package tern.server.nashorn; import java.util.List; import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import javax.script.ScriptException; import com.eclipsesource.json.Json; import com.eclipsesource.json.JsonObject; import tern.ITernProject; import tern.TernException; import tern.server.AbstractScriptEngineTernServer; import tern.server.IResponseHandler; import tern.server.protocol.IJSONObjectHelper; import tern.server.protocol.MinimalJSONHelper; import tern.server.protocol.TernDoc; import tern.server.protocol.html.ScriptTagRegion; import tern.utils.IOUtils; /** * Tern server implemented with Nashorn. * */ public class NashornTernServer extends AbstractScriptEngineTernServer { private ScriptEngine engine; public NashornTernServer(ITernProject project) { super(project); } @Override public void addFile(String name, String text, ScriptTagRegion[] tags) { TernDoc doc = new TernDoc(); doc.addFile(name, text, tags, null); try { request(doc); } catch (TernException e) { e.printStackTrace(); } } @Override public void request(TernDoc doc, IResponseHandler handler) { try { JsonObject data = request(doc); handler.onSuccess(data, null); } catch (Exception e) { handler.onError(e.getMessage(), e); } } private synchronized JsonObject request(TernDoc doc) throws TernException { ScriptEngine engine = getEngine(); try { String script = new StringBuilder("server.request(").append(doc.toString()).append(");").toString(); String json = (String) engine.eval(script); return Json.parse(json).asObject(); } catch (Throwable e) { throw new TernException(e); } } @Override public IJSONObjectHelper getJSONObjectHelper() { return MinimalJSONHelper.INSTANCE; } @Override protected void doDispose() { if (engine != null) { try { } finally { engine = null; } } fireEndServer(); } public void log(String message, Integer level) { if (level == 1) { System.err.println(message); } else { System.out.println(message); } } private synchronized ScriptEngine getEngine() throws TernException { if (engine == null) { engine = loadEngine(); } return engine; } private ScriptEngine loadEngine() throws TernException { ScriptEngine engine = null; TernResources resources = loadTern(); try { final ScriptEngineManager factory = new ScriptEngineManager(); engine = factory.getEngineByName("nashorn"); // Load tern scripts (acorn + ternjs) + plugins scripts List<TernResource> scripts = resources.getScripts(); for (TernResource script : scripts) { eval(script.getFilename(), script.getContent(), engine); } // Get defs String defs = resources.getDefsAsString(); // invocable.(this, "log", "_javaConsole", new Class<?>[] { // String.class, Integer.class }); eval("tern-nashorn.js", IOUtils.toString(NashornTernServer.class.getResourceAsStream("tern-nashorn.js")), engine); StringBuilder script = new StringBuilder("var server = new J2V8TernServer("); script.append("["); script.append(defs.toString()); script.append("],"); script.append(getProject().getPlugins() != null ? getProject().getPlugins().toString() : ""); script.append(");"); eval("init.js", script.toString(), engine); return engine; } catch (Exception e) { throw new TernException(e); } } private static void eval(String filename, String content, ScriptEngine engine) throws ScriptException { engine.put(ScriptEngine.FILENAME, filename); engine.eval(content); } }