Prevented potential infinite recursion in hashCode/equals
Issue: SPR-11219
This commit is contained in:
parent
6183683041
commit
994efe45fd
|
@ -73,11 +73,9 @@ import org.springframework.util.StringUtils;
|
|||
* @see #forClass(Class)
|
||||
* @see #forType(Type)
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public final class ResolvableType implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
private static ConcurrentReferenceHashMap<ResolvableType, ResolvableType> cache =
|
||||
new ConcurrentReferenceHashMap<ResolvableType, ResolvableType>();
|
||||
|
||||
|
@ -93,14 +91,14 @@ public final class ResolvableType implements Serializable {
|
|||
|
||||
|
||||
/**
|
||||
* The underlying java type being managed (only ever {@code null} for {@link #NONE}).
|
||||
* The underlying Java type being managed (only ever {@code null} for {@link #NONE}).
|
||||
*/
|
||||
private final Type type;
|
||||
|
||||
/**
|
||||
* Optional provider for the type.
|
||||
*/
|
||||
private TypeProvider typeProvider;
|
||||
private final TypeProvider typeProvider;
|
||||
|
||||
/**
|
||||
* The {@code VariableResolver} to use or {@code null} if no resolver is available.
|
||||
|
@ -125,12 +123,13 @@ public final class ResolvableType implements Serializable {
|
|||
|
||||
/**
|
||||
* Private constructor used to create a new {@link ResolvableType}.
|
||||
* @param type the underlying java type (may only be {@code null} for {@link #NONE})
|
||||
* @param type the underlying Java type (may only be {@code null} for {@link #NONE})
|
||||
* @param variableResolver the resolver used for {@link TypeVariable}s (may be {@code null})
|
||||
* @param componentType an option declared component type for arrays (may be {@code null})
|
||||
*/
|
||||
private ResolvableType(Type type, TypeProvider typeProvider,
|
||||
VariableResolver variableResolver, ResolvableType componentType) {
|
||||
private ResolvableType(
|
||||
Type type, TypeProvider typeProvider, VariableResolver variableResolver, ResolvableType componentType) {
|
||||
|
||||
this.type = type;
|
||||
this.typeProvider = typeProvider;
|
||||
this.variableResolver = variableResolver;
|
||||
|
@ -590,7 +589,6 @@ public final class ResolvableType implements Serializable {
|
|||
if (this.type instanceof ParameterizedType) {
|
||||
return forType(((ParameterizedType) this.type).getRawType(), this.variableResolver);
|
||||
}
|
||||
|
||||
if (this.type instanceof WildcardType) {
|
||||
Type resolved = resolveBounds(((WildcardType) this.type).getUpperBounds());
|
||||
if (resolved == null) {
|
||||
|
@ -598,10 +596,8 @@ public final class ResolvableType implements Serializable {
|
|||
}
|
||||
return forType(resolved, this.variableResolver);
|
||||
}
|
||||
|
||||
if (this.type instanceof TypeVariable) {
|
||||
TypeVariable<?> variable = (TypeVariable<?>) this.type;
|
||||
|
||||
// Try default variable resolution
|
||||
if (this.variableResolver != null) {
|
||||
ResolvableType resolved = this.variableResolver.resolveVariable(variable);
|
||||
|
@ -609,11 +605,9 @@ public final class ResolvableType implements Serializable {
|
|||
return resolved;
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback to bounds
|
||||
return forType(resolveBounds(variable.getBounds()), this.variableResolver);
|
||||
}
|
||||
|
||||
return NONE;
|
||||
}
|
||||
|
||||
|
@ -628,7 +622,6 @@ public final class ResolvableType implements Serializable {
|
|||
if (this.type instanceof TypeVariable) {
|
||||
return resolveType().resolveVariable(variable);
|
||||
}
|
||||
|
||||
if (this.type instanceof ParameterizedType) {
|
||||
ParameterizedType parameterizedType = (ParameterizedType) this.type;
|
||||
TypeVariable<?>[] variables = resolve().getTypeParameters();
|
||||
|
@ -638,16 +631,13 @@ public final class ResolvableType implements Serializable {
|
|||
return forType(actualType, this.variableResolver);
|
||||
}
|
||||
}
|
||||
|
||||
if (parameterizedType.getOwnerType() != null) {
|
||||
return forType(parameterizedType.getOwnerType(), this.variableResolver).resolveVariable(variable);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.variableResolver != null) {
|
||||
return this.variableResolver.resolveVariable(variable);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -673,27 +663,22 @@ public final class ResolvableType implements Serializable {
|
|||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj instanceof ResolvableType) {
|
||||
ResolvableType other = (ResolvableType) obj;
|
||||
boolean equals = ObjectUtils.nullSafeEquals(this.type, other.type);
|
||||
equals &= ObjectUtils.nullSafeEquals(getSource(), other.getSource());
|
||||
equals &= variableResolverSourceEquals(this.variableResolver, other.variableResolver);
|
||||
equals &= ObjectUtils.nullSafeEquals(this.componentType, other.componentType);
|
||||
return equals;
|
||||
if (!(obj instanceof ResolvableType)) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
ResolvableType other = (ResolvableType) obj;
|
||||
return (ObjectUtils.nullSafeEquals(this.type, other.type) &&
|
||||
ObjectUtils.nullSafeEquals(getSource(), other.getSource()) &&
|
||||
variableResolverSourceEquals(other.variableResolver) &&
|
||||
ObjectUtils.nullSafeEquals(this.componentType, other.componentType));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hashCode = ObjectUtils.nullSafeHashCode(this.type);
|
||||
hashCode = hashCode * 31 + ObjectUtils.nullSafeHashCode(
|
||||
this.variableResolver == null ? null : this.variableResolver.getSource());
|
||||
hashCode = hashCode * 31 + ObjectUtils.nullSafeHashCode(this.componentType);
|
||||
return hashCode;
|
||||
return ObjectUtils.nullSafeHashCode(this.type);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -713,10 +698,15 @@ public final class ResolvableType implements Serializable {
|
|||
return new DefaultVariableResolver();
|
||||
}
|
||||
|
||||
private static boolean variableResolverSourceEquals(VariableResolver o1, VariableResolver o2) {
|
||||
Object s1 = (o1 == null ? null : o1.getSource());
|
||||
Object s2 = (o2 == null ? null : o2.getSource());
|
||||
return ObjectUtils.nullSafeEquals(s1,s2);
|
||||
private boolean variableResolverSourceEquals(VariableResolver other) {
|
||||
if (this.variableResolver == null) {
|
||||
return (other == null);
|
||||
}
|
||||
if (other == null) {
|
||||
return false;
|
||||
}
|
||||
Object src = this.variableResolver.getSource();
|
||||
return (src == this ? src == other.getSource() : ObjectUtils.nullSafeEquals(src, other.getSource()));
|
||||
}
|
||||
|
||||
private static ResolvableType[] forTypes(Type[] types, VariableResolver owner) {
|
||||
|
@ -840,6 +830,7 @@ public final class ResolvableType implements Serializable {
|
|||
*/
|
||||
public static ResolvableType forConstructorParameter(Constructor<?> constructor, int parameterIndex,
|
||||
Class<?> implementationClass) {
|
||||
|
||||
Assert.notNull(constructor, "Constructor must not be null");
|
||||
MethodParameter methodParameter = new MethodParameter(constructor, parameterIndex);
|
||||
methodParameter.setContainingClass(implementationClass);
|
||||
|
@ -923,7 +914,7 @@ public final class ResolvableType implements Serializable {
|
|||
* @param componentType the component type
|
||||
* @return a {@link ResolvableType} as an array of the specified component type
|
||||
*/
|
||||
public static ResolvableType forArrayComponent(final ResolvableType componentType) {
|
||||
public static ResolvableType forArrayComponent(ResolvableType componentType) {
|
||||
Assert.notNull(componentType, "ComponentType must not be null");
|
||||
Class<?> arrayClass = Array.newInstance(componentType.resolve(), 0).getClass();
|
||||
return new ResolvableType(arrayClass, null, null, componentType);
|
||||
|
@ -1035,7 +1026,7 @@ public final class ResolvableType implements Serializable {
|
|||
Object getSource();
|
||||
|
||||
/**
|
||||
* Resolve the specified varaible.
|
||||
* Resolve the specified variable.
|
||||
* @param variable the variable to resolve
|
||||
* @return the resolved variable or {@code null}
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue