KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > avalon > framework > configuration > NamespacedSAXConfigurationHandler


1 /* ====================================================================
2  * The Apache Software License, Version 1.1
3  *
4  * Copyright (c) 1997-2003 The Apache Software Foundation. All rights
5  * reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  *
14  * 2. Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in
16  * the documentation and/or other materials provided with the
17  * distribution.
18  *
19  * 3. The end-user documentation included with the redistribution,
20  * if any, must include the following acknowledgment:
21  * "This product includes software developed by the
22  * Apache Software Foundation (http://www.apache.org/)."
23  * Alternately, this acknowledgment may appear in the software
24  * itself, if and wherever such third-party acknowledgments
25  * normally appear.
26  *
27  * 4. The names "Jakarta", "Avalon", and "Apache Software Foundation"
28  * must not be used to endorse or promote products derived from this
29  * software without prior written permission. For written
30  * permission, please contact apache@apache.org.
31  *
32  * 5. Products derived from this software may not be called "Apache",
33  * nor may "Apache" appear in their name, without prior written
34  * permission of the Apache Software Foundation.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
40  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47  * SUCH DAMAGE.
48  * ====================================================================
49  *
50  * This software consists of voluntary contributions made by many
51  * individuals on behalf of the Apache Software Foundation. For more
52  * information on the Apache Software Foundation, please see
53  * <http://www.apache.org/>.
54  */

55 package org.apache.avalon.framework.configuration;
56
57 import java.util.ArrayList JavaDoc;
58 import java.util.BitSet JavaDoc;
59 import java.util.Iterator JavaDoc;
60 import org.xml.sax.Attributes JavaDoc;
61 import org.xml.sax.Locator JavaDoc;
62 import org.xml.sax.SAXException JavaDoc;
63 import org.xml.sax.SAXParseException JavaDoc;
64 import org.xml.sax.helpers.AttributesImpl JavaDoc;
65 import org.xml.sax.helpers.NamespaceSupport JavaDoc;
66
67 /**
68  * A SAXConfigurationHandler helps build Configurations out of sax events,
69  * including namespace information.
70  *
71  * @author <a HREF="mailto:dev@avalon.apache.org">Avalon Development Team</a>
72  * @version CVS $Revision: 1.17 $ $Date: 2003/02/11 15:58:39 $
73  */

74 public class NamespacedSAXConfigurationHandler
75     extends SAXConfigurationHandler
76 {
77     /**
78      * Likely number of nested configuration items. If more is
79      * encountered the lists will grow automatically.
80      */

81     private static final int EXPECTED_DEPTH = 5;
82     private final ArrayList JavaDoc m_elements = new ArrayList JavaDoc( EXPECTED_DEPTH );
83     private final ArrayList JavaDoc m_prefixes = new ArrayList JavaDoc( EXPECTED_DEPTH );
84     private final ArrayList JavaDoc m_values = new ArrayList JavaDoc( EXPECTED_DEPTH );
85     /**
86      * Contains true at index n if space in the configuration with
87      * depth n is to be preserved.
88      */

89     private final BitSet JavaDoc m_preserveSpace = new BitSet JavaDoc();
90     private Configuration m_configuration;
91     private Locator JavaDoc m_locator;
92     private NamespaceSupport JavaDoc m_namespaceSupport = new NamespaceSupport JavaDoc();
93
94     /**
95      * Get the configuration object that was built.
96      *
97      * @return a <code>Configuration</code> object
98      */

99     public Configuration getConfiguration()
100     {
101         return m_configuration;
102     }
103
104     /**
105      * Clears all data from this configuration handler.
106      */

107     public void clear()
108     {
109         m_elements.clear();
110         Iterator JavaDoc i = m_prefixes.iterator();
111         while( i.hasNext() )
112         {
113             ( (ArrayList JavaDoc)i.next() ).clear();
114         }
115         m_prefixes.clear();
116         m_values.clear();
117         m_locator = null;
118     }
119
120     /**
121      * Set the document <code>Locator</code> to use.
122      *
123      * @param locator a <code>Locator</code> value
124      */

125     public void setDocumentLocator( final Locator JavaDoc locator )
126     {
127         m_locator = locator;
128     }
129
130     /**
131      * Handling hook for starting the document parsing.
132      *
133      * @throws SAXException if an error occurs
134      */

135     public void startDocument()
136         throws SAXException JavaDoc
137     {
138         m_namespaceSupport.reset();
139         super.startDocument();
140     }
141
142     /**
143      * Handling hook for ending the document parsing.
144      *
145      * @throws SAXException if an error occurs
146      */

147     public void endDocument()
148         throws SAXException JavaDoc
149     {
150         super.endDocument();
151         m_namespaceSupport.reset();
152     }
153
154     /**
155      * Handling hook for character data.
156      *
157      * @param ch a <code>char[]</code> of data
158      * @param start offset in the character array from which to start reading
159      * @param end length of character data
160      * @throws SAXException if an error occurs
161      */

162     public void characters( final char[] ch, int start, int end )
163         throws SAXException JavaDoc
164     {
165         // it is possible to play micro-optimization here by doing
166
// manual trimming and thus preserve some precious bits
167
// of memory, but it's really not important enough to justify
168
// resulting code complexity
169
final int depth = m_values.size() - 1;
170         final StringBuffer JavaDoc valueBuffer = (StringBuffer JavaDoc)m_values.get( depth );
171         valueBuffer.append( ch, start, end );
172     }
173
174     /**
175      * Handling hook for finishing parsing of an element.
176      *
177      * @param namespaceURI a <code>String</code> value
178      * @param localName a <code>String</code> value
179      * @param rawName a <code>String</code> value
180      * @throws SAXException if an error occurs
181      */

182     public void endElement( final String JavaDoc namespaceURI,
183                             final String JavaDoc localName,
184                             final String JavaDoc rawName )
185         throws SAXException JavaDoc
186     {
187         final int depth = m_elements.size() - 1;
188         final DefaultConfiguration finishedConfiguration =
189             (DefaultConfiguration)m_elements.remove( depth );
190         final String JavaDoc accumulatedValue =
191             ( (StringBuffer JavaDoc)m_values.remove( depth ) ).toString();
192         final ArrayList JavaDoc prefixes = (ArrayList JavaDoc)m_prefixes.remove( depth );
193
194         final Iterator JavaDoc i = prefixes.iterator();
195         while( i.hasNext() )
196         {
197             endPrefixMapping( (String JavaDoc)i.next() );
198         }
199         prefixes.clear();
200
201         if( finishedConfiguration.getChildren().length == 0 )
202         {
203             // leaf node
204
String JavaDoc finishedValue;
205             if( m_preserveSpace.get( depth ) )
206             {
207                 finishedValue = accumulatedValue;
208             }
209             else if( 0 == accumulatedValue.length() )
210             {
211                 finishedValue = null;
212             }
213             else
214             {
215                 finishedValue = accumulatedValue.trim();
216             }
217             finishedConfiguration.setValue( finishedValue );
218         }
219         else
220         {
221             final String JavaDoc trimmedValue = accumulatedValue.trim();
222             if( trimmedValue.length() > 0 )
223             {
224                 throw new SAXException JavaDoc( "Not allowed to define mixed content in the "
225                                         + "element " + finishedConfiguration.getName() + " at "
226                                         + finishedConfiguration.getLocation() );
227             }
228         }
229
230         if( 0 == depth )
231         {
232             m_configuration = finishedConfiguration;
233         }
234
235         m_namespaceSupport.popContext();
236     }
237
238     /**
239      * Create a new <code>DefaultConfiguration</code> with the specified
240      * local name, namespace, and location.
241      *
242      * @param localName a <code>String</code> value
243      * @param namespaceURI a <code>String</code> value
244      * @param location a <code>String</code> value
245      * @return a <code>DefaultConfiguration</code> value
246      */

247     protected DefaultConfiguration createConfiguration( final String JavaDoc localName,
248                                                         final String JavaDoc namespaceURI,
249                                                         final String JavaDoc location )
250     {
251         String JavaDoc prefix = m_namespaceSupport.getPrefix( namespaceURI );
252         if( prefix == null )
253         {
254             prefix = "";
255         }
256         return new DefaultConfiguration( localName, location, namespaceURI, prefix );
257     }
258
259     /**
260      * Handling hook for starting parsing of an element.
261      *
262      * @param namespaceURI a <code>String</code> value
263      * @param localName a <code>String</code> value
264      * @param rawName a <code>String</code> value
265      * @param attributes an <code>Attributes</code> value
266      * @throws SAXException if an error occurs
267      */

268     public void startElement( final String JavaDoc namespaceURI,
269                               final String JavaDoc localName,
270                               final String JavaDoc rawName,
271                               final Attributes JavaDoc attributes )
272         throws SAXException JavaDoc
273     {
274         m_namespaceSupport.pushContext();
275         final DefaultConfiguration configuration =
276             createConfiguration( localName, namespaceURI, getLocationString() );
277         // depth of new configuration (not decrementing here, configuration
278
// is to be added)
279
final int depth = m_elements.size();
280         boolean preserveSpace = false; // top level element trims space by default
281

282         if( depth > 0 )
283         {
284             final DefaultConfiguration parent =
285                 (DefaultConfiguration)m_elements.get( depth - 1 );
286             parent.addChild( configuration );
287             // inherits parent's space preservation policy
288
preserveSpace = m_preserveSpace.get( depth - 1 );
289         }
290
291         m_elements.add( configuration );
292         m_values.add( new StringBuffer JavaDoc() );
293
294         final ArrayList JavaDoc prefixes = new ArrayList JavaDoc();
295         AttributesImpl JavaDoc componentAttr = new AttributesImpl JavaDoc();
296
297         for( int i = 0; i < attributes.getLength(); i++ )
298         {
299             if( attributes.getQName( i ).startsWith( "xmlns" ) )
300             {
301                 prefixes.add( attributes.getLocalName( i ) );
302                 this.startPrefixMapping( attributes.getLocalName( i ),
303                                          attributes.getValue( i ) );
304             }
305             else if( attributes.getQName( i ).equals( "xml:space" ) )
306             {
307                 preserveSpace = attributes.getValue( i ).equals( "preserve" );
308             }
309             else
310             {
311                 componentAttr.addAttribute( attributes.getURI( i ),
312                                             attributes.getLocalName( i ),
313                                             attributes.getQName( i ),
314                                             attributes.getType( i ),
315                                             attributes.getValue( i ) );
316             }
317         }
318
319         if( preserveSpace )
320         {
321             m_preserveSpace.set( depth );
322         }
323         else
324         {
325             m_preserveSpace.clear( depth );
326         }
327
328         m_prefixes.add( prefixes );
329
330         final int attributesSize = componentAttr.getLength();
331
332         for( int i = 0; i < attributesSize; i++ )
333         {
334             final String JavaDoc name = componentAttr.getQName( i );
335             final String JavaDoc value = componentAttr.getValue( i );
336             configuration.setAttribute( name, value );
337         }
338     }
339
340     /**
341      * This just throws an exception on a parse error.
342      * @param exception the parse error
343      * @throws SAXException if an error occurs
344      */

345     public void error( final SAXParseException JavaDoc exception )
346         throws SAXException JavaDoc
347     {
348         throw exception;
349     }
350
351     /**
352      * This just throws an exception on a parse error.
353      * @param exception the parse error
354      * @throws SAXException if an error occurs
355      */

356     public void warning( final SAXParseException JavaDoc exception )
357         throws SAXException JavaDoc
358     {
359         throw exception;
360     }
361
362     /**
363      * This just throws an exception on a parse error.
364      * @param exception the parse error
365      * @throws SAXException if an error occurs
366      */

367     public void fatalError( final SAXParseException JavaDoc exception )
368         throws SAXException JavaDoc
369     {
370         throw exception;
371     }
372
373     /**
374      * Returns a string showing the current system ID, line number and column number.
375      *
376      * @return a <code>String</code> value
377      */

378     protected String JavaDoc getLocationString()
379     {
380         if( null == m_locator )
381         {
382             return "Unknown";
383         }
384         else
385         {
386             return
387                 m_locator.getSystemId() + ":"
388                 + m_locator.getLineNumber() + ":"
389                 + m_locator.getColumnNumber();
390         }
391     }
392
393     /**
394      * Handling hook for starting prefix mapping.
395      *
396      * @param prefix a <code>String</code> value
397      * @param uri a <code>String</code> value
398      * @throws SAXException if an error occurs
399      */

400     public void startPrefixMapping( String JavaDoc prefix, String JavaDoc uri )
401         throws SAXException JavaDoc
402     {
403         m_namespaceSupport.declarePrefix( prefix, uri );
404         super.startPrefixMapping( prefix, uri );
405     }
406 }
407
Popular Tags