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 org.apache.commons.jexl3.internal.Debugger;
20 import org.apache.commons.jexl3.internal.TemplateDebugger;
21 import org.apache.commons.jexl3.internal.TemplateInterpreter;
22 import org.apache.commons.jexl3.internal.introspection.Permissions;
23 import org.apache.commons.jexl3.internal.introspection.Uberspect;
24 import org.apache.commons.logging.Log;
25 import org.apache.commons.logging.LogFactory;
26
27 import java.io.PrintWriter;
28 import java.io.StringReader;
29 import java.io.StringWriter;
30 import java.io.Writer;
31 import java.lang.reflect.Method;
32 import java.util.Arrays;
33 import java.util.Collections;
34 import java.util.List;
35 import java.util.Set;
36 import org.junit.After;
37 import org.junit.Assert;
38 import org.junit.Before;
39 import org.junit.Test;
40 import org.junit.runner.RunWith;
41 import org.junit.runners.Parameterized;
42
43
44
45
46 @SuppressWarnings({"UnnecessaryBoxing", "AssertEqualsBetweenInconvertibleTypes"})
47 @RunWith(Parameterized.class)
48 public class JXLTTest extends JexlTestCase {
49 private static final Log LOGGER = LogFactory.getLog(JxltEngine.class);
50 private final MapContext vars = new MapContext();
51 private JexlEvalContext context = null;
52 private final JexlBuilder BUILDER;
53 private final JexlEngine ENGINE;
54 private final JxltEngine JXLT;
55
56 public JXLTTest(final JexlBuilder builder) {
57 super("JXLTTest");
58 BUILDER = builder;
59 ENGINE = BUILDER.create();
60 JXLT = ENGINE.createJxltEngine();
61 }
62
63
64 @Parameterized.Parameters
65 public static List<JexlBuilder> engines() {
66 final JexlFeatures f = new JexlFeatures();
67 f.lexical(true).lexicalShade(true);
68 return Arrays.<JexlBuilder>asList(
69 new JexlBuilder().silent(false).lexical(true).lexicalShade(true).cache(128).strict(true),
70 new JexlBuilder().features(f).silent(false).cache(128).strict(true),
71 new JexlBuilder().silent(false).cache(128).strict(true));
72 }
73
74 @Before
75 @Override
76 public void setUp() throws Exception {
77
78 java.util.logging.Logger.getLogger(org.apache.commons.jexl3.JexlEngine.class.getName()).setLevel(java.util.logging.Level.SEVERE);
79 context = new JexlEvalContext(vars);
80 }
81
82 @After
83 @Override
84 public void tearDown() throws Exception {
85 debuggerCheck(ENGINE);
86 super.tearDown();
87 }
88
89 private boolean isLexicalShade() {
90 JexlOptions options = context.getEngineOptions();
91 if (options.isLexicalShade()) {
92 return true;
93 }
94 options = new JexlOptions().set(ENGINE);
95 return options.isLexicalShade();
96 }
97
98 private static String refactor(final TemplateDebugger td, final JxltEngine.Template ts) {
99 final boolean dbg = td.debug(ts);
100 if (dbg) {
101 return td.toString();
102 }
103 return "";
104 }
105
106
107 private String getSource(final String tostring) {
108 final int len = tostring.length();
109 int sc = tostring.lastIndexOf(" /*= ");
110 if (sc >= 0) {
111 sc += " /*= ".length();
112 }
113 final int ec = tostring.lastIndexOf(" */");
114 if (sc >= 0 && ec >= 0 && ec > sc && ec < len) {
115 return tostring.substring(sc, ec);
116 }
117 return tostring;
118
119 }
120
121 public static class Froboz {
122 int value;
123
124 public Froboz(final int v) {
125 value = v;
126 }
127
128 public void setValue(final int v) {
129 value = v;
130 }
131
132 public int getValue() {
133 return value;
134 }
135
136 public int plus10() {
137 final int i = value;
138 value += 10;
139 return i;
140 }
141 }
142
143 @Test
144 public void testStatement() throws Exception {
145 final Froboz froboz = new Froboz(32);
146 context.set("froboz", froboz);
147 final JxltEngine.Expression check = JXLT.createExpression("${ froboz.plus10() }");
148 final Object o = check.evaluate(context);
149 Assert.assertEquals("Result is not 32", new Integer(32), o);
150 Assert.assertEquals("Result is not 42", 42, froboz.getValue());
151 final Set<List<String>> evars = check.getVariables();
152 Assert.assertEquals(1, evars.size());
153 }
154
155 @Test
156 public void testAssign() throws Exception {
157 final Froboz froboz = new Froboz(32);
158 context.set("froboz", froboz);
159 final JxltEngine.Expression assign = JXLT.createExpression("${froboz.value = 42}");
160 final JxltEngine.Expression check = JXLT.createExpression("${froboz.value}");
161 Object o = assign.evaluate(context);
162 Assert.assertEquals("Result is not 10", new Integer(42), o);
163 o = check.evaluate(context);
164 Assert.assertEquals("Result is not 10", new Integer(42), o);
165 }
166
167 @Test
168 public void testComposite() throws Exception {
169 final String source = "Dear ${p} ${name};";
170 final JxltEngine.Expression expr = JXLT.createExpression(source);
171 context.set("p", "Mr");
172 context.set("name", "Doe");
173 Assert.assertTrue("expression should be immediate", expr.isImmediate());
174 Object o = expr.evaluate(context);
175 Assert.assertEquals("Dear Mr Doe;", o);
176 context.set("p", "Ms");
177 context.set("name", "Jones");
178 o = expr.evaluate(context);
179 Assert.assertEquals("Dear Ms Jones;", o);
180 Assert.assertEquals(source, getSource(expr.toString()));
181 }
182
183 boolean contains(final Set<List<String>> set, final List<String> list) {
184 for (final List<String> sl : set) {
185 if (sl.equals(list)) {
186 return true;
187 }
188 }
189 return false;
190 }
191
192 @Test
193 public void testPrepareEvaluate() throws Exception {
194 final String source = "Dear #{p} ${name};";
195 final JxltEngine.Expression expr = JXLT.createExpression("Dear #{p} ${name};");
196 Assert.assertTrue("expression should be deferred", expr.isDeferred());
197
198 final Set<List<String>> evars = expr.getVariables();
199 Assert.assertEquals(1, evars.size());
200 Assert.assertTrue(contains(evars, Collections.singletonList("name")));
201 context.set("name", "Doe");
202 final JxltEngine.Expression phase1 = expr.prepare(context);
203 final String as = phase1.asString();
204 Assert.assertEquals("Dear ${p} Doe;", as);
205 final Set<List<String>> evars1 = phase1.getVariables();
206 Assert.assertEquals(1, evars1.size());
207 Assert.assertTrue(contains(evars1, Collections.singletonList("p")));
208 vars.clear();
209 context.set("p", "Mr");
210 context.set("name", "Should not be used in 2nd phase");
211 final Object o = phase1.evaluate(context);
212 Assert.assertEquals("Dear Mr Doe;", o);
213
214 final String p1 = getSource(phase1.toString());
215 Assert.assertEquals(source, getSource(phase1.toString()));
216 Assert.assertEquals(source, getSource(expr.toString()));
217 }
218
219 @Test
220 public void testNested() throws Exception {
221 final String source = "#{${hi}+'.world'}";
222 final JxltEngine.Expression expr = JXLT.createExpression(source);
223
224 final Set<List<String>> evars = expr.getVariables();
225 Assert.assertEquals(1, evars.size());
226 Assert.assertTrue(contains(evars, Collections.singletonList("hi")));
227
228 context.set("hi", "greeting");
229 context.set("greeting.world", "Hello World!");
230 Assert.assertTrue("expression should be deferred", expr.isDeferred());
231 final Object o = expr.evaluate(context);
232 Assert.assertEquals("Hello World!", o);
233
234 Assert.assertEquals(source, getSource(expr.toString()));
235 }
236
237 @Test
238 public void testNestedTemplate() throws Exception {
239 final String source = "#{${hi}+'.world'}";
240 final JxltEngine.Template expr = JXLT.createTemplate(source, "hi");
241
242 context.set("greeting.world", "Hello World!");
243 final StringWriter strw = new StringWriter();
244 expr.evaluate(context, strw, "greeting");
245 final String o = strw.toString();
246 Assert.assertEquals("Hello World!", o);
247
248 Assert.assertEquals(source, getSource(expr.toString()));
249 }
250
251 @Test
252 public void testImmediate() throws Exception {
253 final JexlContext none = null;
254 final String source = "${'Hello ' + 'World!'}";
255 final JxltEngine.Expression expr = JXLT.createExpression(source);
256 final JxltEngine.Expression prepared = expr.prepare(none);
257 Assert.assertEquals("prepare should return same expression", "Hello World!", prepared.asString());
258 final Object o = expr.evaluate(none);
259 Assert.assertTrue("expression should be immediate", expr.isImmediate());
260 Assert.assertEquals("Hello World!", o);
261
262 Assert.assertEquals(source, getSource(expr.toString()));
263 }
264
265 @Test
266 public void testConstant0() throws Exception {
267 final JexlContext none = null;
268 final String source = "Hello World!";
269 final JxltEngine.Expression expr = JXLT.createExpression(source);
270 Assert.assertSame("prepare should return same expression", expr.prepare(none), expr);
271 final Object o = expr.evaluate(none);
272 Assert.assertTrue("expression should be immediate", expr.isImmediate());
273 Assert.assertEquals("Hello World!", o);
274
275 Assert.assertEquals(source, getSource(expr.toString()));
276 }
277
278 @Test
279 public void testConstant2() throws Exception {
280 final JexlContext none = null;
281 final String source = "${size({'map':123,'map2':456})}";
282 final JxltEngine.Expression expr = JXLT.createExpression(source);
283
284 final Object o = expr.evaluate(none);
285 Assert.assertTrue("expression should be immediate", expr.isImmediate());
286 Assert.assertEquals(2, o);
287
288 Assert.assertEquals(source, getSource(expr.toString()));
289 }
290
291 @Test
292 public void testConstant3() throws Exception {
293 final JexlContext none = null;
294 final String source = "#{size({'map':123,'map2':456})}";
295 final JxltEngine.Expression expr = JXLT.createExpression(source);
296
297 final Object o = expr.evaluate(none);
298 Assert.assertTrue("expression should be deferred", expr.isDeferred());
299 Assert.assertEquals(2, o);
300
301 Assert.assertEquals(source, getSource(expr.toString()));
302 }
303
304 @Test
305 public void testConstant4() throws Exception {
306 final JexlContext none = null;
307 final String source = "#{ ${size({'1':2,'2': 3})} }";
308 final JxltEngine.Expression expr = JXLT.createExpression(source);
309
310 final Object o = expr.evaluate(none);
311 Assert.assertTrue("expression should be deferred", expr.isDeferred());
312 Assert.assertEquals(2, o);
313
314 Assert.assertEquals(source, getSource(expr.toString()));
315 }
316
317 @Test
318 public void testDeferred() throws Exception {
319 final JexlContext none = null;
320 final String source = "#{'world'}";
321 final JxltEngine.Expression expr = JXLT.createExpression(source);
322 Assert.assertTrue("expression should be deferred", expr.isDeferred());
323 final String as = expr.prepare(none).asString();
324 Assert.assertEquals("prepare should return immediate version", "${'world'}", as);
325 final Object o = expr.evaluate(none);
326 Assert.assertEquals("world", o);
327
328 Assert.assertEquals(source, getSource(expr.toString()));
329 }
330
331 @Test
332 public void testEscape() throws Exception {
333 final JexlContext none = null;
334 JxltEngine.Expression expr;
335 Object o;
336
337 expr = JXLT.createExpression("\\#{'world'}");
338 o = expr.evaluate(none);
339 Assert.assertEquals("#{'world'}", o);
340 expr = JXLT.createExpression("\\${'world'}");
341 o = expr.evaluate(none);
342 Assert.assertEquals("${'world'}", o);
343 }
344
345 @Test
346 public void testEscapeString() throws Exception {
347 final JxltEngine.Expression expr = JXLT.createExpression("\\\"${'world\\'s finest'}\\\"");
348 final JexlContext none = null;
349 final Object o = expr.evaluate(none);
350 Assert.assertEquals("\"world's finest\"", o);
351 }
352
353 @Test
354 public void testNonEscapeString() throws Exception {
355 final JxltEngine.Expression expr = JXLT.createExpression("c:\\some\\windows\\path");
356 final JexlContext none = null;
357 final Object o = expr.evaluate(none);
358 Assert.assertEquals("c:\\some\\windows\\path", o);
359 }
360
361 @Test
362 public void testMalformed() throws Exception {
363 try {
364 final JxltEngine.Expression expr = JXLT.createExpression("${'world'");
365 final JexlContext none = null;
366 expr.evaluate(none);
367 Assert.fail("should be malformed");
368 } catch (final JxltEngine.Exception xjexl) {
369
370 final String xmsg = xjexl.getMessage();
371 LOGGER.debug(xmsg);
372 }
373 }
374
375 @Test
376 public void testMalformedNested() throws Exception {
377 try {
378 final JxltEngine.Expression expr = JXLT.createExpression("#{${hi} world}");
379 final JexlContext none = null;
380 expr.evaluate(none);
381 Assert.fail("should be malformed");
382 } catch (final JxltEngine.Exception xjexl) {
383
384 final String xmsg = xjexl.getMessage();
385 LOGGER.debug(xmsg);
386 }
387 }
388
389 @Test
390 public void testMalformedNested2() throws Exception {
391 try {
392 final JxltEngine.Expression expr = JXLT.createExpression("#{${hi} world}");
393 final JexlContext ctxt = new MapContext();
394 ctxt.set("hi", "hello");
395 expr.evaluate(ctxt);
396 Assert.fail("should be malformed");
397 } catch (final JxltEngine.Exception xjexl) {
398
399 final String xmsg = xjexl.getMessage();
400 LOGGER.debug(xmsg);
401 }
402 }
403
404 @Test
405 public void testBadContextNested() throws Exception {
406 try {
407 final JxltEngine.Expression expr = JXLT.createExpression("#{${hi}+'.world'}");
408 final JexlContext none = null;
409 expr.evaluate(none);
410 Assert.fail("should be malformed");
411 } catch (final JxltEngine.Exception xjexl) {
412
413 final String xmsg = xjexl.getMessage();
414 LOGGER.debug(xmsg);
415 }
416 }
417
418 @Test
419 public void testCharAtBug() throws Exception {
420 context.set("foo", "abcdef");
421 final JexlOptions options = context.getEngineOptions();
422 JxltEngine.Expression expr = JXLT.createExpression("${foo.substring(2,4)/*comment*/}");
423 Object o = expr.evaluate(context);
424 Assert.assertEquals("cd", o);
425
426 context.set("bar", "foo");
427 try {
428 options.setSilent(true);
429 expr = JXLT.createExpression("#{${bar}+'.charAt(-2)'}");
430 expr = expr.prepare(context);
431 o = expr.evaluate(context);
432 Assert.assertNull(o);
433 } finally {
434 options.setSilent(false);
435 }
436
437 }
438
439 @Test
440 public void testTemplate0() throws Exception {
441 final String source = " $$ if(x) {\nx is ${x}\n $$ } else {\n${'no x'}\n$$ }\n";
442 StringWriter strw;
443 String output;
444
445 final JxltEngine.Template t = JXLT.createTemplate(source);
446
447 context.set("x", 42);
448 strw = new StringWriter();
449 t.evaluate(context, strw);
450 output = strw.toString();
451 Assert.assertEquals("x is 42\n", output);
452
453 strw = new StringWriter();
454 context.set("x", "");
455 t.evaluate(context, strw);
456 output = strw.toString();
457 Assert.assertEquals("no x\n", output);
458
459 final String dstr = t.toString();
460 Assert.assertNotNull(dstr);
461 }
462
463 @Test
464 public void testTemplate10() throws Exception {
465 final String source = "$$(x)->{ if(x) {\nx is ${x}\n$$ } else {\n${'no x'}\n$$ } }\n";
466 StringWriter strw;
467 String output;
468
469 final JxltEngine.Template t = JXLT.createTemplate("$$", new StringReader(source), (String[]) null);
470 final String dstr = t.asString();
471 Assert.assertNotNull(dstr);
472
473 final String[] ps = t.getParameters();
474 Assert.assertTrue(Arrays.asList(ps).contains("x"));
475
476 strw = new StringWriter();
477 t.evaluate(context, strw, 42);
478 output = strw.toString();
479 Assert.assertEquals("x is 42\n", output);
480 }
481
482 @Test
483 public void testTemplate1() throws Exception {
484 final String source = "$$ if(x) {\nx is ${x}\n$$ } else {\n${'no x'}\n$$ }\n";
485 StringWriter strw;
486 String output;
487
488 final JxltEngine.Template t = JXLT.createTemplate("$$", new StringReader(source), "x");
489 final String dstr = t.asString();
490 Assert.assertNotNull(dstr);
491
492 strw = new StringWriter();
493 t.evaluate(context, strw, 42);
494 output = strw.toString();
495 Assert.assertEquals("x is 42\n", output);
496
497 strw = new StringWriter();
498 t.evaluate(context, strw, "");
499 output = strw.toString();
500 Assert.assertEquals("no x\n", output);
501 }
502
503 @Test
504 public void testTemplate2() throws Exception {
505 final String source = "The answer: ${x}";
506 StringWriter strw;
507 String output;
508
509 final JxltEngine.Template t = JXLT.createTemplate("$$", new StringReader(source), "x");
510 final String dstr = t.asString();
511 Assert.assertNotNull(dstr);
512
513 strw = new StringWriter();
514 t.evaluate(context, strw, 42);
515 output = strw.toString();
516 Assert.assertEquals("The answer: 42", output);
517 }
518
519 @Test
520 public void testPrepareTemplate() throws Exception {
521 final String source
522 = "$$ for(var x : list) {\n"
523 + "${l10n}=#{x}\n"
524 + "$$ }\n";
525 final int[] args = {42};
526 final JxltEngine.Template tl10n = JXLT.createTemplate(source, "list");
527 final String dstr = tl10n.asString();
528 Assert.assertNotNull(dstr);
529 final Set<List<String>> vars = tl10n.getVariables();
530 Assert.assertFalse(vars.isEmpty());
531 context.set("l10n", "valeur");
532 final JxltEngine.Template tpFR = tl10n.prepare(context);
533 context.set("l10n", "value");
534 final JxltEngine.Template tpEN = tl10n.prepare(context);
535 context.set("l10n", null);
536
537 StringWriter strw;
538 strw = new StringWriter();
539 tpFR.evaluate(context, strw, args);
540 final String outFR = strw.toString();
541 Assert.assertEquals("valeur=42\n", outFR);
542
543 context.set("l10n", null);
544 strw = new StringWriter();
545 tpEN.evaluate(context, strw, args);
546 final String outEN = strw.toString();
547 Assert.assertEquals("value=42\n", outEN);
548 }
549
550 @Test
551 public void test42() throws Exception {
552 final String test42
553 = "$$ for(var x : list) {\n"
554 + "$$ if (x == 42) {\n"
555 + "Life, the universe, and everything\n"
556 + "$$ } else if (x > 42) {\n"
557 + "The value ${x} is over fourty-two\n"
558 + "$$ } else {\n"
559 + "The value ${x} is under fourty-two\n"
560 + "$$ }\n"
561 + "$$ }\n";
562 final JxltEngine.Template t = JXLT.createTemplate("$$", new StringReader(test42), "list");
563 final StringWriter strw = new StringWriter();
564 final int[] list = {1, 3, 5, 42, 169};
565 t.evaluate(context, strw, list);
566 final String output = strw.toString();
567 final String out42
568 = "The value 1 is under fourty-two\n"
569 + "The value 3 is under fourty-two\n"
570 + "The value 5 is under fourty-two\n"
571 + "Life, the universe, and everything\n"
572 + "The value 169 is over fourty-two\n";
573 Assert.assertEquals(out42, output);
574
575 final String dstr = t.asString();
576 Assert.assertNotNull(dstr);
577
578 final TemplateDebugger td = new TemplateDebugger();
579 final String refactored = refactor(td, t);
580 Assert.assertNotNull(refactored);
581 Assert.assertEquals(test42, refactored);
582 }
583
584 @Test
585 public void testInheritedDebugger() throws Exception {
586 final String src = "if ($A) { $B + 1; } else { $C - 2 }";
587 final JexlEngine jexl = JXLT.getEngine();
588 final JexlScript script = jexl.createScript(src);
589
590 final Debugger sd = new Debugger();
591 final String rscript = sd.debug(script)? sd.toString() : null;
592 Assert.assertNotNull(rscript);
593
594 final TemplateDebugger td = new TemplateDebugger();
595 final String refactored = td.debug(script)? td.toString() : null;
596 Assert.assertNotNull(refactored);
597 Assert.assertEquals(refactored, rscript);
598 }
599
600 public static class FrobozWriter extends PrintWriter {
601 public FrobozWriter(final Writer w) {
602 super(w);
603 }
604
605 public void print(final Froboz froboz) {
606 super.print("froboz{");
607 super.print(froboz.value);
608 super.print("}");
609 }
610
611 @Override
612 public String toString() {
613 return out.toString();
614 }
615 }
616
617 @Test
618 public void testWriter() throws Exception {
619 final Froboz froboz = new Froboz(42);
620 final Writer writer = new FrobozWriter(new StringWriter());
621 final JxltEngine.Template t = JXLT.createTemplate("$$", new StringReader("$$$jexl.print(froboz)"), "froboz");
622 t.evaluate(context, writer, froboz);
623 Assert.assertEquals("froboz{42}", writer.toString());
624 }
625
626 @Test
627 public void testReport() throws Exception {
628 final String rpt
629 = "<report>\n"
630 + "\n"
631 + "\n$$ var a = 1;"
632 + "\n$$ var x = 2;"
633 + "\n"
634 + "\n$$ var y = 9;"
635 + "\n"
636 + "\n ${x + y}"
637 + "\n</report>\n";
638 final JxltEngine.Template t = JXLT.createTemplate("$$", new StringReader(rpt));
639 final StringWriter strw = new StringWriter();
640 t.evaluate(context, strw);
641 final String output = strw.toString();
642 final String ctl = "<report>\n\n\n\n\n 11\n</report>\n";
643 Assert.assertEquals(ctl, output);
644
645 final TemplateDebugger td = new TemplateDebugger();
646 final String refactored = refactor(td, t);
647 Assert.assertNotNull(refactored);
648 Assert.assertEquals(rpt, refactored);
649 }
650
651 @Test
652 public void testReport1() throws Exception {
653 final String rpt
654 = "<report>\n"
655 + "this is ${x}\n"
656 + "${x + 1}\n"
657 + "${x + 2}\n"
658 + "${x + 3}\n"
659 + "</report>\n";
660 final JxltEngine.Template t = JXLT.createTemplate("$$", new StringReader(rpt));
661 final StringWriter strw = new StringWriter();
662 context.set("x", 42);
663 t.evaluate(context, strw, 42);
664 final String output = strw.toString();
665 int count = 0;
666 for (int i = 0; i < output.length(); ++i) {
667 final char c = output.charAt(i);
668 if ('\n' == c) {
669 count += 1;
670 }
671 }
672 Assert.assertEquals(6, count);
673 Assert.assertTrue(output.indexOf("42") > 0);
674 Assert.assertTrue(output.indexOf("43") > 0);
675 Assert.assertTrue(output.indexOf("44") > 0);
676 Assert.assertTrue(output.indexOf("45") > 0);
677 }
678
679 @Test
680 public void testReport2() throws Exception {
681 final String rpt
682 = "<report>\n"
683 + "this is ${x}\n"
684 + "${x + 1}\n"
685 + "${x + 2}\n"
686 + "${x + 3}\n"
687 + "</report>\n";
688 final JxltEngine.Template t = JXLT.createTemplate("$$", new StringReader(rpt), "x");
689 final StringWriter strw = new StringWriter();
690 t.evaluate(context, strw, 42);
691 final String output = strw.toString();
692 int count = 0;
693 for (int i = 0; i < output.length(); ++i) {
694 final char c = output.charAt(i);
695 if ('\n' == c) {
696 count += 1;
697 }
698 }
699 Assert.assertEquals(6, count);
700 Assert.assertTrue(output.indexOf("42") > 0);
701 Assert.assertTrue(output.indexOf("43") > 0);
702 Assert.assertTrue(output.indexOf("44") > 0);
703 Assert.assertTrue(output.indexOf("45") > 0);
704
705 final TemplateDebugger td = new TemplateDebugger();
706 final String xxx = refactor(td, t);
707 Assert.assertNotNull(xxx);
708 Assert.assertEquals(rpt, xxx);
709 }
710 @Test
711 public void testOneLiner() throws Exception {
712 final JxltEngine.Template t = JXLT.createTemplate("$$", new StringReader("fourty-two"));
713 final StringWriter strw = new StringWriter();
714 t.evaluate(context, strw);
715 final String output = strw.toString();
716 Assert.assertEquals("fourty-two", output);
717 }
718
719 @Test
720 public void testOneLinerVar() throws Exception {
721 final JxltEngine.Template t = JXLT.createTemplate("$$", new StringReader("fourty-${x}"));
722 final StringWriter strw = new StringWriter();
723 context.set("x", "two");
724 t.evaluate(context, strw);
725 final String output = strw.toString();
726 Assert.assertEquals("fourty-two", output);
727 }
728
729 @Test
730 public void testInterpolation() throws Exception {
731 final String expr = "`Hello \n${user}`";
732 final JexlScript script = ENGINE.createScript(expr);
733 context.set("user", "Dimitri");
734 Object value = script.execute(context);
735 Assert.assertEquals(expr, "Hello \nDimitri", value);
736 context.set("user", "Rahul");
737 value = script.execute(context);
738 Assert.assertEquals(expr, "Hello \nRahul", value);
739 }
740
741 @Test
742 public void testInterpolationGlobal() throws Exception {
743 if (isLexicalShade()) {
744 context.set("user", null);
745 }
746 final String expr = "user='Dimitri'; `Hello \n${user}`";
747 final Object value = ENGINE.createScript(expr).execute(context);
748 Assert.assertEquals(expr, "Hello \nDimitri", value);
749 }
750
751 @Test
752 public void testInterpolationLocal() throws Exception {
753 final String expr = "var user='Henrib'; `Hello \n${user}`";
754 final Object value = ENGINE.createScript(expr).execute(context);
755 Assert.assertEquals(expr, "Hello \nHenrib", value);
756 }
757
758 @Test
759 public void testInterpolationLvsG() throws Exception {
760 if (isLexicalShade()) {
761 context.set("user", null);
762 }
763 final String expr = "user='Dimitri'; var user='Henrib'; `H\\\"ello \n${user}`";
764 final Object value = ENGINE.createScript(expr).execute(context);
765 Assert.assertEquals(expr, "H\"ello \nHenrib", value);
766 }
767
768 @Test
769 public void testInterpolationLvsG2() throws Exception {
770 if (isLexicalShade()) {
771 context.set("user", null);
772 }
773 final String expr = "user='Dimitri'; var user='Henrib'; `H\\`ello \n${user}`";
774 final Object value = ENGINE.createScript(expr).execute(context);
775 Assert.assertEquals(expr, "H`ello \nHenrib", value);
776 }
777
778 @Test
779 public void testInterpolationParameter() throws Exception {
780 final String expr = "(user)->{`Hello \n${user}`}";
781 JexlScript script = ENGINE.createScript(expr);
782 Object value = script.execute(context, "Henrib");
783 Assert.assertEquals(expr, "Hello \nHenrib", value);
784 value = ENGINE.createScript(expr).execute(context, "Dimitri");
785 Assert.assertEquals(expr, "Hello \nDimitri", value);
786 }
787
788 @Test
789 public void testDbgEscapes() throws Exception {
790 String[] srcs = new String[]{
791 "jexl:print('hello\\'\\nworld')",
792 "'hello\\tworld'",
793 "'hello\\nworld'",
794 "'hello\\fworld'",
795 "'hello\\rworld'"
796 };
797 for(String src : srcs) {
798 JexlScript script = ENGINE.createScript(src);
799 Debugger dbg = new Debugger();
800 dbg.debug(script);
801 String msrc = dbg.toString();
802 Assert.assertEquals(src, msrc);
803 }
804 }
805
806 @Test
807 public void testImmediateTemplate() throws Exception {
808 context.set("tables", new String[]{"table1", "table2"});
809 context.set("w" ,"x=1");
810 final JxltEngine.Template t = JXLT.createTemplate("$$", new StringReader(
811 "select * from \n"+
812 "$$var comma = false; \n"+
813 "$$for(var c : tables) { \n"+
814 "$$ if (comma) $jexl.write(','); else comma = true;\n"+
815 "${c}"+
816 "\n$$}\n"+
817 "where ${w}\n"
818 ));
819 final StringWriter strw = new StringWriter();
820
821 t.evaluate(context, strw);
822 final String output = strw.toString();
823 Assert.assertTrue(output.contains("table1") && output.contains("table2"));
824 }
825
826 public static class Executor311 {
827 private final String name;
828
829 public Executor311(final String name) {
830 this.name = name;
831 }
832
833 public Object execute(final JexlScript script, final Object ...args) {
834 Object[] actuals;
835 if (args != null && args.length > 0) {
836 actuals = new Object[args.length + 1] ;
837 System.arraycopy(args, 0, actuals, 1, args.length);
838 actuals[0] = name;
839 } else {
840 actuals = new Object[]{name};
841 }
842 return script.execute(JexlEngine.getThreadContext(), actuals);
843 }
844 }
845
846 public static class Context311 extends MapContext
847 implements JexlContext.OptionsHandle, JexlContext.ThreadLocal {
848 private JexlOptions options = null;
849
850 public void setOptions(final JexlOptions o) {
851 options = o;
852 }
853
854 public Executor311 exec(final String name) {
855 return new Executor311(name);
856 }
857
858 @Override
859 public JexlOptions getEngineOptions() {
860 return options;
861 }
862
863 JexlOptions newOptions() {
864 options = new JexlOptions();
865 return options;
866 }
867 }
868
869 @Test
870 public void test311a() throws Exception {
871 final JexlContext ctx = null;
872 final String rpt
873 = "$$((a)->{\n"
874 + "<p>Universe ${a}</p>\n"
875 + "$$})(42)";
876 final JxltEngine.Template t = JXLT.createTemplate("$$", new StringReader(rpt));
877 final StringWriter strw = new StringWriter();
878 t.evaluate(ctx, strw);
879 final String output = strw.toString();
880 Assert.assertEquals("<p>Universe 42</p>\n", output);
881 }
882
883 @Test
884 public void test311b() throws Exception {
885 final JexlContext ctx311 = new Context311();
886 final String rpt
887 = "$$ exec('42').execute(()->{\n"
888 + "<p>Universe 42</p>\n"
889 + "$$})";
890 final JxltEngine.Template t = JXLT.createTemplate("$$", new StringReader(rpt));
891 final StringWriter strw = new StringWriter();
892 t.evaluate(ctx311, strw, 42);
893 final String output = strw.toString();
894 Assert.assertEquals("<p>Universe 42</p>\n", output);
895 }
896
897 @Test
898 public void test311c() throws Exception {
899 final Context311 ctx311 = new Context311();
900 ctx311.newOptions().setLexical(true);
901 final String rpt
902 = "$$ exec('42').execute((a)->{"
903 + "\n<p>Universe ${a}</p>"
904 + "\n$$})";
905 final JxltEngine.Template t = JXLT.createTemplate("$$", new StringReader(rpt));
906 final StringWriter strw = new StringWriter();
907 t.evaluate(ctx311, strw, 42);
908 final String output = strw.toString();
909 Assert.assertEquals("<p>Universe 42</p>\n", output);
910 }
911
912 @Test
913 public void test311d() throws Exception {
914 final Context311 ctx311 = new Context311();
915 ctx311.newOptions().setLexical(true);
916 final String rpt
917 = "$$ exec('4').execute((a, b)->{"
918 + "\n<p>Universe ${a}${b}</p>"
919 + "\n$$}, '2')";
920 final JxltEngine.Template t = JXLT.createTemplate("$$", new StringReader(rpt));
921 final StringWriter strw = new StringWriter();
922 t.evaluate(ctx311, strw, 42);
923 final String output = strw.toString();
924 Assert.assertEquals("<p>Universe 42</p>\n", output);
925 }
926
927 @Test
928 public void test311e() throws Exception {
929 final Context311 ctx311 = new Context311();
930 ctx311.newOptions().setLexical(true);
931 final String rpt
932 = "exec('4').execute((a, b)->{"
933 + " '<p>Universe ' + a + b + '</p>'"
934 + "}, '2')";
935 final JexlScript script = JEXL.createScript(rpt);
936 final String output = script.execute(ctx311, 42).toString();
937 Assert.assertEquals("<p>Universe 42</p>", output);
938 }
939
940 @Test
941 public void test311f() throws Exception {
942 final Context311 ctx311 = new Context311();
943 ctx311.newOptions().setLexical(true);
944 final String rpt
945 = "exec('4').execute((a, b)->{"
946 + " `<p>Universe ${a}${b}</p>`"
947 + "}, '2')";
948 final JexlScript script = JEXL.createScript(rpt);
949 final String output = script.execute(ctx311, 42).toString();
950 Assert.assertEquals("<p>Universe 42</p>", output);
951 }
952
953 @Test
954 public void test311g() throws Exception {
955 final Context311 ctx311 = new Context311();
956 ctx311.newOptions().setLexical(true);
957 final String rpt
958 = "(a, b)->{"
959 + " `<p>Universe ${a}${b}</p>`"
960 + "}";
961 final JexlScript script = JEXL.createScript(rpt);
962 final String output = script.execute(ctx311, "4", "2").toString();
963 Assert.assertEquals("<p>Universe 42</p>", output);
964 }
965
966 @Test
967 public void test311h() throws Exception {
968 final Context311 ctx311 = new Context311();
969 ctx311.newOptions().setLexical(true);
970 final String rpt= " `<p>Universe ${a}${b}</p>`";
971 final JexlScript script = JEXL.createScript(rpt, "a", "b");
972 final String output = script.execute(ctx311, "4", "2").toString();
973 Assert.assertEquals("<p>Universe 42</p>", output);
974 }
975
976 @Test
977 public void test311i() throws Exception {
978 final JexlContext ctx311 = new Context311();
979 final String rpt
980 = "$$var u = 'Universe'; exec('4').execute((a, b)->{"
981 + "\n<p>${u} ${a}${b}</p>"
982 + "\n$$}, '2')";
983 final JxltEngine.Template t = JXLT.createTemplate("$$", new StringReader(rpt));
984 final StringWriter strw = new StringWriter();
985 t.evaluate(ctx311, strw, 42);
986 final String output = strw.toString();
987 Assert.assertEquals("<p>Universe 42</p>\n", output);
988 }
989
990 @Test
991 public void test315() throws Exception {
992 String s315;
993 StringWriter strw;
994 JxltEngine.Template t315;
995 String output;
996
997 s315 = "<report/>$";
998 t315 = JXLT.createTemplate("$$", new StringReader(s315));
999 strw = new StringWriter();
1000 t315.evaluate(context, strw);
1001 output = strw.toString();
1002 Assert.assertEquals(s315, output);
1003
1004 s315 = "<foo/>#";
1005 t315 = JXLT.createTemplate("$$", new StringReader(s315));
1006 strw = new StringWriter();
1007 t315.evaluate(context, strw);
1008 output = strw.toString();
1009 Assert.assertEquals(s315, output);
1010
1011 s315 = "<bar/>\\";
1012 t315 = JXLT.createTemplate("$$", new StringReader(s315));
1013 strw = new StringWriter();
1014 t315.evaluate(context, strw);
1015 output = strw.toString();
1016 Assert.assertEquals(s315, output);
1017 }
1018
1019 @Test
1020 public void testLexicalTemplate() throws Exception {
1021 final JexlOptions opts = new JexlOptions();
1022 final JexlContext ctxt = new PragmaticContext(opts);
1023 opts.setCancellable(false);
1024 opts.setStrict(false);
1025 opts.setSafe(true);
1026 opts.setLexical(false);
1027 opts.setLexicalShade(false);
1028 final String src0 = "${$options.strict?'+':'-'}strict"
1029 + " ${$options.cancellable?'+':'-'}cancellable"
1030 + " ${$options.lexical?'+':'-'}lexical"
1031 + " ${$options.lexicalShade?'+':'-'}lexicalShade"
1032 + " ${$options.safe?'+':'-'}safe";
1033
1034 final JxltEngine.Template tmplt0 = JXLT.createTemplate("$$", new StringReader(src0));
1035 final Writer strw0 = new StringWriter();
1036 tmplt0.evaluate(ctxt, strw0);
1037 final String output0 = strw0.toString();
1038 JexlFeatures features = BUILDER.features();
1039 if (features != null && features.isLexical() && features.isLexicalShade()) {
1040 Assert.assertEquals("-strict -cancellable +lexical +lexicalShade +safe", output0);
1041 } else {
1042 Assert.assertEquals("-strict -cancellable -lexical -lexicalShade +safe", output0);
1043 }
1044
1045 final String src = "$$ #pragma script.mode pro50\n" + src0;
1046
1047 final JxltEngine.Template tmplt = JXLT.createTemplate("$$", new StringReader(src));
1048 final Writer strw = new StringWriter();
1049 tmplt.evaluate(ctxt, strw);
1050 final String output = strw.toString();
1051 Assert.assertEquals("+strict +cancellable +lexical +lexicalShade -safe", output);
1052 }
1053
1054 @Test
1055 public void testTemplatePragmaPro50() throws Exception {
1056 final JexlOptions opts = new JexlOptions();
1057 opts.setCancellable(false);
1058 opts.setStrict(false);
1059 opts.setSafe(true);
1060 opts.setLexical(false);
1061 opts.setLexicalShade(false);
1062 opts.setSharedInstance(true);
1063 final JexlContext ctxt = new PragmaticContext(opts);
1064 final String src = "$$ #pragma script.mode pro50\n"
1065 + "$$ var tab = null;\n"
1066 + "$$ tab.dummy();";
1067 final JxltEngine.Template tmplt = JXLT.createTemplate("$$", new StringReader(src));
1068 final Writer strw = new StringWriter();
1069 try {
1070 tmplt.evaluate(ctxt, strw);
1071 Assert.fail("tab var is null");
1072 } catch (final JexlException.Variable xvar) {
1073 Assert.assertEquals("tab", xvar.getVariable());
1074 Assert.assertFalse(xvar.isUndefined());
1075 }
1076 }
1077
1078 @Test
1079 public void testTemplateOutOfScope() throws Exception {
1080 final JexlOptions opts = new JexlOptions();
1081 opts.setCancellable(false);
1082 opts.setStrict(false);
1083 opts.setLexical(false);
1084 opts.setLexicalShade(false);
1085 opts.setSharedInstance(true);
1086 final JexlContext ctxt = new PragmaticContext(opts);
1087 final String src = "$$if (false) { var tab = 42; }\n"
1088 + "${tab}";
1089 JxltEngine.Template tmplt;
1090 final JexlFeatures features = BUILDER.features();
1091 try {
1092 tmplt = JXLT.createTemplate("$$", new StringReader(src));
1093 } catch (final JexlException xparse) {
1094 if (features != null && features.isLexicalShade()) {
1095 return;
1096 }
1097 throw xparse;
1098 }
1099 final Writer strw = new StringWriter();
1100 opts.setSafe(true);
1101 try {
1102 tmplt.evaluate(ctxt, strw);
1103 Assert.assertTrue(strw.toString().isEmpty());
1104 } catch (final JexlException.Variable xvar) {
1105 Assert.fail("safe should prevent local shade");
1106 }
1107 opts.setStrict(true);
1108 opts.setSafe(false);
1109 try {
1110 tmplt.evaluate(ctxt, strw);
1111 Assert.fail("tab var is undefined");
1112 } catch (final JexlException.Variable xvar) {
1113 Assert.assertTrue("tab".equals(xvar.getVariable()));
1114 Assert.assertTrue(xvar.isUndefined());
1115 } catch (final JexlException xany) {
1116 Assert.assertTrue(xany.getMessage().contains("tab"));
1117 }
1118 }
1119
1120 @Test
1121 public void testCommentedTemplate0() throws Exception {
1122 final JexlContext ctxt = new MapContext();
1123 final JexlEngine jexl = new JexlBuilder().create();
1124 final JxltEngine jxlt = jexl.createJxltEngine();
1125 JxltEngine.Template tmplt;
1126 final String src = "$$/*\n"
1127 + "Hello\n"
1128 + "$$*/";
1129 tmplt = jxlt.createTemplate(src);
1130 Assert.assertNotNull(tmplt);
1131 final Writer strw = new StringWriter();
1132 tmplt.evaluate(ctxt, strw);
1133 Assert.assertTrue(strw.toString().isEmpty());
1134 }
1135
1136 @Test
1137 public void testCommentedTemplate1() throws Exception {
1138 final JexlContext ctxt = new MapContext();
1139 final JexlEngine jexl = new JexlBuilder().create();
1140 final JxltEngine jxlt = jexl.createJxltEngine();
1141 JxltEngine.Template tmplt;
1142 final String src = "$$/*\n"
1143 + "one\n"
1144 + "$$*/\n"
1145 + "42\n"
1146 + "$$/*\n"
1147 + "three\n"
1148 + "$$*/\n";
1149 tmplt = jxlt.createTemplate(src);
1150 Assert.assertNotNull(tmplt);
1151 final Writer strw = new StringWriter();
1152 tmplt.evaluate(ctxt, strw);
1153 Assert.assertEquals("42\n", strw.toString());
1154 }
1155
1156 @Test
1157 public void testConstantTemplate() {
1158 String src = "<script>\n" +
1159 " function test(src){\n" +
1160 " var res = src.replace(/\\n\\t\\s/g, '\\n');\n" +
1161 " }\n" +
1162 " test();\n" +
1163 " </script>";
1164 final JexlContext ctxt = new MapContext();
1165 final JexlEngine jexl = new JexlBuilder().create();
1166 final JxltEngine jxlt = jexl.createJxltEngine();
1167 JxltEngine.Template tmplt;
1168 tmplt = jxlt.createTemplate(src);
1169 Assert.assertNotNull(tmplt);
1170 final Writer strw = new StringWriter();
1171 tmplt.evaluate(ctxt, strw);
1172 String result = strw.toString();
1173 Assert.assertEquals(src, result);
1174 }
1175
1176 private static final Permissions NOJEXL3 = new Permissions() {
1177 @Override public boolean allow(Class<?> clazz) {
1178 String cname = clazz.getName();
1179 return !cname.contains("jexl3") || cname.contains("311");
1180 }
1181 };
1182
1183 @Test
1184 public void testSanboxedTemplate() throws Exception {
1185 final String src = "Hello ${user}";
1186 final JexlContext ctxt = new MapContext();
1187 ctxt.set("user", "Francesco");
1188
1189 Uberspect uberspect = new Uberspect(LogFactory.getLog(JXLTTest.class), null, NOJEXL3);
1190 Method method = uberspect.getMethod(TemplateInterpreter.class, "print", new Object[]{Integer.TYPE});
1191 Assert.assertNull(method);
1192
1193 final JexlEngine jexl= new JexlBuilder().uberspect(uberspect).create();
1194 final JxltEngine jxlt = jexl.createJxltEngine();
1195
1196 JxltEngine.Template tmplt = jxlt.createTemplate(src);
1197 Writer strw = new StringWriter();
1198 tmplt.evaluate(ctxt, strw);
1199 String result = strw.toString();
1200 Assert.assertEquals("Hello Francesco", result);
1201 }
1202
1203 @Test
1204 public void testSanboxed311i() throws Exception {
1205
1206 Uberspect uberspect = new Uberspect(LogFactory.getLog(JXLTTest.class), null, NOJEXL3);
1207 Method method = uberspect.getMethod(TemplateInterpreter.class, "print", new Object[]{Integer.TYPE});
1208 final JexlEngine jexl= new JexlBuilder().uberspect(uberspect).create();
1209 final JxltEngine jxlt = jexl.createJxltEngine();
1210 final JexlContext ctx311 = new Context311();
1211 final String rpt
1212 = "$$var u = 'Universe'; exec('4').execute((a, b)->{"
1213 + "\n<p>${u} ${a}${b}</p>"
1214 + "\n$$}, '2')";
1215 final JxltEngine.Template t = jxlt.createTemplate("$$", new StringReader(rpt));
1216 final StringWriter strw = new StringWriter();
1217 t.evaluate(ctx311, strw, 42);
1218 final String output = strw.toString();
1219 Assert.assertEquals("<p>Universe 42</p>\n", output);
1220 }
1221 }