From 381ccde48d11ef82c371789898e563233141b7ee Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Tue, 6 May 2014 18:49:16 +0200 Subject: [PATCH] IdToEntityConverter defensively handles access to getDeclaredMethods Issue: SPR-11758 --- .../convert/support/IdToEntityConverter.java | 35 ++++++++++++++----- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/spring-core/src/main/java/org/springframework/core/convert/support/IdToEntityConverter.java b/spring-core/src/main/java/org/springframework/core/convert/support/IdToEntityConverter.java index e80bd599cd..35f1d22350 100644 --- a/spring-core/src/main/java/org/springframework/core/convert/support/IdToEntityConverter.java +++ b/spring-core/src/main/java/org/springframework/core/convert/support/IdToEntityConverter.java @@ -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. @@ -31,20 +31,23 @@ import org.springframework.util.ReflectionUtils; * Converts an entity identifier to a entity reference by calling a static finder method * on the target entity type. * - *

For this converter to match, the finder method must be public, static, have the signature + *

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 getConvertibleTypes() { return Collections.singleton(new ConvertiblePair(Object.class, Object.class)); @@ -53,7 +56,8 @@ final class IdToEntityConverter implements ConditionalGenericConverter { @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 @@ -62,18 +66,31 @@ final class IdToEntityConverter implements ConditionalGenericConverter { 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;