/**
* 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.j2v8;
import java.io.IOException;
import java.util.List;
import com.eclipsesource.json.Json;
import com.eclipsesource.json.JsonObject;
import com.eclipsesource.v8.V8;
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 J2V8
*
*/
public class J2V8TernServer extends AbstractScriptEngineTernServer {
private V8 v8;
public J2V8TernServer(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 {
V8 v8 = getV8();
try {
v8.getLocker().acquire();
String script = new StringBuilder("server.request(")
.append(doc.toString()).append(");").toString();
String json = v8.executeStringScript(script);
return Json.parse(json).asObject();
} catch (Throwable e) {
throw new TernException(e);
} finally {
v8.getLocker().release();
}
}
@Override
public IJSONObjectHelper getJSONObjectHelper() {
return MinimalJSONHelper.INSTANCE;
}
@Override
protected void doDispose() {
if (v8 != null) {
try {
v8.getLocker().acquire();
v8.release();
if (V8.getActiveRuntimes() != 0) {
throw new IllegalStateException(
"V8Runtimes not properly released.");
}
} finally {
v8 = null;
}
}
fireEndServer();
}
public void log(String message, Integer level) {
if (level == 1) {
System.err.println(message);
} else {
System.out.println(message);
}
}
private synchronized V8 getV8() throws TernException {
if (v8 == null) {
v8 = loadV8();
}
return v8;
}
private V8 loadV8() throws TernException {
V8 v8 = null;
TernResources resources = loadTern();
try {
v8 = V8.createV8Runtime();
v8.getLocker().acquire();
// Load tern scripts (acorn + ternjs) + plugins scripts
List<TernResource> scripts = resources.getScripts();
for (TernResource script : scripts) {
v8.executeScript(script.getContent(), script.getFilename(), 0);
}
// Get defs
String defs = resources.getDefsAsString();
v8.registerJavaMethod(this, "log", "_javaConsole", new Class<?>[] {
String.class, Integer.class });
v8.executeScript(IOUtils.toString(J2V8TernServer.class
.getResourceAsStream("tern-j2v8.js")), "tern-j2v8.js", 0);
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(");");
v8.executeScript(script.toString());
return v8;
} catch (IOException e) {
throw new TernException(e);
} finally {
if (v8 != null) {
v8.getLocker().release();
}
}
}
}