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