View Javadoc

1   package org.apache.commons.betwixt.digester;
2   
3   /*
4    * Copyright 2001-2004 The Apache Software Foundation.
5    * 
6    * Licensed under the Apache License, Version 2.0 (the "License");
7    * you may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    * 
10   *      http://www.apache.org/licenses/LICENSE-2.0
11   * 
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */ 
18  import java.beans.BeanInfo;
19  import java.beans.Introspector;
20  import java.beans.PropertyDescriptor;
21  
22  import org.apache.commons.betwixt.AttributeDescriptor;
23  import org.apache.commons.betwixt.ElementDescriptor;
24  import org.apache.commons.betwixt.XMLUtils;
25  import org.apache.commons.betwixt.expression.ConstantExpression;
26  import org.apache.commons.logging.Log;
27  import org.apache.commons.logging.LogFactory;
28  import org.xml.sax.Attributes;
29  import org.xml.sax.SAXException;
30  
31  /*** 
32    * <p><code>AttributeRule</code> the digester Rule for parsing the 
33    * &lt;attribute&gt; elements.</p>
34    *
35    * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
36    * @version $Id: AttributeRule.java,v 1.9 2004/02/28 13:38:32 yoavs Exp $
37    */
38  public class AttributeRule extends RuleSupport {
39  
40      /*** Logger */
41      private static final Log log = LogFactory.getLog( AttributeRule.class );
42      /*** This loads all classes created by name. Defaults to this class's classloader */
43      private ClassLoader classLoader;
44      /*** The <code>Class</code> whose .betwixt file is being digested */
45      private Class beanClass;
46      
47      /*** Base constructor */
48      public AttributeRule() {
49          this.classLoader = getClass().getClassLoader();
50      }
51      
52      // Rule interface
53      //-------------------------------------------------------------------------    
54      
55      /***
56       * Process the beginning of this element.
57       *
58       * @param attributes The attribute list of this element
59       * @throws SAXException 1. If the attribute tag is not inside an element tag.
60       * 2. If the name attribute is not valid XML attribute name.
61       */
62      public void begin(Attributes attributes) throws SAXException {
63          
64          AttributeDescriptor descriptor = new AttributeDescriptor();
65          String name = attributes.getValue( "name" );
66  
67          // check that name is well formed 
68          if ( !XMLUtils.isWellFormedXMLName( name ) ) {
69              throw new SAXException("'" + name + "' would not be a well formed xml attribute name.");
70          }
71          
72          descriptor.setQualifiedName( name );
73          descriptor.setLocalName( name );
74          String uri = attributes.getValue( "uri" );
75          if ( uri != null ) {
76              descriptor.setURI( uri );        
77          }
78          String propertyName = attributes.getValue( "property" );
79          descriptor.setPropertyName( propertyName );
80          descriptor.setPropertyType( loadClass( attributes.getValue( "type" ) ) );
81          
82          if ( propertyName != null && propertyName.length() > 0 ) {
83              configureDescriptor(descriptor);
84          } else {
85              String value = attributes.getValue( "value" );
86              if ( value != null ) {
87                  descriptor.setTextExpression( new ConstantExpression( value ) );
88              }
89          }
90  
91          Object top = digester.peek();
92          if ( top instanceof ElementDescriptor ) {
93              ElementDescriptor parent = (ElementDescriptor) top;
94              parent.addAttributeDescriptor( descriptor );
95          } else {
96              throw new SAXException( "Invalid use of <attribute>. It should " 
97                  + "be nested inside an <element> element" );
98          }            
99  
100         digester.push(descriptor);        
101     }
102 
103 
104     /***
105      * Process the end of this element.
106      */
107     public void end() {
108         Object top = digester.pop();
109     }
110 
111     
112     // Implementation methods
113     //-------------------------------------------------------------------------    
114     /***
115      * Loads a class (using the appropriate classloader)
116      *
117      * @param name the name of the class to load
118      * @return the class instance loaded by the appropriate classloader
119      */
120     protected Class loadClass( String name ) {
121         // XXX: should use a ClassLoader to handle complex class loading situations
122         if ( name != null ) {
123             try {
124                 return classLoader.loadClass(name);
125             } catch (Exception e) { // SWALLOW
126             }
127         }
128         return null;            
129     }
130     
131     /*** 
132      * Set the Expression and Updater from a bean property name 
133      * @param attributeDescriptor configure this <code>AttributeDescriptor</code> 
134      * from the property with a matching name in the bean class
135      */
136     protected void configureDescriptor(AttributeDescriptor attributeDescriptor) {
137         Class beanClass = getBeanClass();
138         if ( beanClass != null ) {
139             String name = attributeDescriptor.getPropertyName();
140             try {
141                 BeanInfo beanInfo = Introspector.getBeanInfo( beanClass );
142                 PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();
143                 if ( descriptors != null ) {
144                     for ( int i = 0, size = descriptors.length; i < size; i++ ) {
145                         PropertyDescriptor descriptor = descriptors[i];
146                         if ( name.equals( descriptor.getName() ) ) {
147                             XMLIntrospectorHelper
148                                 .configureProperty( attributeDescriptor, descriptor );
149                             getProcessedPropertyNameSet().add( name );
150                             break;
151                         }
152                     }
153                 }
154             } catch (Exception e) {
155                 log.warn( "Caught introspection exception", e );
156             }
157         }
158     }    
159 }