Skip to content

Commit

Permalink
IdToEntityConverter defensively handles access to getDeclaredMethods
Browse files Browse the repository at this point in the history
Issue: SPR-11758
  • Loading branch information
jhoeller committed May 6, 2014
1 parent bea34ea commit 381ccde
Showing 1 changed file with 26 additions and 9 deletions.
Original file line number Diff line number Diff line change
@@ -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");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -31,20 +31,23 @@
* Converts an entity identifier to a entity reference by calling a static finder method
* 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.
*
* @author Keith Donald
* @author Juergen Hoeller
* @since 3.0
*/
final class IdToEntityConverter implements ConditionalGenericConverter {

private final ConversionService conversionService;


public IdToEntityConverter(ConversionService conversionService) {
this.conversionService = conversionService;
}


@Override
public Set<ConvertiblePair> getConvertibleTypes() {
return Collections.singleton(new ConvertiblePair(Object.class, Object.class));
Expand All @@ -53,7 +56,8 @@ public Set<ConvertiblePair> getConvertibleTypes() {
@Override
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
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
Expand All @@ -62,18 +66,31 @@ public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor t
return null;
}
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);
}


private Method getFinder(Class<?> 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) {
if (Modifier.isStatic(method.getModifiers()) && method.getParameterTypes().length == 1 && method.getReturnType().equals(entityClass)) {
if (method.getName().equals(finderMethod)) {
return method;
}
if (Modifier.isStatic(method.getModifiers()) && method.getName().equals(finderMethod) &&
method.getParameterTypes().length == 1 && method.getReturnType().equals(entityClass) &&
(localOnlyFiltered || method.getDeclaringClass().equals(entityClass))) {
return method;
}
}
return null;
Expand Down

0 comments on commit 381ccde

Please sign in to comment.