IdToEntityConverter defensively handles access to getDeclaredMethods
Issue: SPR-11758
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2012 the original author or authors.
|
* Copyright 2002-2014 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -31,20 +31,23 @@ import org.springframework.util.ReflectionUtils;
|
|||||||
* Converts an entity identifier to a entity reference by calling a static finder method
|
* Converts an entity identifier to a entity reference by calling a static finder method
|
||||||
* on the target entity type.
|
* on the target entity type.
|
||||||
*
|
*
|
||||||
* <p>For this converter to match, the finder method must be public, static, have the signature
|
* <p>For this converter to match, the finder method must be static, have the signature
|
||||||
* {@code find[EntityName]([IdType])}, and return an instance of the desired entity type.
|
* {@code find[EntityName]([IdType])}, and return an instance of the desired entity type.
|
||||||
*
|
*
|
||||||
* @author Keith Donald
|
* @author Keith Donald
|
||||||
|
* @author Juergen Hoeller
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
final class IdToEntityConverter implements ConditionalGenericConverter {
|
final class IdToEntityConverter implements ConditionalGenericConverter {
|
||||||
|
|
||||||
private final ConversionService conversionService;
|
private final ConversionService conversionService;
|
||||||
|
|
||||||
|
|
||||||
public IdToEntityConverter(ConversionService conversionService) {
|
public IdToEntityConverter(ConversionService conversionService) {
|
||||||
this.conversionService = conversionService;
|
this.conversionService = conversionService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<ConvertiblePair> getConvertibleTypes() {
|
public Set<ConvertiblePair> getConvertibleTypes() {
|
||||||
return Collections.singleton(new ConvertiblePair(Object.class, Object.class));
|
return Collections.singleton(new ConvertiblePair(Object.class, Object.class));
|
||||||
@@ -53,7 +56,8 @@ final class IdToEntityConverter implements ConditionalGenericConverter {
|
|||||||
@Override
|
@Override
|
||||||
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||||
Method finder = getFinder(targetType.getType());
|
Method finder = getFinder(targetType.getType());
|
||||||
return finder != null && this.conversionService.canConvert(sourceType, TypeDescriptor.valueOf(finder.getParameterTypes()[0]));
|
return (finder != null &&
|
||||||
|
this.conversionService.canConvert(sourceType, TypeDescriptor.valueOf(finder.getParameterTypes()[0])));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -62,18 +66,31 @@ final class IdToEntityConverter implements ConditionalGenericConverter {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
Method finder = getFinder(targetType.getType());
|
Method finder = getFinder(targetType.getType());
|
||||||
Object id = this.conversionService.convert(source, sourceType, TypeDescriptor.valueOf(finder.getParameterTypes()[0]));
|
Object id = this.conversionService.convert(
|
||||||
|
source, sourceType, TypeDescriptor.valueOf(finder.getParameterTypes()[0]));
|
||||||
return ReflectionUtils.invokeMethod(finder, source, id);
|
return ReflectionUtils.invokeMethod(finder, source, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private Method getFinder(Class<?> entityClass) {
|
private Method getFinder(Class<?> entityClass) {
|
||||||
String finderMethod = "find" + getEntityName(entityClass);
|
String finderMethod = "find" + getEntityName(entityClass);
|
||||||
Method[] methods = entityClass.getDeclaredMethods();
|
Method[] methods;
|
||||||
|
boolean localOnlyFiltered;
|
||||||
|
try {
|
||||||
|
methods = entityClass.getDeclaredMethods();
|
||||||
|
localOnlyFiltered = true;
|
||||||
|
}
|
||||||
|
catch (SecurityException ex) {
|
||||||
|
// Not allowed to access non-public methods...
|
||||||
|
// Fallback: check locally declared public methods only.
|
||||||
|
methods = entityClass.getMethods();
|
||||||
|
localOnlyFiltered = false;
|
||||||
|
}
|
||||||
for (Method method : methods) {
|
for (Method method : methods) {
|
||||||
if (Modifier.isStatic(method.getModifiers()) && method.getParameterTypes().length == 1 && method.getReturnType().equals(entityClass)) {
|
if (Modifier.isStatic(method.getModifiers()) && method.getName().equals(finderMethod) &&
|
||||||
if (method.getName().equals(finderMethod)) {
|
method.getParameterTypes().length == 1 && method.getReturnType().equals(entityClass) &&
|
||||||
return method;
|
(localOnlyFiltered || method.getDeclaringClass().equals(entityClass))) {
|
||||||
}
|
return method;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
Reference in New Issue
Block a user