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 2016/07/12 16:02:59 UTC
svn commit: r1752310 - in /commons/proper/jexl/trunk/src:
main/java/org/apache/commons/jexl3/JexlArithmetic.java
main/java/org/apache/commons/jexl3/internal/Interpreter.java
test/java/org/apache/commons/jexl3/ArithmeticTest.java
Author: henrib
Date: Tue Jul 12 16:02:59 2016
New Revision: 1752310
URL: http://svn.apache.org/viewvc?rev=1752310&view=rev
Log:
JEXL:
Partial fix for JEXL-201 / JEXL-203 - moved silent/strict/cancellable flags out of interpreter (thus overridable by contextual options)
Modified:
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlArithmetic.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java
commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ArithmeticTest.java
Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlArithmetic.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlArithmetic.java?rev=1752310&r1=1752309&r2=1752310&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlArithmetic.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlArithmetic.java Tue Jul 12 16:02:59 2016
@@ -106,29 +106,44 @@ public class JexlArithmetic {
/**
* Apply options to this arithmetic which eventually may create another instance.
+ * @see #createWithOptions(boolean, java.math.MathContext, int)
*
* @param options the {@link JexlEngine.Options} to use
* @return an arithmetic with those options set
*/
public JexlArithmetic options(JexlEngine.Options options) {
- boolean ostrict = options.isStrictArithmetic() == null
- ? this.strict
- : options.isStrictArithmetic();
+ Boolean ostrict = options.isStrictArithmetic();
+ if (ostrict == null) {
+ ostrict = isStrict();
+ }
MathContext bigdContext = options.getArithmeticMathContext();
if (bigdContext == null) {
- bigdContext = mathContext;
+ bigdContext = getMathContext();
}
int bigdScale = options.getArithmeticMathScale();
if (bigdScale == Integer.MIN_VALUE) {
- bigdScale = mathScale;
+ bigdScale = getMathScale();
}
- if ((ostrict != this.strict)
- || bigdScale != this.mathScale
- || bigdContext != this.mathContext) {
- return new JexlArithmetic(ostrict, bigdContext, bigdScale);
- } else {
- return this;
+ if (ostrict != isStrict()
+ || bigdScale != getMathScale()
+ || bigdContext != getMathContext()) {
+ return createWithOptions(ostrict, bigdContext, bigdScale);
}
+ return this;
+ }
+
+ /**
+ * Creates a JexlArithmetic instance.
+ * Called by options(...) method when another instance of the same class of arithmetic is required.
+ * @see #options(org.apache.commons.jexl3.JexlEngine.Options)
+ *
+ * @param astrict whether this arithmetic is lenient or strict
+ * @param bigdContext the math context instance to use for +,-,/,*,% operations on big decimals.
+ * @param bigdScale the scale used for big decimals.
+ * @return default is a new JexlArithmetic instance
+ */
+ protected JexlArithmetic createWithOptions(boolean astrict, MathContext bigdContext, int bigdScale) {
+ return new JexlArithmetic(astrict, bigdContext, bigdScale);
}
/**
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=1752310&r1=1752309&r2=1752310&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 Tue Jul 12 16:02:59 2016
@@ -138,16 +138,8 @@ public class Interpreter extends ParserV
protected final Scope.Frame frame;
/** The context to store/retrieve variables. */
protected final JexlContext.NamespaceResolver ns;
- /** Strict interpreter flag (may temporarily change when calling size and empty as functions). */
- protected final boolean strictEngine;
- /** Strict interpreter flag. */
- protected final boolean strictArithmetic;
- /** Silent interpreter flag. */
- protected final boolean silent;
/** Cache executors. */
protected final boolean cache;
- /** Throw on cancel. */
- protected final boolean cancellable;
/** Cancellation support. */
protected volatile boolean cancelled = false;
/** Empty parameters for method matching. */
@@ -166,17 +158,14 @@ public class Interpreter extends ParserV
this.context = aContext != null ? aContext : Engine.EMPTY_CONTEXT;
if (this.context instanceof JexlEngine.Options) {
JexlEngine.Options opts = (JexlEngine.Options) context;
- Boolean ostrict = opts.isStrict();
- Boolean osilent = opts.isSilent();
- Boolean ocancellable = opts.isCancellable();
- this.strictEngine = ostrict == null ? jexl.isStrict() : ostrict;
- this.silent = osilent == null ? jexl.isSilent() : osilent;
- this.cancellable = ocancellable == null ? jexl.cancellable : ocancellable;
this.arithmetic = jexl.arithmetic.options(opts);
+ if (!arithmetic.getClass().equals(jexl.arithmetic.getClass())) {
+ logger.error(
+ "expected arithmetic to be " + jexl.arithmetic.getClass().getSimpleName() +
+ ", got " + arithmetic.getClass().getSimpleName()
+ );
+ }
} else {
- this.strictEngine = jexl.isStrict();
- this.silent = jexl.isSilent();
- this.cancellable = jexl.cancellable;
this.arithmetic = jexl.arithmetic;
}
if (this.context instanceof JexlContext.NamespaceResolver) {
@@ -185,7 +174,6 @@ public class Interpreter extends ParserV
ns = Engine.EMPTY_NS;
}
this.functions = jexl.functions;
- this.strictArithmetic = this.arithmetic.isStrict();
this.cache = jexl.cache != null;
this.frame = eFrame;
this.functors = null;
@@ -212,11 +200,11 @@ public class Interpreter extends ParserV
return xreturn.getValue();
} catch (JexlException.Cancel xcancel) {
cancelled |= Thread.interrupted();
- if (cancellable) {
+ if (isCancellable()) {
throw xcancel.clean();
}
} catch (JexlException xjexl) {
- if (!silent) {
+ if (!isSilent()) {
throw xjexl.clean();
}
logger.warn(xjexl.getMessage(), xjexl.getCause());
@@ -267,6 +255,48 @@ public class Interpreter extends ParserV
}
/**
+ * Whether this interpreter is currently evaluating with a strict engine flag.
+ * @return true if strict engine, false otherwise
+ */
+ protected boolean isStrictEngine() {
+ if (this.context instanceof JexlEngine.Options) {
+ JexlEngine.Options opts = (JexlEngine.Options) context;
+ Boolean strict = opts.isStrict();
+ if (strict != null) {
+ return strict.booleanValue();
+ }
+ }
+ return jexl.isStrict();
+ }
+
+ /**
+ * Whether this interpreter is currently evaluating with a silent mode.
+ * @return true if silent, false otherwise
+ */
+ protected boolean isSilent() {
+ if (this.context instanceof JexlEngine.Options) {
+ JexlEngine.Options opts = (JexlEngine.Options) context;
+ Boolean silent = opts.isSilent();
+ if (silent != null) {
+ return silent.booleanValue();
+ }
+ }
+ return jexl.isSilent();
+ }
+
+ /** @return true if interrupt throws a JexlException.Cancel. */
+ protected boolean isCancellable() {
+ if (this.context instanceof JexlEngine.Options) {
+ JexlEngine.Options opts = (JexlEngine.Options) context;
+ Boolean ocancellable = opts.isCancellable();
+ if (ocancellable != null) {
+ return ocancellable.booleanValue();
+ }
+ }
+ return jexl.cancellable;
+ }
+
+ /**
* Finds the node causing a NPE for diadic operators.
* @param xrt the RuntimeException
* @param node the parent node
@@ -294,10 +324,10 @@ public class Interpreter extends ParserV
* @return throws JexlException if isStrict, null otherwise
*/
protected Object unsolvableVariable(JexlNode node, String var, boolean undef) {
- if (!silent) {
+ if (!isSilent()) {
logger.warn(JexlException.variableError(node, var, undef));
}
- if (strictEngine && (undef || arithmetic.isStrict())) {
+ if (isStrictEngine() && (undef || arithmetic.isStrict())) {
throw new JexlException.Variable(node, var, undef);
}
return null;
@@ -310,10 +340,10 @@ public class Interpreter extends ParserV
* @return throws JexlException if isStrict, null otherwise
*/
protected Object unsolvableMethod(JexlNode node, String method) {
- if (!silent) {
+ if (!isSilent()) {
logger.warn(JexlException.methodError(node, method));
}
- if (strictEngine) {
+ if (isStrictEngine()) {
throw new JexlException.Method(node, method);
}
return null;
@@ -327,10 +357,10 @@ public class Interpreter extends ParserV
* @return throws JexlException if isStrict, null otherwise
*/
protected Object unsolvableProperty(JexlNode node, String var, Throwable cause) {
- if (!silent) {
+ if (!isSilent()) {
logger.warn(JexlException.propertyError(node, var), cause);
}
- if (strictEngine) {
+ if (isStrictEngine()) {
throw new JexlException.Property(node, var, cause);
}
return null;
@@ -345,10 +375,10 @@ public class Interpreter extends ParserV
*/
protected void operatorError(JexlNode node, JexlOperator operator, Throwable cause) {
if (cause != null) {
- if (!silent) {
+ if (!isSilent()) {
logger.warn(JexlException.operatorError(node, operator.getOperatorSymbol()), cause);
}
- if (strictEngine) {
+ if (isStrictEngine()) {
throw new JexlException.Operator(node, operator.getOperatorSymbol(), cause);
}
}
@@ -360,10 +390,10 @@ public class Interpreter extends ParserV
* @return throws JexlException if isStrict, null otherwise
*/
protected Object invocationFailed(JexlException xjexl) {
- if (!silent) {
+ if (!isSilent()) {
logger.warn(xjexl.getMessage(), xjexl.getCause());
}
- if (strictEngine
+ if (isStrictEngine()
|| xjexl instanceof JexlException.Return
|| xjexl instanceof JexlException.Cancel) {
throw xjexl;
@@ -398,10 +428,10 @@ public class Interpreter extends ParserV
* @throws JexlException if isStrict
*/
protected void annotationError(JexlNode node, String annotation, Throwable cause) {
- if (!silent) {
+ if (!isSilent()) {
logger.warn(JexlException.annotationError(node, annotation), cause);
}
- if (strictEngine) {
+ if (isStrictEngine()) {
throw new JexlException.Annotation(node, annotation, cause);
}
}
@@ -430,11 +460,6 @@ public class Interpreter extends ParserV
return cancelled;
}
- /** @return true if interrupt throws a JexlException.Cancel. */
- protected boolean isCancellable() {
- return cancellable;
- }
-
/**
* Resolves a namespace, eventually allocating an instance using context as constructor argument.
* <p>
@@ -533,7 +558,7 @@ public class Interpreter extends ParserV
Object result = operators.tryOverload(node, JexlOperator.DIVIDE, left, right);
return result != JexlEngine.TRY_FAILED ? result : arithmetic.divide(left, right);
} catch (ArithmeticException xrt) {
- if (!strictArithmetic) {
+ if (!arithmetic.isStrict()) {
return 0.0d;
}
JexlNode xnode = findNullOperand(xrt, node, left, right);
@@ -549,7 +574,7 @@ public class Interpreter extends ParserV
Object result = operators.tryOverload(node, JexlOperator.MOD, left, right);
return result != JexlEngine.TRY_FAILED ? result : arithmetic.mod(left, right);
} catch (ArithmeticException xrt) {
- if (!strictArithmetic) {
+ if (!arithmetic.isStrict()) {
return 0.0d;
}
JexlNode xnode = findNullOperand(xrt, node, left, right);
Modified: commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ArithmeticTest.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ArithmeticTest.java?rev=1752310&r1=1752309&r2=1752310&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ArithmeticTest.java (original)
+++ commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ArithmeticTest.java Tue Jul 12 16:02:59 2016
@@ -539,6 +539,22 @@ public class ArithmeticTest extends Jexl
}
@Test
+ public void testOption() throws Exception {
+ Map<String, Object> vars = new HashMap<String, Object>();
+ JexlEvalContext context = new JexlEvalContext(vars);
+ JexlScript script = JEXL.createScript("0 + '1.2' ");
+ Object result;
+
+ context.setStrictArithmetic(true);
+ result = script.execute(context);
+ Assert.assertEquals("01.2", result);
+
+ context.setStrictArithmetic(false);
+ result = script.execute(context);
+ Assert.assertEquals(1.2d, (Double) result, EPSILON);
+ }
+
+ @Test
public void testIsFloatingPointPattern() throws Exception {
JexlArithmetic ja = new JexlArithmetic(true);