KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > fop > tools > DocumentReader


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

51 package org.apache.fop.tools;
52
53 import java.io.IOException JavaDoc;
54
55 // DOM
56
import org.w3c.dom.*;
57
58 // SAX
59
import org.xml.sax.*;
60 import org.xml.sax.helpers.AttributesImpl JavaDoc;
61
62 /**
63  * This presents a DOM as an XMLReader to make it easy to use a Document
64  * with a SAX-based implementation.
65  *
66  * @author Kelly A Campbell
67  *
68  */

69
70 public class DocumentReader implements XMLReader {
71
72     // //////////////////////////////////////////////////////////////////
73
// Configuration.
74
// //////////////////////////////////////////////////////////////////
75
private boolean _namespaces = true;
76     private boolean _namespace_prefixes = true;
77
78
79     /**
80      * Look up the value of a feature.
81      *
82      * <p>The feature name is any fully-qualified URI. It is
83      * possible for an XMLReader to recognize a feature name but
84      * to be unable to return its value; this is especially true
85      * in the case of an adapter for a SAX1 Parser, which has
86      * no way of knowing whether the underlying parser is
87      * performing validation or expanding external entities.</p>
88      *
89      * <p>All XMLReaders are required to recognize the
90      * http://xml.org/sax/features/namespaces and the
91      * http://xml.org/sax/features/namespace-prefixes feature names.</p>
92      *
93      * <p>Some feature values may be available only in specific
94      * contexts, such as before, during, or after a parse.</p>
95      *
96      * <p>Typical usage is something like this:</p>
97      *
98      * <pre>
99      * XMLReader r = new MySAXDriver();
100      *
101      * // try to activate validation
102      * try {
103      * r.setFeature("http://xml.org/sax/features/validation", true);
104      * } catch (SAXException e) {
105      * System.err.println("Cannot activate validation.");
106      * }
107      *
108      * // register event handlers
109      * r.setContentHandler(new MyContentHandler());
110      * r.setErrorHandler(new MyErrorHandler());
111      *
112      * // parse the first document
113      * try {
114      * r.parse("http://www.foo.com/mydoc.xml");
115      * } catch (IOException e) {
116      * System.err.println("I/O exception reading XML document");
117      * } catch (SAXException e) {
118      * System.err.println("XML exception reading document.");
119      * }
120      * </pre>
121      *
122      * <p>Implementors are free (and encouraged) to invent their own features,
123      * using names built on their own URIs.</p>
124      *
125      * @param name The feature name, which is a fully-qualified URI.
126      * @return The current state of the feature (true or false).
127      * @exception org.xml.sax.SAXNotRecognizedException When the
128      * XMLReader does not recognize the feature name.
129      * @exception org.xml.sax.SAXNotSupportedException When the
130      * XMLReader recognizes the feature name but
131      * cannot determine its value at this time.
132      * @see #setFeature
133      */

134     public boolean getFeature(String JavaDoc name)
135             throws SAXNotRecognizedException, SAXNotSupportedException {
136         if ("http://xml.org/sax/features/namespaces".equals(name)) {
137             return _namespaces;
138         } else if ("http://xml.org/sax/features/namespace-prefixes".equals(name)) {
139             return _namespace_prefixes;
140         } else {
141             throw new SAXNotRecognizedException("Feature '" + name
142                                                 + "' not recognized or supported by Document2SAXAdapter");
143         }
144
145     }
146
147
148
149     /**
150      * Set the state of a feature.
151      *
152      * <p>The feature name is any fully-qualified URI. It is
153      * possible for an XMLReader to recognize a feature name but
154      * to be unable to set its value; this is especially true
155      * in the case of an adapter for a SAX1 Parser,
156      * which has no way of affecting whether the underlying parser is
157      * validating, for example.</p>
158      *
159      * <p>All XMLReaders are required to support setting
160      * http://xml.org/sax/features/namespaces to true and
161      * http://xml.org/sax/features/namespace-prefixes to false.</p>
162      *
163      * <p>Some feature values may be immutable or mutable only
164      * in specific contexts, such as before, during, or after
165      * a parse.</p>
166      *
167      * @param name The feature name, which is a fully-qualified URI.
168      * @param state The requested state of the feature (true or false).
169      * @exception org.xml.sax.SAXNotRecognizedException When the
170      * XMLReader does not recognize the feature name.
171      * @exception org.xml.sax.SAXNotSupportedException When the
172      * XMLReader recognizes the feature name but
173      * cannot set the requested value.
174      * @see #getFeature
175      */

176     public void setFeature(String JavaDoc name, boolean value)
177             throws SAXNotRecognizedException, SAXNotSupportedException {
178         if ("http://xml.org/sax/features/namespaces".equals(name)) {
179             _namespaces = value;
180         } else if ("http://xml.org/sax/features/namespace-prefixes".equals(name)) {
181             _namespace_prefixes = value;
182         } else {
183             throw new SAXNotRecognizedException("Feature '" + name
184                                                 + "' not recognized or supported by Document2SAXAdapter");
185         }
186
187     }
188
189
190
191     /**
192      * Look up the value of a property.
193      *
194      * <p>The property name is any fully-qualified URI. It is
195      * possible for an XMLReader to recognize a property name but
196      * to be unable to return its state; this is especially true
197      * in the case of an adapter for a SAX1 Parser.</p>
198      *
199      * <p>XMLReaders are not required to recognize any specific
200      * property names, though an initial core set is documented for
201      * SAX2.</p>
202      *
203      * <p>Some property values may be available only in specific
204      * contexts, such as before, during, or after a parse.</p>
205      *
206      * <p>Implementors are free (and encouraged) to invent their own properties,
207      * using names built on their own URIs.</p>
208      *
209      * @param name The property name, which is a fully-qualified URI.
210      * @return The current value of the property.
211      * @exception org.xml.sax.SAXNotRecognizedException When the
212      * XMLReader does not recognize the property name.
213      * @exception org.xml.sax.SAXNotSupportedException When the
214      * XMLReader recognizes the property name but
215      * cannot determine its value at this time.
216      * @see #setProperty
217      */

218     public Object JavaDoc getProperty(String JavaDoc name)
219             throws SAXNotRecognizedException, SAXNotSupportedException {
220         throw new SAXNotRecognizedException("Property '" + name
221                                             + "' not recognized or supported by Document2SAXAdapter");
222     }
223
224
225
226     /**
227      * Set the value of a property.
228      *
229      * <p>The property name is any fully-qualified URI. It is
230      * possible for an XMLReader to recognize a property name but
231      * to be unable to set its value; this is especially true
232      * in the case of an adapter for a SAX1 Parser.</p>
233      *
234      * <p>XMLReaders are not required to recognize setting
235      * any specific property names, though a core set is provided with
236      * SAX2.</p>
237      *
238      * <p>Some property values may be immutable or mutable only
239      * in specific contexts, such as before, during, or after
240      * a parse.</p>
241      *
242      * <p>This method is also the standard mechanism for setting
243      * extended handlers.</p>
244      *
245      * @param name The property name, which is a fully-qualified URI.
246      * @param state The requested value for the property.
247      * @exception org.xml.sax.SAXNotRecognizedException When the
248      * XMLReader does not recognize the property name.
249      * @exception org.xml.sax.SAXNotSupportedException When the
250      * XMLReader recognizes the property name but
251      * cannot set the requested value.
252      */

253     public void setProperty(String JavaDoc name, Object JavaDoc value)
254             throws SAXNotRecognizedException, SAXNotSupportedException {
255         throw new SAXNotRecognizedException("Property '" + name
256                                             + "' not recognized or supported by Document2SAXAdapter");
257     }
258
259
260
261     // //////////////////////////////////////////////////////////////////
262
// Event handlers.
263
// //////////////////////////////////////////////////////////////////
264
private EntityResolver _entityResolver = null;
265     private DTDHandler _dtdHandler = null;
266     private ContentHandler _contentHandler = null;
267     private ErrorHandler _errorHandler = null;
268
269
270     /**
271      * Allow an application to register an entity resolver.
272      *
273      * <p>If the application does not register an entity resolver,
274      * the XMLReader will perform its own default resolution.</p>
275      *
276      * <p>Applications may register a new or different resolver in the
277      * middle of a parse, and the SAX parser must begin using the new
278      * resolver immediately.</p>
279      *
280      * @param resolver The entity resolver.
281      * @exception java.lang.NullPointerException If the resolver
282      * argument is null.
283      * @see #getEntityResolver
284      */

285     public void setEntityResolver(EntityResolver resolver) {
286         _entityResolver = resolver;
287     }
288
289
290
291     /**
292      * Return the current entity resolver.
293      *
294      * @return The current entity resolver, or null if none
295      * has been registered.
296      * @see #setEntityResolver
297      */

298     public EntityResolver getEntityResolver() {
299         return _entityResolver;
300     }
301
302
303
304     /**
305      * Allow an application to register a DTD event handler.
306      *
307      * <p>If the application does not register a DTD handler, all DTD
308      * events reported by the SAX parser will be silently ignored.</p>
309      *
310      * <p>Applications may register a new or different handler in the
311      * middle of a parse, and the SAX parser must begin using the new
312      * handler immediately.</p>
313      *
314      * @param handler The DTD handler.
315      * @exception java.lang.NullPointerException If the handler
316      * argument is null.
317      * @see #getDTDHandler
318      */

319     public void setDTDHandler(DTDHandler handler) {
320         _dtdHandler = handler;
321     }
322
323
324
325     /**
326      * Return the current DTD handler.
327      *
328      * @return The current DTD handler, or null if none
329      * has been registered.
330      * @see #setDTDHandler
331      */

332     public DTDHandler getDTDHandler() {
333         return _dtdHandler;
334     }
335
336
337
338     /**
339      * Allow an application to register a content event handler.
340      *
341      * <p>If the application does not register a content handler, all
342      * content events reported by the SAX parser will be silently
343      * ignored.</p>
344      *
345      * <p>Applications may register a new or different handler in the
346      * middle of a parse, and the SAX parser must begin using the new
347      * handler immediately.</p>
348      *
349      * @param handler The content handler.
350      * @exception java.lang.NullPointerException If the handler
351      * argument is null.
352      * @see #getContentHandler
353      */

354     public void setContentHandler(ContentHandler handler) {
355         _contentHandler = handler;
356     }
357
358
359
360     /**
361      * Return the current content handler.
362      *
363      * @return The current content handler, or null if none
364      * has been registered.
365      * @see #setContentHandler
366      */

367     public ContentHandler getContentHandler() {
368         return _contentHandler;
369     }
370
371
372
373     /**
374      * Allow an application to register an error event handler.
375      *
376      * <p>If the application does not register an error handler, all
377      * error events reported by the SAX parser will be silently
378      * ignored; however, normal processing may not continue. It is
379      * highly recommended that all SAX applications implement an
380      * error handler to avoid unexpected bugs.</p>
381      *
382      * <p>Applications may register a new or different handler in the
383      * middle of a parse, and the SAX parser must begin using the new
384      * handler immediately.</p>
385      *
386      * @param handler The error handler.
387      * @exception java.lang.NullPointerException If the handler
388      * argument is null.
389      * @see #getErrorHandler
390      */

391     public void setErrorHandler(ErrorHandler handler) {
392         _errorHandler = handler;
393     }
394
395     /**
396      * Return the current error handler.
397      *
398      * @return The current error handler, or null if none
399      * has been registered.
400      * @see #setErrorHandler
401      */

402     public ErrorHandler getErrorHandler() {
403         return _errorHandler;
404     }
405
406
407
408     // //////////////////////////////////////////////////////////////////
409
// Parsing.
410
// //////////////////////////////////////////////////////////////////
411

412     /**
413      * Parse an XML DOM document.
414      *
415      *
416      *
417      * @param source The input source for the top-level of the
418      * XML document.
419      * @exception org.xml.sax.SAXException Any SAX exception, possibly
420      * wrapping another exception.
421      * @exception java.io.IOException An IO exception from the parser,
422      * possibly from a byte stream or character stream
423      * supplied by the application.
424      * @see org.xml.sax.InputSource
425      * @see #parse(java.lang.String)
426      * @see #setEntityResolver
427      * @see #setDTDHandler
428      * @see #setContentHandler
429      * @see #setErrorHandler
430      */

431     public void parse(InputSource input) throws IOException JavaDoc, SAXException {
432         if (input instanceof DocumentInputSource) {
433             Document document = ((DocumentInputSource)input).getDocument();
434             if (_contentHandler == null) {
435                 throw new SAXException("ContentHandler is null. Please use setContentHandler()");
436             }
437
438             // refactored from org.apache.fop.apps.Driver
439
/* most of this code is modified from John Cowan's */
440
441             Node currentNode;
442             AttributesImpl JavaDoc currentAtts;
443
444             /* temporary array for making Strings into character arrays */
445             char[] array = null;
446
447             currentAtts = new AttributesImpl JavaDoc();
448
449             /* start at the document element */
450             currentNode = document;
451             while (currentNode != null) {
452                 switch (currentNode.getNodeType()) {
453                 case Node.DOCUMENT_NODE:
454                     _contentHandler.startDocument();
455                     break;
456                 case Node.CDATA_SECTION_NODE:
457                 case Node.TEXT_NODE:
458                     String JavaDoc data = currentNode.getNodeValue();
459                     int datalen = data.length();
460                     if (array == null || array.length < datalen) {
461                         /*
462                          * if the array isn't big enough, make a new
463                          * one
464                          */

465                         array = new char[datalen];
466                     }
467                     data.getChars(0, datalen, array, 0);
468                     _contentHandler.characters(array, 0, datalen);
469                     break;
470                 case Node.PROCESSING_INSTRUCTION_NODE:
471                     _contentHandler.processingInstruction(currentNode.getNodeName(),
472                                                           currentNode.getNodeValue());
473                     break;
474                 case Node.ELEMENT_NODE:
475                     NamedNodeMap map = currentNode.getAttributes();
476                     currentAtts.clear();
477                     for (int i = map.getLength() - 1; i >= 0; i--) {
478                         Attr att = (Attr)map.item(i);
479                         currentAtts.addAttribute(att.getNamespaceURI(),
480                                                  att.getLocalName(),
481                                                  att.getName(), "CDATA",
482                                                  att.getValue());
483                     }
484                     _contentHandler.startElement(currentNode.getNamespaceURI(),
485                                                  currentNode.getLocalName(),
486                                                  currentNode.getNodeName(),
487                                                  currentAtts);
488                     break;
489                 }
490
491                 Node nextNode = currentNode.getFirstChild();
492                 if (nextNode != null) {
493                     currentNode = nextNode;
494                     continue;
495                 }
496
497                 while (currentNode != null) {
498                     switch (currentNode.getNodeType()) {
499                     case Node.DOCUMENT_NODE:
500                         _contentHandler.endDocument();
501                         break;
502                     case Node.ELEMENT_NODE:
503                         _contentHandler.endElement(currentNode.getNamespaceURI(),
504                                                    currentNode.getLocalName(),
505                                                    currentNode.getNodeName());
506                         break;
507                     }
508
509                     nextNode = currentNode.getNextSibling();
510                     if (nextNode != null) {
511                         currentNode = nextNode;
512                         break;
513                     }
514
515                     currentNode = currentNode.getParentNode();
516                 }
517             }
518
519         } else {
520             throw new SAXException("DocumentReader only supports parsing of a DocumentInputSource");
521         }
522
523     }
524
525
526
527     /**
528      * DocumentReader requires a DocumentInputSource, so this is not
529      * implements and simply throws a SAXException. Use parse(DocumentInputSource)
530      * instead
531      *
532      * @param systemId The system identifier (URI).
533      * @exception org.xml.sax.SAXException Any SAX exception, possibly
534      * wrapping another exception.
535      * @exception java.io.IOException An IO exception from the parser,
536      * possibly from a byte stream or character stream
537      * supplied by the application.
538      * @see #parse(org.xml.sax.InputSource)
539      */

540     public void parse(String JavaDoc systemId) throws IOException JavaDoc, SAXException {
541         throw new SAXException("DocumentReader only supports parsing of a DocumentInputSource");
542     }
543
544 }
545
546
547
Popular Tags