KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javolution > xml > sax > XMLReaderImpl


1 /*
2  * Javolution - Java(TM) Solution for Real-Time and Embedded Systems
3  * Copyright (C) 2005 - Javolution (http://javolution.org/)
4  * All rights reserved.
5  *
6  * Permission to use, copy, modify, and distribute this software is
7  * freely granted, provided that this notice is preserved.
8  */

9 package javolution.xml.sax;
10
11 import j2me.lang.CharSequence;
12 import j2me.lang.UnsupportedOperationException;
13
14 import java.io.IOException JavaDoc;
15 import java.io.InputStream JavaDoc;
16 import java.io.Reader JavaDoc;
17
18 import javolution.lang.Reflection;
19 import javolution.lang.Reusable;
20 import javolution.text.CharArray;
21 import javolution.xml.stream.XMLStreamConstants;
22 import javolution.xml.stream.XMLStreamException;
23 import javolution.xml.stream.XMLStreamReaderImpl;
24
25 import org.xml.sax.DTDHandler JavaDoc;
26 import org.xml.sax.EntityResolver JavaDoc;
27 import org.xml.sax.ErrorHandler JavaDoc;
28 import org.xml.sax.InputSource JavaDoc;
29 import org.xml.sax.SAXException JavaDoc;
30 import org.xml.sax.SAXNotRecognizedException JavaDoc;
31 import org.xml.sax.SAXNotSupportedException JavaDoc;
32
33 /**
34  * <p> This class provides a real-time SAX2-like XML parser; this parser is
35  * <i>extremely</i> fast and <b>does not create temporary objects</b>
36  * (no garbage generated and no GC interruption).</p>
37  *
38  * <p> The parser is implemented as a SAX2 wrapper around
39  * {@link XMLStreamReaderImpl} and share the same characteristics.</p>
40  *
41  * <p><i> Note: This parser is a <b>SAX2-like</b> parser with the
42  * <code>java.lang.String</code> type replaced by
43  * {@link CharArray}/{@link CharSequence} in the {@link ContentHandler},
44  * {@link Attributes} interfaces and {@link DefaultHandler} base class.
45  * If a standard SAX2 or JAXP parser is required, you may consider using
46  * the wrapping class {@link SAX2ReaderImpl}. Fast but not as fast as
47  * <code>java.lang.String</code> instances are dynamically allocated
48  * while parsing.</i></p>
49  *
50  * @author <a HREF="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
51  * @version 4.0, June 16, 2006
52  */

53 public class XMLReaderImpl implements XMLReader, Reusable {
54
55     /**
56      * Holds the default handler instance.
57      */

58     private static DefaultHandler DEFAULT_HANDLER = new DefaultHandler();
59
60     /**
61      * Holds the content handler.
62      */

63     private ContentHandler _contentHandler;
64
65     /**
66      * Holds the error handler.
67      */

68     private ErrorHandler JavaDoc _errorHandler;
69
70     /**
71      * Holds reusable StAX reader.
72      */

73     private final XMLStreamReaderImpl _xmlReader = new XMLStreamReaderImpl();
74
75     /**
76      * Default constructor.
77      */

78     public XMLReaderImpl() {
79         // Sets default handlers.
80
setContentHandler(DEFAULT_HANDLER);
81         setErrorHandler(DEFAULT_HANDLER);
82     }
83
84     /**
85      * Parses an XML document from the specified input stream
86      * (encoding retrieved from input source and the XML prolog if any).
87      *
88      * @param in the input stream with unknown encoding.
89      * @throws org.xml.sax.SAXException any SAX exception, possibly
90      * wrapping another exception.
91      * @throws IOException an IO exception from the parser,
92      * possibly from a byte stream or character stream
93      * supplied by the application.
94      */

95     public void parse(InputStream JavaDoc in) throws IOException JavaDoc, SAXException JavaDoc {
96         try {
97             _xmlReader.setInput(in);
98             parseAll();
99         } catch (XMLStreamException e) {
100             if (e.getNestedException() instanceof IOException JavaDoc)
101                 throw (IOException JavaDoc)e.getNestedException();
102             throw new SAXException JavaDoc(e);
103         } finally {
104             _xmlReader.reset();
105         }
106     }
107     
108     /**
109      * Parses an XML document from the specified input stream and encoding.
110      *
111      * @param in the input stream.
112      * @param encoding the input stream encoding.
113      * @throws org.xml.sax.SAXException any SAX exception, possibly
114      * wrapping another exception.
115      * @throws IOException an IO exception from the parser,
116      * possibly from a byte stream or character stream
117      * supplied by the application.
118      */

119     public void parse(InputStream JavaDoc in, String JavaDoc encoding) throws IOException JavaDoc, SAXException JavaDoc {
120         try {
121             _xmlReader.setInput(in, encoding);
122             parseAll();
123         } catch (XMLStreamException e) {
124             if (e.getNestedException() instanceof IOException JavaDoc)
125                 throw (IOException JavaDoc)e.getNestedException();
126             throw new SAXException JavaDoc(e);
127         } finally {
128             _xmlReader.reset();
129         }
130     }
131     
132     /**
133      * Parses an XML document using the specified reader.
134      *
135      * @param reader the document reader.
136      * @throws SAXException any SAX exception, possibly wrapping another
137      * exception.
138      * @throws IOException an IO exception from the parser, possibly from
139      * a byte stream or character stream supplied by the application.
140      * @see javolution.io.UTF8StreamReader
141      * @see javolution.io.UTF8ByteBufferReader
142      * @see javolution.io.CharSequenceReader
143      */

144     public void parse(Reader JavaDoc reader) throws IOException JavaDoc, SAXException JavaDoc {
145         try {
146             _xmlReader.setInput(reader);
147             parseAll();
148         } catch (XMLStreamException e) {
149             if (e.getNestedException() instanceof IOException JavaDoc)
150                 throw (IOException JavaDoc)e.getNestedException();
151             throw new SAXException JavaDoc(e);
152         } finally {
153             _xmlReader.reset();
154         }
155     }
156
157     // Implements XMLReader interface.
158
public void parse(InputSource JavaDoc input) throws IOException JavaDoc, SAXException JavaDoc {
159         Reader JavaDoc reader = input.getCharacterStream();
160         if (reader != null) {
161             parse(reader);
162         } else {
163             InputStream JavaDoc inStream = input.getByteStream();
164             if (inStream != null) {
165                 parse(inStream, input.getEncoding());
166             } else {
167                 parse(input.getSystemId());
168             }
169         }
170     }
171
172     // Implements XMLReader interface.
173
public void parse(String JavaDoc systemId) throws IOException JavaDoc, SAXException JavaDoc {
174         InputStream JavaDoc inStream;
175         try {
176             Object JavaDoc url = NEW_URL.newInstance(systemId);
177             inStream = (InputStream JavaDoc) OPEN_STREAM.invoke(url);
178         } catch (Exception JavaDoc urlException) { // Try as filename.
179
try {
180                 inStream = (InputStream JavaDoc) NEW_FILE_INPUT_STREAM.newInstance(systemId);
181             } catch (Exception JavaDoc fileException) {
182                 throw new UnsupportedOperationException JavaDoc("Cannot parse "
183                         + systemId);
184             }
185         }
186         parse(inStream);
187     }
188
189     private static final Reflection.Constructor NEW_URL = Reflection
190             .getConstructor("java.net.URL(j2me.lang.String)");
191
192     private static final Reflection.Method OPEN_STREAM = Reflection
193             .getMethod("java.net.URL.openStream()");
194
195     private static final Reflection.Constructor NEW_FILE_INPUT_STREAM = Reflection
196             .getConstructor("j2me.io.FileInputStream(j2me.lang.String)");
197
198     // Implements XMLReader interface.
199
public void setContentHandler(ContentHandler handler) {
200         if (handler != null) {
201             _contentHandler = handler;
202         } else {
203             throw new NullPointerException JavaDoc();
204         }
205     }
206
207     // Implements XMLReader interface.
208
public ContentHandler getContentHandler() {
209         return (_contentHandler == DEFAULT_HANDLER) ? null : _contentHandler;
210     }
211
212     // Implements XMLReader interface.
213
public void setErrorHandler(ErrorHandler JavaDoc handler) {
214         if (handler != null) {
215             _errorHandler = handler;
216         } else {
217             throw new NullPointerException JavaDoc();
218         }
219     }
220
221     // Implements XMLReader interface.
222
public ErrorHandler JavaDoc getErrorHandler() {
223         return (_errorHandler == DEFAULT_HANDLER) ? null : _errorHandler;
224     }
225
226     // Implements XMLReader interface.
227
public boolean getFeature(String JavaDoc name) throws SAXNotRecognizedException JavaDoc,
228             SAXNotSupportedException JavaDoc {
229         if (name.equals("http://xml.org/sax/features/namespaces")) {
230             return true;
231         } else if (name
232                 .equals("http://xml.org/sax/features/namespace-prefixes")) {
233             return true;
234         } else {
235             throw new SAXNotRecognizedException JavaDoc("Feature " + name
236                     + " not recognized");
237         }
238     }
239
240     public void setFeature(String JavaDoc name, boolean value)
241             throws SAXNotRecognizedException JavaDoc, SAXNotSupportedException JavaDoc {
242         if (name.equals("http://xml.org/sax/features/namespaces")
243                 || name
244                         .equals("http://xml.org/sax/features/namespace-prefixes")) {
245             return; // Ignores, these features are always set.
246
} else {
247             throw new SAXNotRecognizedException JavaDoc("Feature " + name
248                     + " not recognized");
249         }
250     }
251
252     public Object JavaDoc getProperty(String JavaDoc name) throws SAXNotRecognizedException JavaDoc,
253             SAXNotSupportedException JavaDoc {
254         throw new SAXNotRecognizedException JavaDoc("Property " + name
255                 + " not recognized");
256     }
257
258     public void setProperty(String JavaDoc name, Object JavaDoc value)
259             throws SAXNotRecognizedException JavaDoc, SAXNotSupportedException JavaDoc {
260         throw new SAXNotRecognizedException JavaDoc("Property " + name
261                 + " not recognized");
262     }
263
264     public void setEntityResolver(EntityResolver JavaDoc resolver) {
265         _entityResolver = resolver;
266     }
267
268     private EntityResolver JavaDoc _entityResolver;
269
270     public EntityResolver JavaDoc getEntityResolver() {
271         return _entityResolver;
272     }
273
274     public void setDTDHandler(DTDHandler JavaDoc handler) {
275         _dtdHandler = handler;
276     }
277
278     private DTDHandler JavaDoc _dtdHandler;
279
280     public DTDHandler JavaDoc getDTDHandler() {
281         return _dtdHandler;
282     }
283
284     // Implements Reusable.
285
public void reset() {
286         setContentHandler(DEFAULT_HANDLER);
287         setErrorHandler(DEFAULT_HANDLER);
288         _xmlReader.reset();
289     }
290
291     /**
292      * Parses the whole document using the real-time pull parser.
293      *
294      * @throws SAXException any SAX exception, possibly wrapping another
295      * exception.
296      * @throws IOException an IO exception from the parser, possibly from
297      * a byte stream or character stream supplied by the application.
298      */

299     private void parseAll() throws XMLStreamException, SAXException JavaDoc {
300         int eventType = _xmlReader.getEventType();
301         if (eventType != XMLStreamConstants.START_DOCUMENT)
302             throw new SAXException JavaDoc("Currently parsing");
303         _contentHandler.startDocument();
304
305         boolean doContinue = true;
306         while (doContinue) {
307             CharArray uri, localName, qName, prefix, text;
308             switch (_xmlReader.next()) {
309             case XMLStreamConstants.START_ELEMENT:
310
311                 // Start prefix mapping.
312
for (int i = 0, count = _xmlReader.getNamespaceCount(); i < count; i++) {
313                     prefix = _xmlReader.getNamespacePrefix(i);
314                     prefix = (prefix == null) ? NO_CHAR : prefix; // Default namespace is ""
315
uri = _xmlReader.getNamespaceURI(i);
316                     _contentHandler.startPrefixMapping(prefix, uri);
317                 }
318
319                 // Start element.
320
uri = _xmlReader.getNamespaceURI();
321                 uri = (uri == null) ? NO_CHAR : uri;
322                 localName = _xmlReader.getLocalName();
323                 qName = _xmlReader.getQName();
324                 _contentHandler.startElement(uri, localName, qName, _xmlReader
325                         .getAttributes());
326                 break;
327
328             case XMLStreamConstants.END_ELEMENT:
329
330                 // End element.
331
uri = _xmlReader.getNamespaceURI();
332                 uri = (uri == null) ? NO_CHAR : uri;
333                 localName = _xmlReader.getLocalName();
334                 qName = _xmlReader.getQName();
335                 _contentHandler.endElement(uri, localName, qName);
336
337                 // End prefix mapping.
338
for (int i = 0, count = _xmlReader.getNamespaceCount(); i < count; i++) {
339                     prefix = _xmlReader.getNamespacePrefix(i);
340                     prefix = (prefix == null) ? NO_CHAR : prefix; // Default namespace is ""
341
_contentHandler.endPrefixMapping(prefix);
342                 }
343                 break;
344
345             case XMLStreamConstants.CDATA:
346             case XMLStreamConstants.CHARACTERS:
347                 text = _xmlReader.getText();
348                 _contentHandler.characters(text.array(), text.offset(), text
349                         .length());
350                 break;
351
352             case XMLStreamConstants.SPACE:
353                 text = _xmlReader.getText();
354                 _contentHandler.ignorableWhitespace(text.array(),
355                         text.offset(), text.length());
356                 break;
357
358             case XMLStreamConstants.PROCESSING_INSTRUCTION:
359                 _contentHandler.processingInstruction(
360                         _xmlReader.getPITarget(), _xmlReader.getPIData());
361                 break;
362
363             case XMLStreamConstants.COMMENT:
364                 // Ignores.
365
break;
366
367             case XMLStreamConstants.END_DOCUMENT:
368                 doContinue = false;
369                 _xmlReader.close();
370                 break;
371
372             }
373         }
374     }
375     
376     private static final CharArray NO_CHAR = new CharArray("");
377 }
Popular Tags