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