KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > avalon > excalibur > xml > JaxpParser


1 /*
2  * Copyright (C) The Apache Software Foundation. All rights reserved.
3  *
4  * This software is published under the terms of the Apache Software License
5  * version 1.1, a copy of which has been included with this distribution in
6  * the LICENSE.txt file.
7  */

8 package org.apache.avalon.excalibur.xml;
9
10 import org.apache.avalon.excalibur.pool.Poolable;
11 import org.apache.avalon.framework.component.ComponentException;
12 import org.apache.avalon.framework.component.ComponentManager;
13 import org.apache.avalon.framework.component.Composable;
14 import org.apache.avalon.framework.logger.AbstractLogEnabled;
15 import org.apache.avalon.framework.parameters.Parameterizable;
16 import org.apache.avalon.framework.parameters.Parameters;
17 import org.w3c.dom.Document JavaDoc;
18 import org.xml.sax.*;
19 import org.xml.sax.ext.LexicalHandler JavaDoc;
20
21 import javax.xml.parsers.*;
22 import java.io.IOException JavaDoc;
23
24 /**
25  * An XMLParser that is only dependant on JAXP 1.1 compliant parsers.
26  *
27  * The configuration can contain the following parameters :
28  * <ul>
29  * <li>validate (boolean, default = <code>false</code>) : should the parser
30  * validate parsed documents ?
31  * </li>
32  * <li>namespace-prefixes (boolean, default = <code>false</code>) : do we want
33  * namespaces declarations also as 'xmlns:' attributes ?<br>
34  * <i>Note</i> : setting this to <code>true</code> confuses some XSL
35  * processors (e.g. Saxon).
36  * </li>
37  * <li>stop-on-warning (boolean, default = <code>true</code>) : should the parser
38  * stop parsing if a warning occurs ?
39  * </li>
40  * <li>stop-on-recoverable-error (boolean, default = <code>true</code>) : should the parser
41  * stop parsing if a recoverable error occurs ?
42  * </li>
43  * <li>reuse-parsers (boolean, default = <code>true</code>) : do we want to reuse
44  * parsers or create a new parser for each parse ?<br>
45  * <i>Note</i> : even if this parameter is <code>true</code>, parsers are not
46  * recycled in case of parsing errors : some parsers (e.g. Xerces) don't like
47  * to be reused after failure.
48  * </li>
49  * </ul>
50  *
51  * @author <a HREF="mailto:bloritsch@apache.org">Berin Loritsch</a>
52  * @author <a HREF="mailto:cziegeler@apache.org">Carsten Ziegeler</a>
53  * @author <a HREF="mailto:sylvain@apache.org">Sylvain Wallez</a>
54  * @version CVS $Revision: 1.9 $ $Date: 2002/01/03 07:18:28 $
55  */

56 public class JaxpParser
57 extends AbstractLogEnabled
58 implements Parser, ErrorHandler, Composable, Parameterizable, Poolable {
59
60     /** the SAX Parser factory */
61     protected SAXParserFactory factory;
62
63     /** the Document Builder factory */
64     protected DocumentBuilderFactory docFactory;
65
66     /** The SAX reader. It is created lazily by {@link #setupXMLReader()}
67         and cleared if a parsing error occurs. */

68     protected XMLReader reader;
69
70     /** The DOM builder. It is created lazily by {@link #setupDocumentBuilder()}
71         and cleared if a parsing error occurs. */

72     protected DocumentBuilder docBuilder;
73
74     /** the component manager */
75     protected ComponentManager manager;
76
77     /** the Entity Resolver */
78     protected EntityResolver resolver;
79
80     /** do we want namespaces also as attributes ? */
81     protected boolean nsPrefixes;
82
83     /** do we want to reuse parsers ? */
84     protected boolean reuseParsers;
85
86     /** do we stop on warnings ? */
87     protected boolean stopOnWarning;
88
89     /** do we stop on recoverable errors ? */
90     protected boolean stopOnRecoverableError;
91
92
93     /**
94      * Get the Entity Resolver from the component manager
95      */

96     public void compose(ComponentManager manager)
97     throws ComponentException
98     {
99         this.manager = manager;
100         if ( this.manager.hasComponent(EntityResolver.ROLE) )
101         {
102             this.resolver = (EntityResolver)this.manager.lookup(EntityResolver.ROLE);
103             if ( this.getLogger().isDebugEnabled() )
104             {
105                 this.getLogger().debug("JaxpParser: Using EntityResolver: " + this.resolver);
106             }
107         }
108     }
109
110     /**
111      * Configure
112      */

113     public void parameterize( Parameters params )
114     {
115         // Validation and namespace prefixes parameters
116
boolean validate = params.getParameterAsBoolean("validate", false);
117         this.nsPrefixes = params.getParameterAsBoolean("namespace-prefixes", false);
118         this.reuseParsers = params.getParameterAsBoolean("reuse-parsers", true);
119         this.stopOnWarning = params.getParameterAsBoolean("stop-on-warning", true);
120         this.stopOnRecoverableError = params.getParameterAsBoolean("stop-on-recoverable-error", true);
121
122         this.factory = SAXParserFactory.newInstance();
123         this.factory.setNamespaceAware(true);
124         this.factory.setValidating(validate);
125
126         this.docFactory = DocumentBuilderFactory.newInstance();
127         docFactory.setNamespaceAware(true);
128         docFactory.setValidating(validate);
129         if ( this.getLogger().isDebugEnabled() )
130         {
131             this.getLogger().debug("JaxpParser: validating: " + validate +
132                                    ", namespace-prefixes: " + this.nsPrefixes +
133                                    ", reuse parser: " + this.reuseParsers +
134                                    ", stop on warning: " + this.stopOnWarning +
135                                    ", stop on recoverable-error: " + this.stopOnRecoverableError);
136         }
137     }
138
139     public void parse(InputSource in, ContentHandler consumer)
140     throws SAXException, IOException JavaDoc
141     {
142         this.setupXMLReader();
143
144         // Ensure we will use a fresh new parser at next parse in case of failure
145
XMLReader tmpReader = this.reader;
146         this.reader = null;
147
148         try {
149             if (consumer instanceof LexicalHandler JavaDoc)
150             {
151                 tmpReader.setProperty("http://xml.org/sax/properties/lexical-handler",
152                         (LexicalHandler JavaDoc)consumer);
153             }
154         }
155         catch (SAXException e)
156         {
157             this.getLogger().warn("SAX2 driver does not support property: "+
158                                   "'http://xml.org/sax/properties/lexical-handler'");
159         }
160
161         tmpReader.setErrorHandler( this );
162         tmpReader.setContentHandler( consumer );
163         if ( null != this.resolver )
164         {
165             tmpReader.setEntityResolver( this.resolver );
166         }
167
168
169         tmpReader.parse(in);
170
171         // Here, parsing was successful : restore this.reader
172
if ( this.reuseParsers )
173             this.reader = tmpReader;
174     }
175
176
177     /**
178      * Parses a new Document object from the given InputSource.
179      */

180     public Document JavaDoc parseDocument(InputSource input)
181     throws SAXException, IOException JavaDoc
182     {
183         this.setupDocumentBuilder();
184
185         // Ensure we will use a fresh new parser at next parse in case of failure
186
DocumentBuilder tmpBuilder = this.docBuilder;
187         this.docBuilder = null;
188
189         if ( null != this.resolver )
190         {
191             tmpBuilder.setEntityResolver(this.resolver);
192         }
193
194         Document JavaDoc result = tmpBuilder.parse(input);
195
196         // Here, parsing was successful : restore this.builder
197
if ( this.reuseParsers)
198             this.docBuilder = tmpBuilder;
199
200         return result;
201     }
202
203     /**
204      * Creates a new <code>XMLReader</code> if needed.
205      */

206     protected void setupXMLReader()
207     throws SAXException
208     {
209         if ( null == this.reader )
210         {
211             // Create the XMLReader
212
try
213             {
214                 this.reader = factory.newSAXParser().getXMLReader();
215             }
216             catch( ParserConfigurationException pce )
217             {
218                 throw new SAXException( "Cannot produce a valid parser", pce );
219             }
220             if ( this.nsPrefixes ) {
221                 try
222                 {
223                     this.reader.setFeature("http://xml.org/sax/features/namespace-prefixes", this.nsPrefixes);
224                 }
225                 catch ( SAXException e )
226                 {
227                     this.getLogger().warn("SAX2 XMLReader does not support setting feature: "+
228                                       "'http://xml.org/sax/features/namespace-prefixes'");
229                 }
230             }
231         }
232     }
233
234     /**
235      * Creates a new <code>DocumentBuilder</code> if needed.
236      */

237     protected void setupDocumentBuilder()
238     throws SAXException
239     {
240         if ( null == this.docBuilder )
241         {
242             try
243             {
244                 this.docBuilder = this.docFactory.newDocumentBuilder();
245             }
246             catch (ParserConfigurationException pce)
247             {
248                 throw new SAXException( "Could not create DocumentBuilder", pce );
249             }
250         }
251     }
252
253     /**
254      * Receive notification of a recoverable error.
255      */

256     public void error( SAXParseException e )
257     throws SAXException
258     {
259         final String JavaDoc msg = "Error parsing "+e.getSystemId()+" (line "+
260                            e.getLineNumber()+" col. "+e.getColumnNumber()+
261                            "): "+e.getMessage();
262         if ( this.stopOnRecoverableError )
263         {
264             throw new SAXException( msg, e );
265         }
266         this.getLogger().error( msg, e );
267     }
268
269     /**
270      * Receive notification of a fatal error.
271      */

272     public void fatalError( SAXParseException e )
273     throws SAXException
274     {
275         throw new SAXException("Fatal error parsing "+e.getSystemId()+" (line "+
276                                e.getLineNumber()+" col. "+e.getColumnNumber()+
277                                "): "+e.getMessage(),e);
278     }
279
280     /**
281      * Receive notification of a warning.
282      */

283     public void warning( SAXParseException e )
284     throws SAXException
285     {
286         final String JavaDoc msg = "Warning parsing "+e.getSystemId()+" (line "+
287                            e.getLineNumber()+" col. "+e.getColumnNumber()+
288                            "): "+e.getMessage();
289         if ( this.stopOnWarning )
290         {
291             throw new SAXException( msg, e );
292         }
293         this.getLogger().warn( msg, e );
294     }
295 }
296
Popular Tags