diff --git a/src/java/org/apache/commons/lang/reflect/MethodUtils.java b/src/java/org/apache/commons/lang/reflect/MethodUtils.java
index 58c517f76..0168acf4b 100644
--- a/src/java/org/apache/commons/lang/reflect/MethodUtils.java
+++ b/src/java/org/apache/commons/lang/reflect/MethodUtils.java
@@ -66,6 +66,7 @@
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
+
/**
* MethodUtils
contains utility methods for working for
* methods by reflection.
@@ -82,7 +83,7 @@
* @author Gregor Raýman
* @author Jan Sorensen
* @author Robert Burrell Donkin
- * @version $Id: MethodUtils.java,v 1.8 2002/11/21 19:38:51 rdonkin Exp $
+ * @version $Id: MethodUtils.java,v 1.9 2002/12/10 19:06:49 rdonkin Exp $
*/
public class MethodUtils {
@@ -116,6 +117,21 @@ public static Method getMethod(Class cls, String methodName) {
return getMethod(cls, methodName, ArrayUtils.EMPTY_CLASS_ARRAY, false);
}
+ /**
+ * Gets a Method by name. The method must be public.
+ * Superclasses will be considered.
+ *
+ * @param cls the class to reflect, must not be null
+ * @param methodName the field name to obtain
+ * @return the Method object
+ * @throws IllegalArgumentException if the class or method name is null
+ * @throws ReflectionException if an error occurs during reflection
+ */
+ public static Method getMethod(Class cls, String methodName, Class paramType) {
+ Class[] paramTypes = {paramType};
+ return getMethod(cls, methodName, paramTypes);
+ }
+
/**
* Gets a Method by name. The method must be public.
* Superclasses will be considered.
@@ -173,7 +189,24 @@ public static Method getMethod(Class cls, String methodName, Class[] paramTypes,
}
throw new NoSuchMethodException("The method '" + methodName + "' could not be found");
} else {
- return cls.getMethod(methodName, paramTypes);
+ // apply workarounds
+ Method method = null;
+ try {
+
+ method = cls.getMethod(methodName, paramTypes);
+
+ } catch(NoSuchMethodException e) {
+ // swallow
+ }
+
+ if (method == null) {
+ // use the same as beanutils for the moment
+ Method[] compatibles = getCompatibleMethods(cls, methodName, paramTypes);
+ if (compatibles.length > 0) {
+ method = compatibles[0];
+ }
+ }
+ return getMethod(method);
}
} catch (ReflectionException ex) {
@@ -186,6 +219,50 @@ public static Method getMethod(Class cls, String methodName, Class[] paramTypes,
ex, "getting method", cls.getName(), null, methodName), ex);
}
}
+
+ /**
+ *
Return an accessible method (that is, one that can be invoked via
+ * reflection) that implements the specified Method. If no such method
+ * can be found, return null
.
Return an accessible method (that is, one that can be invoked via
- * reflection) with given name and a single parameter. If no such method
- * can be found, return null
.
- * Basically, a convenience wrapper that constructs a Class
- * array for you.
Return an accessible method (that is, one that can be invoked via
- * reflection) with given name and parameters. If no such method
- * can be found, return null
.
- * This is just a convenient wrapper for
- * {@link #getAccessibleMethod(Method method)}.
Return an accessible method (that is, one that can be invoked via
- * reflection) that implements the specified Method. If no such method
- * can be found, return null
.
Return an accessible method (that is, one that can be invoked via * reflection) that implements the specified method, by scanning through @@ -433,7 +464,9 @@ public static Method getAccessibleMethod(Method method) { */ private static Method getAccessibleMethodFromInterfaceNest (Class clazz, String methodName, Class parameterTypes[]) { - + if (debug) { + log("Finding accessible method " + methodName + " from interface nest"); + } Method method = null; // Search up the superclass chain @@ -470,38 +503,18 @@ public static Method getAccessibleMethod(Method method) { } // If we found a method return it - if (method != null) + if (method != null) { + if (debug) { + log("Found method in class " + method.getDeclaringClass()); + } return (method); - + } // We did not find anything return (null); - } - - - /** - *
Find an accessible method that matches the given name and has compatible parameters. - * Compatible parameters mean that every method parameter is assignable from - * the given parameters. - * In other words, it finds a method with the given name - * that will take the parameters given.
- * - *
This method is slightly undeterminstic since it loops - * through methods names and return the first matching method.
- * - *This method is used by - * {@link - * #invokeMethod(Object object,String methodName,Object [] args,Class[] parameterTypes)}. - * - *
This method can match primitive parameter by passing in wrapper classes.
- * For example, a Boolean
will match a primitive boolean
- * parameter.
- *
- * @param clazz find method in this class
- * @param methodName find method with this name
- * @param parameterTypes find method with compatible parameters
- */
- private static Method getMatchingAccessibleMethod(
+ }
+
+ private static Method[] getCompatibleMethods(
Class clazz,
String methodName,
Class[] parameterTypes) {
@@ -510,90 +523,36 @@ private static Method getMatchingAccessibleMethod(
log("Matching name=" + methodName + " on " + clazz);
}
- // see if we can find the method directly
- // most of the time this works and it's much faster
- try {
- Method method = clazz.getMethod(methodName, parameterTypes);
- if (debug) {
- log("Found straight match: " + method);
- log("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
- log(
- "Cannot setAccessible on method. Therefore cannot use jvm access bug workaround.",
- se);
- }
- return method;
-
- } catch (NoSuchMethodException e) { /* SWALLOW */ }
-
// search through all methods
int paramSize = parameterTypes.length;
Method[] methods = clazz.getMethods();
+ ArrayList compatibles = new ArrayList(methods.length);
for (int i = 0, size = methods.length; i < size ; i++) {
+ if (debug) {
+ log("Checking: " + methods[i]);
+ }
if (methods[i].getName().equals(methodName)) {
// log some trace information
if (debug) {
- log("Found matching name:");
- log(methods[i]);
+ log("Found matching name:" + methods[i]);
}
// compare parameters
Class[] methodsParams = methods[i].getParameterTypes();
if (ReflectionUtils.isCompatible(parameterTypes, methodsParams)) {
// get accessible version of method
- Method method = getAccessibleMethod(methods[i]);
+ Method method = getMethod(methods[i]);
if (method != null) {
- if (debug) {
- log(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
- log(
- "Cannot setAccessible on method. Therefore cannot use jvm access bug workaround.",
- se);
- }
- return method;
+ compatibles.add(method);
+ } else {
+ log("Couldn't find accessible method for: " + methods[i]);
}
-
- log("Couldn't find accessible method.");
}
}
}
- // didn't find a match
- log("No match found.");
- return null;
- }
+ return (Method[]) compatibles.toArray(new Method[compatibles.size()]);
+ }
private static void log(Object o) {
if (debug) {
diff --git a/src/test/org/apache/commons/lang/reflect/MethodUtilsTestCase.java b/src/test/org/apache/commons/lang/reflect/MethodUtilsTestCase.java
index 2555e9bf8..778878447 100644
--- a/src/test/org/apache/commons/lang/reflect/MethodUtilsTestCase.java
+++ b/src/test/org/apache/commons/lang/reflect/MethodUtilsTestCase.java
@@ -129,7 +129,7 @@ public void testGetAccessibleMethod() {
// easy bit first - find a public method
// METHOD ONE
- Method method = MethodUtils.getAccessibleMethod
+ Method method = MethodUtils.getMethod
(TestBean.class, "setStringProperty", String.class);
// check that we've found one that matches
@@ -141,7 +141,7 @@ public void testGetAccessibleMethod() {
// trickier this one - find a method in a direct interface
// METHOD TWO
- method = MethodUtils.getAccessibleMethod
+ method = MethodUtils.getMethod
(privateBeanFactory.create().getClass(),
"methodBar",
String.class);
@@ -155,7 +155,7 @@ public void testGetAccessibleMethod() {
// trickier this one - find a method in a indirect interface
// METHOD THREE
- method = MethodUtils.getAccessibleMethod
+ method = MethodUtils.getMethod
(privateBeanFactory.createSubclass().getClass(),
"methodBaz",
String.class);
@@ -478,7 +478,7 @@ public void testSimpleStatic3() {
try {
// Acquire the methods we need
- Method currentCounterMethod = MethodUtils.getAccessibleMethod
+ Method currentCounterMethod = MethodUtils.getMethod
(TestBean.class, "currentCounter",
new Class[0]);
assertNotNull("currentCounterMethod exists",
@@ -493,7 +493,7 @@ public void testSimpleStatic3() {
Modifier.isPublic(currentCounterMethod.getModifiers()));
assertTrue("currentCounterMethod static",
Modifier.isStatic(currentCounterMethod.getModifiers()));
- Method incrementCounterMethod1 = MethodUtils.getAccessibleMethod
+ Method incrementCounterMethod1 = MethodUtils.getMethod
(TestBean.class, "incrementCounter",
new Class[0]);
assertNotNull("incrementCounterMethod1 exists",
@@ -508,7 +508,7 @@ public void testSimpleStatic3() {
Modifier.isPublic(incrementCounterMethod1.getModifiers()));
assertTrue("incrementCounterMethod1 static",
Modifier.isStatic(incrementCounterMethod1.getModifiers()));
- Method incrementCounterMethod2 = MethodUtils.getAccessibleMethod
+ Method incrementCounterMethod2 = MethodUtils.getMethod
(TestBean.class, "incrementCounter",
new Class[] { Integer.TYPE });
assertNotNull("incrementCounterMethod2 exists",