View Javadoc

1   /*
2    * Copyright 2001-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.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      // Implementation methods
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                  BeanInfo beanInfo = Introspector.getBeanInfo( beanClass );
64                  PropertyDescriptor[] descriptors = 
65                      beanInfo.getPropertyDescriptors();
66                  if ( descriptors != null ) {
67                      for ( int i = 0, size = descriptors.length; i < size; i++ ) {
68                          PropertyDescriptor descriptor = descriptors[i];
69                          if ( propertyName.equals( descriptor.getName() ) ) {
70                              log.trace("Found matching method.");
71                              return descriptor;
72                          }
73                      }
74                  }
75                  log.trace("No match found.");
76                  return null;
77              } catch (Exception e) {
78                  log.warn( "Caught introspection exception", e );
79              }
80          }
81          return null;
82      }
83      
84      
85      /***
86       * Gets the type of a property
87       *
88       * @param propertyClassName class name for property type (may be null)
89       * @param beanClass class that has property 
90       * @param propertyName the name of the property whose type is to be determined
91       * @return property type 
92       */
93      protected Class getPropertyType( String propertyClassName, 
94                                       Class beanClass, String propertyName ) {
95          // XXX: should use a ClassLoader to handle 
96          //      complex class loading situations
97          if ( propertyClassName != null ) {
98              try {
99                  Class answer = classLoader.loadClass(propertyClassName);
100                 if (answer != null) {
101                     if (log.isTraceEnabled()) {
102                         log.trace("Used specified type " + answer);
103                     }
104                     return answer;
105                 }
106             } catch (Exception e) {
107                 log.warn("Cannot load specified type", e);
108             }
109         }
110         
111         PropertyDescriptor descriptor = 
112             getPropertyDescriptor( beanClass, propertyName );        
113         if ( descriptor != null ) { 
114             return descriptor.getPropertyType();
115         }
116         
117         if (log.isTraceEnabled()) {
118             log.trace("Cannot find property type.");
119             log.trace("  className=" + propertyClassName 
120                         + " base=" + beanClass + " name=" + propertyName);
121         }
122         return null;            
123     }
124 }