|
40 | 40 | import org.apache.commons.lang3.ClassUtils; |
41 | 41 | import org.apache.commons.lang3.ClassUtils.Interfaces; |
42 | 42 | import org.apache.commons.lang3.Validate; |
| 43 | +import org.apache.commons.lang3.stream.LangCollectors; |
43 | 44 |
|
44 | 45 | /** |
45 | 46 | * Utility reflection methods focused on {@link Method}s, originally from Commons BeanUtils. |
@@ -293,6 +294,19 @@ public static <A extends Annotation> A getAnnotation(final Method method, final |
293 | 294 | return annotation; |
294 | 295 | } |
295 | 296 |
|
| 297 | + private static Method getInvokeMethod(final boolean forceAccess, final String methodName, final Class<?>[] parameterTypes, final Class<? extends Object> cls) { |
| 298 | + final Method method; |
| 299 | + if (forceAccess) { |
| 300 | + method = getMatchingMethod(cls, methodName, parameterTypes); |
| 301 | + if (method != null && !method.isAccessible()) { |
| 302 | + method.setAccessible(true); |
| 303 | + } |
| 304 | + } else { |
| 305 | + method = getMatchingAccessibleMethod(cls, methodName, parameterTypes); |
| 306 | + } |
| 307 | + return method; |
| 308 | + } |
| 309 | + |
296 | 310 | /** |
297 | 311 | * Gets an accessible method that matches the given name and has compatible parameters. Compatible parameters mean that every method parameter is assignable |
298 | 312 | * from the given parameters. In other words, it finds a method with the given name that will take the parameters given. |
@@ -336,13 +350,13 @@ public static Method getMatchingAccessibleMethod(final Class<?> cls, final Strin |
336 | 350 | if (bestMatch != null && bestMatch.isVarArgs() && bestMatch.getParameterTypes().length > 0 && parameterTypes.length > 0) { |
337 | 351 | final Class<?>[] methodParameterTypes = bestMatch.getParameterTypes(); |
338 | 352 | final Class<?> methodParameterComponentType = methodParameterTypes[methodParameterTypes.length - 1].getComponentType(); |
339 | | - final String methodParameterComponentTypeName = ClassUtils.primitiveToWrapper(methodParameterComponentType).getName(); |
| 353 | + final String varVargTypeName = ClassUtils.primitiveToWrapper(methodParameterComponentType).getName(); |
340 | 354 | final Class<?> lastParameterType = parameterTypes[parameterTypes.length - 1]; |
341 | 355 | final String parameterTypeName = lastParameterType == null ? null : lastParameterType.getName(); |
342 | 356 | final String parameterTypeSuperClassName = lastParameterType == null ? null |
343 | 357 | : lastParameterType.getSuperclass() != null ? lastParameterType.getSuperclass().getName() : null; |
344 | | - if (parameterTypeName != null && parameterTypeSuperClassName != null && !methodParameterComponentTypeName.equals(parameterTypeName) |
345 | | - && !methodParameterComponentTypeName.equals(parameterTypeSuperClassName)) { |
| 358 | + if (parameterTypeName != null && parameterTypeSuperClassName != null && !varVargTypeName.equals(parameterTypeName) |
| 359 | + && !varVargTypeName.equals(parameterTypeSuperClassName)) { |
346 | 360 | return null; |
347 | 361 | } |
348 | 362 | } |
@@ -673,10 +687,9 @@ public static Object invokeExactMethod(final Object object, final String methodN |
673 | 687 | public static Object invokeExactMethod(final Object object, final String methodName, final Object[] args, final Class<?>[] parameterTypes) |
674 | 688 | throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { |
675 | 689 | final Class<?> cls = Objects.requireNonNull(object, "object").getClass(); |
676 | | - final Method method = getAccessibleMethod(cls, methodName, ArrayUtils.nullToEmpty(parameterTypes)); |
677 | | - if (method == null) { |
678 | | - throw new NoSuchMethodException("No such accessible method: " + methodName + "() on object: " + cls.getName()); |
679 | | - } |
| 690 | + final Class<?>[] paramTypes = ArrayUtils.nullToEmpty(parameterTypes); |
| 691 | + final Method method = getAccessibleMethod(cls, methodName, paramTypes); |
| 692 | + requireNonNull(method, cls, methodName, paramTypes); |
680 | 693 | return method.invoke(object, ArrayUtils.nullToEmpty(args)); |
681 | 694 | } |
682 | 695 |
|
@@ -741,10 +754,9 @@ public static Object invokeExactStaticMethod(final Class<?> cls, final String me |
741 | 754 | */ |
742 | 755 | public static Object invokeExactStaticMethod(final Class<?> cls, final String methodName, final Object[] args, final Class<?>[] parameterTypes) |
743 | 756 | throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { |
744 | | - final Method method = getAccessibleMethod(cls, methodName, ArrayUtils.nullToEmpty(parameterTypes)); |
745 | | - if (method == null) { |
746 | | - throw new NoSuchMethodException("No such accessible method: " + methodName + "() on class: " + cls.getName()); |
747 | | - } |
| 757 | + final Class<?>[] paramTypes = ArrayUtils.nullToEmpty(parameterTypes); |
| 758 | + final Method method = getAccessibleMethod(cls, methodName, ArrayUtils.nullToEmpty(paramTypes)); |
| 759 | + requireNonNull(method, cls, methodName, paramTypes); |
748 | 760 | return method.invoke(null, ArrayUtils.nullToEmpty(args)); |
749 | 761 | } |
750 | 762 |
|
@@ -858,26 +870,12 @@ public static Object invokeMethod(final Object object, final boolean forceAccess |
858 | 870 | * @see SecurityManager#checkPermission |
859 | 871 | * @since 3.5 |
860 | 872 | */ |
861 | | - public static Object invokeMethod(final Object object, final boolean forceAccess, final String methodName, final Object[] args, Class<?>[] parameterTypes) |
| 873 | + public static Object invokeMethod(final Object object, final boolean forceAccess, final String methodName, final Object[] args, final Class<?>[] parameterTypes) |
862 | 874 | throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { |
863 | | - Objects.requireNonNull(object, "object"); |
864 | | - parameterTypes = ArrayUtils.nullToEmpty(parameterTypes); |
865 | | - final String messagePrefix; |
866 | | - final Method method; |
867 | | - final Class<? extends Object> cls = object.getClass(); |
868 | | - if (forceAccess) { |
869 | | - messagePrefix = "No such method: "; |
870 | | - method = getMatchingMethod(cls, methodName, parameterTypes); |
871 | | - if (method != null && !method.isAccessible()) { |
872 | | - method.setAccessible(true); |
873 | | - } |
874 | | - } else { |
875 | | - messagePrefix = "No such accessible method: "; |
876 | | - method = getMatchingAccessibleMethod(cls, methodName, parameterTypes); |
877 | | - } |
878 | | - if (method == null) { |
879 | | - throw new NoSuchMethodException(messagePrefix + methodName + "() on object: " + cls.getName()); |
880 | | - } |
| 875 | + final Class<? extends Object> cls = Objects.requireNonNull(object, "object").getClass(); |
| 876 | + final Class<?>[] paramTypes = ArrayUtils.nullToEmpty(parameterTypes); |
| 877 | + final Method method = getInvokeMethod(forceAccess, methodName, paramTypes, cls); |
| 878 | + requireNonNull(method, cls, methodName, paramTypes); |
881 | 879 | return method.invoke(object, toVarArgs(method, ArrayUtils.nullToEmpty(args))); |
882 | 880 | } |
883 | 881 |
|
@@ -1056,11 +1054,19 @@ public static Object invokeStaticMethod(final Class<?> cls, final String methodN |
1056 | 1054 | */ |
1057 | 1055 | public static Object invokeStaticMethod(final Class<?> cls, final String methodName, final Object[] args, final Class<?>[] parameterTypes) |
1058 | 1056 | throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { |
1059 | | - final Method method = getMatchingAccessibleMethod(cls, methodName, ArrayUtils.nullToEmpty(parameterTypes)); |
| 1057 | + final Class<?>[] paramTypes = ArrayUtils.nullToEmpty(parameterTypes); |
| 1058 | + final Method method = getMatchingAccessibleMethod(cls, methodName, paramTypes); |
| 1059 | + requireNonNull(method, cls, methodName, paramTypes); |
| 1060 | + return method.invoke(null, toVarArgs(method, ArrayUtils.nullToEmpty(args))); |
| 1061 | + } |
| 1062 | + |
| 1063 | + private static Method requireNonNull(final Method method, final Class<?> cls, final String methodName, final Class<?>[] parameterTypes) |
| 1064 | + throws NoSuchMethodException { |
1060 | 1065 | if (method == null) { |
1061 | | - throw new NoSuchMethodException("No such accessible method: " + methodName + "() on class: " + cls.getName()); |
| 1066 | + throw new NoSuchMethodException(String.format("No method: %s.%s(%s)", cls.getName(), methodName, |
| 1067 | + Stream.of(parameterTypes).map(Class::getName).collect(LangCollectors.joining()))); |
1062 | 1068 | } |
1063 | | - return method.invoke(null, toVarArgs(method, ArrayUtils.nullToEmpty(args))); |
| 1069 | + return method; |
1064 | 1070 | } |
1065 | 1071 |
|
1066 | 1072 | private static Object[] toVarArgs(final Method method, final Object[] args) { |
|
0 commit comments