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);
+    }
 }


Reply via email to