|
1 | 1 | /*
|
2 |
| - * Copyright 2002-2012 the original author or authors. |
| 2 | + * Copyright 2002-2014 the original author or authors. |
3 | 3 | *
|
4 | 4 | * Licensed under the Apache License, Version 2.0 (the "License");
|
5 | 5 | * you may not use this file except in compliance with the License.
|
|
31 | 31 | * Converts an entity identifier to a entity reference by calling a static finder method
|
32 | 32 | * on the target entity type.
|
33 | 33 | *
|
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 |
35 | 35 | * {@code find[EntityName]([IdType])}, and return an instance of the desired entity type.
|
36 | 36 | *
|
37 | 37 | * @author Keith Donald
|
| 38 | + * @author Juergen Hoeller |
38 | 39 | * @since 3.0
|
39 | 40 | */
|
40 | 41 | final class IdToEntityConverter implements ConditionalGenericConverter {
|
41 | 42 |
|
42 | 43 | private final ConversionService conversionService;
|
43 | 44 |
|
| 45 | + |
44 | 46 | public IdToEntityConverter(ConversionService conversionService) {
|
45 | 47 | this.conversionService = conversionService;
|
46 | 48 | }
|
47 | 49 |
|
| 50 | + |
48 | 51 | public Set<ConvertiblePair> getConvertibleTypes() {
|
49 | 52 | return Collections.singleton(new ConvertiblePair(Object.class, Object.class));
|
50 | 53 | }
|
51 | 54 |
|
52 | 55 | public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
53 | 56 | Method finder = getFinder(targetType.getType());
|
54 |
| - return finder != null && this.conversionService.canConvert(sourceType, TypeDescriptor.valueOf(finder.getParameterTypes()[0])); |
| 57 | + return (finder != null && |
| 58 | + this.conversionService.canConvert(sourceType, TypeDescriptor.valueOf(finder.getParameterTypes()[0]))); |
55 | 59 | }
|
56 | 60 |
|
57 | 61 | public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
58 | 62 | if (source == null) {
|
59 | 63 | return null;
|
60 | 64 | }
|
61 | 65 | Method finder = getFinder(targetType.getType());
|
62 |
| - Object id = this.conversionService.convert(source, sourceType, TypeDescriptor.valueOf(finder.getParameterTypes()[0])); |
| 66 | + Object id = this.conversionService.convert( |
| 67 | + source, sourceType, TypeDescriptor.valueOf(finder.getParameterTypes()[0])); |
63 | 68 | return ReflectionUtils.invokeMethod(finder, source, id);
|
64 | 69 | }
|
65 | 70 |
|
| 71 | + |
66 | 72 | private Method getFinder(Class<?> entityClass) {
|
67 | 73 | String finderMethod = "find" + getEntityName(entityClass);
|
68 |
| - Method[] methods = entityClass.getDeclaredMethods(); |
| 74 | + Method[] methods; |
| 75 | + boolean localOnlyFiltered; |
| 76 | + try { |
| 77 | + methods = entityClass.getDeclaredMethods(); |
| 78 | + localOnlyFiltered = true; |
| 79 | + } |
| 80 | + catch (SecurityException ex) { |
| 81 | + // Not allowed to access non-public methods... |
| 82 | + // Fallback: check locally declared public methods only. |
| 83 | + methods = entityClass.getMethods(); |
| 84 | + localOnlyFiltered = false; |
| 85 | + } |
69 | 86 | for (Method method : methods) {
|
70 |
| - if (Modifier.isStatic(method.getModifiers()) && method.getParameterTypes().length == 1 && method.getReturnType().equals(entityClass)) { |
71 |
| - if (method.getName().equals(finderMethod)) { |
72 |
| - return method; |
73 |
| - } |
| 87 | + if (Modifier.isStatic(method.getModifiers()) && method.getName().equals(finderMethod) && |
| 88 | + method.getParameterTypes().length == 1 && method.getReturnType().equals(entityClass) && |
| 89 | + (localOnlyFiltered || method.getDeclaringClass().equals(entityClass))) { |
| 90 | + return method; |
74 | 91 | }
|
75 | 92 | }
|
76 | 93 | return null;
|
|
0 commit comments