package org.dynjs.jsr223;
import org.dynjs.runtime.Compiler;
import org.dynjs.runtime.*;
import org.dynjs.runtime.linker.DynJSBootstrapper;
import org.dynjs.runtime.linker.java.jsimpl.JSJavaImplementationManager;
import org.dynjs.runtime.source.ReaderSourceProvider;
import javax.script.*;
import java.io.IOException;
import java.io.Reader;
/**
* @author Bob McWhirter
*/
public class DynJSScriptEngine extends AbstractScriptEngine implements Compilable, Invocable {
public static final String GLOBAL_OBJECT = "org.dynjs.global-object";
private final DynJSScriptEngineFactory factory;
DynJSScriptEngine(DynJSScriptEngineFactory factory) {
this.factory = factory;
this.context = new SimpleScriptContext();
this.context.setBindings(factory.getGlobalBindings(), ScriptContext.GLOBAL_SCOPE);
}
@Override
public DynJSCompiledScript compile(String script) throws ScriptException {
Compiler compiler = new DynJS().newCompiler();
try {
JSProgram program = compiler.withSource(script).compile();
return new DynJSCompiledScript(this, program);
} catch (IOException e) {
throw new ScriptException(e);
}
}
@Override
public DynJSCompiledScript compile(Reader script) throws ScriptException {
Compiler compiler = new DynJS().newCompiler();
try {
JSProgram program = compiler.withSource( new ReaderSourceProvider(script) ).compile();
return new DynJSCompiledScript(this, program);
} catch (IOException e) {
throw new ScriptException(e);
}
}
@Override
public Object eval(String script, ScriptContext context) throws ScriptException {
DynJSCompiledScript program = compile(script);
return program.eval(context);
//ScriptEngineGlobalObject global = getGlobalObject( context );
//DynJS runtime = getRuntime( global, context );
//return runtime.newRunner().withSource( script ).execute();
}
@Override
public Object eval(Reader reader, ScriptContext context) throws ScriptException {
DynJSCompiledScript program = compile(reader);
return program.eval(context);
}
@Override
public Bindings createBindings() {
return new SimpleBindings();
}
@Override
public ScriptEngineFactory getFactory() {
return this.factory;
}
@Override
public Object invokeMethod(Object thiz, String name, Object... args) throws ScriptException, NoSuchMethodException {
if (!(thiz instanceof JSObject)) {
throw new IllegalArgumentException("'this' should be an instance of " + JSObject.class.getName());
}
ScriptEngineGlobalObject global = RuntimeHelper.getGlobalObject(this.context);
DynJS runtime = RuntimeHelper.getRuntime(global, this.context);
Object property = ((JSObject) thiz).get(runtime.getDefaultExecutionContext(), name);
if (property == Types.UNDEFINED) {
throw new NoSuchMethodException("No such property '" + name + "'");
}
if (!(property instanceof JSFunction)) {
throw new ScriptException("Property '" + name + "' is not a function");
}
JSFunction function = (JSFunction) property;
return runtime.getDefaultExecutionContext().call(function, thiz, args);
}
@Override
public Object invokeFunction(String name, Object... args) throws ScriptException, NoSuchMethodException {
ScriptEngineGlobalObject global = RuntimeHelper.getGlobalObject(this.context);
return invokeMethod(global, name, args);
}
@Override
public <T> T getInterface(Class<T> clasz) {
ScriptEngineGlobalObject global = RuntimeHelper.getGlobalObject(this.context);
return getInterface(global, clasz);
}
@Override
public <T> T getInterface(Object thiz, Class<T> clasz) {
if (!(thiz instanceof JSObject)) {
throw new IllegalArgumentException("'this' should be an instance of " + JSObject.class.getName());
}
ScriptEngineGlobalObject global = RuntimeHelper.getGlobalObject(this.context);
DynJS runtime = RuntimeHelper.getRuntime(global, this.context);
JSJavaImplementationManager manager = DynJSBootstrapper.JAVA_IMPLEMENTATION_MANAGER;
try {
return ((T) manager.getImplementationWrapper(clasz, runtime.getDefaultExecutionContext(), (JSObject) thiz));
} catch (Exception e) {
return null;
}
}
}