1 package org.apache.commons.betwixt.digester;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 import java.beans.BeanInfo;
20 import java.beans.Introspector;
21 import java.beans.PropertyDescriptor;
22 import java.lang.reflect.Method;
23
24 import org.apache.commons.betwixt.AttributeDescriptor;
25 import org.apache.commons.betwixt.ElementDescriptor;
26 import org.apache.commons.betwixt.XMLUtils;
27 import org.apache.commons.betwixt.expression.ConstantExpression;
28 import org.apache.commons.betwixt.expression.MethodExpression;
29 import org.apache.commons.betwixt.expression.MethodUpdater;
30 import org.apache.commons.logging.Log;
31 import org.apache.commons.logging.LogFactory;
32 import org.xml.sax.Attributes;
33 import org.xml.sax.SAXException;
34
35
36
37
38
39
40
41
42 public class AttributeRule extends RuleSupport {
43
44
45 private static final Log log = LogFactory.getLog( AttributeRule.class );
46
47 private ClassLoader classLoader;
48
49 private Class beanClass;
50
51
52 public AttributeRule() {
53 this.classLoader = getClass().getClassLoader();
54 }
55
56
57
58
59
60
61
62
63
64
65
66 public void begin(String name, String namespace, Attributes attributes) throws SAXException {
67
68 AttributeDescriptor descriptor = new AttributeDescriptor();
69 String nameAttributeValue = attributes.getValue( "name" );
70
71
72 if ( !XMLUtils.isWellFormedXMLName( nameAttributeValue ) ) {
73 throw new SAXException("'" + nameAttributeValue + "' would not be a well formed xml attribute name.");
74 }
75
76 String qName = nameAttributeValue;
77 descriptor.setLocalName( nameAttributeValue );
78 String uri = attributes.getValue( "uri" );
79 if ( uri != null ) {
80 descriptor.setURI( uri );
81 String prefix = getXMLIntrospector().getConfiguration().getPrefixMapper().getPrefix(uri);
82 qName = prefix + ":" + nameAttributeValue;
83 }
84 descriptor.setQualifiedName( qName );
85
86 String propertyName = attributes.getValue( "property" );
87 descriptor.setPropertyName( propertyName );
88 descriptor.setPropertyType( loadClass( attributes.getValue( "type" ) ) );
89
90 if ( propertyName != null && propertyName.length() > 0 ) {
91 configureDescriptor(descriptor);
92 } else {
93 String value = attributes.getValue( "value" );
94 if ( value != null ) {
95 descriptor.setTextExpression( new ConstantExpression( value ) );
96 }
97 }
98
99 Object top = digester.peek();
100 if ( top instanceof ElementDescriptor ) {
101 ElementDescriptor parent = (ElementDescriptor) top;
102 parent.addAttributeDescriptor( descriptor );
103 } else {
104 throw new SAXException( "Invalid use of <attribute>. It should "
105 + "be nested inside an <element> element" );
106 }
107
108 digester.push(descriptor);
109 }
110
111
112
113
114
115 public void end(String name, String namespace) {
116 AttributeDescriptor descriptor = (AttributeDescriptor)digester.pop();
117 ElementDescriptor parent = (ElementDescriptor)digester.peek();
118
119
120 if( getXMLIntrospector().getConfiguration().getAttributeSuppressionStrategy().suppress(descriptor)) {
121 parent.removeAttributeDescriptor(descriptor);
122 }
123 }
124
125
126
127
128
129
130
131
132
133
134 protected Class loadClass( String name ) {
135
136 if ( name != null ) {
137 try {
138 return classLoader.loadClass(name);
139 } catch (Exception e) {
140 }
141 }
142 return null;
143 }
144
145
146
147
148
149
150 protected void configureDescriptor(AttributeDescriptor attributeDescriptor) {
151 Class beanClass = getBeanClass();
152 if ( beanClass != null ) {
153 String name = attributeDescriptor.getPropertyName();
154 try {
155 BeanInfo beanInfo;
156 if( getXMLIntrospector().getConfiguration().ignoreAllBeanInfo() ) {
157 beanInfo = Introspector.getBeanInfo( beanClass, Introspector.IGNORE_ALL_BEANINFO );
158 }
159 else {
160 beanInfo = Introspector.getBeanInfo( beanClass );
161 }
162 PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();
163 if ( descriptors != null ) {
164 for ( int i = 0, size = descriptors.length; i < size; i++ ) {
165 PropertyDescriptor descriptor = descriptors[i];
166 if ( name.equals( descriptor.getName() ) ) {
167 configureProperty( attributeDescriptor, descriptor );
168 getProcessedPropertyNameSet().add( name );
169 break;
170 }
171 }
172 }
173 } catch (Exception e) {
174 log.warn( "Caught introspection exception", e );
175 }
176 }
177 }
178
179
180
181
182
183
184
185 private void configureProperty(
186 AttributeDescriptor attributeDescriptor,
187 PropertyDescriptor propertyDescriptor ) {
188 Class type = propertyDescriptor.getPropertyType();
189 Method readMethod = propertyDescriptor.getReadMethod();
190 Method writeMethod = propertyDescriptor.getWriteMethod();
191
192 if ( readMethod == null ) {
193 log.trace( "No read method" );
194 return;
195 }
196
197 if ( log.isTraceEnabled() ) {
198 log.trace( "Read method=" + readMethod );
199 }
200
201
202 if ( getXMLIntrospector().isLoopType( type ) ) {
203 log.warn( "Using loop type for an attribute. Type = "
204 + type.getName() + " attribute: " + attributeDescriptor.getQualifiedName() );
205 }
206
207 log.trace( "Standard property" );
208 attributeDescriptor.setTextExpression( new MethodExpression( readMethod ) );
209
210 if ( writeMethod != null ) {
211 attributeDescriptor.setUpdater( new MethodUpdater( writeMethod ) );
212 }
213
214 attributeDescriptor.setPropertyName( propertyDescriptor.getName() );
215 attributeDescriptor.setPropertyType( type );
216
217
218
219
220 }
221
222 }