KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > myfaces > el > PropertyResolverImpl


1 /*
2  * Copyright 2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.myfaces.el;
17
18 import org.apache.commons.beanutils.MethodUtils;
19 import org.apache.commons.logging.Log;
20 import org.apache.commons.logging.LogFactory;
21
22 import javax.faces.el.EvaluationException;
23 import javax.faces.el.PropertyNotFoundException;
24 import javax.faces.el.PropertyResolver;
25 import javax.faces.el.ReferenceSyntaxException;
26 import java.beans.BeanInfo JavaDoc;
27 import java.beans.IntrospectionException JavaDoc;
28 import java.beans.Introspector JavaDoc;
29 import java.beans.PropertyDescriptor JavaDoc;
30 import java.lang.reflect.Array JavaDoc;
31 import java.lang.reflect.Method JavaDoc;
32 import java.util.List JavaDoc;
33 import java.util.Map JavaDoc;
34
35
36 /**
37  * @author Manfred Geiler (latest modification by $Author: mmarinschek $)
38  * @author Anton Koinov
39  * @version $Revision: 1.31 $ $Date: 2005/01/09 18:15:12 $
40  * $Log: PropertyResolverImpl.java,v $
41  * Revision 1.31 2005/01/09 18:15:12 mmarinschek
42  * small changes - better error handling, label renderer supports more hooks for sub-classes
43  *
44  * Revision 1.30 2004/12/03 08:41:45 manolito
45  * MYFACES-44 / PropertyResolverImpl has special logic for UIComponents
46  *
47  * Revision 1.29 2004/10/13 11:51:00 matze
48  * renamed packages to org.apache
49  *
50  * Revision 1.28 2004/09/20 14:35:48 dave0000
51  * bug 1030875:
52  * getType() should return null if type cannot be determined
53  * isReadOnly() should return false if read-only cannot be determined
54  *
55  * Revision 1.27 2004/07/01 22:05:11 mwessendorf
56  * ASF switch
57  *
58  * Revision 1.26 2004/06/23 15:56:16 manolito
59  * removed our own version of commons-beanutils MethodUtils
60  *
61  * Revision 1.25 2004/05/18 17:09:29 manolito
62  * resolved the problem with inaccessible methods in private classes that implement a public interface
63  *
64  * Revision 1.24 2004/04/26 05:54:59 dave0000
65  * Add coercion to ValueBinding (and related changes)
66  *
67  * Revision 1.23 2004/04/08 13:42:13 royalts
68  * removed main method
69  *
70  * Revision 1.22 2004/04/08 05:16:45 dave0000
71  * change to always use JSF PropertyResolver (was using JSP PR sometimes)
72  *
73  * Revision 1.21 2004/04/06 06:48:23 manolito
74  * IndexedPropertyDescriptor issue
75  *
76  */

77 public class PropertyResolverImpl extends PropertyResolver
78 {
79     private static final Log log =
80         LogFactory.getLog(PropertyResolverImpl.class);
81
82     //~ Static fields/initializers ---------------------------------------------
83

84     private static final Object JavaDoc[] NO_ARGS = {};
85
86     //~ Public PropertyResolver Methods ----------------------------------------
87

88     public Object JavaDoc getValue(Object JavaDoc base, Object JavaDoc property)
89             throws EvaluationException, PropertyNotFoundException
90     {
91         try
92         {
93             if (base == null || property == null ||
94                 property instanceof String JavaDoc && ((String JavaDoc)property).length() == 0)
95             {
96                 return null;
97             }
98             if (base instanceof Map JavaDoc)
99             {
100                 return ((Map JavaDoc) base).get(property);
101             }
102
103             // If none of the special bean types, then process as normal Bean
104
return getProperty(base, property.toString());
105         }
106         catch (RuntimeException JavaDoc e)
107         {
108             log.error("Exception getting value of property " + property
109                 + " of bean "
110                 + base != null ? base.getClass().getName() : "NULL", e);
111             throw e;
112         }
113     }
114
115     public Object JavaDoc getValue(Object JavaDoc base, int index)
116             throws EvaluationException, PropertyNotFoundException
117     {
118         try
119         {
120             if (base == null)
121             {
122                 return null;
123             }
124
125             try
126             {
127                 if (base.getClass().isArray())
128                 {
129                     return Array.get(base, index);
130                 }
131                 if (base instanceof List JavaDoc)
132                 {
133                     return ((List JavaDoc) base).get(index);
134                 }
135             }
136             catch (IndexOutOfBoundsException JavaDoc e)
137             {
138                 // Note: ArrayIndexOutOfBoundsException also here
139
return null;
140             }
141
142             throw new ReferenceSyntaxException("Must be array or List. Bean: "
143                 + base.getClass().getName() + ", index " + index);
144         }
145         catch (RuntimeException JavaDoc e)
146         {
147             log.error("Exception getting value for index " + index
148                 + " of bean "
149                 + base != null ? base.getClass().getName() : "NULL", e);
150             throw e;
151         }
152     }
153
154     public void setValue(Object JavaDoc base, Object JavaDoc property, Object JavaDoc newValue)
155             throws EvaluationException, PropertyNotFoundException
156     {
157         try
158         {
159             if (base == null)
160             {
161                 throw new PropertyNotFoundException(
162                     "Null bean, property: " + property);
163             }
164             if (property == null ||
165                 property instanceof String JavaDoc && ((String JavaDoc)property).length() == 0)
166             {
167                 throw new PropertyNotFoundException("Bean: "
168                     + base.getClass().getName()
169                     + ", null or empty property name");
170             }
171
172             if (base instanceof Map JavaDoc)
173             {
174                 ((Map JavaDoc) base).put(property, newValue);
175
176                 return;
177             }
178
179             // If none of the special bean types, then process as normal Bean
180
setProperty(base, property.toString(), newValue);
181         }
182         catch (RuntimeException JavaDoc e)
183         {
184             log.error("Exception setting property " + property
185                 + " of bean "
186                 + base != null ? base.getClass().getName() : "NULL", e);
187             throw e;
188         }
189     }
190
191     public void setValue(Object JavaDoc base, int index, Object JavaDoc newValue)
192             throws EvaluationException, PropertyNotFoundException
193     {
194         try
195         {
196             if (base == null)
197             {
198                 throw new PropertyNotFoundException(
199                     "Null bean, index: " + index);
200             }
201
202             try
203             {
204                 if (base.getClass().isArray())
205                 {
206                     Array.set(base, index, newValue);
207
208                     return;
209                 }
210                 if (base instanceof List JavaDoc)
211                 {
212                     // REVISIT: should we try to grow the list, if growable type
213
// (e.g., ArrayList, etc.), and if not large
214
// enough?
215
((List JavaDoc) base).set(index, newValue);
216
217                     return;
218                 }
219             }
220             catch (IndexOutOfBoundsException JavaDoc e)
221             {
222                 throw new PropertyNotFoundException("Bean: "
223                     + base.getClass().getName() + ", index " + index, e);
224             }
225
226             throw new EvaluationException(
227                 "Bean must be array or List. Bean: "
228                 + base.getClass().getName() + ", index " + index);
229         }
230         catch (RuntimeException JavaDoc e)
231         {
232             log.error("Exception setting value of index " + index + " of bean "
233                 + base != null ? base.getClass().getName() : "NULL", e);
234             throw e;
235         }
236     }
237
238     public boolean isReadOnly(Object JavaDoc base, Object JavaDoc property)
239     {
240         try
241         {
242             if (base == null || property == null ||
243                 property instanceof String JavaDoc && ((String JavaDoc)property).length() == 0)
244             {
245                 // Cannot determine read-only, return false (is this what the spec requires?)
246
return false;
247             }
248
249             // Is there any way to determine whether Map.put() will fail?
250
if (base instanceof Map JavaDoc)
251             {
252                 return false;
253             }
254
255             // If none of the special bean types, then process as normal Bean
256
PropertyDescriptor JavaDoc propertyDescriptor =
257                 getPropertyDescriptor(base, property.toString());
258
259             return propertyDescriptor.getWriteMethod() == null;
260         }
261         catch (Exception JavaDoc e)
262         {
263             // Cannot determine read-only, return false (is this what the spec requires?)
264
return false;
265         }
266     }
267
268     public boolean isReadOnly(Object JavaDoc base, int index)
269     {
270         try
271         {
272             if (base == null)
273             {
274                 // Cannot determine read-only, return false (is this what the spec requires?)
275
return false;
276             }
277             if (base instanceof List JavaDoc || base.getClass().isArray())
278             {
279                 // Is there any way to determine whether List.set() will fail?
280
return false;
281             }
282
283             // Cannot determine read-only, return false (is this what the spec requires?)
284
return false;
285         }
286         catch (Exception JavaDoc e)
287         {
288             // Cannot determine read-only, return false (is this what the spec requires?)
289
return false;
290         }
291     }
292
293     public Class JavaDoc getType(Object JavaDoc base, Object JavaDoc property)
294     {
295         try
296         {
297             if (base == null || property == null ||
298                 property instanceof String JavaDoc && ((String JavaDoc)property).length() == 0)
299             {
300                 // Cannot determine type, return null per JSF spec
301
return null;
302             }
303
304             if (base instanceof Map JavaDoc)
305             {
306                 Object JavaDoc value = ((Map JavaDoc) base).get(property);
307
308                 // REVISIT: when generics are imlemented in JVM 1.5
309
return (value == null) ? Object JavaDoc.class : value.getClass();
310             }
311
312             // If none of the special bean types, then process as normal Bean
313
PropertyDescriptor JavaDoc propertyDescriptor =
314                 getPropertyDescriptor(base, property.toString());
315
316             return propertyDescriptor.getPropertyType();
317         }
318         catch (Exception JavaDoc e)
319         {
320             // Cannot determine type, return null per JSF spec
321
return null;
322         }
323     }
324
325     public Class JavaDoc getType(Object JavaDoc base, int index)
326     {
327         try
328         {
329             if (base == null)
330             {
331                 // Cannot determine type, return null per JSF spec
332
return null;
333             }
334
335             if (base.getClass().isArray())
336             {
337                 return base.getClass().getComponentType();
338             }
339
340             if (base instanceof List JavaDoc)
341             {
342                 // REVISIT: does it make sense to do this or simply return
343
// Object.class? What if the new value is not of
344
// the old value's class?
345
Object JavaDoc value = ((List JavaDoc) base).get(index);
346
347                 // REVISIT: when generics are implemented in JVM 1.5
348
return (value != null) ? value.getClass() : Object JavaDoc.class;
349             }
350
351             // Cannot determine type, return null per JSF spec
352
return null;
353         }
354         catch (Exception JavaDoc e)
355         {
356             // Cannot determine type, return null per JSF spec
357
return null;
358         }
359     }
360
361
362     //~ Internal Helper Methods ------------------------------------------------
363

364     public static void setProperty(Object JavaDoc base, String JavaDoc name, Object JavaDoc newValue)
365     {
366         PropertyDescriptor JavaDoc propertyDescriptor =
367             getPropertyDescriptor(base, name);
368
369         Method JavaDoc m = propertyDescriptor.getWriteMethod();
370         if (m == null)
371         {
372             throw new PropertyNotFoundException(
373                 "Bean: " + base.getClass().getName() + ", property: " + name);
374         }
375
376         // Check if the concrete class of this method is accessible and if not
377
// search for a public interface that declares this method
378
m = MethodUtils.getAccessibleMethod(m);
379         if (m == null)
380         {
381             throw new PropertyNotFoundException(
382                 "Bean: " + base.getClass().getName() + ", property: " + name + " (not accessible!)");
383         }
384
385         try
386         {
387             m.invoke(base, new Object JavaDoc[] {newValue});
388         }
389         catch (Throwable JavaDoc t)
390         {
391             throw new EvaluationException("Bean: "
392                 + base.getClass().getName() + ", property: " + name, t);
393         }
394     }
395
396     public static Object JavaDoc getProperty(Object JavaDoc base, String JavaDoc name)
397     {
398         PropertyDescriptor JavaDoc propertyDescriptor =
399             getPropertyDescriptor(base, name);
400
401         Method JavaDoc m = propertyDescriptor.getReadMethod();
402         if (m == null)
403         {
404             throw new PropertyNotFoundException(
405                 "Bean: " + base.getClass().getName() + ", property: " + name);
406         }
407
408         // Check if the concrete class of this method is accessible and if not
409
// search for a public interface that declares this method
410
m = MethodUtils.getAccessibleMethod(m);
411         if (m == null)
412         {
413             throw new PropertyNotFoundException(
414                 "Bean: " + base.getClass().getName() + ", property: " + name + " (not accessible!)");
415         }
416
417         try
418         {
419             return m.invoke(base, NO_ARGS);
420         }
421         catch (Throwable JavaDoc t)
422         {
423             throw new EvaluationException("Bean: "
424                 + base.getClass().getName() + ", property: " + name, t);
425         }
426     }
427
428     public static PropertyDescriptor JavaDoc getPropertyDescriptor(
429         Object JavaDoc base, String JavaDoc name)
430     {
431         PropertyDescriptor JavaDoc propertyDescriptor;
432
433         try
434         {
435             propertyDescriptor =
436                 getPropertyDescriptor(
437                     Introspector.getBeanInfo(base.getClass()), name);
438         }
439         catch (IntrospectionException JavaDoc e)
440         {
441             throw new PropertyNotFoundException("Bean: "
442                 + base.getClass().getName() + ", property: " + name, e);
443         }
444
445         return propertyDescriptor;
446     }
447
448     public static PropertyDescriptor JavaDoc getPropertyDescriptor(
449         BeanInfo JavaDoc beanInfo, String JavaDoc propertyName)
450     {
451         PropertyDescriptor JavaDoc[] propDescriptors =
452             beanInfo.getPropertyDescriptors();
453         
454         if (propDescriptors != null)
455         {
456             // TODO: cache this in classLoader safe way
457
for (int i = 0, len = propDescriptors.length; i < len; i++)
458             {
459                 if (propDescriptors[i].getName().equals(propertyName))
460                     return propDescriptors[i];
461             }
462         }
463
464         throw new PropertyNotFoundException("Bean: "
465             + beanInfo.getBeanDescriptor().getBeanClass().getName()
466             + ", property: " + propertyName);
467     }
468     
469 }
470
Popular Tags