Author: henrib Date: Tue May 1 20:21:10 2012 New Revision: 1332806 URL: http://svn.apache.org/viewvc?rev=1332806&view=rev Log: Fix for JEXL-131; modified the code as mentioned in the mailing list thread. (http://apache-commons.680414.n4.nabble.com/jexl-Unified-jexl-throws-exception-when-processing-white-space-in-file-tt4578778.html); Fix for method exception not being reported correctly, backport of jexl3 behavior; Fix for variable/property existence versus null operands raising the correct exceptions: added separate strict flag to JexlEngine so JexlArithmetic can have its own , backport of jexl3 behavior. Fix for decimal number constants not defaulting to "double" behavior ( aka Grace's JEXL-126 fixed in jexl3 backport); Modified pom for 2.1.2-SNAPSHOT;
Added: commons/proper/jexl/branches/2.0/src/test/java/org/apache/commons/jexl2/ExceptionTest.java - copied, changed from r1332642, commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ExceptionTest.java Modified: commons/proper/jexl/branches/2.0/pom.xml commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl2/Interpreter.java commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl2/JexlArithmetic.java commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl2/JexlEngine.java commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl2/JexlException.java commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl2/ObjectContext.java commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl2/UnifiedJEXL.java commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl2/parser/ASTNumberLiteral.java commons/proper/jexl/branches/2.0/src/test/java/org/apache/commons/jexl2/ArithmeticTest.java commons/proper/jexl/branches/2.0/src/test/java/org/apache/commons/jexl2/ArrayLiteralTest.java commons/proper/jexl/branches/2.0/src/test/java/org/apache/commons/jexl2/IssuesTest.java Modified: commons/proper/jexl/branches/2.0/pom.xml URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/pom.xml?rev=1332806&r1=1332805&r2=1332806&view=diff ============================================================================== --- commons/proper/jexl/branches/2.0/pom.xml (original) +++ commons/proper/jexl/branches/2.0/pom.xml Tue May 1 20:21:10 2012 @@ -19,12 +19,12 @@ <parent> <groupId>org.apache.commons</groupId> <artifactId>commons-parent</artifactId> - <version>22</version> + <version>25</version> </parent> <modelVersion>4.0.0</modelVersion> <groupId>org.apache.commons</groupId> <artifactId>commons-jexl</artifactId> - <version>2.1.1-SNAPSHOT</version> + <version>2.1.2-SNAPSHOT</version> <name>Commons JEXL</name> <inceptionYear>2001</inceptionYear> <description>The Commons Jexl library is an implementation of the JSTL Expression Language with extensions.</description> Modified: commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl2/Interpreter.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl2/Interpreter.java?rev=1332806&r1=1332805&r2=1332806&view=diff ============================================================================== --- commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl2/Interpreter.java (original) +++ commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl2/Interpreter.java Tue May 1 20:21:10 2012 @@ -107,7 +107,7 @@ public class Interpreter implements Pars protected final JexlContext context; /** Strict interpreter flag. Do not modify; will be made final/private in a later version. */ protected boolean strict; - /** Silent intepreter flag. Do not modify; will be made final/private in a later version. */ + /** Silent intepreter flag. Do not modify; will be made final/private in a later version. */ protected boolean silent; /** Cache executors. */ protected final boolean cache; @@ -116,26 +116,24 @@ public class Interpreter implements Pars /** * Parameter names if any. * Intended for use in debugging; not currently used externally. - * @since 2.1 + * @since 2.1 */ @SuppressWarnings("unused") private String[] parameters = null; - - /** + /** * Cancellation support. * @see #isCancelled() * @since 2.1 */ private volatile boolean cancelled = false; - /** Empty parameters for method matching. */ protected static final Object[] EMPTY_PARAMS = new Object[0]; /** * Creates an interpreter. - * @param jexl the engine creating this interpreter + * @param jexl the engine creating this interpreter * @param aContext the context to evaluate expression - * @deprecated + * @deprecated */ @Deprecated public Interpreter(JexlEngine jexl, JexlContext aContext) { @@ -144,8 +142,8 @@ public class Interpreter implements Pars /** * Creates an interpreter. - * @param jexl the engine creating this interpreter - * @param aContext the context to evaluate expression + * @param jexl the engine creating this interpreter + * @param aContext the context to evaluate expression * @param strictFlag whether this interpreter runs in strict mode * @param silentFlag whether this interpreter runs in silent mode * @since 2.1 @@ -158,7 +156,7 @@ public class Interpreter implements Pars this.strict = strictFlag; this.silent = silentFlag; this.cache = jexl.cache != null; - this.context = aContext != null? aContext : JexlEngine.EMPTY_CONTEXT; + this.context = aContext != null ? aContext : JexlEngine.EMPTY_CONTEXT; this.functors = null; } @@ -178,12 +176,12 @@ public class Interpreter implements Pars this.context = base.context; this.functors = base.functors; } - + /** * Sets whether this interpreter considers unknown variables, methods and constructors as errors. * @param flag true for strict, false for lenient * @deprecated Do not use; will be removed in a later version - * @since 2.1 + * @since 2.1 */ // TODO why add a method and then deprecate it? @Deprecated @@ -245,7 +243,7 @@ public class Interpreter implements Pars registers = null; } } - + /** * Gets the context. * @return the {@link JexlContext} used for evaluation. @@ -297,9 +295,9 @@ public class Interpreter implements Pars /** * Finds the node causing a NPE for diadic operators. - * @param xrt the RuntimeException - * @param node the parent node - * @param left the left argument + * @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 */ @@ -363,7 +361,7 @@ public class Interpreter implements Pars * The lifetime of such instances span the current expression or script evaluation. * * @param prefix the prefix name (may be null for global namespace) - * @param node the AST node + * @param node the AST node * @return the namespace instance */ protected Object resolveNamespace(String prefix, JexlNode node) { @@ -998,10 +996,10 @@ public class Interpreter implements Pars * 2 - if this fails, narrow the arguments and try again * 3 - if this still fails, seeks a Script or JexlMethod as a property of that bean. * </p> - * @param node the method node - * @param bean the bean this method should be invoked upon + * @param node the method node + * @param bean the bean this method should be invoked upon * @param methodNode the node carrying the method name - * @param argb the first argument index, child of the method node + * @param argb the first argument index, child of the method node * @return the result of the method invocation */ private Object call(JexlNode node, Object bean, ASTIdentifier methodNode, int argb) { @@ -1059,7 +1057,7 @@ public class Interpreter implements Pars vm = (JexlMethod) functor; cacheable = false; } else { - xjexl = new JexlException.Method(node, methodName); + xjexl = new JexlException.Method(node, methodName, null); } } } @@ -1072,10 +1070,10 @@ public class Interpreter implements Pars } return eval; } - } catch (InvocationTargetException e) { - xjexl = new JexlException(node, "method invocation error", e.getCause()); - } catch (Exception e) { - xjexl = new JexlException(node, "method error", e); + } catch (JexlException xany) { + xjexl = xany; + } catch (Exception xany) { + xjexl = new JexlException.Method(node, methodName, xany); } return invocationFailed(xjexl); } @@ -1144,7 +1142,7 @@ public class Interpreter implements Pars ctor = uberspect.getConstructorMethod(cobject, argv, node); } if (ctor == null) { - xjexl = new JexlException.Method(node, cobject.toString()); + xjexl = new JexlException.Method(node, cobject.toString(), null); } } if (xjexl == null) { @@ -1156,9 +1154,11 @@ public class Interpreter implements Pars return instance; } } catch (InvocationTargetException e) { - xjexl = new JexlException(node, "constructor invocation error", e.getCause()); + xjexl = new JexlException.Method(node, cobject.toString(), e.getCause()); + } catch (JexlException xany) { + xjexl = xany; } catch (Exception e) { - xjexl = new JexlException(node, "constructor error", e); + xjexl = new JexlException.Method(node, cobject.toString(), e); } return invocationFailed(xjexl); } @@ -1292,6 +1292,18 @@ public class Interpreter implements Pars return Boolean.FALSE; } + /** + * Checks whether a reference child node holds a local variable reference. + * @param node the reference node + * @param which the child we are checking + * @return true if child is local variable, false otherwise + */ + private boolean isLocalVariable(ASTReference node, int which) { + return (node.jjtGetNumChildren() > which + && node.jjtGetChild(which) instanceof ASTIdentifier + && ((ASTIdentifier) node.jjtGetChild(which)).getRegister() >= 0); + } + /** {@inheritDoc} */ public Object visit(ASTReference node, Object data) { // could be array access, identifier or map literal @@ -1330,35 +1342,29 @@ public class Interpreter implements Pars } else { propertyName = theNode.image; } + isVariable &= result == null; } - if (result == null) { - if (isVariable && !isTernaryProtected(node) - // variable unknow in context and not (from) a register - && !(context.has(variableName.toString()) - || (numChildren == 1 - && node.jjtGetChild(0) instanceof ASTIdentifier - && ((ASTIdentifier) node.jjtGetChild(0)).getRegister() >= 0))) { - JexlException xjexl = propertyName != null - ? new JexlException.Property(node, propertyName) - : new JexlException.Variable(node, variableName.toString()); - return unknownVariable(xjexl); - } + if (result == null && isVariable && variableName != null + && !isTernaryProtected(node) && !(context.has(variableName.toString()) || isLocalVariable(node, 0))) { + JexlException xjexl = new JexlException.Variable(node, variableName.toString()); + // variable unknown in context and not a local + return unknownVariable(xjexl); } return result; } - /** + /** * {@inheritDoc} - * @since 2.1 + * @since 2.1 */ public Object visit(ASTReferenceExpression node, Object data) { ASTArrayAccess upper = node; return visit(upper, data); } - /** + /** * {@inheritDoc} - * @since 2.1 + * @since 2.1 */ public Object visit(ASTReturnStatement node, Object data) { Object val = node.jjtGetChild(0).jjtAccept(this, data); @@ -1465,7 +1471,7 @@ public class Interpreter implements Pars * Calculate the <code>size</code> of various types: Collection, Array, * Map, String, and anything that has a int size() method. * @param node the node that gave the value to size - * @param val the object to get the size of. + * @param val the object to get the size of. * @return the size of val */ private int sizeOf(JexlNode node, Object val) { @@ -1498,9 +1504,9 @@ public class Interpreter implements Pars /** * Gets an attribute of an object. * - * @param object to retrieve value from + * @param object to retrieve value from * @param attribute the attribute of the object, e.g. an index (1, 0, 2) or - * key for a map + * key for a map * @return the attribute value */ public Object getAttribute(Object object, Object attribute) { @@ -1510,10 +1516,9 @@ public class Interpreter implements Pars /** * Gets an attribute of an object. * - * @param object to retrieve value from - * @param attribute the attribute of the object, e.g. an index (1, 0, 2) or - * key for a map - * @param node the node that evaluated as the object + * @param object to retrieve value from + * @param attribute the attribute of the object, e.g. an index (1, 0, 2) or key for a map + * @param node the node that evaluated as the object * @return the attribute value */ protected Object getAttribute(Object object, Object attribute, JexlNode node) { @@ -1534,6 +1539,7 @@ public class Interpreter implements Pars } } } + JexlException xjexl = null; JexlPropertyGet vg = uberspect.getPropertyGet(object, attribute, node); if (vg != null) { try { @@ -1544,29 +1550,35 @@ public class Interpreter implements Pars } return value; } catch (Exception xany) { - if (node == null) { - throw new RuntimeException(xany); - } else { - JexlException xjexl = new JexlException.Property(node, attribute.toString()); - if (strict) { - throw xjexl; - } - if (!silent) { - logger.warn(xjexl.getMessage()); - } - } + String attrStr = attribute != null ? attribute.toString() : null; + xjexl = new JexlException.Property(node, attrStr, xany); } } + if (xjexl == null) { + if (node == null) { + String error = "unable to get object property" + + ", class: " + object.getClass().getName() + + ", property: " + attribute; + throw new UnsupportedOperationException(error); + } + String attrStr = attribute != null ? attribute.toString() : null; + xjexl = new JexlException.Property(node, attrStr, null); + } + if (strict) { + throw xjexl; + } + if (!silent) { + logger.warn(xjexl.getMessage()); + } return null; } /** * Sets an attribute of an object. * - * @param object to set the value to - * @param attribute the attribute of the object, e.g. an index (1, 0, 2) or - * key for a map - * @param value the value to assign to the object's attribute + * @param object to set the value to + * @param attribute the attribute of the object, e.g. an index (1, 0, 2) or key for a map + * @param value the value to assign to the object's attribute */ public void setAttribute(Object object, Object attribute, Object value) { setAttribute(object, attribute, value, null); @@ -1575,11 +1587,10 @@ public class Interpreter implements Pars /** * Sets an attribute of an object. * - * @param object to set the value to - * @param attribute the attribute of the object, e.g. an index (1, 0, 2) or - * key for a map - * @param value the value to assign to the object's attribute - * @param node the node that evaluated as the object + * @param object to set the value to + * @param attribute the attribute of the object, e.g. an index (1, 0, 2) or key for a map + * @param value the value to assign to the object's attribute + * @param node the node that evaluated as the object */ protected void setAttribute(Object object, Object attribute, Object value, JexlNode node) { if (isCancelled()) { @@ -1614,16 +1625,16 @@ public class Interpreter implements Pars node.jjtSetValue(vs); } return; - } catch (RuntimeException xrt) { - if (node == null) { - throw xrt; - } - xjexl = new JexlException(node, "set object property error", xrt); } catch (Exception xany) { if (node == null) { - throw new RuntimeException(xany); + if (xany instanceof RuntimeException) { + throw (RuntimeException) xany; + } else { + throw new RuntimeException(xany); + } } - xjexl = new JexlException(node, "set object property error", xany); + String attrStr = attribute != null ? attribute.toString() : null; + xjexl = new JexlException.Property(node, attrStr, xany); } } if (xjexl == null) { @@ -1634,7 +1645,8 @@ public class Interpreter implements Pars + ", argument: " + value.getClass().getSimpleName(); throw new UnsupportedOperationException(error); } - xjexl = new JexlException.Property(node, attribute.toString()); + String attrStr = attribute != null ? attribute.toString() : null; + xjexl = new JexlException.Property(node, attrStr, null); } if (strict) { throw xjexl; Modified: commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl2/JexlArithmetic.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl2/JexlArithmetic.java?rev=1332806&r1=1332805&r2=1332806&view=diff ============================================================================== --- commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl2/JexlArithmetic.java (original) +++ commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl2/JexlArithmetic.java Tue May 1 20:21:10 2012 @@ -57,7 +57,8 @@ public class JexlArithmetic { * @since 2.1 */ protected static final int BIGD_SCALE = -1; - /** Whether this JexlArithmetic instance behaves in strict or lenient mode. + /** + * Whether this JexlArithmetic instance behaves in strict or lenient mode. * May be made final in a later version. */ private volatile boolean strict; Modified: commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl2/JexlEngine.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl2/JexlEngine.java?rev=1332806&r1=1332805&r2=1332806&view=diff ============================================================================== --- commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl2/JexlEngine.java (original) +++ commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl2/JexlEngine.java Tue May 1 20:21:10 2012 @@ -151,7 +151,7 @@ public class JexlEngine { */ protected final Parser parser = new Parser(new StringReader(";")); //$NON-NLS-1$ /** - * Whether expressions evaluated by this engine will throw exceptions (false) or + * Whether expressions evaluated by this engine will throw exceptions (false) or * return null (true) on errors. Default is false. */ // TODO could this be private? @@ -162,6 +162,10 @@ public class JexlEngine { // TODO could this be private? protected volatile boolean debug = true; /** + * Whether this engine baehaves in strict mode. + */ + private volatile boolean strict = false; + /** * The map of 'prefix:function' to object implementing the functions. */ // TODO this could probably be private; is it threadsafe? @@ -201,6 +205,7 @@ public class JexlEngine { if (theFunctions != null) { this.functions = theFunctions; } + this.strict = !this.arithmetic.isLenient(); } /** @@ -275,7 +280,7 @@ public class JexlEngine { public boolean isSilent() { return this.silent; } - + /** * Sets whether this engine considers unknown variables, methods and constructors as errors or evaluates them * as null or zero. @@ -289,6 +294,7 @@ public class JexlEngine { */ @SuppressWarnings("deprecation") public void setLenient(boolean flag) { + strict = !flag; if (arithmetic instanceof JexlThreadedArithmetic) { JexlThreadedArithmetic.setLenient(Boolean.valueOf(flag)); } else { @@ -301,7 +307,7 @@ public class JexlEngine { * @return true if lenient, false if strict */ public boolean isLenient() { - return arithmetic.isLenient(); + return !strict; } /** @@ -940,7 +946,7 @@ public class JexlEngine { if (image == null) { var.add(new Debugger().data(desc)); } else { - var.add(image); + var.add(image); } } else if (desc instanceof ASTIdentifier) { if (((ASTIdentifier) desc).getRegister() < 0) { @@ -1066,7 +1072,7 @@ public class JexlEngine { } /** - * Checks whether an identifier is a local variable or argument, ie stored in a register. + * Checks whether an identifier is a local variable or argument, ie stored in a register. * @param name the register name * @return the register index */ @@ -1175,7 +1181,7 @@ public class JexlEngine { private Object[] registers = null; /** Parameter and argument names if any. */ private String[] parameters = null; - + /** * Creates a new frame. * @param r the registers @@ -1185,14 +1191,14 @@ public class JexlEngine { registers = r; parameters = p; } - + /** * @return the registers */ public Object[] getRegisters() { return registers; } - + /** * @return the parameters */ Modified: commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl2/JexlException.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl2/JexlException.java?rev=1332806&r1=1332805&r2=1332806&view=diff ============================================================================== --- commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl2/JexlException.java (original) +++ commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl2/JexlException.java Tue May 1 20:21:10 2012 @@ -86,7 +86,7 @@ public class JexlException extends Runti } /** - * Unwraps the cause of a throwable due to reflection. + * Unwraps the cause of a throwable due to reflection. * @param xthrow the throwable * @return the cause */ @@ -260,8 +260,8 @@ public class JexlException extends Runti * @param node the offending ASTnode * @param var the unknown variable */ - public Property(JexlNode node, String var) { - super(node, var); + public Property(JexlNode node, String var, Throwable cause) { + super(node, var, cause); } /** @@ -287,8 +287,8 @@ public class JexlException extends Runti * @param node the offending ASTnode * @param name the unknown method */ - public Method(JexlNode node, String name) { - super(node, name); + public Method(JexlNode node, String name, Throwable cause) { + super(node, name, cause); } /** Modified: commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl2/ObjectContext.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl2/ObjectContext.java?rev=1332806&r1=1332805&r2=1332806&view=diff ============================================================================== --- commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl2/ObjectContext.java (original) +++ commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl2/ObjectContext.java Tue May 1 20:21:10 2012 @@ -23,9 +23,9 @@ package org.apache.commons.jexl2; */ public class ObjectContext<T> implements JexlContext { /** The property solving jexl engine. */ - private final JexlEngine jexl; + protected final JexlEngine jexl; /** The object serving as context provider. */ - private final T object; + protected final T object; /** * Creates a new ObjectContext. Modified: commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl2/UnifiedJEXL.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl2/UnifiedJEXL.java?rev=1332806&r1=1332805&r2=1332806&view=diff ============================================================================== --- commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl2/UnifiedJEXL.java (original) +++ commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl2/UnifiedJEXL.java Tue May 1 20:21:10 2012 @@ -985,7 +985,7 @@ public final class UnifiedJEXL { private final String body; /** - * Creates a new block. + * Creates a new block. * @param theType the type * @param theBlock the content */ @@ -1007,7 +1007,7 @@ public final class UnifiedJEXL { * <p> * The source text is parsed considering each line beginning with '$$' (as default pattern) as JEXL script code * and all others as Unified JEXL expressions; those expressions will be invoked from the script during - * evaluation and their output gathered through a writer. + * evaluation and their output gathered through a writer. * It is thus possible to use looping or conditional construct "around" expressions generating output. * </p> * For instance: @@ -1341,22 +1341,22 @@ public final class UnifiedJEXL { * Whether a sequence starts with a given set of characters (following spaces). * <p>Space characters at beginning of line before the pattern are discarded.</p> * @param sequence the sequence - * @param pattern the pattern to match at start of sequence + * @param pattern the pattern to match at start of sequence * @return the first position after end of pattern if it matches, -1 otherwise - * @since 2.1 */ protected int startsWith(CharSequence sequence, CharSequence pattern) { + int length = sequence.length(); int s = 0; - while (Character.isSpaceChar(sequence.charAt(s))) { + while (s < length && Character.isSpaceChar(sequence.charAt(s))) { s += 1; } - sequence = sequence.subSequence(s, sequence.length()); - if (pattern.length() <= sequence.length() - && sequence.subSequence(0, pattern.length()).equals(pattern)) { - return s + pattern.length(); - } else { - return -1; + if (s < length && pattern.length() <= (length - s)) { + sequence = sequence.subSequence(s, length); + if (sequence.subSequence(0, pattern.length()).equals(pattern)) { + return s + pattern.length(); + } } + return -1; } /** @@ -1368,7 +1368,7 @@ public final class UnifiedJEXL { */ protected List<TemplateBlock> readTemplate(final String prefix, Reader source) { try { - int prefixLen = prefix.length(); + int prefixLen; List<TemplateBlock> blocks = new ArrayList<TemplateBlock>(); BufferedReader reader; if (source instanceof BufferedReader) { Modified: commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl2/parser/ASTNumberLiteral.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl2/parser/ASTNumberLiteral.java?rev=1332806&r1=1332805&r2=1332806&view=diff ============================================================================== --- commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl2/parser/ASTNumberLiteral.java (original) +++ commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl2/parser/ASTNumberLiteral.java Tue May 1 20:21:10 2012 @@ -40,7 +40,7 @@ public class ASTNumberLiteral extends Je public Number getLiteral() { return literal; } - + /** {@inheritDoc} */ @Override protected boolean isConstant(boolean literal) { @@ -124,28 +124,27 @@ public class ASTNumberLiteral extends Je switch (s.charAt(last)) { case 'b': case 'B': { - result = new BigDecimal(s.substring(0, last)); rclass = BigDecimal.class; + result = new BigDecimal(s.substring(0, last)); + break; + } + case 'f': + case 'F': { + rclass = Float.class; + result = Float.valueOf(s.substring(0, last)); break; } case 'd': - case 'D': { + case 'D': rclass = Double.class; - result = Double.valueOf(s); + result = Double.valueOf(s.substring(0, last)); break; - } - case 'f': - case 'F': default: { - rclass = Float.class; + rclass = Double.class; try { - result = Float.valueOf(s); - } catch (NumberFormatException take2) { - try { - result = Double.valueOf(s); - } catch (NumberFormatException take3) { - result = new BigDecimal(s); - } + result = Double.valueOf(s); + } catch (NumberFormatException take3) { + result = new BigDecimal(s); } break; } Modified: commons/proper/jexl/branches/2.0/src/test/java/org/apache/commons/jexl2/ArithmeticTest.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/test/java/org/apache/commons/jexl2/ArithmeticTest.java?rev=1332806&r1=1332805&r2=1332806&view=diff ============================================================================== --- commons/proper/jexl/branches/2.0/src/test/java/org/apache/commons/jexl2/ArithmeticTest.java (original) +++ commons/proper/jexl/branches/2.0/src/test/java/org/apache/commons/jexl2/ArithmeticTest.java Tue May 1 20:21:10 2012 @@ -122,7 +122,7 @@ public class ArithmeticTest extends Jexl asserter.setVariable("aBigDecimal", new BigDecimal("8.8")); asserter.assertExpression("-3", new Integer("-3")); - asserter.assertExpression("-3.0", new Float("-3.0")); + asserter.assertExpression("-3.0", new Double("-3.0")); asserter.assertExpression("-aByte", new Byte((byte) -1)); asserter.assertExpression("-aShort", new Short((short) -2)); asserter.assertExpression("-anInteger", new Integer(-3)); @@ -258,7 +258,7 @@ public class ArithmeticTest extends Jexl MatchingContainer ad = new MatchingContainer(ai); Set<Integer> as = ad.values; Object[] vars = { ai, al, am, ad, as }; - + for(Object var : vars) { asserter.setVariable("container", var); for(int x : ai) { Modified: commons/proper/jexl/branches/2.0/src/test/java/org/apache/commons/jexl2/ArrayLiteralTest.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/test/java/org/apache/commons/jexl2/ArrayLiteralTest.java?rev=1332806&r1=1332805&r2=1332806&view=diff ============================================================================== --- commons/proper/jexl/branches/2.0/src/test/java/org/apache/commons/jexl2/ArrayLiteralTest.java (original) +++ commons/proper/jexl/branches/2.0/src/test/java/org/apache/commons/jexl2/ArrayLiteralTest.java Tue May 1 20:21:10 2012 @@ -47,7 +47,7 @@ public class ArrayLiteralTest extends Je JexlContext jc = new MapContext(); Object o = e.evaluate( jc ); - Object[] check = { new Float(5), new Integer(10) }; + Object[] check = { new Double(5), new Integer(10) }; assertTrue( Arrays.equals(check, (Object[])o) ); assertTrue (o.getClass().isArray() && o.getClass().getComponentType().equals(Number.class)); } @@ -59,7 +59,7 @@ public class ArrayLiteralTest extends Je "[ 10 , null , 10]", "[ '10' , null ]", "[ null, '10' , null ]" - }; + }; Object [][]checks = { {null, new Integer(10)}, {new Integer(10), null}, Copied: commons/proper/jexl/branches/2.0/src/test/java/org/apache/commons/jexl2/ExceptionTest.java (from r1332642, commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ExceptionTest.java) URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/test/java/org/apache/commons/jexl2/ExceptionTest.java?p2=commons/proper/jexl/branches/2.0/src/test/java/org/apache/commons/jexl2/ExceptionTest.java&p1=commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ExceptionTest.java&r1=1332642&r2=1332806&rev=1332806&view=diff ============================================================================== --- commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ExceptionTest.java (original) +++ commons/proper/jexl/branches/2.0/src/test/java/org/apache/commons/jexl2/ExceptionTest.java Tue May 1 20:21:10 2012 @@ -14,9 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.jexl3; - -import org.apache.commons.jexl3.internal.Engine; +package org.apache.commons.jexl2; /** * Checks various exception handling cases. @@ -33,28 +31,42 @@ public class ExceptionTest extends JexlT } } + public static class ThrowNPEContext extends ObjectContext<ThrowNPE> implements NamespaceResolver { + public ThrowNPEContext(JexlEngine jexl, ThrowNPE arg) { + super(jexl, arg); + } + + public Object resolveNamespace(String name) { + return name == null? object : null; + } + } + public void testWrappedEx() throws Exception { - JexlEngine jexl = new Engine(); - JexlExpression e = jexl.createExpression("method()"); - JexlContext jc = new ObjectContext<ThrowNPE>(jexl, new ThrowNPE()); + JexlEngine jexl = new JexlEngine(); + // make unknown vars throw + jexl.setSilent(false); + jexl.setStrict(true); + Expression e = jexl.createExpression("method()"); + JexlContext jc = new ThrowNPEContext(jexl, new ThrowNPE()); try { e.evaluate(jc); fail("Should have thrown NPE"); } catch (JexlException xany) { Throwable xth = xany.getCause(); - assertEquals(NullPointerException.class, xth.getClass()); + assertEquals(NullPointerException.class, xth != null? xth.getClass() : null); } } // Unknown vars and properties versus null operands public void testEx() throws Exception { JexlEngine jexl = createEngine(false); - JexlExpression e = jexl.createExpression("c.e * 6"); - JexlEvalContext ctxt = new JexlEvalContext(); - // ensure errors will throw - ctxt.setSilent(false); + Expression e = jexl.createExpression("c.e * 6"); + JexlContext ctxt = new MapContext(); // make unknown vars throw - ctxt.setStrict(true); + jexl.setSilent(false); + jexl.setStrict(true); + assertFalse(jexl.getArithmetic().isLenient()); + assertTrue(jexl.isStrict()); // empty cotext try { /* Object o = */ e.evaluate(ctxt); @@ -65,7 +77,9 @@ public class ExceptionTest extends JexlT } // disallow null operands - ctxt.setStrictArithmetic(true); + jexl.getArithmetic().setLenient(false); + assertFalse(jexl.getArithmetic().isLenient()); + assertTrue(jexl.isStrict()); ctxt.set("c.e", null); try { /* Object o = */ e.evaluate(ctxt); @@ -76,7 +90,10 @@ public class ExceptionTest extends JexlT } // allow null operands - ctxt.setStrictArithmetic(false); + jexl.setStrict(true); + jexl.getArithmetic().setLenient(true); + assertTrue(jexl.getArithmetic().isLenient()); + assertTrue(jexl.isStrict()); try { /* Object o = */ e.evaluate(ctxt); @@ -84,6 +101,10 @@ public class ExceptionTest extends JexlT fail("c.e in expr should not throw"); } + jexl.getArithmetic().setLenient(false); + jexl.setStrict(true); + assertFalse(jexl.getArithmetic().isLenient()); + assertTrue(jexl.isStrict()); // ensure c.e is not a defined property ctxt.set("c", "{ 'a' : 3, 'b' : 5}"); ctxt.set("e", Integer.valueOf(2)); Modified: commons/proper/jexl/branches/2.0/src/test/java/org/apache/commons/jexl2/IssuesTest.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/test/java/org/apache/commons/jexl2/IssuesTest.java?rev=1332806&r1=1332805&r2=1332806&view=diff ============================================================================== --- commons/proper/jexl/branches/2.0/src/test/java/org/apache/commons/jexl2/IssuesTest.java (original) +++ commons/proper/jexl/branches/2.0/src/test/java/org/apache/commons/jexl2/IssuesTest.java Tue May 1 20:21:10 2012 @@ -49,7 +49,7 @@ public class IssuesTest extends JexlTest assertEquals(42.0d, vars.get("d")); assertEquals(56.3f, vars.get("e")); assertEquals(56.3f, vars.get("f")); - assertEquals(63.5f, vars.get("g")); + assertEquals(63.5, vars.get("g")); assertEquals(0x10, vars.get("h")); assertEquals(010, vars.get("i")); assertEquals(0x10L, vars.get("j")); @@ -455,7 +455,7 @@ public class IssuesTest extends JexlTest } } -// A's class definition +// A's class definition public static class A105 { String nameA; String propA; @@ -719,21 +719,22 @@ public class IssuesTest extends JexlTest s = jexl.createScript("foo.'q u u x'"); result = s.execute(jc); assertEquals("456", result); - + Debugger dbg = new Debugger(); dbg.debug(((ExpressionImpl) s).script); String dbgdata = dbg.data(); assertEquals("foo.'q u u x';", dbgdata); } - + public static class Container { String value0; int value1; + public Container(String name, int number) { value0 = name; value1 = number; } - + public Object getProperty(String name) { if ("name".equals(name)) { return value0; @@ -743,6 +744,7 @@ public class IssuesTest extends JexlTest return null; } } + public Object getProperty(int ref) { if (0 == ref) { return value0; @@ -752,24 +754,25 @@ public class IssuesTest extends JexlTest return null; } } - + public void setProperty(String name, String value) { if ("name".equals(name)) { this.value0 = value; } - } - + } + public void setProperty(String name, int value) { if ("number".equals(name)) { this.value1 = value; } - } + } + public void setProperty(int ref, String value) { if (0 == ref) { this.value0 = value; } - } - + } + public void setProperty(int ref, int value) { if (1 == ref) { this.value1 = value; @@ -782,44 +785,44 @@ public class IssuesTest extends JexlTest Container quux = new Container("quux", 42); Script get; Object result; - + Script getName = jexl.createScript("foo.property.name", "foo"); result = getName.execute(null, quux); assertEquals("quux", result); - + Script get0 = jexl.createScript("foo.property.0", "foo"); result = get0.execute(null, quux); assertEquals("quux", result); - + Script getNumber = jexl.createScript("foo.property.number", "foo"); result = getNumber.execute(null, quux); assertEquals(42, result); - + Script get1 = jexl.createScript("foo.property.1", "foo"); result = get1.execute(null, quux); assertEquals(42, result); - + Script setName = jexl.createScript("foo.property.name = $0", "foo", "$0"); setName.execute(null, quux, "QUUX"); result = getName.execute(null, quux); assertEquals("QUUX", result); result = get0.execute(null, quux); assertEquals("QUUX", result); - + Script set0 = jexl.createScript("foo.property.0 = $0", "foo", "$0"); set0.execute(null, quux, "BAR"); result = getName.execute(null, quux); assertEquals("BAR", result); result = get0.execute(null, quux); assertEquals("BAR", result); - + Script setNumber = jexl.createScript("foo.property.number = $0", "foo", "$0"); setNumber.execute(null, quux, -42); result = getNumber.execute(null, quux); assertEquals(-42, result); result = get1.execute(null, quux); assertEquals(-42, result); - + Script set1 = jexl.createScript("foo.property.1 = $0", "foo", "$0"); set1.execute(null, quux, 24); result = getNumber.execute(null, quux); @@ -827,4 +830,96 @@ public class IssuesTest extends JexlTest result = get1.execute(null, quux); assertEquals(24, result); } + + public static class Foo125 { + public String method() { + return "OK"; + } + } + + public static class Foo125Context implements JexlContext, NamespaceResolver { + private final JexlEngine jexl; + private final Foo125 object; + + @Override + public Object resolveNamespace(String name) { + if (name == null) { + return object; + } else { + return null; + } + } + + public Foo125Context(JexlEngine engine, Foo125 wrapped) { + this.jexl = engine; + this.object = wrapped; + } + + public Object get(String name) { + return jexl.getProperty(object, name); + } + + public void set(String name, Object value) { + jexl.setProperty(object, name, value); + } + + public boolean has(String name) { + return jexl.getUberspect().getPropertyGet(object, name, null) != null; + } + } + + public void test125() throws Exception { + JexlEngine jexl = new JexlEngine(); + Expression e = jexl.createExpression("method()"); + JexlContext jc = new Foo125Context(jexl, new Foo125()); + assertEquals("OK", e.evaluate(jc)); + } + + public void testReturnIssue() throws Exception { + JexlEngine jexl = new JexlEngine(); + String[] items = {"foo", "bar", "quux"}; + Script s = jexl.createScript("for(var x : items) { if(x.equals(y)) { return true; } }", "items", "y"); + Object r = s.execute(null, items, "bar"); + assertEquals(true, r); + r = s.execute(null, items, "froboz"); + assertNull(r); + JexlContext ctxt = new MapContext(); + ctxt.set("items", items); + ctxt.set("y", "bar"); + s = jexl.createScript("for(x : items) { if(x.equals(y)) { return true; } }"); + r = s.execute(ctxt); + assertEquals(true, r); + ctxt.set("y", "froboz"); + r = s.execute(ctxt); + assertNull(r); + } + + public void test130a() throws Exception { + String myName = "Test.Name"; + Object myValue = "Test.Value"; + + JexlEngine myJexlEngine = new JexlEngine(); + MapContext myMapContext = new MapContext(); + myMapContext.set(myName, myValue); + + Object myObjectWithTernaryConditional = myJexlEngine.createScript(myName + "?:null").execute(myMapContext); + assertEquals(myValue, myObjectWithTernaryConditional); + } + + public void test130b() throws Exception { + String myName = "Test.Name"; + Object myValue = new Object() { + @Override + public String toString() { + return "Test.Value"; + } + }; + + JexlEngine myJexlEngine = new JexlEngine(); + MapContext myMapContext = new MapContext(); + myMapContext.set(myName, myValue); + + Object myObjectWithTernaryConditional = myJexlEngine.createScript(myName + "?:null").execute(myMapContext); + assertEquals(myValue, myObjectWithTernaryConditional); + } }