package org.eclipse.emf.henshin.interpreter.impl;
import java.util.List;
import java.util.regex.Pattern;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
/**
* Script engine wrapper for automatic handling of Java imports.
*/
public class ScriptEngineWrapper {
/**
* The original scripting engine to delegate to.
*/
private ScriptEngine engine;
public ScriptEngineWrapper(ScriptEngine engine) {
this.engine = engine;
}
public ScriptEngine getEngine() {
return engine;
}
/**
* Evaluates a given expression in a context which is extended with the
* provided imports
*
* The imports are on purpose not added to the global scope to prevent
* pollution of the namespace.
*
* @param script
* Script to be executed.
* @param imports
* List of imports.
* @return The result.
* @throws ScriptException
* On script execution errors.
*/
public Object eval(String script, List<String> imports)
throws ScriptException {
if (!imports.isEmpty()) {
script = "(function() { with (new JavaImporter("
+ toImportString(imports) + ")) { return " + script
+ " ; }}).call(this);";
}
return engine.eval(script);
}
/**
* Converts a list of imports like List("foo.Foo", "foo.bar.*") into one
* string "foo.Foo, foo.bar"
*/
private String toImportString(List<String> imports) {
StringBuffer out = new StringBuffer();
String delim = "";
for (String i : imports) {
out.append(delim).append(stripWildcard(i));
delim = ", ";
}
return out.toString();
}
private String stripWildcard(String imp) {
return isWildcard(imp) ? imp.substring(0, imp.length() - 2) : imp;
}
private boolean isWildcard(String imp) {
return Pattern.matches("(.*)\\.\\*$", imp);
}
public static ScriptEngineWrapper newInstance() {
ScriptEngine engine = new ScriptEngineManager()
.getEngineByName("JavaScript");
if (engine == null) {
System.err.println("Warning: cannot find JavaScript engine");
} else
try {
// Add java.lang to the global namespace
engine.eval("importPackage(java.lang)");
} catch (Throwable t1) {
// Try again with compatibility library
try {
engine.eval("load(\"nashorn:mozilla_compat.js\");\n importPackage(java.lang)");
} catch (Throwable t2) {
// Also didn't work
System.err
.println("Warning: error importing java.lang package in JavaScript engine");
}
}
return new ScriptEngineWrapper(engine);
}
}