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 73bb932 JEXL-359: refactored OperatorController, tidy code linked to
strictness, clean-up test;
73bb932 is described below
commit 73bb932e6cf856d4516ec543a3335925cd4d88aa
Author: henrib <[email protected]>
AuthorDate: Mon Feb 14 18:58:46 2022 +0100
JEXL-359: refactored OperatorController, tidy code linked to strictness,
clean-up test;
---
RELEASE-NOTES.txt | 1 +
.../org/apache/commons/jexl3/JexlArithmetic.java | 18 ++-
.../apache/commons/jexl3/internal/Interpreter.java | 40 +++---
.../commons/jexl3/internal/InterpreterBase.java | 24 ++--
.../jexl3/internal/introspection/ClassMap.java | 2 +-
.../jexl3/internal/introspection/Permissions.java | 26 ++--
.../org/apache/commons/jexl3/parser/JexlNode.java | 16 +--
.../commons/jexl3/parser/OperatorController.java | 146 +++++++++++----------
.../org/apache/commons/jexl3/ArithmeticTest.java | 13 ++
.../org/apache/commons/jexl3/SideEffectTest.java | 1 -
10 files changed, 155 insertions(+), 132 deletions(-)
diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt
index be26679..631cd31 100644
--- a/RELEASE-NOTES.txt
+++ b/RELEASE-NOTES.txt
@@ -38,6 +38,7 @@ allow fine-tuning the scripting integration into any project.
New Features in 3.3:
====================
+* JEXL-359: Allow per-operator arithmetic handling of null arguments
* JEXL-357: Configure accessible packages/classes/methods/fields
Bugs Fixed in 3.3:
diff --git a/src/main/java/org/apache/commons/jexl3/JexlArithmetic.java
b/src/main/java/org/apache/commons/jexl3/JexlArithmetic.java
index 4a8e364..9c3033a 100644
--- a/src/main/java/org/apache/commons/jexl3/JexlArithmetic.java
+++ b/src/main/java/org/apache/commons/jexl3/JexlArithmetic.java
@@ -373,6 +373,22 @@ public class JexlArithmetic {
}
/**
+ * Checks whether this arithmetic considers a given operator as strict or
null-safe.
+ * <p>When an operator is strict, it does <em>not</em> accept null
arguments when the arithmetic is strict.
+ * If null-safe (ie not-strict), the operator does accept null arguments
even if the arithmetic itself is strict.</p>
+ * <p>The default implementation considers equal/not-equal operators as
null-safe so one can check for null as in
+ * <code>if (myvar == null) {...}</code>. Note that this operator is used
for equal and not-equal syntax.</p>
+ * <p>An arithmetic refining its strict behavior handling for more
operators must declare which by overriding
+ * this method.</p>
+ * @param operator the operator to check for null-argument(s) handling
+ * @return true if operator considers null arguments as errors, false if
operator has appropriate semantics
+ * for null argument(s)
+ */
+ public boolean isStrict(JexlOperator operator) {
+ return operator == JexlOperator.EQ? false : isStrict();
+ }
+
+ /**
* The MathContext instance used for +,-,/,*,% operations on big decimals.
*
* @return the math context
@@ -746,7 +762,7 @@ public class JexlArithmetic {
}
}
}
- return toString(left).concat(toString(right));
+ return (left == null? "" : toString(left)).concat(right == null ? "" :
toString(right));
}
/**
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 fbd47a4..3590d9c 100644
--- a/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java
+++ b/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java
@@ -264,7 +264,7 @@ public class Interpreter extends InterpreterBase {
final Object result = operators.tryOverload(node,
JexlOperator.ADD, left, right);
return result != JexlEngine.TRY_FAILED ? result :
arithmetic.add(left, right);
} catch (final ArithmeticException xrt) {
- throw new JexlException(node, "+ error", xrt);
+ throw new JexlException(findNullOperand(node, left, right), "+
error", xrt);
}
}
@@ -276,7 +276,7 @@ public class Interpreter extends InterpreterBase {
final Object result = operators.tryOverload(node,
JexlOperator.SUBTRACT, left, right);
return result != JexlEngine.TRY_FAILED ? result :
arithmetic.subtract(left, right);
} catch (final ArithmeticException xrt) {
- throw new JexlException(node, "- error", xrt);
+ throw new JexlException(findNullOperand(node, left, right), "-
error", xrt);
}
}
@@ -288,8 +288,7 @@ public class Interpreter extends InterpreterBase {
final Object result = operators.tryOverload(node,
JexlOperator.MULTIPLY, left, right);
return result != JexlEngine.TRY_FAILED ? result :
arithmetic.multiply(left, right);
} catch (final ArithmeticException xrt) {
- final JexlNode xnode = findNullOperand(xrt, node, left, right);
- throw new JexlException(xnode, "* error", xrt);
+ throw new JexlException(findNullOperand(node, left, right), "*
error", xrt);
}
}
@@ -304,8 +303,7 @@ public class Interpreter extends InterpreterBase {
if (!arithmetic.isStrict()) {
return 0.0d;
}
- final JexlNode xnode = findNullOperand(xrt, node, left, right);
- throw new JexlException(xnode, "/ error", xrt);
+ throw new JexlException(findNullOperand(node, left, right), "/
error", xrt);
}
}
@@ -320,8 +318,7 @@ public class Interpreter extends InterpreterBase {
if (!arithmetic.isStrict()) {
return 0.0d;
}
- final JexlNode xnode = findNullOperand(xrt, node, left, right);
- throw new JexlException(xnode, "% error", xrt);
+ throw new JexlException(findNullOperand(node, left, right), "%
error", xrt);
}
}
@@ -333,7 +330,7 @@ public class Interpreter extends InterpreterBase {
final Object result = operators.tryOverload(node,
JexlOperator.AND, left, right);
return result != JexlEngine.TRY_FAILED ? result :
arithmetic.and(left, right);
} catch (final ArithmeticException xrt) {
- throw new JexlException(node, "& error", xrt);
+ throw new JexlException(findNullOperand(node, left, right), "&
error", xrt);
}
}
@@ -341,11 +338,14 @@ public class Interpreter extends InterpreterBase {
protected Object visit(final ASTBitwiseOrNode node, final Object data) {
final Object left = node.jjtGetChild(0).jjtAccept(this, data);
final Object right = node.jjtGetChild(1).jjtAccept(this, data);
+ if (arithmetic.isStrict(JexlOperator.OR) && left == null || right ==
null) {
+ // boum
+ }
try {
final Object result = operators.tryOverload(node, JexlOperator.OR,
left, right);
return result != JexlEngine.TRY_FAILED ? result :
arithmetic.or(left, right);
} catch (final ArithmeticException xrt) {
- throw new JexlException(node, "| error", xrt);
+ throw new JexlException(findNullOperand(node, left, right), "|
error", xrt);
}
}
@@ -357,7 +357,7 @@ public class Interpreter extends InterpreterBase {
final Object result = operators.tryOverload(node,
JexlOperator.XOR, left, right);
return result != JexlEngine.TRY_FAILED ? result :
arithmetic.xor(left, right);
} catch (final ArithmeticException xrt) {
- throw new JexlException(node, "^ error", xrt);
+ throw new JexlException(findNullOperand(node, left, right), "^
error", xrt);
}
}
@@ -369,7 +369,7 @@ public class Interpreter extends InterpreterBase {
final Object result = operators.tryOverload(node, JexlOperator.EQ,
left, right);
return result != JexlEngine.TRY_FAILED ? result :
arithmetic.equals(left, right);
} catch (final ArithmeticException xrt) {
- throw new JexlException(node, "== error", xrt);
+ throw new JexlException(findNullOperand(node, left, right), "==
error", xrt);
}
}
@@ -383,8 +383,7 @@ public class Interpreter extends InterpreterBase {
? !arithmetic.toBoolean(result)
: !arithmetic.equals(left, right);
} catch (final ArithmeticException xrt) {
- final JexlNode xnode = findNullOperand(xrt, node, left, right);
- throw new JexlException(xnode, "!= error", xrt);
+ throw new JexlException(findNullOperand(node, left, right), "!=
error", xrt);
}
}
@@ -398,7 +397,7 @@ public class Interpreter extends InterpreterBase {
? result
: arithmetic.greaterThanOrEqual(left, right);
} catch (final ArithmeticException xrt) {
- throw new JexlException(node, ">= error", xrt);
+ throw new JexlException(findNullOperand(node, left, right), ">=
error", xrt);
}
}
@@ -412,7 +411,7 @@ public class Interpreter extends InterpreterBase {
? result
: arithmetic.greaterThan(left, right);
} catch (final ArithmeticException xrt) {
- throw new JexlException(node, "> error", xrt);
+ throw new JexlException(findNullOperand(node, left, right), ">
error", xrt);
}
}
@@ -426,7 +425,7 @@ public class Interpreter extends InterpreterBase {
? result
: arithmetic.lessThanOrEqual(left, right);
} catch (final ArithmeticException xrt) {
- throw new JexlException(node, "<= error", xrt);
+ throw new JexlException(findNullOperand(node, left, right), "<=
error", xrt);
}
}
@@ -440,7 +439,7 @@ public class Interpreter extends InterpreterBase {
? result
: arithmetic.lessThan(left, right);
} catch (final ArithmeticException xrt) {
- throw new JexlException(node, "< error", xrt);
+ throw new JexlException(findNullOperand(node, left, right), "<
error", xrt);
}
}
@@ -493,8 +492,7 @@ public class Interpreter extends InterpreterBase {
try {
return arithmetic.createRange(left, right);
} catch (final ArithmeticException xrt) {
- final JexlNode xnode = findNullOperand(xrt, node, left, right);
- throw new JexlException(xnode, ".. error", xrt);
+ throw new JexlException(findNullOperand(node, left, right), "..
error", xrt);
}
}
@@ -1231,7 +1229,7 @@ public class Interpreter extends InterpreterBase {
final String aname = ant != null ? ant.toString() : "?";
final boolean defined = isVariableDefined(frame, block, aname);
// defined but null; arg of a strict operator?
- if (defined && (!arithmetic.isStrict() ||
!node.jjtGetParent().isStrictOperator())) {
+ if (defined &&
!node.jjtGetParent().isStrictOperator(arithmetic)) {
return null;
}
return unsolvableVariable(node, aname, !defined);
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 0e759f3..6b2d7dc 100644
--- a/src/main/java/org/apache/commons/jexl3/internal/InterpreterBase.java
+++ b/src/main/java/org/apache/commons/jexl3/internal/InterpreterBase.java
@@ -309,7 +309,7 @@ public abstract class InterpreterBase extends ParserVisitor
{
// not out of scope with no lexical shade ?
if (value != Scope.UNDEFINED) {
// null argument of an arithmetic operator ?
- if (value == null && arithmetic.isStrict() &&
identifier.jjtGetParent().isStrictOperator()) {
+ if (value == null &&
identifier.jjtGetParent().isStrictOperator(arithmetic)) {
return unsolvableVariable(identifier, name, false); //
defined but null
}
return value;
@@ -328,7 +328,7 @@ public abstract class InterpreterBase extends ParserVisitor
{
if (!ignore) {
return undefinedVariable(identifier, name); // undefined
}
- } else if (arithmetic.isStrict() &&
identifier.jjtGetParent().isStrictOperator()) {
+ } else if (identifier.jjtGetParent().isStrictOperator(arithmetic))
{
return unsolvableVariable(identifier, name, false); // defined
but null
}
}
@@ -385,22 +385,24 @@ public abstract class InterpreterBase extends
ParserVisitor {
return options.isCancellable();
}
+ @Deprecated
+ protected JexlNode findNullOperand(final RuntimeException xrt, final
JexlNode node, final Object left, final Object right) {
+ return findNullOperand(node, left, right);
+ }
+
/**
* Finds the node causing a NPE for diadic operators.
- * @param xrt the RuntimeException
* @param node the parent node
* @param left the left argument
* @param right the right argument
* @return the left, right or parent node
*/
- protected JexlNode findNullOperand(final RuntimeException xrt, final
JexlNode node, final Object left, final Object right) {
- if (xrt instanceof JexlArithmetic.NullOperand) {
- if (left == null) {
- return node.jjtGetChild(0);
- }
- if (right == null) {
- return node.jjtGetChild(1);
- }
+ protected JexlNode findNullOperand(final JexlNode node, final Object left,
final Object right) {
+ if (left == null) {
+ return node.jjtGetChild(0);
+ }
+ if (right == null) {
+ return node.jjtGetChild(1);
}
return node;
}
diff --git
a/src/main/java/org/apache/commons/jexl3/internal/introspection/ClassMap.java
b/src/main/java/org/apache/commons/jexl3/internal/introspection/ClassMap.java
index 770342b..7e36ce9 100644
---
a/src/main/java/org/apache/commons/jexl3/internal/introspection/ClassMap.java
+++
b/src/main/java/org/apache/commons/jexl3/internal/introspection/ClassMap.java
@@ -62,7 +62,7 @@ final class ClassMap {
/**
* The cache miss marker method.
*/
- private static final Method CACHE_MISS = cacheMiss();
+ static final Method CACHE_MISS = cacheMiss();
/**
* This is the cache to store and look up the method information.
* <p>
diff --git
a/src/main/java/org/apache/commons/jexl3/internal/introspection/Permissions.java
b/src/main/java/org/apache/commons/jexl3/internal/introspection/Permissions.java
index a2cebdf..15f897f 100644
---
a/src/main/java/org/apache/commons/jexl3/internal/introspection/Permissions.java
+++
b/src/main/java/org/apache/commons/jexl3/internal/introspection/Permissions.java
@@ -111,7 +111,7 @@ public class Permissions implements JexlPermissions {
* @param clazz the clazz
* @return the clazz key
*/
- private static String classKey(final Class<?> clazz) {
+ static String classKey(final Class<?> clazz) {
return classKey(clazz, null);
}
@@ -122,7 +122,7 @@ public class Permissions implements JexlPermissions {
* @param strb the buffer to compose the key
* @return the clazz key
*/
- private static String classKey(final Class<?> clazz, final StringBuilder
strb) {
+ static String classKey(final Class<?> clazz, final StringBuilder strb) {
StringBuilder keyb = strb;
Class<?> outer = clazz.getEnclosingClass();
if (outer != null) {
@@ -175,50 +175,44 @@ public class Permissions implements JexlPermissions {
/** Marker for whole NoJexl class. */
static final NoJexlClass NOJEXL_CLASS = new
NoJexlClass(Collections.emptySet(), Collections.emptySet()) {
- @Override
- boolean deny(Field field) {
+ @Override boolean deny(Field field) {
return true;
}
- @Override
- boolean deny(Method method) {
+ @Override boolean deny(Method method) {
return true;
}
- @Override
- boolean deny(Constructor<?> method) {
+ @Override boolean deny(Constructor<?> method) {
return true;
}
};
/** Marker for allowed class. */
static final NoJexlClass JEXL_CLASS = new
NoJexlClass(Collections.emptySet(), Collections.emptySet()) {
- @Override
- boolean deny(Field field) {
+ @Override boolean deny(Field field) {
return false;
}
- @Override
- boolean deny(Method method) {
+ @Override boolean deny(Method method) {
return false;
}
- @Override
- boolean deny(Constructor<?> method) {
+ @Override boolean deny(Constructor<?> method) {
return false;
}
};
/** Marker for @NoJexl package. */
static final NoJexlPackage NOJEXL_PACKAGE = new
NoJexlPackage(Collections.emptyMap()) {
- NoJexlClass getNoJexl(Class<?> clazz) {
+ @Override NoJexlClass getNoJexl(Class<?> clazz) {
return NOJEXL_CLASS;
}
};
/** Marker for fully allowed package. */
static final NoJexlPackage JEXL_PACKAGE = new
NoJexlPackage(Collections.emptyMap()) {
- NoJexlClass getNoJexl(Class<?> clazz) {
+ @Override NoJexlClass getNoJexl(Class<?> clazz) {
return JEXL_CLASS;
}
};
diff --git a/src/main/java/org/apache/commons/jexl3/parser/JexlNode.java
b/src/main/java/org/apache/commons/jexl3/parser/JexlNode.java
index 0922712..9240a82 100644
--- a/src/main/java/org/apache/commons/jexl3/parser/JexlNode.java
+++ b/src/main/java/org/apache/commons/jexl3/parser/JexlNode.java
@@ -16,6 +16,7 @@
*/
package org.apache.commons.jexl3.parser;
+import org.apache.commons.jexl3.JexlArithmetic;
import org.apache.commons.jexl3.JexlException;
import org.apache.commons.jexl3.JexlInfo;
import org.apache.commons.jexl3.internal.ScriptVisitor;
@@ -116,23 +117,14 @@ public abstract class JexlNode extends SimpleNode {
}
/**
- * Checks whether this node is an operator.
- *
- * @return true if node is an operator node, false otherwise
- */
- public boolean isOperator() {
- return OperatorController.INSTANCE.control(this, Boolean.TRUE);
- }
-
- /**
* Checks whether this node is an operator that accepts a null argument
* even when arithmetic is in strict mode.
- * The sole cases are equals and not equals.
+ * The default cases are equals and not equals.
*
* @return true if node accepts null arguments, false otherwise
*/
- public boolean isStrictOperator() {
- return OperatorController.INSTANCE.control(this, Boolean.FALSE);
+ public boolean isStrictOperator(JexlArithmetic arithmetic) {
+ return OperatorController.INSTANCE.isStrict(arithmetic, this);
}
/**
diff --git
a/src/main/java/org/apache/commons/jexl3/parser/OperatorController.java
b/src/main/java/org/apache/commons/jexl3/parser/OperatorController.java
index 90d0f3c..ffe7017 100644
--- a/src/main/java/org/apache/commons/jexl3/parser/OperatorController.java
+++ b/src/main/java/org/apache/commons/jexl3/parser/OperatorController.java
@@ -16,7 +16,8 @@
*/
package org.apache.commons.jexl3.parser;
-import org.apache.commons.jexl3.JexlException;
+import org.apache.commons.jexl3.JexlArithmetic;
+import org.apache.commons.jexl3.JexlOperator;
import org.apache.commons.jexl3.internal.ScriptVisitor;
/**
@@ -24,168 +25,175 @@ import org.apache.commons.jexl3.internal.ScriptVisitor;
**/
class OperatorController extends ScriptVisitor {
static final OperatorController INSTANCE = new OperatorController();
+
/**
- * Controls the operator.
- * @param node the node
- * @param safe whether we are checking for any or only null-unsafe
operators
- * @return true if node is (null-unsafe) operator
+ * Checks whether an operator is strict for a given arithmetic.
+ * @param node the node which should delegate to an operator
+ * @return true if node points to a (null-unsafe) operator
*/
- boolean control(final JexlNode node, Boolean safe) {
- return Boolean.TRUE.equals(node.jjtAccept(this, safe));
+ boolean isStrict(JexlArithmetic arithmetic, final JexlNode node) {
+ if (arithmetic.isStrict()) {
+ Object ctl = node.jjtAccept(this, arithmetic);
+ if (ctl instanceof JexlOperator) {
+ JexlOperator operator = (JexlOperator) ctl;
+ return arithmetic.isStrict(operator);
+ }
+ }
+ return false;
}
@Override
- protected Object visitNode(final JexlNode node, final Object data) {
- return false;
+ protected JexlOperator visitNode(final JexlNode node, final Object data) {
+ return null;
}
@Override
- protected Object visit(final ASTNotNode node, final Object data) {
- return true;
+ protected JexlOperator visit(final ASTNotNode node, final Object data) {
+ return JexlOperator.NOT;
}
@Override
- protected Object visit(final ASTAddNode node, final Object data) {
- return true;
+ protected JexlOperator visit(final ASTAddNode node, final Object data) {
+ return JexlOperator.ADD;
}
@Override
- protected Object visit(final ASTSetAddNode node, final Object data) {
- return true;
+ protected JexlOperator visit(final ASTSetAddNode node, final Object data) {
+ return JexlOperator.SELF_ADD;
}
@Override
- protected Object visit(final ASTMulNode node, final Object data) {
- return true;
+ protected JexlOperator visit(final ASTMulNode node, final Object data) {
+ return JexlOperator.MULTIPLY;
}
@Override
- protected Object visit(final ASTSetMultNode node, final Object data) {
- return true;
+ protected JexlOperator visit(final ASTSetMultNode node, final Object data)
{
+ return JexlOperator.SELF_MULTIPLY;
}
@Override
- protected Object visit(final ASTModNode node, final Object data) {
- return true;
+ protected JexlOperator visit(final ASTModNode node, final Object data) {
+ return JexlOperator.MOD;
}
@Override
- protected Object visit(final ASTSetModNode node, final Object data) {
- return true;
+ protected JexlOperator visit(final ASTSetModNode node, final Object data) {
+ return JexlOperator.SELF_MOD;
}
@Override
- protected Object visit(final ASTDivNode node, final Object data) {
- return true;
+ protected JexlOperator visit(final ASTDivNode node, final Object data) {
+ return JexlOperator.DIVIDE;
}
@Override
- protected Object visit(final ASTSetDivNode node, final Object data) {
- return true;
+ protected JexlOperator visit(final ASTSetDivNode node, final Object data) {
+ return JexlOperator.SELF_DIVIDE;
}
@Override
- protected Object visit(final ASTBitwiseAndNode node, final Object data) {
- return true;
+ protected JexlOperator visit(final ASTBitwiseAndNode node, final Object
data) {
+ return JexlOperator.AND;
}
@Override
- protected Object visit(final ASTSetAndNode node, final Object data) {
- return true;
+ protected JexlOperator visit(final ASTSetAndNode node, final Object data) {
+ return JexlOperator.SELF_AND;
}
@Override
- protected Object visit(final ASTBitwiseOrNode node, final Object data) {
- return true;
+ protected JexlOperator visit(final ASTBitwiseOrNode node, final Object
data) {
+ return JexlOperator.OR;
}
@Override
- protected Object visit(final ASTSetOrNode node, final Object data) {
- return true;
+ protected JexlOperator visit(final ASTSetOrNode node, final Object data) {
+ return JexlOperator.SELF_OR;
}
@Override
- protected Object visit(final ASTBitwiseXorNode node, final Object data) {
- return true;
+ protected JexlOperator visit(final ASTBitwiseXorNode node, final Object
data) {
+ return JexlOperator.XOR;
}
@Override
- protected Object visit(final ASTSetXorNode node, final Object data) {
- return true;
+ protected JexlOperator visit(final ASTSetXorNode node, final Object data) {
+ return JexlOperator.SELF_OR;
}
@Override
- protected Object visit(final ASTBitwiseComplNode node, final Object data) {
- return true;
+ protected JexlOperator visit(final ASTBitwiseComplNode node, final Object
data) {
+ return JexlOperator.COMPLEMENT;
}
@Override
- protected Object visit(final ASTSubNode node, final Object data) {
- return true;
+ protected JexlOperator visit(final ASTSubNode node, final Object data) {
+ return JexlOperator.SUBTRACT;
}
@Override
- protected Object visit(final ASTSetSubNode node, final Object data) {
- return true;
+ protected JexlOperator visit(final ASTSetSubNode node, final Object data) {
+ return JexlOperator.SELF_SUBTRACT;
}
@Override
- protected Object visit(final ASTEQNode node, final Object data) {
- return data;
+ protected JexlOperator visit(final ASTEQNode node, final Object data) {
+ return JexlOperator.EQ;
}
@Override
- protected Object visit(final ASTNENode node, final Object data) {
- return data;
+ protected JexlOperator visit(final ASTNENode node, final Object data) {
+ return JexlOperator.EQ;
}
@Override
- protected Object visit(final ASTGTNode node, final Object data) {
- return true;
+ protected JexlOperator visit(final ASTGTNode node, final Object data) {
+ return JexlOperator.GT;
}
@Override
- protected Object visit(final ASTGENode node, final Object data) {
- return true;
+ protected JexlOperator visit(final ASTGENode node, final Object data) {
+ return JexlOperator.GTE;
}
@Override
- protected Object visit(final ASTLTNode node, final Object data) {
- return true;
+ protected JexlOperator visit(final ASTLTNode node, final Object data) {
+ return JexlOperator.LT;
}
@Override
- protected Object visit(final ASTLENode node, final Object data) {
- return true;
+ protected JexlOperator visit(final ASTLENode node, final Object data) {
+ return JexlOperator.LTE;
}
@Override
- protected Object visit(final ASTSWNode node, final Object data) {
- return true;
+ protected JexlOperator visit(final ASTSWNode node, final Object data) {
+ return JexlOperator.STARTSWITH;
}
@Override
- protected Object visit(final ASTNSWNode node, final Object data) {
- return true;
+ protected JexlOperator visit(final ASTNSWNode node, final Object data) {
+ return JexlOperator.STARTSWITH;
}
@Override
- protected Object visit(final ASTEWNode node, final Object data) {
- return true;
+ protected JexlOperator visit(final ASTEWNode node, final Object data) {
+ return JexlOperator.ENDSWITH;
}
@Override
- protected Object visit(final ASTNEWNode node, final Object data) {
- return true;
+ protected JexlOperator visit(final ASTNEWNode node, final Object data) {
+ return JexlOperator.ENDSWITH;
}
@Override
- protected Object visit(final ASTERNode node, final Object data) {
- return true;
+ protected JexlOperator visit(final ASTERNode node, final Object data) {
+ return JexlOperator.CONTAINS;
}
@Override
- protected Object visit(final ASTNRNode node, final Object data) {
- return true;
+ protected JexlOperator visit(final ASTNRNode node, final Object data) {
+ return JexlOperator.CONTAINS;
}
}
diff --git a/src/test/java/org/apache/commons/jexl3/ArithmeticTest.java
b/src/test/java/org/apache/commons/jexl3/ArithmeticTest.java
index 3cc31b6..91f704c 100644
--- a/src/test/java/org/apache/commons/jexl3/ArithmeticTest.java
+++ b/src/test/java/org/apache/commons/jexl3/ArithmeticTest.java
@@ -777,6 +777,19 @@ public class ArithmeticTest extends JexlTestCase {
script = jexl.createScript("'1.2' + '1.2' ");
result = script.execute(null);
Assert.assertEquals("1.21.2", result);
+
+ }
+
+ @Test
+ public void testNullArgs() throws Exception {
+ JexlEngine jexl = new JexlBuilder().arithmetic(new
JexlArithmetic(true) {
+ @Override public boolean isStrict(JexlOperator op) {
+ return JexlOperator.ADD == op? false: super.isStrict(op);
+ }
+ }).create();
+ JexlScript script = jexl.createScript("'1.2' + x ", "x");
+ Object result = script.execute(null, null);
+ Assert.assertEquals("1.2", result);
}
@Test
diff --git a/src/test/java/org/apache/commons/jexl3/SideEffectTest.java
b/src/test/java/org/apache/commons/jexl3/SideEffectTest.java
index adbb053..c258b7d 100644
--- a/src/test/java/org/apache/commons/jexl3/SideEffectTest.java
+++ b/src/test/java/org/apache/commons/jexl3/SideEffectTest.java
@@ -592,7 +592,6 @@ public class SideEffectTest extends JexlTestCase {
Assert.assertSame(zz, z);
Assert.assertEquals(1, z.size());
z.clear();
- ctx.clear();
boolean t246 = false;
// call with null