1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.krad.uif.util;
17
18 import java.beans.BeanInfo;
19 import java.beans.IntrospectionException;
20 import java.beans.Introspector;
21 import java.beans.PropertyDescriptor;
22 import java.beans.PropertyEditorManager;
23 import java.lang.reflect.Method;
24 import java.util.Collections;
25 import java.util.Map;
26 import java.util.WeakHashMap;
27
28 import org.apache.log4j.Logger;
29
30
31
32
33
34
35 public class ObjectPropertyUtils {
36
37 private static final Logger LOG = Logger.getLogger(ObjectPropertyUtils.class);
38
39
40
41
42
43
44
45
46
47
48
49
50 private static Map<Class<?>, Map<String, PropertyDescriptor>> PROPERTY_DESCRIPTOR_CACHE = Collections
51 .synchronizedMap(new WeakHashMap<Class<?>, Map<String, PropertyDescriptor>>(2048));
52
53
54
55
56
57
58
59 public static Map<String, PropertyDescriptor> getPropertyDescriptors(Class<?> beanClass) {
60 Map<String, PropertyDescriptor> propertyDescriptors = PROPERTY_DESCRIPTOR_CACHE.get(beanClass);
61
62 if (propertyDescriptors == null) {
63 BeanInfo beanInfo;
64 try {
65 beanInfo = Introspector.getBeanInfo(beanClass);
66 } catch (IntrospectionException e) {
67 LOG.warn(
68 "Bean Info not found for bean " + beanClass, e);
69 beanInfo = null;
70 }
71
72 Map<String, PropertyDescriptor> unsynchronizedPropertyDescriptorMap = new java.util.LinkedHashMap<String, PropertyDescriptor>();
73
74 if (beanInfo != null) {
75 for (PropertyDescriptor propertyDescriptor : beanInfo
76 .getPropertyDescriptors()) {
77 unsynchronizedPropertyDescriptorMap.put(propertyDescriptor.getName(), propertyDescriptor);
78 }
79 }
80
81 PROPERTY_DESCRIPTOR_CACHE.put(beanClass, propertyDescriptors = Collections.unmodifiableMap(Collections
82 .synchronizedMap(unsynchronizedPropertyDescriptorMap)));
83 }
84
85 return propertyDescriptors;
86 }
87
88
89
90
91
92
93
94
95 public static PropertyDescriptor getPropertyDescriptor(Class<?> beanClass, String propertyName) {
96 if (propertyName == null) {
97 throw new IllegalArgumentException("Null property name");
98 }
99
100 PropertyDescriptor propertyDescriptor = getPropertyDescriptors(beanClass).get(propertyName);
101 if (propertyDescriptor != null) {
102 return propertyDescriptor;
103 } else {
104 throw new IllegalArgumentException("Property " + propertyName
105 + " not found for bean " + beanClass);
106 }
107 }
108
109
110
111
112
113
114
115
116 public static Method getReadMethod(Class<?> beanClass, String propertyName) {
117 if (propertyName == null || propertyName.length() == 0) {
118 return null;
119 }
120
121 Method readMethod = null;
122
123 PropertyDescriptor propertyDescriptor = ObjectPropertyUtils.getPropertyDescriptors(beanClass).get(propertyName);
124 if (propertyDescriptor != null) {
125 readMethod = propertyDescriptor.getReadMethod();
126 }
127
128 if (readMethod == null) {
129 try {
130 readMethod = beanClass.getMethod("get" + Character.toUpperCase(propertyName.charAt(0))
131 + propertyName.substring(1));
132 } catch (SecurityException e) {
133
134 } catch (NoSuchMethodException e) {
135
136 }
137 }
138
139 if (readMethod == null) {
140 try {
141 Method trm = beanClass.getMethod("is"
142 + Character.toUpperCase(propertyName.charAt(0))
143 + propertyName.substring(1));
144 if (trm.getReturnType() == Boolean.class
145 || trm.getReturnType() == Boolean.TYPE)
146 readMethod = trm;
147 } catch (SecurityException e) {
148
149 } catch (NoSuchMethodException e) {
150
151 }
152 }
153
154 return readMethod;
155 }
156
157
158
159
160
161
162
163
164 public static Method getWriteMethod(Class<?> beanClass, String propertyName) {
165 PropertyDescriptor propertyDescriptor = ObjectPropertyUtils.getPropertyDescriptors(beanClass).get(propertyName);
166
167 if (propertyDescriptor != null) {
168 Method writeMethod = propertyDescriptor.getWriteMethod();
169 assert writeMethod == null
170 || (writeMethod.getParameterTypes().length == 1 && writeMethod.getParameterTypes()[0] != null) : writeMethod;
171 return writeMethod;
172 } else {
173 return null;
174 }
175 }
176
177
178
179
180
181
182
183
184
185
186 public static void copyPropertiesToObject(Map<String, String> properties, Object object) {
187 for (Map.Entry<String, String> property : properties.entrySet()) {
188 setPropertyValue(object, property.getKey(), property.getValue());
189 }
190 }
191
192
193
194
195
196
197
198
199
200 public static Class<?> getPropertyType(Class<?> beanClass, String propertyPath) {
201 return ObjectPropertyReference.resolvePath(null, beanClass, propertyPath, false).getPropertyType();
202 }
203
204
205
206
207
208
209
210
211
212
213 public static Class<?> getPropertyType(Object object, String propertyPath) {
214 return ObjectPropertyReference.resolvePath(object, object.getClass(), propertyPath, false).getPropertyType();
215 }
216
217
218
219
220
221
222
223
224
225 @SuppressWarnings("unchecked")
226 public static <T extends Object> T getPropertyValue(Object object, String propertyPath) {
227 if (ProcessLogger.isTraceActive() && object != null) {
228
229
230 ProcessLogger.countBegin("bean-property-read");
231 }
232
233 try {
234
235 return (T) ObjectPropertyReference.resolvePath(object, object.getClass(), propertyPath, false).get();
236
237 } catch (RuntimeException e) {
238 throw new RuntimeException("Error getting property '" + propertyPath + "' from " + object, e);
239 } finally {
240 if (ProcessLogger.isTraceActive() && object != null) {
241 ProcessLogger.countEnd("bean-property-read", object.getClass().getSimpleName() + ":" + propertyPath);
242 }
243 }
244
245 }
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261 public static void initializeProperty(Object object, String propertyPath) {
262 Class<?> propertyType = getPropertyType(object, propertyPath);
263 try {
264 setPropertyValue(object, propertyPath, propertyType.newInstance());
265 } catch (InstantiationException e) {
266
267 setPropertyValue(object, propertyPath, null);
268 } catch (IllegalAccessException e) {
269 throw new RuntimeException("Unable to set new instance for property: " + propertyPath, e);
270 }
271 }
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291 public static void setPropertyValue(Object object, String propertyPath, Object propertyValue) {
292 if (ProcessLogger.isTraceActive() && object != null) {
293
294
295 ProcessLogger.countBegin("bean-property-write");
296 }
297
298 try {
299
300 ObjectPropertyReference.resolvePath(object, object.getClass(), propertyPath, true).set(propertyValue);
301
302 } catch (RuntimeException e) {
303 throw new RuntimeException("Error setting property '" + propertyPath + "' on " + object + " with "
304 + propertyValue, e);
305 } finally {
306 if (ProcessLogger.isTraceActive() && object != null) {
307 ProcessLogger.countEnd("bean-property-write", object.getClass().getSimpleName() + ":" + propertyPath);
308 }
309 }
310
311 }
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331 public static void setPropertyValue(Object object, String propertyPath, Object propertyValue, boolean ignoreUnknown) {
332 try {
333 setPropertyValue(object, propertyPath, propertyValue);
334 } catch (RuntimeException e) {
335
336 if (!ignoreUnknown) {
337 throw e;
338 }
339 if (LOG.isTraceEnabled()) {
340 LOG.trace("Ignoring exception thrown during setting of property '" + propertyPath + "': "
341 + e.getLocalizedMessage());
342 }
343 }
344 }
345
346
347
348
349
350
351
352
353
354 public static boolean isReadableProperty(Object object, String propertyPath) {
355 return ObjectPropertyReference.resolvePath(object, object.getClass(), propertyPath, false).canRead();
356 }
357
358
359
360
361
362
363
364
365
366 public static boolean isWritableProperty(Object object, String propertyPath) {
367 return ObjectPropertyReference.resolvePath(object, object.getClass(), propertyPath, false).canWrite();
368 }
369
370
371
372
373 private ObjectPropertyUtils() {}
374
375 }