You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by ra...@apache.org on 2009/08/01 02:36:52 UTC

svn commit: r799779 [2/3] - in /commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl: ./ context/ parser/ scripting/ util/ util/introspection/

Modified: commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/scripting/JexlScriptEngine.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/scripting/JexlScriptEngine.java?rev=799779&r1=799778&r2=799779&view=diff
==============================================================================
--- commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/scripting/JexlScriptEngine.java (original)
+++ commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/scripting/JexlScriptEngine.java Sat Aug  1 00:36:51 2009
@@ -104,7 +104,7 @@
                     context.setBindings(new SimpleBindings(vars), ScriptContext.ENGINE_SCOPE);
                 }
 
-                public Map getVars() {
+                public Map<String,Object> getVars() {
                     return new JexlContextWrapper(context);
                 }
             };
@@ -137,7 +137,7 @@
      * Current implementation only gives access to ENGINE_SCOPE binding.
      */
     @SuppressWarnings("unchecked")
-    private static class JexlContextWrapper implements Map {
+    private static class JexlContextWrapper implements Map<String,Object> {
         
         private final ScriptContext context;
 
@@ -180,7 +180,7 @@
             return bnd.keySet();
         }
 
-        public Object put(final Object key, final Object value) {
+        public Object put(final String key, final Object value) {
             Bindings bnd = context.getBindings(ScriptContext.ENGINE_SCOPE);
             return bnd.put(String.valueOf(key), value);
         }

Modified: commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/AbstractExecutor.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/AbstractExecutor.java?rev=799779&r1=799778&r2=799779&view=diff
==============================================================================
--- commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/AbstractExecutor.java (original)
+++ commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/AbstractExecutor.java Sat Aug  1 00:36:51 2009
@@ -14,16 +14,17 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 package org.apache.commons.jexl.util;
+import org.apache.commons.jexl.util.introspection.MethodKey;
+import org.apache.commons.jexl.util.introspection.VelMethod;
+import org.apache.commons.jexl.util.introspection.VelPropertySet;
+import org.apache.commons.jexl.util.introspection.VelPropertyGet;
 import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-
 
 /**
  * Abstract class that is used to execute an arbitrary
  * method that is introspected. This is the superclass
- * for the GetExecutor and PropertyExecutor.
+ * for all other AbstractExecutor classes.
  *
  * @since 1.0
  * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
@@ -31,35 +32,53 @@
  * @version $Id$
  */
 public abstract class AbstractExecutor {
-    /** Empty parameters list for method matching. */
-    protected static final Object[] EMPTY_PARAMS = {};
+    /** A marker for invocation failures in tryInvoke. */
+    public static final Object TRY_FAILED = new Object() {
+        @Override
+        public String toString() {
+            return "tryExecute failed";
+        }
+    };
+
     /**
-     * Method to be executed.
+     * A helper to initialize the marker methods (array.get, list.get, etc...).
+     * @param clazz the class to introspect
+     * @param name the name of the method
+     * @param parms the parameters
+     * @return the method
      */
-    protected final Method method;
+    static java.lang.reflect.Method initMarker(Class<?> clazz, String name, Class<?>... parms) {
+        try {
+            return clazz.getMethod(name, parms);
+        } catch (Exception xnever) {
+            throw new Error(xnever);
+        }
+    }
 
     /**
-     * Default and sole constructor.
-     * @param theMethod the method held by this executor
+     * Creates an arguments array.
+     * @param args the list of arguments
+     * @return the arguments array
      */
-    protected AbstractExecutor(Method theMethod) {
-        method = theMethod;
+    static Object[] makeArgs(Object... args) {
+        return args;
     }
 
+    /** The class this executor applies to. */
+    protected final Class<?> objectClass;
+    /** Method to be executed. */
+    protected final java.lang.reflect.Method method;
+
     /**
-     * Execute method against context.
-     *
-     * @param o The owner.
-     * @return The return value.
-     * @throws IllegalAccessException Method is inaccessible.
-     * @throws InvocationTargetException Method body throws an exception.
-     */
-    public Object execute(Object o)
-            throws IllegalAccessException, InvocationTargetException {
-        return method == null? null : method.invoke(o, (Object[]) null);
+     * Default and sole constructor.
+     * @param theClass the class this executor applies to
+     * @param theMethod the method held by this executor
+     */
+    protected AbstractExecutor(Class<?> theClass, java.lang.reflect.Method theMethod) {
+        objectClass = theClass;
+        method = theMethod;
     }
 
-
     /**
      * Tell whether the executor is alive by looking
      * at the value of the method.
@@ -71,10 +90,188 @@
     }
 
     /**
-     * Gets the method to be executed.
-     * @return Method The method to be executed.
+     * Specifies if this executor is cacheable and able to be reused for this
+     * class of object it was returned for.
+     *
+     * @return true if can be reused for this class, false if not
+     */
+    public boolean isCacheable() {
+        return method != null;
+    }
+
+    /**
+     * Gets the method to be executed or used as a marker.
+     * @return Method The method used by execute in derived classes.
      */
-    public final Method getMethod() {
+    public final java.lang.reflect.Method getMethod() {
         return method;
     }
- }
\ No newline at end of file
+
+    /**
+     * Gets the method name used.
+     * @return method name
+     */
+    public final String getMethodName() {
+        return method.getName();
+    }
+
+    /**
+     * Abstract class that is used to execute an arbitrary 'get' method.
+     */
+    public abstract static class Get extends AbstractExecutor implements VelPropertyGet {
+        /**
+         * Default and sole constructor.
+         * @param theClass the class this executor applies to
+         * @param theMethod the method held by this executor
+         */
+        protected Get(Class<?> theClass, java.lang.reflect.Method theMethod) {
+            super(theClass, theMethod);
+        }
+
+        /** {@inheritDoc} */
+        public final Object invoke(Object o) throws Exception {
+            return execute(o);
+        }
+
+        /**
+         * Gets the property value from an object.
+         *
+         * @param o 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 o)
+                throws IllegalAccessException, InvocationTargetException;
+
+        /**
+         * Tries to reuse this executor, checking that it is compatible with
+         * the actual set of arguments.
+         * @param o The object to get the property from.
+         * @param property The property to get from the object.
+         * @return The property value or TRY_FAILED if checking failed.
+         */
+        public Object tryExecute(Object o, Object property) {
+            return TRY_FAILED;
+        }
+    }
+    
+    /**
+     * Abstract class that is used to execute an arbitrary 'set' method.
+     */
+    public abstract static class Set extends AbstractExecutor implements VelPropertySet {
+        /**
+         * Default and sole constructor.
+         * @param theClass the class this executor applies to
+         * @param theMethod the method held by this executor
+         */
+        protected Set(Class<?> theClass, java.lang.reflect.Method theMethod) {
+            super(theClass, theMethod);
+        }
+
+        /** {@inheritDoc} */
+        public Object invoke(Object o, Object arg) throws Exception {
+            return execute(o, arg);
+        }
+
+        /**
+         * Sets the property value of an object.
+         *
+         * @param o The object to set the property in.
+         * @param arg The value.
+         * @return The return value.
+         * @throws IllegalAccessException Method is inaccessible.
+         * @throws InvocationTargetException Method body throws an exception.
+         */
+        public abstract Object execute(Object o, Object arg)
+                throws IllegalAccessException, InvocationTargetException;
+
+        /**
+         * Tries to reuse this executor, checking that it is compatible with
+         * the actual set of arguments.
+         * @param o The object to invoke the method from.
+         * @param property The property to set in the object.
+         * @param arg The value to use as the property value.
+         * @return The return value or TRY_FAILED if checking failed.
+         */
+        public Object tryExecute(Object o, Object property, Object arg) {
+            return TRY_FAILED;
+        }
+        
+    }
+
+
+
+    /**
+     * Abstract class that is used to execute an arbitrary method.
+     */
+    public abstract static class Method extends AbstractExecutor implements VelMethod {
+        /**
+         * 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.
+         */
+        protected Method(Class<?> c, Parameter km) {
+            super(c, km.method);
+            key = km.key;
+        }
+
+        /** {@inheritDoc} */
+        public final Object invoke(Object o, Object[] args) throws Exception {
+            return execute(o, args);
+        }
+
+        /**
+         * Returns the return type of the method invoked.
+         * @return return type
+         */
+        public final Class<?> getReturnType() {
+            return method.getReturnType();
+        }
+
+        /**
+         * Invokes the method to be executed.
+         *
+         * @param o 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 o, Object[] args)
+                throws IllegalAccessException, InvocationTargetException;
+
+        /**
+         * Tries to reuse this executor, checking that it is compatible with
+         * the actual set of arguments.
+         * @param o 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 INVOKE_FAILED if checking failed.
+         */
+        public Object tryExecute(String name, Object o, Object[] args){
+            return TRY_FAILED;
+        }
+
+    }
+
+}

Modified: commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/ArrayIterator.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/ArrayIterator.java?rev=799779&r1=799778&r2=799779&view=diff
==============================================================================
--- commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/ArrayIterator.java (original)
+++ commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/ArrayIterator.java Sat Aug  1 00:36:51 2009
@@ -17,13 +17,10 @@
 
 package org.apache.commons.jexl.util;
 
-
-
 import java.util.Iterator;
 import java.util.NoSuchElementException;
 import java.lang.reflect.Array;
 
-
 /**
  *  <p>
  *  An Iterator wrapper for an Object[]. This will
@@ -44,41 +41,29 @@
  * @version $Id$
  */
 public class ArrayIterator implements Iterator<Object> {
-    /**
-     * The objects to iterate over.
-     */
+    /** The objects to iterate over. */
     private final Object array;
-
-    /**
-     * The current position and size in the array.
-     */
-    private int pos;
-
-    /**
-     * The size of the array.
-     */
+    /** The size of the array. */
     private final int size;
+    /** The current position and size in the array. */
+    private int pos;
 
     /**
      * Creates a new iterator instance for the specified array.
-     *
      * @param arr The array for which an iterator is desired.
      */
     public ArrayIterator(Object arr) {
-        /*
-         * if this isn't an array, then throw.  Note that this is 
-         * for internal use - so this should never happen - if it does
-         *  we screwed up.
-         */
-         
-        if (!arr.getClass().isArray()) {
-            throw new IllegalArgumentException("Programmer error :"
-                      + " internal ArrayIterator invoked w/o array");
+        if (arr == null) {
+            array = null;
+            pos = 0;
+            size = 0;
+        } else if (!arr.getClass().isArray()) {
+            throw new IllegalArgumentException(arr.getClass() + " is not an array");
+        } else {
+            array = arr;
+            pos = 0;
+            size = Array.getLength(array);
         }
-            
-        array = arr;
-        pos = 0;
-        size = Array.getLength(array);
     }
 
     /**
@@ -89,12 +74,8 @@
     public Object next() {
         if (pos < size) {
             return Array.get(array, pos++);
-        }
-                
-        /*
-         *  we screwed up...
-         */
-         
+        }    
+        // we screwed up...
         throw new NoSuchElementException("No more elements: " + pos
                                          + " / " + size);
     }

Modified: commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/ArrayListWrapper.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/ArrayListWrapper.java?rev=799779&r1=799778&r2=799779&view=diff
==============================================================================
--- commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/ArrayListWrapper.java (original)
+++ commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/ArrayListWrapper.java Sat Aug  1 00:36:51 2009
@@ -31,13 +31,14 @@
 
     /**
      * Create the wrapper.
-     * @param array {@link #array}
+     * @param anArray {@link #array}
      */
-    // CSOFF: HiddenField
-    public ArrayListWrapper(Object array) {
-        this.array = array;
+    public ArrayListWrapper(Object anArray) {
+        if (!anArray.getClass().isArray()) {
+            throw new IllegalArgumentException(anArray.getClass() + " is not an array");
+        }
+        this.array = anArray;
     }
-    // CSON: HiddenField
 
     /** {@inheritDoc} */
     @Override

Added: commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/BooleanGetExecutor.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/BooleanGetExecutor.java?rev=799779&view=auto
==============================================================================
--- commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/BooleanGetExecutor.java (added)
+++ commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/BooleanGetExecutor.java Sat Aug  1 00:36:51 2009
@@ -0,0 +1,75 @@
+/*
+ * 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.jexl.util;
+import java.lang.reflect.InvocationTargetException;
+/**
+ * Specialized executor to get a boolean property from an object.
+ */
+public final class BooleanGetExecutor extends AbstractExecutor.Get {
+    /** The property. */
+    private final String property;
+    /**
+     * Creates an instance by attempting discovery of the get method.
+     * @param is the introspector
+     * @param clazz the class to introspect
+     * @param identifier the property to get
+     */
+    public BooleanGetExecutor(Introspector is, Class<?> clazz, String identifier) {
+        super(clazz, discover(is, clazz, identifier));
+        property = identifier;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public Object execute(Object o)
+        throws IllegalAccessException, InvocationTargetException {
+        return method == null ? null : method.invoke(o, (Object[]) null);
+    }
+    
+    /** {@inheritDoc} */
+    @Override
+    public Object tryExecute(Object o, Object identifier) {
+        if (o != null && method !=  null
+            // ensure method name matches the property name
+            && property.equals(identifier)
+            && objectClass.equals(o.getClass())) {
+            try {
+                return method.invoke(o, (Object[]) null);
+            } catch (InvocationTargetException xinvoke) {
+                return TRY_FAILED; // fail
+            } catch (IllegalAccessException xill) {
+                return TRY_FAILED;// fail
+            }
+        }
+        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

Propchange: commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/BooleanGetExecutor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/BooleanGetExecutor.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Added: commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/DuckGetExecutor.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/DuckGetExecutor.java?rev=799779&view=auto
==============================================================================
--- commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/DuckGetExecutor.java (added)
+++ commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/DuckGetExecutor.java Sat Aug  1 00:36:51 2009
@@ -0,0 +1,94 @@
+/*
+ * 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.jexl.util;
+
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * Specialized executor to get a property from an object.
+ * <p>Duck as in duck-typing for an interface like:
+ * <code>
+ * interface Get {
+ *      Object get(Object key);
+ * }
+ * </code>
+ * </p>
+ */
+/**
+ * Specialized executor to get a property from an object.
+ * <p>Duck as in duck-typing for classes that implement an get(object) method.</p>
+ */
+public final class DuckGetExecutor extends AbstractExecutor.Get {
+    /** The property. */
+    private final Object property;
+
+    /**
+     * Creates an instance by attempting discovery of the get method.
+     * @param is the introspector
+     * @param clazz the class to introspect
+     * @param identifier the property to get
+     */
+    public DuckGetExecutor(Introspector is, Class<?> clazz, Object identifier) {
+        super(clazz, discover(is, clazz, identifier));
+        property = identifier;
+    }
+
+    /**
+     * Get the property from the object.
+     * @param o the object.
+     * @return object.get(property)
+     * @throws IllegalAccessException Method is inaccessible.
+     * @throws InvocationTargetException Method body throws an exception.
+     */
+    @Override
+    public Object execute(Object o)
+            throws IllegalAccessException, InvocationTargetException {
+        Object[] args = {property};
+        return method == null ? null : method.invoke(o, args);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public Object tryExecute(Object o, Object identifier) {
+        if (o != null && method !=  null
+            // ensure method name matches the property name
+            && property.equals(identifier)
+            && objectClass.equals(o.getClass())) {
+            try {
+                Object[] args = {property};
+                return method.invoke(o, args);
+            } catch (InvocationTargetException xinvoke) {
+                return TRY_FAILED; // fail
+            } catch (IllegalAccessException xill) {
+                return TRY_FAILED;// fail
+            }
+        }
+        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));
+    }
+}

Propchange: commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/DuckGetExecutor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/DuckGetExecutor.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Added: commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/DuckSetExecutor.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/DuckSetExecutor.java?rev=799779&view=auto
==============================================================================
--- commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/DuckSetExecutor.java (added)
+++ commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/DuckSetExecutor.java Sat Aug  1 00:36:51 2009
@@ -0,0 +1,89 @@
+/*
+ * 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.jexl.util;
+
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * Specialized executor to set a property of an object.
+ * <p>Duck as in duck-typing for an interface like:
+ * <code>
+ * interface Set {
+ *      Object put(Object property, Object value);
+ * }
+ * </code>
+ * </p>
+ */
+public final class DuckSetExecutor extends AbstractExecutor.Set {
+    /** The property. */
+    private final Object property;
+    
+    /**
+     * Creates an instance.
+     *@param is the introspector
+     *@param clazz the class to find the set method from
+     *@param identifier the key to use as 1st argument to the set method
+     *@param arg the value to use as 2nd argument to the set method
+     */
+    public DuckSetExecutor(Introspector is, Class<?> clazz, Object identifier, Object arg) {
+        super(clazz, discover(is, clazz, identifier, arg));
+        property = identifier;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public Object execute(Object o, Object arg)
+            throws IllegalAccessException, InvocationTargetException {
+        Object[] pargs = {property, arg};
+        if (method != null) {
+            method.invoke(o, pargs);
+        }
+        return arg;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public Object tryExecute(Object o, Object identifier, Object arg) {
+        if (o != null && method !=  null
+            // ensure method name matches the property name
+            && property.equals(identifier)
+            && objectClass.equals(o.getClass())) {
+            try {
+                Object[] args = {property, arg};
+                return method.invoke(o, args);
+            } catch (InvocationTargetException xinvoke) {
+                return TRY_FAILED; // fail
+            } catch (IllegalAccessException xill) {
+                return TRY_FAILED;// fail
+            }
+        }
+        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 identifier the key to use as 1st argument to the set method
+     *@param arg 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 identifier, Object arg) {
+        return is.getMethod(clazz, "put", makeArgs(identifier, arg));
+    }
+}
\ No newline at end of file

Propchange: commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/DuckSetExecutor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/DuckSetExecutor.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Modified: commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/EnumerationIterator.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/EnumerationIterator.java?rev=799779&r1=799778&r2=799779&view=diff
==============================================================================
--- commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/EnumerationIterator.java (original)
+++ commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/EnumerationIterator.java Sat Aug  1 00:36:51 2009
@@ -23,10 +23,10 @@
 
 /**
  * An Iterator wrapper for an Enumeration.
- *
  * @since 1.0
  * @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a>
  * @version $Id$
+ * @param <T> the type of object this iterator returns
  */
 public class EnumerationIterator<T> implements Iterator<T> {
     /**

Modified: commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/Introspector.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/Introspector.java?rev=799779&r1=799778&r2=799779&view=diff
==============================================================================
--- commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/Introspector.java (original)
+++ commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/Introspector.java Sat Aug  1 00:36:51 2009
@@ -16,40 +16,245 @@
  */
 package org.apache.commons.jexl.util;
 
+import java.lang.reflect.Method;
+import java.lang.reflect.Constructor;
+
 import org.apache.commons.jexl.util.introspection.Uberspect;
 import org.apache.commons.jexl.util.introspection.UberspectImpl;
-import org.apache.commons.jexl.util.introspection.UberspectLoggable;
+import org.apache.commons.jexl.util.introspection.MethodKey;
+
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
 /**
- *  Little class to manage a Velocity uberspector (Vel 1.4+) for instrospective
- *  services.
- *
- *  @since 1.0
- *  @author <a href="mailto:geirm@apache.org">Geir Magnusson Jr.</a>
- *  @version $Id$
+ *  Default introspection services.
+ *  <p>Finding methods as well as property getters & setters.</p>
  */
-public class Introspector {
+public class Introspector  {
+    /** The default uberspector that handles all introspection patterns. */
+    private static volatile Uberspect uberSpect;
+    /** The logger to use for all warnings & errors. */
+    protected final Log rlog;
+    /** The (low level) introspector to use for introspection services. */
+    protected final org.apache.commons.jexl.util.introspection.Introspector introspector;
+
     /**
-     *  The uberspector from Velocity that handles all introspection patterns.
+     *  Gets the default instance of Uberspect.
+     * <p>This is lazily initialized to avoid building a default instance if there
+     * is no use for it. The main reason for not using the default Uberspect instance is to
+     * be able to use a (low level) introspector created with a given logger
+     * instead of the default one.</p>
+     *  @return Uberspect the default uberspector instance.
      */
-    private static final Uberspect uberSpect;
+    // CSOFF: DoubleCheckedLocking
+    public static Uberspect getUberspect() {
+        // uses a double-locking pattern since java5 memory model allows it
+        if (uberSpect == null) {
+            synchronized (Uberspect.class) {
+                if (uberSpect == null) {
+                    Log logger = LogFactory.getLog(Introspector.class);
+                    uberSpect = new UberspectImpl(logger);
+                }
+            }
+        }
+        return uberSpect;
+    }
+    // CSON: DoubleCheckedLocking
 
-    static {
+    /**
+     * Creates a new instance of Uberspect.
+     * @param logger the logger used by this Uberspect.
+     * @return the new instance
+     */
+    public static Uberspect getUberspect(Log logger) {
+        return new UberspectImpl(logger);
+    }
+
+    /**
+     * Creates an introspector.
+     * @param log the logger to use for warnings.
+     * @param is the low level introspector.
+     */
+    public Introspector(Log log, org.apache.commons.jexl.util.introspection.Introspector is) {
+        rlog = log;
+        introspector = is;
+    }
 
-        Log logger = LogFactory.getLog(Introspector.class);
+    /**
+     * Coerce an Object  to an Integer.
+     * @param arg the Object to coerce
+     * @return an Integer if it can be converted, null otherwise
+     */
+    protected Integer toInteger(Object arg) {
+        if (arg == null) {
+            return null;
+        }
+        if (arg instanceof Number) {
+            return ((Number) arg).intValue();
+        }
+        try {
+            return Integer.parseInt(arg.toString());
+        } catch(NumberFormatException xnumber) {
+            return null;
+        }
+    }
 
-        uberSpect = new UberspectImpl();
-        ((UberspectLoggable) uberSpect).setRuntimeLogger(logger);
+    /**
+     * Coerce an Object to a String.
+     * @param arg the Object to coerce
+     * @return a String if it can be converted, null otherwise
+     */
+    protected String toString(Object arg) {
+        return arg == null? null : arg.toString();
     }
 
     /**
-     *  For now, expose the raw uberspector to the AST.
+     * Gets the method defined by <code>name</code> and
+     * <code>params</code> for the Class <code>c</code>.
+     *
+     * @param c Class in which the method search is taking place
+     * @param name Name of the method being searched for
+     * @param params An array of Objects (not Classes) that describe the
+     *               the parameters
      *
-     *  @return Uberspect The Velocity uberspector.
+     * @return The desired Method object.
+     * @throws IllegalArgumentException When the parameters passed in can not be used for introspection.
+     * CSOFF: RedundantThrows
      */
-    public static Uberspect getUberspect() {
-        return uberSpect;
+    protected final Method getMethod(Class<?> c, String name, Object[] params) throws IllegalArgumentException {
+        return introspector.getMethod(c, new MethodKey(name, params));
+    }
+
+    /**
+     * Gets the method defined by <code>key</code> and for the Class <code>c</code>.
+     *
+     * @param c Class in which the method search is taking place
+     * @param key MethodKey of the method being searched for
+     *
+     * @return The desired Method object.
+     * @throws IllegalArgumentException When the parameters passed in can not be used for introspection.
+     * CSOFF: RedundantThrows
+     */
+    protected final Method getMethod(Class<?> c, MethodKey key) throws IllegalArgumentException {
+        return introspector.getMethod(c, key);
+    }
+
+    /**
+     * Returns a general constructor.
+     * @param ctorHandle the object
+     * @param args contrusctor arguments
+     * @return a {@link java.lang.reflect.Constructor}
+     */
+    public final Constructor<?> getConstructor(Object ctorHandle, Object[] args) {
+        String className = null;
+        if (ctorHandle instanceof Class<?>) {
+            className = ((Class<?>) ctorHandle).getName();
+        } else if (ctorHandle != null) {
+            className = ctorHandle.toString();
+        } else {
+            return null;
+        }
+        return introspector.getConstructor(new MethodKey(className, args));
+    }
+
+    /**
+     * Returns a general method.
+     * @param obj the object
+     * @param name the method name
+     * @param args method arguments
+     * @return a {@link AbstractExecutor.Method}.
+     */
+    public final AbstractExecutor.Method getMethodExecutor(Object obj, String name, Object[] args) {
+        AbstractExecutor.Method me = new MethodExecutor(this, obj, name, args);
+        return me.isAlive()? me : null;
     }
+
+    /**
+     * Return a property getter.
+     * @param obj the object to get the property from.
+     * @param identifier property name
+     * @return a {@link AbstractExecutor.Get}.
+     */
+    public final AbstractExecutor.Get getGetExecutor(Object obj, Object identifier) {
+        final Class<?> claz = obj.getClass();
+        final String property = toString(identifier);
+        Method method;
+        AbstractExecutor.Get executor;
+        // first try for a getFoo() type of property (also getfoo() )
+        if (property != null) {
+            executor = new PropertyGetExecutor(this, claz, property);
+            if (executor.isAlive()) {
+                return executor;
+            }
+        }
+        // look for boolean isFoo()
+        if (property != null) {
+            executor = new BooleanGetExecutor(this, claz, property);
+            if (executor.isAlive()) {
+                return executor;
+            }
+        }
+        // let's see if we are a map...
+        executor = new MapGetExecutor(this, claz, identifier);
+        if (executor.isAlive()) {
+            return executor;
+        }
+        // if that didn't work, look for get("foo")
+        executor = new DuckGetExecutor(this, claz, identifier);
+        if (executor.isAlive()) {
+            return executor;
+        }
+        // let's see if we can convert the identifier to an int,
+        // if obj is an array or a list, we can still do something
+        Integer index = toInteger(identifier);
+        if (index != null) {
+            executor = new ListGetExecutor(this, claz, index);
+            if (executor.isAlive()) {
+                return executor;
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Return a property setter.
+     * @param obj the object to get the property from.
+     * @param identifier property name (or identifier)
+     * @param arg value to set
+     * @return a {@link AbstractExecutor.Set}.
+     */
+    public final AbstractExecutor.Set getSetExecutor(final Object obj, final Object identifier, Object arg) {
+        final Class<?> claz = obj.getClass();
+        final String property = toString(identifier);
+        AbstractExecutor.Set executor;
+        // first try for a setFoo() type of property (also setfoo() )
+        if (property != null) {
+            executor = new PropertySetExecutor(this, claz, property, arg);
+            if (executor.isAlive()) {
+                return executor;
+            }
+        }
+        // let's see if we are a map...
+        executor = new MapSetExecutor(this, claz, identifier, arg);
+        if (executor.isAlive()) {
+            return executor;
+        }
+        // if that didn't work, look for get("foo")
+        executor = new DuckSetExecutor(this, claz, property, arg);
+        if (executor.isAlive()) {
+            return executor;
+        }
+        // let's see if we can convert the identifier to an int,
+        // if obj is an array or a list, we can still do something
+        Integer index = toInteger(identifier);
+        if (index != null) {
+            executor = new ListSetExecutor(this, claz, index, arg);
+            if (executor.isAlive()) {
+                return executor;
+            }
+        }
+        return null;
+     }
+
 }

Added: commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/ListGetExecutor.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/ListGetExecutor.java?rev=799779&view=auto
==============================================================================
--- commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/ListGetExecutor.java (added)
+++ commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/ListGetExecutor.java Sat Aug  1 00:36:51 2009
@@ -0,0 +1,90 @@
+/*
+ * 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.jexl.util;
+import java.util.List;
+import java.lang.reflect.Array;
+/**
+ * Specialized executor to get a property from a List or array.
+ */
+public final class ListGetExecutor extends AbstractExecutor.Get {
+    /** The java.lang.reflect.Array.get method used as an active marker in ListGet. */
+    private static final java.lang.reflect.Method ARRAY_GET =
+            initMarker(Array.class, "get", Object.class, Integer.TYPE);
+    /** The java.util.list.get method used as an active marker in ListGet. */
+    private static final java.lang.reflect.Method LIST_GET =
+            initMarker(List.class, "get", Integer.TYPE);
+    /** The property. */
+    private final Integer property;
+
+    /**
+     * Creates an instance checking for the List interface or Array capability.
+     * @param is the introspector
+     * @param clazz the class to introspect
+     * @param index the index to use in list.get(index)
+     */
+    public ListGetExecutor(Introspector is, Class<?> clazz, Integer index) {
+        super(clazz, discover(clazz));
+        property = index;
+    }
+
+    /**
+     * Get the property from the list or array.
+     * @param list the List/array.
+     * @return list.get(index)
+     */
+    @Override
+    public Object execute(final Object list) {
+        if (method == ARRAY_GET) {
+            return java.lang.reflect.Array.get(list, property);
+        } else {
+            return ((List<?>) list).get(property);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public Object tryExecute(final Object list, Object index) {
+        if (method == discover(list.getClass())
+            && objectClass.equals(list.getClass())
+            && index instanceof Integer) {
+            if (method == ARRAY_GET) {
+                return java.lang.reflect.Array.get(list, property);
+            } else {
+                return ((List<?>) list).get(property);
+            }
+        }
+        return TRY_FAILED;
+    }
+
+
+    /**
+     * Finds the method to perform the get on a list of array.
+     * @param clazz the class to introspect
+     * @return a marker method, list.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;
+    }
+}

Propchange: commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/ListGetExecutor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/ListGetExecutor.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Added: commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/ListSetExecutor.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/ListSetExecutor.java?rev=799779&view=auto
==============================================================================
--- commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/ListSetExecutor.java (added)
+++ commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/ListSetExecutor.java Sat Aug  1 00:36:51 2009
@@ -0,0 +1,94 @@
+/*
+ * 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.jexl.util;
+import java.util.List;
+import java.lang.reflect.Array;
+/**
+ * Specialized executor to set a property in a List or array.
+ */
+public final class ListSetExecutor extends AbstractExecutor.Set {
+        /** 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.list.set method used as an active marker in ListSet. */
+    private static final java.lang.reflect.Method LIST_SET =
+            initMarker(List.class, "set", Integer.TYPE, Object.class);
+    /** The property. */
+    private final Integer property;
+
+    /**
+     * Creates an instance checking for the List interface or Array capability.
+     * @param is the introspector
+     * @param clazz the class that might implement the map interface
+     * @param index the index to use in list.set(index,value)
+     * @param value the value to use in list.set(index,value)
+     */
+    public ListSetExecutor(Introspector is, Class<?> clazz, Integer index, Object value) {
+        super(clazz, discover(clazz));
+        property = index;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public Object execute(final Object list, Object arg) {
+        if (method == ARRAY_SET) {
+            java.lang.reflect.Array.set(list, property, arg);
+        } else {
+            ((List<Object>) list).set(property, arg);
+        }
+        return arg;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public Object tryExecute(final Object list, Object index, Object arg) {
+        if (method == discover(list.getClass())
+            && objectClass.equals(list.getClass())
+            && index instanceof Integer) {
+            Integer idx = (Integer) index;
+        if (method == ARRAY_SET) {
+            java.lang.reflect.Array.set(list, idx, arg);
+        } else {
+            ((List<Object>) list).set(idx, arg);
+        }
+        }
+        return TRY_FAILED;
+    }
+
+
+    /**
+     * Finds the method to perform 'set' on a list of array.
+     * @param clazz the class to introspect
+     * @return a marker method, list.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 = arg == null? Object.class : arg.getClass();
+            // if (IntrospectionUtils.isMethodInvocationConvertible(formal, actual, false)) {
+                return ARRAY_SET;
+            // }
+        }
+        if (List.class.isAssignableFrom(clazz)) {
+            return LIST_SET;
+        }
+        return null;
+    }
+}

Propchange: commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/ListSetExecutor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/ListSetExecutor.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Modified: commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/MapGetExecutor.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/MapGetExecutor.java?rev=799779&r1=799778&r2=799779&view=diff
==============================================================================
--- commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/MapGetExecutor.java (original)
+++ commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/MapGetExecutor.java Sat Aug  1 00:36:51 2009
@@ -18,70 +18,54 @@
 package org.apache.commons.jexl.util;
 
 import java.util.Map;
-import java.lang.reflect.Method;
 
-import org.apache.commons.logging.Log;
-
-
-/**
- * GetExecutor that is smart about Maps. If it detects one, it does not
- * use Reflection but a cast to access the getter.
- *
- * @author <a href="mailto:henning@apache.org">Henning P. Schmiedehausen</a>
- * @version $Id$
+ /**
+ * Specialized executor to get a property from a Map.
  */
-public class MapGetExecutor extends AbstractExecutor {
-    /** A one argument signature to find method. */
-    private static final Class<?>[] OBJECT_PARM = new Class<?>[]{Object.class};
-    /** the property to get. */
-    private final String property;
+public final class MapGetExecutor extends AbstractExecutor.Get {
+    /** The java.util.map.get method used as an active marker in MapGet. */
+    private static final java.lang.reflect.Method MAP_GET =
+            initMarker(Map.class, "get", Object.class);
+    /** The property. */
+    private final Object property;
 
     /**
-     * Creates the instance.
-     * @param rlog The logger.
-     * @param clazz the class to execute the get on.
-     * @param aProperty the property or key to get.
+     * Creates an instance checking for the Map interface.
+     * @param is the introspector
+     * @param clazz the class that might implement the map interface
+     * @param key the key to use in map.get(key)
      */
-    public MapGetExecutor(final Log rlog, final Class<?> clazz, final String aProperty) {
-        super(aProperty != null? discover(rlog, clazz, aProperty) : null);
-        this.property = aProperty;
+    public MapGetExecutor(Introspector is, Class<?> clazz, Object key) {
+        super(clazz, discover(clazz));
+        property = key;
     }
 
     /**
-     * Finds the method for a MapGetExecutor.
-     *
-     * @param rlog The logger.
-     * @param clazz The class being analyzed.
-     * @param property The boolean property.
-     * @return The method.
+     * Get the property from the map.
+     * @param map the map.
+     * @return map.get(property)
      */
-    private static Method discover(final Log rlog, final Class<?> clazz, final String property) {
-        Method m = null;
-        Class<?>[] interfaces = clazz.getInterfaces();
-        for (int i = 0; i < interfaces.length; i++) {
-            if (interfaces[i].equals(Map.class)) {
-                try {
-                    m = Map.class.getMethod("get", OBJECT_PARM);
-                    // pass through application level runtime exceptions
-                } catch (RuntimeException e) {
-                    throw e;
-                } catch (Exception e) {
-                    rlog.error("While looking for get('" + property + "') method:", e);
-                }
-                break;
-            }
-        }
-        return m;
+    @Override
+    public Object execute(final Object map) {
+        return ((Map<Object, ?>) map).get(property);
     }
 
+    /** {@inheritDoc} */
+    @Override
+    public Object tryExecute(final Object map, Object key) {
+        if (objectClass.equals(map.getClass())
+            && (key == null || property.getClass().equals(key.getClass()))) {
+            return ((Map<Object, ?>) map).get(key);
+        }
+        return TRY_FAILED;
+    }
 
-    /** 
-     * Get the property from the map.
-     * @param o the map.
-     * @return o.get(property)
+    /**
+     * Finds the method to perform 'get' on a map.
+     * @param clazz the class to introspect
+     * @return a marker method, map.get
      */
-    @Override
-    public Object execute(final Object o) {
-        return ((Map<String,?>) o).get(property);
+    static java.lang.reflect.Method discover(Class<?> clazz) {
+        return (Map.class.isAssignableFrom(clazz))? MAP_GET : null;
     }
-}
\ No newline at end of file
+}

Added: commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/MapSetExecutor.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/MapSetExecutor.java?rev=799779&view=auto
==============================================================================
--- commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/MapSetExecutor.java (added)
+++ commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/MapSetExecutor.java Sat Aug  1 00:36:51 2009
@@ -0,0 +1,68 @@
+/*
+ * 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.jexl.util;
+import java.util.Map;
+import java.lang.reflect.InvocationTargetException;
+/**
+ * Specialized executor to set a property in a Map.
+ */
+public final class MapSetExecutor extends AbstractExecutor.Set {
+    /** The java.util.map.put method used as an active marker in MapSet. */
+    private static final java.lang.reflect.Method MAP_SET = initMarker(Map.class, "put", Object.class, Object.class);
+    /** The property. */
+    private final Object property;
+
+    /**
+     * Creates an instance checking for the Map interface.
+     *@param is the introspector
+     *@param clazz the class that might implement the map interface
+     *@param key the key to use as argument in map.put(key,value)
+     *@param value the value to use as argument in map.put(key,value)
+    */
+    public MapSetExecutor(Introspector is, Class<?> clazz, Object key, Object value) {
+        super(clazz, discover(clazz));
+        property = key;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public Object execute(final Object map, Object value)
+    throws IllegalAccessException, InvocationTargetException {
+        ((Map<Object, Object>) map).put(property, value);
+        return value;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public Object tryExecute(final Object map, Object key, Object value) {
+        if (objectClass.equals(map.getClass())
+            && (key == null || property.getClass().equals(key.getClass()))) {
+            return ((Map<Object, Object>) map).put(key, value);
+        }
+        return TRY_FAILED;
+    }
+
+    /**
+     * Finds the method to perform 'set' on a map.
+     * @param clazz the class to introspect
+     * @return a marker method, map.get
+     */
+    static java.lang.reflect.Method discover(Class<?> clazz) {
+        return (Map.class.isAssignableFrom(clazz))? MAP_SET : null;
+    }
+}

Propchange: commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/MapSetExecutor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/MapSetExecutor.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Added: commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/MethodExecutor.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/MethodExecutor.java?rev=799779&view=auto
==============================================================================
--- commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/MethodExecutor.java (added)
+++ commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/MethodExecutor.java Sat Aug  1 00:36:51 2009
@@ -0,0 +1,184 @@
+/*
+ * 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.jexl.util;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.InvocationTargetException;
+import org.apache.commons.jexl.util.introspection.MethodKey;
+
+/**
+ * Specialized executor to invoke a method on an object.
+ */
+public final class MethodExecutor extends AbstractExecutor.Method {
+    /** Whether this method handles varargs. */
+    private final boolean isVarArgs;
+    /**
+     * Creates a new instance.
+     * @param is the introspector used to discover the method
+     * @param obj the object to find the method in
+     * @param name the method name
+     * @param args the method arguments
+     */
+    public MethodExecutor(Introspector is, Object obj, String name, Object[] args) {
+        super(obj.getClass(), discover(is, obj, name, args));
+        isVarArgs = method != null && isVarArgMethod(method);
+    }
+
+    /**
+     * Invokes the method to be executed.
+     * @param o 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.
+     */
+    @Override
+    public Object execute(Object o, Object[] args)
+        throws IllegalAccessException, InvocationTargetException  {
+        if (isVarArgs) {
+            Class<?>[] formal = method.getParameterTypes();
+            int index = formal.length - 1;
+            Class<?> type = formal[index].getComponentType();
+            if (args.length >= index) {
+                args = handleVarArg(type, index, args);
+            }
+        }
+        if (method.getDeclaringClass() == ArrayListWrapper.class && o.getClass().isArray()) {
+            return method.invoke(new ArrayListWrapper(o), args);
+        } else {
+            return method.invoke(o, args);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public Object tryExecute(String name, Object o, Object[] args) {
+        MethodKey tkey = new MethodKey(name, args);
+        // let's assume that invocation will fly if the declaring class is the
+        // same and arguments have the same type
+        if (objectClass.equals(o.getClass()) && tkey.equals(key)) {
+            try {
+                return execute(o, args);
+            } catch (InvocationTargetException xinvoke) {
+                return TRY_FAILED; // fail
+            } catch (IllegalAccessException xill) {
+                return TRY_FAILED;// fail
+            }
+        }
+        return TRY_FAILED;
+    }
+
+
+    /**
+     * Discovers a method for a {@link MethodExecutor}.
+     * <p>
+     * If the object is an array, an attempt will be made to find the
+     * method in a List (see {@link ArrayListWrapper})
+     * </p>
+     * <p>
+     * If the object is a class, an attempt will be made to find the
+     * method as a static method of that class.
+     * </p>
+     * @param is the introspector used to discover the method
+     * @param obj the object to introspect
+     * @param method the name of the method to find
+     * @param args the method arguments
+     * @return a filled up parameter (may contain a null method)
+     */
+    private static Parameter discover(Introspector is,
+            Object obj, String method, Object[] args) {
+        final Class<?> clazz = obj.getClass();
+        final MethodKey key = new MethodKey(method, args);
+        java.lang.reflect.Method m = is.getMethod(clazz, key);
+        if (m == null && clazz.isArray()) {
+            // check for support via our array->list wrapper
+            m = is.getMethod(ArrayListWrapper.class, key);
+        }
+        if (m == null && obj instanceof Class<?>) {
+            m = is.getMethod((Class<?>) obj, key);
+        }
+        return new Parameter(m, key);
+    }
+
+    /**
+     * Reassembles arguments if the method is a vararg method.
+     * @param type   The vararg class type (aka component type
+     *               of the expected array arg)
+     * @param index  The index of the vararg in the method declaration
+     *               (This will always be one less than the number of
+     *               expected arguments.)
+     * @param actual The actual parameters being passed to this method
+     * @return The actual parameters adjusted for the varargs in order
+     * to fit the method declaration.
+     */
+    protected Object[] handleVarArg(Class<?> type, int index, Object[] actual) {
+        // if no values are being passed into the vararg
+        if (actual.length == index) {
+            // create an empty array of the expected type
+            actual = new Object[]{Array.newInstance(type, 0)};
+        } else if (actual.length == index + 1) {
+            // if one value is being passed into the vararg
+            // make sure the last arg is an array of the expected type
+            if (MethodKey.isInvocationConvertible(type,
+                    actual[index].getClass(),
+                    false)) {
+                // create a 1-length array to hold and replace the last param
+                Object lastActual = Array.newInstance(type, 1);
+                Array.set(lastActual, 0, actual[index]);
+                actual[index] = lastActual;
+            }
+        } else if (actual.length > index + 1) {
+            // if multiple values are being passed into the vararg
+            // put the last and extra actual in an array of the expected type
+            int size = actual.length - index;
+            Object lastActual = Array.newInstance(type, size);
+            for (int i = 0; i < size; i++) {
+                Array.set(lastActual, i, actual[index + i]);
+            }
+
+            // put all into a new actual array of the appropriate size
+            Object[] newActual = new Object[index + 1];
+            for (int i = 0; i < index; i++) {
+                newActual[i] = actual[i];
+            }
+            newActual[index] = lastActual;
+
+            // replace the old actual array
+            actual = newActual;
+        }
+        return actual;
+    }
+
+   /**
+     * Determines if a method can accept a variable number of arguments.
+     * @param m a the method to check
+     * @return true if method is vararg, false otherwise
+     */
+    private static boolean isVarArgMethod(java.lang.reflect.Method m) {
+        Class<?>[] formal = m.getParameterTypes();
+        if (formal == null || formal.length == 0) {
+            return false;
+        } else {
+            Class<?> last = formal[formal.length - 1];
+            // if the last arg is an array, then
+            // we consider this a varargs method
+            return last.isArray();
+        }
+    }
+}
+
+

Propchange: commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/MethodExecutor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/MethodExecutor.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Added: commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/PropertyGetExecutor.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/PropertyGetExecutor.java?rev=799779&view=auto
==============================================================================
--- commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/PropertyGetExecutor.java (added)
+++ commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/PropertyGetExecutor.java Sat Aug  1 00:36:51 2009
@@ -0,0 +1,107 @@
+/*
+ * 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.jexl.util;
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * Specialized executor to get a property from an object.
+ */
+public final class PropertyGetExecutor extends AbstractExecutor.Get {
+    /** A static signature for method(). */
+    private static final Object[] EMPTY_PARAMS = {};
+    /** The property. */
+    private final String property;
+    
+    /**
+     * Creates an instance by attempting discovery of the get method.
+     * @param is the introspector
+     * @param clazz the class to introspect
+     * @param identifier the property to get
+     */
+    public PropertyGetExecutor(Introspector is, Class<?> clazz, String identifier) {
+        super(clazz, discover(is, clazz, identifier));
+        property = identifier;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public Object execute(Object o)
+        throws IllegalAccessException, InvocationTargetException {
+        return method == null ? null : method.invoke(o, (Object[]) null);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public Object tryExecute(Object o, Object identifier) {
+        if (o != null && method !=  null
+            && property.equals(identifier)
+            && objectClass.equals(o.getClass())) {
+            try {
+                return method.invoke(o, (Object[]) null);
+            } catch (InvocationTargetException xinvoke) {
+                return TRY_FAILED; // fail
+            } catch (IllegalAccessException xill) {
+                return TRY_FAILED;// fail
+            }
+        }
+        return TRY_FAILED;
+    }
+
+    /**
+     * Discovers the method for a {@link PropertyGet}.
+     * <p>The method to be found should be named "get{P,p}property.</p>
+     *@param is the introspector
+     *@param clazz the class to find the get method from
+     *@param property the property name to find
+     *@return the method if found, null otherwise
+     */
+    static java.lang.reflect.Method discover(Introspector is,
+            final Class<?> clazz, String property) {
+        return discoverGet(is, "get", clazz, property);
+    }
+
+
+    /**
+     * Base method for boolean & object property get.
+     * @param is the introspector
+     * @param which "is" or "get" for boolean or object
+     * @param clazz The class being examined.
+     * @param property The property being addressed.
+     * @return The {get,is}{p,P}roperty method if one exists, null otherwise.
+     */
+    static java.lang.reflect.Method discoverGet(Introspector is,
+            String which, Class<?> clazz, String property) {
+        //  this is gross and linear, but it keeps it straightforward.
+        java.lang.reflect.Method method = null;
+        final int start = which.length(); // "get" or "is" so 3 or 2 for char case switch
+        // start with get<Property>
+        StringBuilder sb = new StringBuilder(which);
+        sb.append(property);
+        // uppercase nth char
+        char c = sb.charAt(start);
+        sb.setCharAt(start, Character.toUpperCase(c));
+        method = is.getMethod(clazz, sb.toString(), EMPTY_PARAMS);
+        //lowercase nth char
+        if (method == null) {
+            sb.setCharAt(start, Character.toLowerCase(c));
+            method = is.getMethod(clazz, sb.toString(), EMPTY_PARAMS);
+        }
+        return method;
+    }
+}
+

Propchange: commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/PropertyGetExecutor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/PropertyGetExecutor.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Added: commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/PropertySetExecutor.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/PropertySetExecutor.java?rev=799779&view=auto
==============================================================================
--- commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/PropertySetExecutor.java (added)
+++ commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/PropertySetExecutor.java Sat Aug  1 00:36:51 2009
@@ -0,0 +1,103 @@
+/*
+ * 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.jexl.util;
+import java.lang.reflect.InvocationTargetException;
+/**
+ * Specialized executor to set a property in an object.
+ */
+public final class PropertySetExecutor extends AbstractExecutor.Set {
+    /** Index of the first character of the set{p,P}roperty. */
+    private static final int SET_START_INDEX = 3;
+    /** The property. */
+    private final String property;
+
+    /**
+     * Creates an instance by attempting discovery of the set method.
+     * @param is the introspector
+     * @param clazz the class to introspect
+     * @param identifier the property to set
+     * @param arg the value to set into the property
+     */
+    public PropertySetExecutor(Introspector is, Class<?> clazz, String identifier, Object arg) {
+        super(clazz, discover(is, clazz, identifier, arg));
+        property = identifier;
+
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public Object execute(Object o, Object arg)
+            throws IllegalAccessException, InvocationTargetException {
+        Object[] pargs = {arg};
+        if (method != null) {
+            method.invoke(o, pargs);
+        }
+        return arg;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public Object tryExecute(Object o, Object identifier, Object arg) {
+        if (o != null && method != null
+            // ensure method name matches the property name
+            && property.equals(identifier)
+            // object class should be same as executor's method declaring class
+            && objectClass.equals(o.getClass())
+            // we are guaranteed the method has one parameter since it is a set(x)
+            && (arg == null || method.getParameterTypes()[0].equals(arg.getClass()))) {
+            try {
+                return execute(o, arg);
+            } catch (InvocationTargetException xinvoke) {
+                return TRY_FAILED; // fail
+            } catch (IllegalAccessException xill) {
+                return TRY_FAILED;// fail
+            }
+        }
+        return TRY_FAILED;
+    }
+
+
+    /**
+     * Discovers the method for a {@link PropertySet}.
+     * <p>The method to be found should be named "set{P,p}property.</p>
+     *@param is the introspector
+     *@param clazz the class to find the get method from
+     *@param property the name of the property to set
+     *@param arg the value to assign to the property
+     *@return the method if found, null otherwise
+     */
+    private static java.lang.reflect.Method discover(Introspector is,
+            final Class<?> clazz, String property, Object arg) {
+        // first, we introspect for the set<identifier> setter method
+        Object[] params = {arg};
+        StringBuilder sb = new StringBuilder("set");
+        sb.append(property);
+        // uppercase nth char
+        char c = sb.charAt(SET_START_INDEX);
+        sb.setCharAt(SET_START_INDEX, Character.toUpperCase(c));
+        java.lang.reflect.Method method = is.getMethod(clazz, sb.toString(), params);
+        // lowercase nth char
+        if (method == null) {
+            sb.setCharAt(SET_START_INDEX, Character.toLowerCase(c));
+            method = is.getMethod(clazz, sb.toString(), params);
+        }
+
+        return method;
+    }
+}
+

Propchange: commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/PropertySetExecutor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/PropertySetExecutor.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Modified: commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/introspection/ClassMap.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/introspection/ClassMap.java?rev=799779&r1=799778&r2=799779&view=diff
==============================================================================
--- commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/introspection/ClassMap.java (original)
+++ commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/introspection/ClassMap.java Sat Aug  1 00:36:51 2009
@@ -24,11 +24,12 @@
 import org.apache.commons.logging.Log;
 
 /**
- * Taken from the Velocity tree so we can be self-sufficient.
+ * Originally taken from the Velocity tree so we can be self-sufficient.
  *
  * A cache of introspection information for a specific class instance.
- * Keys objects by an agregation of the method name and the names of classes
+ * Keys objects by an agregation of the method name and the classes
  * that make up the parameters.
+ * @see MethodKey
  *
  * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
  * @author <a href="mailto:bob@werken.com">Bob McWhirter</a>
@@ -38,7 +39,7 @@
  * @version $Id$
  * @since 1.0
  */
-public class ClassMap {
+final class ClassMap {
     /** cache of methods. */
     private final MethodCache methodCache;
 
@@ -63,14 +64,13 @@
     /**
      * Find a Method using the method name and parameter objects.
      *
-     * @param name   The method name to look up.
-     * @param params An array of parameters for the method.
+     * @param key the method key
      * @return A Method object representing the method to invoke or null.
-     * @throws MethodMap.AmbiguousException When more than one method is a match for the parameters.
+     * @throws MethodKey.AmbiguousException When more than one method is a match for the parameters.
      */
-    public Method findMethod(final String name, final Object[] params)
-            throws MethodMap.AmbiguousException {
-        return methodCache.get(name, params);
+    public Method findMethod(final MethodKey key)
+            throws MethodKey.AmbiguousException {
+        return methodCache.get(key);
     }
 
     /**
@@ -154,7 +154,7 @@
      * @version $Id$
      * <p>
      * It stores the association between:
-     *  - a key made of a method name & an array of argument types. (@see MethodCache.MethodKey)
+     *  - a key made of a method name & an array of argument types.
      *  - a method.
      * </p>
      * <p>
@@ -237,24 +237,12 @@
          * If nothing is found, then we must actually go
          * and introspect the method from the MethodMap.
          *</p>
-         * @param name   The method name to look up.
-         * @param params An array of parameters for the method.
-         * @return A Method object representing the method to invoke or null.
-         * @throws MethodMap.AmbiguousException When more than one method is a match for the parameters.
-         */
-        Method get(final String name, final Object[] params)
-                throws MethodMap.AmbiguousException {
-            return get(new MethodKey(name, params));
-        }
-
-        /**
-         * Finds a Method using a MethodKey.
          * @param methodKey the method key
-         * @return a method
-         * @throws MethodMap.AmbiguousException if method resolution is ambiguous
+         * @return A Method object representing the method to invoke or null.
+         * @throws MethodKey.AmbiguousException When more than one method is a match for the parameters.
          */
         Method get(final MethodKey methodKey)
-                throws MethodMap.AmbiguousException {
+                throws MethodKey.AmbiguousException {
             synchronized (methodMap) {
                 Method cacheEntry = cache.get(methodKey);
                 // We looked this up before and failed.
@@ -271,7 +259,7 @@
                         } else {
                             cache.put(methodKey, CACHE_MISS);
                         }
-                    } catch (MethodMap.AmbiguousException ae) {
+                    } catch (MethodKey.AmbiguousException ae) {
                         // that's a miss :-)
                         cache.put(methodKey, CACHE_MISS);
                         throw ae;
@@ -311,137 +299,4 @@
             }
         }
     }
-
-    /**
-     * A method key for the introspector cache.
-     * <p>
-     * This replaces the original key scheme which used to build the key
-     * by concatenating the method name and parameters class names as one string
-     * with the exception that primitive types were converted to their object class equivalents.
-     * </p>
-     * <p>
-     * The key is still based on the same information, it is just wrapped in an object instead.
-     * Primitive type classes are converted to they object equivalent to make a key;
-     * int foo(int) and int foo(Integer) do generate the same key.
-     * </p>
-     * A key can be constructed either from arguments (array of objects) or from parameters
-     * (array of class).
-     * Roughly 3x faster than string key to access the map & uses less memory.
-     */
-    static final class MethodKey {
-        /** The hash code. */
-        private final int hashCode;
-        /** The method name. */
-        private final String method;
-        /** The parameters. */
-        private final Class<?>[] params;
-        /** A marker for empty parameter list. */
-        private static final Class<?>[] NOARGS = new Class<?>[0];
-        /** The hash code constants. */
-        private static final int HASH = 37;
-
-        /** Creates a MethodKey from a method.
-         *  Used to store information in the method map.
-         * @param aMethod the method to build the key from
-         */
-        MethodKey(Method aMethod) {
-            this(aMethod.getName(), aMethod.getParameterTypes());
-        }
-
-        /** Creates a MethodKey from a method name and a set of arguments (objects).
-         *  Used to query the method map.
-         * @param aMethod the method name
-         * @param args the arguments instances to match the method signature
-         */
-        MethodKey(String aMethod, Object[] args) {
-            // !! keep this in sync with the other ctor (hash code) !!
-            this.method = aMethod;
-            int hash = this.method.hashCode();
-            final int size;
-             // CSOFF: InnerAssignment
-            if (args != null && (size = args.length) > 0) {
-                // CSON: InnerAssignment
-                this.params = new Class<?>[size];
-                for (int p = 0; p < size; ++p) {
-                    // ctor(Object) : {
-                    Object arg = args[p];
-                    // no need to go thru primitive type conversion since these are objects
-                    Class<?> parm = arg == null ? Object.class : arg.getClass();
-                    // }
-                    hash = (HASH * hash) + parm.hashCode();
-                    this.params[p] = parm;
-                }
-            } else {
-                this.params = NOARGS;
-            }
-            this.hashCode = hash;
-        }
-
-        /** Creates a MethodKey from a method name and a set of parameters (classes).
-         *  Used to store information in the method map. ( @see MethodKey#primitiveClass )
-         * @param aMethod the method name
-         * @param args the argument classes to match the method signature
-         */
-        MethodKey(String aMethod, Class<?>[] args) {
-            // !! keep this in sync with the other ctor (hash code) !!
-            this.method = aMethod;
-            int hash = this.method.hashCode();
-            final int size;
-            // CSOFF: InnerAssignment
-            if (args != null && (size = args.length) > 0) {
-                // CSON: InnerAssignment
-                this.params = new Class<?>[size];
-                for (int p = 0; p < size; ++p) {
-                    // ctor(Class): {
-                    Class<?> parm = MethodCache.primitiveClass(args[p]);
-                    // }
-                    hash = (HASH * hash) + parm.hashCode();
-                    this.params[p] = parm;
-                }
-            } else {
-                this.params = NOARGS;
-            }
-            this.hashCode = hash;
-        }
-
-        /**
-         * Gets this key's method name.
-         * @return the method name
-         */
-        String getMethod() {
-            return method;
-        }
-
-        /**
-         * Gets this key's method parameter classes.
-         * @return the parameters
-         */
-        Class<?>[] getParameters() {
-            return params;
-        }
-
-        @Override
-        public int hashCode() {
-            return hashCode;
-        }
-
-        @Override
-        public boolean equals(Object arg) {
-            if (arg instanceof MethodKey) {
-                MethodKey key = (MethodKey) arg;
-                return method.equals(key.method) && java.util.Arrays.equals(params, key.params);
-            }
-            return false;
-        }
-
-        @Override
-        /** Compatible with original string key. */
-        public String toString() {
-            StringBuilder builder = new StringBuilder(method);
-            for (Class<?> c : params) {
-                builder.append(c.getName());
-            }
-            return builder.toString();
-        }
-    }
 }
\ No newline at end of file

Added: commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/introspection/DebugInfo.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/introspection/DebugInfo.java?rev=799779&view=auto
==============================================================================
--- commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/introspection/DebugInfo.java (added)
+++ commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/introspection/DebugInfo.java Sat Aug  1 00:36:51 2009
@@ -0,0 +1,34 @@
+/*
+ * 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.jexl.util.introspection;
+
+/**
+ * A little class to abstract debugging info.
+ */
+public interface DebugInfo {
+    /** A default debug info with (oviously) no information. */
+    DebugInfo NONE = new DebugInfo() {
+        public String debugString() {
+            return "?@?:?";
+        }
+    };
+    /**
+     * Formats this information.
+     * @return a human readable string.
+     */
+    String debugString();
+}

Propchange: commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/introspection/DebugInfo.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/util/introspection/DebugInfo.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL