View Javadoc
1 package org.apache.commons.betwixt.digester; 2 3 /* 4 * ==================================================================== 5 * 6 * The Apache Software License, Version 1.1 7 * 8 * Copyright (c) 1999-2002 The Apache Software Foundation. All rights 9 * reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in 20 * the documentation and/or other materials provided with the 21 * distribution. 22 * 23 * 3. The end-user documentation included with the redistribution, if 24 * any, must include the following acknowlegement: 25 * "This product includes software developed by the 26 * Apache Software Foundation (http://www.apache.org/)." 27 * Alternately, this acknowlegement may appear in the software itself, 28 * if and wherever such third-party acknowlegements normally appear. 29 * 30 * 4. The names "The Jakarta Project", "Commons", and "Apache Software 31 * Foundation" must not be used to endorse or promote products derived 32 * from this software without prior written permission. For written 33 * permission, please contact apache@apache.org. 34 * 35 * 5. Products derived from this software may not be called "Apache" 36 * nor may "Apache" appear in their names without prior written 37 * permission of the Apache Group. 38 * 39 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 40 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 41 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 42 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR 43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 45 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 46 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 47 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 48 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 49 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 50 * SUCH DAMAGE. 51 * ==================================================================== 52 * 53 * This software consists of voluntary contributions made by many 54 * individuals on behalf of the Apache Software Foundation. For more 55 * information on the Apache Software Foundation, please see 56 * <http://www.apache.org/>;. 57 * 58 */ 59 60 import java.beans.BeanInfo; 61 import java.beans.Introspector; 62 import java.beans.PropertyDescriptor; 63 64 import org.apache.commons.betwixt.ElementDescriptor; 65 import org.apache.commons.betwixt.XMLBeanInfo; 66 import org.apache.commons.betwixt.expression.ConstantExpression; 67 import org.apache.commons.logging.Log; 68 import org.apache.commons.logging.LogFactory; 69 import org.xml.sax.Attributes; 70 import org.xml.sax.SAXException; 71 72 /*** 73 * <p><code>ElementRule</code> the digester Rule for parsing 74 * the <element> elements.</p> 75 * 76 * @author <a href="mailto:jstrachan@apache.org">James Strachan</a> 77 * @version $Id: ElementRule.java,v 1.6 2003/01/07 22:32:57 rdonkin Exp $ 78 */ 79 public class ElementRule extends RuleSupport { 80 81 /*** Logger */ 82 private static final Log log = LogFactory.getLog( ElementRule.class ); 83 /*** Classloader used to load classes by name */ 84 private ClassLoader classLoader; 85 /*** Class for which the .bewixt file is being digested */ 86 private Class beanClass; 87 /*** Base constructor */ 88 public ElementRule() { 89 this.classLoader = getClass().getClassLoader(); 90 } 91 92 // Rule interface 93 //------------------------------------------------------------------------- 94 95 /*** 96 * Process the beginning of this element. 97 * 98 * @param attributes The attribute list of this element 99 * @throws SAXException when this tag's parent is not either an info or element tag 100 */ 101 public void begin(Attributes attributes) throws SAXException { 102 String name = attributes.getValue( "name" ); 103 104 ElementDescriptor descriptor = new ElementDescriptor(); 105 descriptor.setQualifiedName( name ); 106 descriptor.setLocalName( name ); 107 String uri = attributes.getValue( "uri" ); 108 if ( uri != null ) { 109 descriptor.setURI( uri ); 110 } 111 112 String propertyName = attributes.getValue( "property" ); 113 descriptor.setPropertyName( propertyName ); 114 115 String propertyType = attributes.getValue( "type" ); 116 117 if (log.isTraceEnabled()) { 118 log.trace( 119 "(BEGIN) name=" + name + " uri=" + uri 120 + " property=" + propertyName + " type=" + propertyType); 121 } 122 123 // set the property type using reflection 124 descriptor.setPropertyType( 125 getPropertyType( propertyType, beanClass, propertyName ) 126 ); 127 128 129 if ( propertyName != null && propertyName.length() > 0 ) { 130 configureDescriptor(descriptor); 131 132 } else { 133 String value = attributes.getValue( "value" ); 134 if ( value != null ) { 135 descriptor.setTextExpression( new ConstantExpression( value ) ); 136 } 137 } 138 139 Object top = digester.peek(); 140 if ( top instanceof XMLBeanInfo ) { 141 XMLBeanInfo beanInfo = (XMLBeanInfo) top; 142 beanInfo.setElementDescriptor( descriptor ); 143 beanClass = beanInfo.getBeanClass(); 144 145 } else if ( top instanceof ElementDescriptor ) { 146 ElementDescriptor parent = (ElementDescriptor) top; 147 parent.addElementDescriptor( descriptor ); 148 149 } else { 150 throw new SAXException( "Invalid use of <element>. It should " 151 + "be nested inside <info> or other <element> nodes" ); 152 } 153 154 digester.push(descriptor); 155 } 156 157 158 /*** 159 * Process the end of this element. 160 */ 161 public void end() { 162 Object top = digester.pop(); 163 } 164 165 166 // Implementation methods 167 //------------------------------------------------------------------------- 168 169 /*** 170 * Gets the type of a property 171 * 172 * @param propertyClassName class name for property type (may be null) 173 * @param beanClass class that has property 174 * @param propertyName the name of the property whose type is to be determined 175 * @return property type 176 */ 177 protected Class getPropertyType( String propertyClassName, 178 Class beanClass, String propertyName ) { 179 // XXX: should use a ClassLoader to handle 180 // complex class loading situations 181 if ( propertyClassName != null ) { 182 try { 183 Class answer = classLoader.loadClass(propertyClassName); 184 if (answer != null) { 185 if (log.isTraceEnabled()) { 186 log.trace("Used specified type " + answer); 187 } 188 return answer; 189 } 190 } catch (Exception e) { 191 log.warn("Cannot load specified type", e); 192 } 193 } 194 195 PropertyDescriptor descriptor = 196 getPropertyDescriptor( beanClass, propertyName ); 197 if ( descriptor != null ) { 198 return descriptor.getPropertyType(); 199 } 200 201 if (log.isTraceEnabled()) { 202 log.trace("Cannot find property type."); 203 log.trace(" className=" + propertyClassName 204 + " base=" + beanClass + " name=" + propertyName); 205 } 206 return null; 207 } 208 209 /*** 210 * Set the Expression and Updater from a bean property name 211 * 212 * @param elementDescriptor configure this <code>ElementDescriptor</code> 213 */ 214 protected void configureDescriptor(ElementDescriptor elementDescriptor) { 215 Class beanClass = getBeanClass(); 216 if ( beanClass != null ) { 217 String name = elementDescriptor.getPropertyName(); 218 PropertyDescriptor descriptor = 219 getPropertyDescriptor( beanClass, name ); 220 if ( descriptor != null ) { 221 XMLIntrospectorHelper 222 .configureProperty( elementDescriptor, descriptor ); 223 getProcessedPropertyNameSet().add( name ); 224 } 225 } 226 } 227 228 /*** 229 * Returns the property descriptor for the class and property name. 230 * Note that some caching could be used to improve performance of 231 * this method. Or this method could be added to PropertyUtils. 232 * 233 * @param beanClass descriptor for property in this class 234 * @param propertyName descriptor for property with this name 235 * @return property descriptor for the named property in the given class 236 */ 237 protected PropertyDescriptor getPropertyDescriptor( Class beanClass, 238 String propertyName ) { 239 if ( beanClass != null && propertyName != null ) { 240 if (log.isTraceEnabled()) { 241 log.trace("Searching for property " + propertyName + " on " + beanClass); 242 } 243 try { 244 BeanInfo beanInfo = Introspector.getBeanInfo( beanClass ); 245 PropertyDescriptor[] descriptors = 246 beanInfo.getPropertyDescriptors(); 247 if ( descriptors != null ) { 248 for ( int i = 0, size = descriptors.length; i < size; i++ ) { 249 PropertyDescriptor descriptor = descriptors[i]; 250 if ( propertyName.equals( descriptor.getName() ) ) { 251 log.trace("Found matching method."); 252 return descriptor; 253 } 254 } 255 } 256 log.trace("No match found."); 257 return null; 258 } catch (Exception e) { 259 log.warn( "Caught introspection exception", e ); 260 } 261 } 262 return null; 263 } 264 265 }

This page was automatically generated by Maven