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-standalone Show documentation
Show all versions of jython-standalone 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;
private final PyModule module;
PyScriptEngine(ScriptEngineFactory factory) {
this.factory = factory;
interp = new PythonInterpreter(new PyScriptEngineScope(this, context));
module = (PyModule)Py.getSystemState().modules.__finditem__("__main__");
}
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());
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 {
if (!(thiz instanceof PyObject)) {
thiz = Py.java2py(thiz);
}
return ((PyObject) thiz).invoke(name, Py.javas2pys(args)).__tojava__(Object.class);
} catch (PyException pye) {
return throwInvokeException(pye, name);
}
}
public Object invokeFunction(String name, Object... args) throws ScriptException,
NoSuchMethodException {
try {
PyObject function = interp.get(name);
if (function == null) {
throw new NoSuchMethodException(name);
}
return function.__call__(Py.javas2pys(args)).__tojava__(Object.class);
} catch (PyException pye) {
return throwInvokeException(pye, name);
}
}
public T getInterface(Class clazz) {
return getInterface(module, 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");
}
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 {
PyObject result = thiz.invoke(method.getName(), Py.javas2pys(args));
return result.__tojava__(Object.class);
} catch (PyException pye) {
return throwInvokeException(pye, method.getName());
}
}
});
return proxy;
}
private static Object throwInvokeException(PyException pye, String methodName)
throws ScriptException, NoSuchMethodException {
if (pye.match(Py.AttributeError)) {
throw new NoSuchMethodException(methodName);
}
throw scriptException(pye);
}
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 ? "