commons-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mben...@apache.org
Subject svn commit: r638851 - in /commons/proper/lang/branches/LANG_POST_2_4/src/java/org/apache/commons/lang: ConstructorUtils.java MethodUtils.java
Date Wed, 19 Mar 2008 14:54:09 GMT
Author: mbenson
Date: Wed Mar 19 07:54:06 2008
New Revision: 638851

URL: http://svn.apache.org/viewvc?rev=638851&view=rev
Log:
Langify

Modified:
    commons/proper/lang/branches/LANG_POST_2_4/src/java/org/apache/commons/lang/ConstructorUtils.java
    commons/proper/lang/branches/LANG_POST_2_4/src/java/org/apache/commons/lang/MethodUtils.java

Modified: commons/proper/lang/branches/LANG_POST_2_4/src/java/org/apache/commons/lang/ConstructorUtils.java
URL: http://svn.apache.org/viewvc/commons/proper/lang/branches/LANG_POST_2_4/src/java/org/apache/commons/lang/ConstructorUtils.java?rev=638851&r1=638850&r2=638851&view=diff
==============================================================================
--- commons/proper/lang/branches/LANG_POST_2_4/src/java/org/apache/commons/lang/ConstructorUtils.java (original)
+++ commons/proper/lang/branches/LANG_POST_2_4/src/java/org/apache/commons/lang/ConstructorUtils.java Wed Mar 19 07:54:06 2008
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.commons.beanutils;
+package org.apache.commons.lang;
 
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
@@ -44,17 +44,22 @@
  * @author Jan Sorensen
  * @author Robert Burrell Donkin
  * @author Rodney Waldhoff
- * @version $Revision$ $Date$
+ * @since 2.5
+ * @version $Id$
  */
 public class ConstructorUtils {
 
-    // --------------------------------------------------------- Private Members
-    /** An empty class array */
-    private static final Class[] EMPTY_CLASS_PARAMETERS = new Class[0];
-    /** An empty object array */
-    private static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
-
-    // --------------------------------------------------------- Public Methods
+    /**
+     * <p>ConstructorUtils instances should NOT be constructed in standard programming.
+     * Instead, the class should be used as
+     * <code>ConstructorUtils.invokeConstructor(cls, args)</code>.</p>
+     *
+     * <p>This constructor is public to permit tools that require a JavaBean
+     * instance to operate.</p>
+     */
+    public ConstructorUtils() {
+        super();
+    }
 
     /**
      * <p>Convenience method returning new instance of <code>klazz</code> using a single argument constructor.
@@ -63,7 +68,7 @@
      *
      * <p>The signatures should be assignment compatible.</p>
      *
-     * @param klass the class to be constructed.
+     * @param cls the class to be constructed.
      * @param arg the actual argument
      * @return new instance of <code>klazz</code>
      *
@@ -74,16 +79,10 @@
      *
      * @see #invokeConstructor(java.lang.Class, java.lang.Object[], java.lang.Class[])
      */
-    public static Object invokeConstructor(Class klass, Object arg)
-        throws
-            NoSuchMethodException,
-            IllegalAccessException,
-            InvocationTargetException,
-            InstantiationException {
-
-        Object[] args = { arg };
-        return invokeConstructor(klass, args);
-
+    public static Object invokeConstructor(Class cls, Object arg)
+            throws NoSuchMethodException, IllegalAccessException,
+            InvocationTargetException, InstantiationException {
+        return invokeConstructor(cls, new Object[] { arg });
     }
 
     /**
@@ -93,7 +92,7 @@
      *
      * <p>The signatures should be assignment compatible.</p>
      *
-     * @param klass the class to be constructed.
+     * @param cls the class to be constructed.
      * @param args actual argument array
      * @return new instance of <code>klazz</code>
      *
@@ -104,23 +103,17 @@
      *
      * @see #invokeConstructor(java.lang.Class, java.lang.Object[], java.lang.Class[])
      */
-    public static Object invokeConstructor(Class klass, Object[] args)
-        throws
-            NoSuchMethodException,
-            IllegalAccessException,
-            InvocationTargetException,
-            InstantiationException {
-
+    public static Object invokeConstructor(Class cls, Object[] args)
+            throws NoSuchMethodException, IllegalAccessException,
+            InvocationTargetException, InstantiationException {
         if (null == args) {
-            args = EMPTY_OBJECT_ARRAY;
+            args = ArrayUtils.EMPTY_OBJECT_ARRAY;
         }
-        int arguments = args.length;
-        Class parameterTypes[] = new Class[arguments];
-        for (int i = 0; i < arguments; i++) {
+        Class parameterTypes[] = new Class[args.length];
+        for (int i = 0; i < args.length; i++) {
             parameterTypes[i] = args[i].getClass();
         }
-        return invokeConstructor(klass, args, parameterTypes);
-
+        return invokeConstructor(cls, args, parameterTypes);
     }
 
     /**
@@ -129,7 +122,7 @@
      *
      * <p>The signatures should be assignment compatible.</p>
      *
-     * @param klass the class to be constructed.
+     * @param cls the class to be constructed.
      * @param args actual argument array
      * @param parameterTypes parameter types array
      * @return new instance of <code>klazz</code>
@@ -140,33 +133,25 @@
      * @throws InstantiationException thrown on the constructor's invocation
      * @see Constructor#newInstance
      */
-    public static Object invokeConstructor(
-        Class klass,
-        Object[] args,
-        Class[] parameterTypes)
-        throws
-            NoSuchMethodException,
-            IllegalAccessException,
-            InvocationTargetException,
+    public static Object invokeConstructor(Class cls, Object[] args,
+            Class[] parameterTypes) throws NoSuchMethodException,
+            IllegalAccessException, InvocationTargetException,
             InstantiationException {
-
         if (parameterTypes == null) {
-            parameterTypes = EMPTY_CLASS_PARAMETERS;
+            parameterTypes = ArrayUtils.EMPTY_CLASS_ARRAY;
         }
         if (args == null) {
-            args = EMPTY_OBJECT_ARRAY;
+            args = ArrayUtils.EMPTY_OBJECT_ARRAY;
         }
-
-        Constructor ctor =
-            getMatchingAccessibleConstructor(klass, parameterTypes);
+        Constructor ctor = getMatchingAccessibleConstructor(cls, parameterTypes);
         if (null == ctor) {
             throw new NoSuchMethodException(
-                "No such accessible constructor on object: " + klass.getName());
+                    "No such accessible constructor on object: "
+                            + cls.getName());
         }
         return ctor.newInstance(args);
     }
 
-
     /**
      * <p>Convenience method returning new instance of <code>klazz</code> using a single argument constructor.
      * The formal parameter type is inferred from the actual values of <code>arg</code>.
@@ -174,7 +159,7 @@
      *
      * <p>The signatures should match exactly.</p>
      *
-     * @param klass the class to be constructed.
+     * @param cls the class to be constructed.
      * @param arg the actual argument
      * @return new instance of <code>klazz</code>
      *
@@ -185,16 +170,10 @@
      *
      * @see #invokeExactConstructor(java.lang.Class, java.lang.Object[], java.lang.Class[])
      */
-    public static Object invokeExactConstructor(Class klass, Object arg)
-        throws
-            NoSuchMethodException,
-            IllegalAccessException,
-            InvocationTargetException,
-            InstantiationException {
-
-        Object[] args = { arg };
-        return invokeExactConstructor(klass, args);
-
+    public static Object invokeExactConstructor(Class cls, Object arg)
+            throws NoSuchMethodException, IllegalAccessException,
+            InvocationTargetException, InstantiationException {
+        return invokeExactConstructor(cls, new Object[] { arg });
     }
 
     /**
@@ -204,7 +183,7 @@
      *
      * <p>The signatures should match exactly.</p>
      *
-     * @param klass the class to be constructed.
+     * @param cls the class to be constructed.
      * @param args actual argument array
      * @return new instance of <code>klazz</code>
      *
@@ -215,22 +194,18 @@
      *
      * @see #invokeExactConstructor(java.lang.Class, java.lang.Object[], java.lang.Class[])
      */
-    public static Object invokeExactConstructor(Class klass, Object[] args)
-        throws
-            NoSuchMethodException,
-            IllegalAccessException,
-            InvocationTargetException,
-            InstantiationException {
+    public static Object invokeExactConstructor(Class cls, Object[] args)
+            throws NoSuchMethodException, IllegalAccessException,
+            InvocationTargetException, InstantiationException {
         if (null == args) {
-            args = EMPTY_OBJECT_ARRAY;
+            args = ArrayUtils.EMPTY_OBJECT_ARRAY;
         }
         int arguments = args.length;
         Class parameterTypes[] = new Class[arguments];
         for (int i = 0; i < arguments; i++) {
             parameterTypes[i] = args[i].getClass();
         }
-        return invokeExactConstructor(klass, args, parameterTypes);
-
+        return invokeExactConstructor(cls, args, parameterTypes);
     }
 
     /**
@@ -240,7 +215,7 @@
      *
      * <p>The signatures should match exactly.</p>
      *
-     * @param klass the class to be constructed.
+     * @param cls the class to be constructed.
      * @param args actual argument array
      * @param parameterTypes parameter types array
      * @return new instance of <code>klazz</code>
@@ -251,69 +226,53 @@
      * @throws InstantiationException thrown on the constructor's invocation
      * @see Constructor#newInstance
      */
-    public static Object invokeExactConstructor(
-        Class klass,
-        Object[] args,
-        Class[] parameterTypes)
-        throws
-            NoSuchMethodException,
-            IllegalAccessException,
-            InvocationTargetException,
+    public static Object invokeExactConstructor(Class cls, Object[] args,
+            Class[] parameterTypes) throws NoSuchMethodException,
+            IllegalAccessException, InvocationTargetException,
             InstantiationException {
-
         if (args == null) {
-            args = EMPTY_OBJECT_ARRAY;
+            args = ArrayUtils.EMPTY_OBJECT_ARRAY;
         }
-
         if (parameterTypes == null) {
-            parameterTypes = EMPTY_CLASS_PARAMETERS;
+            parameterTypes = ArrayUtils.EMPTY_CLASS_ARRAY;
         }
-
-        Constructor ctor = getAccessibleConstructor(klass, parameterTypes);
+        Constructor ctor = getAccessibleConstructor(cls, parameterTypes);
         if (null == ctor) {
             throw new NoSuchMethodException(
-                "No such accessible constructor on object: " + klass.getName());
+                    "No such accessible constructor on object: "
+                            + cls.getName());
         }
         return ctor.newInstance(args);
-
     }
 
     /**
      * Returns a constructor with single argument.
-     * @param klass the class to be constructed
+     * @param cls the class to be constructed
      * @param parameterType The constructor parameter type
      * @return null if matching accessible constructor can not be found.
      * @see Class#getConstructor
      * @see #getAccessibleConstructor(java.lang.reflect.Constructor)
      */
-    public static Constructor getAccessibleConstructor(
-        Class klass,
-        Class parameterType) {
-
-        Class[] parameterTypes = { parameterType };
-        return getAccessibleConstructor(klass, parameterTypes);
-
+    public static Constructor getAccessibleConstructor(Class cls,
+            Class parameterType) {
+        return getAccessibleConstructor(cls, new Class[] { parameterType });
     }
 
     /**
      * Returns a constructor given a class and signature.
-     * @param klass the class to be constructed
+     * @param cls the class to be constructed
      * @param parameterTypes the parameter array
      * @return null if matching accessible constructor can not be found
      * @see Class#getConstructor
      * @see #getAccessibleConstructor(java.lang.reflect.Constructor)
      */
-    public static Constructor getAccessibleConstructor(
-        Class klass,
-        Class[] parameterTypes) {
-
+    public static Constructor getAccessibleConstructor(Class cls,
+            Class[] parameterTypes) {
         try {
-            return getAccessibleConstructor(
-                klass.getConstructor(parameterTypes));
+            return getAccessibleConstructor(cls.getConstructor(parameterTypes));
         } catch (NoSuchMethodException e) {
             return (null);
         }
-
     }
 
     /**
@@ -323,29 +282,11 @@
      * @see java.lang.SecurityManager
      */
     public static Constructor getAccessibleConstructor(Constructor ctor) {
-
-        // Make sure we have a method to check
-        if (ctor == null) {
-            return (null);
-        }
-
-        // If the requested method is not public we cannot call it
-        if (!Modifier.isPublic(ctor.getModifiers())) {
-            return (null);
-        }
-
-        // If the declaring class is public, we are done
-        Class clazz = ctor.getDeclaringClass();
-        if (Modifier.isPublic(clazz.getModifiers())) {
-            return (ctor);
-        }
-
-        // what else can we do?
-        return null;
-
+        return MemberUtils.isAccessible(ctor)
+                && Modifier.isPublic(ctor.getDeclaringClass().getModifiers()) ? ctor
+                : null;
     }
 
-    // -------------------------------------------------------- Private Methods
     /**
      * <p>Find an accessible constructor with compatible parameters.
      * Compatible parameters mean that every method parameter is assignable from
@@ -357,80 +298,41 @@
      * are assignment compatible with the parameter types.
      * The first matching constructor is returned.</p>
      *
-     * @param clazz find constructor for this class
+     * @param cls find constructor for this class
      * @param parameterTypes find method with compatible parameters
      * @return a valid Constructor object. If there's no matching constructor, returns <code>null</code>.
      */
-    private static Constructor getMatchingAccessibleConstructor(
-        Class clazz,
-        Class[] parameterTypes) {
-        // see if we can find the method directly
+    public static Constructor getMatchingAccessibleConstructor(Class cls,
+            Class[] parameterTypes) {
+        // see if we can find the constructor directly
         // most of the time this works and it's much faster
         try {
-            Constructor ctor = clazz.getConstructor(parameterTypes);
-            try {
-                //
-                // XXX Default access superclass workaround
-                //
-                // When a public class has a default access superclass
-                // with public methods, these methods are accessible.
-                // Calling them from compiled code works fine.
-                //
-                // Unfortunately, using reflection to invoke these methods
-                // seems to (wrongly) to prevent access even when the method
-                // modifer is public.
-                //
-                // The following workaround solves the problem but will only
-                // work from sufficiently privilages code. 
-                //
-                // Better workarounds would be greatfully accepted.
-                //
-                ctor.setAccessible(true);
-            } catch (SecurityException se) {
-                /* SWALLOW, if workaround fails don't fret. */
-            }
+            Constructor ctor = cls.getConstructor(parameterTypes);
+            MemberUtils.setAccessibleWorkaround(ctor);
             return ctor;
-
         } catch (NoSuchMethodException e) { /* SWALLOW */
         }
-
-        // search through all methods 
-        int paramSize = parameterTypes.length;
-        Constructor[] ctors = clazz.getConstructors();
-        for (int i = 0, size = ctors.length; i < size; i++) {
+        Constructor result = null;
+        // search through all constructors
+        Constructor[] ctors = cls.getConstructors();
+        for (int i = 0; i < ctors.length; i++) {
             // compare parameters
-            Class[] ctorParams = ctors[i].getParameterTypes();
-            int ctorParamSize = ctorParams.length;
-            if (ctorParamSize == paramSize) {
-                boolean match = true;
-                for (int n = 0; n < ctorParamSize; n++) {
-                    if (!MethodUtils
-                        .isAssignmentCompatible(
-                            ctorParams[n],
-                            parameterTypes[n])) {
-                        match = false;
-                        break;
-                    }
-                }
-
-                if (match) {
-                    // get accessible version of method
-                    Constructor ctor = getAccessibleConstructor(ctors[i]);
-                    if (ctor != null) {
-                        try {
-                            ctor.setAccessible(true);
-                        } catch (SecurityException se) {
-                            /* Swallow SecurityException
-                             * TODO: Why?
-                             */
-                        }
-                        return ctor;
+            if (ClassUtils.isAssignable(parameterTypes, ctors[i]
+                    .getParameterTypes(), true)) {
+                // get accessible version of method
+                Constructor ctor = getAccessibleConstructor(ctors[i]);
+                if (ctor != null) {
+                    MemberUtils.setAccessibleWorkaround(ctor);
+                    if (result == null
+                            || MemberUtils.compareParameterTypes(ctor
+                                    .getParameterTypes(), result
+                                    .getParameterTypes(), parameterTypes) < 0) {
+                        result = ctor;
                     }
                 }
             }
         }
-
-        return null;
+        return result;
     }
 
 }

Modified: commons/proper/lang/branches/LANG_POST_2_4/src/java/org/apache/commons/lang/MethodUtils.java
URL: http://svn.apache.org/viewvc/commons/proper/lang/branches/LANG_POST_2_4/src/java/org/apache/commons/lang/MethodUtils.java?rev=638851&r1=638850&r2=638851&view=diff
==============================================================================
--- commons/proper/lang/branches/LANG_POST_2_4/src/java/org/apache/commons/lang/MethodUtils.java (original)
+++ commons/proper/lang/branches/LANG_POST_2_4/src/java/org/apache/commons/lang/MethodUtils.java Wed Mar 19 07:54:06 2008
@@ -14,34 +14,32 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-package org.apache.commons.beanutils;
-
+package org.apache.commons.lang;
 
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 
+import java.util.Arrays;
 import java.util.WeakHashMap;
 
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-
 /**
- * <p> Utility reflection methods focussed on methods in general rather than properties in particular. </p>
+ * <p> Utility reflection methods focused on methods, originally from Commons BeanUtils.
+ * Differences from the BeanUtils version may be noted, especially where similar functionality
+ * already existed within Lang.
+ * </p>
  *
  * <h3>Known Limitations</h3>
  * <h4>Accessing Public Methods In A Default Access Superclass</h4>
- * <p>There is an issue when invoking public methods contained in a default access superclass.
+ * <p>There is an issue when invoking public methods contained in a default access superclass on JREs prior to 1.4.
  * Reflection locates these methods fine and correctly assigns them as public.
  * However, an <code>IllegalAccessException</code> is thrown if the method is invoked.</p>
  *
  * <p><code>MethodUtils</code> contains a workaround for this situation. 
  * It will attempt to call <code>setAccessible</code> on this method.
  * If this call succeeds, then the method can be invoked as normal.
- * This call will only succeed when the application has sufficient security privilages. 
- * If this call fails then a warning will be logged and the method may fail.</p>
+ * This call will only succeed when the application has sufficient security privileges. 
+ * If this call fails then the method may fail.</p>
  *
  * @author Craig R. McClanahan
  * @author Ralph Schaer
@@ -50,40 +48,13 @@
  * @author Gregor Ra&#253;man
  * @author Jan Sorensen
  * @author Robert Burrell Donkin
+ * @author Niall Pemberton
+ * @author Matt Benson
+ * @since 2.5
+ * @version $Id$
  */
-
 public class MethodUtils {
 
-    // --------------------------------------------------------- Private Methods
-    
-    /** 
-     * Only log warning about accessibility work around once.
-     * <p>
-     * Note that this is broken when this class is deployed via a shared
-     * classloader in a container, as the warning message will be emitted
-     * only once, not once per webapp. However making the warning appear
-     * once per webapp means having a map keyed by context classloader
-     * which introduces nasty memory-leak problems. As this warning is
-     * really optional we can ignore this problem; only one of the webapps
-     * will get the warning in its logs but that should be good enough.
-     */
-    private static boolean loggedAccessibleWarning = false;
-    
-    /** 
-     * Indicates whether methods should be cached for improved performance.
-     * <p>
-     * Note that when this class is deployed via a shared classloader in
-     * a container, this will affect all webapps. However making this
-     * configurable per webapp would mean having a map keyed by context classloader
-     * which may introduce memory-leak problems.
-     */
-    private static boolean CACHE_METHODS = true;
-
-    /** An empty class array */
-    private static final Class[] EMPTY_CLASS_PARAMETERS = new Class[0];
-    /** An empty object array */
-    private static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
-
     /**
      * Stores a cache of MethodDescriptor -> Method in a WeakHashMap.
      * <p>
@@ -104,9 +75,29 @@
      * class via different classloaders will generate non-equal MethodDescriptor
      * objects and hence end up with different entries in the map.
      */
-    private static WeakHashMap cache = new WeakHashMap();
-    
-    // --------------------------------------------------------- Public Methods
+    private static final WeakHashMap/* <MethodDescriptor, Method> */cache = new WeakHashMap();
+
+    /**
+     * Indicates whether methods should be cached for improved performance.
+     * <p>
+     * Note that when this class is deployed via a shared classloader in
+     * a container, this will affect all webapps. However making this
+     * configurable per webapp would mean having a map keyed by context classloader
+     * which may introduce memory-leak problems.
+     */
+    private static boolean cacheMethods = true;
+
+    /**
+     * <p>MethodUtils instances should NOT be constructed in standard programming.
+     * Instead, the class should be used as
+     * <code>MethodUtils.getAccessibleMethod(method)</code>.</p>
+     *
+     * <p>This constructor is public to permit tools that require a JavaBean
+     * instance to operate.</p>
+     */
+    public MethodUtils() {
+        super();
+    }
 
     /**
      * Set whether methods should be cached for greater performance or not,
@@ -116,8 +107,8 @@
      * cached for greater performance, otherwise <code>false</code>
      */
     public static synchronized void setCacheMethods(boolean cacheMethods) {
-        CACHE_METHODS = cacheMethods;
-        if (!CACHE_METHODS) {
+        MethodUtils.cacheMethods = cacheMethods;
+        if (!MethodUtils.cacheMethods) {
             clearCache();
         }
     }
@@ -131,21 +122,18 @@
         cache.clear();
         return size;
     }
-    
+
     /**
      * <p>Invoke a named method whose parameter type matches the object type.</p>
      *
-     * <p>The behaviour of this method is less deterministic 
-     * than <code>invokeExactMethod()</code>.
-     * It loops through all methods with names that match
-     * and then executes the first it finds with compatable parameters.</p>
+     * <p>This method delegates the method search to {@link #getMatchingAccessibleMethod(Class, String, Class[])}.</p>
      *
      * <p>This method supports calls to methods taking primitive parameters 
-     * via passing in wrapping classes. So, for example, a <code>Boolean</code> class
+     * via passing in wrapping classes. So, for example, a <code>Boolean</code> object
      * would match a <code>boolean</code> primitive.</p>
      *
      * <p> This is a convenient wrapper for
-     * {@link #invokeMethod(Object object,String methodName,Object [] args)}.
+     * {@link #invokeMethod(Object object, String methodName, Object[] args)}.
      * </p>
      *
      * @param object invoke method on this object
@@ -154,40 +142,26 @@
      * @return The value returned by the invoked method
      *
      * @throws NoSuchMethodException if there is no such accessible method
-     * @throws InvocationTargetException wraps an exception thrown by the
-     *  method invoked
-     * @throws IllegalAccessException if the requested method is not accessible
-     *  via reflection
+     * @throws InvocationTargetException wraps an exception thrown by the method invoked
+     * @throws IllegalAccessException if the requested method is not accessible via reflection
      */
-    public static Object invokeMethod(
-            Object object,
-            String methodName,
-            Object arg)
-            throws
-            NoSuchMethodException,
-            IllegalAccessException,
+    public static Object invokeMethod(Object object, String methodName,
+            Object arg) throws NoSuchMethodException, IllegalAccessException,
             InvocationTargetException {
-
-        Object[] args = {arg};
-        return invokeMethod(object, methodName, args);
-
+        return invokeMethod(object, methodName, new Object[] { arg });
     }
 
-
     /**
      * <p>Invoke a named method whose parameter type matches the object type.</p>
      *
-     * <p>The behaviour of this method is less deterministic 
-     * than {@link #invokeExactMethod(Object object,String methodName,Object [] args)}. 
-     * It loops through all methods with names that match
-     * and then executes the first it finds with compatable parameters.</p>
+     * <p>This method delegates the method search to {@link #getMatchingAccessibleMethod(Class, String, Class[])}.</p>
      *
      * <p>This method supports calls to methods taking primitive parameters 
-     * via passing in wrapping classes. So, for example, a <code>Boolean</code> class
+     * via passing in wrapping classes. So, for example, a <code>Boolean</code> object
      * would match a <code>boolean</code> primitive.</p>
      *
      * <p> This is a convenient wrapper for
-     * {@link #invokeMethod(Object object,String methodName,Object [] args,Class[] parameterTypes)}.
+     * {@link #invokeMethod(Object object,String methodName, Object[] args, Class[] parameterTypes)}.
      * </p>
      *
      * @param object invoke method on this object
@@ -196,47 +170,32 @@
      * @return The value returned by the invoked method
      *
      * @throws NoSuchMethodException if there is no such accessible method
-     * @throws InvocationTargetException wraps an exception thrown by the
-     *  method invoked
-     * @throws IllegalAccessException if the requested method is not accessible
-     *  via reflection
+     * @throws InvocationTargetException wraps an exception thrown by the method invoked
+     * @throws IllegalAccessException if the requested method is not accessible via reflection
      */
-    public static Object invokeMethod(
-            Object object,
-            String methodName,
-            Object[] args)
-            throws
-            NoSuchMethodException,
-            IllegalAccessException,
-            InvocationTargetException {
-        
+    public static Object invokeMethod(Object object, String methodName,
+            Object[] args) throws NoSuchMethodException,
+            IllegalAccessException, InvocationTargetException {
         if (args == null) {
-            args = EMPTY_OBJECT_ARRAY;
-        }  
+            args = ArrayUtils.EMPTY_OBJECT_ARRAY;
+        }
         int arguments = args.length;
         Class[] parameterTypes = new Class[arguments];
         for (int i = 0; i < arguments; i++) {
             parameterTypes[i] = args[i].getClass();
         }
         return invokeMethod(object, methodName, args, parameterTypes);
-
     }
 
-
     /**
      * <p>Invoke a named method whose parameter type matches the object type.</p>
      *
-     * <p>The behaviour of this method is less deterministic 
-     * than {@link 
-     * #invokeExactMethod(Object object,String methodName,Object [] args,Class[] parameterTypes)}. 
-     * It loops through all methods with names that match
-     * and then executes the first it finds with compatable parameters.</p>
+     * <p>This method delegates the method search to {@link #getMatchingAccessibleMethod(Class, String, Class[])}.</p>
      *
      * <p>This method supports calls to methods taking primitive parameters 
-     * via passing in wrapping classes. So, for example, a <code>Boolean</code> class
+     * via passing in wrapping classes. So, for example, a <code>Boolean</code> object
      * would match a <code>boolean</code> primitive.</p>
      *
-     *
      * @param object invoke method on this object
      * @param methodName get method with this name
      * @param args use these arguments - treat null as empty array
@@ -244,40 +203,29 @@
      * @return The value returned by the invoked method
      *
      * @throws NoSuchMethodException if there is no such accessible method
-     * @throws InvocationTargetException wraps an exception thrown by the
-     *  method invoked
-     * @throws IllegalAccessException if the requested method is not accessible
-     *  via reflection
+     * @throws InvocationTargetException wraps an exception thrown by the method invoked
+     * @throws IllegalAccessException if the requested method is not accessible via reflection
      */
-    public static Object invokeMethod(
-            Object object,
-            String methodName,
-            Object[] args,
-            Class[] parameterTypes)
-                throws
-                    NoSuchMethodException,
-                    IllegalAccessException,
-                    InvocationTargetException {
-                    
+    public static Object invokeMethod(Object object, String methodName,
+            Object[] args, Class[] parameterTypes)
+            throws NoSuchMethodException, IllegalAccessException,
+            InvocationTargetException {
         if (parameterTypes == null) {
-            parameterTypes = EMPTY_CLASS_PARAMETERS;
-        }        
+            parameterTypes = ArrayUtils.EMPTY_CLASS_ARRAY;
+        }
         if (args == null) {
-            args = EMPTY_OBJECT_ARRAY;
-        }  
-
-        Method method = getMatchingAccessibleMethod(
-                object.getClass(),
-                methodName,
-                parameterTypes);
+            args = ArrayUtils.EMPTY_OBJECT_ARRAY;
+        }
+        Method method = getMatchingAccessibleMethod(object.getClass(),
+                methodName, parameterTypes);
         if (method == null) {
-            throw new NoSuchMethodException("No such accessible method: " +
-                    methodName + "() on object: " + object.getClass().getName());
+            throw new NoSuchMethodException("No such accessible method: "
+                    + methodName + "() on object: "
+                    + object.getClass().getName());
         }
         return method.invoke(object, args);
     }
 
-
     /**
      * <p>Invoke a method whose parameter type matches exactly the object
      * type.</p>
@@ -297,21 +245,12 @@
      * @throws IllegalAccessException if the requested method is not accessible
      *  via reflection
      */
-    public static Object invokeExactMethod(
-            Object object,
-            String methodName,
-            Object arg)
-            throws
-            NoSuchMethodException,
-            IllegalAccessException,
+    public static Object invokeExactMethod(Object object, String methodName,
+            Object arg) throws NoSuchMethodException, IllegalAccessException,
             InvocationTargetException {
-
-        Object[] args = {arg};
-        return invokeExactMethod(object, methodName, args);
-
+        return invokeExactMethod(object, methodName, new Object[] { arg });
     }
 
-
     /**
      * <p>Invoke a method whose parameter types match exactly the object
      * types.</p>
@@ -330,27 +269,20 @@
      * @throws IllegalAccessException if the requested method is not accessible
      *  via reflection
      */
-    public static Object invokeExactMethod(
-            Object object,
-            String methodName,
-            Object[] args)
-            throws
-            NoSuchMethodException,
-            IllegalAccessException,
-            InvocationTargetException {
+    public static Object invokeExactMethod(Object object, String methodName,
+            Object[] args) throws NoSuchMethodException,
+            IllegalAccessException, InvocationTargetException {
         if (args == null) {
-            args = EMPTY_OBJECT_ARRAY;
-        }  
+            args = ArrayUtils.EMPTY_OBJECT_ARRAY;
+        }
         int arguments = args.length;
         Class[] parameterTypes = new Class[arguments];
         for (int i = 0; i < arguments; i++) {
             parameterTypes[i] = args[i].getClass();
         }
         return invokeExactMethod(object, methodName, args, parameterTypes);
-
     }
 
-
     /**
      * <p>Invoke a method whose parameter types match exactly the parameter
      * types given.</p>
@@ -370,34 +302,24 @@
      * @throws IllegalAccessException if the requested method is not accessible
      *  via reflection
      */
-    public static Object invokeExactMethod(
-            Object object,
-            String methodName,
-            Object[] args,
-            Class[] parameterTypes)
-            throws
-            NoSuchMethodException,
-            IllegalAccessException,
+    public static Object invokeExactMethod(Object object, String methodName,
+            Object[] args, Class[] parameterTypes)
+            throws NoSuchMethodException, IllegalAccessException,
             InvocationTargetException {
-        
         if (args == null) {
-            args = EMPTY_OBJECT_ARRAY;
-        }  
-                
+            args = ArrayUtils.EMPTY_OBJECT_ARRAY;
+        }
         if (parameterTypes == null) {
-            parameterTypes = EMPTY_CLASS_PARAMETERS;
+            parameterTypes = ArrayUtils.EMPTY_CLASS_ARRAY;
         }
-
-        Method method = getAccessibleMethod(
-                object.getClass(),
-                methodName,
+        Method method = getAccessibleMethod(object.getClass(), methodName,
                 parameterTypes);
         if (method == null) {
-            throw new NoSuchMethodException("No such accessible method: " +
-                    methodName + "() on object: " + object.getClass().getName());
+            throw new NoSuchMethodException("No such accessible method: "
+                    + methodName + "() on object: "
+                    + object.getClass().getName());
         }
         return method.invoke(object, args);
-
     }
 
     /**
@@ -407,7 +329,7 @@
      * <p>This uses reflection to invoke the method obtained from a call to
      * {@link #getAccessibleMethod(Class, String, Class[])}.</p>
      *
-     * @param objectClass invoke static method on this class
+     * @param cls invoke static method on this class
      * @param methodName get method with this name
      * @param args use these arguments - treat null as empty array
      * @param parameterTypes match these parameters - treat null as empty array
@@ -419,43 +341,28 @@
      * @throws IllegalAccessException if the requested method is not accessible
      *  via reflection
      */
-    public static Object invokeExactStaticMethod(
-            Class objectClass,
-            String methodName,
-            Object[] args,
-            Class[] parameterTypes)
-            throws
-            NoSuchMethodException,
-            IllegalAccessException,
+    public static Object invokeExactStaticMethod(Class cls, String methodName,
+            Object[] args, Class[] parameterTypes)
+            throws NoSuchMethodException, IllegalAccessException,
             InvocationTargetException {
-        
         if (args == null) {
-            args = EMPTY_OBJECT_ARRAY;
-        }  
-                
+            args = ArrayUtils.EMPTY_OBJECT_ARRAY;
+        }
         if (parameterTypes == null) {
-            parameterTypes = EMPTY_CLASS_PARAMETERS;
+            parameterTypes = ArrayUtils.EMPTY_CLASS_ARRAY;
         }
-
-        Method method = getAccessibleMethod(
-                objectClass,
-                methodName,
-                parameterTypes);
+        Method method = getAccessibleMethod(cls, methodName, parameterTypes);
         if (method == null) {
-            throw new NoSuchMethodException("No such accessible method: " +
-                    methodName + "() on class: " + objectClass.getName());
+            throw new NoSuchMethodException("No such accessible method: "
+                    + methodName + "() on class: " + cls.getName());
         }
         return method.invoke(null, args);
-
     }
 
     /**
      * <p>Invoke a named static method whose parameter type matches the object type.</p>
      *
-     * <p>The behaviour of this method is less deterministic 
-     * than {@link #invokeExactMethod(Object, String, Object[], Class[])}. 
-     * It loops through all methods with names that match
-     * and then executes the first it finds with compatable parameters.</p>
+     * <p>This method delegates the method search to {@link #getMatchingAccessibleMethod(Class, String, Class[])}.</p>
      *
      * <p>This method supports calls to methods taking primitive parameters 
      * via passing in wrapping classes. So, for example, a <code>Boolean</code> class
@@ -465,7 +372,7 @@
      * {@link #invokeStaticMethod(Class objectClass,String methodName,Object [] args)}.
      * </p>
      *
-     * @param objectClass invoke static method on this class
+     * @param cls invoke static method on this class
      * @param methodName get method with this name
      * @param arg use this argument
      * @return The value returned by the invoked method
@@ -476,28 +383,16 @@
      * @throws IllegalAccessException if the requested method is not accessible
      *  via reflection
      */
-    public static Object invokeStaticMethod(
-            Class objectClass,
-            String methodName,
-            Object arg)
-            throws
-            NoSuchMethodException,
-            IllegalAccessException,
+    public static Object invokeStaticMethod(Class cls, String methodName,
+            Object arg) throws NoSuchMethodException, IllegalAccessException,
             InvocationTargetException {
-
-        Object[] args = {arg};
-        return invokeStaticMethod (objectClass, methodName, args);
-
+        return invokeStaticMethod(cls, methodName, new Object[] { arg });
     }
 
-
     /**
      * <p>Invoke a named static method whose parameter type matches the object type.</p>
      *
-     * <p>The behaviour of this method is less deterministic 
-     * than {@link #invokeExactMethod(Object object,String methodName,Object [] args)}. 
-     * It loops through all methods with names that match
-     * and then executes the first it finds with compatable parameters.</p>
+     * <p>This method delegates the method search to {@link #getMatchingAccessibleMethod(Class, String, Class[])}.</p>
      *
      * <p>This method supports calls to methods taking primitive parameters 
      * via passing in wrapping classes. So, for example, a <code>Boolean</code> class
@@ -507,7 +402,7 @@
      * {@link #invokeStaticMethod(Class objectClass,String methodName,Object [] args,Class[] parameterTypes)}.
      * </p>
      *
-     * @param objectClass invoke static method on this class
+     * @param cls invoke static method on this class
      * @param methodName get method with this name
      * @param args use these arguments - treat null as empty array
      * @return The value returned by the invoked method
@@ -518,43 +413,31 @@
      * @throws IllegalAccessException if the requested method is not accessible
      *  via reflection
      */
-    public static Object invokeStaticMethod(
-            Class objectClass,
-            String methodName,
-            Object[] args)
-            throws
-            NoSuchMethodException,
-            IllegalAccessException,
-            InvocationTargetException {
-        
+    public static Object invokeStaticMethod(Class cls, String methodName,
+            Object[] args) throws NoSuchMethodException,
+            IllegalAccessException, InvocationTargetException {
         if (args == null) {
-            args = EMPTY_OBJECT_ARRAY;
-        }  
+            args = ArrayUtils.EMPTY_OBJECT_ARRAY;
+        }
         int arguments = args.length;
         Class[] parameterTypes = new Class[arguments];
         for (int i = 0; i < arguments; i++) {
             parameterTypes[i] = args[i].getClass();
         }
-        return invokeStaticMethod (objectClass, methodName, args, parameterTypes);
-
+        return invokeStaticMethod(cls, methodName, args, parameterTypes);
     }
 
-
     /**
      * <p>Invoke a named static method whose parameter type matches the object type.</p>
      *
-     * <p>The behaviour of this method is less deterministic 
-     * than {@link 
-     * #invokeExactStaticMethod(Class objectClass,String methodName,Object [] args,Class[] parameterTypes)}. 
-     * It loops through all methods with names that match
-     * and then executes the first it finds with compatable parameters.</p>
+     * <p>This method delegates the method search to {@link #getMatchingAccessibleMethod(Class, String, Class[])}.</p>
      *
      * <p>This method supports calls to methods taking primitive parameters 
      * via passing in wrapping classes. So, for example, a <code>Boolean</code> class
      * would match a <code>boolean</code> primitive.</p>
      *
      *
-     * @param objectClass invoke static method on this class
+     * @param cls invoke static method on this class
      * @param methodName get method with this name
      * @param args use these arguments - treat null as empty array
      * @param parameterTypes match these parameters - treat null as empty array
@@ -566,35 +449,25 @@
      * @throws IllegalAccessException if the requested method is not accessible
      *  via reflection
      */
-    public static Object invokeStaticMethod(
-            Class objectClass,
-            String methodName,
-            Object[] args,
-            Class[] parameterTypes)
-                throws
-                    NoSuchMethodException,
-                    IllegalAccessException,
-                    InvocationTargetException {
-                    
+    public static Object invokeStaticMethod(Class cls, String methodName,
+            Object[] args, Class[] parameterTypes)
+            throws NoSuchMethodException, IllegalAccessException,
+            InvocationTargetException {
         if (parameterTypes == null) {
-            parameterTypes = EMPTY_CLASS_PARAMETERS;
-        }        
+            parameterTypes = ArrayUtils.EMPTY_CLASS_ARRAY;
+        }
         if (args == null) {
-            args = EMPTY_OBJECT_ARRAY;
-        }  
-
-        Method method = getMatchingAccessibleMethod(
-                objectClass,
-                methodName,
+            args = ArrayUtils.EMPTY_OBJECT_ARRAY;
+        }
+        Method method = getMatchingAccessibleMethod(cls, methodName,
                 parameterTypes);
         if (method == null) {
-            throw new NoSuchMethodException("No such accessible method: " +
-                    methodName + "() on class: " + objectClass.getName());
+            throw new NoSuchMethodException("No such accessible method: "
+                    + methodName + "() on class: " + cls.getName());
         }
         return method.invoke(null, args);
     }
 
-
     /**
      * <p>Invoke a static method whose parameter type matches exactly the object
      * type.</p>
@@ -603,7 +476,7 @@
      * {@link #invokeExactStaticMethod(Class objectClass,String methodName,Object [] args)}.
      * </p>
      *
-     * @param objectClass invoke static method on this class
+     * @param cls invoke static method on this class
      * @param methodName get method with this name
      * @param arg use this argument
      * @return The value returned by the invoked method
@@ -614,21 +487,12 @@
      * @throws IllegalAccessException if the requested method is not accessible
      *  via reflection
      */
-    public static Object invokeExactStaticMethod(
-            Class objectClass,
-            String methodName,
-            Object arg)
-            throws
-            NoSuchMethodException,
-            IllegalAccessException,
+    public static Object invokeExactStaticMethod(Class cls, String methodName,
+            Object arg) throws NoSuchMethodException, IllegalAccessException,
             InvocationTargetException {
-
-        Object[] args = {arg};
-        return invokeExactStaticMethod (objectClass, methodName, args);
-
+        return invokeExactStaticMethod(cls, methodName, new Object[] { arg });
     }
 
-
     /**
      * <p>Invoke a static method whose parameter types match exactly the object
      * types.</p>
@@ -636,7 +500,7 @@
      * <p> This uses reflection to invoke the method obtained from a call to
      * {@link #getAccessibleMethod(Class, String, Class[])}.</p>
      *
-     * @param objectClass invoke static method on this class
+     * @param cls invoke static method on this class
      * @param methodName get method with this name
      * @param args use these arguments - treat null as empty array
      * @return The value returned by the invoked method
@@ -647,27 +511,20 @@
      * @throws IllegalAccessException if the requested method is not accessible
      *  via reflection
      */
-    public static Object invokeExactStaticMethod(
-            Class objectClass,
-            String methodName,
-            Object[] args)
-            throws
-            NoSuchMethodException,
-            IllegalAccessException,
-            InvocationTargetException {
+    public static Object invokeExactStaticMethod(Class cls, String methodName,
+            Object[] args) throws NoSuchMethodException,
+            IllegalAccessException, InvocationTargetException {
         if (args == null) {
-            args = EMPTY_OBJECT_ARRAY;
-        }  
+            args = ArrayUtils.EMPTY_OBJECT_ARRAY;
+        }
         int arguments = args.length;
         Class[] parameterTypes = new Class[arguments];
         for (int i = 0; i < arguments; i++) {
             parameterTypes[i] = args[i].getClass();
         }
-        return invokeExactStaticMethod(objectClass, methodName, args, parameterTypes);
-
+        return invokeExactStaticMethod(cls, methodName, args, parameterTypes);
     }
 
-
     /**
      * <p>Return an accessible method (that is, one that can be invoked via
      * reflection) with given name and a single parameter.  If no such method
@@ -675,22 +532,17 @@
      * Basically, a convenience wrapper that constructs a <code>Class</code>
      * array for you.</p>
      *
-     * @param clazz get method from this class
+     * @param cls get method from this class
      * @param methodName get method with this name
      * @param parameterType taking this type of parameter
      * @return The accessible method
      */
-    public static Method getAccessibleMethod(
-            Class clazz,
-            String methodName,
+    public static Method getAccessibleMethod(Class cls, String methodName,
             Class parameterType) {
-
-        Class[] parameterTypes = {parameterType};
-        return getAccessibleMethod(clazz, methodName, parameterTypes);
-
+        return getAccessibleMethod(cls, methodName,
+                new Class[] { parameterType });
     }
 
-
     /**
      * <p>Return an accessible method (that is, one that can be invoked via
      * reflection) with given name and parameters.  If no such method
@@ -698,35 +550,30 @@
      * This is just a convenient wrapper for
      * {@link #getAccessibleMethod(Method method)}.</p>
      *
-     * @param clazz get method from this class
+     * @param cls get method from this class
      * @param methodName get method with this name
      * @param parameterTypes with these parameters types
      * @return The accessible method
      */
-    public static Method getAccessibleMethod(
-            Class clazz,
-            String methodName,
+    public static Method getAccessibleMethod(Class cls, String methodName,
             Class[] parameterTypes) {
-
         try {
-            MethodDescriptor md = new MethodDescriptor(clazz, methodName, parameterTypes, true);
+            MethodDescriptor md = new MethodDescriptor(cls, methodName,
+                    parameterTypes, true);
             // Check the cache first
             Method method = getCachedMethod(md);
             if (method != null) {
                 return method;
             }
-            
-            method =  getAccessibleMethod
-                    (clazz.getMethod(methodName, parameterTypes));
+            method = getAccessibleMethod(cls.getMethod(methodName,
+                    parameterTypes));
             cacheMethod(md, method);
             return method;
         } catch (NoSuchMethodException e) {
             return (null);
         }
-
     }
 
-
     /**
      * <p>Return an accessible method (that is, one that can be invoked via
      * reflection) that implements the specified Method.  If no such method
@@ -736,68 +583,50 @@
      * @return The accessible method
      */
     public static Method getAccessibleMethod(Method method) {
-
-        // Make sure we have a method to check
-        if (method == null) {
-            return (null);
-        }
-
-        // If the requested method is not public we cannot call it
-        if (!Modifier.isPublic(method.getModifiers())) {
-            return (null);
+        if (!MemberUtils.isAccessible(method)) {
+            return null;
         }
-
         // If the declaring class is public, we are done
-        Class clazz = method.getDeclaringClass();
-        if (Modifier.isPublic(clazz.getModifiers())) {
-            return (method);
+        Class cls = method.getDeclaringClass();
+        if (Modifier.isPublic(cls.getModifiers())) {
+            return method;
         }
-
-        String methodName      = method.getName();
+        String methodName = method.getName();
         Class[] parameterTypes = method.getParameterTypes();
 
         // Check the implemented interfaces and subinterfaces
-        method =
-                getAccessibleMethodFromInterfaceNest(clazz,
-                        methodName,
-                        parameterTypes);
+        method = getAccessibleMethodFromInterfaceNest(cls, methodName,
+                parameterTypes);
 
         // Check the superclass chain
         if (method == null) {
-            method = getAccessibleMethodFromSuperclass(clazz,
-                        methodName,
-                        parameterTypes);
+            method = getAccessibleMethodFromSuperclass(cls, methodName,
+                    parameterTypes);
         }
-
-        return (method);
-
+        return method;
     }
 
-
-    // -------------------------------------------------------- Private Methods
-
     /**
      * <p>Return an accessible method (that is, one that can be invoked via
      * reflection) by scanning through the superclasses. If no such method
      * can be found, return <code>null</code>.</p>
      *
-     * @param clazz Class to be checked
+     * @param cls Class to be checked
      * @param methodName Method name of the method we wish to call
      * @param parameterTypes The parameter type signatures
      */
-    private static Method getAccessibleMethodFromSuperclass
-            (Class clazz, String methodName, Class[] parameterTypes) {
-
-        Class parentClazz = clazz.getSuperclass();
-        while (parentClazz != null) {
-            if (Modifier.isPublic(parentClazz.getModifiers())) {
+    private static Method getAccessibleMethodFromSuperclass(Class cls,
+            String methodName, Class[] parameterTypes) {
+        Class parentClass = cls.getSuperclass();
+        while (parentClass != null) {
+            if (Modifier.isPublic(parentClass.getModifiers())) {
                 try {
-                    return parentClazz.getMethod(methodName, parameterTypes);
+                    return parentClass.getMethod(methodName, parameterTypes);
                 } catch (NoSuchMethodException e) {
                     return null;
                 }
             }
-            parentClazz = parentClazz.getSuperclass();
+            parentClass = parentClass.getSuperclass();
         }
         return null;
     }
@@ -812,61 +641,46 @@
      * It is because there doesn't seem any reason why other classes should
      * call this rather than the higher level methods.</p>
      *
-     * @param clazz Parent class for the interfaces to be checked
+     * @param cls Parent class for the interfaces to be checked
      * @param methodName Method name of the method we wish to call
      * @param parameterTypes The parameter type signatures
      */
-    private static Method getAccessibleMethodFromInterfaceNest
-            (Class clazz, String methodName, Class[] parameterTypes) {
-
+    private static Method getAccessibleMethodFromInterfaceNest(Class cls,
+            String methodName, Class[] parameterTypes) {
         Method method = null;
 
         // Search up the superclass chain
-        for (; clazz != null; clazz = clazz.getSuperclass()) {
+        for (; cls != null; cls = cls.getSuperclass()) {
 
             // Check the implemented interfaces of the parent class
-            Class[] interfaces = clazz.getInterfaces();
+            Class[] interfaces = cls.getInterfaces();
             for (int i = 0; i < interfaces.length; i++) {
-
                 // Is this interface public?
                 if (!Modifier.isPublic(interfaces[i].getModifiers())) {
                     continue;
                 }
-
                 // Does the method exist on this interface?
                 try {
                     method = interfaces[i].getDeclaredMethod(methodName,
                             parameterTypes);
                 } catch (NoSuchMethodException e) {
-                    /* Swallow, if no method is found after the loop then this
+                    /*
+                     * Swallow, if no method is found after the loop then this
                      * method returns null.
                      */
                 }
                 if (method != null) {
                     break;
                 }
-
                 // Recursively check our parent interfaces
-                method =
-                        getAccessibleMethodFromInterfaceNest(interfaces[i],
-                                methodName,
-                                parameterTypes);
+                method = getAccessibleMethodFromInterfaceNest(interfaces[i],
+                        methodName, parameterTypes);
                 if (method != null) {
                     break;
                 }
-
             }
-
-        }
-
-        // If we found a method return it
-        if (method != null) {
-            return (method);
         }
-
-        // We did not find anything
-        return (null);
-
+        return method;
     }
 
     /**
@@ -876,368 +690,75 @@
      * In other words, it finds a method with the given name 
      * that will take the parameters given.<p>
      *
-     * <p>This method is slightly undeterminstic since it loops 
-     * through methods names and return the first matching method.</p>
-     * 
      * <p>This method is used by 
      * {@link 
-     * #invokeMethod(Object object,String methodName,Object [] args,Class[] parameterTypes)}.
+     * #invokeMethod(Object object, String methodName, Object[] args, Class[] parameterTypes)}.
      *
      * <p>This method can match primitive parameter by passing in wrapper classes.
      * For example, a <code>Boolean</code> will match a primitive <code>boolean</code>
      * parameter.
      *
-     * @param clazz find method in this class
+     * @param cls find method in this class
      * @param methodName find method with this name
-     * @param parameterTypes find method with compatible parameters 
+     * @param parameterTypes find method with most compatible parameters 
      * @return The accessible method
      */
-    public static Method getMatchingAccessibleMethod(
-                                                Class clazz,
-                                                String methodName,
-                                                Class[] parameterTypes) {
-        // trace logging
-        Log log = LogFactory.getLog(MethodUtils.class);
-        if (log.isTraceEnabled()) {
-            log.trace("Matching name=" + methodName + " on " + clazz);
+    public static Method getMatchingAccessibleMethod(Class cls,
+            String methodName, Class[] parameterTypes) {
+        MethodDescriptor md = new MethodDescriptor(cls, methodName,
+                parameterTypes, false);
+        // Check the cache first
+        Method method = getCachedMethod(md);
+        if (method != null) {
+            return method;
         }
-        MethodDescriptor md = new MethodDescriptor(clazz, methodName, parameterTypes, false);
-        
         // see if we can find the method directly
         // most of the time this works and it's much faster
         try {
-            // Check the cache first
-            Method method = getCachedMethod(md);
-            if (method != null) {
-                return method;
-            }
-
-            method = clazz.getMethod(methodName, parameterTypes);
-            if (log.isTraceEnabled()) {
-                log.trace("Found straight match: " + method);
-                log.trace("isPublic:" + Modifier.isPublic(method.getModifiers()));
-            }
-            
-            try {
-                //
-                // XXX Default access superclass workaround
-                //
-                // When a public class has a default access superclass
-                // with public methods, these methods are accessible.
-                // Calling them from compiled code works fine.
-                //
-                // Unfortunately, using reflection to invoke these methods
-                // seems to (wrongly) to prevent access even when the method
-                // modifer is public.
-                //
-                // The following workaround solves the problem but will only
-                // work from sufficiently privilages code. 
-                //
-                // Better workarounds would be greatfully accepted.
-                //
-                method.setAccessible(true);
-                
-            } catch (SecurityException se) {
-                // log but continue just in case the method.invoke works anyway
-                if (!loggedAccessibleWarning) {
-                    boolean vulnerableJVM = false;
-                    try {
-                        String specVersion = System.getProperty("java.specification.version");
-                        if (specVersion.charAt(0) == '1' && 
-                                (specVersion.charAt(2) == '0' ||
-                                 specVersion.charAt(2) == '1' ||
-                                 specVersion.charAt(2) == '2' ||
-                                 specVersion.charAt(2) == '3')) {
-                                 
-                            vulnerableJVM = true;
-                        }
-                    } catch (SecurityException e) {
-                        // don't know - so display warning
-                        vulnerableJVM = true;
-                    }
-                    if (vulnerableJVM) {
-                        log.warn(
-                            "Current Security Manager restricts use of workarounds for reflection bugs "
-                            + " in pre-1.4 JVMs.");
-                    }
-                    loggedAccessibleWarning = true;
-                }
-                log.debug(
-                        "Cannot setAccessible on method. Therefore cannot use jvm access bug workaround.", 
-                        se);
-            }
+            method = cls.getMethod(methodName, parameterTypes);
+            MemberUtils.setAccessibleWorkaround(method);
             cacheMethod(md, method);
             return method;
-            
-        } catch (NoSuchMethodException e) { /* SWALLOW */ }
-        
-        // search through all methods 
-        int paramSize = parameterTypes.length;
+        } catch (NoSuchMethodException e) { /* SWALLOW */
+        }
+        // search through all methods
         Method bestMatch = null;
-        Method[] methods = clazz.getMethods();
-        float bestMatchCost = Float.MAX_VALUE;
-        float myCost = Float.MAX_VALUE;
-        for (int i = 0, size = methods.length; i < size ; i++) {
+        Method[] methods = cls.getMethods();
+        for (int i = 0, size = methods.length; i < size; i++) {
             if (methods[i].getName().equals(methodName)) {
-                // log some trace information
-                if (log.isTraceEnabled()) {
-                    log.trace("Found matching name:");
-                    log.trace(methods[i]);
-                }                
-                
                 // compare parameters
-                Class[] methodsParams = methods[i].getParameterTypes();
-                int methodParamSize = methodsParams.length;
-                if (methodParamSize == paramSize) {          
-                    boolean match = true;
-                    for (int n = 0 ; n < methodParamSize; n++) {
-                        if (log.isTraceEnabled()) {
-                            log.trace("Param=" + parameterTypes[n].getName());
-                            log.trace("Method=" + methodsParams[n].getName());
-                        }
-                        if (!isAssignmentCompatible(methodsParams[n], parameterTypes[n])) {
-                            if (log.isTraceEnabled()) {
-                                log.trace(methodsParams[n] + " is not assignable from " 
-                                            + parameterTypes[n]);
-                            }    
-                            match = false;
-                            break;
-                        }
-                    }
-                    
-                    if (match) {
-                        // get accessible version of method
-                        Method method = getAccessibleMethod(methods[i]);
-                        if (method != null) {
-                            if (log.isTraceEnabled()) {
-                                log.trace(method + " accessible version of " 
-                                            + methods[i]);
-                            }
-                            try {
-                                //
-                                // XXX Default access superclass workaround
-                                // (See above for more details.)
-                                //
-                                method.setAccessible(true);
-                                
-                            } catch (SecurityException se) {
-                                // log but continue just in case the method.invoke works anyway
-                                if (!loggedAccessibleWarning) {
-                                    log.warn(
-            "Cannot use JVM pre-1.4 access bug workaround due to restrictive security manager.");
-                                    loggedAccessibleWarning = true;
-                                }
-                                log.debug(
-            "Cannot setAccessible on method. Therefore cannot use jvm access bug workaround.", 
-                                        se);
-                            }
-                            myCost = getTotalTransformationCost(parameterTypes,method.getParameterTypes());
-                            if ( myCost < bestMatchCost ) {
-                               bestMatch = method;
-                               bestMatchCost = myCost;
-                            }
+                if (ClassUtils.isAssignable(parameterTypes, methods[i]
+                        .getParameterTypes(), true)) {
+                    // get accessible version of method
+                    Method accessibleMethod = getAccessibleMethod(methods[i]);
+                    if (accessibleMethod != null) {
+                        if (bestMatch == null
+                                || MemberUtils.compareParameterTypes(
+                                        accessibleMethod.getParameterTypes(),
+                                        bestMatch.getParameterTypes(),
+                                        parameterTypes) < 0) {
+                            bestMatch = accessibleMethod;
                         }
-                        
-                        log.trace("Couldn't find accessible method.");
                     }
                 }
             }
         }
-        if ( bestMatch != null ){
-                 cacheMethod(md, bestMatch);
-        } else {
-        // didn't find a match
-               log.trace("No match found.");
-        }
-        
-        return bestMatch;                                        
-    }
-
-    /**
-     * Returns the sum of the object transformation cost for each class in the source
-     * argument list.
-     * @param srcArgs The source arguments
-     * @param destArgs The destination arguments
-     * @return The total transformation cost
-     */
-    private static float getTotalTransformationCost(Class[] srcArgs, Class[] destArgs) {
-
-        float totalCost = 0.0f;
-        for (int i = 0; i < srcArgs.length; i++) {
-            Class srcClass, destClass;
-            srcClass = srcArgs[i];
-            destClass = destArgs[i];
-            totalCost += getObjectTransformationCost(srcClass, destClass);
-        }
-
-        return totalCost;
-    }
-    
-    /**
-     * Gets the number of steps required needed to turn the source class into the 
-     * destination class. This represents the number of steps in the object hierarchy 
-     * graph.
-     * @param srcClass The source class
-     * @param destClass The destination class
-     * @return The cost of transforming an object
-     */
-    private static float getObjectTransformationCost(Class srcClass, Class destClass) {
-        float cost = 0.0f;
-        while (destClass != null && !destClass.equals(srcClass)) {
-            if (destClass.isInterface() && isAssignmentCompatible(destClass,srcClass)) {
-                // slight penalty for interface match. 
-                // we still want an exact match to override an interface match, but  
-                // an interface match should override anything where we have to get a 
-                // superclass.
-                cost += 0.25f;
-                break;
-            }
-            cost++;
-            destClass = destClass.getSuperclass();
-        }
-
-        /*
-         * If the destination class is null, we've travelled all the way up to 
-         * an Object match. We'll penalize this by adding 1.5 to the cost.
-         */
-        if (destClass == null) {
-            cost += 1.5f;
-        }
-
-        return cost;
-    }
-    
-    
-    /**
-     * <p>Determine whether a type can be used as a parameter in a method invocation.
-     * This method handles primitive conversions correctly.</p>
-     *
-     * <p>In order words, it will match a <code>Boolean</code> to a <code>boolean</code>,
-     * a <code>Long</code> to a <code>long</code>,
-     * a <code>Float</code> to a <code>float</code>,
-     * a <code>Integer</code> to a <code>int</code>,
-     * and a <code>Double</code> to a <code>double</code>.
-     * Now logic widening matches are allowed.
-     * For example, a <code>Long</code> will not match a <code>int</code>.
-     *
-     * @param parameterType the type of parameter accepted by the method
-     * @param parameterization the type of parameter being tested 
-     *
-     * @return true if the assignement is compatible.
-     */
-    public static final boolean isAssignmentCompatible(Class parameterType, Class parameterization) {
-        // try plain assignment
-        if (parameterType.isAssignableFrom(parameterization)) {
-            return true;
-        }
-        
-        if (parameterType.isPrimitive()) {
-            // this method does *not* do widening - you must specify exactly
-            // is this the right behaviour?
-            Class parameterWrapperClazz = getPrimitiveWrapper(parameterType);
-            if (parameterWrapperClazz != null) {
-                return parameterWrapperClazz.equals(parameterization);
-            }
-        }
-        
-        return false;
-    }
-    
-    /**
-     * Gets the wrapper object class for the given primitive type class.
-     * For example, passing <code>boolean.class</code> returns <code>Boolean.class</code>
-     * @param primitiveType the primitive type class for which a match is to be found
-     * @return the wrapper type associated with the given primitive 
-     * or null if no match is found
-     */
-    public static Class getPrimitiveWrapper(Class primitiveType) {
-        // does anyone know a better strategy than comparing names?
-        if (boolean.class.equals(primitiveType)) {
-            return Boolean.class;
-        } else if (float.class.equals(primitiveType)) {
-            return Float.class;
-        } else if (long.class.equals(primitiveType)) {
-            return Long.class;
-        } else if (int.class.equals(primitiveType)) {
-            return Integer.class;
-        } else if (short.class.equals(primitiveType)) {
-            return Short.class;
-        } else if (byte.class.equals(primitiveType)) {
-            return Byte.class;
-        } else if (double.class.equals(primitiveType)) {
-            return Double.class;
-        } else if (char.class.equals(primitiveType)) {
-            return Character.class;
-        } else {
-            
-            return null;
+        if (bestMatch != null) {
+            MemberUtils.setAccessibleWorkaround(bestMatch);
+            cacheMethod(md, bestMatch);
         }
+        return bestMatch;
     }
 
     /**
-     * Gets the class for the primitive type corresponding to the primitive wrapper class given.
-     * For example, an instance of <code>Boolean.class</code> returns a <code>boolean.class</code>. 
-     * @param wrapperType the 
-     * @return the primitive type class corresponding to the given wrapper class,
-     * null if no match is found
-     */
-    public static Class getPrimitiveType(Class wrapperType) {
-        // does anyone know a better strategy than comparing names?
-        if (Boolean.class.equals(wrapperType)) {
-            return boolean.class;
-        } else if (Float.class.equals(wrapperType)) {
-            return float.class;
-        } else if (Long.class.equals(wrapperType)) {
-            return long.class;
-        } else if (Integer.class.equals(wrapperType)) {
-            return int.class;
-        } else if (Short.class.equals(wrapperType)) {
-            return short.class;
-        } else if (Byte.class.equals(wrapperType)) {
-            return byte.class;
-        } else if (Double.class.equals(wrapperType)) {
-            return double.class;
-        } else if (Character.class.equals(wrapperType)) {
-            return char.class;
-        } else {
-            Log log = LogFactory.getLog(MethodUtils.class);
-            if (log.isDebugEnabled()) {
-                log.debug("Not a known primitive wrapper class: " + wrapperType);
-            }
-            return null;
-        }
-    }
-    
-    /**
-     * Find a non primitive representation for given primitive class.
-     *
-     * @param clazz the class to find a representation for, not null
-     * @return the original class if it not a primitive. Otherwise the wrapper class. Not null
-     */
-    public static Class toNonPrimitiveClass(Class clazz) {
-        if (clazz.isPrimitive()) {
-            Class primitiveClazz = MethodUtils.getPrimitiveWrapper(clazz);
-            // the above method returns 
-            if (primitiveClazz != null) {
-                return primitiveClazz;
-            } else {
-                return clazz;
-            }
-        } else {
-            return clazz;
-        }
-    }
-    
-
-    /**
      * Return the method from the cache, if present.
      *
      * @param md The method descriptor
      * @return The cached method
      */
     private static Method getCachedMethod(MethodDescriptor md) {
-        if (CACHE_METHODS) {
-            return (Method)cache.get(md);
+        if (cacheMethods) {
+            return (Method) cache.get(md);
         }
         return null;
     }
@@ -1249,7 +770,7 @@
      * @param method The method to cache
      */
     private static void cacheMethod(MethodDescriptor md, Method method) {
-        if (CACHE_METHODS) {
+        if (cacheMethods) {
             if (method != null) {
                 cache.put(md, method);
             }
@@ -1274,7 +795,8 @@
          * @param paramTypes the array of classes representing the paramater types
          * @param exact whether the match has to be exact.
          */
-        public MethodDescriptor(Class cls, String methodName, Class[] paramTypes, boolean exact) {
+        public MethodDescriptor(Class cls, String methodName,
+                Class[] paramTypes, boolean exact) {
             if (cls == null) {
                 throw new IllegalArgumentException("Class cannot be null");
             }
@@ -1282,16 +804,16 @@
                 throw new IllegalArgumentException("Method Name cannot be null");
             }
             if (paramTypes == null) {
-                paramTypes = EMPTY_CLASS_PARAMETERS;
+                paramTypes = ArrayUtils.EMPTY_CLASS_ARRAY;
             }
-
             this.cls = cls;
             this.methodName = methodName;
             this.paramTypes = paramTypes;
-            this.exact= exact;
-
+            this.exact = exact;
+            // is this adequate? :/
             this.hashCode = methodName.length();
         }
+
         /**
          * Checks for equality.
          * @param obj object to be tested for equality
@@ -1301,15 +823,13 @@
             if (!(obj instanceof MethodDescriptor)) {
                 return false;
             }
-            MethodDescriptor md = (MethodDescriptor)obj;
+            MethodDescriptor md = (MethodDescriptor) obj;
 
-            return (
-                exact == md.exact &&
-                methodName.equals(md.methodName) &&
-                cls.equals(md.cls) &&
-                java.util.Arrays.equals(paramTypes, md.paramTypes)
-            );
+            return exact == md.exact && methodName.equals(md.methodName)
+                    && cls.equals(md.cls)
+                    && Arrays.equals(paramTypes, md.paramTypes);
         }
+
         /**
          * Returns the string length of method name. I.e. if the
          * hashcodes are different, the objects are different. If the



Mime
View raw message