MethodUtils.java 源代码
package com.x8zs.plugin.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;
public class MethodUtils {
private static Map<String, Method> sMethodCache = new HashMap();
private static <T> Constructor<T> getAccessibleConstructor(Constructor<T> constructor) {
boolean z6;
if (constructor != null) {
z6 = true;
} else {
z6 = false;
}
Validate.isTrue(z6, "constructor cannot be null", new Object[0]);
if (!MemberUtils.isAccessible(constructor) || !isAccessible(constructor.getDeclaringClass())) {
return null;
}
return constructor;
}
private static Method getAccessibleMethod(Method method) {
if (!MemberUtils.isAccessible(method)) {
return null;
}
Class<?> declaringClass = method.getDeclaringClass();
if (Modifier.isPublic(declaringClass.getModifiers())) {
return method;
}
String name = method.getName();
Class<?>[] parameterTypes = method.getParameterTypes();
Method accessibleMethodFromInterfaceNest = getAccessibleMethodFromInterfaceNest(declaringClass, name, parameterTypes);
return accessibleMethodFromInterfaceNest == null ? getAccessibleMethodFromSuperclass(declaringClass, name, parameterTypes) : accessibleMethodFromInterfaceNest;
}
private static Method getAccessibleMethodFromInterfaceNest(Class<?> cls, String str, Class<?>... clsArr) {
while (cls != null) {
Class<?>[] interfaces = cls.getInterfaces();
for (int i6 = 0; i6 < interfaces.length; i6++) {
if (Modifier.isPublic(interfaces[i6].getModifiers())) {
try {
return interfaces[i6].getDeclaredMethod(str, clsArr);
} catch (NoSuchMethodException unused) {
Method accessibleMethodFromInterfaceNest = getAccessibleMethodFromInterfaceNest(interfaces[i6], str, clsArr);
if (accessibleMethodFromInterfaceNest != null) {
return accessibleMethodFromInterfaceNest;
}
}
}
}
cls = cls.getSuperclass();
}
return null;
}
private static Method getAccessibleMethodFromSuperclass(Class<?> cls, String str, Class<?>... clsArr) {
for (Class<? super Object> superclass = cls.getSuperclass(); superclass != null; superclass = superclass.getSuperclass()) {
if (Modifier.isPublic(superclass.getModifiers())) {
try {
return superclass.getMethod(str, clsArr);
} catch (NoSuchMethodException unused) {
return null;
}
}
}
return null;
}
private static String getKey(Class<?> cls, String str, Class<?>... clsArr) {
StringBuilder sb = new StringBuilder();
sb.append(cls.toString());
sb.append("#");
sb.append(str);
if (clsArr != null && clsArr.length > 0) {
for (Class<?> cls2 : clsArr) {
sb.append(cls2.toString());
sb.append("#");
}
} else {
sb.append(Void.class.toString());
}
return sb.toString();
}
public static <T> Constructor<T> getMatchingAccessibleConstructor(Class<T> cls, Class<?>... clsArr) {
boolean z6;
Constructor<T> accessibleConstructor;
if (cls != null) {
z6 = true;
} else {
z6 = false;
}
Validate.isTrue(z6, "class cannot be null", new Object[0]);
try {
Constructor<T> constructor = cls.getConstructor(clsArr);
MemberUtils.setAccessibleWorkaround(constructor);
return constructor;
} catch (NoSuchMethodException unused) {
Constructor<T> constructor2 = null;
for (Constructor<?> constructor3 : cls.getConstructors()) {
if (MemberUtils.isAssignable(clsArr, constructor3.getParameterTypes(), true) && (accessibleConstructor = getAccessibleConstructor(constructor3)) != null) {
MemberUtils.setAccessibleWorkaround(accessibleConstructor);
if (constructor2 == null || MemberUtils.compareParameterTypes(accessibleConstructor.getParameterTypes(), constructor2.getParameterTypes(), clsArr) < 0) {
constructor2 = accessibleConstructor;
}
}
}
return constructor2;
}
}
private static Method getMatchingAccessibleMethod(Class<?> cls, String str, Class<?>... clsArr) {
Method method;
Method accessibleMethod;
String key = getKey(cls, str, clsArr);
synchronized (sMethodCache) {
method = sMethodCache.get(key);
}
if (method != null) {
if (!method.isAccessible()) {
method.setAccessible(true);
}
return method;
}
try {
Method method2 = cls.getMethod(str, clsArr);
MemberUtils.setAccessibleWorkaround(method2);
synchronized (sMethodCache) {
sMethodCache.put(key, method2);
}
return method2;
} catch (NoSuchMethodException unused) {
Method method3 = null;
for (Method method4 : cls.getMethods()) {
if (method4.getName().equals(str) && MemberUtils.isAssignable(clsArr, method4.getParameterTypes(), true) && (accessibleMethod = getAccessibleMethod(method4)) != null && (method3 == null || MemberUtils.compareParameterTypes(accessibleMethod.getParameterTypes(), method3.getParameterTypes(), clsArr) < 0)) {
method3 = accessibleMethod;
}
}
if (method3 != null) {
MemberUtils.setAccessibleWorkaround(method3);
}
synchronized (sMethodCache) {
sMethodCache.put(key, method3);
return method3;
}
}
}
public static <T> T invokeConstructor(Class<T> cls, Object... objArr) {
Object[] nullToEmpty = Utils.nullToEmpty(objArr);
return (T) invokeConstructor(cls, nullToEmpty, Utils.toClass(nullToEmpty));
}
public static Object invokeMethod(Object obj, String str, Object[] objArr, Class<?>[] clsArr) {
Class<?>[] nullToEmpty = Utils.nullToEmpty(clsArr);
Object[] nullToEmpty2 = Utils.nullToEmpty(objArr);
Method matchingAccessibleMethod = getMatchingAccessibleMethod(obj.getClass(), str, nullToEmpty);
if (matchingAccessibleMethod != null) {
return matchingAccessibleMethod.invoke(obj, nullToEmpty2);
}
throw new NoSuchMethodException("No such accessible method: " + str + "() on object: " + obj.getClass().getName());
}
public static Object invokeStaticMethod(Class cls, String str, Object[] objArr, Class<?>[] clsArr) {
Class<?>[] nullToEmpty = Utils.nullToEmpty(clsArr);
Object[] nullToEmpty2 = Utils.nullToEmpty(objArr);
Method matchingAccessibleMethod = getMatchingAccessibleMethod(cls, str, nullToEmpty);
if (matchingAccessibleMethod != null) {
return matchingAccessibleMethod.invoke(null, nullToEmpty2);
}
throw new NoSuchMethodException("No such accessible method: " + str + "() on object: " + cls.getName());
}
private static boolean isAccessible(Class<?> cls) {
while (cls != null) {
if (!Modifier.isPublic(cls.getModifiers())) {
return false;
}
cls = cls.getEnclosingClass();
}
return true;
}
public static <T> T invokeConstructor(Class<T> cls, Object[] objArr, Class<?>[] clsArr) {
Object[] nullToEmpty = Utils.nullToEmpty(objArr);
Constructor matchingAccessibleConstructor = getMatchingAccessibleConstructor(cls, Utils.nullToEmpty(clsArr));
if (matchingAccessibleConstructor != null) {
return (T) matchingAccessibleConstructor.newInstance(nullToEmpty);
}
throw new NoSuchMethodException("No such accessible constructor on object: " + cls.getName());
}
public static Object invokeMethod(Object obj, String str, Object... objArr) {
Object[] nullToEmpty = Utils.nullToEmpty(objArr);
return invokeMethod(obj, str, nullToEmpty, Utils.toClass(nullToEmpty));
}
public static Object invokeStaticMethod(Class cls, String str, Object... objArr) {
Object[] nullToEmpty = Utils.nullToEmpty(objArr);
return invokeStaticMethod(cls, str, nullToEmpty, Utils.toClass(nullToEmpty));
}
public static Method getAccessibleMethod(Class<?> cls, String str, Class<?>... clsArr) {
Method method;
String key = getKey(cls, str, clsArr);
synchronized (sMethodCache) {
method = sMethodCache.get(key);
}
if (method != null) {
if (!method.isAccessible()) {
method.setAccessible(true);
}
return method;
}
Method accessibleMethod = getAccessibleMethod(cls.getMethod(str, clsArr));
synchronized (sMethodCache) {
sMethodCache.put(key, accessibleMethod);
}
return accessibleMethod;
}
}