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.junit.Assert;
20 import org.junit.Test;
21
22 import java.util.Collections;
23 import java.util.HashMap;
24 import java.util.Map;
25 import java.util.concurrent.atomic.AtomicInteger;
26
27
28
29
30 @SuppressWarnings({"AssertEqualsBetweenInconvertibleTypes"})
31 public class ContextNamespaceTest extends JexlTestCase {
32
33 public ContextNamespaceTest() {
34 super("ContextNamespaceTest");
35 }
36
37
38
39
40 public static class Taxes {
41 private final double vat;
42
43 public Taxes(final TaxesContext ctxt) {
44 vat = ctxt.getVAT();
45 }
46
47 public Taxes(final double d) {
48 vat = d;
49 }
50
51 public double vat(final double n) {
52 return (n * vat) / 100.;
53 }
54 }
55
56
57
58
59 public static class TaxesContext extends MapContext implements JexlContext.ThreadLocal, JexlContext.NamespaceResolver {
60 private Taxes taxes = null;
61 private final double vat;
62
63 TaxesContext(final double vat) {
64 this.vat = vat;
65 }
66
67 @Override
68 public Object resolveNamespace(final String name) {
69 if ("taxes".equals(name)) {
70 if (taxes == null) {
71 taxes = new Taxes(vat);
72 }
73 return taxes;
74 }
75 return null;
76 }
77
78 public double getVAT() {
79 return vat;
80 }
81 }
82
83 @Test
84 public void testThreadedContext() {
85 final JexlEngine jexl = new JexlBuilder().create();
86 final JexlContext context = new TaxesContext(18.6);
87 final String strs = "taxes:vat(1000)";
88 final JexlScript staxes = jexl.createScript(strs);
89 final Object result = staxes.execute(context);
90 Assert.assertEquals(186., result);
91 }
92
93 @Test
94 public void testNamespacePragma() {
95 final JexlEngine jexl = new JexlBuilder().create();
96 final JexlContext context = new TaxesContext(18.6);
97
98 final String strs =
99 "#pragma jexl.namespace.tax org.apache.commons.jexl3.ContextNamespaceTest$Taxes\n"
100 + "tax:vat(2000)";
101 final JexlScript staxes = jexl.createScript(strs);
102 final Object result = staxes.execute(context);
103 Assert.assertEquals(372., result);
104 }
105
106 public static class Context346 extends MapContext {
107 public int func(int y) { return 42 * y;}
108 }
109
110 @Test
111 public void testNamespace346a() {
112 JexlContext ctxt = new Context346();
113 final JexlEngine jexl = new JexlBuilder().safe(false).create();
114 String src = "x != null ? x : func(y)";
115 final JexlScript script = jexl.createScript(src,"x","y");
116 Object result = script.execute(ctxt, null, 1);
117 Assert.assertEquals(42, result);
118 result = script.execute(ctxt, 169, -169);
119 Assert.assertEquals(169, result);
120 }
121
122 @Test
123 public void testNamespace346b() {
124 JexlContext ctxt = new MapContext();
125 Map<String, Object> ns = new HashMap<>();
126 ns.put("x", Math.class);
127 ns.put(null, Math.class);
128 final JexlEngine jexl = new JexlBuilder().safe(false).namespaces(ns).create();
129 String src = "x != null ? x : abs(y)";
130 final JexlScript script = jexl.createScript(src,"x","y");
131 Object result = script.execute(ctxt, null, 42);
132 Assert.assertEquals(42, result);
133 result = script.execute(ctxt, 169, -169);
134 Assert.assertEquals(169, result);
135 }
136
137 public static class Ns348 {
138 public static int func(int y) { return 42 * y;}
139 }
140
141 public static class ContextNs348 extends MapContext implements JexlContext.NamespaceResolver {
142 ContextNs348() { super(); }
143
144 @Override
145 public Object resolveNamespace(String name) {
146 return "ns".equals(name)? new Ns348() : null;
147 }
148 }
149
150 @Test
151 public void testNamespace348a() {
152 JexlContext ctxt = new MapContext();
153 Map<String, Object> ns = new HashMap<>();
154 ns.put("ns", Ns348.class);
155 final JexlEngine jexl = new JexlBuilder().safe(false).namespaces(ns).create();
156 run348a(jexl, ctxt);
157 run348b(jexl, ctxt);
158 run348c(jexl, ctxt);
159 run348d(jexl, ctxt);
160 }
161
162 @Test
163 public void testNamespace348b() {
164 JexlContext ctxt = new ContextNs348();
165 final JexlEngine jexl = new JexlBuilder().safe(false).create();
166
167 run348a(jexl, ctxt, "ns:");
168 run348b(jexl, ctxt, "ns:");
169 run348c(jexl, ctxt, "ns:");
170 run348d(jexl, ctxt, "ns:");
171 }
172
173 @Test
174 public void testNamespace348c() {
175 JexlContext ctxt = new ContextNs348();
176 Map<String, Object> ns = new HashMap<>();
177 ns.put("ns", Ns348.class);
178 JexlFeatures f = new JexlFeatures();
179 f.namespaceTest((n)->true);
180 final JexlEngine jexl = new JexlBuilder().namespaces(ns).features(f).safe(false).create();
181 run348a(jexl, ctxt);
182 run348b(jexl, ctxt);
183 run348c(jexl, ctxt);
184 run348d(jexl, ctxt);
185 }
186
187 @Test
188 public void testNamespace348d() {
189 JexlContext ctxt = new ContextNs348();
190 JexlFeatures f = new JexlFeatures();
191 f.namespaceTest((n)->true);
192 final JexlEngine jexl = new JexlBuilder().features(f).safe(false).create();
193 run348a(jexl, ctxt);
194 run348b(jexl, ctxt);
195 run348c(jexl, ctxt);
196 run348d(jexl, ctxt);
197 }
198
199 private void run348a(JexlEngine jexl, JexlContext ctxt) {
200 run348a(jexl, ctxt, "ns : ");
201 }
202 private void run348a(JexlEngine jexl, JexlContext ctxt, String ns) {
203 String src = "empty(x) ? "+ns+"func(y) : z";
204
205 JexlScript script = jexl.createScript(src, "x", "y", "z");
206 Object result = script.execute(ctxt, null, 1, 169);
207 Assert.assertEquals(42, result);
208 result = script.execute(ctxt, "42", 1, 169);
209 Assert.assertEquals(169, result);
210 }
211
212 private void run348b(JexlEngine jexl, JexlContext ctxt) {
213 run348b(jexl, ctxt, "ns : ");
214 }
215 private void run348b(JexlEngine jexl, JexlContext ctxt, String ns) {
216 String src = "empty(x) ? "+ns+"func(y) : z";
217
218 JexlScript script = jexl.createScript(src);
219 ctxt.set("x", null);
220 ctxt.set("y", 1);
221 ctxt.set("z", 169);
222 Object result = script.execute(ctxt);
223 Assert.assertEquals(42, result);
224 ctxt.set("x", "42");
225 result = script.execute(ctxt);
226 Assert.assertEquals(169, result);
227
228 result = script.execute(ctxt);
229 Assert.assertEquals(169, result);
230 }
231
232 private void run348c(JexlEngine jexl, JexlContext ctxt) {
233 run348c(jexl, ctxt, "ns : ");
234 }
235 private void run348c(JexlEngine jexl, JexlContext ctxt, String ns) {
236 String src = "empty(x) ? z : "+ns+"func(y)";
237
238 JexlScript script = jexl.createScript(src, "x", "z", "y");
239 Object result = script.execute(ctxt, null, 169, 1);
240 Assert.assertEquals(src, 169, result);
241 result = script.execute(ctxt, "42", 169, 1);
242 Assert.assertEquals(src, 42, result);
243 }
244
245 private void run348d(JexlEngine jexl, JexlContext ctxt) {
246 run348d(jexl, ctxt, "ns : ");
247 }
248 private void run348d(JexlEngine jexl, JexlContext ctxt, String ns) {
249 String src = "empty(x) ? z : "+ns+"func(y)";
250
251 JexlScript script = null;
252 try {
253 script = jexl.createScript(src);
254 } catch(JexlException.Parsing xparse) {
255 Assert.fail(src);
256 }
257 ctxt.set("x", null);
258 ctxt.set("z", 169);
259 ctxt.set("y", 1);
260 Object result = script.execute(ctxt);
261 Assert.assertEquals(src, 169, result);
262 ctxt.set("x", "42");
263 result = script.execute(ctxt);
264 Assert.assertEquals(src,42, result);
265 }
266
267 @Test
268 public void testNamespacePragmaString() {
269 final JexlEngine jexl = new JexlBuilder().create();
270 final JexlContext context = new MapContext();
271
272 final String strs =
273 "#pragma jexl.namespace.str java.lang.String\n"
274 + "str:format('%04d', 42)";
275 final JexlScript staxes = jexl.createScript(strs);
276 final Object result = staxes.execute(context);
277 Assert.assertEquals("0042", result);
278 }
279
280 public static class Vat {
281 private double vat;
282
283 Vat(final double vat) {
284 this.vat = vat;
285 }
286
287 public double getVAT() {
288 return vat;
289 }
290
291 public void setVAT(final double vat) {
292 this.vat = vat;
293 }
294
295 public double getvat() {
296 throw new UnsupportedOperationException("no way");
297 }
298
299 public void setvat(final double vat) {
300 throw new UnsupportedOperationException("no way");
301 }
302 }
303
304 @Test
305 public void testObjectContext() {
306 final JexlEngine jexl = new JexlBuilder().strict(true).silent(false).create();
307 final Vat vat = new Vat(18.6);
308 final ObjectContext<Vat> ctxt = new ObjectContext<>(jexl, vat);
309 Assert.assertEquals(18.6d, (Double) ctxt.get("VAT"), 0.0001d);
310 ctxt.set("VAT", 20.0d);
311 Assert.assertEquals(20.0d, (Double) ctxt.get("VAT"), 0.0001d);
312
313 try {
314 ctxt.get("vat");
315 Assert.fail("should have failed");
316 } catch(final JexlException.Property xprop) {
317
318 }
319
320 try {
321 ctxt.set("vat", 33.0d);
322 Assert.fail("should have failed");
323 } catch(final JexlException.Property xprop) {
324
325 }
326 }
327
328 static AtomicInteger nsnsCtor = new AtomicInteger(0);
329
330 public static class NsNs {
331 private final int constVar;
332 public NsNs(JexlContext ctxt) {
333 nsnsCtor.incrementAndGet();
334 Object n = ctxt.get("NUMBER");
335 constVar = (n instanceof Number) ? ((Number) n).intValue() : -1;
336 }
337
338 public int callIt(int n) {
339 return n + constVar;
340 }
341 }
342
343 @Test
344 public void testNsNsContext0() {
345 nsnsCtor.set(0);
346 String clsName = NsNs.class.getName();
347 runNsNsContext(Collections.singletonMap("nsns", clsName));
348 }
349
350 @Test
351 public void testNsNsContext1() {
352 nsnsCtor.set(0);
353 runNsNsContext(Collections.singletonMap("nsns", NsNs.class));
354 }
355
356 private void runNsNsContext(Map<String,Object> nsMap) {
357 JexlContext ctxt = new MapContext();
358 ctxt.set("NUMBER", 19);
359 final JexlEngine jexl = new JexlBuilder().strict(true).silent(false).cache(32)
360 .namespaces(nsMap).create();
361 final JexlScript script = jexl.createScript("x ->{ nsns:callIt(x); nsns:callIt(x); }");
362 Number result = (Number) script.execute(ctxt, 23);
363 Assert.assertEquals(42, result);
364 Assert.assertEquals(1, nsnsCtor.get());
365 result = (Number) script.execute(ctxt, 623);
366 Assert.assertEquals(642, result);
367 Assert.assertEquals(2, nsnsCtor.get());
368 }
369
370 public static class StaticNs {
371 private StaticNs() { }
372 public static int callIt(int n) {
373 return n + 19;
374 }
375 }
376
377 @Test
378 public void testStaticNs0() {
379 runStaticNsContext(Collections.singletonMap("sns", StaticNs.class));
380 }
381
382 @Test
383 public void testStaticNs1() {
384 runStaticNsContext(Collections.singletonMap("sns", StaticNs.class.getName()));
385 }
386
387 private void runStaticNsContext(Map<String,Object> nsMap) {
388 JexlContext ctxt = new MapContext();
389 final JexlEngine jexl = new JexlBuilder().strict(true).silent(false).cache(32)
390 .namespaces(nsMap).create();
391 final JexlScript script = jexl.createScript("x ->{ sns:callIt(x); sns:callIt(x); }");
392 Number result = (Number) script.execute(ctxt, 23);
393 Assert.assertEquals(42, result);
394 result = (Number) script.execute(ctxt, 623);
395 Assert.assertEquals(642, result);
396 }
397 }