1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.jexl3.internal;
18
19 import java.util.List;
20 import java.util.Map;
21 import java.util.Objects;
22 import java.util.Set;
23
24 import org.apache.commons.jexl3.JexlContext;
25 import org.apache.commons.jexl3.JexlEngine;
26 import org.apache.commons.jexl3.JexlExpression;
27 import org.apache.commons.jexl3.JexlFeatures;
28 import org.apache.commons.jexl3.JexlInfo;
29 import org.apache.commons.jexl3.JexlOptions;
30 import org.apache.commons.jexl3.JexlScript;
31 import org.apache.commons.jexl3.parser.ASTJexlScript;
32
33
34
35
36 public class Script implements JexlScript, JexlExpression {
37
38
39
40 public class Callable implements java.util.concurrent.Callable<Object> {
41
42 protected final Interpreter interpreter;
43
44 protected volatile Object result;
45
46
47
48
49
50 protected Callable(final Interpreter intrprtr) {
51 this.interpreter = intrprtr;
52 this.result = intrprtr;
53 }
54
55 @Override
56 public Object call() throws Exception {
57 synchronized(this) {
58 if (result == interpreter) {
59 checkCacheVersion();
60 result = interpret();
61 }
62 return result;
63 }
64 }
65
66
67
68
69
70 public boolean cancel() {
71 return interpreter.cancel();
72 }
73
74
75
76
77
78 protected Object interpret() {
79 return interpreter.interpret(script);
80 }
81
82
83
84
85 public boolean isCancellable() {
86 return interpreter.isCancellable();
87 }
88
89
90
91
92 public boolean isCancelled() {
93 return interpreter.isCancelled();
94 }
95 }
96
97
98
99 protected final Engine jexl;
100
101
102
103 protected final String source;
104
105
106
107 protected final ASTJexlScript script;
108
109
110
111
112 protected int version;
113
114
115
116
117
118
119
120
121 protected Script(final Engine engine, final String expr, final ASTJexlScript ref) {
122 jexl = engine;
123 source = expr;
124 script = ref;
125 version = jexl.getUberspect().getVersion();
126 }
127
128
129
130
131
132
133
134
135 @Override
136 public Callable callable(final JexlContext context) {
137 return callable(context, (Object[]) null);
138 }
139
140
141
142
143
144
145
146
147
148 @Override
149 public Callable callable(final JexlContext context, final Object... args) {
150 return new Callable(createInterpreter(context, script.createFrame(args)));
151 }
152
153
154
155
156
157
158
159
160
161 protected void checkCacheVersion() {
162 final int uberVersion = jexl.getUberspect().getVersion();
163 if (version != uberVersion) {
164
165 if (version > 0) {
166 script.clearCache();
167 }
168 version = uberVersion;
169 }
170 }
171
172
173
174
175
176
177 protected Frame createFrame(final Object[] args) {
178 return script.createFrame(args);
179 }
180
181
182
183
184
185
186
187 protected Interpreter createInterpreter(final JexlContext context, final Frame frame) {
188 return createInterpreter(context, frame, null);
189 }
190
191
192
193
194
195
196
197
198 protected Interpreter createInterpreter(final JexlContext context, final Frame frame, final JexlOptions options) {
199 return jexl.createInterpreter(context, frame, options != null ? options : jexl.evalOptions(script, context));
200 }
201
202 @Override
203 public JexlScript curry(final Object... args) {
204 final String[] parms = script.getParameters();
205 if (parms == null || parms.length == 0) {
206 return this;
207 }
208 return new Closure(this, args);
209 }
210
211 @Override
212 public boolean equals(final Object obj) {
213 if (obj == null) {
214 return false;
215 }
216 if (getClass() != obj.getClass()) {
217 return false;
218 }
219 final Script other = (Script) obj;
220 if (this.jexl != other.jexl) {
221 return false;
222 }
223 if (!Objects.equals(this.source, other.source)) {
224 return false;
225 }
226 return true;
227 }
228
229 @Override
230 public Object evaluate(final JexlContext context) {
231 return execute(context);
232 }
233
234 @Override
235 public Object execute(final JexlContext context) {
236 checkCacheVersion();
237 final Frame frame = createFrame(null);
238 final Interpreter interpreter = createInterpreter(context, frame);
239 return interpreter.interpret(script);
240 }
241
242 @Override
243 public Object execute(final JexlContext context, final Object... args) {
244 checkCacheVersion();
245 final Frame frame = createFrame(args != null && args.length > 0 ? args : null);
246 final Interpreter interpreter = createInterpreter(context, frame);
247 return interpreter.interpret(script);
248 }
249
250
251
252
253
254 public String[] getCapturedVariables() {
255 return script.getCapturedVariables();
256 }
257
258
259
260
261 public JexlEngine getEngine() {
262 return jexl;
263 }
264
265
266
267
268 public JexlFeatures getFeatures() {
269 return script.getFeatures();
270 }
271
272
273
274
275 public JexlInfo getInfo() {
276 return script.jexlInfo();
277 }
278
279 @Override
280 public String[] getLocalVariables() {
281 return script.getLocalVariables();
282 }
283
284 @Override
285 public String[] getParameters() {
286 return script.getParameters();
287 }
288
289 @Override
290 public String getParsedText() {
291 return getParsedText(2);
292 }
293
294 @Override
295 public String getParsedText(final int indent) {
296 final Debugger debug = new Debugger();
297 debug.outputPragmas(true).indentation(indent).debug(script, false);
298 return debug.toString();
299 }
300
301
302
303
304
305
306 @Override
307 public Map<String, Object> getPragmas() {
308 return script.getPragmas();
309 }
310
311
312
313
314 protected ASTJexlScript getScript() {
315 return script;
316 }
317
318 @Override
319 public String getSourceText() {
320 return source;
321 }
322
323 @Override
324 public String[] getUnboundParameters() {
325 return getParameters();
326 }
327
328
329
330
331
332
333
334 @Override
335 public Set<List<String>> getVariables() {
336 return jexl.getVariables(script);
337 }
338
339 @Override
340 public int hashCode() {
341
342 int hash = 17;
343 hash = 31 * hash + (this.jexl != null ? this.jexl.hashCode() : 0);
344 hash = 31 * hash + (this.source != null ? this.source.hashCode() : 0);
345 return hash;
346
347 }
348
349 @Override
350 public String toString() {
351 CharSequence src = source;
352 if (src == null) {
353 final Debugger debug = new Debugger();
354 debug.debug(script, false);
355 src = debug.toString();
356 }
357 return src.toString();
358 }
359 }