1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.el;
20
21 import org.apache.commons.beanutils.MethodUtils;
22 import org.apache.commons.logging.Log;
23 import org.apache.commons.logging.LogFactory;
24
25 import javax.faces.el.EvaluationException;
26 import javax.faces.el.PropertyNotFoundException;
27 import javax.faces.el.PropertyResolver;
28 import javax.faces.el.ReferenceSyntaxException;
29 import java.beans.BeanInfo;
30 import java.beans.IntrospectionException;
31 import java.beans.Introspector;
32 import java.beans.PropertyDescriptor;
33 import java.lang.reflect.Array;
34 import java.lang.reflect.Method;
35 import java.util.List;
36 import java.util.Map;
37
38
39
40
41
42
43
44 public class PropertyResolverImpl extends PropertyResolver
45 {
46 private static final Log log =
47 LogFactory.getLog(PropertyResolverImpl.class);
48
49
50
51 private static final Object[] NO_ARGS = {};
52
53
54
55 public Object getValue(Object base, Object property)
56 throws EvaluationException, PropertyNotFoundException
57 {
58 try
59 {
60 if(base == null)
61 {
62 if(log.isDebugEnabled())
63 log.debug("property : "+property +" could not be retrieved as base was null.");
64
65 return null;
66 }
67
68
69
70 if (property == null ||
71 (property instanceof String && ((String)property).length() == 0 &&
72 !(base instanceof Map)))
73 {
74 if(log.isDebugEnabled())
75 log.debug("property for base with class: "+ base.getClass().getName() +" could not be retrieved as property was null.");
76
77 return null;
78 }
79 if (base instanceof Map)
80 {
81 return ((Map) base).get(property);
82 }
83
84
85 return getProperty(base, property.toString());
86 }
87 catch (PropertyNotFoundException e) {
88
89 if(log.isDebugEnabled())
90 log.debug("Exception while retrieving property; base with class : "+base.getClass().getName()+", property : "+property,e);
91
92 throw e;
93 }
94 catch (RuntimeException e)
95 {
96 if(log.isDebugEnabled())
97 log.debug("Exception while retrieving property; base : "+base.getClass().getName()+", property : "+property,e);
98
99 throw new EvaluationException("Exception getting value of property " + property
100 + " of base of type : "
101 + base.getClass().getName(), e);
102 }
103 }
104
105 public Object getValue(Object base, int index)
106 throws EvaluationException, PropertyNotFoundException
107 {
108 try
109 {
110 if (base == null)
111 {
112 if(log.isDebugEnabled())
113 log.debug("index : "+index+" not retrievable cause base is null.");
114 return null;
115 }
116
117 try
118 {
119 if (base.getClass().isArray())
120 {
121 return Array.get(base, index);
122 }
123 if (base instanceof List)
124 {
125 return ((List) base).get(index);
126 }
127 }
128 catch (IndexOutOfBoundsException e)
129 {
130 if(log.isDebugEnabled())
131 log.debug("IndexOutOfBoundException while getting property; base with class: "+base.getClass().getName()+", index : "+index,e);
132
133
134 return null;
135 }
136
137 throw new ReferenceSyntaxException("Must be array or List. Bean with class: "
138 + base.getClass().getName() + ", index " + index);
139 }
140 catch (RuntimeException e)
141 {
142 if(log.isDebugEnabled())
143 log.debug("Exception while getting property; base with class: "+base.getClass().getName()+", index : "+index,e);
144
145 throw new EvaluationException("Exception getting value for index " + index
146 + " of bean "
147 + base != null ? base.getClass().getName() : "NULL", e);
148 }
149 }
150
151 public void setValue(Object base, Object property, Object newValue)
152 throws EvaluationException, PropertyNotFoundException
153 {
154 try
155 {
156 if (base == null)
157 {
158 throw new PropertyNotFoundException(
159 "Null bean, property: " + property);
160 }
161 if (property == null ||
162 property instanceof String && ((String)property).length() == 0)
163 {
164 throw new PropertyNotFoundException("Bean with class : "
165 + base.getClass().getName()
166 + ", null or empty property name");
167 }
168
169 if (base instanceof Map)
170 {
171 ((Map) base).put(property, newValue);
172
173 return;
174 }
175
176
177 setProperty(base, property.toString(), newValue);
178 }
179 catch (PropertyNotFoundException e) {
180 if(log.isDebugEnabled())
181 log.debug("Exception while setting property; base with class : "+base.getClass().getName()+", property : "+property,e);
182 throw e;
183 }
184 catch (RuntimeException e)
185 {
186 if(log.isDebugEnabled())
187 log.debug("Exception while setting property; base : "+base.getClass().getName()+", property : "+property,e);
188
189 throw new EvaluationException("Exception setting property " + property
190 + " of base with class "
191 + base.getClass().getName(), e);
192 }
193 }
194
195 public void setValue(Object base, int index, Object newValue)
196 throws EvaluationException, PropertyNotFoundException
197 {
198 try
199 {
200 if (base == null)
201 {
202 throw new PropertyNotFoundException(
203 "Null bean, index: " + index);
204 }
205
206 try
207 {
208 if (base.getClass().isArray())
209 {
210 Array.set(base, index, newValue);
211
212 return;
213 }
214 if (base instanceof List)
215 {
216
217
218
219 ((List) base).set(index, newValue);
220
221 return;
222 }
223 }
224 catch (IndexOutOfBoundsException e)
225 {
226 throw new PropertyNotFoundException("Base with class : "
227 + base.getClass().getName() + ", index " + index, e);
228 }
229
230 throw new EvaluationException(
231 "Bean must be array or List. Base with class: "
232 + base.getClass().getName() + ", index " + index);
233 }
234 catch (PropertyNotFoundException e) {
235 throw e;
236 }
237 catch (RuntimeException e)
238 {
239 throw new EvaluationException("Exception setting value of index " + index + " of bean "
240 + base.getClass().getName(), e);
241 }
242 }
243
244 public boolean isReadOnly(Object base, Object property)
245 {
246 try
247 {
248 if (base == null || property == null ||
249 property instanceof String && ((String)property).length() == 0)
250 {
251
252 return false;
253 }
254
255
256 if (base instanceof Map)
257 {
258 return false;
259 }
260
261
262 PropertyDescriptor propertyDescriptor =
263 getPropertyDescriptor(base, property.toString());
264
265 return propertyDescriptor.getWriteMethod() == null;
266 }
267 catch (Exception e)
268 {
269
270 return false;
271 }
272 }
273
274 public boolean isReadOnly(Object base, int index)
275 {
276 try
277 {
278
279 if (base == null)
280 {
281
282 return false;
283 }
284 if (base instanceof List || base.getClass().isArray())
285 {
286
287 return false;
288 }
289
290
291 return false;
292 }
293 catch (Exception e)
294 {
295
296 return false;
297 }
298 }
299
300 public Class getType(Object base, Object property)
301 {
302 try
303 {
304 if (base == null)
305 {
306 throw new PropertyNotFoundException("Base bean is null.");
307 }
308 else if (property == null)
309 {
310 throw new PropertyNotFoundException("Property name is null.");
311 }
312 else if (property instanceof String && ((String)property).length() == 0)
313 {
314 throw new PropertyNotFoundException("Property name is an empty String.");
315 }
316
317 if (base instanceof Map)
318 {
319 Object value = ((Map) base).get(property);
320
321
322 return (value == null) ? Object.class : value.getClass();
323 }
324
325
326 PropertyDescriptor propertyDescriptor =
327 getPropertyDescriptor(base, property.toString());
328
329 return propertyDescriptor.getPropertyType();
330 }
331 catch (PropertyNotFoundException e) {
332 throw e;
333 }
334 catch (Exception e)
335 {
336 return null;
337 }
338 }
339
340 public Class getType(Object base, int index)
341 {
342 if (base == null)
343 {
344 throw new PropertyNotFoundException("Bean is null");
345 }
346
347 try
348 {
349 if (base.getClass().isArray())
350 {
351 if (base instanceof Object[] && ((Object[])base)[index] != null) {
352 Object[] array = (Object[]) base;
353 return array[index].getClass();
354 } else {
355 return base.getClass().getComponentType();
356 }
357 }
358
359 if (base instanceof List)
360 {
361
362
363
364 Object value = ((List) base).get(index);
365
366
367 return (value != null) ? value.getClass() : Object.class;
368 }
369
370
371 return null;
372 }
373 catch (IndexOutOfBoundsException e) {
374 throw new PropertyNotFoundException("Bean: "
375 + base.getClass().getName() + ", index " + index, e);
376 }
377 catch (Exception e)
378 {
379 throw new EvaluationException("Exception getting type of index " + index + " of bean with class : "
380 + base.getClass().getName(), e);
381 }
382 }
383
384
385
386
387 public static void setProperty(Object base, String name, Object newValue)
388 {
389 PropertyDescriptor propertyDescriptor =
390 getPropertyDescriptor(base, name);
391
392 Method m = propertyDescriptor.getWriteMethod();
393 if (m == null)
394 {
395 throw new PropertyNotFoundException(
396 getMessage(base, name)+ " (no write method for property!)");
397 }
398
399
400
401 m = MethodUtils.getAccessibleMethod(m);
402 if (m == null)
403 {
404 throw new PropertyNotFoundException(
405 getMessage(base, name) + " (not accessible!)");
406 }
407
408 try
409 {
410 m.invoke(base, new Object[] {newValue});
411 }
412 catch (Throwable t)
413 {
414 if(log.isDebugEnabled())
415 log.debug("Exception while invoking setter method.",t);
416 throw new EvaluationException(getMessage(base, name, newValue, m), t);
417 }
418 }
419
420 private static String getMessage(Object base, String name, Object newValue, Method m)
421 {
422 return "Bean: "
423 + base.getClass().getName() + ", property: " + name +", newValue: "+(newValue==null?" null ":newValue)+
424 ",newValue class: "+(newValue==null?" null ":newValue.getClass().getName())+" method parameter class: "
425 +((m.getParameterTypes()!=null&&m.getParameterTypes().length>0)
426 ?m.getParameterTypes()[0].getName():"null");
427
428 }
429
430 private static String getMessage(Object base, String name)
431 {
432 return "Bean: "
433 + base.getClass().getName() + ", property: " + name;
434 }
435
436 public static Object getProperty(Object base, String name)
437 {
438 PropertyDescriptor propertyDescriptor =
439 getPropertyDescriptor(base, name);
440
441 Method m = propertyDescriptor.getReadMethod();
442 if (m == null)
443 {
444 throw new PropertyNotFoundException(
445 getMessage(base, name));
446 }
447
448
449
450 m = MethodUtils.getAccessibleMethod(m);
451 if (m == null)
452 {
453 throw new PropertyNotFoundException(
454 getMessage(base, name) + " (not accessible!)");
455 }
456
457 try
458 {
459 return m.invoke(base, NO_ARGS);
460 }
461 catch (Throwable t)
462 {
463 throw new EvaluationException(getMessage(base, name), t);
464 }
465 }
466
467 public static PropertyDescriptor getPropertyDescriptor(
468 Object base, String name)
469 {
470 PropertyDescriptor propertyDescriptor;
471
472 try
473 {
474 propertyDescriptor =
475 getPropertyDescriptor(
476 Introspector.getBeanInfo(base.getClass()), name);
477 }
478 catch (IntrospectionException e)
479 {
480 throw new PropertyNotFoundException(getMessage(base, name), e);
481 }
482
483 return propertyDescriptor;
484 }
485
486 public static PropertyDescriptor getPropertyDescriptor(
487 BeanInfo beanInfo, String propertyName)
488 {
489 PropertyDescriptor[] propDescriptors =
490 beanInfo.getPropertyDescriptors();
491
492 if (propDescriptors != null)
493 {
494
495 for (int i = 0, len = propDescriptors.length; i < len; i++)
496 {
497 if (propDescriptors[i].getName().equals(propertyName))
498 return propDescriptors[i];
499 }
500 }
501
502 throw new PropertyNotFoundException("Bean: "
503 + beanInfo.getBeanDescriptor().getBeanClass().getName()
504 + ", property: " + propertyName);
505 }
506
507 }