1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.jexl3;
18
19 import java.math.BigDecimal;
20 import java.math.BigInteger;
21 import java.util.Collections;
22 import java.util.Map;
23 import java.util.Set;
24 import java.util.TreeMap;
25 import java.util.concurrent.ConcurrentHashMap;
26 import java.util.concurrent.ConcurrentMap;
27 import java.util.concurrent.atomic.AtomicInteger;
28
29 import org.junit.Assert;
30 import org.junit.Test;
31
32
33
34
35 public class PragmaTest extends JexlTestCase {
36
37
38
39 public PragmaTest() {
40 super("PragmaTest");
41 }
42
43
44
45
46 @Test
47 @SuppressWarnings("AssertEqualsBetweenInconvertibleTypes")
48 public void testPragmas() {
49 final JexlScript script = JEXL.createScript("#pragma one 1\n#pragma the.very.hard 'truth'\n2;");
50 Assert.assertNotNull(script);
51 final Map<String, Object> pragmas = script.getPragmas();
52 Assert.assertEquals(2, pragmas.size());
53 Assert.assertEquals(1, pragmas.get("one"));
54 Assert.assertEquals("truth", pragmas.get("the.very.hard"));
55 }
56
57 @Test
58 @SuppressWarnings("AssertEqualsBetweenInconvertibleTypes")
59 public void testJxltPragmas() {
60 final JxltEngine engine = new JexlBuilder().create().createJxltEngine();
61 final JxltEngine.Template tscript = engine.createTemplate("$$ #pragma one 1\n$$ #pragma the.very.hard 'truth'\n2;");
62 Assert.assertNotNull(tscript);
63 final Map<String, Object> pragmas = tscript.getPragmas();
64 Assert.assertEquals(2, pragmas.size());
65 Assert.assertEquals(1, pragmas.get("one"));
66 Assert.assertEquals("truth", pragmas.get("the.very.hard"));
67 }
68
69 public static class SafeContext extends JexlEvalContext {
70
71 public void processPragmas(final Map<String, Object> pragmas) {
72 if (pragmas != null && !pragmas.isEmpty()) {
73 final JexlOptions options = getEngineOptions();
74 for (final Map.Entry<String, Object> pragma : pragmas.entrySet()) {
75 final String key = pragma.getKey();
76 final Object value = pragma.getValue();
77 if ("jexl.safe".equals(key) && value instanceof Boolean) {
78 options.setSafe((Boolean) value);
79 } else if ("jexl.strict".equals(key) && value instanceof Boolean) {
80 options.setStrict((Boolean) value);
81 } else if ("jexl.silent".equals(key) && value instanceof Boolean) {
82 options.setSilent((Boolean) value);
83 }
84 }
85 }
86 }
87
88
89
90
91
92 public void sleep(final long ms) {
93 try {
94 Thread.sleep(ms);
95 } catch (final InterruptedException e) {
96
97 }
98 }
99 }
100
101 @Test
102 @SuppressWarnings("AssertEqualsBetweenInconvertibleTypes")
103 public void testSafePragma() {
104 SafeContext jc = new SafeContext();
105 jc.set("foo", null);
106 final JexlScript script = JEXL.createScript("#pragma jexl.safe true\nfoo.bar;");
107 Assert.assertNotNull(script);
108 jc.processPragmas(script.getPragmas());
109 Object result = script.execute(jc);
110 Assert.assertNull(result);
111 jc = new SafeContext();
112 jc.set("foo", null);
113 try {
114 script.execute(jc);
115 Assert.fail("should have thrown");
116 } catch (final JexlException xvar) {
117
118 }
119 }
120
121 public static class ModuleContext extends MapContext {
122 protected final Map<String, JexlScript> sources = new TreeMap<>();
123
124 ModuleContext() { }
125 public Object script(String name) {
126 return sources.get(name);
127 }
128
129 void script(String name, JexlScript script) { sources.put(name, script); }
130 }
131
132 public static class CachingModuleContext extends ModuleContext implements JexlContext.ModuleProcessor {
133 private final ConcurrentMap<String, Object> modules = new ConcurrentHashMap<>();
134 private final AtomicInteger count = new AtomicInteger(0);
135
136 public int getCountCompute() {
137 return count.get();
138 }
139
140 CachingModuleContext() {
141 }
142
143 @Override
144 public Object processModule(JexlEngine engine, JexlInfo info, String name, final String body) {
145 if (body.isEmpty()) {
146 modules.remove(name);
147 return null;
148 }
149 return modules.computeIfAbsent(name, (n) -> {
150 Object module = engine.createExpression(info, body).evaluate(this);
151 if (module instanceof JexlScript) {
152 module = ((JexlScript) module).execute(this);
153 }
154 count.incrementAndGet();
155 return module;
156 });
157 }
158 }
159
160 @Test public void testPragmaModuleNoCache() {
161 ModuleContext ctxt = new ModuleContext();
162 runPragmaModule(ctxt, null);
163 }
164 @Test public void testPragmaModuleCache() {
165 CachingModuleContext ctxt = new CachingModuleContext();
166 runPragmaModule(ctxt, ctxt);
167 }
168 void runPragmaModule(ModuleContext ctxt, CachingModuleContext cmCtxt) {
169 ctxt.script("module0", JEXL.createScript("function f42(x) { 42 + x; } function f43(x) { 43 + x; }; { 'f42' : f42, 'f43' : f43 }"));
170 ConcurrentMap<String, Object> modules = new ConcurrentHashMap<>();
171 JexlScript script ;
172 Object result ;
173 script = JEXL.createScript("#pragma jexl.module.m0 \"script('module0')\"\n m0:f42(10);");
174 result = script.execute(ctxt);
175 Assert.assertEquals(52, result);
176 if (cmCtxt != null) {
177 Assert.assertEquals(1, cmCtxt.getCountCompute());
178 }
179 result = script.execute(ctxt);
180 Assert.assertEquals(52, result);
181 if (cmCtxt != null) {
182 Assert.assertEquals(1, cmCtxt.getCountCompute());
183 }
184 script = JEXL.createScript("#pragma jexl.module.m0 \"script('module0')\"\n m0:f43(10);");
185 result = script.execute(ctxt);
186 Assert.assertEquals(53, result);
187 if (cmCtxt != null) {
188 Assert.assertEquals(1, cmCtxt.getCountCompute());
189 }
190 try {
191 script = JEXL.createScript("#pragma jexl.module.m0 ''\n#pragma jexl.module.m0 \"fubar('module0')\"\n m0:f43(10);");
192 result = script.execute(ctxt);
193 Assert.fail("fubar sshoud fail");
194 } catch(JexlException.Method xmethod) {
195 Assert.assertEquals("fubar", xmethod.getMethod());
196 }
197 }
198
199
200 public static class StaticSleeper {
201
202 private StaticSleeper() {}
203
204 public static void sleep(final long ms) {
205 try {
206 Thread.sleep(ms);
207 } catch (final InterruptedException e) {
208
209 }
210 }
211 }
212
213 public static class Sleeper {
214 public void sleep(final long ms) {
215 try {
216 Thread.sleep(ms);
217 } catch (final InterruptedException e) {
218
219 }
220 }
221 }
222
223 @Test
224 public void testImportPragmaValueSet() {
225 String src =
226 "#pragma jexl.import java.util\n"+
227 "#pragma jexl.import java.io\n"+
228 "#pragma jexl.import java.net\n"+
229 "42";
230 final JexlScript script = JEXL.createScript(src);
231 Map<String, Object> pragmas = script.getPragmas();
232 Object importz = pragmas.get("jexl.import");
233 Assert.assertTrue(importz instanceof Set<?>);
234 Set<String> importzz = (Set<String>) importz;
235 Assert.assertTrue(importzz.contains("java.util"));
236 Assert.assertTrue(importzz.contains("java.io"));
237 Assert.assertTrue(importzz.contains("java.net"));
238 Assert.assertEquals(3, importzz.size());
239 String parsed = script.getParsedText();
240 Assert.assertEquals(src, parsed);
241 }
242 @Test
243 public void testPragmaOptions1() {
244 final String str = "i; #pragma jexl.options '-strict'\n";
245 final JexlEngine jexl = new JexlBuilder()
246 .features(new JexlFeatures().pragmaAnywhere(false))
247 .strict(true).create();
248 final JexlContext ctxt = new MapContext();
249 try {
250 final JexlScript e = jexl.createScript(str);
251 Assert.fail("i should not be resolved");
252 } catch (final JexlException xany) {
253 Assert.assertNotNull(xany);
254 }
255 }
256 @Test
257 public void testImportPragmaDisabled() {
258 String src =
259 "#pragma jexl.import java.util\n"+
260 "#pragma jexl.import java.io\n"+
261 "#pragma jexl.import java.net\n"+
262 "42";
263 JexlFeatures features = new JexlFeatures();
264 features.importPragma(false);
265 final JexlEngine jexl = new JexlBuilder().features(features).create();
266 try {
267 final JexlScript script = jexl.createScript(src);
268 } catch(JexlException.Parsing xparse) {
269 Assert.assertTrue(xparse.getMessage().contains("import pragma"));
270 }
271 }
272 @Test
273 public void testNamespacePragmaDisabled() {
274 JexlFeatures features = new JexlFeatures();
275 features.namespacePragma(false);
276 final JexlEngine jexl = new JexlBuilder().features(features).create();
277 try {
278 final JexlScript src = jexl.createScript(
279 "#pragma jexl.namespace.sleeper " + StaticSleeper.class.getName() + "\n"
280 + "sleeper:sleep(100);"
281 + "42");
282 Assert.fail("should have thrown syntax exception");
283 } catch(JexlException.Parsing xparse) {
284 Assert.assertTrue(xparse.getMessage().contains("namespace pragma"));
285 }
286 }
287 @Test
288 @SuppressWarnings("AssertEqualsBetweenInconvertibleTypes")
289 public void testStaticNamespacePragma() {
290 final JexlContext jc = new SafeContext();
291 final JexlScript script = JEXL.createScript(
292 "#pragma jexl.namespace.sleeper " + StaticSleeper.class.getName() + "\n"
293 + "sleeper:sleep(100);"
294 + "42");
295 final Object result = script.execute(jc);
296 Assert.assertEquals(42, result);
297 }
298
299 @Test
300 @SuppressWarnings("AssertEqualsBetweenInconvertibleTypes")
301 public void testStatictNamespacePragmaCtl() {
302 final Map<String, Object> ns = Collections.singletonMap("sleeper", StaticSleeper.class.getName());
303 final JexlEngine jexl = new JexlBuilder().namespaces(ns).create();
304 final JexlContext jc = new SafeContext();
305 final JexlScript script = jexl.createScript(
306 "sleeper:sleep(100);"
307 + "42");
308 final Object result = script.execute(jc);
309 Assert.assertEquals(42, result);
310 }
311
312 @Test
313 @SuppressWarnings("AssertEqualsBetweenInconvertibleTypes")
314 public void testNamespacePragma() {
315 final JexlContext jc = new SafeContext();
316 final String src =
317 "#pragma jexl.namespace.sleeper " + Sleeper.class.getName() + "\n"
318 + "sleeper:sleep(100);\n"
319 + "42;\n";
320 final JexlScript script = JEXL.createScript(src);
321 final Object result = script.execute(jc);
322 Assert.assertEquals(42, result);
323 String parsed = script.getParsedText();
324 Assert.assertEquals(src, parsed);
325 }
326
327 @Test
328 @SuppressWarnings("AssertEqualsBetweenInconvertibleTypes")
329 public void testNamespacePragmaCtl() {
330 final Map<String, Object> ns = Collections.singletonMap("sleeper", Sleeper.class.getName());
331 final JexlEngine jexl = new JexlBuilder().namespaces(ns).create();
332 final JexlContext jc = new SafeContext();
333 final JexlScript script = jexl.createScript(
334 "sleeper:sleep(100);"
335 + "42");
336 final Object result = script.execute(jc);
337 Assert.assertEquals(42, result);
338 }
339
340 @Test public void test354() {
341 Map<String, Number> values = new TreeMap<>();
342 values.put("1", 1);
343 values.put("+1", 1);
344 values.put("-1", -1);
345 values.put("1l", 1L);
346 values.put("+1l", 1L);
347 values.put("-1l", -1L);
348 values.put("10h", BigInteger.valueOf(10));
349 values.put("-11h", BigInteger.valueOf(-11));
350 values.put("+12h", BigInteger.valueOf(12));
351 values.put("0xa", 0xa);
352 values.put("+0xa", 0xa);
353 values.put("-0xa", -0xa);
354 values.put("0xacl", 0xacL);
355 values.put("+0xadl", 0xadL);
356 values.put("-0xafl", -0xafL);
357 values.put("1d", 1d);
358 values.put("-1d", -1d);
359 values.put("+1d", 1d);
360 values.put("1f", 1f);
361 values.put("-1f", -1f);
362 values.put("+1f", 1f);
363 values.put("1B", new BigDecimal(1));
364 values.put("-1B", new BigDecimal(-1));
365 values.put("+1B", new BigDecimal(1));
366 values.put("-42424242424242424242424242424242", new BigInteger("-42424242424242424242424242424242"));
367 values.put("+42424242424242424242424242424242", new BigInteger("+42424242424242424242424242424242"));
368 values.put("42424242424242424242424242424242", new BigInteger("42424242424242424242424242424242"));
369 JexlEngine jexl = new JexlBuilder().safe(true).create();
370 for(Map.Entry<String, Number> e : values.entrySet()) {
371 String text = "#pragma number " + e.getKey();
372 JexlScript script = jexl.createScript(text);
373 Assert.assertNotNull(script);
374 Map<String, Object> pragmas = script.getPragmas();
375 Assert.assertNotNull(pragmas);
376 Assert.assertEquals(e.getKey(), e.getValue(), pragmas.get("number"));
377 }
378 }
379 }