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