Statistics
| Revision:

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 679 jjdelcerro
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 1112 jjdelcerro
import java.util.List;
9 679 jjdelcerro
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 1023 jjdelcerro
32
    public PythonInterpreter getPythonInterpreter() {
33
        return this.interp;
34
    }
35 679 jjdelcerro
36 1112 jjdelcerro
    @Override
37 679 jjdelcerro
    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 1112 jjdelcerro
    @Override
54 679 jjdelcerro
    public Object eval(Reader reader, ScriptContext context) throws ScriptException {
55
        return eval(compileScript(reader, context), context);
56
    }
57
58 1112 jjdelcerro
    @Override
59 679 jjdelcerro
    public Bindings createBindings() {
60
        return new SimpleBindings();
61
    }
62
63 1112 jjdelcerro
    @Override
64 679 jjdelcerro
    public ScriptEngineFactory getFactory() {
65
        return factory;
66
    }
67
68 1112 jjdelcerro
    @Override
69 679 jjdelcerro
    public CompiledScript compile(String script) throws ScriptException {
70
        return new PyCompiledScript(compileScript(script, context));
71
    }
72
73 1112 jjdelcerro
    @Override
74 679 jjdelcerro
    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 1112 jjdelcerro
    @Override
105 679 jjdelcerro
    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 1112 jjdelcerro
    @Override
155 679 jjdelcerro
    public <T> T getInterface(Class<T> clazz) {
156
        return getInterface(new PyModule("__jsr223__", interp.getLocals()), clazz);
157
    }
158
159 1112 jjdelcerro
    @Override
160 679 jjdelcerro
    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 1112 jjdelcerro
                @Override
175 679 jjdelcerro
                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 1112 jjdelcerro
        ScriptException se;
198 679 jjdelcerro
        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 1112 jjdelcerro
        private final PyCode code;
240 679 jjdelcerro
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 1112 jjdelcerro
255 679 jjdelcerro
    }
256
257 1112 jjdelcerro
    @Override
258 679 jjdelcerro
    public void close() {
259
        interp.close();
260
    }
261 1112 jjdelcerro
262
    public List<String> getLocalNames() {
263
        PyScriptEngineScope locals = (PyScriptEngineScope) interp.getLocals();
264
        PyList names = (PyList) locals.scope_keys();
265
        return names;
266
    }
267
268 679 jjdelcerro
}