KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cocoon > components > parser > JaxpParser


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.cocoon.components.parser;
17
18 import java.io.IOException JavaDoc;
19
20 import javax.xml.parsers.DocumentBuilder JavaDoc;
21 import javax.xml.parsers.DocumentBuilderFactory JavaDoc;
22 import javax.xml.parsers.ParserConfigurationException JavaDoc;
23 import javax.xml.parsers.SAXParserFactory JavaDoc;
24
25 import org.apache.avalon.excalibur.pool.Poolable;
26 import org.apache.avalon.framework.activity.Disposable;
27 import org.apache.avalon.framework.component.ComponentException;
28 import org.apache.avalon.framework.component.ComponentManager;
29 import org.apache.avalon.framework.component.Composable;
30 import org.apache.avalon.framework.parameters.ParameterException;
31 import org.apache.avalon.framework.parameters.Parameterizable;
32 import org.apache.avalon.framework.parameters.Parameters;
33 import org.apache.cocoon.components.resolver.Resolver;
34 import org.apache.cocoon.util.ClassUtils;
35 import org.apache.cocoon.xml.AbstractXMLProducer;
36 import org.w3c.dom.DOMImplementation JavaDoc;
37 import org.w3c.dom.Document JavaDoc;
38 import org.xml.sax.ErrorHandler JavaDoc;
39 import org.xml.sax.InputSource JavaDoc;
40 import org.xml.sax.SAXException JavaDoc;
41 import org.xml.sax.SAXParseException JavaDoc;
42 import org.xml.sax.XMLReader JavaDoc;
43
44 /**
45  * An XMLParser that is only dependant on JAXP 1.1 compliant parsers.
46  *
47  * The configuration can contain the following parameters :
48  * <ul>
49  * <li>validate (boolean, default = <code>false</code>) : should the parser
50  * validate parsed documents ?
51  * </li>
52  * <li>namespace-prefixes (boolean, default = <code>false</code>) : do we want
53  * namespaces declarations also as 'xmlns:' attributes ?<br>
54  * <i>Note</i> : setting this to <code>true</code> confuses some XSL
55  * processors (e.g. Saxon).
56  * </li>
57  * <li>reuse-parsers (boolean, default = <code>true</code>) : do we want to reuse
58  * parsers or create a new parser for each parse ?<br>
59  * <i>Note</i> : even if this parameter is <code>true</code>, parsers are not
60  * recycled in case of parsing errors : some parsers (e.g. Xerces) don't like
61  * to be reused after failure.
62  * </li>
63  * <li>sax-parser-factory (string, optional) : the name of the <code>SAXParserFactory</code>
64  * implementation class to be used instead of using the standard JAXP mechanism
65  * (<code>SAXParserFactory.newInstance()</code>). This allows to choose
66  * unambiguously the JAXP implementation to be used when several of them are
67  * available in the classpath.
68  * </li>
69  * <li>document-builder-factory (string, optional) : the name of the
70  * <code>DocumentBuilderFactory</code> implementation to be used (similar to
71  * <code>sax-parser-factory</code> for DOM).
72  * </li>
73  * </ul>
74  *
75  * @deprecated The Avalon XML Parser is now used inside Cocoon. This role
76  * will be removed in future releases.
77
78  * @author <a HREF="mailto:bloritsch@apache.org">Berin Loritsch</a>
79  * @author <a HREF="mailto:cziegeler@apache.org">Carsten Ziegeler</a>
80  * @author <a HREF="mailto:sylvain@apache.org">Sylvain Wallez</a>
81  * @version CVS $Id: JaxpParser.java 30932 2004-07-29 17:35:38Z vgritsenko $
82  */

83 public class JaxpParser extends AbstractXMLProducer
84 implements Parser, ErrorHandler JavaDoc, Composable, Parameterizable, Disposable, Poolable {
85
86     /** the SAX Parser factory */
87     protected SAXParserFactory JavaDoc factory;
88
89     /** the Document Builder factory */
90     protected DocumentBuilderFactory JavaDoc docFactory;
91
92     /** The SAX reader. It is created lazily by {@link #setupXMLReader()}
93         and cleared if a parsing error occurs. */

94     protected XMLReader JavaDoc reader;
95
96     /** The DOM builder. It is created lazily by {@link #setupDocumentBuilder()}
97         and cleared if a parsing error occurs. */

98     protected DocumentBuilder JavaDoc docBuilder;
99
100     /** the component manager */
101     protected ComponentManager manager;
102
103     /** the Entity Resolver */
104     protected Resolver resolver;
105
106     /** do we want namespaces also as attributes ? */
107     protected boolean nsPrefixes;
108
109     /** do we want to reuse parsers ? */
110     protected boolean reuseParsers;
111
112     /**
113      * Get the Entity Resolver from the component manager
114      */

115     public void compose(ComponentManager manager)
116     throws ComponentException {
117         this.manager = manager;
118         if ( manager.hasComponent( Resolver.ROLE ) ) {
119             if (getLogger().isDebugEnabled()) {
120                 getLogger().debug("Looking up " + Resolver.ROLE);
121             }
122             this.resolver = (Resolver)manager.lookup(Resolver.ROLE);
123         }
124     }
125
126     /**
127      * Dispose
128      */

129     public void dispose() {
130         if (this.manager != null) {
131             this.manager.release( this.resolver );
132         }
133     }
134
135     /**
136      * Configure
137      */

138     public void parameterize(Parameters params)
139     throws ParameterException {
140         // Validation and namespace prefixes parameters
141
boolean validate = params.getParameterAsBoolean("validate", false);
142         this.nsPrefixes = params.getParameterAsBoolean("namespace-prefixes", false);
143         this.reuseParsers = params.getParameterAsBoolean("reuse-parsers", true);
144
145         // Get the SAXFactory
146
String JavaDoc className = params.getParameter("sax-parser-factory", null);
147         if (className == null) {
148             factory = SAXParserFactory.newInstance();
149         } else {
150             // Will use specific class
151
try {
152                 Class JavaDoc factoryClass = ClassUtils.loadClass(className);
153                 factory = (SAXParserFactory JavaDoc)factoryClass.newInstance();
154             } catch(Exception JavaDoc e) {
155                 throw new ParameterException("Cannot load SAXParserFactory class " + className, e);
156             }
157         }
158         factory.setNamespaceAware(true);
159         factory.setValidating(validate);
160
161         // Get the DocumentFactory
162
className = params.getParameter("document-builder-factory", null);
163         if (className == null) {
164             this.docFactory = DocumentBuilderFactory.newInstance();
165         } else {
166             // Will use specific class
167
try {
168                 Class JavaDoc factoryClass = ClassUtils.loadClass(className);
169                 this.docFactory = (DocumentBuilderFactory JavaDoc)factoryClass.newInstance();
170             } catch(Exception JavaDoc e) {
171                 throw new ParameterException("Cannot load DocumentBuilderFactory class " + className, e);
172             }
173         }
174
175         docFactory.setNamespaceAware(true);
176         docFactory.setValidating(validate);
177     }
178
179     public void parse(InputSource JavaDoc in)
180     throws SAXException JavaDoc, IOException JavaDoc {
181         setupXMLReader();
182         try {
183             this.reader.setProperty("http://xml.org/sax/properties/lexical-handler", super.lexicalHandler);
184         } catch (SAXException JavaDoc e) {
185             getLogger().warn("SAX2 driver does not support property: "+
186                              "'http://xml.org/sax/properties/lexical-handler'");
187         }
188
189         this.reader.setErrorHandler(this);
190         this.reader.setContentHandler(super.contentHandler);
191         if(this.resolver != null) {
192             reader.setEntityResolver(this.resolver);
193         }
194
195         // Ensure we will use a fresh new parser at next parse in case of failure
196
XMLReader JavaDoc tmpReader = this.reader;
197         this.reader = null;
198
199         tmpReader.parse(in);
200
201         // Here, parsing was successful : restore this.reader
202
if (this.reuseParsers)
203             this.reader = tmpReader;
204     }
205
206     /**
207      * Create a new Document object.
208      */

209     public Document JavaDoc newDocument() {
210         setupDocumentBuilder();
211         return this.docBuilder.newDocument();
212     }
213
214     /**
215      * Create a new Document object with a specified DOCTYPE.
216      */

217     public Document JavaDoc newDocument(String JavaDoc name) {
218         return this.newDocument(name, null, null);
219     }
220
221     /**
222      * Create a new Document object with a specified DOCTYPE, public ID and
223      * system ID.
224      */

225     public Document JavaDoc newDocument(String JavaDoc name, String JavaDoc publicId, String JavaDoc systemId) {
226         setupDocumentBuilder();
227         // Fixme: is there a better way to achieve this?
228
DOMImplementation JavaDoc impl = this.docBuilder.newDocument().getImplementation();
229         return impl.createDocument(
230             null,
231             name,
232             impl.createDocumentType(name, publicId, systemId)
233         );
234     }
235
236     /**
237      * Parses a new Document object from the given InputSource.
238      */

239     public Document JavaDoc parseDocument(InputSource JavaDoc input) throws SAXException JavaDoc, IOException JavaDoc {
240         setupDocumentBuilder();
241
242         // Ensure we will use a fresh new parser at next parse in case of failure
243
DocumentBuilder JavaDoc tmpBuilder = this.docBuilder;
244         this.docBuilder = null;
245
246         Document JavaDoc result = tmpBuilder.parse(input);
247
248         // Here, parsing was successful : restore this.builder
249
if (this.reuseParsers)
250             this.docBuilder = tmpBuilder;
251
252         return result;
253     }
254
255     /**
256      * Creates a new <code>XMLReader</code> if needed.
257      */

258     protected void setupXMLReader() throws SAXException JavaDoc {
259         if (this.reader == null) {
260             // Create the XMLReader
261
try {
262                 this.reader = factory.newSAXParser().getXMLReader();
263                 this.reader.setFeature("http://xml.org/sax/features/namespace-prefixes", nsPrefixes);
264             } catch(Exception JavaDoc e) {
265                 getLogger().error("Cannot produce a valid parser", e);
266                 throw new SAXException JavaDoc("Cannot produce a valid parser", e);
267             }
268         }
269     }
270
271     /**
272      * Creates a new <code>DocumentBuilder</code> if needed.
273      */

274     protected void setupDocumentBuilder() {
275         if (this.docBuilder == null) {
276             try {
277                 this.docBuilder = this.docFactory.newDocumentBuilder();
278             } catch (ParserConfigurationException JavaDoc pce) {
279                 getLogger().error("Could not create DocumentBuilder", pce);
280                 throw new org.apache.avalon.framework.CascadingRuntimeException(
281                     "Could not create DocumentBuilder", pce);
282             }
283         }
284     }
285
286     /**
287      * Receive notification of a recoverable error.
288      */

289     public void error(SAXParseException JavaDoc e)
290     throws SAXException JavaDoc {
291         throw new SAXException JavaDoc("Error parsing "+e.getSystemId()+" (line "+
292                                e.getLineNumber()+" col. "+e.getColumnNumber()+
293                                "): "+e.getMessage(),e);
294     }
295
296     /**
297      * Receive notification of a fatal error.
298      */

299     public void fatalError(SAXParseException JavaDoc e)
300     throws SAXException JavaDoc {
301         throw new SAXException JavaDoc("Fatal error parsing "+e.getSystemId()+" (line "+
302                                e.getLineNumber()+" col. "+e.getColumnNumber()+
303                                "): "+e.getMessage(),e);
304     }
305
306     /**
307      * Receive notification of a warning.
308      */

309     public void warning(SAXParseException JavaDoc e)
310     throws SAXException JavaDoc {
311         throw new SAXException JavaDoc("Warning parsing "+e.getSystemId()+" (line "+
312                                e.getLineNumber()+" col. "+e.getColumnNumber()+
313                                "): "+e.getMessage(),e);
314     }
315 }
316
Popular Tags