This is an automated email from the ASF dual-hosted git repository.
henrib pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-jexl.git
The following commit(s) were added to refs/heads/master by this push:
new 8e4f41d JEXL-328: ensure creation of options before evaluation do
call pragma processing, added tests Task #JEXL-328 - JXLT template scripts
evaluation do not process pragmas
8e4f41d is described below
commit 8e4f41de2f8407bc3b9e42bbbac7749944c1d538
Author: henrib <[email protected]>
AuthorDate: Wed Mar 4 17:44:54 2020 +0100
JEXL-328: ensure creation of options before evaluation do call pragma
processing, added tests
Task #JEXL-328 - JXLT template scripts evaluation do not process pragmas
---
RELEASE-NOTES.txt | 1 +
.../org/apache/commons/jexl3/internal/Engine.java | 59 +++++++++-
.../apache/commons/jexl3/internal/Interpreter.java | 6 +-
.../commons/jexl3/internal/InterpreterBase.java | 21 ++++
.../org/apache/commons/jexl3/internal/Script.java | 52 +--------
.../commons/jexl3/internal/TemplateEngine.java | 25 ++++-
.../jexl3/internal/TemplateInterpreter.java | 124 +++++++++++++++++----
.../commons/jexl3/internal/TemplateScript.java | 35 ++++--
src/site/xdoc/changes.xml | 3 +
.../org/apache/commons/jexl3/FeaturesTest.java | 2 +-
.../java/org/apache/commons/jexl3/JXLTTest.java | 98 ++++++++++++++--
11 files changed, 330 insertions(+), 96 deletions(-)
diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt
index 27f7655..4249085 100644
--- a/RELEASE-NOTES.txt
+++ b/RELEASE-NOTES.txt
@@ -74,6 +74,7 @@ New Features in 3.2:
Bugs Fixed in 3.2:
==================
+* JEXL-328: JXLT template scripts evaluation do not process pragmas
* JEXL-327: map[null] does not work in assignment context
* JEXL-326: Link to "JavaCC" on syntax reference page is broken
* JEXL-325: Potential race-condition in NumberParser.toString()
diff --git a/src/main/java/org/apache/commons/jexl3/internal/Engine.java
b/src/main/java/org/apache/commons/jexl3/internal/Engine.java
index 20da2a0..f470fd9 100644
--- a/src/main/java/org/apache/commons/jexl3/internal/Engine.java
+++ b/src/main/java/org/apache/commons/jexl3/internal/Engine.java
@@ -341,6 +341,62 @@ public class Engine extends JexlEngine {
}
/**
+ * Compute a script options for evaluation.
+ * <p>This calls processPragma(...).
+ * @param script the script
+ * @param context the context
+ * @return the options
+ */
+ protected JexlOptions options(ASTJexlScript script, JexlContext context) {
+ final JexlOptions opts = options(context);
+ if (script != null) {
+ // when parsing lexical, try hard to run lexical
+ JexlFeatures features = script.getFeatures();
+ if (features != null) {
+ if (features.isLexical()) {
+ opts.setLexical(true);
+ }
+ if (features.isLexicalShade()) {
+ opts.setLexicalShade(true);
+ }
+ }
+ // process script pragmas if any
+ processPragmas(script, context, opts);
+ }
+ return opts;
+ }
+
+ /**
+ * Processes a script pragmas.
+ * <p>Only called from options(...)
+ * @param script the script
+ * @param context the context
+ * @param opts the options
+ */
+ protected void processPragmas(ASTJexlScript script, JexlContext context,
JexlOptions opts) {
+ Map<String, Object> pragmas = script.getPragmas();
+ if (pragmas != null && !pragmas.isEmpty()) {
+ JexlContext.PragmaProcessor processor =
+ context instanceof JexlContext.PragmaProcessor
+ ? (JexlContext.PragmaProcessor) context
+ : null;
+ for(Map.Entry<String, Object> pragma : pragmas.entrySet()) {
+ String key = pragma.getKey();
+ Object value = pragma.getValue();
+ if (PRAGMA_OPTIONS.equals(key)) {
+ if (value instanceof String) {
+ String[] vs = ((String) value).split(" ");
+ opts.setFlags(vs);
+ }
+ }
+ if (processor != null) {
+ processor.processPragma(key, value);
+ }
+ }
+ }
+ }
+
+ /**
* Sets options from this engine options.
* @param opts the options to set
* @return the options
@@ -348,7 +404,7 @@ public class Engine extends JexlEngine {
public JexlOptions optionsSet(JexlOptions opts) {
if (opts != null) {
opts.set(options);
- }
+ }
return opts;
}
@@ -375,6 +431,7 @@ public class Engine extends JexlEngine {
return new Interpreter(this, opts, context, frame);
}
+
@Override
public Script createExpression(JexlInfo info, String expression) {
return createScript(expressionFeatures, info, expression, null);
diff --git a/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java
b/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java
index 99a81c9..8d955eb 100644
--- a/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java
+++ b/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java
@@ -1223,8 +1223,8 @@ public class Interpreter extends InterpreterBase {
}
if (ant != null) {
String aname = ant.toString();
- boolean undefined = !(context.has(aname));
- return unsolvableVariable(node, aname, undefined);
+ boolean defined = isVariableDefined(frame, block, aname);
+ return unsolvableVariable(node, aname, !defined);
}
return unsolvableProperty(node,
stringifyProperty(ptyNode), ptyNode == objectNode,
null);
@@ -1234,7 +1234,7 @@ public class Interpreter extends InterpreterBase {
return null;
}
String aname = ant != null ? ant.toString() : "?";
- boolean defined = context.has(aname);
+ boolean defined = isVariableDefined(frame, block, aname);
if (defined && !arithmetic.isStrict()) {
return null;
}
diff --git
a/src/main/java/org/apache/commons/jexl3/internal/InterpreterBase.java
b/src/main/java/org/apache/commons/jexl3/internal/InterpreterBase.java
index 1a69717..8655760 100644
--- a/src/main/java/org/apache/commons/jexl3/internal/InterpreterBase.java
+++ b/src/main/java/org/apache/commons/jexl3/internal/InterpreterBase.java
@@ -246,6 +246,27 @@ public abstract class InterpreterBase extends
ParserVisitor {
}
/**
+ * Checks whether a variable is defined.
+ * <p>The var may be either a local variable declared in the frame and
+ * visible from the block or defined in the context.
+ * @param frame the frame
+ * @param block the block
+ * @param name the variable name
+ * @return true if variable is defined, false otherwise
+ */
+ protected boolean isVariableDefined(Frame frame, LexicalScope block,
String name) {
+ if (frame != null && block != null) {
+ Integer ref = frame.getScope().getSymbol(name);
+ int symbol = ref != null? ref : -1;
+ if (symbol >= 0 && block.hasSymbol(symbol)) {
+ Object value = frame.get(symbol);
+ return value != Scope.UNDEFINED && value != Scope.UNDECLARED;
+ }
+ }
+ return context.has(name);
+ }
+
+ /**
* Gets a value of a defined local variable or from the context.
* @param frame the local frame
* @param block the lexical block if any
diff --git a/src/main/java/org/apache/commons/jexl3/internal/Script.java
b/src/main/java/org/apache/commons/jexl3/internal/Script.java
index c458242..ed01345 100644
--- a/src/main/java/org/apache/commons/jexl3/internal/Script.java
+++ b/src/main/java/org/apache/commons/jexl3/internal/Script.java
@@ -17,6 +17,7 @@
package org.apache.commons.jexl3.internal;
import org.apache.commons.jexl3.JexlContext;
+import org.apache.commons.jexl3.JexlFeatures;
import org.apache.commons.jexl3.JexlInfo;
import org.apache.commons.jexl3.JexlOptions;
import org.apache.commons.jexl3.JexlEngine;
@@ -27,8 +28,6 @@ import org.apache.commons.jexl3.parser.ASTJexlScript;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import org.apache.commons.jexl3.JexlFeatures;
-
/**
* <p>A JexlScript implementation.</p>
* @since 1.1
@@ -50,10 +49,6 @@ public class Script implements JexlScript, JexlExpression {
* The engine version (as class loader change count) that last evaluated
this script.
*/
protected int version;
- /**
- * The name of the options pragma.
- */
- protected static final String PRAGMA_OPTIONS = "jexl.options";
/**
* @return the script AST
@@ -105,55 +100,14 @@ public class Script implements JexlScript, JexlExpression
{
}
/**
- * Compute this script options for evaluation.
- * <p>This also calls the pragma processor
- * @param context the context
- * @return the options
- */
- protected JexlOptions options(JexlContext context) {
- JexlOptions opts = jexl.options(context);
- // when parsing lexical, try hard to run lexical
- JexlFeatures features = script.getFeatures();
- if (features != null) {
- if (features.isLexical()) {
- opts.setLexical(true);
- }
- if (features.isLexicalShade()) {
- opts.setLexicalShade(true);
- }
- }
- // process script pragmas if any
- Map<String, Object> pragmas = script.getPragmas();
- if (pragmas != null) {
- JexlContext.PragmaProcessor processor =
- context instanceof JexlContext.PragmaProcessor
- ? (JexlContext.PragmaProcessor) context
- : null;
- for(Map.Entry<String, Object> pragma : pragmas.entrySet()) {
- String key = pragma.getKey();
- Object value = pragma.getValue();
- if (PRAGMA_OPTIONS.equals(key)) {
- if (value instanceof String) {
- String[] vs = ((String) value).split(" ");
- opts.setFlags(vs);
- }
- }
- if (processor != null) {
- processor.processPragma(key, value);
- }
- }
- }
- return opts;
- }
-
- /**
* Creates this script interpreter.
* @param context the context
* @param frame the calling frame
* @return the interpreter
*/
protected Interpreter createInterpreter(JexlContext context, Frame frame) {
- return jexl.createInterpreter(context, frame, options(context));
+ JexlOptions opts = jexl.options(script, context);
+ return jexl.createInterpreter(context, frame, opts);
}
/**
diff --git
a/src/main/java/org/apache/commons/jexl3/internal/TemplateEngine.java
b/src/main/java/org/apache/commons/jexl3/internal/TemplateEngine.java
index 8f1a7ea..fa2831b 100644
--- a/src/main/java/org/apache/commons/jexl3/internal/TemplateEngine.java
+++ b/src/main/java/org/apache/commons/jexl3/internal/TemplateEngine.java
@@ -18,6 +18,7 @@ package org.apache.commons.jexl3.internal;
import org.apache.commons.jexl3.JexlContext;
import org.apache.commons.jexl3.JexlException;
+import org.apache.commons.jexl3.JexlOptions;
import org.apache.commons.jexl3.JexlInfo;
import org.apache.commons.jexl3.JxltEngine;
import org.apache.commons.jexl3.parser.ASTJexlScript;
@@ -291,7 +292,7 @@ public final class TemplateEngine extends JxltEngine {
*/
protected final TemplateExpression prepare(Frame frame, JexlContext
context) {
try {
- Interpreter interpreter = new TemplateInterpreter(jexl,
context, frame, null, null);
+ Interpreter interpreter = jexl.createInterpreter(context,
frame, jexl.options(context));
return prepare(interpreter);
} catch (JexlException xjexl) {
JexlException xuel = createException(xjexl.getInfo(),
"prepare", this, xjexl);
@@ -319,6 +320,15 @@ public final class TemplateEngine extends JxltEngine {
}
/**
+ * The options to use during evaluation.
+ * @param context the context
+ * @return the options
+ */
+ protected JexlOptions options(JexlContext context) {
+ return jexl.options(null, context);
+ }
+
+ /**
* Evaluates this expression.
* @param frame the frame storing parameters and local variables
* @param context the context storing global variables
@@ -327,7 +337,13 @@ public final class TemplateEngine extends JxltEngine {
*/
protected final Object evaluate(Frame frame, JexlContext context) {
try {
- Interpreter interpreter = new TemplateInterpreter(jexl,
context, frame, null, null);
+ JexlOptions options = options(context);
+ TemplateInterpreter.Arguments args = new TemplateInterpreter
+ .Arguments(jexl)
+ .context(context)
+ .options(options)
+ .frame(frame);
+ Interpreter interpreter = new TemplateInterpreter(args);
return evaluate(interpreter);
} catch (JexlException xjexl) {
JexlException xuel = createException(xjexl.getInfo(),
"evaluate", this, xjexl);
@@ -420,6 +436,11 @@ public final class TemplateEngine extends JxltEngine {
strb.append("}");
return strb;
}
+
+ @Override
+ protected JexlOptions options(JexlContext context) {
+ return jexl.options(node instanceof ASTJexlScript? (ASTJexlScript)
node : null, context);
+ }
@Override
protected Object evaluate(Interpreter interpreter) {
diff --git
a/src/main/java/org/apache/commons/jexl3/internal/TemplateInterpreter.java
b/src/main/java/org/apache/commons/jexl3/internal/TemplateInterpreter.java
index 7babe6f..d095625 100644
--- a/src/main/java/org/apache/commons/jexl3/internal/TemplateInterpreter.java
+++ b/src/main/java/org/apache/commons/jexl3/internal/TemplateInterpreter.java
@@ -18,14 +18,16 @@ package org.apache.commons.jexl3.internal;
import org.apache.commons.jexl3.JexlContext;
import org.apache.commons.jexl3.JexlInfo;
+import org.apache.commons.jexl3.JexlOptions;
import org.apache.commons.jexl3.internal.TemplateEngine.TemplateExpression;
import org.apache.commons.jexl3.introspection.JexlMethod;
import org.apache.commons.jexl3.introspection.JexlUberspect;
import org.apache.commons.jexl3.parser.ASTIdentifier;
-import org.apache.commons.jexl3.parser.JexlNode;
-import java.io.Writer;
import org.apache.commons.jexl3.parser.ASTJexlLambda;
import org.apache.commons.jexl3.parser.ASTJexlScript;
+import org.apache.commons.jexl3.parser.JexlNode;
+
+import java.io.Writer;
/**
* The type of interpreter to use during evaluation of templates.
@@ -39,18 +41,85 @@ public class TemplateInterpreter extends Interpreter {
private final Writer writer;
/**
+ * Helper ctor.
+ * <p>Stores the different properties required to create a Template
interpreter.
+ */
+ static class Arguments {
+ /** The engine. */
+ Engine jexl;
+ /** The options. */
+ JexlOptions options;
+ /** The context. */
+ JexlContext jcontext;
+ /** The frame. */
+ Frame jframe;
+ /** The expressions. */
+ TemplateExpression[] expressions;
+ /** The writer. */
+ Writer out;
+
+ /**
+ * Sole ctor.
+ * @param e the JEXL engine
+ */
+ Arguments(Engine e) {
+ this.jexl = e;
+ }
+ /**
+ * Sets the options.
+ * @param o the options
+ * @return this instance
+ */
+ Arguments options(JexlOptions o) {
+ this.options = o;
+ return this;
+ }
+ /**
+ * Sets the context.
+ * @param j the context
+ * @return this instance
+ */
+ Arguments context(JexlContext j) {
+ this.jcontext = j;
+ return this;
+ }
+ /**
+ * Sets the frame.
+ * @param f the frame
+ * @return this instance
+ */
+ Arguments frame(Frame f) {
+ this.jframe = f;
+ return this;
+ }
+ /**
+ * Sets the expressions.
+ * @param e the expressions
+ * @return this instance
+ */
+ Arguments expressions(TemplateExpression[] e) {
+ this.expressions = e;
+ return this;
+ }
+ /**
+ * Sets the writer.
+ * @param o the writer
+ * @return this instance
+ */
+ Arguments writer(Writer o) {
+ this.out = o;
+ return this;
+ }
+ }
+
+ /**
* Creates a template interpreter instance.
- * @param jexl the engine instance
- * @param jcontext the base context
- * @param jframe the calling frame
- * @param expressions the list of TemplateExpression from the
TemplateScript to evaluate
- * @param out the output writer
+ * @param args the template interpreter arguments
*/
- TemplateInterpreter(Engine jexl,
- JexlContext jcontext, Frame jframe, TemplateExpression[]
expressions, Writer out) {
- super(jexl, null, jcontext, jframe);
- exprs = expressions;
- writer = out;
+ TemplateInterpreter(Arguments args) {
+ super(args.jexl, args.options, args.jcontext, args.jframe);
+ exprs = args.expressions;
+ writer = args.out;
block = new LexicalFrame(frame, null);
}
@@ -145,24 +214,31 @@ public class TemplateInterpreter extends Interpreter {
}
@Override
- protected Object visit(ASTJexlScript node, Object data) {
- if (node instanceof ASTJexlLambda && !((ASTJexlLambda)
node).isTopLevel()) {
- return new Closure(this, (ASTJexlLambda) node) {
+ protected Object visit(ASTJexlScript script, Object data) {
+ if (script instanceof ASTJexlLambda && !((ASTJexlLambda)
script).isTopLevel()) {
+ return new Closure(this, (ASTJexlLambda) script) {
@Override
protected Interpreter createInterpreter(JexlContext context,
Frame local) {
- return new TemplateInterpreter(jexl, context, local,
exprs, writer);
+ JexlOptions opts = jexl.options(script, context);
+ TemplateInterpreter.Arguments targs = new
TemplateInterpreter.Arguments(jexl)
+ .context(context)
+ .options(opts)
+ .frame(local)
+ .expressions(exprs)
+ .writer(writer);
+ return new TemplateInterpreter(targs);
}
};
}
// otherwise...
- final int numChildren = node.jjtGetNumChildren();
- Object result = null;
- for (int i = 0; i < numChildren; i++) {
- JexlNode child = node.jjtGetChild(i);
- result = child.jjtAccept(this, data);
- cancelCheck(child);
+ final int numChildren = script.jjtGetNumChildren();
+ Object result = null;
+ for (int i = 0; i < numChildren; i++) {
+ JexlNode child = script.jjtGetChild(i);
+ result = child.jjtAccept(this, data);
+ cancelCheck(child);
+ }
+ return result;
}
- return result;
- }
}
diff --git
a/src/main/java/org/apache/commons/jexl3/internal/TemplateScript.java
b/src/main/java/org/apache/commons/jexl3/internal/TemplateScript.java
index eed231c..88f4ccc 100644
--- a/src/main/java/org/apache/commons/jexl3/internal/TemplateScript.java
+++ b/src/main/java/org/apache/commons/jexl3/internal/TemplateScript.java
@@ -23,6 +23,14 @@ import
org.apache.commons.jexl3.internal.TemplateEngine.Block;
import org.apache.commons.jexl3.internal.TemplateEngine.BlockType;
import org.apache.commons.jexl3.internal.TemplateEngine.TemplateExpression;
import org.apache.commons.jexl3.parser.ASTJexlScript;
+import org.apache.commons.jexl3.JexlException;
+import org.apache.commons.jexl3.JexlOptions;
+import org.apache.commons.jexl3.parser.ASTArguments;
+import org.apache.commons.jexl3.parser.ASTFunctionNode;
+import org.apache.commons.jexl3.parser.ASTIdentifier;
+import org.apache.commons.jexl3.parser.ASTNumberLiteral;
+import org.apache.commons.jexl3.parser.JexlNode;
+
import java.io.Reader;
import java.io.Writer;
import java.util.ArrayList;
@@ -30,12 +38,6 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
-import org.apache.commons.jexl3.JexlException;
-import org.apache.commons.jexl3.parser.ASTArguments;
-import org.apache.commons.jexl3.parser.ASTFunctionNode;
-import org.apache.commons.jexl3.parser.ASTIdentifier;
-import org.apache.commons.jexl3.parser.ASTNumberLiteral;
-import org.apache.commons.jexl3.parser.JexlNode;
/**
* A Template instance.
@@ -246,9 +248,15 @@ public final class TemplateScript implements
JxltEngine.Template {
@Override
public TemplateScript prepare(JexlContext context) {
- Engine jexl = jxlt.getEngine();
+ final Engine jexl = jxlt.getEngine();
+ JexlOptions options = jexl.options(script, context);
Frame frame = script.createFrame((Object[]) null);
- Interpreter interpreter = new TemplateInterpreter(jexl, context,
frame, null, null);
+ TemplateInterpreter.Arguments targs = new TemplateInterpreter
+ .Arguments(jxlt.getEngine())
+ .context(context)
+ .options(options)
+ .frame(frame);
+ Interpreter interpreter = new TemplateInterpreter(targs);
TemplateExpression[] immediates = new TemplateExpression[exprs.length];
for (int e = 0; e < exprs.length; ++e) {
try {
@@ -272,8 +280,17 @@ public final class TemplateScript implements
JxltEngine.Template {
@Override
public void evaluate(JexlContext context, Writer writer, Object... args) {
+ final Engine jexl = jxlt.getEngine();
+ JexlOptions options = jexl.options(script, context);
Frame frame = script.createFrame(args);
- Interpreter interpreter = new TemplateInterpreter(jxlt.getEngine(),
context, frame, exprs, writer);
+ TemplateInterpreter.Arguments targs = new TemplateInterpreter
+ .Arguments(jexl)
+ .context(context)
+ .options(options)
+ .frame(frame)
+ .expressions(exprs)
+ .writer(writer);
+ Interpreter interpreter = new TemplateInterpreter(targs);
interpreter.interpret(script);
}
diff --git a/src/site/xdoc/changes.xml b/src/site/xdoc/changes.xml
index 8d80239..83c6b23 100644
--- a/src/site/xdoc/changes.xml
+++ b/src/site/xdoc/changes.xml
@@ -26,6 +26,9 @@
</properties>
<body>
<release version="3.2" date="unreleased">
+ <action dev="henrib" type="fix" issue="JEXL-328">
+ JXLT template scripts evaluation do not process pragmas
+ </action>
<action dev="henrib" type="fix" issue="JEXL-327" due-to="David
Costanzo">
map[null] does not work in assignment context
</action>
diff --git a/src/test/java/org/apache/commons/jexl3/FeaturesTest.java
b/src/test/java/org/apache/commons/jexl3/FeaturesTest.java
index 02256ad..01fbf5e 100644
--- a/src/test/java/org/apache/commons/jexl3/FeaturesTest.java
+++ b/src/test/java/org/apache/commons/jexl3/FeaturesTest.java
@@ -46,7 +46,7 @@ public class FeaturesTest extends JexlTestCase {
JexlScript ctl = JEXL.createScript(script);
Assert.assertNotNull(ctl);
try {
- JexlScript e = jexl.createScript(features, null, script, null);
+ JexlScript e = jexl.createScript(features, null, script);
Assert.fail("should fail parse: " + script);
} catch (JexlException.Feature xfeature) {
String msg = xfeature.getMessage();
diff --git a/src/test/java/org/apache/commons/jexl3/JXLTTest.java
b/src/test/java/org/apache/commons/jexl3/JXLTTest.java
index 95d1dd3..9f91d3c 100644
--- a/src/test/java/org/apache/commons/jexl3/JXLTTest.java
+++ b/src/test/java/org/apache/commons/jexl3/JXLTTest.java
@@ -17,7 +17,6 @@
package org.apache.commons.jexl3;
import org.apache.commons.jexl3.internal.Debugger;
-import org.apache.commons.jexl3.internal.Engine;
import org.apache.commons.jexl3.internal.TemplateDebugger;
import org.apache.commons.jexl3.internal.TemplateScript;
import org.apache.commons.logging.Log;
@@ -28,7 +27,6 @@ import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.util.Arrays;
-import java.util.Collection;
import java.util.List;
import java.util.Set;
@@ -95,8 +93,7 @@ public class JXLTTest extends JexlTestCase {
if (options.isLexicalShade()) {
return true;
}
- options = new JexlOptions();
- ((Engine) ENGINE).optionsSet(options);
+ options = new JexlOptions().set(ENGINE);
return options.isLexicalShade();
}
@@ -161,12 +158,14 @@ public class JXLTTest extends JexlTestCase {
@Test
public void testAssign() throws Exception {
- JxltEngine.Expression assign = JXLT.createExpression("${froboz.value =
10}");
+ Froboz froboz = new Froboz(32);
+ context.set("froboz", froboz);
+ JxltEngine.Expression assign = JXLT.createExpression("${froboz.value =
42}");
JxltEngine.Expression check = JXLT.createExpression("${froboz.value}");
Object o = assign.evaluate(context);
- Assert.assertEquals("Result is not 10", new Integer(10), o);
+ Assert.assertEquals("Result is not 10", new Integer(42), o);
o = check.evaluate(context);
- Assert.assertEquals("Result is not 10", new Integer(10), o);
+ Assert.assertEquals("Result is not 10", new Integer(42), o);
}
@Test
@@ -1001,5 +1000,90 @@ public class JXLTTest extends JexlTestCase {
output = strw.toString();
Assert.assertEquals(s315, output);
}
+
+ // define mode pro50
+ static final JexlOptions MODE_PRO50 = new JexlOptions();
+ static {
+ MODE_PRO50.setFlags( "+strict +cancellable +lexical +lexicalShade
-safe".split(" "));
+ }
+
+ public static class PragmaticContext extends MapContext implements
JexlContext.PragmaProcessor, JexlContext.OptionsHandle {
+ private final JexlOptions options;
+
+ public PragmaticContext(JexlOptions o) {
+ this.options = o;
+ }
+
+ @Override
+ public void processPragma(String key, Object value) {
+ if ("script.mode".equals(key) && "pro50".equals(value)) {
+ options.set(MODE_PRO50);
+ }
+ }
+
+ @Override
+ public Object get(String name) {
+ if ("$options".equals(name)) {
+ return options;
+ }
+ return super.get(name);
+ }
+
+ @Override
+ public JexlOptions getEngineOptions() {
+ return options;
+ }
+ }
+ @Test
+ public void testLexicalTemplate() throws Exception {
+ JexlOptions opts = new JexlOptions();
+ JexlContext ctxt = new PragmaticContext(opts);
+ opts.setCancellable(false);
+ opts.setStrict(false);
+ opts.setSafe(true);
+ opts.setLexical(false);
+ opts.setLexicalShade(false);
+ String src0 = "${$options.strict?'+':'-'}strict"
+ + " ${$options.cancellable?'+':'-'}cancellable"
+ + " ${$options.lexical?'+':'-'}lexical"
+ + " ${$options.lexicalShade?'+':'-'}lexicalShade"
+ + " ${$options.safe?'+':'-'}safe";
+
+ JxltEngine.Template tmplt0 = JXLT.createTemplate("$$", new
StringReader(src0));
+ Writer strw0 = new StringWriter();
+ tmplt0.evaluate(ctxt, strw0);
+ String output0 = strw0.toString();
+ Assert.assertEquals( "-strict -cancellable -lexical -lexicalShade
+safe", output0);
+
+ String src = "$$ #pragma script.mode pro50\n"
+ + "${$options.strict?'+':'-'}strict"
+ + " ${$options.cancellable?'+':'-'}cancellable"
+ + " ${$options.lexical?'+':'-'}lexical"
+ + " ${$options.lexicalShade?'+':'-'}lexicalShade"
+ + " ${$options.safe?'+':'-'}safe";
+
+ JxltEngine.Template tmplt = JXLT.createTemplate("$$", new
StringReader(src));
+ Writer strw = new StringWriter();
+ tmplt.evaluate(ctxt, strw);
+ String output = strw.toString();
+ Assert.assertEquals("+strict +cancellable +lexical +lexicalShade
-safe", output);
+ }
+ @Test
+ public void testTemplatePragmaPro50() throws Exception {
+ JexlOptions opts = new JexlOptions();
+ JexlContext ctxt = new PragmaticContext(opts);
+ String src = "$$ #pragma script.mode pro50\n"
+ + "$$ var tab = null;\n"
+ + "$$ tab.dummy();";
+ JxltEngine.Template tmplt = JXLT.createTemplate("$$", new
StringReader(src));
+ Writer strw = new StringWriter();
+ try {
+ tmplt.evaluate(ctxt, strw);
+ Assert.fail("tab var is null");
+ } catch (JexlException.Variable xvar) {
+ Assert.assertTrue("tab".equals(xvar.getVariable()));
+ Assert.assertFalse(xvar.isUndefined());
+ }
+ }
}