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