1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.commons.betwixt.digester;
17
18 import java.beans.BeanInfo;
19 import java.beans.Introspector;
20 import java.beans.PropertyDescriptor;
21
22 import org.apache.commons.logging.Log;
23 import org.apache.commons.logging.LogFactory;
24
25 /*** <p>Factors out common code used by Betwixt rules that access bean properties.
26 * Maybe a lot of this should be moved into <code>BeanUtils</code>.</p>
27 *
28 * @author Robert Burrell Donkin
29 * @since 0.5
30 */
31 public abstract class MappedPropertyRule extends RuleSupport {
32
33 /*** Logger */
34 private static final Log log = LogFactory.getLog( MappedPropertyRule.class );
35 /*** Classloader used to load classes by name */
36 private ClassLoader classLoader;
37 /*** Base constructor */
38 public MappedPropertyRule() {
39 this.classLoader = getClass().getClassLoader();
40 }
41
42
43
44
45
46
47 /***
48 * Returns the property descriptor for the class and property name.
49 * Note that some caching could be used to improve performance of
50 * this method. Or this method could be added to PropertyUtils.
51 *
52 * @param beanClass descriptor for property in this class
53 * @param propertyName descriptor for property with this name
54 * @return property descriptor for the named property in the given class
55 */
56 protected PropertyDescriptor getPropertyDescriptor( Class beanClass,
57 String propertyName ) {
58 if ( beanClass != null && propertyName != null ) {
59 if (log.isTraceEnabled()) {
60 log.trace("Searching for property " + propertyName + " on " + beanClass);
61 }
62 try {
63
64
65
66 BeanInfo beanInfo = Introspector.getBeanInfo( beanClass );
67 PropertyDescriptor[] descriptors =
68 beanInfo.getPropertyDescriptors();
69 if ( descriptors != null ) {
70 for ( int i = 0, size = descriptors.length; i < size; i++ ) {
71 PropertyDescriptor descriptor = descriptors[i];
72 if ( propertyName.equals( descriptor.getName() ) ) {
73 log.trace("Found matching method.");
74 return descriptor;
75 }
76 }
77 }
78
79 if (beanClass.isInterface()) {
80 Class[] superinterfaces = beanClass.getInterfaces();
81 for (int i=0, size=superinterfaces.length; i<size; i++) {
82 PropertyDescriptor descriptor = getPropertyDescriptor(superinterfaces[i], propertyName);
83 if (descriptor != null)
84 {
85 return descriptor;
86 }
87 }
88 }
89
90 log.trace("No match found.");
91 return null;
92 } catch (Exception e) {
93 log.warn( "Caught introspection exception", e );
94 }
95 }
96 return null;
97 }
98
99
100 /***
101 * Gets the type of a property
102 *
103 * @param propertyClassName class name for property type (may be null)
104 * @param beanClass class that has property
105 * @param propertyName the name of the property whose type is to be determined
106 * @return property type
107 */
108 protected Class getPropertyType( String propertyClassName,
109 Class beanClass, String propertyName ) {
110
111
112 if ( propertyClassName != null ) {
113 try {
114 Class answer = classLoader.loadClass(propertyClassName);
115 if (answer != null) {
116 if (log.isTraceEnabled()) {
117 log.trace("Used specified type " + answer);
118 }
119 return answer;
120 }
121 } catch (Exception e) {
122 log.warn("Cannot load specified type", e);
123 }
124 }
125
126 PropertyDescriptor descriptor =
127 getPropertyDescriptor( beanClass, propertyName );
128 if ( descriptor != null ) {
129 return descriptor.getPropertyType();
130 }
131
132 if (log.isTraceEnabled()) {
133 log.trace("Cannot find property type.");
134 log.trace(" className=" + propertyClassName
135 + " base=" + beanClass + " name=" + propertyName);
136 }
137 return null;
138 }
139 }