Author: henrib Date: Wed Jun 10 16:30:16 2015 New Revision: 1684706 URL: http://svn.apache.org/r1684706 Log: Moved some issues related tests to existing feature test classes; Refactored tests using annotations; Fixed edge case where identifier starts with zeroes (must not be considered as integers);
Added: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/annotations/JexlSet.java (with props) commons/proper/jexl/trunk/src/test/scripts/testA.jexl Removed: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/Main.java commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/SandboxTest.java Modified: commons/proper/jexl/trunk/pom.xml commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlArithmetic.java commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlBuilder.java commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlContext.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/JxltEngine.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/introspection/ArrayListWrapper.java commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/ClassMap.java commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/MethodKey.java commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/PropertyGetExecutor.java commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/Uberspect.java commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ASTIdentifierAccess.java commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ArithmeticOperatorTest.java commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ArithmeticTest.java commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ArrayAccessTest.java commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ArrayLiteralTest.java commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/AssignTest.java commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/BitwiseOperatorTest.java commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/BlockTest.java commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/CacheTest.java commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ClassCreatorTest.java 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/ForEachTest.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/IssuesTest.java commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/JXLTTest.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/JexlTestCase.java commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/LambdaTest.java commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/MapLiteralTest.java commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/MethodTest.java commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ParseFailuresTest.java commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/PragmaTest.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/PublicFieldsTest.java commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/RangeTest.java commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ScriptCallableTest.java commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ScriptTest.java commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/SetLiteralTest.java commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/VarTest.java commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/WhileTest.java commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/examples/ArrayTest.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/internal/introspection/DiscoveryTest.java commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/internal/introspection/MethodKeyTest.java commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/introspection/SandboxTest.java commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/junit/AsserterTest.java Modified: commons/proper/jexl/trunk/pom.xml URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/pom.xml?rev=1684706&r1=1684705&r2=1684706&view=diff ============================================================================== --- commons/proper/jexl/trunk/pom.xml (original) +++ commons/proper/jexl/trunk/pom.xml Wed Jun 10 16:30:16 2015 @@ -117,10 +117,14 @@ <maven.compiler.target>1.6</maven.compiler.target> <commons.componentid>jexl</commons.componentid> <commons.release.version>3.0</commons.release.version> + <commons.site.path>jexl</commons.site.path> + <commons.scmPubUrl>https://svn.apache.org/repos/infra/websites/production/commons/content/proper/commons-jexl</commons.scmPubUrl> + <commons.scmPubCheckoutDirectory>site-content</commons.scmPubCheckoutDirectory> <!-- The RC version used in the staging repository URL. --> <commons.rc.version>RC1</commons.rc.version> <commons.release.3.version>2.1</commons.release.3.version> <commons.release.3.binary.suffix>2.1.1</commons.release.3.binary.suffix> + <commons.release.2.desc>Legacy</commons.release.2.desc> <commons.release.2.version>1.1</commons.release.2.version> <commons.release.2.binary.suffix /> <commons.jira.id>JEXL</commons.jira.id> @@ -199,29 +203,29 @@ </instrumentation> </configuration> </plugin> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-scm-publish-plugin</artifactId> - <configuration> - <ignorePathsToDelete> - <ignorePathToDelete>javadocs</ignorePathToDelete> - </ignorePathsToDelete> - </configuration> - </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-scm-publish-plugin</artifactId> + <configuration> + <ignorePathsToDelete> + <ignorePathToDelete>javadocs</ignorePathToDelete> + </ignorePathsToDelete> + </configuration> + </plugin> </plugins> </build> <reporting> <plugins> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-javadoc-plugin</artifactId> - <version>2.9.1</version> - <configuration> - <excludePackageNames>*.internal;*.parser</excludePackageNames> - <show>public</show> - </configuration> - </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-javadoc-plugin</artifactId> + <version>2.9.1</version> + <configuration> + <excludePackageNames>*.internal;*.parser</excludePackageNames> + <show>public</show> + </configuration> + </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-changes-plugin</artifactId> @@ -262,7 +266,7 @@ <configuration> <excludeFilterFile>${basedir}/src/main/config/findbugs-exclude-filter.xml</excludeFilterFile> <xmlOutput>true</xmlOutput> - <!-- Optional directory to put findbugs xdoc xml report --> + <!-- Optional directory to put findbugs xdoc xml report --> <xmlOutputDirectory>target/site</xmlOutputDirectory> </configuration> </plugin> 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=1684706&r1=1684705&r2=1684706&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 Wed Jun 10 16:30:16 2015 @@ -26,6 +26,7 @@ import java.math.MathContext; * Perform arithmetic. * <p> * The 5 arithmetic operators (+, - , *, /, %) follow the same evaluation rules regarding their arguments. + * </p> * <ol> * <li>If both are null, result is 0</li> * <li>If either is a BigDecimal, coerce both to BigDecimal and perform operation</li> @@ -38,14 +39,13 @@ import java.math.MathContext; * </ol> * </li> * </ol> - * </p> * Note that the only exception thrown by JexlArithmetic is ArithmeticException. * @since 2.0 */ public class JexlArithmetic { /** * The overload-able operators. - * Note that logical and (ie &&) and logical or (ie ||) are not in this list to avoid breaking + * Note that logical and (ie &&) and logical or (ie ||) are not in this list to avoid breaking * their shortcut semantics. * @since 3.0 */ @@ -863,7 +863,7 @@ public class JexlArithmetic { * Performs a bitwise and. * @param left the left operand * @param right the right operator - * @return left & right + * @return left & right */ public Object bitwiseAnd(Object left, Object right) { long l = toLong(left); @@ -919,7 +919,7 @@ public class JexlArithmetic { * @param left the left operand * @param right the right operator * @param operator the operator - * @return -1 if left < right; +1 if left > > right; 0 if left == right + * @return -1 if left < right; +1 if left > right; 0 if left == right * @throws ArithmeticException if either left or right is null */ protected int compare(Object left, Object right, String operator) { 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=1684706&r1=1684705&r2=1684706&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 Jun 10 16:30:16 2015 @@ -36,7 +36,7 @@ import java.nio.charset.Charset; * </p> * <ul> * <li>When "silent" & "not-strict": - * <p> 0 & null should be indicators of "default" values so that even in an case of error, + * <p> 0 & null should be indicators of "default" values so that even in an case of error, * something meaningfull can still be inferred; may be convenient for configurations. * </p> * </li> @@ -52,7 +52,7 @@ import java.nio.charset.Charset; * </li> * <li>When "not-silent" & "strict": * <p>The finest error control grain is obtained; it is the closest to Java code - - * still augmented by "script" capabilities regarding automated conversions & type matching. + * still augmented by "script" capabilities regarding automated conversions and type matching. * </p> * </li> * </ul> Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlContext.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlContext.java?rev=1684706&r1=1684705&r2=1684706&view=diff ============================================================================== --- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlContext.java (original) +++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlContext.java Wed Jun 10 16:30:16 2015 @@ -104,7 +104,7 @@ public interface JexlContext { * keeping a reference to such a context is to be considered with great care and caution. * It should also be noted that sharing such a context between threads should implicate synchronizing variable * accessing the implementation class. - * @see JexlEngine#setThreadContext() + * @see JexlEngine#setThreadContext(JexlContext.ThreadLocal) * @see JexlEngine#getThreadContext() */ public interface ThreadLocal extends JexlContext { 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=1684706&r1=1684705&r2=1684706&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 Jun 10 16:30:16 2015 @@ -29,10 +29,10 @@ import java.nio.charset.Charset; /** * Creates and evaluates JexlExpression and JexlScript objects. - * Determines the behavior of expressions & scripts during their evaluation with respect to: + * Determines the behavior of expressions and scripts during their evaluation with respect to: * <ul> * <li>Introspection, see {@link JexlUberspect}</li> - * <li>Arithmetic & comparison, see {@link JexlArithmetic}</li> + * <li>Arithmetic and comparison, see {@link JexlArithmetic}</li> * <li>Error reporting</li> * <li>Logging</li> * </ul> @@ -51,7 +51,7 @@ public abstract class JexlEngine { return "tryExecute failed"; } }; - + /** * The thread local context. */ Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JxltEngine.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JxltEngine.java?rev=1684706&r1=1684705&r2=1684706&view=diff ============================================================================== --- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JxltEngine.java (original) +++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JxltEngine.java Wed Jun 10 16:30:16 2015 @@ -66,7 +66,7 @@ public abstract class JxltEngine { * <li>The "composite" syntax is of the form <code>"...${jexl-expr0}... #{jexl-expr1}..."</code></li> * </ul> * <p> - * Deferred & immediate expression carry different intentions: + * Deferred and immediate expression carry different intentions: * <ul> * <li>An immediate expression indicate that evaluation is intended to be performed close to * the definition/parsing point.</li> @@ -82,14 +82,14 @@ public abstract class JxltEngine { * <p> * The API reflects this feature in 2 methods, prepare and evaluate. The prepare method * will evaluate the immediate subexpression and return an expression that contains only - * the deferred subexpressions (& constants), a prepared expression. Such a prepared expression + * the deferred subexpressions (and constants), a prepared expression. Such a prepared expression * is suitable for a later phase evaluation that may occur with a different JexlContext. * Note that it is valid to call evaluate without prepare in which case the same JexlContext * is used for the 2 evaluation phases. * </p> * <p> * In the most common use-case where deferred expressions are to be kept around as properties of objects, - * one should createExpression & prepare an expression before storing it and evaluate it each time + * one should createExpression and prepare an expression before storing it and evaluate it each time * the property storing it is accessed. * </p> * <p> @@ -172,7 +172,7 @@ public abstract class JxltEngine { * <p> * In effect, this binds the result of the immediate sub-expressions evaluation in the * context, allowing to differ evaluation of the remaining (deferred) expression within another context. - * This only has an effect to nested & composite expressions that contain differed & immediate sub-expressions. + * This only has an effect to nested and composite expressions that contain differed and immediate sub-expressions. * </p> * <p> * If the underlying JEXL engine is silent, errors will be logged through its logger as warning. @@ -196,12 +196,12 @@ public abstract class JxltEngine { /** * Creates a a {@link Expression} from an expression string. - * Uses & fills up the expression cache if any. + * Uses and fills up the expression cache if any. * <p> * If the underlying JEXL engine is silent, errors will be logged through its logger as warnings. * </p> * @param expression the {@link Template} string expression - * @return the {@link Expression}, null if silent and an error occured + * @return the {@link Expression}, null if silent and an error occurred * @throws Exception if an error occurs and the {@link JexlEngine} * is not silent */ Added: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/annotations/JexlSet.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/annotations/JexlSet.java?rev=1684706&view=auto ============================================================================== --- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/annotations/JexlSet.java (added) +++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/annotations/JexlSet.java Wed Jun 10 16:30:16 2015 @@ -0,0 +1,35 @@ +/* + * 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.annotations; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Indicates to JEXL Introspection that this method is a property setter. + * See {@link org.apache.commons.jexl3.introspection.JexlSandbox} for another way to restrict JEXL access. + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.METHOD, ElementType.FIELD}) +public @interface JexlSet { + String property(); +} Propchange: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/annotations/JexlSet.java ------------------------------------------------------------------------------ svn:eol-style = native 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=1684706&r1=1684705&r2=1684706&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 Jun 10 16:30:16 2015 @@ -446,12 +446,12 @@ public class Engine extends JexlEngine { xjexl = xany; } catch (Exception xany) { xjexl = new JexlException.Method(info, meth, xany); - } finally { - if (xjexl != null) { - if (silent) { - logger.warn(xjexl.getMessage(), xjexl.getCause()); - return null; - } + } + if (xjexl != null) { + if (silent) { + logger.warn(xjexl.getMessage(), xjexl.getCause()); + result = null; + } else { throw xjexl.clean(); } } @@ -661,7 +661,7 @@ public class Engine extends JexlEngine { * @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 occured during parsing + * @throws JexlException if any error occurred during parsing */ protected ASTJexlScript parse(JexlInfo info, String src, Scope scope, boolean registers, boolean expression) { final boolean cached = src.length() < cacheThreshold && cache != null; @@ -685,7 +685,7 @@ public class Engine extends JexlEngine { } /** - * Trims the source from front & ending spaces. + * Trims the source from front and ending spaces. * @param str expression to clean * @return trimmed expression ending in a semi-colon */ 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=1684706&r1=1684705&r2=1684706&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 Jun 10 16:30:16 2015 @@ -124,11 +124,11 @@ public class Interpreter extends ParserV protected final JexlContext context; /** The context to store/retrieve variables. */ protected final JexlContext.NamespaceResolver ns; - /** Strict interpreter flag (may temporarily change during when calling size & empty as functions). */ + /** Strict interpreter flag (may temporarily change during when calling size and empty as functions). */ protected boolean strictEngine; /** Strict interpreter flag. */ protected final boolean strictArithmetic; - /** Silent intepreter flag. */ + /** Silent interpreter flag. */ protected final boolean silent; /** Cache executors. */ protected final boolean cache; @@ -177,7 +177,8 @@ public class Interpreter extends ParserV /** * Interpret the given script/expression. - * <p> If the underlying JEXL engine is silent, errors will be logged through + * <p> + * If the underlying JEXL engine is silent, errors will be logged through * its logger as warning. * @param node the script or expression to interpret. * @return the result of the interpretation. @@ -201,14 +202,14 @@ public class Interpreter extends ParserV throw xjexl.clean(); } finally { if (functors != null && AUTOCLOSEABLE != null) { - for(Object functor : functors.values()) { - if (functor != null && AUTOCLOSEABLE.isAssignableFrom(functor.getClass())) { - try { + for (Object functor : functors.values()) { + if (functor != null && AUTOCLOSEABLE.isAssignableFrom(functor.getClass())) { + try { jexl.invokeMethod(functor, "close", EMPTY_PARAMS); - } catch(Exception xclose) { + } catch (Exception xclose) { logger.warn(xclose.getMessage(), xclose.getCause()); - } - } + } + } } } functors = null; @@ -220,12 +221,13 @@ public class Interpreter extends ParserV /** Java7 AutoCloseable interface defined?. */ private static final Class<?> AUTOCLOSEABLE; + static { Class<?> c; try { - c = Class.forName("java.lang.AutoCloseable"); - } catch(ClassNotFoundException xclass) { - c = null; + c = Class.forName("java.lang.AutoCloseable"); + } catch (ClassNotFoundException xclass) { + c = null; } AUTOCLOSEABLE = c; } @@ -252,8 +254,8 @@ public class Interpreter extends ParserV /** * Triggered when a variable can not be resolved. - * @param node the node where the error originated from - * @param var the variable name + * @param node the node where the error originated from + * @param var the variable name * @param undef whether the variable is undefined or null * @return throws JexlException if isStrict, null otherwise */ @@ -269,7 +271,7 @@ public class Interpreter extends ParserV /** * Triggered when a method can not be resolved. - * @param node the node where the error originated from + * @param node the node where the error originated from * @param method the method name * @return throws JexlException if isStrict, null otherwise */ @@ -285,8 +287,8 @@ public class Interpreter extends ParserV /** * Triggered when a property can not be resolved. - * @param node the node where the error originated from - * @param var the property name + * @param node the node where the error originated from + * @param var the property name * @param cause the cause if any * @return throws JexlException if isStrict, null otherwise */ @@ -327,7 +329,9 @@ public class Interpreter extends ParserV } /** - * Resolves a namespace, eventually allocating an instance using context as constructor argument. <p>The lifetime of + * Resolves a namespace, eventually allocating an instance using context as constructor argument. + * <p> + * The lifetime of * such instances span the current expression or script evaluation.</p> * @param prefix the prefix name (may be null for global namespace) * @param node the AST node @@ -379,10 +383,11 @@ public class Interpreter extends ParserV /** * Attempts to call a monadic operator. - * <p>This takes care of finding and caching the operator method when appropriate - * @param node the syntactic node + * <p> + * This takes care of finding and caching the operator method when appropriate + * @param node the syntactic node * @param operator the operator - * @param arg the argument + * @param arg the argument * @return the result of the operator evaluation or TRY_FAILED */ protected Object callOperator(JexlNode node, Operator operator, Object arg) { @@ -415,11 +420,12 @@ public class Interpreter extends ParserV /** * Attempts to call a diadic operator. - * <p>This takes care of finding and caching the operator method when appropriate - * @param node the syntactic node + * <p> + * This takes care of finding and caching the operator method when appropriate + * @param node the syntactic node * @param operator the operator - * @param lhs the left hand side argument - * @param rhs the right hand side argument + * @param lhs the left hand side argument + * @param rhs the right hand side argument * @return the result of the operator evaluation or TRY_FAILED */ protected Object callOperator(JexlNode node, Operator operator, Object lhs, Object rhs) { @@ -499,7 +505,7 @@ public class Interpreter extends ParserV Object right = node.jjtGetChild(1).jjtAccept(this, data); try { Object result = callOperator(node, Operator.ADD, left, right); - return result != JexlEngine.TRY_FAILED? result : arithmetic.add(left, right); + return result != JexlEngine.TRY_FAILED ? result : arithmetic.add(left, right); } catch (ArithmeticException xrt) { throw new JexlException(node, "+ error", xrt); } @@ -511,7 +517,7 @@ public class Interpreter extends ParserV Object right = node.jjtGetChild(1).jjtAccept(this, data); try { Object result = callOperator(node, Operator.SUBTRACT, left, right); - return result != JexlEngine.TRY_FAILED? result : arithmetic.subtract(left, right); + return result != JexlEngine.TRY_FAILED ? result : arithmetic.subtract(left, right); } catch (ArithmeticException xrt) { throw new JexlException(node, "- error", xrt); } @@ -523,7 +529,7 @@ public class Interpreter extends ParserV Object right = node.jjtGetChild(1).jjtAccept(this, data); try { Object result = callOperator(node, Operator.AND, left, right); - return result != JexlEngine.TRY_FAILED? result : arithmetic.bitwiseAnd(left, right); + return result != JexlEngine.TRY_FAILED ? result : arithmetic.bitwiseAnd(left, right); } catch (ArithmeticException xrt) { throw new JexlException(node, "& error", xrt); } @@ -534,7 +540,7 @@ public class Interpreter extends ParserV Object arg = node.jjtGetChild(0).jjtAccept(this, data); try { Object result = callOperator(node, Operator.COMPLEMENT, arg); - return result != JexlEngine.TRY_FAILED? result : arithmetic.bitwiseComplement(arg); + return result != JexlEngine.TRY_FAILED ? result : arithmetic.bitwiseComplement(arg); } catch (ArithmeticException xrt) { throw new JexlException(node, "~ error", xrt); } @@ -546,7 +552,7 @@ public class Interpreter extends ParserV Object right = node.jjtGetChild(1).jjtAccept(this, data); try { Object result = callOperator(node, Operator.OR, left, right); - return result != JexlEngine.TRY_FAILED? result : arithmetic.bitwiseOr(left, right); + return result != JexlEngine.TRY_FAILED ? result : arithmetic.bitwiseOr(left, right); } catch (ArithmeticException xrt) { throw new JexlException(node, "| error", xrt); } @@ -558,7 +564,7 @@ public class Interpreter extends ParserV Object right = node.jjtGetChild(1).jjtAccept(this, data); try { Object result = callOperator(node, Operator.XOR, left, right); - return result != JexlEngine.TRY_FAILED? result : arithmetic.bitwiseXor(left, right); + return result != JexlEngine.TRY_FAILED ? result : arithmetic.bitwiseXor(left, right); } catch (ArithmeticException xrt) { throw new JexlException(node, "^ error", xrt); } @@ -580,7 +586,7 @@ public class Interpreter extends ParserV Object right = node.jjtGetChild(1).jjtAccept(this, data); try { Object result = callOperator(node, Operator.DIVIDE, left, right); - return result != JexlEngine.TRY_FAILED? result : arithmetic.divide(left, right); + return result != JexlEngine.TRY_FAILED ? result : arithmetic.divide(left, right); } catch (ArithmeticException xrt) { if (!strictArithmetic) { return 0.0d; @@ -650,9 +656,9 @@ public class Interpreter extends ParserV try { // execute statement result = statement.jjtAccept(this, data); - } catch(JexlException.Break stmtBreak) { + } catch (JexlException.Break stmtBreak) { break; - } catch(JexlException.Continue stmtContinue) { + } catch (JexlException.Continue stmtContinue) { //continue; } } @@ -909,10 +915,10 @@ public class Interpreter extends ParserV Object left = node.jjtGetChild(0).jjtAccept(this, data); Object right = node.jjtGetChild(1).jjtAccept(this, data); try { - Object result = callOperator(node, Operator.LTE, left, right); - return result != JexlEngine.TRY_FAILED - ? result - : arithmetic.lessThanOrEqual(left, right) ? Boolean.TRUE : Boolean.FALSE; + Object result = callOperator(node, Operator.LTE, left, right); + return result != JexlEngine.TRY_FAILED + ? result + : arithmetic.lessThanOrEqual(left, right) ? Boolean.TRUE : Boolean.FALSE; } catch (ArithmeticException xrt) { throw new JexlException(node, "<= error", xrt); } @@ -923,10 +929,10 @@ public class Interpreter extends ParserV Object left = node.jjtGetChild(0).jjtAccept(this, data); Object right = node.jjtGetChild(1).jjtAccept(this, data); try { - Object result = callOperator(node, Operator.LT, left, right); - return result != JexlEngine.TRY_FAILED - ? result - : arithmetic.lessThan(left, right) ? Boolean.TRUE : Boolean.FALSE; + Object result = callOperator(node, Operator.LT, left, right); + return result != JexlEngine.TRY_FAILED + ? result + : arithmetic.lessThan(left, right) ? Boolean.TRUE : Boolean.FALSE; } catch (ArithmeticException xrt) { throw new JexlException(node, "< error", xrt); } @@ -987,7 +993,7 @@ public class Interpreter extends ParserV Object right = node.jjtGetChild(1).jjtAccept(this, data); try { Object result = callOperator(node, Operator.MOD, left, right); - return result != JexlEngine.TRY_FAILED? result : arithmetic.mod(left, right); + return result != JexlEngine.TRY_FAILED ? result : arithmetic.mod(left, right); } catch (ArithmeticException xrt) { if (!strictArithmetic) { return 0.0d; @@ -1003,7 +1009,7 @@ public class Interpreter extends ParserV Object right = node.jjtGetChild(1).jjtAccept(this, data); try { Object result = callOperator(node, Operator.MULTIPLY, left, right); - return result != JexlEngine.TRY_FAILED? result : arithmetic.multiply(left, right); + return result != JexlEngine.TRY_FAILED ? result : arithmetic.multiply(left, right); } catch (ArithmeticException xrt) { JexlNode xnode = findNullOperand(xrt, node, left, right); throw new JexlException(xnode, "* error", xrt); @@ -1016,7 +1022,7 @@ public class Interpreter extends ParserV Object right = node.jjtGetChild(1).jjtAccept(this, data); try { Object result = callOperator(node, Operator.EQ, left, right); - return result != JexlEngine.TRY_FAILED + return result != JexlEngine.TRY_FAILED ? arithmetic.toBoolean(result) ? Boolean.FALSE : Boolean.TRUE : arithmetic.equals(left, right) ? Boolean.FALSE : Boolean.TRUE; } catch (ArithmeticException xrt) { @@ -1116,7 +1122,7 @@ public class Interpreter extends ParserV if (result != JexlEngine.TRY_FAILED) { return result; } - Object number = result != JexlEngine.TRY_FAILED? result : arithmetic.negate(val); + Object number = result != JexlEngine.TRY_FAILED ? result : arithmetic.negate(val); // attempt to recoerce to literal class if (valNode instanceof ASTNumberLiteral && number instanceof Number) { number = arithmetic.narrowNumber((Number) number, ((ASTNumberLiteral) valNode).getLiteralClass()); @@ -1140,9 +1146,9 @@ public class Interpreter extends ParserV try { // execute statement result = node.jjtGetChild(1).jjtAccept(this, data); - } catch(JexlException.Break stmtBreak) { + } catch (JexlException.Break stmtBreak) { break; - } catch(JexlException.Continue stmtContinue) { + } catch (JexlException.Continue stmtContinue) { //continue; } } @@ -1203,7 +1209,16 @@ public class Interpreter extends ParserV return opcall; } if (object instanceof Number) { - return ((Number) object).intValue() == 0 ? Boolean.TRUE : Boolean.FALSE; + Number number = (Number) object; + if (number instanceof Double) { + double value = number.doubleValue(); + return value == 0. || Double.isNaN(value) ? Boolean.TRUE : Boolean.FALSE; + } + if (number instanceof Float) { + float value = number.floatValue(); + return value == 0. || Float.isNaN(value) ? Boolean.TRUE : Boolean.FALSE; + } + return number.intValue() == 0 ? Boolean.TRUE : Boolean.FALSE; } if (object instanceof String) { return "".equals(object) ? Boolean.TRUE : Boolean.FALSE; @@ -1249,18 +1264,18 @@ public class Interpreter extends ParserV if (opcall != JexlEngine.TRY_FAILED) { return opcall; } - if (object instanceof Collection<?>) { - return ((Collection<?>) object).size(); + if (object instanceof String) { + return ((String) object).length(); } if (object.getClass().isArray()) { return Array.getLength(object); } + if (object instanceof Collection<?>) { + return ((Collection<?>) object).size(); + } if (object instanceof Map<?, ?>) { return ((Map<?, ?>) object).size(); } - if (object instanceof String) { - return ((String) object).length(); - } // check if there is a size method on the object that returns an // integer and if so, just use it JexlMethod vm = uberspect.getMethod(object, "size", EMPTY_PARAMS); @@ -1615,7 +1630,8 @@ public class Interpreter extends ParserV /** * Calls a method (or function). - * <p> Method resolution is a follows: + * <p> + * Method resolution is a follows: * 1 - attempt to find a method in the bean passed as parameter; * 3 - if this fails, seeks a JexlScript or JexlMethod as a property of that bean; * 2 - if this fails, narrow the arguments and try again @@ -1710,7 +1726,7 @@ public class Interpreter extends ParserV } else { return unsolvableMethod(node, methodName); } - } catch(JexlException.Method xmethod) { + } catch (JexlException.Method xmethod) { throw xmethod; } catch (Exception xany) { xjexl = new JexlException(node, methodName, xany); @@ -1784,7 +1800,7 @@ public class Interpreter extends ParserV node.jjtSetValue(ctor); } return instance; - } catch(JexlException.Method xmethod) { + } catch (JexlException.Method xmethod) { throw xmethod; } catch (Exception xany) { String dbgStr = cobject != null ? cobject.toString() : null; @@ -1830,7 +1846,8 @@ public class Interpreter extends ParserV } } } - JexlException xjexl = null; + // resolve that property + Exception xcause = null; JexlPropertyGet vg = uberspect.getPropertyGet(object, attribute); if (vg != null) { try { @@ -1841,27 +1858,20 @@ public class Interpreter extends ParserV } return value; } catch (Exception xany) { - String attrStr = attribute != null ? attribute.toString() : null; - return unsolvableProperty(node, attrStr, xany); + xcause = xany; } } - if (xjexl == null) { - if (node == null) { - String error = "unable to get object property" - + ", class: " + object.getClass().getName() - + ", property: " + attribute; - throw new UnsupportedOperationException(error); - } + // lets fail + if (node != null) { String attrStr = attribute != null ? attribute.toString() : null; - return unsolvableProperty(node, attrStr, null); - } - if (strictEngine) { - throw xjexl; - } - if (!silent) { - logger.warn(xjexl.getMessage()); + return unsolvableProperty(node, attrStr, xcause); + } else { + // direct call + String error = "unable to get object property" + + ", class: " + object.getClass().getName() + + ", property: " + attribute; + throw new UnsupportedOperationException(error, xcause); } - return null; } /** @@ -1898,7 +1908,7 @@ public class Interpreter extends ParserV } } } - JexlException xjexl = null; + Exception xcause = null; JexlPropertySet vs = uberspect.getPropertySet(object, attribute, value); // if we can't find an exact match, narrow the value argument and try again if (vs == null) { @@ -1917,35 +1927,20 @@ public class Interpreter extends ParserV } return; } catch (Exception xany) { - if (node == null) { - if (xany instanceof RuntimeException) { - throw (RuntimeException) xany; - } else { - throw new RuntimeException(xany); - } - } - String attrStr = attribute != null ? attribute.toString() : null; - unsolvableProperty(node, attrStr, xany); - return; + xcause = xany; } } - if (xjexl == null) { - if (node == null) { - String error = "unable to set object property" - + ", class: " + object.getClass().getName() - + ", property: " + attribute - + ", argument: " + value.getClass().getSimpleName(); - throw new UnsupportedOperationException(error); - } + // lets fail + if (node != null) { String attrStr = attribute != null ? attribute.toString() : null; - unsolvableProperty(node, attrStr, null); - return; - } - if (strictEngine) { - throw xjexl; - } - if (!silent) { - logger.warn(xjexl.getMessage()); + unsolvableProperty(node, attrStr, xcause); + } else { + // direct call + String error = "unable to set object property" + + ", class: " + object.getClass().getName() + + ", property: " + attribute + + ", argument: " + value.getClass().getSimpleName(); + throw new UnsupportedOperationException(error, xcause); } } } 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=1684706&r1=1684705&r2=1684706&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 Jun 10 16:30:16 2015 @@ -36,7 +36,7 @@ public class Script implements JexlScrip */ protected final Engine jexl; /** - * Original expression stripped from leading & trailing spaces. + * Original expression stripped from leading and trailing spaces. */ protected final String source; /** 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=1684706&r1=1684705&r2=1684706&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 Jun 10 16:30:16 2015 @@ -292,17 +292,17 @@ public final class TemplateEngine extend * Prepares a sub-expression for interpretation. * @param interpreter a JEXL interpreter * @return a prepared unified expression - * @throws JexlException (only for nested & composite) + * @throws JexlException (only for nested and composite) */ protected TemplateExpression prepare(Interpreter interpreter) { return this; } /** - * Intreprets a sub-expression. + * Interprets a sub-expression. * @param interpreter a JEXL interpreter * @return the result of interpretation - * @throws JexlException (only for nested & composite) + * @throws JexlException (only for nested and composite) */ protected abstract Object evaluate(Interpreter interpreter); } Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/ArrayListWrapper.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/ArrayListWrapper.java?rev=1684706&r1=1684705&r2=1684706&view=diff ============================================================================== --- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/ArrayListWrapper.java (original) +++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/ArrayListWrapper.java Wed Jun 10 16:30:16 2015 @@ -23,8 +23,9 @@ import java.util.RandomAccess; /** * A class that wraps an array within an AbstractList. * <p> - * It overrides all methods because introspection uses this class a a marker for wrapped arrays; the declared class - * for any method is thus always ArrayListWrapper. + * It overrides some methods because introspection uses this class a a marker for wrapped arrays; the declared class + * for these method is thus ArrayListWrapper. + * The methods are get/set/size/contains and indexOf because it is used by contains. * </p> */ public class ArrayListWrapper extends AbstractList<Object> implements RandomAccess { @@ -63,33 +64,6 @@ public class ArrayListWrapper extends Ab } @Override - public Object[] toArray() { - final int size = size(); - Object[] a = new Object[size]; - for(int i = 0; i < size; ++i) { - a[i] = get(i); - } - return a; - } - - @Override - @SuppressWarnings("unchecked") - public <T> T[] toArray(T[] a) { - final int size = size(); - if (a.length < size) { - T[] x = (T[]) Array.newInstance(a.getClass().getComponentType(), size); - System.arraycopy(a, a.length, x, 0, a.length); - } - for(int i = 0; i < size; ++i) { - a[i] = (T) get(i); - } - if (a.length > size) { - a[size] = null; - } - return a; - } - - @Override public int indexOf(Object o) { final int size = size(); if (o == null) { Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/ClassMap.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/ClassMap.java?rev=1684706&r1=1684705&r2=1684706&view=diff ============================================================================== --- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/ClassMap.java (original) +++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/ClassMap.java Wed Jun 10 16:30:16 2015 @@ -63,12 +63,12 @@ final class ClassMap { * This is the cache to store and look up the method information. * <p> * It stores the association between: - * - a key made of a method name & an array of argument types. + * - a key made of a method name and an array of argument types. * - a method. * </p> * <p> * Since the invocation of the associated method is dynamic, there is no need (nor way) to differentiate between - * foo(int,int) & foo(Integer,Integer) since in practise, only the latter form will be used through a call. + * foo(int,int) and foo(Integer,Integer) since in practise, only the latter form will be used through a call. * This of course, applies to all 8 primitive types. * </p> * Uses ConcurrentMap since 3.0, marginally faster than 2.1 under contention. Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/MethodKey.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/MethodKey.java?rev=1684706&r1=1684705&r2=1684706&view=diff ============================================================================== --- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/MethodKey.java (original) +++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/MethodKey.java Wed Jun 10 16:30:16 2015 @@ -42,7 +42,7 @@ import java.util.Map; * </p> * A key can be constructed either from arguments (array of objects) or from parameters * (array of class). - * Roughly 3x faster than string key to access the map & uses less memory. + * Roughly 3x faster than string key to access the map and uses less memory. */ public final class MethodKey { /** The initial size of the primitive conversion map. */ Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/PropertyGetExecutor.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/PropertyGetExecutor.java?rev=1684706&r1=1684705&r2=1684706&view=diff ============================================================================== --- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/PropertyGetExecutor.java (original) +++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/PropertyGetExecutor.java Wed Jun 10 16:30:16 2015 @@ -81,7 +81,7 @@ public final class PropertyGetExecutor e } /** - * Base method for boolean & object property get. + * Base method for boolean and object property get. * @param is the introspector * @param which "is" or "get" for boolean or object * @param clazz The class being examined. Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/Uberspect.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/Uberspect.java?rev=1684706&r1=1684705&r2=1684706&view=diff ============================================================================== --- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/Uberspect.java (original) +++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/Uberspect.java Wed Jun 10 16:30:16 2015 @@ -53,7 +53,7 @@ public class Uberspect implements JexlUb * Publicly exposed special failure object returned by tryInvoke. */ public static final Object TRY_FAILED = JexlEngine.TRY_FAILED; - /** The logger to use for all warnings & errors. */ + /** The logger to use for all warnings and errors. */ protected final Logger rlog; /** The introspector version. */ private final AtomicInteger version; Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ASTIdentifierAccess.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ASTIdentifierAccess.java?rev=1684706&r1=1684705&r2=1684706&view=diff ============================================================================== --- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ASTIdentifierAccess.java (original) +++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ASTIdentifierAccess.java Wed Jun 10 16:30:16 2015 @@ -33,11 +33,39 @@ public final class ASTIdentifierAccess e void setIdentifier(String id) { name = id; - try { - identifier = Integer.valueOf(id); - } catch(NumberFormatException xnumber) { - identifier = null; + identifier = parseIdentifier(id); + } + + /** + * Parse an identifier which must be of the form: + * 0|([1-9][0-9]*) + * @param id the identifier + * @return an integer or null + */ + private static Integer parseIdentifier(String id) { + // hand coded because the was no way to fail on leading '0's using NumberFormat + if (id != null) { + final int length = id.length(); + int val = 0; + for (int i = 0; i < length; ++i) { + char c = id.charAt(i); + // leading 0s but no just 0, NaN + if (c == '0') { + if (length == 1) { + return 0; + } else if (val == 0) { + return null; + } + } // any non numeric, NaN + else if (c < '0' || c > '9') { + return null; + } + val *= 10; + val += (c - '0'); + } + return val; } + return null; } public Object getIdentifier() { Modified: commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ArithmeticOperatorTest.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ArithmeticOperatorTest.java?rev=1684706&r1=1684705&r2=1684706&view=diff ============================================================================== --- commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ArithmeticOperatorTest.java (original) +++ commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ArithmeticOperatorTest.java Wed Jun 10 16:30:16 2015 @@ -26,6 +26,9 @@ import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; import org.apache.commons.jexl3.junit.Asserter; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; /** * Tests for the startsWith, endsWith, match and range operators. @@ -34,6 +37,7 @@ import org.apache.commons.jexl3.junit.As public class ArithmeticOperatorTest extends JexlTestCase { private Asserter asserter; + @Before @Override public void setUp() { asserter = new Asserter(JEXL); @@ -44,10 +48,11 @@ public class ArithmeticOperatorTest exte * Create the named test. * @param name test name */ - public ArithmeticOperatorTest(String name) { - super(name); + public ArithmeticOperatorTest() { + super("ArithmeticOperatorTest"); } + @Test public void testRegexp() throws Exception { asserter.setVariable("str", "abc456"); asserter.assertExpression("str =~ '.*456'", Boolean.TRUE); @@ -71,6 +76,7 @@ public class ArithmeticOperatorTest exte asserter.assertExpression("'z' !~ ['a','b','c','d','e','f']", Boolean.TRUE); } + @Test public void testStartsEndsWithString() throws Exception { asserter.setVariable("x", "foobar"); asserter.assertExpression("x =^ 'foo'", Boolean.TRUE); @@ -80,6 +86,7 @@ public class ArithmeticOperatorTest exte asserter.assertExpression("x =$ 'foo'", Boolean.TRUE); } + @Test public void testNotStartsEndsWithString() throws Exception { asserter.setVariable("x", "foobar"); asserter.assertExpression("x !^ 'foo'", Boolean.FALSE); @@ -149,6 +156,7 @@ public class ArithmeticOperatorTest exte } } + @Test public void testMatch() throws Exception { // check in/not-in on array, list, map, set and duck-type collection int[] ai = {2, 4, 42, 54}; @@ -177,6 +185,7 @@ public class ArithmeticOperatorTest exte } } + @Test public void testStartsEndsWith() throws Exception { asserter.setVariable("x", "foobar"); asserter.assertExpression("x =^ 'foo'", Boolean.TRUE); @@ -196,6 +205,7 @@ public class ArithmeticOperatorTest exte asserter.assertExpression("x =^ [42, 54]", Boolean.TRUE); } + @Test public void testNotStartsEndsWith() throws Exception { asserter.setVariable("x", "foobar"); asserter.assertExpression("x !^ 'foo'", Boolean.FALSE); @@ -226,6 +236,7 @@ public class ArithmeticOperatorTest exte } } + @Test @SuppressWarnings("unchecked") public void testInterval() throws Exception { Map<String, Object> ns = new HashMap<String, Object>(); @@ -236,33 +247,33 @@ public class ArithmeticOperatorTest exte script = jexl.createScript("1 .. 3"); result = script.execute(null); - assertTrue(result instanceof Iterable<?>); + Assert.assertTrue(result instanceof Iterable<?>); Iterator<Integer> ii = ((Iterable<Integer>) result).iterator(); - assertEquals(Integer.valueOf(1), ii.next()); - assertEquals(Integer.valueOf(2), ii.next()); - assertEquals(Integer.valueOf(3), ii.next()); - assertNull(ii.next()); + Assert.assertEquals(Integer.valueOf(1), ii.next()); + Assert.assertEquals(Integer.valueOf(2), ii.next()); + Assert.assertEquals(Integer.valueOf(3), ii.next()); + Assert.assertNull(ii.next()); script = jexl.createScript("(4 - 3) .. (9 / 3)"); result = script.execute(null); - assertTrue(result instanceof Iterable<?>); + Assert.assertTrue(result instanceof Iterable<?>); ii = ((Iterable<Integer>) result).iterator(); - assertEquals(Integer.valueOf(1), ii.next()); - assertEquals(Integer.valueOf(2), ii.next()); - assertEquals(Integer.valueOf(3), ii.next()); - assertNull(ii.next()); + Assert.assertEquals(Integer.valueOf(1), ii.next()); + Assert.assertEquals(Integer.valueOf(2), ii.next()); + Assert.assertEquals(Integer.valueOf(3), ii.next()); + Assert.assertNull(ii.next()); // sum of 1, 2, 3 script = jexl.createScript("var x = 0; for(var y : ((5 - 4) .. (12 / 4))) { x = x + y }; x"); result = script.execute(null); - assertEquals(Integer.valueOf(6), result); + Assert.assertEquals(Integer.valueOf(6), result); script = jexl.createScript("calc:sum(1 .. 3)"); result = script.execute(null); - assertEquals(Integer.valueOf(6), result); + Assert.assertEquals(Integer.valueOf(6), result); script = jexl.createScript("calc:sum(-3 .. 3)"); result = script.execute(null); - assertEquals(Integer.valueOf(0), result); + Assert.assertEquals(Integer.valueOf(0), result); } } 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=1684706&r1=1684705&r2=1684706&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 Wed Jun 10 16:30:16 2015 @@ -23,23 +23,30 @@ import java.util.Map; import java.math.BigDecimal; import java.math.BigInteger; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +@SuppressWarnings({"UnnecessaryBoxing", "AssertEqualsBetweenInconvertibleTypes"}) public class ArithmeticTest extends JexlTestCase { - private Asserter asserter; + private final Asserter asserter; public ArithmeticTest() { super("ArithmeticTest"); asserter = new Asserter(JEXL); } + @Before @Override public void setUp() { } + @Test public void testUndefinedVar() throws Exception { asserter.failExpression("objects[1].status", ".* undefined variable objects.*"); } + @Test public void testLeftNullOperand() throws Exception { asserter.setVariable("left", null); asserter.setVariable("right", Integer.valueOf(8)); @@ -54,6 +61,7 @@ public class ArithmeticTest extends Jexl asserter.failExpression("left ^ right", ".*null.*"); } + @Test public void testRightNullOperand() throws Exception { asserter.setVariable("left", Integer.valueOf(9)); asserter.setVariable("right", null); @@ -67,6 +75,7 @@ public class ArithmeticTest extends Jexl asserter.failExpression("left ^ right", ".*null.*"); } + @Test public void testNullOperands() throws Exception { asserter.setVariable("left", null); asserter.setVariable("right", null); @@ -80,11 +89,13 @@ public class ArithmeticTest extends Jexl asserter.failExpression("left ^ right", ".*null.*"); } + @Test public void testNullOperand() throws Exception { asserter.setVariable("right", null); asserter.failExpression("~right", ".*null.*"); } + @Test public void testBigDecimal() throws Exception { asserter.setVariable("left", new BigDecimal(2)); asserter.setVariable("right", new BigDecimal(6)); @@ -95,6 +106,7 @@ public class ArithmeticTest extends Jexl asserter.assertExpression("right % left", new BigDecimal(0)); } + @Test public void testBigInteger() throws Exception { asserter.setVariable("left", new BigInteger("2")); asserter.setVariable("right", new BigInteger("6")); @@ -108,6 +120,7 @@ public class ArithmeticTest extends Jexl /** * test some simple mathematical calculations */ + @Test public void testUnaryMinus() throws Exception { asserter.setVariable("aByte", new Byte((byte) 1)); asserter.setVariable("aShort", new Short((short) 2)); @@ -133,6 +146,7 @@ public class ArithmeticTest extends Jexl /** * test some simple mathematical calculations */ + @Test public void testCalculations() throws Exception { asserter.setStrict(true, false); /* @@ -175,6 +189,7 @@ public class ArithmeticTest extends Jexl } + @Test public void testCoercions() throws Exception { asserter.assertExpression("1", new Integer(1)); // numerics default to Integer asserter.assertExpression("5L", new Long(5)); @@ -207,50 +222,75 @@ public class ArithmeticTest extends Jexl } // JEXL-24: long integers (and doubles) + @Test public void testLongLiterals() throws Exception { JexlEvalContext ctxt = new JexlEvalContext(); ctxt.setStrictArithmetic(true); String stmt = "{a = 10L; b = 10l; c = 42.0D; d = 42.0d; e=56.3F; f=56.3f; g=63.5; h=0x10; i=010; j=0x10L; k=010l}"; JexlScript expr = JEXL.createScript(stmt); /* Object value = */ expr.execute(ctxt); - assertEquals(10L, ctxt.get("a")); - assertEquals(10l, ctxt.get("b")); - assertEquals(42.0D, ctxt.get("c")); - assertEquals(42.0d, ctxt.get("d")); - assertEquals(56.3f, ctxt.get("e")); - assertEquals(56.3f, ctxt.get("f")); - assertEquals(63.5d, ctxt.get("g")); - assertEquals(0x10, ctxt.get("h")); - assertEquals(010, ctxt.get("i")); - assertEquals(0x10L, ctxt.get("j")); - assertEquals(010l, ctxt.get("k")); + Assert.assertEquals(10L, ctxt.get("a")); + Assert.assertEquals(10l, ctxt.get("b")); + Assert.assertEquals(42.0D, ctxt.get("c")); + Assert.assertEquals(42.0d, ctxt.get("d")); + Assert.assertEquals(56.3f, ctxt.get("e")); + Assert.assertEquals(56.3f, ctxt.get("f")); + Assert.assertEquals(63.5d, ctxt.get("g")); + Assert.assertEquals(0x10, ctxt.get("h")); + Assert.assertEquals(010, ctxt.get("i")); + Assert.assertEquals(0x10L, ctxt.get("j")); + Assert.assertEquals(010l, ctxt.get("k")); + } + + @Test + public void testBigLiteralValue() throws Exception { + JexlEvalContext ctxt = new JexlEvalContext(); + ctxt.setStrictArithmetic(true); + JexlExpression e = JEXL.createExpression("9223372036854775806.5B"); + String res = String.valueOf(e.evaluate(ctxt)); + Assert.assertEquals("9223372036854775806.5", res); + } + + @Test + public void testBigdOp() throws Exception { + BigDecimal sevendot475 = new BigDecimal("7.475"); + BigDecimal SO = new BigDecimal("325"); + JexlContext jc = new MapContext(); + jc.set("SO", SO); + + String expr = "2.3*SO/100"; + + Object evaluate = JEXL.createExpression(expr).evaluate(jc); + Assert.assertEquals(sevendot475, (BigDecimal) evaluate); } // JEXL-24: big integers and big decimals + @Test public void testBigLiterals() throws Exception { JexlEvalContext ctxt = new JexlEvalContext(); ctxt.setStrictArithmetic(true); String stmt = "{a = 10H; b = 10h; c = 42.0B; d = 42.0b;}"; JexlScript expr = JEXL.createScript(stmt); /* Object value = */ expr.execute(ctxt); - assertEquals(new BigInteger("10"), ctxt.get("a")); - assertEquals(new BigInteger("10"), ctxt.get("b")); - assertEquals(new BigDecimal("42.0"), ctxt.get("c")); - assertEquals(new BigDecimal("42.0"), ctxt.get("d")); + Assert.assertEquals(new BigInteger("10"), ctxt.get("a")); + Assert.assertEquals(new BigInteger("10"), ctxt.get("b")); + Assert.assertEquals(new BigDecimal("42.0"), ctxt.get("c")); + Assert.assertEquals(new BigDecimal("42.0"), ctxt.get("d")); } // JEXL-24: big decimals with exponent + @Test public void testBigExponentLiterals() throws Exception { JexlEvalContext ctxt = new JexlEvalContext(); ctxt.setStrictArithmetic(true); String stmt = "{a = 42.0e1B; b = 42.0E+2B; c = 42.0e-1B; d = 42.0E-2b; e=4242.4242e1b}"; JexlScript expr = JEXL.createScript(stmt); /* Object value = */ expr.execute(ctxt); - assertEquals(new BigDecimal("42.0e+1"), ctxt.get("a")); - assertEquals(new BigDecimal("42.0e+2"), ctxt.get("b")); - assertEquals(new BigDecimal("42.0e-1"), ctxt.get("c")); - assertEquals(new BigDecimal("42.0e-2"), ctxt.get("d")); - assertEquals(new BigDecimal("4242.4242e1"), ctxt.get("e")); + Assert.assertEquals(new BigDecimal("42.0e+1"), ctxt.get("a")); + Assert.assertEquals(new BigDecimal("42.0e+2"), ctxt.get("b")); + Assert.assertEquals(new BigDecimal("42.0e-1"), ctxt.get("c")); + Assert.assertEquals(new BigDecimal("42.0e-2"), ctxt.get("d")); + Assert.assertEquals(new BigDecimal("4242.4242e1"), ctxt.get("e")); } // JEXL-24: doubles with exponent @@ -260,10 +300,10 @@ public class ArithmeticTest extends Jexl String stmt = "{a = 42.0e1D; b = 42.0E+2D; c = 42.0e-1d; d = 42.0E-2d;}"; JexlScript expr = JEXL.createScript(stmt); /* Object value = */ expr.execute(ctxt); - assertEquals(Double.valueOf("42.0e+1"), ctxt.get("a")); - assertEquals(Double.valueOf("42.0e+2"), ctxt.get("b")); - assertEquals(Double.valueOf("42.0e-1"), ctxt.get("c")); - assertEquals(Double.valueOf("42.0e-2"), ctxt.get("d")); + Assert.assertEquals(Double.valueOf("42.0e+1"), ctxt.get("a")); + Assert.assertEquals(Double.valueOf("42.0e+2"), ctxt.get("b")); + Assert.assertEquals(Double.valueOf("42.0e-1"), ctxt.get("c")); + Assert.assertEquals(Double.valueOf("42.0e-2"), ctxt.get("d")); } /** @@ -272,6 +312,7 @@ public class ArithmeticTest extends Jexl * if not silent, all arith exception throw * @throws Exception */ + @Test public void testDivideByZero() throws Exception { Map<String, Object> vars = new HashMap<String, Object>(); JexlEvalContext context = new JexlEvalContext(vars); @@ -284,7 +325,6 @@ public class ArithmeticTest extends Jexl vars.put("aBigInteger", new BigInteger("7")); vars.put("aBigDecimal", new BigDecimal("8.8")); - vars.put("zByte", new Byte((byte) 0)); vars.put("zShort", new Short((short) 0)); vars.put("zInteger", new Integer(0)); @@ -332,16 +372,17 @@ public class ArithmeticTest extends Jexl } } if (strict) { - assertTrue("All expressions should have thrown " + zthrow + "/" + PERMS, + Assert.assertTrue("All expressions should have thrown " + zthrow + "/" + PERMS, zthrow == PERMS); } else { - assertTrue("All expressions should have zeroed " + zeval + "/" + PERMS, + Assert.assertTrue("All expressions should have zeroed " + zeval + "/" + PERMS, zeval == PERMS); } } debuggerCheck(jexl); } + @Test public void testNaN() throws Exception { Map<String, Object> ns = new HashMap<String, Object>(); ns.put("double", Double.class); @@ -350,16 +391,16 @@ public class ArithmeticTest extends Jexl Object result; script = jexl.createScript("#NaN"); result = script.execute(null); - assertTrue(Double.isNaN((Double) result)); + Assert.assertTrue(Double.isNaN((Double) result)); script = jexl.createScript("NaN"); result = script.execute(null); - assertTrue(Double.isNaN((Double) result)); + Assert.assertTrue(Double.isNaN((Double) result)); script = jexl.createScript("double:isNaN(#NaN)"); result = script.execute(null); - assertTrue((Boolean) result); + Assert.assertTrue((Boolean) result); script = jexl.createScript("double:isNaN(NaN)"); result = script.execute(null); - assertTrue((Boolean) result); + Assert.assertTrue((Boolean) result); } public static class EmptyTestContext extends MapContext implements JexlContext.NamespaceResolver { @@ -379,6 +420,7 @@ public class ArithmeticTest extends Jexl } } + @Test public void testEmpty() throws Exception { Object[] SCRIPTS = { "var x = null; log('x = %s', x);", 0, @@ -407,12 +449,13 @@ public class ArithmeticTest extends Jexl Object expected = SCRIPTS[e + 1]; script = jexl.createScript(stext); Object result = script.execute(jc); - assertEquals("failed on " + stext, expected, result); + Assert.assertEquals("failed on " + stext, expected, result); } } public static class Var { final int value; + Var(int v) { value = v; } @@ -423,48 +466,63 @@ public class ArithmeticTest extends Jexl public ArithmeticPlus(boolean strict) { super(strict); } + public boolean equals(Var lhs, Var rhs) { return lhs.value == rhs.value; } + public boolean lessThan(Var lhs, Var rhs) { return lhs.value < rhs.value; } + public boolean lessThanOrEqual(Var lhs, Var rhs) { return lhs.value <= rhs.value; } + public boolean greaterThan(Var lhs, Var rhs) { return lhs.value > rhs.value; } + public boolean greaterThanOrEqual(Var lhs, Var rhs) { return lhs.value >= rhs.value; } + public Var add(Var lhs, Var rhs) { return new Var(lhs.value + rhs.value); } + public Var subtract(Var lhs, Var rhs) { return new Var(lhs.value - rhs.value); } + public Var divide(Var lhs, Var rhs) { return new Var(lhs.value / rhs.value); } + public Var multiply(Var lhs, Var rhs) { return new Var(lhs.value * rhs.value); } + public Var mod(Var lhs, Var rhs) { return new Var(lhs.value / rhs.value); } + public Var negate(Var arg) { return new Var(-arg.value); } + public Var bitwiseAnd(Var lhs, Var rhs) { return new Var(lhs.value & rhs.value); } + public Var bitwiseOr(Var lhs, Var rhs) { return new Var(lhs.value | rhs.value); } + public Var bitwiseXor(Var lhs, Var rhs) { return new Var(lhs.value ^ rhs.value); } + public Var bitwiseComplement(Var arg) { return new Var(~arg.value); } @@ -482,117 +540,231 @@ public class ArithmeticTest extends Jexl public Object negate(final String str) { final int length = str.length(); StringBuilder strb = new StringBuilder(str.length()); - for(int c = length - 1; c >= 0; --c) { + for (int c = length - 1; c >= 0; --c) { strb.append(str.charAt(c)); } return strb.toString(); } } + @Test public void testArithmeticPlus() throws Exception { JexlEngine jexl = new JexlBuilder().cache(64).arithmetic(new ArithmeticPlus(false)).create(); JexlContext jc = new EmptyTestContext(); runOverload(jexl, jc); } + @Test public void testArithmeticPlusNoCache() throws Exception { JexlEngine jexl = new JexlBuilder().cache(0).arithmetic(new ArithmeticPlus(false)).create(); JexlContext jc = new EmptyTestContext(); runOverload(jexl, jc); } - protected void runOverload(JexlEngine jexl,JexlContext jc) { + protected void runOverload(JexlEngine jexl, JexlContext jc) { JexlScript script; Object result; script = jexl.createScript("(x, y)->{ x < y }"); result = script.execute(jc, 42, 43); - assertEquals(true, result); + Assert.assertEquals(true, result); result = script.execute(jc, new Var(42), new Var(43)); - assertEquals(true, result); + Assert.assertEquals(true, result); result = script.execute(jc, new Var(42), new Var(43)); - assertEquals(true, result); + Assert.assertEquals(true, result); result = script.execute(jc, 43, 42); - assertEquals(false, result); + Assert.assertEquals(false, result); result = script.execute(jc, new Var(43), new Var(42)); - assertEquals(false, result); + Assert.assertEquals(false, result); result = script.execute(jc, new Var(43), new Var(42)); - assertEquals(false, result); + Assert.assertEquals(false, result); script = jexl.createScript("(x, y)->{ x <= y }"); result = script.execute(jc, 42, 43); - assertEquals(true, result); + Assert.assertEquals(true, result); result = script.execute(jc, new Var(42), new Var(43)); - assertEquals(true, result); + Assert.assertEquals(true, result); result = script.execute(jc, new Var(41), new Var(44)); - assertEquals(true, result); + Assert.assertEquals(true, result); result = script.execute(jc, 43, 42); - assertEquals(false, result); + Assert.assertEquals(false, result); result = script.execute(jc, new Var(45), new Var(40)); - assertEquals(false, result); + Assert.assertEquals(false, result); result = script.execute(jc, new Var(46), new Var(39)); - assertEquals(false, result); + Assert.assertEquals(false, result); script = jexl.createScript("(x, y)->{ x == y }"); result = script.execute(jc, 42, 43); - assertEquals(false, result); + Assert.assertEquals(false, result); result = script.execute(jc, new Var(42), new Var(43)); - assertEquals(false, result); + Assert.assertEquals(false, result); result = script.execute(jc, new Var(41), new Var(44)); - assertEquals(false, result); + Assert.assertEquals(false, result); result = script.execute(jc, 43, 42); - assertEquals(false, result); + Assert.assertEquals(false, result); result = script.execute(jc, new Var(45), new Var(40)); - assertEquals(false, result); + Assert.assertEquals(false, result); result = script.execute(jc, new Var(46), new Var(39)); - assertEquals(false, result); + Assert.assertEquals(false, result); script = jexl.createScript("(x, y)->{ x % y }"); result = script.execute(jc, 4242, 100); - assertEquals(42, result); + Assert.assertEquals(42, result); result = script.execute(jc, new Var(4242), new Var(100)); - assertEquals(42, ((Var) result).value); + Assert.assertEquals(42, ((Var) result).value); result = script.execute(jc, new Var(4242), new Var(100)); - assertEquals(42, ((Var) result).value); + Assert.assertEquals(42, ((Var) result).value); script = jexl.createScript("(x, y)->{ x * y }"); result = script.execute(jc, 6, 7); - assertEquals(42, result); + Assert.assertEquals(42, result); result = script.execute(jc, new Var(6), new Var(7)); - assertEquals(42, ((Var) result).value); + Assert.assertEquals(42, ((Var) result).value); result = script.execute(jc, new Var(6), new Var(7)); - assertEquals(42, ((Var) result).value); + Assert.assertEquals(42, ((Var) result).value); script = jexl.createScript("(x, y)->{ x + y }"); result = script.execute(jc, 35, 7); - assertEquals(42, result); + Assert.assertEquals(42, result); result = script.execute(jc, new Var(35), new Var(7)); - assertEquals(42, ((Var) result).value); + Assert.assertEquals(42, ((Var) result).value); result = script.execute(jc, new Var(35), new Var(7)); - assertEquals(42, ((Var) result).value); + Assert.assertEquals(42, ((Var) result).value); script = jexl.createScript("(x, y)->{ x - y }"); result = script.execute(jc, 49, 7); - assertEquals(42, result); + Assert.assertEquals(42, result); result = script.execute(jc, "foobarquux", "bar"); - assertEquals("fooquux", result); + Assert.assertEquals("fooquux", result); result = script.execute(jc, 50, 8); - assertEquals(42, result); + Assert.assertEquals(42, result); result = script.execute(jc, new Var(50), new Var(8)); - assertEquals(42, ((Var) result).value); + Assert.assertEquals(42, ((Var) result).value); result = script.execute(jc, new Var(50), new Var(8)); - assertEquals(42, ((Var) result).value); + Assert.assertEquals(42, ((Var) result).value); script = jexl.createScript("(x)->{ -x }"); result = script.execute(jc, -42); - assertEquals(42, result); + Assert.assertEquals(42, result); result = script.execute(jc, new Var(-42)); - assertEquals(42, ((Var) result).value); + Assert.assertEquals(42, ((Var) result).value); result = script.execute(jc, new Var(-42)); - assertEquals(42, ((Var) result).value); + Assert.assertEquals(42, ((Var) result).value); result = script.execute(jc, "pizza"); - assertEquals("azzip", result); + Assert.assertEquals("azzip", result); result = script.execute(jc, -142); - assertEquals(142, result); + Assert.assertEquals(142, result); + } + + public static class Arithmetic132 extends JexlArithmetic { + public Arithmetic132() { + super(false); + } + + protected double divideZero(BigDecimal x) { + int ls = x.signum(); + if (ls < 0) { + return Double.NEGATIVE_INFINITY; + } else if (ls > 0) { + return Double.POSITIVE_INFINITY; + } else { + return Double.NaN; + } + } + + protected double divideZero(BigInteger x) { + int ls = x.signum(); + if (ls < 0) { + return Double.NEGATIVE_INFINITY; + } else if (ls > 0) { + return Double.POSITIVE_INFINITY; + } else { + return Double.NaN; + } + } + + @Override + public Object divide(Object left, Object right) { + if (left == null && right == null) { + return controlNullNullOperands(); + } + // if either are bigdecimal use that type + if (left instanceof BigDecimal || right instanceof BigDecimal) { + BigDecimal l = toBigDecimal(left); + BigDecimal r = toBigDecimal(right); + if (BigDecimal.ZERO.equals(r)) { + return divideZero(l); + } + BigDecimal result = l.divide(r, getMathContext()); + return narrowBigDecimal(left, right, result); + } + // if either are floating point (double or float) use double + if (isFloatingPointNumber(left) || isFloatingPointNumber(right)) { + double l = toDouble(left); + double r = toDouble(right); + return new Double(l / r); + } + // otherwise treat as integers + BigInteger l = toBigInteger(left); + BigInteger r = toBigInteger(right); + if (BigInteger.ZERO.equals(r)) { + return divideZero(l); + } + BigInteger result = l.divide(r); + return narrowBigInteger(left, right, result); + } + + @Override + public Object mod(Object left, Object right) { + if (left == null && right == null) { + return controlNullNullOperands(); + } + // if either are bigdecimal use that type + if (left instanceof BigDecimal || right instanceof BigDecimal) { + BigDecimal l = toBigDecimal(left); + BigDecimal r = toBigDecimal(right); + if (BigDecimal.ZERO.equals(r)) { + return divideZero(l); + } + BigDecimal remainder = l.remainder(r, getMathContext()); + return narrowBigDecimal(left, right, remainder); + } + // if either are floating point (double or float) use double + if (isFloatingPointNumber(left) || isFloatingPointNumber(right)) { + double l = toDouble(left); + double r = toDouble(right); + return new Double(l % r); + } + // otherwise treat as integers + BigInteger l = toBigInteger(left); + BigInteger r = toBigInteger(right); + BigInteger result = l.mod(r); + if (BigInteger.ZERO.equals(r)) { + return divideZero(l); + } + return narrowBigInteger(left, right, result); + } + } + + @Test + public void testInfiniteArithmetic() throws Exception { + Map<String, Object> ns = new HashMap<String, Object>(); + ns.put("math", Math.class); + JexlEngine jexl = new JexlBuilder().arithmetic(new Arithmetic132()).namespaces(ns).create(); + + Object evaluate = jexl.createExpression("1/0").evaluate(null); + Assert.assertTrue(Double.isInfinite((Double) evaluate)); + + evaluate = jexl.createExpression("-1/0").evaluate(null); + Assert.assertTrue(Double.isInfinite((Double) evaluate)); + + evaluate = jexl.createExpression("1.0/0.0").evaluate(null); + Assert.assertTrue(Double.isInfinite((Double) evaluate)); + + evaluate = jexl.createExpression("-1.0/0.0").evaluate(null); + Assert.assertTrue(Double.isInfinite((Double) evaluate)); + + evaluate = jexl.createExpression("math:abs(-42)").evaluate(null); + Assert.assertEquals(42, evaluate); } -} \ No newline at end of file +} Modified: commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ArrayAccessTest.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ArrayAccessTest.java?rev=1684706&r1=1684705&r2=1684706&view=diff ============================================================================== --- commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ArrayAccessTest.java (original) +++ commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ArrayAccessTest.java Wed Jun 10 16:30:16 2015 @@ -22,6 +22,7 @@ import java.util.List; import java.util.Map; import org.apache.commons.jexl3.junit.Asserter; +import org.junit.Before; /** @@ -48,6 +49,7 @@ public class ArrayAccessTest extends Jex } @Override + @Before public void setUp() { asserter = new Asserter(JEXL); } @@ -146,6 +148,18 @@ public class ArrayAccessTest extends Jex asserter.assertExpression("base.objects.1.status", null); } + public void testArrayIdentifierParsing() throws Exception { + Map<Object, Number> map = new HashMap<Object, Number>(); + map.put("00200", -42.42d); + map.put(200, 42.42d); + asserter.setVariable("objects", map); + asserter.assertExpression("objects.get('00200')", -42.42d); + asserter.assertExpression("objects.'00200'", -42.42d); + asserter.assertExpression("objects.get(200)", 42.42d); + asserter.assertExpression("objects.'200'", 42.42d); + asserter.assertExpression("objects.200", 42.42d); + } + public void testArrayMethods() throws Exception { Object[] objects = new Object[] {"an", "array", new Long(0)};