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