commons-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From hen...@apache.org
Subject svn commit: r1220681 [1/2] - in /commons/proper/jexl/trunk: ./ src/main/java/org/apache/commons/jexl3/ src/main/java/org/apache/commons/jexl3/internal/ src/main/java/org/apache/commons/jexl3/internal/introspection/ src/main/java/org/apache/commons/jexl...
Date Mon, 19 Dec 2011 10:43:36 GMT
Author: henrib
Date: Mon Dec 19 10:43:35 2011
New Revision: 1220681

URL: http://svn.apache.org/viewvc?rev=1220681&view=rev
Log:
JEXL-123:
Extracted various types of executors from Uberspect;
Revamped executor discovery to avoid unnecessary allocation on failure;
Used Method arrays instead of List<Method> when applicable;
Removed JexlInfoHandle which was never really used 

Added:
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/ConstructorMethod.java   (with props)
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/FieldGetExecutor.java   (with props)
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/FieldSetExecutor.java   (with props)
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/IndexedType.java   (with props)
Removed:
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlInfoHandle.java
Modified:
    commons/proper/jexl/trunk/pom.xml
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlEvalContext.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlException.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/ObjectContext.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/TemplateEngine.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/AbstractExecutor.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/BooleanGetExecutor.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/DuckGetExecutor.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/DuckSetExecutor.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/Introspector.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/ListGetExecutor.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/ListSetExecutor.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/MapGetExecutor.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/MapSetExecutor.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/MethodExecutor.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/PropertySetExecutor.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/SandboxUberspect.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/introspection/JexlUberspect.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/JexlNode.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/internal/introspection/DiscoveryTest.java

Modified: commons/proper/jexl/trunk/pom.xml
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/pom.xml?rev=1220681&r1=1220680&r2=1220681&view=diff
==============================================================================
--- commons/proper/jexl/trunk/pom.xml (original)
+++ commons/proper/jexl/trunk/pom.xml Mon Dec 19 10:43:35 2011
@@ -269,7 +269,6 @@
                         <ruleset>/rulesets/braces.xml</ruleset>
                         <ruleset>/rulesets/unusedcode.xml</ruleset>
                         <ruleset>/rulesets/imports.xml</ruleset>
-                        <ruleset>/rulesets/codesize.xml</ruleset>
                         <ruleset>/rulesets/coupling.xml</ruleset>
                         <ruleset>/rulesets/design.xml</ruleset>
                         <ruleset>/rulesets/strings.xml</ruleset>

Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlEvalContext.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlEvalContext.java?rev=1220681&r1=1220680&r2=1220681&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlEvalContext.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlEvalContext.java Mon Dec 19 10:43:35 2011
@@ -34,9 +34,7 @@ public class JexlEvalContext implements 
     /** Whether the engine should be strict. */
     private Boolean strict = null;
     /** Whether the arithmetic should be strict. */
-    private Boolean astrict = null;
-    /** The namespaces vars the engine should use. */
-    private Map<String, Object> namespaces = null;
+    private Boolean mathStrict = null;
     /** The math scale the arithmetic should use. */
     private int mathScale = Integer.MIN_VALUE;
     /** The math context the arithmetic should use. */
@@ -87,7 +85,6 @@ public class JexlEvalContext implements 
     public void clearOptions() {
         silent = null;
         strict = null;
-        namespaces = null;
         mathScale = -1;
         mathContext = null;
     }
@@ -112,7 +109,7 @@ public class JexlEvalContext implements 
      */
     public void setStrict(boolean se, boolean sa) {
         this.strict = se ? Boolean.TRUE : Boolean.FALSE;
-        this.astrict = sa ? Boolean.TRUE : Boolean.FALSE;
+        this.mathStrict = sa ? Boolean.TRUE : Boolean.FALSE;
     }
 
     /**
@@ -138,15 +135,15 @@ public class JexlEvalContext implements 
      * @param s true means strict error reporting, false allows mentioned conditions to be evaluated as 0
      */
     public void setStrictArithmetic(boolean s) {
-        this.astrict = s ? Boolean.TRUE : Boolean.FALSE;
+        this.mathStrict = s ? Boolean.TRUE : Boolean.FALSE;
     }
 
     @Override
     public Boolean isStrictArithmetic() {
-        if (astrict == null) {
+        if (mathStrict == null) {
             return null;
         } else {
-            return astrict.booleanValue() ? Boolean.TRUE : Boolean.FALSE;
+            return mathStrict.booleanValue() ? Boolean.TRUE : Boolean.FALSE;
         }
     }
 

Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlException.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlException.java?rev=1220681&r1=1220680&r2=1220681&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlException.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlException.java Mon Dec 19 10:43:35 2011
@@ -17,12 +17,13 @@
 package org.apache.commons.jexl3;
 
 import org.apache.commons.jexl3.internal.Debugger;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.UndeclaredThrowableException;
 import org.apache.commons.jexl3.parser.JexlNode;
 import org.apache.commons.jexl3.parser.ParseException;
 import org.apache.commons.jexl3.parser.TokenMgrError;
 
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.UndeclaredThrowableException;
+
 /**
  * Wraps any error that might occur during interpretation of a script or expression.
  * @since 2.0
@@ -35,9 +36,9 @@ public class JexlException extends Runti
     /** A marker to use in NPEs stating a null operand error. */
     public static final String NULL_OPERAND = "jexl.null";
     /** Minimum number of characters around exception location. */
-    private static final int MIN_EXCHARLOC = 5;
+    private static final int MIN_EXCHARLOC = 10;
     /** Maximum number of characters around exception location. */
-    private static final int MAX_EXCHARLOC = 10;
+    private static final int MAX_EXCHARLOC = 15;
 
     /**
      * Creates a new JexlException.

Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/ObjectContext.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/ObjectContext.java?rev=1220681&r1=1220680&r2=1220681&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/ObjectContext.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/ObjectContext.java Mon Dec 19 10:43:35 2011
@@ -49,6 +49,6 @@ public class ObjectContext<T> implements
 
     @Override
     public boolean has(String name) {
-        return jexl.getUberspect().getPropertyGet(object, name, null) != null;
+        return jexl.getUberspect().getPropertyGet(object, name) != null;
     }
 }

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=1220681&r1=1220680&r2=1220681&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 Mon Dec 19 10:43:35 2011
@@ -24,7 +24,6 @@ import org.apache.commons.jexl3.JexlEngi
 import org.apache.commons.jexl3.JexlException;
 import org.apache.commons.jexl3.JexlExpression;
 import org.apache.commons.jexl3.JexlInfo;
-import org.apache.commons.jexl3.JexlInfoHandle;
 import org.apache.commons.jexl3.JexlScript;
 
 import org.apache.commons.jexl3.internal.introspection.SandboxUberspect;
@@ -214,41 +213,21 @@ public class Engine extends JexlEngine {
         return new TemplateEngine(this);
     }
 
-    /**
-     * Checks whether this engine is in debug mode.
-     * @return true if debug is on, false otherwise
-     */
     @Override
     public boolean isDebug() {
         return this.debug;
     }
 
-    /**
-     * Checks whether this engine throws JexlException during evaluation.
-     * @return true if silent, false (default) otherwise
-     */
     @Override
     public boolean isSilent() {
         return this.silent;
     }
 
-
-    /**
-     * Checks whether this engine behaves in strict or lenient mode.
-     * Equivalent to !isLenient().
-     * @return true for strict, false for lenient
-     */
     @Override
     public final boolean isStrict() {
         return strict;
     }
 
-    /**
-     * Sets the class loader used to discover classes in 'new' expressions.
-     * <p>This method is <em>not</em> thread safe; it should be called as an optional step of the JexlEngine
-     * initialization code before expression creation &amp; evaluation.</p>
-     * @param loader the class loader to use
-     */
     @Override
     public void setClassLoader(ClassLoader loader) {
         uberspect.setClassLoader(loader);
@@ -264,32 +243,11 @@ public class Engine extends JexlEngine {
         return new Script(this, text, tree);
     }
 
-    /**
-     * Creates an JexlExpression from a String containing valid
-     * JEXL syntax.  This method parses the expression which
-     * must contain either a reference or an expression.
-     * @param expression A String containing valid JEXL syntax
-     * @return An JexlExpression object which can be evaluated with a JexlContext
-     * @throws JexlException An exception can be thrown if there is a problem
-     *      parsing this expression, or if the expression is neither an
-     *      expression nor a reference.
-     */
     @Override
     public JexlExpression createExpression(String expression) {
         return createExpression(expression, null);
     }
 
-    /**
-     * Creates an JexlExpression from a String containing valid
-     * JEXL syntax.  This method parses the expression which
-     * must contain either a reference or an expression.
-     * @param expression A String containing valid JEXL syntax
-     * @return An JexlExpression object which can be evaluated with a JexlContext
-     * @param info An info structure to carry debugging information if needed
-     * @throws JexlException An exception can be thrown if there is a problem
-     *      parsing this expression, or if the expression is neither an
-     *      expression or a reference.
-     */
     @Override
     public JexlExpression createExpression(String expression, JexlInfo info) {
         // Parse the expression
@@ -301,45 +259,16 @@ public class Engine extends JexlEngine {
         return createExpression(tree, expression);
     }
 
-    /**
-     * Creates a Script from a String containing valid JEXL syntax.
-     * This method parses the script which validates the syntax.
-     *
-     * @param scriptText A String containing valid JEXL syntax
-     * @return A {@link Script} which can be executed using a {@link JexlContext}.
-     * @throws JexlException if there is a problem parsing the script.
-     */
     @Override
     public Script createScript(String scriptText) {
         return createScript(scriptText, null, null);
     }
-
-    /**
-     * Creates a Script from a String containing valid JEXL syntax.
-     * This method parses the script which validates the syntax.
-     *
-     * @param scriptText A String containing valid JEXL syntax
-     * @param names the script parameter names
-     * @return A {@link Script} which can be executed using a {@link JexlContext}.
-     * @throws JexlException if there is a problem parsing the script.
-     */
+    
     @Override
     public Script createScript(String scriptText, String... names) {
         return createScript(scriptText, null, names);
     }
 
-    /**
-     * Creates a Script from a String containing valid JEXL syntax.
-     * This method parses the script which validates the syntax.
-     * It uses an array of parameter names that will be resolved during parsing;
-     * a corresponding array of arguments containing values should be used during evaluation.
-     *
-     * @param scriptText A String containing valid JEXL syntax
-     * @param info An info structure to carry debugging information if needed
-     * @param names the script parameter names
-     * @return A {@link Script} which can be executed using a {@link JexlContext}.
-     * @throws JexlException if there is a problem parsing the script.
-     */
     @Override
     public Script createScript(String scriptText, JexlInfo info, String[] names) {
         if (scriptText == null) {
@@ -360,17 +289,6 @@ public class Engine extends JexlEngine {
         return new Script(this, text, tree);
     }
 
-    /**
-     * Creates a Script from a {@link File} containing valid JEXL syntax.
-     * This method parses the script and validates the syntax.
-     *
-     * @param scriptFile A {@link File} containing valid JEXL syntax.
-     *      Must not be null. Must be a readable file.
-     * @return A {@link Script} which can be executed with a
-     *      {@link JexlContext}.
-     * @throws IOException if there is a problem reading the script.
-     * @throws JexlException if there is a problem parsing the script.
-     */
     @Override
     public Script createScript(File scriptFile) throws IOException {
         if (scriptFile == null) {
@@ -387,17 +305,6 @@ public class Engine extends JexlEngine {
         return createScript(readerToString(reader), info, null);
     }
 
-    /**
-     * Creates a Script from a {@link URL} containing valid JEXL syntax.
-     * This method parses the script and validates the syntax.
-     *
-     * @param scriptUrl A {@link URL} containing valid JEXL syntax.
-     *      Must not be null. Must be a readable file.
-     * @return A {@link Script} which can be executed with a
-     *      {@link JexlContext}.
-     * @throws IOException if there is a problem reading the script.
-     * @throws JexlException if there is a problem parsing the script.
-     */
     @Override
     public JexlScript createScript(URL scriptUrl) throws IOException {
         if (scriptUrl == null) {
@@ -413,36 +320,11 @@ public class Engine extends JexlEngine {
         return createScript(readerToString(reader), info, null);
     }
 
-    /**
-     * Accesses properties of a bean using an expression.
-     * <p>
-     * jexl.get(myobject, "foo.bar"); should equate to
-     * myobject.getFoo().getBar(); (or myobject.getFoo().get("bar"))
-     * </p>
-     * <p>
-     * If the JEXL engine is silent, errors will be logged through its logger as warning.
-     * </p>
-     * @param bean the bean to get properties from
-     * @param expr the property expression
-     * @return the value of the property
-     * @throws JexlException if there is an error parsing the expression or during evaluation
-     */
     @Override
     public Object getProperty(Object bean, String expr) {
         return getProperty(null, bean, expr);
     }
 
-    /**
-     * Accesses properties of a bean using an expression.
-     * <p>
-     * If the JEXL engine is silent, errors will be logged through its logger as warning.
-     * </p>
-     * @param context the evaluation context
-     * @param bean the bean to get properties from
-     * @param expr the property expression
-     * @return the value of the property
-     * @throws JexlException if there is an error parsing the expression or during evaluation
-     */
     @Override
     public Object getProperty(JexlContext context, Object bean, String expr) {
         if (context == null) {
@@ -469,36 +351,11 @@ public class Engine extends JexlEngine {
         }
     }
 
-    /**
-     * Assign properties of a bean using an expression.
-     * <p>
-     * jexl.set(myobject, "foo.bar", 10); should equate to
-     * myobject.getFoo().setBar(10); (or myobject.getFoo().put("bar", 10) )
-     * </p>
-     * <p>
-     * If the JEXL engine is silent, errors will be logged through its logger as warning.
-     * </p>
-     * @param bean the bean to set properties in
-     * @param expr the property expression
-     * @param value the value of the property
-     * @throws JexlException if there is an error parsing the expression or during evaluation
-     */
     @Override
     public void setProperty(Object bean, String expr, Object value) {
         setProperty(null, bean, expr, value);
     }
 
-    /**
-     * Assign properties of a bean using an expression.
-     * <p>
-     * If the JEXL engine is silent, errors will be logged through its logger as warning.
-     * </p>
-     * @param context the evaluation context
-     * @param bean the bean to set properties in
-     * @param expr the property expression
-     * @param value the value of the property
-     * @throws JexlException if there is an error parsing the expression or during evaluation
-     */
     @Override
     public void setProperty(JexlContext context, Object bean, String expr, Object value) {
         if (context == null) {
@@ -525,29 +382,15 @@ public class Engine extends JexlEngine {
         }
     }
 
-    /**
-     * Invokes an object's method by name and arguments.
-     * @param obj the method's invoker object
-     * @param meth the method's name
-     * @param args the method's arguments
-     * @return the method returned value or null if it failed and engine is silent
-     * @throws JexlException if method could not be found or failed and engine is not silent
-     */
     @Override
     public Object invokeMethod(Object obj, String meth, Object... args) {
         JexlException xjexl = null;
         Object result = null;
         final JexlInfo info = jexlInfo();
-        JexlInfoHandle handle = new JexlInfoHandle() {
-            @Override
-            public JexlInfo jexlInfo() {
-                return info;
-            }
-        };
         try {
-            JexlMethod method = uberspect.getMethod(obj, meth, args, handle);
+            JexlMethod method = uberspect.getMethod(obj, meth, args);
             if (method == null && arithmetic.narrowArguments(args)) {
-                method = uberspect.getMethod(obj, meth, args, handle);
+                method = uberspect.getMethod(obj, meth, args);
             }
             if (method != null) {
                 result = method.invoke(obj, args);
@@ -568,26 +411,11 @@ public class Engine extends JexlEngine {
         return result;
     }
 
-    /**
-     * Creates a new instance of an object using the most appropriate constructor
-     * based on the arguments.
-     * @param <T> the type of object
-     * @param clazz the class to instantiate
-     * @param args the constructor arguments
-     * @return the created object instance or null on failure when silent
-     */
     @Override
     public <T> T newInstance(Class<? extends T> clazz, Object... args) {
         return clazz.cast(doCreateInstance(clazz, args));
     }
 
-    /**
-     * Creates a new instance of an object using the most appropriate constructor
-     * based on the arguments.
-     * @param clazz the name of the class to instantiate resolved through this engine's class loader
-     * @param args the constructor arguments
-     * @return the created object instance or null on failure when silent
-     */
     @Override
     public Object newInstance(String clazz, Object... args) {
         return doCreateInstance(clazz, args);
@@ -604,16 +432,10 @@ public class Engine extends JexlEngine {
         JexlException xjexl = null;
         Object result = null;
         final JexlInfo info = jexlInfo();
-        JexlInfoHandle handle = new JexlInfoHandle() {
-            @Override
-            public JexlInfo jexlInfo() {
-                return info;
-            }
-        };
         try {
-            JexlMethod ctor = uberspect.getConstructor(clazz, args, handle);
+            JexlMethod ctor = uberspect.getConstructor(clazz, args);
             if (ctor == null && arithmetic.narrowArguments(args)) {
-                ctor = uberspect.getConstructor(clazz, args, handle);
+                ctor = uberspect.getConstructor(clazz, args);
             }
             if (ctor != null) {
                 result = ctor.invoke(clazz, args);
@@ -737,9 +559,6 @@ public class Engine extends JexlEngine {
         };
     }
 
-    /**
-     * Clears the expression cache.
-     */
     @Override
     public void clearCache() {
         synchronized (parser) {

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=1220681&r1=1220680&r2=1220681&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 Mon Dec 19 10:43:35 2011
@@ -289,7 +289,7 @@ public class Interpreter extends ParserV
         // allow namespace to be instantiated as functor with context if possible, not an error otherwise
         if (namespace instanceof Class<?>) {
             Object[] args = new Object[]{context};
-            JexlMethod ctor = uberspect.getConstructor(namespace, args, node);
+            JexlMethod ctor = uberspect.getConstructor(namespace, args);
             if (ctor != null) {
                 try {
                     namespace = ctor.invoke(namespace, args);
@@ -657,7 +657,7 @@ public class Interpreter extends ParserV
             JexlNode statement = node.jjtGetChild(2);
             // get an iterator for the collection/array etc via the
             // introspector.
-            Iterator<?> itemsIterator = uberspect.getIterator(iterableValue, node);
+            Iterator<?> itemsIterator = uberspect.getIterator(iterableValue);
             if (itemsIterator != null) {
                 while (itemsIterator.hasNext()) {
                     if (isCancelled()) {
@@ -725,11 +725,11 @@ public class Interpreter extends ParserV
             // try a contains method (duck type set)
             try {
                 Object[] argv = {left};
-                JexlMethod vm = uberspect.getMethod(right, "contains", argv, node);
+                JexlMethod vm = uberspect.getMethod(right, "contains", argv);
                 if (vm != null) {
                     return arithmetic.toBoolean(vm.invoke(right, argv)) ? Boolean.TRUE : Boolean.FALSE;
                 } else if (arithmetic.narrowArguments(argv)) {
-                    vm = uberspect.getMethod(right, "contains", argv, node);
+                    vm = uberspect.getMethod(right, "contains", argv);
                     if (vm != null) {
                         return arithmetic.toBoolean(vm.invoke(right, argv)) ? Boolean.TRUE : Boolean.FALSE;
                     }
@@ -740,7 +740,7 @@ public class Interpreter extends ParserV
                 throw new JexlException(node, "=~ error", e);
             }
             // try iterative comparison
-            Iterator<?> it = uberspect.getIterator(right, node);
+            Iterator<?> it = uberspect.getIterator(right);
             if (it != null) {
                 while (it.hasNext()) {
                     Object next = it.next();
@@ -915,11 +915,11 @@ public class Interpreter extends ParserV
                 }
             }
             boolean cacheable = cache;
-            JexlMethod vm = uberspect.getMethod(bean, methodName, argv, node);
+            JexlMethod vm = uberspect.getMethod(bean, methodName, argv);
             // DG: If we can't find an exact match, narrow the parameters and try again
             if (vm == null) {
                 if (arithmetic.narrowArguments(argv)) {
-                    vm = uberspect.getMethod(bean, methodName, argv, node);
+                    vm = uberspect.getMethod(bean, methodName, argv);
                 }
                 if (vm == null) {
                     Object functor = null;
@@ -932,7 +932,7 @@ public class Interpreter extends ParserV
                             functor = context.get(methodName);
                         }
                     } else {
-                        JexlPropertyGet gfunctor = uberspect.getPropertyGet(bean, methodName, node);
+                        JexlPropertyGet gfunctor = uberspect.getPropertyGet(bean, methodName);
                         if (gfunctor != null) {
                             functor = gfunctor.tryInvoke(bean, methodName);
                         }
@@ -1022,11 +1022,11 @@ public class Interpreter extends ParserV
                     }
                 }
             }
-            JexlMethod ctor = uberspect.getConstructor(cobject, argv, node);
+            JexlMethod ctor = uberspect.getConstructor(cobject, argv);
             // DG: If we can't find an exact match, narrow the parameters and try again
             if (ctor == null) {
                 if (arithmetic.narrowArguments(argv)) {
-                    ctor = uberspect.getConstructor(cobject, argv, node);
+                    ctor = uberspect.getConstructor(cobject, argv);
                 }
                 if (ctor == null) {
                     xjexl = new JexlException.Method(node, cobject.toString());
@@ -1111,11 +1111,11 @@ public class Interpreter extends ParserV
             // try a contains method (duck type set)
             try {
                 Object[] argv = {left};
-                JexlMethod vm = uberspect.getMethod(right, "contains", argv, node);
+                JexlMethod vm = uberspect.getMethod(right, "contains", argv);
                 if (vm != null) {
                     return arithmetic.toBoolean(vm.invoke(right, argv)) ? Boolean.FALSE : Boolean.TRUE;
                 } else if (arithmetic.narrowArguments(argv)) {
-                    vm = uberspect.getMethod(right, "contains", argv, node);
+                    vm = uberspect.getMethod(right, "contains", argv);
                     if (vm != null) {
                         return arithmetic.toBoolean(vm.invoke(right, argv)) ? Boolean.FALSE : Boolean.TRUE;
                     }
@@ -1126,7 +1126,7 @@ public class Interpreter extends ParserV
                 throw new JexlException(node, "!~ error", e);
             }
             // try iterative comparison
-            Iterator<?> it = uberspect.getIterator(right, node.jjtGetChild(1));
+            Iterator<?> it = uberspect.getIterator(right);//, node.jjtGetChild(1));
             if (it != null) {
                 while (it.hasNext()) {
                     Object next = it.next();
@@ -1360,7 +1360,7 @@ public class Interpreter extends ParserV
             // check if there is a size method on the object that returns an
             // integer and if so, just use it
             Object[] params = new Object[0];
-            JexlMethod vm = uberspect.getMethod(val, "size", EMPTY_PARAMS, node);
+            JexlMethod vm = uberspect.getMethod(val, "size", EMPTY_PARAMS);
             if (vm != null && vm.getReturnType() == Integer.TYPE) {
                 Integer result;
                 try {
@@ -1413,7 +1413,7 @@ public class Interpreter extends ParserV
                 }
             }
         }
-        JexlPropertyGet vg = uberspect.getPropertyGet(object, attribute, node);
+        JexlPropertyGet vg = uberspect.getPropertyGet(object, attribute);
         if (vg != null) {
             try {
                 Object value = vg.invoke(object);
@@ -1476,13 +1476,13 @@ public class Interpreter extends ParserV
             }
         }
         JexlException xjexl = null;
-        JexlPropertySet vs = uberspect.getPropertySet(object, attribute, value, node);
+        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) {
             // replace all numbers with the smallest type that will fit
             Object[] narrow = {value};
             if (arithmetic.narrowArguments(narrow)) {
-                vs = uberspect.getPropertySet(object, attribute, narrow[0], node);
+                vs = uberspect.getPropertySet(object, attribute, narrow[0]);
             }
         }
         if (vs != null) {

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=1220681&r1=1220680&r2=1220681&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 Mon Dec 19 10:43:35 2011
@@ -1121,7 +1121,7 @@ public final class TemplateEngine extend
                 } else if (arg != null) {
                     Object[] value = {arg};
                     JexlUberspect uber = getEngine().getUberspect();
-                    JexlMethod method = uber.getMethod(writer, "print", value, null);
+                    JexlMethod method = uber.getMethod(writer, "print", value);
                     if (method != null) {
                         method.invoke(writer, value);
                     } else {

Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/AbstractExecutor.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/AbstractExecutor.java?rev=1220681&r1=1220680&r2=1220681&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/AbstractExecutor.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/AbstractExecutor.java Mon Dec 19 10:43:35 2011
@@ -20,8 +20,6 @@ import org.apache.commons.jexl3.introspe
 import org.apache.commons.jexl3.introspection.JexlPropertyGet;
 import org.apache.commons.jexl3.introspection.JexlPropertySet;
 
-import java.lang.reflect.InvocationTargetException;
-
 /**
  * Abstract class that is used to execute an arbitrary
  * method that is introspected. This is the superclass
@@ -29,7 +27,7 @@ import java.lang.reflect.InvocationTarge
  *
  * @since 1.0
  */
-public abstract class AbstractExecutor {
+abstract class AbstractExecutor {
     /** A marker for invocation failures in tryInvoke. */
     public static final Object TRY_FAILED = new Object() {
         @Override
@@ -54,6 +52,34 @@ public abstract class AbstractExecutor {
     }
 
     /**
+     * Coerce an Object  to an Integer.
+     * @param arg the Object to coerce
+     * @return an Integer if it can be converted, null otherwise
+     */
+    static Integer toInteger(Object arg) {
+        if (arg == null) {
+            return null;
+        } else if (arg instanceof Number) {
+            return Integer.valueOf(((Number) arg).intValue());
+        } else {
+            try {
+                return Integer.valueOf(arg.toString());
+            } catch (NumberFormatException xnumber) {
+                return null;
+            }
+        }
+    }
+
+    /**
+     * Coerce an Object to a String.
+     * @param arg the Object to coerce
+     * @return a String if it can be converted, null otherwise
+     */
+    static String toString(Object arg) {
+        return arg == null ? null : arg.toString();
+    }
+
+    /**
      * Creates an arguments array.
      * @param args the list of arguments
      * @return the arguments array
@@ -61,7 +87,7 @@ public abstract class AbstractExecutor {
     static Object[] makeArgs(Object... args) {
         return args;
     }
-
+    
     /** The class this executor applies to. */
     protected final Class<?> objectClass;
     /** Method to be executed. */
@@ -152,7 +178,7 @@ public abstract class AbstractExecutor {
     public final Class<?> getTargetClass() {
         return objectClass;
     }
-    
+
     /**
      * Gets the property targeted by this executor.
      * @return the target property
@@ -169,7 +195,6 @@ public abstract class AbstractExecutor {
         return method.getName();
     }
 
-
     /**
      * Checks whether a tryExecute failed or not.
      * @param exec the value returned by tryExecute
@@ -191,46 +216,8 @@ public abstract class AbstractExecutor {
         protected Get(Class<?> theClass, java.lang.reflect.Method theMethod) {
             super(theClass, theMethod);
         }
-
-        @Override
-        public final Object invoke(Object obj) throws Exception {
-            return execute(obj);
-        }
-        
-        @Override
-        public final Object tryInvoke(Object obj, Object key) {
-            return tryExecute(obj, key);
-        }
-
-        /**
-         * Gets the property value from an object.
-         *
-         * @param obj The object to get the property from.
-         * @return The property value.
-         * @throws IllegalAccessException Method is inaccessible.
-         * @throws InvocationTargetException Method body throws an exception.
-         */
-        public abstract Object execute(Object obj)
-                throws IllegalAccessException, InvocationTargetException;
-
-        /**
-         * Tries to reuse this executor, checking that it is compatible with
-         * the actual set of arguments.
-         * <p>Compatibility means that:
-         * <code>o</code> must be of the same class as this executor's
-         * target class and
-         * <code>property</code> must be of the same class as this
-         * executor's target property (for list and map based executors) and have the same
-         * value (for other types).</p>
-         * @param obj The object to get the property from.
-         * @param key The property to get from the object.
-         * @return The property value or TRY_FAILED if checking failed.
-         */
-        public Object tryExecute(Object obj, Object key) {
-            return TRY_FAILED;
-        }
     }
-    
+
     /**
      * Abstract class that is used to execute an arbitrary 'set' method.
      */
@@ -243,94 +230,24 @@ public abstract class AbstractExecutor {
         protected Set(Class<?> theClass, java.lang.reflect.Method theMethod) {
             super(theClass, theMethod);
         }
-
-        @Override
-        public final Object invoke(Object obj, Object arg) throws Exception {
-            return execute(obj, arg);
-        }
-
-        @Override
-        public final Object tryInvoke(Object obj, Object key, Object value) {
-            return tryExecute(obj, key, value);
-        }
-
-        /**
-         * Sets the property value of an object.
-         *
-         * @param obj The object to set the property in.
-         * @param value The value.
-         * @return The return value.
-         * @throws IllegalAccessException Method is inaccessible.
-         * @throws InvocationTargetException Method body throws an exception.
-         */
-        public abstract Object execute(Object obj, Object value)
-                throws IllegalAccessException, InvocationTargetException;
-
-        /**
-         * Tries to reuse this executor, checking that it is compatible with
-         * the actual set of arguments.
-         * <p>Compatibility means that:
-         * <code>o</code> must be of the same class as this executor's
-         * target class,
-         * <code>property</code> must be of the same class as this
-         * executor's target property (for list and map based executors) and have the same
-         * value (for other types)
-         * and that <code>arg</code> must be a valid argument for this
-         * executor underlying method.</p>
-         * @param obj The object to invoke the method from.
-         * @param key The property to set in the object.
-         * @param value The value to use as the property value.
-         * @return The return value or TRY_FAILED if checking failed.
-         */
-        public Object tryExecute(Object obj, Object key, Object value) {
-            return TRY_FAILED;
-        }
-        
     }
 
-
-
     /**
      * Abstract class that is used to execute an arbitrary method.
      */
     public abstract static class Method extends AbstractExecutor implements JexlMethod {
-        /**
-         * A helper class to pass the method &amp; parameters.
-         */
-        protected static final class Parameter {
-            /** The method. */
-            private final java.lang.reflect.Method method;
-            /** The method key. */
-            private final MethodKey key;
-            /** Creates an instance.
-             * @param m the method
-             * @param k the method key
-             */
-            public Parameter(java.lang.reflect.Method m, MethodKey k) {
-                method = m;
-                key = k;
-            }
-        }
         /** The method key discovered from the arguments. */
         protected final MethodKey key;
+
         /**
          * Creates a new instance.
          * @param c the class this executor applies to
-         * @param km the method and MethodKey to encapsulate.
+         * @param m the method
+         * @param k the MethodKey
          */
-        protected Method(Class<?> c, Parameter km) {
-            super(c, km.method);
-            key = km.key;
-        }
-
-        @Override
-        public final Object invoke(Object obj, Object[] params) throws Exception {
-            return execute(obj, params);
-        }
-
-        @Override
-        public final Object tryInvoke(String name, Object obj, Object[] params) {
-            return tryExecute(name, obj, params);
+        protected Method(Class<?> c, java.lang.reflect.Method m, MethodKey k) {
+            super(c, m);
+            key = k;
         }
 
         /** {@inheritDoc} */
@@ -338,36 +255,10 @@ public abstract class AbstractExecutor {
         public Object getTargetProperty() {
             return key;
         }
-        
+
         @Override
         public final Class<?> getReturnType() {
             return method.getReturnType();
         }
-
-        /**
-         * Invokes the method to be executed.
-         *
-         * @param obj the object to invoke the method upon
-         * @param args the method arguments
-         * @return the result of the method invocation
-         * @throws IllegalAccessException Method is inaccessible.
-         * @throws InvocationTargetException Method body throws an exception.
-         */
-        public abstract Object execute(Object obj, Object[] args)
-                throws IllegalAccessException, InvocationTargetException;
-
-        /**
-         * Tries to reuse this executor, checking that it is compatible with
-         * the actual set of arguments.
-         * @param obj the object to invoke the method upon
-         * @param name the method name
-         * @param args the method arguments
-         * @return the result of the method invocation or TRY_FAILED if checking failed.
-         */
-        public Object tryExecute(String name, Object obj, Object[] args){
-            return TRY_FAILED;
-        }
-
     }
-
 }

Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/BooleanGetExecutor.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/BooleanGetExecutor.java?rev=1220681&r1=1220680&r2=1220681&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/BooleanGetExecutor.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/BooleanGetExecutor.java Mon Dec 19 10:43:35 2011
@@ -24,33 +24,48 @@ import java.lang.reflect.InvocationTarge
 public final class BooleanGetExecutor extends AbstractExecutor.Get {
     /** The property. */
     private final String property;
+    
     /**
-     * Creates an instance by attempting discovery of the get method.
+     * Discovers a BooleanGetExecutor.
+     * <p>The method to be found should be named "is{P,p}property and return a boolean.</p>
+     * 
      * @param is the introspector
+     * @param clazz the class to find the get method from
+     * @param property the the property name
+     * @return the executor if found, null otherwise
+     */
+    public static BooleanGetExecutor discover(Introspector is, final Class<?> clazz, String property) {
+        java.lang.reflect.Method m = PropertyGetExecutor.discoverGet(is, "is", clazz, property);
+        if (m != null && (m.getReturnType() == Boolean.TYPE || m.getReturnType() == Boolean.class)) {
+            return new BooleanGetExecutor(clazz, m, property);
+        } else {
+            return null;
+        }
+    }
+    
+    /**
+     * Creates an instance by attempting discovery of the get method.
      * @param clazz the class to introspect
+     * @param method the method held by this executor
      * @param key the property to get
      */
-    public BooleanGetExecutor(Introspector is, Class<?> clazz, String key) {
-        super(clazz, discover(is, clazz, key));
+    private BooleanGetExecutor(Class<?> clazz, java.lang.reflect.Method method, String key) {
+        super(clazz, method);
         property = key;
     }
 
-    /** {@inheritDoc} */
     @Override
     public Object getTargetProperty() {
         return property;
     }
 
-    /** {@inheritDoc} */
     @Override
-    public Object execute(Object obj)
-        throws IllegalAccessException, InvocationTargetException {
+    public Object invoke(Object obj) throws IllegalAccessException, InvocationTargetException {
         return method == null ? null : method.invoke(obj, (Object[]) null);
     }
     
-    /** {@inheritDoc} */
     @Override
-    public Object tryExecute(Object obj, Object key) {
+    public Object tryInvoke(Object obj, Object key) {
         if (obj != null && method !=  null
             // ensure method name matches the property name
             && property.equals(key)
@@ -65,18 +80,4 @@ public final class BooleanGetExecutor ex
         }
         return TRY_FAILED;
     }
-
-    /**
-     * Discovers the method for a {@link BooleanGet}.
-     * <p>The method to be found should be named "is{P,p}property and return a boolean.</p>
-     *@param is the introspector
-     *@param clazz the class to find the get method from
-     *@param property the the property name
-     *@return the method if found, null otherwise
-     */
-    static java.lang.reflect.Method discover(Introspector is, final Class<?> clazz, String property) {
-        java.lang.reflect.Method m = PropertyGetExecutor.discoverGet(is, "is", clazz, property);
-        return (m != null && m.getReturnType() == Boolean.TYPE) ? m : null;
-    }
-
 }
\ No newline at end of file

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=1220681&r1=1220680&r2=1220681&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 Mon Dec 19 10:43:35 2011
@@ -77,7 +77,7 @@ final class ClassMap {
     /**
      * Keep track of all methods with the same name; this is not modified after creation.
      */
-    private final Map<String, List<Method>> byName = new HashMap<String, List<Method>>();
+    private final Map<String, Method[]> byName = new HashMap<String, Method[]>();
     /** 
      * Cache of fields.
      */
@@ -130,8 +130,7 @@ final class ClassMap {
      * @return the array of method names
      */
     String[] getMethodNames() {
-        java.util.Set<String> set = byName.keySet();
-        return set.toArray(new String[set.size()]);
+        return byName.keySet().toArray(new String[byName.size()]);
     }
 
     /**
@@ -140,9 +139,9 @@ final class ClassMap {
      * @return the array of methods (null or non-empty)
      */
     Method[] getMethods(final String methodName) {
-        List<Method> lm = byName.get(methodName);
-        if (lm != null && !lm.isEmpty()) {
-            return lm.toArray(new Method[lm.size()]);
+        Method[] lm = byName.get(methodName);
+        if (lm != null && lm.length > 0) {
+            return lm.clone();
         } else {
             return null;
         }
@@ -173,7 +172,7 @@ final class ClassMap {
         } else if (cacheEntry == null) {
             try {
                 // That one is expensive...
-                List<Method> methodList = byName.get(methodKey.getMethod());
+                Method[] methodList = byName.get(methodKey.getMethod());
                 if (methodList != null) {
                     cacheEntry = methodKey.getMostSpecificMethod(methodList);
                 }
@@ -244,7 +243,7 @@ final class ClassMap {
                         break;
                     }
                 }
-                List<Method> lmn = lm.subList(start, end);
+                Method[] lmn = lm.subList(start, end).toArray(new Method[end - start]);
                 cache.byName.put(name, lmn);
                 start = end;
             }

Added: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/ConstructorMethod.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/ConstructorMethod.java?rev=1220681&view=auto
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/ConstructorMethod.java (added)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/ConstructorMethod.java Mon Dec 19 10:43:35 2011
@@ -0,0 +1,124 @@
+/*
+ * 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.internal.introspection;
+
+import java.beans.IntrospectionException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import org.apache.commons.jexl3.introspection.JexlMethod;
+
+/**
+ * A JexlMethod that wraps a constructor.
+ */
+public final class ConstructorMethod implements JexlMethod {
+    /** The wrapped constructor. */
+    private final Constructor<?> ctor;
+
+    /**
+     * Discovers a class constructor and wrap it as a JexlMethod.
+     * @param is the introspector
+     * @param ctorHandle a class or class name
+     * @param args constructor arguments
+     * @return a {@link JexlMethod}
+     */
+    public static ConstructorMethod discover(Introspector is, Object ctorHandle, Object[] args) {
+        String className = null;
+        Class<?> clazz = null;
+        if (ctorHandle instanceof Class<?>) {
+            clazz = (Class<?>) ctorHandle;
+            className = clazz.getName();
+        } else if (ctorHandle != null) {
+            className = ctorHandle.toString();
+        } else {
+            return null;
+        }
+        Constructor<?> ctor = is.getConstructor(clazz, new MethodKey(className, args));
+        if (ctor != null) {
+            return new ConstructorMethod(ctor);
+        } else {
+            return null;
+        }
+    }
+    /**
+     * Creates a constructor method.
+     * @param theCtor the constructor to wrap
+     */
+    ConstructorMethod(Constructor<?> theCtor) {
+        this.ctor = theCtor;
+    }
+
+    @Override
+    public Object invoke(Object obj, Object[] params) throws Exception {
+        Class<?> ctorClass = ctor.getDeclaringClass();
+        boolean invoke = true;
+        if (obj != null) {
+            if (obj instanceof Class<?>) {
+                invoke = ctorClass.equals((Class<?>) obj);
+            } else {
+                invoke = ctorClass.getName().equals(obj.toString());
+            }
+        }
+        if (invoke) {
+            return ctor.newInstance(params);
+        }
+        throw new IntrospectionException("constructor resolution error");
+    }
+
+    @Override
+    public Object tryInvoke(String name, Object obj, Object[] params) {
+        try {
+            Class<?> ctorClass = ctor.getDeclaringClass();
+            boolean invoke = true;
+            if (obj != null) {
+                if (obj instanceof Class<?>) {
+                    invoke = ctorClass.equals((Class<?>) obj);
+                } else {
+                    invoke = ctorClass.getName().equals(obj.toString());
+                }
+            }
+            invoke &= name == null || ctorClass.getName().equals(name);
+            if (invoke) {
+                return ctor.newInstance(params);
+            }
+        } catch (InstantiationException xinstance) {
+            return Uberspect.TRY_FAILED;
+        } catch (IllegalAccessException xaccess) {
+            return Uberspect.TRY_FAILED;
+        } catch (IllegalArgumentException xargument) {
+            return Uberspect.TRY_FAILED;
+        } catch (InvocationTargetException xinvoke) {
+            return Uberspect.TRY_FAILED;
+        }
+        return Uberspect.TRY_FAILED;
+    }
+
+    @Override
+    public boolean tryFailed(Object rval) {
+        return rval == Uberspect.TRY_FAILED;
+    }
+
+    @Override
+    public boolean isCacheable() {
+        return true;
+    }
+
+    @Override
+    public Class<?> getReturnType() {
+        return ctor.getDeclaringClass();
+    }
+    
+}

Propchange: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/ConstructorMethod.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/DuckGetExecutor.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/DuckGetExecutor.java?rev=1220681&r1=1220680&r2=1220681&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/DuckGetExecutor.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/DuckGetExecutor.java Mon Dec 19 10:43:35 2011
@@ -34,43 +34,45 @@ public final class DuckGetExecutor exten
     private final Object property;
 
     /**
-     * Creates an instance by attempting discovery of the get method.
+     * Attempts to discover a DuckGetExecutor.
      * @param is the introspector
-     * @param clazz the class to introspect
+     * @param clazz the class to find the get method from
+     * @param identifier the key to use as an argument to the get method
+     * @return the executor if found, null otherwise
+     */
+    public static DuckGetExecutor discover(Introspector is, Class<?> clazz, Object identifier) {
+        java.lang.reflect.Method method = is.getMethod(clazz, "get", makeArgs(identifier));
+        return method == null? null : new DuckGetExecutor(clazz, method, identifier);
+    }
+
+    /**
+     * Creates an instance.
+     * @param clazz he class the get method applies to
+     * @param method the method held by this executor
      * @param identifier the property to get
      */
-    public DuckGetExecutor(Introspector is, Class<?> clazz, Object identifier) {
-        super(clazz, discover(is, clazz, identifier));
+    private DuckGetExecutor(Class<?> clazz, java.lang.reflect.Method method, Object identifier) {
+        super(clazz, method);
         property = identifier;
     }
 
-    /** {@inheritDoc} */
     @Override
     public Object getTargetProperty() {
         return property;
     }
 
-    /**
-     * Get the property from the object.
-     * @param obj the object.
-     * @return object.get(property)
-     * @throws IllegalAccessException Method is inaccessible.
-     * @throws InvocationTargetException Method body throws an exception.
-     */
     @Override
-    public Object execute(Object obj)
-            throws IllegalAccessException, InvocationTargetException {
+    public Object invoke(Object obj) throws IllegalAccessException, InvocationTargetException {
         Object[] args = {property};
         return method == null ? null : method.invoke(obj, args);
     }
 
-    /** {@inheritDoc} */
     @Override
-    public Object tryExecute(Object obj, Object key) {
-        if (obj != null && method !=  null
-            // ensure method name matches the property name
-            && property.equals(key)
-            && objectClass.equals(obj.getClass())) {
+    public Object tryInvoke(Object obj, Object key) {
+        if (obj != null && method != null
+                // ensure method name matches the property name
+                && property.equals(key)
+                && objectClass.equals(obj.getClass())) {
             try {
                 Object[] args = {property};
                 return method.invoke(obj, args);
@@ -82,16 +84,4 @@ public final class DuckGetExecutor exten
         }
         return TRY_FAILED;
     }
-
-    /**
-     * Discovers a method for a {@link GetExecutor.DuckGet}.
-     *@param is the introspector
-     *@param clazz the class to find the get method from
-     *@param identifier the key to use as an argument to the get method
-     *@return the method if found, null otherwise
-     */
-    private static java.lang.reflect.Method discover(Introspector is,
-            final Class<?> clazz, Object identifier) {
-        return is.getMethod(clazz, "get", makeArgs(identifier));
-    }
 }

Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/DuckSetExecutor.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/DuckSetExecutor.java?rev=1220681&r1=1220680&r2=1220681&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/DuckSetExecutor.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/DuckSetExecutor.java Mon Dec 19 10:43:35 2011
@@ -34,27 +34,37 @@ public final class DuckSetExecutor exten
     private final Object property;
     
     /**
+     * Discovers a DuckSetExecutor.
+     * 
+     * @param is the introspector
+     * @param clazz the class to find the set method from
+     * @param key the key to use as 1st argument to the set method
+     * @param value the value to use as 2nd argument to the set method
+     * @return the executor if found, null otherwise
+     */
+    public static DuckSetExecutor discover(Introspector is, Class<?> clazz, Object key, Object value) {
+        java.lang.reflect.Method method = is.getMethod(clazz, "set", makeArgs(key, value));
+        return method == null? null : new DuckSetExecutor(clazz, method, key);
+    }
+    
+    /**
      * Creates an instance.
-     *@param is the introspector
-     *@param clazz the class to find the set method from
-     *@param key the key to use as 1st argument to the set method
-     *@param value the value to use as 2nd argument to the set method
+     * @param clazz the class the set method applies to
+     * @param method the method called through this executor
+     * @param key the key to use as 1st argument to the set method
      */
-    public DuckSetExecutor(Introspector is, Class<?> clazz, Object key, Object value) {
-        super(clazz, discover(is, clazz, key, value));
+    private DuckSetExecutor(Class<?> clazz, java.lang.reflect.Method method, Object key) {
+        super(clazz, method);
         property = key;
     }
 
-    /** {@inheritDoc} */
     @Override
     public Object getTargetProperty() {
         return property;
     }
 
-    /** {@inheritDoc} */
     @Override
-    public Object execute(Object obj, Object value)
-            throws IllegalAccessException, InvocationTargetException {
+    public Object invoke(Object obj, Object value) throws IllegalAccessException, InvocationTargetException {
         Object[] pargs = {property, value};
         if (method != null) {
             method.invoke(obj, pargs);
@@ -62,9 +72,8 @@ public final class DuckSetExecutor exten
         return value;
     }
 
-    /** {@inheritDoc} */
     @Override
-    public Object tryExecute(Object obj, Object key, Object value) {
+    public Object tryInvoke(Object obj, Object key, Object value) {
         if (obj != null && method !=  null
             // ensure method name matches the property name
             && property.equals(key)
@@ -81,17 +90,4 @@ public final class DuckSetExecutor exten
         }
         return TRY_FAILED;
     }
-
-    /**
-     * Discovers the method for a {@link DuckSet}.
-     *@param is the introspector
-     *@param clazz the class to find the set method from
-     *@param key the key to use as 1st argument to the set method
-     *@param value the value to use as 2nd argument to the set method
-     *@return the method if found, null otherwise
-     */
-    private static java.lang.reflect.Method discover(Introspector is,
-            Class<?> clazz, Object key, Object value) {
-        return is.getMethod(clazz, "set", makeArgs(key, value));
-    }
 }
\ No newline at end of file

Added: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/FieldGetExecutor.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/FieldGetExecutor.java?rev=1220681&view=auto
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/FieldGetExecutor.java (added)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/FieldGetExecutor.java Mon Dec 19 10:43:35 2011
@@ -0,0 +1,84 @@
+/*
+ * 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.internal.introspection;
+
+import java.lang.reflect.Field;
+import org.apache.commons.jexl3.introspection.JexlPropertyGet;
+
+/**
+ * A JexlPropertyGet for public fields.
+ */
+public final class FieldGetExecutor implements JexlPropertyGet {
+    /**
+     * The public field.
+     */
+    private final Field field;
+
+    /**
+     * Attempts to discover a FieldGetExecutor.
+     * 
+     * @param is the introspector
+     * @param clazz the class to find the get method from
+     * @param identifier the key to use as an argument to the get method
+     * @return the executor if found, null otherwise
+     */
+    public static JexlPropertyGet discover(Introspector is, Class<?> clazz, String identifier) {
+        if (identifier != null) {
+            Field field = is.getField(clazz, identifier);
+            if (field != null) {
+                return new FieldGetExecutor(field);
+            }
+        }
+        return null;
+    }
+    /**
+     * Creates a new instance of FieldPropertyGet.
+     * @param theField the class public field
+     */
+    private FieldGetExecutor(Field theField) {
+        field = theField;
+    }
+
+    @Override
+    public Object invoke(Object obj) throws Exception {
+        return field.get(obj);
+    }
+
+    @Override
+    public Object tryInvoke(Object obj, Object key) {
+        if (obj.getClass().equals(field.getDeclaringClass()) && key.equals(field.getName())) {
+            try {
+                return field.get(obj);
+            } catch (IllegalAccessException xill) {
+                return Uberspect.TRY_FAILED;
+            }
+        }
+        return Uberspect.TRY_FAILED;
+    }
+
+    @Override
+    public boolean tryFailed(Object rval) {
+        return rval == Uberspect.TRY_FAILED;
+    }
+
+    @Override
+    public boolean isCacheable() {
+        return true;
+    }
+    
+}

Propchange: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/FieldGetExecutor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/FieldSetExecutor.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/FieldSetExecutor.java?rev=1220681&view=auto
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/FieldSetExecutor.java (added)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/FieldSetExecutor.java Mon Dec 19 10:43:35 2011
@@ -0,0 +1,92 @@
+/*
+ * 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.internal.introspection;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import org.apache.commons.jexl3.introspection.JexlPropertySet;
+
+/**
+ * A JexlPropertySet for public fields.
+ */
+public final class FieldSetExecutor implements JexlPropertySet {
+    /**
+     * The public field.
+     */
+    private final Field field;
+
+    /**
+     * Attempts to discover a FieldSetExecutor.
+     * 
+     * @param is the introspector
+     * @param clazz the class to find the get method from
+     * @param identifier the key to use as an argument to the get method
+     * @param value the value to set the field to
+     * @return the executor if found, null otherwise
+     */
+    public static JexlPropertySet discover(Introspector is, Class<?> clazz, String identifier, Object value) {
+        if (identifier != null) {
+            Field field = is.getField(clazz, identifier);
+            if (field != null
+                && !Modifier.isFinal(field.getModifiers())
+                && (value == null || MethodKey.isInvocationConvertible(field.getType(), value.getClass(), false))) {
+                return new FieldSetExecutor(field);
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Creates a new instance of FieldPropertySet.
+     * @param theField the class public field
+     */
+    private FieldSetExecutor(Field theField) {
+        field = theField;
+    }
+
+    @Override
+    public Object invoke(Object obj, Object arg) throws Exception {
+        field.set(obj, arg);
+        return arg;
+    }
+
+    @Override
+    public Object tryInvoke(Object obj, Object key, Object value) {
+        if (obj.getClass().equals(field.getDeclaringClass())
+            && key.equals(field.getName())
+            && (value == null || MethodKey.isInvocationConvertible(field.getType(), value.getClass(), false))) {
+            try {
+                field.set(obj, value);
+                return value;
+            } catch (IllegalAccessException xill) {
+                return Uberspect.TRY_FAILED;
+            }
+        }
+        return Uberspect.TRY_FAILED;
+    }
+
+    @Override
+    public boolean tryFailed(Object rval) {
+        return rval == Uberspect.TRY_FAILED;
+    }
+
+    @Override
+    public boolean isCacheable() {
+        return true;
+    }
+}

Propchange: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/FieldSetExecutor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/IndexedType.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/IndexedType.java?rev=1220681&view=auto
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/IndexedType.java (added)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/IndexedType.java Mon Dec 19 10:43:35 2011
@@ -0,0 +1,197 @@
+/*
+ * 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.internal.introspection;
+
+
+import org.apache.commons.jexl3.introspection.JexlPropertyGet;
+import java.lang.reflect.Method;
+import java.beans.IntrospectionException;
+
+/**
+ * Abstract an indexed property container.
+ * This stores the container name and owning class as well as the list of available getter and setter methods.
+ * It implements JexlPropertyGet since such a container can only be accessed from its owning instance (not set).
+ */
+public final class IndexedType implements JexlPropertyGet {
+    /** The container name. */
+    private final String container;
+    /** The owning class. */
+    private final Class<?> clazz;
+    /** The array of getter methods. */
+    private final Method[] getters;
+    /** The array of setter methods. */
+    private final Method[] setters;
+
+    /**
+     * Attempts to find an indexed-property getter in an object.
+     * The code attempts to find the list of methods getXXX() and setXXX().
+     * Note that this is not equivalent to the strict bean definition of indexed properties; the type of the key
+     * is not necessarily an int and the set/get arrays are not resolved.
+     * 
+     * @param is the introspector
+     * @param object the object
+     * @param name the container name
+     * @return a JexlPropertyGet is successfull, null otherwise
+     */
+    public static JexlPropertyGet discover(Introspector is, Object object, String name) {
+        if (object != null && name != null) {
+            String base = name.substring(0, 1).toUpperCase() + name.substring(1);
+            final String container = name;
+            final Class<?> clazz = object.getClass();
+            final Method[] getters = is.getMethods(object.getClass(), "get" + base);
+            final Method[] setters = is.getMethods(object.getClass(), "set" + base);
+            if (getters != null) {
+                return new IndexedType(container, clazz, getters, setters);
+            }
+        }
+        return null;
+    }
+    
+    /**
+     * A generic indexed property container, exposes get(key) and set(key, value) and solves method call dynamically
+     * based on arguments.
+     * <p>Must remain public for introspection purpose.</p>
+     */
+    public static final class IndexedContainer {
+        /** The instance owning the container. */
+        private final Object object;
+        /** The container type instance. */
+        private final IndexedType type;
+
+        /**
+         * Creates a new duck container.
+         * @param theType the container type
+         * @param theObject the instance owning the container
+         */
+        private IndexedContainer(IndexedType theType, Object theObject) {
+            this.type = theType;
+            this.object = theObject;
+        }
+
+        /**
+         * Gets a property from a container.
+         * @param key the property key
+         * @return the property value
+         * @throws Exception if inner invocation fails
+         */
+        public Object get(Object key) throws Exception {
+            return type.invokeGet(object, key);
+        }
+
+        /**
+         * Sets a property in a container.
+         * @param key the property key
+         * @param value the property value
+         * @return the invocation result (frequently null)
+         * @throws Exception if inner invocation fails
+         */
+        public Object set(Object key, Object value) throws Exception {
+            return type.invokeSet(object, key, value);
+        }
+    }
+    
+    /**
+     * Creates a new indexed type.
+     * @param name the container name
+     * @param c the owning class
+     * @param gets the array of getter methods
+     * @param sets the array of setter methods
+     */
+    private IndexedType(String name, Class<?> c, Method[] gets, Method[] sets) {
+        this.container = name;
+        this.clazz = c;
+        this.getters = gets;
+        this.setters = sets;
+    }
+
+    @Override
+    public Object invoke(Object obj) throws Exception {
+        if (obj != null && clazz.equals(obj.getClass())) {
+            return new IndexedContainer(this, obj);
+        } else {
+            throw new IntrospectionException("property resolution error");
+        }
+    }
+
+    @Override
+    public Object tryInvoke(Object obj, Object key) {
+        if (obj != null && key != null && clazz.equals(obj.getClass()) && container.equals(key.toString())) {
+            return new IndexedContainer(this, obj);
+        } else {
+            return Uberspect.TRY_FAILED;
+        }
+    }
+
+    @Override
+    public boolean tryFailed(Object rval) {
+        return rval == Uberspect.TRY_FAILED;
+    }
+
+    @Override
+    public boolean isCacheable() {
+        return true;
+    }
+
+    /**
+     * Gets the value of a property from a container.
+     * @param object the instance owning the container (not null)
+     * @param key the property key (not null)
+     * @return the property value
+     * @throws Exception if invocation failed; IntrospectionException if a property getter could not be found
+     */
+    private Object invokeGet(Object object, Object key) throws Exception {
+        if (getters != null) {
+            final Object[] args = {key};
+            final Method jm;
+            if (getters.length == 1) {
+                jm = getters[0];
+            } else {
+                jm = new MethodKey(getters[0].getName(), args).getMostSpecificMethod(getters);
+            }
+            if (jm != null) {
+                return jm.invoke(object, args);
+            }
+        }
+        throw new IntrospectionException("property get error: " + object.getClass().toString() + "@" + key.toString());
+    }
+
+    /**
+     * Sets the value of a property in a container.
+     * @param object the instance owning the container (not null)
+     * @param key the property key (not null)
+     * @param value the property value (not null)
+     * @return the result of the method invocation (frequently null)
+     * @throws Exception if invocation failed; IntrospectionException if a property setter could not be found
+     */
+    private Object invokeSet(Object object, Object key, Object value) throws Exception {
+        if (setters != null) {
+            final Object[] args = {key, value};
+            final Method jm;
+            if (setters.length == 1) {
+                jm = setters[0];
+            } else {
+                jm = new MethodKey(setters[0].getName(), args).getMostSpecificMethod(setters);
+            }
+            if (jm != null) {
+                return jm.invoke(object, args);
+            }
+        }
+        throw new IntrospectionException("property set error: " + object.getClass().toString() + "@" + key.toString());
+    }
+    
+}

Propchange: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/IndexedType.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/Introspector.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/Introspector.java?rev=1220681&r1=1220680&r2=1220681&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/Introspector.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/Introspector.java Mon Dec 19 10:43:35 2011
@@ -23,9 +23,9 @@ import java.lang.reflect.Field;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
-import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 
@@ -251,14 +251,14 @@ public final class Introspector {
                     // add it to list of known loaded classes
                     constructibleClasses.put(cname, clazz);
                 }
-                List<Constructor<?>> l = new LinkedList<Constructor<?>>();
+                List<Constructor<?>> l = new ArrayList<Constructor<?>>();
                 for (Constructor<?> ictor : clazz.getConstructors()) {
                     if (Modifier.isPublic(ictor.getModifiers()) && Permissions.allow(ictor)) {
                         l.add(ictor);
                     }
                 }
                 // try to find one
-                ctor = key.getMostSpecificConstructor(l);
+                ctor = key.getMostSpecificConstructor(l.toArray(new Constructor<?>[l.size()]));
                 if (ctor != null) {
                     constructorsMap.put(key, ctor);
                 } else {

Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/ListGetExecutor.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/ListGetExecutor.java?rev=1220681&r1=1220680&r2=1220681&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/ListGetExecutor.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/ListGetExecutor.java Mon Dec 19 10:43:35 2011
@@ -14,8 +14,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 package org.apache.commons.jexl3.internal.introspection;
+
 import java.util.List;
 import java.lang.reflect.Array;
 
@@ -34,29 +34,44 @@ public final class ListGetExecutor exten
     private final Integer property;
 
     /**
-     * Creates an instance checking for the List interface or Array capability.
+     * Attempts to discover a ListGetExecutor.
+     * 
      * @param is the introspector
-     * @param clazz the class to introspect
-     * @param key the key to use in obj.get(key)
+     * @param clazz the class to find the get method from
+     * @param identifier the key to use as an argument to the get method
+     * @return the executor if found, null otherwise
      */
-    public ListGetExecutor(Introspector is, Class<?> clazz, Integer key) {
-        super(clazz, discover(clazz));
-        property = key;
+    public static ListGetExecutor discover(Introspector is, Class<?> clazz, Object identifier) {
+        java.lang.reflect.Method method = null;
+        Integer index = toInteger(identifier);
+        if (index != null) {
+            if (clazz.isArray()) {
+                method = ARRAY_GET;
+            } else if (List.class.isAssignableFrom(clazz)) {
+                method = LIST_GET;
+            }
+        }
+        return method == null ? null : new ListGetExecutor(clazz, method, index);
+    }
+
+    /**
+     * Creates an instance.
+     * @param clazz he class the get method applies to
+     * @param method the method held by this executor
+     * @param identifier the property to get
+     */
+    private ListGetExecutor(Class<?> clazz, java.lang.reflect.Method method, Integer identifier) {
+        super(clazz, method);
+        property = identifier;
     }
 
-    /** {@inheritDoc} */
     @Override
     public Object getTargetProperty() {
         return property;
     }
-    
-    /**
-     * Get the property from the obj or array.
-     * @param obj the List/array.
-     * @return obj.get(key)
-     */
+
     @Override
-    public Object execute(final Object obj) {
+    public Object invoke(final Object obj) {
         if (method == ARRAY_GET) {
             return java.lang.reflect.Array.get(obj, property.intValue());
         } else {
@@ -64,35 +79,18 @@ public final class ListGetExecutor exten
         }
     }
 
-    /** {@inheritDoc} */
     @Override
-    public Object tryExecute(final Object obj, Object key) {
+    public Object tryInvoke(final Object obj, Object key) {
+        Integer index = toInteger(key);
         if (obj != null && method != null
             && objectClass.equals(obj.getClass())
-            && key instanceof Integer) {
+            && index != null) {
             if (method == ARRAY_GET) {
-                return java.lang.reflect.Array.get(obj, ((Integer) key).intValue());
+                return java.lang.reflect.Array.get(obj, index.intValue());
             } else {
-                return ((List<?>) obj).get(((Integer) key).intValue());
+                return ((List<?>) obj).get(index.intValue());
             }
         }
         return TRY_FAILED;
     }
-
-
-    /**
-     * Finds the method to perform the get on a obj of array.
-     * @param clazz the class to introspect
-     * @return a marker method, obj.get or array.get
-     */
-    static java.lang.reflect.Method discover(Class<?> clazz) {
-        //return discoverList(false, clazz, property);
-        if (clazz.isArray()) {
-            return ARRAY_GET;
-        }
-        if (List.class.isAssignableFrom(clazz)) {
-            return LIST_GET;
-        }
-        return null;
-    }
 }

Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/ListSetExecutor.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/ListSetExecutor.java?rev=1220681&r1=1220680&r2=1220681&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/ListSetExecutor.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/ListSetExecutor.java Mon Dec 19 10:43:35 2011
@@ -14,8 +14,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 package org.apache.commons.jexl3.internal.introspection;
+
 import java.util.List;
 import java.lang.reflect.Array;
 
@@ -24,7 +24,7 @@ import java.lang.reflect.Array;
  * @since 2.0
  */
 public final class ListSetExecutor extends AbstractExecutor.Set {
-        /** The java.lang.reflect.Array.get method used as an active marker in ListGet. */
+    /** The java.lang.reflect.Array.get method used as an active marker in ListGet. */
     private static final java.lang.reflect.Method ARRAY_SET =
             initMarker(Array.class, "set", Object.class, Integer.TYPE, Object.class);
     /** The java.util.obj.set method used as an active marker in ListSet. */
@@ -34,26 +34,52 @@ public final class ListSetExecutor exten
     private final Integer property;
 
     /**
-     * Creates an instance checking for the List interface or Array capability.
+     * Attempts to discover a ListSetExecutor.
+     * 
      * @param is the introspector
-     * @param clazz the class that might implement the map interface
-     * @param key the key to use in obj.set(key,value)
-     * @param value the value to use in obj.set(key,value)
+     * @param clazz the class to find the get method from
+     * @param identifier the key to use as an argument to the get method
+     * @param value the value to use as argument in list.put(key,value)
+     * @return the executor if found, null otherwise
+     */
+    public static ListSetExecutor discover(Introspector is, Class<?> clazz, Object identifier, Object value) {
+        Integer index = toInteger(identifier);
+        java.lang.reflect.Method method = null;
+        if (index != null) {
+            if (clazz.isArray()) {
+                // we could verify if the call can be performed but it does not change
+                // the fact we would fail...
+                // Class<?> formal = clazz.getComponentType();
+                // Class<?> actual = value == null? Object.class : value.getClass();
+                // if (IntrospectionUtils.isMethodInvocationConvertible(formal, actual, false)) {
+                method = ARRAY_SET;
+                // }
+            } else if (List.class.isAssignableFrom(clazz)) {
+                method = LIST_SET;
+            }
+        }
+        return method == null ? null : new ListSetExecutor(clazz, method, index);
+    }
+
+    /**
+     * Creates an instance.
+     * 
+     * @param clazz the class the set method applies to
+     * @param method the method called through this executor
+     * @param key the key to use as 1st argument to the set method
      */
-    public ListSetExecutor(Introspector is, Class<?> clazz, Integer key, Object value) {
-        super(clazz, discover(clazz));
+    private ListSetExecutor(Class<?> clazz, java.lang.reflect.Method method, Integer key) {
+        super(clazz, method);
         property = key;
     }
 
-    /** {@inheritDoc} */
     @Override
     public Object getTargetProperty() {
         return property;
     }
-    
-    /** {@inheritDoc} */
+
     @Override
-    public Object execute(final Object obj, Object value) {
+    public Object invoke(final Object obj, Object value) {
         if (method == ARRAY_SET) {
             java.lang.reflect.Array.set(obj, property.intValue(), value);
         } else {
@@ -64,43 +90,21 @@ public final class ListSetExecutor exten
         return value;
     }
 
-    /** {@inheritDoc} */
     @Override
-    public Object tryExecute(final Object obj, Object key, Object value) {
+    public Object tryInvoke(final Object obj, Object key, Object value) {
+        Integer index = toInteger(key);
         if (obj != null && method != null
-            && objectClass.equals(obj.getClass())
-            && key instanceof Integer) {
+                && objectClass.equals(obj.getClass())
+                && index != null) {
             if (method == ARRAY_SET) {
-                Array.set(obj, ((Integer) key).intValue(), value);
+                Array.set(obj, index.intValue(), value);
             } else {
                 @SuppressWarnings("unchecked")  // LSE should only be created for array or list types
                 final List<Object> list = (List<Object>) obj;
-                list.set(((Integer) key).intValue(), value);
+                list.set(index.intValue(), value);
             }
             return value;
         }
         return TRY_FAILED;
     }
-
-
-    /**
-     * Finds the method to perform 'set' on a obj of array.
-     * @param clazz the class to introspect
-     * @return a marker method, obj.set or array.set
-     */
-    static java.lang.reflect.Method discover(Class<?> clazz) {
-        if (clazz.isArray()) {
-            // we could verify if the call can be performed but it does not change
-            // the fact we would fail...
-            // Class<?> formal = clazz.getComponentType();
-            // Class<?> actual = value == null? Object.class : value.getClass();
-            // if (IntrospectionUtils.isMethodInvocationConvertible(formal, actual, false)) {
-                return ARRAY_SET;
-            // }
-        }
-        if (List.class.isAssignableFrom(clazz)) {
-            return LIST_SET;
-        }
-        return null;
-    }
 }



Mime
View raw message