src.org.python.jsr223.PyScriptEngine Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jython Show documentation
Show all versions of jython Show documentation
Jython is an implementation of the high-level, dynamic, object-oriented
language Python written in 100% Pure Java, and seamlessly integrated with
the Java platform. It thus allows you to run Python on any Java platform.
package org.python.jsr223;
import java.lang.reflect.Method;
import org.python.core.*;
import java.io.Reader;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import javax.script.AbstractScriptEngine;
import javax.script.Bindings;
import javax.script.Compilable;
import javax.script.CompiledScript;
import javax.script.Invocable;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptException;
import javax.script.SimpleBindings;
import org.python.util.PythonInterpreter;
public class PyScriptEngine extends AbstractScriptEngine implements Compilable, Invocable {
private final PythonInterpreter interp;
private final ScriptEngineFactory factory;
PyScriptEngine(ScriptEngineFactory factory) {
this.factory = factory;
interp = PythonInterpreter.threadLocalStateInterpreter(new PyScriptEngineScope(this, context));
}
public Object eval(String script, ScriptContext context) throws ScriptException {
return eval(compileScript(script, context), context);
}
private Object eval(PyCode code, ScriptContext context) throws ScriptException {
try {
interp.setIn(context.getReader());
interp.setOut(context.getWriter());
interp.setErr(context.getErrorWriter());
interp.setLocals(new PyScriptEngineScope(this, context));
return interp.eval(code).__tojava__(Object.class);
} catch (PyException pye) {
throw scriptException(pye);
}
}
public Object eval(Reader reader, ScriptContext context) throws ScriptException {
return eval(compileScript(reader, context), context);
}
public Bindings createBindings() {
return new SimpleBindings();
}
public ScriptEngineFactory getFactory() {
return factory;
}
public CompiledScript compile(String script) throws ScriptException {
return new PyCompiledScript(compileScript(script, context));
}
public CompiledScript compile(Reader reader) throws ScriptException {
return new PyCompiledScript(compileScript(reader, context));
}
private PyCode compileScript(String script, ScriptContext context) throws ScriptException {
try {
String filename = (String) context.getAttribute(ScriptEngine.FILENAME);
if (filename == null) {
return interp.compile(script);
} else {
return interp.compile(script, filename);
}
} catch (PyException pye) {
throw scriptException(pye);
}
}
private PyCode compileScript(Reader reader, ScriptContext context) throws ScriptException {
try {
String filename = (String) context.getAttribute(ScriptEngine.FILENAME);
if (filename == null) {
return interp.compile(reader);
} else {
return interp.compile(reader, filename);
}
} catch (PyException pye) {
throw scriptException(pye);
}
}
public Object invokeMethod(Object thiz, String name, Object... args) throws ScriptException,
NoSuchMethodException {
try {
interp.setLocals(new PyScriptEngineScope(this, context));
if (!(thiz instanceof PyObject)) {
thiz = Py.java2py(thiz);
}
PyObject method = ((PyObject) thiz).__findattr__(name);
if (method == null) {
throw new NoSuchMethodException(name);
}
//return method.__call__(Py.javas2pys(args)).__tojava__(Object.class);
PyObject result;
if(args != null) {
result = method.__call__(Py.javas2pys(args));
} else {
result = method.__call__();
}
return result.__tojava__(Object.class);
} catch (PyException pye) {
throw scriptException(pye);
}
}
public Object invokeFunction(String name, Object... args) throws ScriptException,
NoSuchMethodException {
try {
interp.setLocals(new PyScriptEngineScope(this, context));
PyObject function = interp.get(name);
if (function == null) {
throw new NoSuchMethodException(name);
}
PyObject result;
if(args != null) {
result = function.__call__(Py.javas2pys(args));
} else {
result = function.__call__();
}
return result.__tojava__(Object.class);
} catch (PyException pye) {
throw scriptException(pye);
}
}
public T getInterface(Class clazz) {
return getInterface(new PyModule("__jsr223__", interp.getLocals()), clazz);
}
public T getInterface(Object obj, Class clazz) {
if (obj == null) {
throw new IllegalArgumentException("object expected");
}
if (clazz == null || !clazz.isInterface()) {
throw new IllegalArgumentException("interface expected");
}
interp.setLocals(new PyScriptEngineScope(this, context));
final PyObject thiz = Py.java2py(obj);
@SuppressWarnings("unchecked")
T proxy = (T) Proxy.newProxyInstance(
clazz.getClassLoader(),
new Class[] { clazz },
new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
interp.setLocals(new PyScriptEngineScope(PyScriptEngine.this, context));
PyObject pyMethod = thiz.__findattr__(method.getName());
if (pyMethod == null)
throw new NoSuchMethodException(method.getName());
PyObject result;
if(args != null) {
result = pyMethod.__call__(Py.javas2pys(args));
} else {
result = pyMethod.__call__();
}
return result.__tojava__(Object.class);
} catch (PyException pye) {
throw scriptException(pye);
}
}
});
return proxy;
}
private static ScriptException scriptException(PyException pye) {
ScriptException se = null;
try {
pye.normalize();
PyObject type = pye.type;
PyObject value = pye.value;
PyTraceback tb = pye.traceback;
if (__builtin__.isinstance(value, Py.SyntaxError)) {
PyObject filename = value.__findattr__("filename");
PyObject lineno = value.__findattr__("lineno");
PyObject offset = value.__findattr__("offset");
value = value.__findattr__("msg");
se = new ScriptException(
Py.formatException(type, value),
filename == null ? "