Skip to content

Commit ae45794

Browse files
committed
IdToEntityConverter defensively handles access to getDeclaredMethods
Issue: SPR-11758 (cherry picked from commit 381ccde)
1 parent fccec21 commit ae45794

File tree

1 file changed

+26
-9
lines changed

1 file changed

+26
-9
lines changed

spring-core/src/main/java/org/springframework/core/convert/support/IdToEntityConverter.java

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2012 the original author or authors.
2+
* Copyright 2002-2014 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -31,20 +31,23 @@
3131
* Converts an entity identifier to a entity reference by calling a static finder method
3232
* on the target entity type.
3333
*
34-
* <p>For this converter to match, the finder method must be public, static, have the signature
34+
* <p>For this converter to match, the finder method must be static, have the signature
3535
* {@code find[EntityName]([IdType])}, and return an instance of the desired entity type.
3636
*
3737
* @author Keith Donald
38+
* @author Juergen Hoeller
3839
* @since 3.0
3940
*/
4041
final class IdToEntityConverter implements ConditionalGenericConverter {
4142

4243
private final ConversionService conversionService;
4344

45+
4446
public IdToEntityConverter(ConversionService conversionService) {
4547
this.conversionService = conversionService;
4648
}
4749

50+
4851
@Override
4952
public Set<ConvertiblePair> getConvertibleTypes() {
5053
return Collections.singleton(new ConvertiblePair(Object.class, Object.class));
@@ -53,7 +56,8 @@ public Set<ConvertiblePair> getConvertibleTypes() {
5356
@Override
5457
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
5558
Method finder = getFinder(targetType.getType());
56-
return finder != null && this.conversionService.canConvert(sourceType, TypeDescriptor.valueOf(finder.getParameterTypes()[0]));
59+
return (finder != null &&
60+
this.conversionService.canConvert(sourceType, TypeDescriptor.valueOf(finder.getParameterTypes()[0])));
5761
}
5862

5963
@Override
@@ -62,18 +66,31 @@ public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor t
6266
return null;
6367
}
6468
Method finder = getFinder(targetType.getType());
65-
Object id = this.conversionService.convert(source, sourceType, TypeDescriptor.valueOf(finder.getParameterTypes()[0]));
69+
Object id = this.conversionService.convert(
70+
source, sourceType, TypeDescriptor.valueOf(finder.getParameterTypes()[0]));
6671
return ReflectionUtils.invokeMethod(finder, source, id);
6772
}
6873

74+
6975
private Method getFinder(Class<?> entityClass) {
7076
String finderMethod = "find" + getEntityName(entityClass);
71-
Method[] methods = entityClass.getDeclaredMethods();
77+
Method[] methods;
78+
boolean localOnlyFiltered;
79+
try {
80+
methods = entityClass.getDeclaredMethods();
81+
localOnlyFiltered = true;
82+
}
83+
catch (SecurityException ex) {
84+
// Not allowed to access non-public methods...
85+
// Fallback: check locally declared public methods only.
86+
methods = entityClass.getMethods();
87+
localOnlyFiltered = false;
88+
}
7289
for (Method method : methods) {
73-
if (Modifier.isStatic(method.getModifiers()) && method.getParameterTypes().length == 1 && method.getReturnType().equals(entityClass)) {
74-
if (method.getName().equals(finderMethod)) {
75-
return method;
76-
}
90+
if (Modifier.isStatic(method.getModifiers()) && method.getName().equals(finderMethod) &&
91+
method.getParameterTypes().length == 1 && method.getReturnType().equals(entityClass) &&
92+
(localOnlyFiltered || method.getDeclaringClass().equals(entityClass))) {
93+
return method;
7794
}
7895
}
7996
return null;

0 commit comments

Comments
 (0)