Fixed detection of setter in case of getter with covariant return type narrowing

Issue: SPR-10995
This commit is contained in:
Juergen Hoeller
2013-10-26 15:14:31 +02:00
parent 42568afb37
commit 045f78e6c5
4 changed files with 81 additions and 36 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,15 +17,12 @@
package org.springframework.util;
import java.beans.Introspector;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
import java.security.AccessControlException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
@@ -578,7 +575,7 @@ public abstract class ClassUtils {
/**
* Determine whether the given class has a public constructor with the given signature.
* <p>Essentially translates {@code NoSuchMethodException} to "false".
* @param clazz the clazz to analyze
* @param clazz the clazz to analyze
* @param paramTypes the parameter types of the method
* @return whether the class has a corresponding constructor
* @see Class#getMethod
@@ -591,7 +588,7 @@ public abstract class ClassUtils {
* Determine whether the given class has a public constructor with the given signature,
* and return it if available (else return {@code null}).
* <p>Essentially translates {@code NoSuchMethodException} to {@code null}.
* @param clazz the clazz to analyze
* @param clazz the clazz to analyze
* @param paramTypes the parameter types of the method
* @return the constructor, or {@code null} if not found
* @see Class#getConstructor
@@ -607,9 +604,9 @@ public abstract class ClassUtils {
}
/**
* Determine whether the given class has a method with the given signature.
* Determine whether the given class has a public method with the given signature.
* <p>Essentially translates {@code NoSuchMethodException} to "false".
* @param clazz the clazz to analyze
* @param clazz the clazz to analyze
* @param methodName the name of the method
* @param paramTypes the parameter types of the method
* @return whether the class has a corresponding method
@@ -620,12 +617,15 @@ public abstract class ClassUtils {
}
/**
* Determine whether the given class has a method with the given signature,
* Determine whether the given class has a public method with the given signature,
* and return it if available (else throws an {@code IllegalStateException}).
* <p>In case of any signature specified, only returns the method if there is a
* unique candidate, i.e. a single public method with the specified name.
* <p>Essentially translates {@code NoSuchMethodException} to {@code IllegalStateException}.
* @param clazz the clazz to analyze
* @param clazz the clazz to analyze
* @param methodName the name of the method
* @param paramTypes the parameter types of the method
* (may be {@code null} to indicate any signature)
* @return the method (never {@code null})
* @throws IllegalStateException if the method has not been found
* @see Class#getMethod
@@ -633,31 +633,69 @@ public abstract class ClassUtils {
public static Method getMethod(Class<?> clazz, String methodName, Class<?>... paramTypes) {
Assert.notNull(clazz, "Class must not be null");
Assert.notNull(methodName, "Method name must not be null");
try {
return clazz.getMethod(methodName, paramTypes);
if (paramTypes != null) {
try {
return clazz.getMethod(methodName, paramTypes);
}
catch (NoSuchMethodException ex) {
throw new IllegalStateException("Expected method not found: " + ex);
}
}
catch (NoSuchMethodException ex) {
throw new IllegalStateException("Expected method not found: " + ex);
else {
Set<Method> candidates = new HashSet<Method>(1);
Method[] methods = clazz.getMethods();
for (Method method : methods) {
if (methodName.equals(method.getName())) {
candidates.add(method);
}
}
if (candidates.size() == 1) {
return candidates.iterator().next();
}
else if (candidates.isEmpty()) {
throw new IllegalStateException("Expected method not found: " + clazz + "." + methodName);
}
else {
throw new IllegalStateException("No unique method found: " + clazz + "." + methodName);
}
}
}
/**
* Determine whether the given class has a method with the given signature,
* Determine whether the given class has a public method with the given signature,
* and return it if available (else return {@code null}).
* <p>In case of any signature specified, only returns the method if there is a
* unique candidate, i.e. a single public method with the specified name.
* <p>Essentially translates {@code NoSuchMethodException} to {@code null}.
* @param clazz the clazz to analyze
* @param clazz the clazz to analyze
* @param methodName the name of the method
* @param paramTypes the parameter types of the method
* (may be {@code null} to indicate any signature)
* @return the method, or {@code null} if not found
* @see Class#getMethod
*/
public static Method getMethodIfAvailable(Class<?> clazz, String methodName, Class<?>... paramTypes) {
Assert.notNull(clazz, "Class must not be null");
Assert.notNull(methodName, "Method name must not be null");
try {
return clazz.getMethod(methodName, paramTypes);
if (paramTypes != null) {
try {
return clazz.getMethod(methodName, paramTypes);
}
catch (NoSuchMethodException ex) {
return null;
}
}
catch (NoSuchMethodException ex) {
else {
Set<Method> candidates = new HashSet<Method>(1);
Method[] methods = clazz.getMethods();
for (Method method : methods) {
if (methodName.equals(method.getName())) {
candidates.add(method);
}
}
if (candidates.size() == 1) {
return candidates.iterator().next();
}
return null;
}
}
@@ -1025,7 +1063,7 @@ public abstract class ClassUtils {
* @param instance the instance to analyze for interfaces
* @return all interfaces that the given instance implements as array
*/
public static Class[] getAllInterfaces(Object instance) {
public static Class<?>[] getAllInterfaces(Object instance) {
Assert.notNull(instance, "Instance must not be null");
return getAllInterfacesForClass(instance.getClass());
}