205 lines
8.5 KiB
Java
205 lines
8.5 KiB
Java
package org.apache.commons.beanutils;
|
|
|
|
import java.lang.reflect.InvocationTargetException;
|
|
import java.lang.reflect.Method;
|
|
import java.lang.reflect.Modifier;
|
|
import org.apache.commons.logging.Log;
|
|
import org.apache.commons.logging.LogFactory;
|
|
|
|
public class MethodUtils {
|
|
private static Log log = LogFactory.getLog(MethodUtils.class);
|
|
|
|
private static boolean loggedAccessibleWarning = false;
|
|
|
|
private static final Class[] emptyClassArray = new Class[0];
|
|
|
|
private static final Object[] emptyObjectArray = new Object[0];
|
|
|
|
public static Object invokeMethod(Object object, String methodName, Object arg) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
|
|
Object[] args = { arg };
|
|
return invokeMethod(object, methodName, args);
|
|
}
|
|
|
|
public static Object invokeMethod(Object object, String methodName, Object[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
|
|
if (args == null)
|
|
args = emptyObjectArray;
|
|
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);
|
|
}
|
|
|
|
public static Object invokeMethod(Object object, String methodName, Object[] args, Class[] parameterTypes) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
|
|
if (parameterTypes == null)
|
|
parameterTypes = emptyClassArray;
|
|
if (args == null)
|
|
args = emptyObjectArray;
|
|
Method method = getMatchingAccessibleMethod(object.getClass(), methodName, parameterTypes);
|
|
if (method == null)
|
|
throw new NoSuchMethodException("No such accessible method: " + methodName + "() on object: " + object.getClass().getName());
|
|
return method.invoke(object, args);
|
|
}
|
|
|
|
public static Object invokeExactMethod(Object object, String methodName, Object arg) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
|
|
Object[] args = { arg };
|
|
return invokeExactMethod(object, methodName, args);
|
|
}
|
|
|
|
public static Object invokeExactMethod(Object object, String methodName, Object[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
|
|
if (args == null)
|
|
args = emptyObjectArray;
|
|
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);
|
|
}
|
|
|
|
public static Object invokeExactMethod(Object object, String methodName, Object[] args, Class[] parameterTypes) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
|
|
if (args == null)
|
|
args = emptyObjectArray;
|
|
if (parameterTypes == null)
|
|
parameterTypes = emptyClassArray;
|
|
Method method = getAccessibleMethod(object.getClass(), methodName, parameterTypes);
|
|
if (method == null)
|
|
throw new NoSuchMethodException("No such accessible method: " + methodName + "() on object: " + object.getClass().getName());
|
|
return method.invoke(object, args);
|
|
}
|
|
|
|
public static Method getAccessibleMethod(Class clazz, String methodName, Class parameterType) {
|
|
Class[] parameterTypes = { parameterType };
|
|
return getAccessibleMethod(clazz, methodName, parameterTypes);
|
|
}
|
|
|
|
public static Method getAccessibleMethod(Class clazz, String methodName, Class[] parameterTypes) {
|
|
try {
|
|
return getAccessibleMethod(clazz.getMethod(methodName, parameterTypes));
|
|
} catch (NoSuchMethodException e) {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public static Method getAccessibleMethod(Method method) {
|
|
if (method == null)
|
|
return null;
|
|
if (!Modifier.isPublic(method.getModifiers()))
|
|
return null;
|
|
Class clazz = method.getDeclaringClass();
|
|
if (Modifier.isPublic(clazz.getModifiers()))
|
|
return method;
|
|
method = getAccessibleMethodFromInterfaceNest(clazz, method.getName(), method.getParameterTypes());
|
|
return method;
|
|
}
|
|
|
|
private static Method getAccessibleMethodFromInterfaceNest(Class clazz, String methodName, Class[] parameterTypes) {
|
|
Method method = null;
|
|
for (; clazz != null; clazz = clazz.getSuperclass()) {
|
|
Class[] interfaces = clazz.getInterfaces();
|
|
for (int i = 0; i < interfaces.length; i++) {
|
|
if (Modifier.isPublic(interfaces[i].getModifiers())) {
|
|
try {
|
|
method = interfaces[i].getDeclaredMethod(methodName, parameterTypes);
|
|
} catch (NoSuchMethodException e) {}
|
|
if (method != null)
|
|
break;
|
|
method = getAccessibleMethodFromInterfaceNest(interfaces[i], methodName, parameterTypes);
|
|
if (method != null)
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (method != null)
|
|
return method;
|
|
return null;
|
|
}
|
|
|
|
public static Method getMatchingAccessibleMethod(Class clazz, String methodName, Class[] parameterTypes) {
|
|
if (log.isTraceEnabled())
|
|
log.trace("Matching name=" + methodName + " on " + clazz);
|
|
try {
|
|
Method method = clazz.getMethod(methodName, parameterTypes);
|
|
if (log.isTraceEnabled()) {
|
|
log.trace("Found straight match: " + method);
|
|
log.trace("isPublic:" + Modifier.isPublic(method.getModifiers()));
|
|
}
|
|
try {
|
|
method.setAccessible(true);
|
|
} catch (SecurityException se) {
|
|
if (!loggedAccessibleWarning) {
|
|
log.warn("Cannot use JVM pre-1.4 access bug workaround die to restrictive security manager.");
|
|
loggedAccessibleWarning = true;
|
|
}
|
|
log.debug("Cannot setAccessible on method. Therefore cannot use jvm access bug workaround.", se);
|
|
}
|
|
return method;
|
|
} catch (NoSuchMethodException e) {
|
|
int paramSize = parameterTypes.length;
|
|
Method[] methods = clazz.getMethods();
|
|
for (int i = 0, size = methods.length; i < size; i++) {
|
|
if (methods[i].getName().equals(methodName)) {
|
|
if (log.isTraceEnabled()) {
|
|
log.trace("Found matching name:");
|
|
log.trace(methods[i]);
|
|
}
|
|
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) {
|
|
Method method = getAccessibleMethod(methods[i]);
|
|
if (method != null) {
|
|
if (log.isTraceEnabled())
|
|
log.trace(method + " accessible version of " + methods[i]);
|
|
try {
|
|
method.setAccessible(true);
|
|
} catch (SecurityException se) {
|
|
if (!loggedAccessibleWarning) {
|
|
log.warn("Cannot use JVM pre-1.4 access bug workaround die to restrictive security manager.");
|
|
loggedAccessibleWarning = true;
|
|
}
|
|
log.debug("Cannot setAccessible on method. Therefore cannot use jvm access bug workaround.", se);
|
|
}
|
|
return method;
|
|
}
|
|
log.trace("Couldn't find accessible method.");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
log.trace("No match found.");
|
|
return null;
|
|
}
|
|
}
|
|
|
|
protected static final boolean isAssignmentCompatible(Class parameterType, Class parameterization) {
|
|
if (parameterType.isAssignableFrom(parameterization))
|
|
return true;
|
|
if (parameterType.isPrimitive()) {
|
|
if (boolean.class.equals(parameterType))
|
|
return Boolean.class.equals(parameterization);
|
|
if (float.class.equals(parameterType))
|
|
return Float.class.equals(parameterization);
|
|
if (long.class.equals(parameterType))
|
|
return Long.class.equals(parameterization);
|
|
if (int.class.equals(parameterType))
|
|
return Integer.class.equals(parameterization);
|
|
if (double.class.equals(parameterType))
|
|
return Double.class.equals(parameterization);
|
|
}
|
|
return false;
|
|
}
|
|
}
|