in src/main/java/org/apache/commons/beanutils2/MethodUtils.java [440:535]
public static Method getMatchingAccessibleMethod(
final Class<?> clazz,
final String methodName,
final Class<?>[] parameterTypes) {
// trace logging
if (LOG.isTraceEnabled()) {
LOG.trace("Matching name=" + methodName + " on " + clazz);
}
final 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()));
}
setMethodAccessible(method); // Default access superclass workaround
cacheMethod(md, method);
return method;
} catch (final NoSuchMethodException e) { /* SWALLOW */ }
// search through all methods
final int paramSize = parameterTypes.length;
Method bestMatch = null;
final Method[] methods = clazz.getMethods();
float bestMatchCost = Float.MAX_VALUE;
float myCost = Float.MAX_VALUE;
for (final Method method2 : methods) {
if (method2.getName().equals(methodName)) {
// log some trace information
if (LOG.isTraceEnabled()) {
LOG.trace("Found matching name:");
LOG.trace(method2);
}
// compare parameters
final Class<?>[] methodsParams = method2.getParameterTypes();
final 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
final Method method = getAccessibleMethod(clazz, method2);
if (method != null) {
if (LOG.isTraceEnabled()) {
LOG.trace(method + " accessible version of "
+ method2);
}
setMethodAccessible(method); // Default access superclass workaround
myCost = getTotalTransformationCost(parameterTypes, method.getParameterTypes());
if ( myCost < bestMatchCost ) {
bestMatch = method;
bestMatchCost = myCost;
}
}
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;
}