You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by he...@apache.org on 2017/11/29 16:27:05 UTC
svn commit: r1816640 [1/2] - in /commons/proper/jexl/trunk: ./
src/main/java/org/apache/commons/jexl3/
src/main/java/org/apache/commons/jexl3/internal/
src/main/java/org/apache/commons/jexl3/parser/ src/site/xdoc/
src/test/java/org/apache/commons/jexl3...
Author: henrib
Date: Wed Nov 29 16:27:04 2017
New Revision: 1816640
URL: http://svn.apache.org/viewvc?rev=1816640&view=rev
Log:
JEXL-243:
Features, refined version. Allow fine grain on what is syntactically available for both scripts and expressions (and make expressions a subset of script features).
Added:
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/ScriptVisitor.java (with props)
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Source.java (with props)
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/FeatureController.java (with props)
Modified:
commons/proper/jexl/trunk/RELEASE-NOTES.txt
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlBuilder.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlEngine.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlFeatures.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Debugger.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Engine.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Script.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/TemplateEngine.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/TemplateScript.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ASTJexlScript.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/JexlParser.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt
commons/proper/jexl/trunk/src/site/xdoc/changes.xml
commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ContextNamespaceTest.java
commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ExceptionTest.java
commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/FeaturesTest.java
commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/IfTest.java
commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/IssuesTest200.java
commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/JexlTest.java
commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/PropertyAccessTest.java
commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/internal/Util.java
commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/parser/ParserTest.java
Modified: commons/proper/jexl/trunk/RELEASE-NOTES.txt
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/RELEASE-NOTES.txt?rev=1816640&r1=1816639&r2=1816640&view=diff
==============================================================================
--- commons/proper/jexl/trunk/RELEASE-NOTES.txt (original)
+++ commons/proper/jexl/trunk/RELEASE-NOTES.txt Wed Nov 29 16:27:04 2017
@@ -27,11 +27,15 @@ Version 3.2 is a minor release.
New Features in 3.2:
====================
+
+* JEXL-243: Allow restricting available features in Script/Expressions
* JEXL-238: Restrict getLiteralClass to a Number for NumberLiterals
+* JEXL-237: Ability to restrict usage of certain names when declaring local variables
* JEXL-236: Support CharSequence in size(), empty() and contains() operators
* JEXL-234: Extend application of operators startsWith and endsWith from String to CharSequence types
* JEXL-226: add ?? operator support
* JEXL-224: The ability to overload call() operator in customized JexlArithmetic implementation
+* JEXL-212: Restrict usage of assignment statements in JexlExpression
Bugs Fixed in 3.2:
==================
Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlBuilder.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlBuilder.java?rev=1816640&r1=1816639&r2=1816640&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlBuilder.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlBuilder.java Wed Nov 29 16:27:04 2017
@@ -175,7 +175,9 @@ public class JexlBuilder {
}
/**
- * Sets the features the engine will use.
+ * Sets the features the engine will use as a base by default.
+ * <p>Note that the script flag will be ignored; the engine will be able to parse expressions and scripts.
+ * <p>Note also that these will apply to template expressions and scripts.
* @param f the features
* @return this builder
*/
Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlEngine.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlEngine.java?rev=1816640&r1=1816639&r2=1816640&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlEngine.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlEngine.java Wed Nov 29 16:27:04 2017
@@ -322,9 +322,21 @@ public abstract class JexlEngine {
public abstract JexlExpression createExpression(JexlInfo info, String expression);
/**
+ * Creates a JexlExpression from a String containing valid JEXL syntax.
+ * This method parses the expression which must contain either a reference or an expression.
+ *
+ * @param expression A String containing valid JEXL syntax
+ * @return An {@link JexlExpression} which can be evaluated using a {@link JexlContext}
+ * @throws JexlException if there is a problem parsing the script
+ */
+ public final JexlExpression createExpression(String expression) {
+ return createExpression(null, expression);
+ }
+ /**
* Creates a JexlScript from a String containing valid JEXL syntax.
* This method parses the script and validates the syntax.
*
+ * @param features A set of features that will be enforced during parsing
* @param info An info structure to carry debugging information if needed
* @param source A string containing valid JEXL syntax
* @param names The script parameter names used during parsing; a corresponding array of arguments containing
@@ -332,18 +344,21 @@ public abstract class JexlEngine {
* @return A {@link JexlScript} which can be executed using a {@link JexlContext}
* @throws JexlException if there is a problem parsing the script
*/
- public abstract JexlScript createScript(JexlInfo info, String source, String[] names);
+ public abstract JexlScript createScript(JexlFeatures features, JexlInfo info, String source, String[] names);
/**
- * Creates a JexlExpression from a String containing valid JEXL syntax.
- * This method parses the expression which must contain either a reference or an expression.
+ * Creates a JexlScript from a String containing valid JEXL syntax.
+ * This method parses the script and validates the syntax.
*
- * @param expression A String containing valid JEXL syntax
- * @return An {@link JexlExpression} which can be evaluated using a {@link JexlContext}
+ * @param info An info structure to carry debugging information if needed
+ * @param source A string containing valid JEXL syntax
+ * @param names The script parameter names used during parsing; a corresponding array of arguments containing
+ * values should be used during evaluation
+ * @return A {@link JexlScript} which can be executed using a {@link JexlContext}
* @throws JexlException if there is a problem parsing the script
*/
- public final JexlExpression createExpression(String expression) {
- return createExpression(null, expression);
+ public final JexlScript createScript(JexlInfo info, String source, String[] names) {
+ return createScript(null, null, source, names);
}
/**
@@ -355,7 +370,7 @@ public abstract class JexlEngine {
* @throws JexlException if there is a problem parsing the script.
*/
public final JexlScript createScript(String scriptText) {
- return createScript(null, scriptText, null);
+ return createScript(null, null, scriptText, null);
}
/**
@@ -369,7 +384,7 @@ public abstract class JexlEngine {
* @throws JexlException if there is a problem parsing the script
*/
public final JexlScript createScript(String scriptText, String... names) {
- return createScript(null, scriptText, names);
+ return createScript(null, null, scriptText, names);
}
/**
@@ -381,7 +396,7 @@ public abstract class JexlEngine {
* @throws JexlException if there is a problem reading or parsing the script.
*/
public final JexlScript createScript(File scriptFile) {
- return createScript(null, readSource(scriptFile), null);
+ return createScript(null, null, readSource(scriptFile), null);
}
/**
@@ -395,7 +410,7 @@ public abstract class JexlEngine {
* @throws JexlException if there is a problem reading or parsing the script.
*/
public final JexlScript createScript(File scriptFile, String... names) {
- return createScript(null, readSource(scriptFile), names);
+ return createScript(null, null, readSource(scriptFile), names);
}
/**
@@ -410,7 +425,7 @@ public abstract class JexlEngine {
* @throws JexlException if there is a problem reading or parsing the script.
*/
public final JexlScript createScript(JexlInfo info, File scriptFile, String[] names) {
- return createScript(info, readSource(scriptFile), names);
+ return createScript(null, info, readSource(scriptFile), names);
}
/**
@@ -436,7 +451,7 @@ public abstract class JexlEngine {
* @throws JexlException if there is a problem reading or parsing the script.
*/
public final JexlScript createScript(URL scriptUrl, String[] names) {
- return createScript(null, readSource(scriptUrl), names);
+ return createScript(null, null, readSource(scriptUrl), names);
}
/**
@@ -451,7 +466,7 @@ public abstract class JexlEngine {
* @throws JexlException if there is a problem reading or parsing the script.
*/
public final JexlScript createScript(JexlInfo info, URL scriptUrl, String[] names) {
- return createScript(info, readSource(scriptUrl), names);
+ return createScript(null, info, readSource(scriptUrl), names);
}
/**
Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlFeatures.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlFeatures.java?rev=1816640&r1=1816639&r2=1816640&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlFeatures.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlFeatures.java Wed Nov 29 16:27:04 2017
@@ -14,7 +14,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package org.apache.commons.jexl3;
import java.util.Collection;
@@ -24,15 +23,23 @@ import java.util.TreeSet;
/**
* A set of language feature options.
- *
+ * These control <em>syntactical</em> constructs that will throw JexlException.Feature exceptions (a
+ * subclass of JexlException.Parsing) when disabled.
+ * <p>
* <ul>
+ * <li>Registers: register syntax (#number), used internally for {g,s}etProperty
* <li>Reserved Names: a set of reserved variable names that can not be used as local variable (or parameter) names
- * <li>Registers: boolean property allowing parsing of register syntax (#number)
- * <li>Global Side Effect : boolean property controlling assigning/modifying values on global variables
- * <li>Side Effect: boolean property controlling side effects assigning/modifying values on any variable
- * <li>New Instance: boolean property controlling creating new instances through new(...) or using class as functor
- * <li>Loops: boolean property controlling usage of loop constructs (while(true), for(...))
- * <li>Lambda: boolean property controlling usage of script function declarations
+ * <li>Global Side Effect : assigning/modifying values on global variables (=, += , -=, ...)
+ * <li>Side Effect : assigning/modifying values on any variables or left-value
+ * <li>Constant Array Reference: ensures array references only use constants;they should be statically solvable.
+ * <li>New Instance: creating an instance using new(...)
+ * <li>Loops: loop constructs (while(true), for(...))
+ * <li>Lambda: function definitions (()->{...}, function(...) ).
+ * <li>Method calls: calling methods (obj.method(...) or obj['method'](...)); when disabled, leaves function calls
+ * - including namespace prefixes - available
+ * <li>Structured literals: arrays, lists, maps, sets, ranges
+ * <li>Pragmas: #pragma x y
+ * <li>Annotation: @annotation statement;
* </ul>
* @since 3.2
*/
@@ -44,36 +51,54 @@ public final class JexlFeatures {
/** Te feature names (for toString()). */
private static final String[] F_NAMES = {
"register", "reserved variable", "local variable", "assign/modify",
- "global assign/modify", "new(...)", "for(...)/while(...)", "function"
+ "global assign/modify", "array reference", "create instance", "loop", "function",
+ "method call", "set/map/array literal", "pragma", "annotation", "script"
};
/** Registers feature ordinal. */
- private static final int REGISTERS = 0;
+ private static final int REGISTER = 0;
/** Reserved name feature ordinal. */
public static final int RESERVED = 1;
/** Locals feature ordinal. */
- public static final int LOCALS = 2;
+ public static final int LOCAL_VAR = 2;
/** Side-effects feature ordinal. */
- public static final int SIDE_EFFECTS = 3;
+ public static final int SIDE_EFFECT = 3;
/** Global side-effects feature ordinal. */
- public static final int SIDE_EFFECTS_GLOBALS = 4;
+ public static final int SIDE_EFFECT_GLOBAL = 4;
+ /** Array get is allowed on expr. */
+ public static final int ARRAY_REF_EXPR = 5;
/** New-instance feature ordinal. */
- public static final int NEW_INSTANCE = 5;
+ public static final int NEW_INSTANCE = 6;
/** Loops feature ordinal. */
- public static final int LOOPS = 6;
+ public static final int LOOP = 7;
+ /** Lambda feature ordinal. */
+ public static final int LAMBDA = 8;
/** Lambda feature ordinal. */
- public static final int LAMBDA = 7;
+ public static final int METHOD_CALL = 9;
+ /** Structured literal feature ordinal. */
+ public static final int STRUCTURED_LITERAL = 10;
+ /** Pragma feature ordinal. */
+ public static final int PRAGMA = 11;
+ /** Annotation feature ordinal. */
+ public static final int ANNOTATION = 12;
+ /** Script feature ordinal. */
+ public static final int SCRIPT = 13;
/**
* Creates an all-features-enabled instance.
*/
public JexlFeatures() {
- flags = (1L) // << REGISTERS)
- | (1L << LOCALS)
- | (1L << SIDE_EFFECTS)
- | (1L << SIDE_EFFECTS_GLOBALS)
+ flags = (1L << LOCAL_VAR)
+ | (1L << SIDE_EFFECT)
+ | (1L << SIDE_EFFECT_GLOBAL)
+ | (1L << ARRAY_REF_EXPR)
| (1L << NEW_INSTANCE)
- | (1L << LOOPS)
- | (1L << LAMBDA);
+ | (1L << LOOP)
+ | (1L << LAMBDA)
+ | (1L << METHOD_CALL)
+ | (1L << STRUCTURED_LITERAL)
+ | (1L << PRAGMA)
+ | (1L << ANNOTATION)
+ | (1L << SCRIPT);
reservedNames = Collections.emptySet();
}
@@ -86,13 +111,43 @@ public final class JexlFeatures {
this.reservedNames = features.reservedNames;
}
+ @Override
+ public int hashCode() { //CSOFF: MagicNumber
+ int hash = 3;
+ hash = 53 * hash + (int) (this.flags ^ (this.flags >>> 32));
+ hash = 53 * hash + (this.reservedNames != null ? this.reservedNames.hashCode() : 0);
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final JexlFeatures other = (JexlFeatures) obj;
+ if (this.flags != other.flags) {
+ return false;
+ }
+ if (this.reservedNames != other.reservedNames
+ && (this.reservedNames == null || !this.reservedNames.equals(other.reservedNames))) {
+ return false;
+ }
+ return true;
+ }
+
/**
* The text corresponding to a feature code.
* @param feature the feature number
* @return the feature name
*/
public static String stringify(int feature) {
- return feature >= 0 && feature < F_NAMES.length? F_NAMES[feature] : "unsupported feature";
+ return feature >= 0 && feature < F_NAMES.length ? F_NAMES[feature] : "unsupported feature";
}
/**
@@ -123,13 +178,13 @@ public final class JexlFeatures {
* @return true if reserved, false otherwise
*/
public boolean isReservedName(String name) {
- return reservedNames.contains(name);
+ return name != null && reservedNames.contains(name);
}
/**
* Sets a feature flag.
* @param feature the feature ordinal
- * @param flag turn-on, turn off
+ * @param flag turn-on, turn off
*/
private void setFeature(int feature, boolean flag) {
if (flag) {
@@ -149,83 +204,150 @@ public final class JexlFeatures {
}
/**
- * Sets whether registers are enabled.
- * <p>When disabled, parsing a script/expression using the register syntax will throw a parsing exception.
+ * Sets whether register are enabled.
+ * <p>
+ * This is mostly used internally during execution of JexlEngine.{g,s}etProperty.
+ * <p>
+ * When disabled, parsing a script/expression using the register syntax will throw a parsing exception.
* @param flag true to enable, false to disable
* @return this features instance
*/
- public JexlFeatures registers(boolean flag) {
- setFeature(REGISTERS, flag);
+ public JexlFeatures register(boolean flag) {
+ setFeature(REGISTER, flag);
return this;
}
/**
* @return true if register syntax is enabled
*/
- public boolean supportsRegisters() {
- return getFeature(REGISTERS);
+ public boolean supportsRegister() {
+ return getFeature(REGISTER);
}
/**
* Sets whether local variables are enabled.
- * <p>When disabled, parsing a script/expression using a local variable or parameter syntax
+ * <p>
+ * When disabled, parsing a script/expression using a local variable or parameter syntax
* will throw a parsing exception.
* @param flag true to enable, false to disable
* @return this features instance
*/
- public JexlFeatures locals(boolean flag) {
- setFeature(LOCALS, flag);
+ public JexlFeatures localVar(boolean flag) {
+ setFeature(LOCAL_VAR, flag);
return this;
}
/**
* @return true if local variables syntax is enabled
*/
- public boolean supportsLocals() {
- return getFeature(LOCALS);
+ public boolean supportsLocalVar() {
+ return getFeature(LOCAL_VAR);
}
- /**
+ /**
* Sets whether side effect expressions on global variables (aka non local) are enabled.
- * <p>When disabled, parsing a script/expression using syntactical constructs modifying variables
+ * <p>
+ * When disabled, parsing a script/expression using syntactical constructs modifying variables
* <em>including all potentially ant-ish variables</em> will throw a parsing exception.
* @param flag true to enable, false to disable
* @return this features instance
*/
- public JexlFeatures sideEffectsGlobal(boolean flag) {
- setFeature(SIDE_EFFECTS_GLOBALS, flag);
+ public JexlFeatures sideEffectGlobal(boolean flag) {
+ setFeature(SIDE_EFFECT_GLOBAL, flag);
return this;
}
/**
* @return true if global variables can be assigned
*/
- public boolean supportsSideEffectsGlobal() {
- return getFeature(SIDE_EFFECTS_GLOBALS);
+ public boolean supportsSideEffectGlobal() {
+ return getFeature(SIDE_EFFECT_GLOBAL);
}
- /**
+ /**
* Sets whether side effect expressions are enabled.
- * <p>When disabled, parsing a script/expression using syntactical constructs modifying variables
+ * <p>
+ * When disabled, parsing a script/expression using syntactical constructs modifying variables
* or members will throw a parsing exception.
* @param flag true to enable, false to disable
* @return this features instance
*/
- public JexlFeatures sideEffects(boolean flag) {
- setFeature(SIDE_EFFECTS, flag);
+ public JexlFeatures sideEffect(boolean flag) {
+ setFeature(SIDE_EFFECT, flag);
return this;
}
/**
* @return true if side effects are enabled, false otherwise
*/
- public boolean supportsSideEffects() {
- return getFeature(SIDE_EFFECTS);
+ public boolean supportsSideEffect() {
+ return getFeature(SIDE_EFFECT);
+ }
+
+ /**
+ * Sets whether array references expressions are enabled.
+ * <p>
+ * When disabled, parsing a script/expression using 'obj[ ref ]' where ref is not a string or integer literal
+ * will throw a parsing exception;
+ * @param flag true to enable, false to disable
+ * @return this features instance
+ */
+ public JexlFeatures arrayReferenceExpr(boolean flag) {
+ setFeature(ARRAY_REF_EXPR, flag);
+ return this;
+ }
+
+ /**
+ * @return true if array references can contain method call expressions, false otherwise
+ */
+ public boolean supportsArrayReferenceExpr() {
+ return getFeature(ARRAY_REF_EXPR);
+ }
+
+ /**
+ * Sets whether method calls expressions are enabled.
+ * <p>
+ * When disabled, parsing a script/expression using 'obj.method()'
+ * will throw a parsing exception;
+ * @param flag true to enable, false to disable
+ * @return this features instance
+ */
+ public JexlFeatures methodCall(boolean flag) {
+ setFeature(METHOD_CALL, flag);
+ return this;
+ }
+
+ /**
+ * @return true if array references can contain expressions, false otherwise
+ */
+ public boolean supportsMethodCall() {
+ return getFeature(METHOD_CALL);
+ }
+
+ /**
+ * Sets whether array/map/set literal expressions are enabled.
+ * <p>
+ * When disabled, parsing a script/expression creating one of these literals
+ * will throw a parsing exception;
+ * @param flag true to enable, false to disable
+ * @return this features instance
+ */
+ public JexlFeatures structuredLiteral(boolean flag) {
+ setFeature(STRUCTURED_LITERAL, flag);
+ return this;
+ }
+
+ /**
+ * @return true if array/map/set literal expressions are supported, false otherwise
+ */
+ public boolean supportsStructuredLiteral() {
+ return getFeature(STRUCTURED_LITERAL);
}
- /**
+ /**
* Sets whether creating new instances is enabled.
- * <p>When disabled, parsing a script/expression using 'new(...)' will throw a parsing exception;
+ * <p>
+ * When disabled, parsing a script/expression using 'new(...)' will throw a parsing exception;
* using a class as functor will fail at runtime.
* @param flag true to enable, false to disable
* @return this features instance
@@ -244,13 +366,14 @@ public final class JexlFeatures {
/**
* Sets whether looping constructs are enabled.
- * <p>When disabled, parsing a script/expression using syntactic looping constructs (for,while)
+ * <p>
+ * When disabled, parsing a script/expression using syntactic looping constructs (for,while)
* will throw a parsing exception.
* @param flag true to enable, false to disable
* @return this features instance
*/
public JexlFeatures loops(boolean flag) {
- setFeature(LOOPS, flag);
+ setFeature(LOOP, flag);
return this;
}
@@ -258,12 +381,13 @@ public final class JexlFeatures {
* @return true if loops are enabled, false otherwise
*/
public boolean supportsLoops() {
- return getFeature(LOOPS);
+ return getFeature(LOOP);
}
- /**
+ /**
* Sets whether lambda/function constructs are enabled.
- * <p>When disabled, parsing a script/expression using syntactic lambda constructs (->,function)
+ * <p>
+ * When disabled, parsing a script/expression using syntactic lambda constructs (->,function)
* will throw a parsing exception.
* @param flag true to enable, false to disable
* @return this features instance
@@ -280,4 +404,72 @@ public final class JexlFeatures {
return getFeature(LAMBDA);
}
+ /**
+ * Sets whether pragma constructs are enabled.
+ * <p>
+ * When disabled, parsing a script/expression using syntactic pragma constructs (#pragma)
+ * will throw a parsing exception.
+ * @param flag true to enable, false to disable
+ * @return this features instance
+ */
+ public JexlFeatures pragma(boolean flag) {
+ setFeature(PRAGMA, flag);
+ return this;
+ }
+
+ /**
+ * @return true if pragma are enabled, false otherwise
+ */
+ public boolean supportsPragma() {
+ return getFeature(PRAGMA);
+ }
+
+ /**
+ * Sets whether annotation constructs are enabled.
+ * <p>
+ * When disabled, parsing a script/expression using syntactic annotation constructs (@annotation)
+ * will throw a parsing exception.
+ * @param flag true to enable, false to disable
+ * @return this features instance
+ */
+ public JexlFeatures annotation(boolean flag) {
+ setFeature(ANNOTATION, flag);
+ return this;
+ }
+
+ /**
+ * @return true if annotation are enabled, false otherwise
+ */
+ public boolean supportsAnnotation() {
+ return getFeature(ANNOTATION);
+ }
+
+ /**
+ * Sets whether scripts constructs are enabled.
+ * <p>
+ * When disabled, parsing a script using syntactic script constructs (statements, ...)
+ * will throw a parsing exception.
+ * @param flag true to enable, false to disable
+ * @return this features instance
+ */
+ public JexlFeatures script(boolean flag) {
+ setFeature(SCRIPT, flag);
+ return this;
+ }
+
+ /**
+ * @return true if scripts are enabled, false otherwise
+ */
+ public boolean supportsScript() {
+ return getFeature(SCRIPT);
+ }
+
+ /**
+ *
+ * @return true if expressions (aka not scripts) are enabled, false otherwise
+ */
+ public boolean supportsExpression() {
+ return !getFeature(SCRIPT);
+ }
+
}
Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Debugger.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Debugger.java?rev=1816640&r1=1816639&r2=1816640&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Debugger.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Debugger.java Wed Nov 29 16:27:04 2017
@@ -280,7 +280,8 @@ public class Debugger extends ParserVisi
|| child instanceof ASTBlock
|| child instanceof ASTIfStatement
|| child instanceof ASTForeachStatement
- || child instanceof ASTWhileStatement)) {
+ || child instanceof ASTWhileStatement
+ || child instanceof ASTAnnotation)) {
builder.append(';');
if (indent > 0) {
builder.append('\n');
@@ -622,15 +623,23 @@ public class Debugger extends ParserVisi
@Override
protected Object visit(ASTIfStatement node, Object data) {
+ final int numChildren = node.jjtGetNumChildren();
+ // if (...) ...
builder.append("if (");
accept(node.jjtGetChild(0), data);
builder.append(") ");
- if (node.jjtGetNumChildren() > 1) {
- acceptStatement(node.jjtGetChild(1), data);
- if (node.jjtGetNumChildren() > 2) {
- builder.append(" else ");
- acceptStatement(node.jjtGetChild(2), data);
- }
+ acceptStatement(node.jjtGetChild(1), data);
+ //.. else if (...) ...
+ for(int c = 2; c < numChildren - 1; c += 2) {
+ builder.append(" else if (");
+ accept(node.jjtGetChild(c), data);
+ builder.append(") ");
+ acceptStatement(node.jjtGetChild(c + 1), data);
+ }
+ // else...
+ if (numChildren % 2 == 1) {
+ builder.append(" else ");
+ acceptStatement(node.jjtGetChild(numChildren - 1), data);
} else {
builder.append(';');
}
@@ -993,14 +1002,7 @@ public class Debugger extends ParserVisi
builder.append('@');
builder.append(node.getName());
if (num > 0) {
- builder.append("(");
- accept(node.jjtGetChild(0), data);
- for(int i = 0; i < num; ++i) {
- builder.append(", ");
- JexlNode child = node.jjtGetChild(i);
- acceptStatement(child, data);
- }
- builder.append(")");
+ accept(node.jjtGetChild(0), data); // zut
}
return null;
}
@@ -1009,6 +1011,9 @@ public class Debugger extends ParserVisi
protected Object visit(ASTAnnotatedStatement node, Object data) {
int num = node.jjtGetNumChildren();
for (int i = 0; i < num; ++i) {
+ if (i > 0) {// && child instanceof ASTBlock) {
+ builder.append(' ');
+ }
JexlNode child = node.jjtGetChild(i);
acceptStatement(child, data);
}
Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Engine.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Engine.java?rev=1816640&r1=1816639&r2=1816640&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Engine.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Engine.java Wed Nov 29 16:27:04 2017
@@ -21,6 +21,7 @@ import org.apache.commons.jexl3.JexlBuil
import org.apache.commons.jexl3.JexlContext;
import org.apache.commons.jexl3.JexlEngine;
import org.apache.commons.jexl3.JexlException;
+import org.apache.commons.jexl3.JexlFeatures;
import org.apache.commons.jexl3.JexlInfo;
import org.apache.commons.jexl3.JexlScript;
import org.apache.commons.jexl3.internal.introspection.SandboxUberspect;
@@ -73,6 +74,10 @@ public class Engine extends JexlEngine {
private UberspectHolder() {}
}
/**
+ * The Log to which all JexlEngine messages will be logged.
+ */
+ protected final Log logger;
+ /**
* The JexlUberspect instance.
*/
protected final JexlUberspect uberspect;
@@ -81,18 +86,9 @@ public class Engine extends JexlEngine {
*/
protected final JexlArithmetic arithmetic;
/**
- * The Log to which all JexlEngine messages will be logged.
- */
- protected final Log logger;
- /**
- * The atomic parsing flag; true whilst parsing.
- */
- protected final AtomicBoolean parsing = new AtomicBoolean(false);
- /**
- * The {@link Parser}; when parsing expressions, this engine uses the parser if it
- * is not already in use otherwise it will create a new temporary one.
+ * The map of 'prefix:function' to object implementing the namespaces.
*/
- protected final Parser parser = new Parser(new StringReader(";")); //$NON-NLS-1$
+ protected final Map<String, Object> functions;
/**
* Whether this engine considers unknown variables, methods and constructors as errors.
*/
@@ -113,21 +109,34 @@ public class Engine extends JexlEngine {
*/
protected final boolean debug;
/**
- * The map of 'prefix:function' to object implementing the namespaces.
+ * The atomic parsing flag; true whilst parsing.
*/
- protected final Map<String, Object> functions;
+ protected final AtomicBoolean parsing = new AtomicBoolean(false);
/**
- * The expression cache.
+ * The default charset.
+ */
+ protected final Charset charset;
+ /**
+ * The set of default script parsing features.
*/
- protected final SoftCache<String, ASTJexlScript> cache;
+ protected final JexlFeatures scriptFeatures;
+ /**
+ * The set of default expression parsing features.
+ */
+ protected final JexlFeatures expressionFeatures;
+ /**
+ * The {@link Parser}; when parsing expressions, this engine uses the parser if it
+ * is not already in use otherwise it will create a new temporary one.
+ */
+ protected final Parser parser = new Parser(new StringReader(";")); //$NON-NLS-1$
/**
* The expression max length to hit the cache.
*/
protected final int cacheThreshold;
/**
- * The default charset.
+ * The expression cache.
*/
- protected final Charset charset;
+ protected final SoftCache<Source, ASTJexlScript> cache;
/**
* The default jxlt engine.
*/
@@ -145,28 +154,34 @@ public class Engine extends JexlEngine {
* @param conf the builder
*/
public Engine(JexlBuilder conf) {
- JexlSandbox sandbox = conf.sandbox();
+ // options:
+ this.strict = conf.strict() == null ? true : conf.strict();
+ this.silent = conf.silent() == null ? false : conf.silent();
+ this.cancellable = conf.cancellable() == null ? !silent && strict : conf.cancellable();
+ this.debug = conf.debug() == null ? true : conf.debug();
+ // core properties:
JexlUberspect uber = conf.uberspect() == null ? getUberspect(conf.logger(), conf.strategy()) : conf.uberspect();
ClassLoader loader = conf.loader();
if (loader != null) {
uber.setClassLoader(loader);
}
+ JexlSandbox sandbox = conf.sandbox();
if (sandbox == null) {
this.uberspect = uber;
} else {
this.uberspect = new SandboxUberspect(uber, sandbox);
}
- parser.setFeatures(conf.features() == null? JexlEngine.DEFAULT_FEATURES : conf.features());
this.logger = conf.logger() == null ? LogFactory.getLog(JexlEngine.class) : conf.logger();
- this.functions = conf.namespaces() == null ? Collections.<String, Object>emptyMap() : conf.namespaces();
- this.strict = conf.strict() == null ? true : conf.strict();
- this.silent = conf.silent() == null ? false : conf.silent();
- this.cancellable = conf.cancellable() == null ? !silent && strict : conf.cancellable();
- this.debug = conf.debug() == null ? true : conf.debug();
this.arithmetic = conf.arithmetic() == null ? new JexlArithmetic(this.strict) : conf.arithmetic();
- this.cache = conf.cache() <= 0 ? null : new SoftCache<String, ASTJexlScript>(conf.cache());
- this.cacheThreshold = conf.cacheThreshold();
+ this.functions = conf.namespaces() == null ? Collections.<String, Object>emptyMap() : conf.namespaces();
+ // parsing & features:
+ JexlFeatures features = conf.features() == null? DEFAULT_FEATURES : conf.features();
+ this.expressionFeatures = new JexlFeatures(features).script(false);
+ this.scriptFeatures = new JexlFeatures(features).script(true);
this.charset = conf.charset();
+ // caching:
+ this.cache = conf.cache() <= 0 ? null : new SoftCache<Source, ASTJexlScript>(conf.cache());
+ this.cacheThreshold = conf.cacheThreshold();
if (uberspect == null) {
throw new IllegalArgumentException("uberspect can not be null");
}
@@ -252,26 +267,34 @@ public class Engine extends JexlEngine {
return new Interpreter(this, context, frame);
}
+
@Override
- public Script createScript(JexlInfo info, String scriptText, String[] names) {
+ public Script createExpression(JexlInfo info, String expression) {
+ return createScript(expressionFeatures, info, expression, null);
+ }
+
+ @Override
+ public Script createScript(JexlFeatures features, JexlInfo info, String scriptText, String[] names) {
if (scriptText == null) {
throw new NullPointerException("source is null");
}
String source = trimSource(scriptText);
Scope scope = names == null ? null : new Scope(null, names);
- ASTJexlScript tree = parse(info, source, scope, false, false);
+ ASTJexlScript tree = parse(info, features == null? scriptFeatures : features, source, scope);
return new Script(this, source, tree);
}
- @Override
- public Script createExpression(JexlInfo info, String expression) {
- if (expression == null) {
- throw new NullPointerException("source is null");
- }
- String source = trimSource(expression);
- ASTJexlScript tree = parse(info, source, null, false, true);
- return new Script(this, source, tree);
- }
+ /**
+ * The features allowed for property set/get methods.
+ */
+ protected static final JexlFeatures PROPERTY_FEATURES = new JexlFeatures()
+ .localVar(false)
+ .loops(false)
+ .lambda(false)
+ .script(false)
+ .arrayReferenceExpr(false)
+ .methodCall(false)
+ .register(true);
@Override
public Object getProperty(Object bean, String expr) {
@@ -288,7 +311,7 @@ public class Engine extends JexlEngine {
src = "#0" + (src.charAt(0) == '[' ? "" : ".") + src;
try {
final Scope scope = new Scope(null, "#0");
- final ASTJexlScript script = parse(null, src, scope, true, true);
+ final ASTJexlScript script = parse(null, PROPERTY_FEATURES, src, scope);
final JexlNode node = script.jjtGetChild(0);
final Scope.Frame frame = script.createFrame(bean);
final Interpreter interpreter = createInterpreter(context, frame);
@@ -312,12 +335,12 @@ public class Engine extends JexlEngine {
if (context == null) {
context = EMPTY_CONTEXT;
}
- // synthetize expr using registers
+ // synthetize expr using register
String src = trimSource(expr);
src = "#0" + (src.charAt(0) == '[' ? "" : ".") + src + "=" + "#1";
try {
final Scope scope = new Scope(null, "#0", "#1");
- final ASTJexlScript script = parse(null, src, scope, true, true);
+ final ASTJexlScript script = parse(null, PROPERTY_FEATURES, src, scope);
final JexlNode node = script.jjtGetChild(0);
final Scope.Frame frame = script.createFrame(bean, value);
final Interpreter interpreter = createInterpreter(context, frame);
@@ -579,18 +602,33 @@ public class Engine extends JexlEngine {
* Parses an expression.
*
* @param info information structure
+ * @param expr whether we parse an expression or a feature
+ * @param src the expression to parse
+ * @param scope the script frame
+ * @return the parsed tree
+ * @throws JexlException if any error occurred during parsing
+ */
+ protected ASTJexlScript parse(JexlInfo info, boolean expr, String src, Scope scope) {
+ return parse(info, expr? this.expressionFeatures : this.scriptFeatures, src, scope);
+ }
+
+ /**
+ * Parses an expression.
+ *
+ * @param info information structure
+ * @param parsingf the set of parsing features
* @param src the expression to parse
* @param scope the script frame
- * @param registers whether the parser should allow the unnamed '#number' syntax for 'registers'
- * @param expression whether the parser allows scripts or only expressions
* @return the parsed tree
* @throws JexlException if any error occurred during parsing
*/
- protected ASTJexlScript parse(JexlInfo info, String src, Scope scope, boolean registers, boolean expression) {
+ protected ASTJexlScript parse(JexlInfo info, JexlFeatures parsingf, String src, Scope scope) {
final boolean cached = src.length() < cacheThreshold && cache != null;
+ final JexlFeatures features = parsingf != null? parsingf : DEFAULT_FEATURES;
+ final Source source = cached? new Source(features, src) : null;
ASTJexlScript script = null;
- if (cached) {
- script = cache.get(src);
+ if (source != null) {
+ script = cache.get(source);
if (script != null) {
Scope f = script.getScope();
if ((f == null && scope == null) || (f != null && f.equals(scope))) {
@@ -603,7 +641,7 @@ public class Engine extends JexlEngine {
if (parsing.compareAndSet(false, true)) {
try {
// lets parse
- script = parser.parse(ninfo, src, scope, registers, expression);
+ script = parser.parse(ninfo, features, src, scope);
} finally {
// no longer in use
parsing.set(false);
@@ -611,10 +649,10 @@ public class Engine extends JexlEngine {
} else {
// ...otherwise parser was in use, create a new temporary one
Parser lparser = new Parser(new StringReader(";"));
- script = lparser.parse(ninfo, src, scope, registers, expression);
+ script = lparser.parse(ninfo, features, src, scope);
}
- if (cached) {
- cache.put(src, script);
+ if (source != null) {
+ cache.put(source, script);
}
return script;
}
Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java?rev=1816640&r1=1816639&r2=1816640&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java Wed Nov 29 16:27:04 2017
@@ -566,22 +566,23 @@ public class Interpreter extends Interpr
@Override
protected Object visit(ASTIfStatement node, Object data) {
int n = 0;
+ final int numChildren = node.jjtGetNumChildren();
try {
Object result = null;
- // first objectNode is the condition
- Object expression = node.jjtGetChild(0).jjtAccept(this, null);
- if (arithmetic.toBoolean(expression)) {
- // first objectNode is true statement
- n = 1;
- result = node.jjtGetChild(n).jjtAccept(this, null);
- } else {
- // if there is a false, execute it. false statement is the second
- // objectNode
- if (node.jjtGetNumChildren() == 3) {
- n = 2;
- result = node.jjtGetChild(n).jjtAccept(this, null);
+ // pairs of { conditions , 'then' statement }
+ for(int ifElse = 0; ifElse < (numChildren - 1); ifElse += 2) {
+ Object condition = node.jjtGetChild(ifElse).jjtAccept(this, null);
+ if (arithmetic.toBoolean(condition)) {
+ // first objectNode is true statement
+ return node.jjtGetChild(ifElse + 1).jjtAccept(this, null);
}
}
+ //
+ if (numChildren % 2 == 1) {
+ // if there is an else, there are an odd number of childrenin the statement and it is the last child,
+ // execute it.
+ result = node.jjtGetChild(numChildren - 1).jjtAccept(this, null);
+ }
return result;
} catch (ArithmeticException xrt) {
throw new JexlException(node.jjtGetChild(n), "if error", xrt);
Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Script.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Script.java?rev=1816640&r1=1816639&r2=1816640&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Script.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Script.java Wed Nov 29 16:27:04 2017
@@ -50,6 +50,13 @@ public class Script implements JexlScrip
protected int version;
/**
+ * @return the script AST
+ */
+ protected ASTJexlScript getScript() {
+ return script;
+ }
+
+ /**
* Do not let this be generally instantiated with a 'new'.
*
* @param engine the interpreter to evaluate the expression
Added: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/ScriptVisitor.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/ScriptVisitor.java?rev=1816640&view=auto
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/ScriptVisitor.java (added)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/ScriptVisitor.java Wed Nov 29 16:27:04 2017
@@ -0,0 +1,496 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.jexl3.internal;
+
+import org.apache.commons.jexl3.JexlExpression;
+import org.apache.commons.jexl3.JexlScript;
+import org.apache.commons.jexl3.parser.ASTAddNode;
+import org.apache.commons.jexl3.parser.ASTAndNode;
+import org.apache.commons.jexl3.parser.ASTAnnotatedStatement;
+import org.apache.commons.jexl3.parser.ASTAnnotation;
+import org.apache.commons.jexl3.parser.ASTArguments;
+import org.apache.commons.jexl3.parser.ASTArrayAccess;
+import org.apache.commons.jexl3.parser.ASTArrayLiteral;
+import org.apache.commons.jexl3.parser.ASTAssignment;
+import org.apache.commons.jexl3.parser.ASTBitwiseAndNode;
+import org.apache.commons.jexl3.parser.ASTBitwiseComplNode;
+import org.apache.commons.jexl3.parser.ASTBitwiseOrNode;
+import org.apache.commons.jexl3.parser.ASTBitwiseXorNode;
+import org.apache.commons.jexl3.parser.ASTBlock;
+import org.apache.commons.jexl3.parser.ASTBreak;
+import org.apache.commons.jexl3.parser.ASTConstructorNode;
+import org.apache.commons.jexl3.parser.ASTContinue;
+import org.apache.commons.jexl3.parser.ASTDivNode;
+import org.apache.commons.jexl3.parser.ASTEQNode;
+import org.apache.commons.jexl3.parser.ASTERNode;
+import org.apache.commons.jexl3.parser.ASTEWNode;
+import org.apache.commons.jexl3.parser.ASTEmptyFunction;
+import org.apache.commons.jexl3.parser.ASTEmptyMethod;
+import org.apache.commons.jexl3.parser.ASTExtendedLiteral;
+import org.apache.commons.jexl3.parser.ASTFalseNode;
+import org.apache.commons.jexl3.parser.ASTForeachStatement;
+import org.apache.commons.jexl3.parser.ASTFunctionNode;
+import org.apache.commons.jexl3.parser.ASTGENode;
+import org.apache.commons.jexl3.parser.ASTGTNode;
+import org.apache.commons.jexl3.parser.ASTIdentifier;
+import org.apache.commons.jexl3.parser.ASTIdentifierAccess;
+import org.apache.commons.jexl3.parser.ASTIfStatement;
+import org.apache.commons.jexl3.parser.ASTJexlScript;
+import org.apache.commons.jexl3.parser.ASTJxltLiteral;
+import org.apache.commons.jexl3.parser.ASTLENode;
+import org.apache.commons.jexl3.parser.ASTLTNode;
+import org.apache.commons.jexl3.parser.ASTMapEntry;
+import org.apache.commons.jexl3.parser.ASTMapLiteral;
+import org.apache.commons.jexl3.parser.ASTMethodNode;
+import org.apache.commons.jexl3.parser.ASTModNode;
+import org.apache.commons.jexl3.parser.ASTMulNode;
+import org.apache.commons.jexl3.parser.ASTNENode;
+import org.apache.commons.jexl3.parser.ASTNEWNode;
+import org.apache.commons.jexl3.parser.ASTNRNode;
+import org.apache.commons.jexl3.parser.ASTNSWNode;
+import org.apache.commons.jexl3.parser.ASTNotNode;
+import org.apache.commons.jexl3.parser.ASTNullLiteral;
+import org.apache.commons.jexl3.parser.ASTNullpNode;
+import org.apache.commons.jexl3.parser.ASTNumberLiteral;
+import org.apache.commons.jexl3.parser.ASTOrNode;
+import org.apache.commons.jexl3.parser.ASTRangeNode;
+import org.apache.commons.jexl3.parser.ASTReference;
+import org.apache.commons.jexl3.parser.ASTReferenceExpression;
+import org.apache.commons.jexl3.parser.ASTReturnStatement;
+import org.apache.commons.jexl3.parser.ASTSWNode;
+import org.apache.commons.jexl3.parser.ASTSetAddNode;
+import org.apache.commons.jexl3.parser.ASTSetAndNode;
+import org.apache.commons.jexl3.parser.ASTSetDivNode;
+import org.apache.commons.jexl3.parser.ASTSetLiteral;
+import org.apache.commons.jexl3.parser.ASTSetModNode;
+import org.apache.commons.jexl3.parser.ASTSetMultNode;
+import org.apache.commons.jexl3.parser.ASTSetOrNode;
+import org.apache.commons.jexl3.parser.ASTSetSubNode;
+import org.apache.commons.jexl3.parser.ASTSetXorNode;
+import org.apache.commons.jexl3.parser.ASTSizeFunction;
+import org.apache.commons.jexl3.parser.ASTSizeMethod;
+import org.apache.commons.jexl3.parser.ASTStringLiteral;
+import org.apache.commons.jexl3.parser.ASTSubNode;
+import org.apache.commons.jexl3.parser.ASTTernaryNode;
+import org.apache.commons.jexl3.parser.ASTTrueNode;
+import org.apache.commons.jexl3.parser.ASTUnaryMinusNode;
+import org.apache.commons.jexl3.parser.ASTVar;
+import org.apache.commons.jexl3.parser.ASTWhileStatement;
+import org.apache.commons.jexl3.parser.JexlNode;
+import org.apache.commons.jexl3.parser.ParserVisitor;
+
+/**
+ * Fully abstract to avoid public interface exposition.
+ */
+public class ScriptVisitor extends ParserVisitor {
+ /**
+ * Visits all AST constituents of a JEXL expression.
+ * @param jscript the expression
+ * @param data some data context
+ * @return the visit result or null if jscript was not a Script implementation
+ */
+ public Object visitExpression (JexlExpression jscript, Object data) {
+ if (jscript instanceof Script) {
+ return ((Script) jscript).getScript().jjtAccept(this, data);
+ }
+ return null;
+ }
+
+ /**
+ * Visits all AST constituents of a JEXL script.
+ * @param jscript the expression
+ * @param data some data context
+ * @return the visit result or null if jscript was not a Script implementation
+ */
+ public Object visitScript(JexlScript jscript, Object data) {
+ if (jscript instanceof Script) {
+ return ((Script) jscript).getScript().jjtAccept(this, data);
+ }
+ return null;
+ }
+
+ /**
+ * Visits a node.
+ * Default implementation visits all its children.
+ * @param node the node to visit
+ * @param data visitor pattern argument
+ * @return visitor pattern value
+ */
+ protected Object visitNode(JexlNode node, Object data) {
+ return node.childrenAccept(this, data);
+ }
+
+ @Override
+ protected Object visit(ASTJexlScript node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTBlock node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTIfStatement node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTWhileStatement node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTContinue node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTBreak node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTForeachStatement node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTReturnStatement node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTAssignment node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTVar node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTReference node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTTernaryNode node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTNullpNode node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTOrNode node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTAndNode node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTBitwiseOrNode node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTBitwiseXorNode node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTBitwiseAndNode node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTEQNode node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTNENode node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTLTNode node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTGTNode node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTLENode node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTGENode node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTERNode node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTNRNode node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTSWNode node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTNSWNode node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTEWNode node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTNEWNode node, Object data) {
+
+ return visitNode(node, data); }
+
+ @Override
+ protected Object visit(ASTAddNode node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTSubNode node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTMulNode node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTDivNode node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTModNode node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTUnaryMinusNode node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTBitwiseComplNode node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTNotNode node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTIdentifier node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTNullLiteral node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTTrueNode node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTFalseNode node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTNumberLiteral node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTStringLiteral node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTSetLiteral node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTExtendedLiteral node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTArrayLiteral node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTRangeNode node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTMapLiteral node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTMapEntry node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTEmptyFunction node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTEmptyMethod node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTSizeFunction node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTFunctionNode node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTMethodNode node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTSizeMethod node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTConstructorNode node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTArrayAccess node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTIdentifierAccess node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTArguments node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTReferenceExpression node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTSetAddNode node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTSetSubNode node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTSetMultNode node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTSetDivNode node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTSetModNode node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTSetAndNode node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTSetOrNode node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTSetXorNode node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTJxltLiteral node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTAnnotation node, Object data) {
+ return visitNode(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTAnnotatedStatement node, Object data) {
+ return visitNode(node, data);
+ }
+}
Propchange: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/ScriptVisitor.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Source.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Source.java?rev=1816640&view=auto
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Source.java (added)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Source.java Wed Nov 29 16:27:04 2017
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.jexl3.internal;
+
+import org.apache.commons.jexl3.JexlFeatures;
+
+/**
+ * Maintains the set of allowed features associated with a script/expression source.
+ * <p>This is meant for caching scripts using their 'source' as key but still distinguishing
+ * scripts with different features and prevent false sharing.
+ */
+public final class Source {
+ /** The hash code, pre-computed for fast op. */
+ private final int hashCode;
+ /** The set of features. */
+ private final JexlFeatures features;
+ /** The actual source script/expression. */
+ private final String str;
+
+ /**
+ * Default constructor.
+ * @param theFeatures the features
+ * @param theStr the script source
+ */
+ Source(JexlFeatures theFeatures, String theStr) { // CSOFF: MagicNumber
+ this.features = theFeatures;
+ this.str = theStr;
+ int hash = 3;
+ hash = 37 * hash + features.hashCode();
+ hash = 37 * hash + str.hashCode() ;
+ this.hashCode = hash;
+ }
+
+ /**
+ * @return the length of the script source
+ */
+ int length() {
+ return str.length();
+ }
+
+ @Override
+ public int hashCode() {
+ return hashCode;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final Source other = (Source) obj;
+ if (this.features != other.features
+ && (this.features == null || !this.features.equals(other.features))) {
+ return false;
+ }
+ if ((this.str == null) ? (other.str != null) : !this.str.equals(other.str)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return str;
+ }
+
+ /**
+ * @return the features associated with the source
+ */
+ public JexlFeatures getFeatures() {
+ return features;
+ }
+
+}
Propchange: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Source.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/TemplateEngine.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/TemplateEngine.java?rev=1816640&r1=1816639&r2=1816640&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/TemplateEngine.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/TemplateEngine.java Wed Nov 29 16:27:04 2017
@@ -540,7 +540,7 @@ public final class TemplateEngine extend
@Override
protected TemplateExpression prepare(Interpreter interpreter) {
String value = interpreter.interpret(node).toString();
- JexlNode dnode = jexl.parse(node.jexlInfo(), value, null, false, noscript);
+ JexlNode dnode = jexl.parse(node.jexlInfo(), noscript, value, null);
return new ImmediateExpression(value, dnode, this);
}
@@ -800,7 +800,7 @@ public final class TemplateEngine extend
String src = strb.toString();
TemplateExpression iexpr = new ImmediateExpression(
src,
- jexl.parse(info.at(lineno, column), src, scope, false, noscript),
+ jexl.parse(info.at(lineno, column), noscript, src, scope),
null);
builder.add(iexpr);
strb.delete(0, Integer.MAX_VALUE);
@@ -848,12 +848,12 @@ public final class TemplateEngine extend
if (nested) {
dexpr = new NestedExpression(
expr.substring(inested, column + 1),
- jexl.parse(info.at(lineno, column), src, scope, false, noscript),
+ jexl.parse(info.at(lineno, column), noscript, src, scope),
null);
} else {
dexpr = new DeferredExpression(
strb.toString(),
- jexl.parse(info.at(lineno, column), src, scope, false, noscript),
+ jexl.parse(info.at(lineno, column), noscript, src, scope),
null);
}
builder.add(dexpr);
Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/TemplateScript.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/TemplateScript.java?rev=1816640&r1=1816639&r2=1816640&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/TemplateScript.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/TemplateScript.java Wed Nov 29 16:27:04 2017
@@ -96,7 +96,7 @@ public final class TemplateScript implem
info = jxlt.getEngine().createInfo();
}
// allow lambda defining params
- script = jxlt.getEngine().parse(info.at(0, 0), strb.toString(), scope, false, false).script();
+ script = jxlt.getEngine().parse(info.at(0, 0), false, strb.toString(), scope).script();
scope = script.getScope();
// create the exprs using the code frame for those appearing after the first block of code
for (int b = 0; b < blocks.size(); ++b) {
Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ASTJexlScript.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ASTJexlScript.java?rev=1816640&r1=1816639&r2=1816640&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ASTJexlScript.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ASTJexlScript.java Wed Nov 29 16:27:04 2017
@@ -16,6 +16,7 @@
*/
package org.apache.commons.jexl3.parser;
+import org.apache.commons.jexl3.JexlFeatures;
import org.apache.commons.jexl3.internal.Scope;
import java.util.Map;
@@ -26,7 +27,9 @@ public class ASTJexlScript extends JexlN
/** The script scope. */
private Scope scope = null;
/** The pragmas. */
- Map<String, Object> pragmas = null;
+ private Map<String, Object> pragmas = null;
+ /** Features. */
+ private JexlFeatures features = null;
public ASTJexlScript(int id) {
super(id);
@@ -54,18 +57,34 @@ public class ASTJexlScript extends JexlN
public Object jjtAccept(ParserVisitor visitor, Object data) {
return visitor.visit(this, data);
}
+ /**
+ * Sets this script pragmas.
+ * @param pragmas the pragmas
+ */
+ public void setPragmas(Map<String, Object> thePragmas) {
+ this.pragmas = thePragmas;
+ }
/**
- * Coerce this script as an expression (ie only one child) if necessary.
- * @return true if the script was coerced, false otherwise
+ * @return this script pragmas.
*/
- public boolean toExpression() {
- if (jjtGetNumChildren() > 1) {
- jjtSetChildren(new JexlNode[]{jjtGetChild(0)});
- return true;
- } else {
- return false;
- }
+ public Map<String, Object> getPragmas() {
+ return pragmas;
+ }
+
+ /**
+ * Sets this script features.
+ * @param theFeatures the features
+ */
+ public void setFeatures(JexlFeatures theFeatures) {
+ this.features = theFeatures;
+ }
+
+ /**
+ * @return this script scope
+ */
+ public JexlFeatures getFeatures() {
+ return features;
}
/**
@@ -84,13 +103,6 @@ public class ASTJexlScript extends JexlN
}
/**
- * @return this script pragmas
- */
- public Map<String,Object> getPragmas() {
- return pragmas;
- }
-
- /**
* Creates an array of arguments by copying values up to the number of parameters.
* @param values the argument values
* @return the arguments array
Added: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/FeatureController.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/FeatureController.java?rev=1816640&view=auto
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/FeatureController.java (added)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/FeatureController.java Wed Nov 29 16:27:04 2017
@@ -0,0 +1,229 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.jexl3.parser;
+
+import org.apache.commons.jexl3.JexlException;
+import org.apache.commons.jexl3.JexlFeatures;
+import org.apache.commons.jexl3.JexlInfo;
+import org.apache.commons.jexl3.internal.ScriptVisitor;
+/**
+ * Controls that a script only uses enabled features.
+ */
+public class FeatureController extends ScriptVisitor {
+ /** The set of features. */
+ private JexlFeatures features = null;
+
+ /**
+ * Creates a features controller .
+ */
+ public FeatureController(JexlFeatures features) {
+ this.features = features;
+ }
+
+ /**
+ * Sets the features to controlNode.
+ * @param fdesc the features
+ */
+ public void setFeatures(JexlFeatures fdesc) {
+ this.features = fdesc;
+ }
+
+ /**
+ * @return the controlled features
+ */
+ public JexlFeatures getFeatures() {
+ return features;
+ }
+
+ /**
+ * Perform the control on a node.
+ * <p>Note that controlNode() does *not* visit node children in this class.
+ * @param node the node to controlNode
+ * @throws JexlException.Feature if required feature is disabled
+ */
+ public void controlNode(JexlNode node) {
+ node.jjtAccept(this, null);
+ }
+
+ @Override
+ protected Object visitNode(JexlNode node, Object data) {
+ // no need to visit them since we close them one by one
+ return data;
+ }
+
+ /**
+ * Throws a feature exception.
+ * @param feature the feature code
+ * @param node the node that caused it
+ */
+ public void throwFeatureException(int feature, JexlNode node) {
+ JexlInfo dbgInfo = node.jexlInfo();
+ throw new JexlException.Feature(dbgInfo, feature, "");
+ }
+
+ /**
+ * Checks whether a node is a string or an integer.
+ * @param child the child node
+ * @return true if string / integer, false otherwise
+ */
+ private boolean isArrayReferenceLiteral(JexlNode child) {
+ if (child instanceof ASTStringLiteral) {
+ return true;
+ }
+ if (child instanceof ASTNumberLiteral && ((ASTNumberLiteral) child).isInteger()) {
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ protected Object visit(ASTArrayAccess node, Object data) {
+ if (!features.supportsArrayReferenceExpr()) {
+ for (int i = 0; i < node.jjtGetNumChildren(); ++i) {
+ JexlNode child = node.jjtGetChild(i);
+ if (!isArrayReferenceLiteral(child)) {
+ throwFeatureException(JexlFeatures.ARRAY_REF_EXPR, child);
+ }
+ }
+ }
+ return data;
+ }
+
+ @Override
+ protected Object visit(ASTWhileStatement node, Object data) {
+ if (!features.supportsLoops()) {
+ throwFeatureException(JexlFeatures.LOOP, node);
+ }
+ return data;
+ }
+
+ @Override
+ protected Object visit(ASTForeachStatement node, Object data) {
+ if (!features.supportsLoops()) {
+ throwFeatureException(JexlFeatures.LOOP, node);
+ }
+ return data;
+ }
+
+ @Override
+ protected Object visit(ASTConstructorNode node, Object data) {
+ if (!features.supportsNewInstance()) {
+ throwFeatureException(JexlFeatures.NEW_INSTANCE, node);
+ }
+ return data;
+ }
+
+ @Override
+ protected Object visit(ASTMethodNode node, Object data) {
+ if (!features.supportsMethodCall()) {
+ throwFeatureException(JexlFeatures.METHOD_CALL, node);
+ }
+ return data;
+ }
+
+ @Override
+ protected Object visit(ASTAnnotation node, Object data) {
+ if (!features.supportsAnnotation()) {
+ throwFeatureException(JexlFeatures.ANNOTATION, node);
+ }
+ return data;
+ }
+
+ @Override
+ protected Object visit(ASTArrayLiteral node, Object data) {
+ if (!features.supportsStructuredLiteral()) {
+ throwFeatureException(JexlFeatures.STRUCTURED_LITERAL, node);
+ }
+ return data;
+ }
+
+ @Override
+ protected Object visit(ASTMapLiteral node, Object data) {
+ if (!features.supportsStructuredLiteral()) {
+ throwFeatureException(JexlFeatures.STRUCTURED_LITERAL, node);
+ }
+ return data;
+ }
+
+ @Override
+ protected Object visit(ASTSetLiteral node, Object data) {
+ if (!features.supportsStructuredLiteral()) {
+ throwFeatureException(JexlFeatures.STRUCTURED_LITERAL, node);
+ }
+ return data;
+ }
+
+ @Override
+ protected Object visit(ASTRangeNode node, Object data) {
+ if (!features.supportsStructuredLiteral()) {
+ throwFeatureException(JexlFeatures.STRUCTURED_LITERAL, node);
+ }
+ return data;
+ }
+
+ private Object controlSideEffect(JexlNode node, Object data) {
+ JexlNode lv = node.jjtGetChild(0);
+ if (!features.supportsSideEffectGlobal() && lv.isGlobalVar()) {
+ throwFeatureException(JexlFeatures.SIDE_EFFECT_GLOBAL, lv);
+ }
+ if (!features.supportsSideEffect()) {
+ throwFeatureException(JexlFeatures.SIDE_EFFECT, lv);
+ }
+ return data;
+ }
+
+ @Override
+ protected Object visit(ASTAssignment node, Object data) {
+ return controlSideEffect(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTSetAddNode node, Object data) {
+ return controlSideEffect(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTSetMultNode node, Object data) {
+ return controlSideEffect(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTSetDivNode node, Object data) {
+ return controlSideEffect(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTSetAndNode node, Object data) {
+ return controlSideEffect(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTSetOrNode node, Object data) {
+ return controlSideEffect(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTSetXorNode node, Object data) {
+ return controlSideEffect(node, data);
+ }
+
+ @Override
+ protected Object visit(ASTSetSubNode node, Object data) {
+ return controlSideEffect(node, data);
+ }
+
+}
Propchange: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/FeatureController.java
------------------------------------------------------------------------------
svn:eol-style = native