1 /*
2 * Copyright 2000-2005 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26 // XMLReaderAdapter.java - adapt an SAX2 XMLReader to a SAX1 Parser
27 // http://www.saxproject.org
28 // Written by David Megginson
29 // NO WARRANTY! This class is in the public domain.
30 // $Id: XMLReaderAdapter.java,v 1.3 2004/11/03 22:53:09 jsuttor Exp $
31
32 package org.xml.sax.helpers;
33
34 import java.io.IOException;
35 import java.util.Locale;
36
37 import org.xml.sax.Parser; // deprecated
38 import org.xml.sax.Locator;
39 import org.xml.sax.InputSource;
40 import org.xml.sax.AttributeList; // deprecated
41 import org.xml.sax.EntityResolver;
42 import org.xml.sax.DTDHandler;
43 import org.xml.sax.DocumentHandler; // deprecated
44 import org.xml.sax.ErrorHandler;
45 import org.xml.sax.SAXException;
46
47 import org.xml.sax.XMLReader;
48 import org.xml.sax.Attributes;
49 import org.xml.sax.ContentHandler;
50 import org.xml.sax.SAXNotSupportedException;
51
52
53 /**
54 * Adapt a SAX2 XMLReader as a SAX1 Parser.
55 *
56 * <blockquote>
57 * <em>This module, both source code and documentation, is in the
58 * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
59 * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
60 * for further information.
61 * </blockquote>
62 *
63 * <p>This class wraps a SAX2 {@link org.xml.sax.XMLReader XMLReader}
64 * and makes it act as a SAX1 {@link org.xml.sax.Parser Parser}. The XMLReader
65 * must support a true value for the
66 * http://xml.org/sax/features/namespace-prefixes property or parsing will fail
67 * with a {@link org.xml.sax.SAXException SAXException}; if the XMLReader
68 * supports a false value for the http://xml.org/sax/features/namespaces
69 * property, that will also be used to improve efficiency.</p>
70 *
71 * @since SAX 2.0
72 * @author David Megginson
73 * @see org.xml.sax.Parser
74 * @see org.xml.sax.XMLReader
75 */
76 public class XMLReaderAdapter implements Parser, ContentHandler
77 {
78
79
80 ////////////////////////////////////////////////////////////////////
81 // Constructor.
82 ////////////////////////////////////////////////////////////////////
83
84
85 /**
86 * Create a new adapter.
87 *
88 * <p>Use the "org.xml.sax.driver" property to locate the SAX2
89 * driver to embed.</p>
90 *
91 * @exception org.xml.sax.SAXException If the embedded driver
92 * cannot be instantiated or if the
93 * org.xml.sax.driver property is not specified.
94 */
95 public XMLReaderAdapter ()
96 throws SAXException
97 {
98 setup(XMLReaderFactory.createXMLReader());
99 }
100
101
102 /**
103 * Create a new adapter.
104 *
105 * <p>Create a new adapter, wrapped around a SAX2 XMLReader.
106 * The adapter will make the XMLReader act like a SAX1
107 * Parser.</p>
108 *
109 * @param xmlReader The SAX2 XMLReader to wrap.
110 * @exception java.lang.NullPointerException If the argument is null.
111 */
112 public XMLReaderAdapter (XMLReader xmlReader)
113 {
114 setup(xmlReader);
115 }
116
117
118
119 /**
120 * Internal setup.
121 *
122 * @param xmlReader The embedded XMLReader.
123 */
124 private void setup (XMLReader xmlReader)
125 {
126 if (xmlReader == null) {
127 throw new NullPointerException("XMLReader must not be null");
128 }
129 this.xmlReader = xmlReader;
130 qAtts = new AttributesAdapter();
131 }
132
133
134
135 ////////////////////////////////////////////////////////////////////
136 // Implementation of org.xml.sax.Parser.
137 ////////////////////////////////////////////////////////////////////
138
139
140 /**
141 * Set the locale for error reporting.
142 *
143 * <p>This is not supported in SAX2, and will always throw
144 * an exception.</p>
145 *
146 * @param locale the locale for error reporting.
147 * @see org.xml.sax.Parser#setLocale
148 * @exception org.xml.sax.SAXException Thrown unless overridden.
149 */
150 public void setLocale (Locale locale)
151 throws SAXException
152 {
153 throw new SAXNotSupportedException("setLocale not supported");
154 }
155
156
157 /**
158 * Register the entity resolver.
159 *
160 * @param resolver The new resolver.
161 * @see org.xml.sax.Parser#setEntityResolver
162 */
163 public void setEntityResolver (EntityResolver resolver)
164 {
165 xmlReader.setEntityResolver(resolver);
166 }
167
168
169 /**
170 * Register the DTD event handler.
171 *
172 * @param handler The new DTD event handler.
173 * @see org.xml.sax.Parser#setDTDHandler
174 */
175 public void setDTDHandler (DTDHandler handler)
176 {
177 xmlReader.setDTDHandler(handler);
178 }
179
180
181 /**
182 * Register the SAX1 document event handler.
183 *
184 * <p>Note that the SAX1 document handler has no Namespace
185 * support.</p>
186 *
187 * @param handler The new SAX1 document event handler.
188 * @see org.xml.sax.Parser#setDocumentHandler
189 */
190 public void setDocumentHandler (DocumentHandler handler)
191 {
192 documentHandler = handler;
193 }
194
195
196 /**
197 * Register the error event handler.
198 *
199 * @param handler The new error event handler.
200 * @see org.xml.sax.Parser#setErrorHandler
201 */
202 public void setErrorHandler (ErrorHandler handler)
203 {
204 xmlReader.setErrorHandler(handler);
205 }
206
207
208 /**
209 * Parse the document.
210 *
211 * <p>This method will throw an exception if the embedded
212 * XMLReader does not support the
213 * http://xml.org/sax/features/namespace-prefixes property.</p>
214 *
215 * @param systemId The absolute URL of the document.
216 * @exception java.io.IOException If there is a problem reading
217 * the raw content of the document.
218 * @exception org.xml.sax.SAXException If there is a problem
219 * processing the document.
220 * @see #parse(org.xml.sax.InputSource)
221 * @see org.xml.sax.Parser#parse(java.lang.String)
222 */
223 public void parse (String systemId)
224 throws IOException, SAXException
225 {
226 parse(new InputSource(systemId));
227 }
228
229
230 /**
231 * Parse the document.
232 *
233 * <p>This method will throw an exception if the embedded
234 * XMLReader does not support the
235 * http://xml.org/sax/features/namespace-prefixes property.</p>
236 *
237 * @param input An input source for the document.
238 * @exception java.io.IOException If there is a problem reading
239 * the raw content of the document.
240 * @exception org.xml.sax.SAXException If there is a problem
241 * processing the document.
242 * @see #parse(java.lang.String)
243 * @see org.xml.sax.Parser#parse(org.xml.sax.InputSource)
244 */
245 public void parse (InputSource input)
246 throws IOException, SAXException
247 {
248 setupXMLReader();
249 xmlReader.parse(input);
250 }
251
252
253 /**
254 * Set up the XML reader.
255 */
256 private void setupXMLReader ()
257 throws SAXException
258 {
259 xmlReader.setFeature("http://xml.org/sax/features/namespace-prefixes", true);
260 try {
261 xmlReader.setFeature("http://xml.org/sax/features/namespaces",
262 false);
263 } catch (SAXException e) {
264 // NO OP: it's just extra information, and we can ignore it
265 }
266 xmlReader.setContentHandler(this);
267 }
268
269
270
271 ////////////////////////////////////////////////////////////////////
272 // Implementation of org.xml.sax.ContentHandler.
273 ////////////////////////////////////////////////////////////////////
274
275
276 /**
277 * Set a document locator.
278 *
279 * @param locator The document locator.
280 * @see org.xml.sax.ContentHandler#setDocumentLocator
281 */
282 public void setDocumentLocator (Locator locator)
283 {
284 if (documentHandler != null)
285 documentHandler.setDocumentLocator(locator);
286 }
287
288
289 /**
290 * Start document event.
291 *
292 * @exception org.xml.sax.SAXException The client may raise a
293 * processing exception.
294 * @see org.xml.sax.ContentHandler#startDocument
295 */
296 public void startDocument ()
297 throws SAXException
298 {
299 if (documentHandler != null)
300 documentHandler.startDocument();
301 }
302
303
304 /**
305 * End document event.
306 *
307 * @exception org.xml.sax.SAXException The client may raise a
308 * processing exception.
309 * @see org.xml.sax.ContentHandler#endDocument
310 */
311 public void endDocument ()
312 throws SAXException
313 {
314 if (documentHandler != null)
315 documentHandler.endDocument();
316 }
317
318
319 /**
320 * Adapt a SAX2 start prefix mapping event.
321 *
322 * @param prefix The prefix being mapped.
323 * @param uri The Namespace URI being mapped to.
324 * @see org.xml.sax.ContentHandler#startPrefixMapping
325 */
326 public void startPrefixMapping (String prefix, String uri)
327 {
328 }
329
330
331 /**
332 * Adapt a SAX2 end prefix mapping event.
333 *
334 * @param prefix The prefix being mapped.
335 * @see org.xml.sax.ContentHandler#endPrefixMapping
336 */
337 public void endPrefixMapping (String prefix)
338 {
339 }
340
341
342 /**
343 * Adapt a SAX2 start element event.
344 *
345 * @param uri The Namespace URI.
346 * @param localName The Namespace local name.
347 * @param qName The qualified (prefixed) name.
348 * @param atts The SAX2 attributes.
349 * @exception org.xml.sax.SAXException The client may raise a
350 * processing exception.
351 * @see org.xml.sax.ContentHandler#endDocument
352 */
353 public void startElement (String uri, String localName,
354 String qName, Attributes atts)
355 throws SAXException
356 {
357 if (documentHandler != null) {
358 qAtts.setAttributes(atts);
359 documentHandler.startElement(qName, qAtts);
360 }
361 }
362
363
364 /**
365 * Adapt a SAX2 end element event.
366 *
367 * @param uri The Namespace URI.
368 * @param localName The Namespace local name.
369 * @param qName The qualified (prefixed) name.
370 * @exception org.xml.sax.SAXException The client may raise a
371 * processing exception.
372 * @see org.xml.sax.ContentHandler#endElement
373 */
374 public void endElement (String uri, String localName,
375 String qName)
376 throws SAXException
377 {
378 if (documentHandler != null)
379 documentHandler.endElement(qName);
380 }
381
382
383 /**
384 * Adapt a SAX2 characters event.
385 *
386 * @param ch An array of characters.
387 * @param start The starting position in the array.
388 * @param length The number of characters to use.
389 * @exception org.xml.sax.SAXException The client may raise a
390 * processing exception.
391 * @see org.xml.sax.ContentHandler#characters
392 */
393 public void characters (char ch[], int start, int length)
394 throws SAXException
395 {
396 if (documentHandler != null)
397 documentHandler.characters(ch, start, length);
398 }
399
400
401 /**
402 * Adapt a SAX2 ignorable whitespace event.
403 *
404 * @param ch An array of characters.
405 * @param start The starting position in the array.
406 * @param length The number of characters to use.
407 * @exception org.xml.sax.SAXException The client may raise a
408 * processing exception.
409 * @see org.xml.sax.ContentHandler#ignorableWhitespace
410 */
411 public void ignorableWhitespace (char ch[], int start, int length)
412 throws SAXException
413 {
414 if (documentHandler != null)
415 documentHandler.ignorableWhitespace(ch, start, length);
416 }
417
418
419 /**
420 * Adapt a SAX2 processing instruction event.
421 *
422 * @param target The processing instruction target.
423 * @param data The remainder of the processing instruction
424 * @exception org.xml.sax.SAXException The client may raise a
425 * processing exception.
426 * @see org.xml.sax.ContentHandler#processingInstruction
427 */
428 public void processingInstruction (String target, String data)
429 throws SAXException
430 {
431 if (documentHandler != null)
432 documentHandler.processingInstruction(target, data);
433 }
434
435
436 /**
437 * Adapt a SAX2 skipped entity event.
438 *
439 * @param name The name of the skipped entity.
440 * @see org.xml.sax.ContentHandler#skippedEntity
441 * @exception org.xml.sax.SAXException Throwable by subclasses.
442 */
443 public void skippedEntity (String name)
444 throws SAXException
445 {
446 }
447
448
449
450 ////////////////////////////////////////////////////////////////////
451 // Internal state.
452 ////////////////////////////////////////////////////////////////////
453
454 XMLReader xmlReader;
455 DocumentHandler documentHandler;
456 AttributesAdapter qAtts;
457
458
459
460 ////////////////////////////////////////////////////////////////////
461 // Internal class.
462 ////////////////////////////////////////////////////////////////////
463
464
465 /**
466 * Internal class to wrap a SAX2 Attributes object for SAX1.
467 */
468 final class AttributesAdapter implements AttributeList
469 {
470 AttributesAdapter ()
471 {
472 }
473
474
475 /**
476 * Set the embedded Attributes object.
477 *
478 * @param The embedded SAX2 Attributes.
479 */
480 void setAttributes (Attributes attributes)
481 {
482 this.attributes = attributes;
483 }
484
485
486 /**
487 * Return the number of attributes.
488 *
489 * @return The length of the attribute list.
490 * @see org.xml.sax.AttributeList#getLength
491 */
492 public int getLength ()
493 {
494 return attributes.getLength();
495 }
496
497
498 /**
499 * Return the qualified (prefixed) name of an attribute by position.
500 *
501 * @return The qualified name.
502 * @see org.xml.sax.AttributeList#getName
503 */
504 public String getName (int i)
505 {
506 return attributes.getQName(i);
507 }
508
509
510 /**
511 * Return the type of an attribute by position.
512 *
513 * @return The type.
514 * @see org.xml.sax.AttributeList#getType(int)
515 */
516 public String getType (int i)
517 {
518 return attributes.getType(i);
519 }
520
521
522 /**
523 * Return the value of an attribute by position.
524 *
525 * @return The value.
526 * @see org.xml.sax.AttributeList#getValue(int)
527 */
528 public String getValue (int i)
529 {
530 return attributes.getValue(i);
531 }
532
533
534 /**
535 * Return the type of an attribute by qualified (prefixed) name.
536 *
537 * @return The type.
538 * @see org.xml.sax.AttributeList#getType(java.lang.String)
539 */
540 public String getType (String qName)
541 {
542 return attributes.getType(qName);
543 }
544
545
546 /**
547 * Return the value of an attribute by qualified (prefixed) name.
548 *
549 * @return The value.
550 * @see org.xml.sax.AttributeList#getValue(java.lang.String)
551 */
552 public String getValue (String qName)
553 {
554 return attributes.getValue(qName);
555 }
556
557 private Attributes attributes;
558 }
559
560 }
561
562 // end of XMLReaderAdapter.java