1 package org.apache.commons.beanutils2;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import static java.beans.Introspector.getBeanInfo;
23
24 import java.beans.BeanInfo;
25 import java.beans.IndexedPropertyDescriptor;
26 import java.beans.IntrospectionException;
27 import java.beans.PropertyDescriptor;
28 import java.lang.reflect.Method;
29 import java.util.ArrayList;
30 import java.util.Arrays;
31 import java.util.Collection;
32 import java.util.HashMap;
33 import java.util.List;
34 import java.util.Map;
35 import java.util.WeakHashMap;
36 import java.util.concurrent.locks.Lock;
37 import java.util.concurrent.locks.ReentrantLock;
38
39
40
41
42 final class PropertyDescriptorsRegistry
43 {
44
45 private static final PropertyDescriptorsRegistry INSTANCE = new PropertyDescriptorsRegistry();
46
47 public static PropertyDescriptorsRegistry getInstance()
48 {
49 return INSTANCE;
50 }
51
52 private final AccessibleObjectsRegistry<Method> methodsRegistry = AccessibleObjectsRegistry.getMethodsRegistry();
53
54 private final Map<Class<?>, Map<String, PropertyDescriptor>> cache =
55 new WeakHashMap<Class<?>, Map<String, PropertyDescriptor>>();
56
57
58
59
60 private PropertyDescriptorsRegistry()
61 {
62
63 }
64
65 public Map<String, PropertyDescriptor> getPropertiesIndex( Class<?> beanType )
66 throws IntrospectionException
67 {
68 final Lock lock = new ReentrantLock();
69 lock.lock();
70 try
71 {
72 Map<String, PropertyDescriptor> propertiesIndex = cache.get( beanType );
73 if ( propertiesIndex != null )
74 {
75 return propertiesIndex;
76 }
77
78 propertiesIndex = new HashMap<String, PropertyDescriptor>();
79 BeanInfo beanInfo = getBeanInfo( beanType );
80
81 List<PropertyDescriptor> propertyDescriptors =
82 new ArrayList<PropertyDescriptor>( Arrays.asList( beanInfo.getPropertyDescriptors() ) );
83 propertyDescriptors.addAll( getMappedPropertyDescriptors( beanType ) );
84 for ( PropertyDescriptor propertyDescriptor : propertyDescriptors )
85 {
86 makeMethodsAccessible( beanType, propertyDescriptor );
87 propertiesIndex.put( propertyDescriptor.getName(), propertyDescriptor );
88 }
89
90 cache.put( beanType, propertiesIndex );
91
92 return propertiesIndex;
93 }
94 finally
95 {
96 lock.unlock();
97 }
98 }
99
100 private Collection<PropertyDescriptor> getMappedPropertyDescriptors( Class<?> beanType )
101 throws IntrospectionException
102 {
103 Map<String, PropertyDescriptor> mappedPropertyDescirptors = new HashMap<String, PropertyDescriptor>();
104 for ( Method method : beanType.getMethods() )
105 {
106 if ( MethodUtils.isMappedGetter( method ) || MethodUtils.isMappedSetter( method ) )
107 {
108 String propertyName = method.getName().substring( 3 );
109 propertyName = Character.toLowerCase( propertyName.charAt( 0 ) ) + propertyName.substring( 1 );
110 if ( !mappedPropertyDescirptors.containsKey( propertyName ) )
111 {
112 mappedPropertyDescirptors.put( propertyName, new MappedPropertyDescriptor( propertyName, beanType ) );
113 }
114 }
115 }
116 return mappedPropertyDescirptors.values();
117 }
118
119 private void makeMethodsAccessible( Class<?> beanType, PropertyDescriptor propertyDescriptor )
120 throws IntrospectionException
121 {
122
123
124 if ( propertyDescriptor.getReadMethod() != null )
125 {
126 Method readMethod = propertyDescriptor.getReadMethod();
127 readMethod = methodsRegistry.get( true, beanType, readMethod.getName() );
128 propertyDescriptor.setReadMethod( readMethod );
129 }
130 if ( propertyDescriptor.getWriteMethod() != null )
131 {
132 Method writeMethod = propertyDescriptor.getWriteMethod();
133 writeMethod = methodsRegistry.get( true, beanType, writeMethod.getName(), writeMethod.getParameterTypes() );
134 propertyDescriptor.setWriteMethod( writeMethod );
135 }
136
137
138
139 if ( propertyDescriptor instanceof IndexedPropertyDescriptor )
140 {
141 IndexedPropertyDescriptor indexedPropertyDescriptor = (IndexedPropertyDescriptor) propertyDescriptor;
142
143 if ( indexedPropertyDescriptor.getIndexedReadMethod() != null )
144 {
145 Method indexedReadMethod = indexedPropertyDescriptor.getIndexedReadMethod();
146 indexedReadMethod = methodsRegistry.get( true,
147 beanType,
148 indexedReadMethod.getName(),
149 indexedReadMethod.getParameterTypes() );
150 indexedPropertyDescriptor.setIndexedReadMethod( indexedReadMethod );
151 }
152 if ( indexedPropertyDescriptor.getIndexedWriteMethod() != null )
153 {
154 Method indexedWriteMethod = indexedPropertyDescriptor.getIndexedWriteMethod();
155 indexedWriteMethod = methodsRegistry.get( true,
156 beanType,
157 indexedWriteMethod.getName(),
158 indexedWriteMethod.getParameterTypes() );
159 indexedPropertyDescriptor.setIndexedWriteMethod( indexedWriteMethod );
160 }
161 }
162 }
163
164 public PropertyDescriptor getPropertyDescriptor( Class<?> beanType, String propertyName )
165 throws IntrospectionException
166 {
167 Map<String, PropertyDescriptor> propertiesIndex = getPropertiesIndex( beanType );
168 return propertiesIndex.get( propertyName );
169 }
170
171 }