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. import java.beans.BeanInfo;
  18. import java.beans.Introspector;
  19. import java.beans.PropertyDescriptor;
  20. import org.apache.commons.logging.Log;
  21. import org.apache.commons.logging.LogFactory;
  22. /** <p>Factors out common code used by Betwixt rules that access bean properties.
  23. * Maybe a lot of this should be moved into <code>BeanUtils</code>.</p>
  24. *
  25. * @author Robert Burrell Donkin
  26. * @sinec 0.5
  27. */
  28. public abstract class MappedPropertyRule extends RuleSupport {
  29. /** Logger */
  30. private static final Log log = LogFactory.getLog( MappedPropertyRule.class );
  31. /** Classloader used to load classes by name */
  32. private ClassLoader classLoader;
  33. /** Base constructor */
  34. public MappedPropertyRule() {
  35. this.classLoader = getClass().getClassLoader();
  36. }
  37. // Implementation methods
  38. //-------------------------------------------------------------------------
  39. /**
  40. * Returns the property descriptor for the class and property name.
  41. * Note that some caching could be used to improve performance of
  42. * this method. Or this method could be added to PropertyUtils.
  43. *
  44. * @param beanClass descriptor for property in this class
  45. * @param propertyName descriptor for property with this name
  46. * @return property descriptor for the named property in the given class
  47. */
  48. protected PropertyDescriptor getPropertyDescriptor( Class beanClass,
  49. String propertyName ) {
  50. if ( beanClass != null && propertyName != null ) {
  51. if (log.isTraceEnabled()) {
  52. log.trace("Searching for property " + propertyName + " on " + beanClass);
  53. }
  54. try {
  55. BeanInfo beanInfo = Introspector.getBeanInfo( beanClass );
  56. PropertyDescriptor[] descriptors =
  57. beanInfo.getPropertyDescriptors();
  58. if ( descriptors != null ) {
  59. for ( int i = 0, size = descriptors.length; i < size; i++ ) {
  60. PropertyDescriptor descriptor = descriptors[i];
  61. if ( propertyName.equals( descriptor.getName() ) ) {
  62. log.trace("Found matching method.");
  63. return descriptor;
  64. }
  65. }
  66. }
  67. log.trace("No match found.");
  68. return null;
  69. } catch (Exception e) {
  70. log.warn( "Caught introspection exception", e );
  71. }
  72. }
  73. return null;
  74. }
  75. /**
  76. * Gets the type of a property
  77. *
  78. * @param propertyClassName class name for property type (may be null)
  79. * @param beanClass class that has property
  80. * @param propertyName the name of the property whose type is to be determined
  81. * @return property type
  82. */
  83. protected Class getPropertyType( String propertyClassName,
  84. Class beanClass, String propertyName ) {
  85. // XXX: should use a ClassLoader to handle
  86. // complex class loading situations
  87. if ( propertyClassName != null ) {
  88. try {
  89. Class answer = classLoader.loadClass(propertyClassName);
  90. if (answer != null) {
  91. if (log.isTraceEnabled()) {
  92. log.trace("Used specified type " + answer);
  93. }
  94. return answer;
  95. }
  96. } catch (Exception e) {
  97. log.warn("Cannot load specified type", e);
  98. }
  99. }
  100. PropertyDescriptor descriptor =
  101. getPropertyDescriptor( beanClass, propertyName );
  102. if ( descriptor != null ) {
  103. return descriptor.getPropertyType();
  104. }
  105. if (log.isTraceEnabled()) {
  106. log.trace("Cannot find property type.");
  107. log.trace(" className=" + propertyClassName
  108. + " base=" + beanClass + " name=" + propertyName);
  109. }
  110. return null;
  111. }
  112. }