gvsig-scripting / org.gvsig.scripting / trunk / org.gvsig.scripting / org.gvsig.scripting.lib / org.gvsig.scripting.lib.impl / src / main / java / org / python / jsr223 / MyPyScriptEngine.java @ 1112
History | View | Annotate | Download (9.27 KB)
1 |
package org.python.jsr223; |
---|---|
2 |
|
3 |
import java.lang.reflect.Method; |
4 |
import org.python.core.*; |
5 |
import java.io.Reader; |
6 |
import java.lang.reflect.InvocationHandler; |
7 |
import java.lang.reflect.Proxy; |
8 |
import java.util.List; |
9 |
import javax.script.AbstractScriptEngine; |
10 |
import javax.script.Bindings; |
11 |
import javax.script.Compilable; |
12 |
import javax.script.CompiledScript; |
13 |
import javax.script.Invocable; |
14 |
import javax.script.ScriptContext; |
15 |
import javax.script.ScriptEngine; |
16 |
import javax.script.ScriptEngineFactory; |
17 |
import javax.script.ScriptException; |
18 |
import javax.script.SimpleBindings; |
19 |
import org.python.util.PythonInterpreter; |
20 |
|
21 |
public class MyPyScriptEngine extends AbstractScriptEngine implements Compilable, Invocable, AutoCloseable { |
22 |
|
23 |
//http://stackoverflow.com/questions/29543532/how-to-call-a-function-inside-a-python-script-and-pass-parameters-while-using-sc
|
24 |
private final PythonInterpreter interp; |
25 |
private final ScriptEngineFactory factory; |
26 |
|
27 |
public MyPyScriptEngine(ScriptEngineFactory factory) {
|
28 |
this.factory = factory;
|
29 |
interp = PythonInterpreter.threadLocalStateInterpreter(new PyScriptEngineScope(this, context)); |
30 |
} |
31 |
|
32 |
public PythonInterpreter getPythonInterpreter() {
|
33 |
return this.interp; |
34 |
} |
35 |
|
36 |
@Override
|
37 |
public Object eval(String script, ScriptContext context) throws ScriptException { |
38 |
return eval(compileScript(script, context), context);
|
39 |
} |
40 |
|
41 |
private Object eval(PyCode code, ScriptContext context) throws ScriptException { |
42 |
try {
|
43 |
interp.setIn(context.getReader()); |
44 |
interp.setOut(context.getWriter()); |
45 |
interp.setErr(context.getErrorWriter()); |
46 |
interp.setLocals(new PyScriptEngineScope(this, context)); |
47 |
return interp.eval(code).__tojava__(Object.class); |
48 |
} catch (PyException pye) {
|
49 |
throw scriptException(pye);
|
50 |
} |
51 |
} |
52 |
|
53 |
@Override
|
54 |
public Object eval(Reader reader, ScriptContext context) throws ScriptException { |
55 |
return eval(compileScript(reader, context), context);
|
56 |
} |
57 |
|
58 |
@Override
|
59 |
public Bindings createBindings() {
|
60 |
return new SimpleBindings(); |
61 |
} |
62 |
|
63 |
@Override
|
64 |
public ScriptEngineFactory getFactory() {
|
65 |
return factory;
|
66 |
} |
67 |
|
68 |
@Override
|
69 |
public CompiledScript compile(String script) throws ScriptException { |
70 |
return new PyCompiledScript(compileScript(script, context)); |
71 |
} |
72 |
|
73 |
@Override
|
74 |
public CompiledScript compile(Reader reader) throws ScriptException { |
75 |
return new PyCompiledScript(compileScript(reader, context)); |
76 |
} |
77 |
|
78 |
private PyCode compileScript(String script, ScriptContext context) throws ScriptException { |
79 |
try {
|
80 |
String filename = (String) context.getAttribute(ScriptEngine.FILENAME); |
81 |
if (filename == null) { |
82 |
return interp.compile(script);
|
83 |
} else {
|
84 |
return interp.compile(script, filename);
|
85 |
} |
86 |
} catch (PyException pye) {
|
87 |
throw scriptException(pye);
|
88 |
} |
89 |
} |
90 |
|
91 |
private PyCode compileScript(Reader reader, ScriptContext context) throws ScriptException { |
92 |
try {
|
93 |
String filename = (String) context.getAttribute(ScriptEngine.FILENAME); |
94 |
if (filename == null) { |
95 |
return interp.compile(reader);
|
96 |
} else {
|
97 |
return interp.compile(reader, filename);
|
98 |
} |
99 |
} catch (PyException pye) {
|
100 |
throw scriptException(pye);
|
101 |
} |
102 |
} |
103 |
|
104 |
@Override
|
105 |
public Object invokeMethod(Object thiz, String name, Object... args) throws ScriptException, |
106 |
NoSuchMethodException {
|
107 |
try {
|
108 |
interp.setLocals(new PyScriptEngineScope(this, context)); |
109 |
if (!(thiz instanceof PyObject)) { |
110 |
thiz = Py.java2py(thiz); |
111 |
} |
112 |
PyObject method = ((PyObject) thiz).__findattr__(name); |
113 |
if (method == null) { |
114 |
throw new NoSuchMethodException(name); |
115 |
} |
116 |
//return method.__call__(Py.javas2pys(args)).__tojava__(Object.class);
|
117 |
PyObject result; |
118 |
if(args != null) { |
119 |
result = method.__call__(Py.javas2pys(args)); |
120 |
} else {
|
121 |
result = method.__call__(); |
122 |
} |
123 |
return result.__tojava__(Object.class); |
124 |
} catch (PyException pye) {
|
125 |
throw scriptException(pye);
|
126 |
} |
127 |
} |
128 |
|
129 |
@Override
|
130 |
public Object invokeFunction(String name, Object... args) throws ScriptException, |
131 |
NoSuchMethodException {
|
132 |
try {
|
133 |
interp.setIn(context.getReader()); |
134 |
interp.setOut(context.getWriter()); |
135 |
interp.setErr(context.getErrorWriter()); |
136 |
interp.setLocals(new PyScriptEngineScope(this, context)); |
137 |
PyObject function = interp.get(name); |
138 |
if (function == null) { |
139 |
throw new NoSuchMethodException(name); |
140 |
} |
141 |
PyObject result; |
142 |
ThreadState state = new ThreadState(this.interp.getSystemState()); |
143 |
if(args != null) { |
144 |
result = function.__call__(state,Py.javas2pys(args)); |
145 |
} else {
|
146 |
result = function.__call__(state); |
147 |
} |
148 |
return result.__tojava__(Object.class); |
149 |
} catch (PyException pye) {
|
150 |
throw scriptException(pye);
|
151 |
} |
152 |
} |
153 |
|
154 |
@Override
|
155 |
public <T> T getInterface(Class<T> clazz) { |
156 |
return getInterface(new PyModule("__jsr223__", interp.getLocals()), clazz); |
157 |
} |
158 |
|
159 |
@Override
|
160 |
public <T> T getInterface(Object obj, Class<T> clazz) { |
161 |
if (obj == null) { |
162 |
throw new IllegalArgumentException("object expected"); |
163 |
} |
164 |
if (clazz == null || !clazz.isInterface()) { |
165 |
throw new IllegalArgumentException("interface expected"); |
166 |
} |
167 |
interp.setLocals(new PyScriptEngineScope(this, context)); |
168 |
final PyObject thiz = Py.java2py(obj);
|
169 |
@SuppressWarnings("unchecked") |
170 |
T proxy = (T) Proxy.newProxyInstance(
|
171 |
clazz.getClassLoader(), |
172 |
new Class[] { clazz }, |
173 |
new InvocationHandler() { |
174 |
@Override
|
175 |
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { |
176 |
try {
|
177 |
interp.setLocals(new PyScriptEngineScope(MyPyScriptEngine.this, context));
|
178 |
PyObject pyMethod = thiz.__findattr__(method.getName()); |
179 |
if (pyMethod == null) |
180 |
throw new NoSuchMethodException(method.getName()); |
181 |
PyObject result; |
182 |
if(args != null) { |
183 |
result = pyMethod.__call__(Py.javas2pys(args)); |
184 |
} else {
|
185 |
result = pyMethod.__call__(); |
186 |
} |
187 |
return result.__tojava__(Object.class); |
188 |
} catch (PyException pye) {
|
189 |
throw scriptException(pye);
|
190 |
} |
191 |
} |
192 |
}); |
193 |
return proxy;
|
194 |
} |
195 |
|
196 |
private static ScriptException scriptException(PyException pye) { |
197 |
ScriptException se; |
198 |
try {
|
199 |
pye.normalize(); |
200 |
|
201 |
PyObject type = pye.type; |
202 |
PyObject value = pye.value; |
203 |
PyTraceback tb = pye.traceback; |
204 |
|
205 |
if (__builtin__.isinstance(value, Py.SyntaxError)) {
|
206 |
PyObject filename = value.__findattr__("filename");
|
207 |
PyObject lineno = value.__findattr__("lineno");
|
208 |
PyObject offset = value.__findattr__("offset");
|
209 |
value = value.__findattr__("msg");
|
210 |
|
211 |
se = new ScriptException(
|
212 |
Py.formatException(type, value), |
213 |
filename == null ? "<script>" : filename.toString(), |
214 |
lineno == null ? 0 : lineno.asInt(), |
215 |
offset == null ? 0 : offset.asInt()); |
216 |
} else if (tb != null) { |
217 |
String filename;
|
218 |
if (tb.tb_frame == null || tb.tb_frame.f_code == null) { |
219 |
filename = null;
|
220 |
} else {
|
221 |
filename = tb.tb_frame.f_code.co_filename; |
222 |
} |
223 |
se = new ScriptException(
|
224 |
Py.formatException(type, value), |
225 |
filename, |
226 |
tb.tb_lineno); |
227 |
} else {
|
228 |
se = new ScriptException(Py.formatException(type, value));
|
229 |
} |
230 |
se.initCause(pye); |
231 |
return se;
|
232 |
} catch (Exception ee) { |
233 |
se = new ScriptException(pye);
|
234 |
} |
235 |
return se;
|
236 |
} |
237 |
|
238 |
private class PyCompiledScript extends CompiledScript { |
239 |
private final PyCode code; |
240 |
|
241 |
PyCompiledScript(PyCode code) { |
242 |
this.code = code;
|
243 |
} |
244 |
|
245 |
@Override
|
246 |
public ScriptEngine getEngine() {
|
247 |
return MyPyScriptEngine.this;
|
248 |
} |
249 |
|
250 |
@Override
|
251 |
public Object eval(ScriptContext ctx) throws ScriptException { |
252 |
return MyPyScriptEngine.this.eval(code, ctx);
|
253 |
} |
254 |
|
255 |
} |
256 |
|
257 |
@Override
|
258 |
public void close() { |
259 |
interp.close(); |
260 |
} |
261 |
|
262 |
public List<String> getLocalNames() { |
263 |
PyScriptEngineScope locals = (PyScriptEngineScope) interp.getLocals(); |
264 |
PyList names = (PyList) locals.scope_keys(); |
265 |
return names;
|
266 |
} |
267 |
|
268 |
} |