1 // ParserAdapter.java - adapt a SAX1 Parser to a SAX2 XMLReader.
2 // http://www.saxproject.org
3 // Written by David Megginson
4 // NO WARRANTY!  This class is in the public domain.
5 // $Id: ParserAdapter.java,v 1.16 2004/04/26 17:34:35 dmegginson Exp $
6 
7 package org.xml.sax.helpers;
8 
9 import org.xml.sax.AttributeList;
10 import org.xml.sax.Attributes;
11 import org.xml.sax.ContentHandler;
12 import org.xml.sax.DTDHandler;
13 import org.xml.sax.DocumentHandler;
14 import org.xml.sax.EntityResolver;
15 import org.xml.sax.ErrorHandler;
16 import org.xml.sax.InputSource;
17 import org.xml.sax.Locator;
18 import org.xml.sax.Parser;
19 import org.xml.sax.SAXException;
20 import org.xml.sax.SAXNotRecognizedException;
21 import org.xml.sax.SAXNotSupportedException;
22 import org.xml.sax.SAXParseException;
23 import org.xml.sax.XMLReader;
24 
25 import android.compat.annotation.UnsupportedAppUsage;
26 
27 import java.io.IOException;
28 import java.util.ArrayList;
29 import java.util.Enumeration;
30 
31 
32 /**
33  * Adapt a SAX1 Parser as a SAX2 XMLReader.
34  *
35  * <blockquote>
36  * <em>This module, both source code and documentation, is in the
37  * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
38  * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
39  * for further information.
40  * </blockquote>
41  *
42  * <p>This class wraps a SAX1 {@link org.xml.sax.Parser Parser}
43  * and makes it act as a SAX2 {@link org.xml.sax.XMLReader XMLReader},
44  * with feature, property, and Namespace support.  Note
45  * that it is not possible to report {@link org.xml.sax.ContentHandler#skippedEntity
46  * skippedEntity} events, since SAX1 does not make that information available.</p>
47  *
48  * <p>This adapter does not test for duplicate Namespace-qualified
49  * attribute names.</p>
50  *
51  * @since SAX 2.0
52  * @author David Megginson
53  * @version 2.0.1 (sax2r2)
54  * @see org.xml.sax.helpers.XMLReaderAdapter
55  * @see org.xml.sax.XMLReader
56  * @see org.xml.sax.Parser
57  */
58 public class ParserAdapter implements XMLReader, DocumentHandler
59 {
60 
61 
62     ////////////////////////////////////////////////////////////////////
63     // Constructors.
64     ////////////////////////////////////////////////////////////////////
65 
66 
67     /**
68      * Construct a new parser adapter.
69      *
70      * <p>Use the "org.xml.sax.parser" property to locate the
71      * embedded SAX1 driver.</p>
72      *
73      * @exception SAXException If the embedded driver
74      *            cannot be instantiated or if the
75      *            org.xml.sax.parser property is not specified.
76      */
ParserAdapter()77     public ParserAdapter ()
78       throws SAXException
79     {
80 
81     String driver = System.getProperty("org.xml.sax.parser");
82 
83     try {
84         setup(ParserFactory.makeParser());
85     } catch (ClassNotFoundException e1) {
86         throw new
87         SAXException("Cannot find SAX1 driver class " +
88                  driver, e1);
89     } catch (IllegalAccessException e2) {
90         throw new
91         SAXException("SAX1 driver class " +
92                  driver +
93                  " found but cannot be loaded", e2);
94     } catch (InstantiationException e3) {
95         throw new
96         SAXException("SAX1 driver class " +
97                  driver +
98                  " loaded but cannot be instantiated", e3);
99     } catch (ClassCastException e4) {
100         throw new
101         SAXException("SAX1 driver class " +
102                  driver +
103                  " does not implement org.xml.sax.Parser");
104     } catch (NullPointerException e5) {
105         throw new
106         SAXException("System property org.xml.sax.parser not specified");
107     }
108     }
109 
110 
111     /**
112      * Construct a new parser adapter.
113      *
114      * <p>Note that the embedded parser cannot be changed once the
115      * adapter is created; to embed a different parser, allocate
116      * a new ParserAdapter.</p>
117      *
118      * @param parser The SAX1 parser to embed.
119      * @exception java.lang.NullPointerException If the parser parameter
120      *            is null.
121      */
ParserAdapter(Parser parser)122     public ParserAdapter (Parser parser)
123     {
124     setup(parser);
125     }
126 
127 
128     /**
129      * Internal setup method.
130      *
131      * @param parser The embedded parser.
132      * @exception java.lang.NullPointerException If the parser parameter
133      *            is null.
134      */
135     @UnsupportedAppUsage
setup(Parser parser)136     private void setup (Parser parser)
137     {
138     if (parser == null) {
139         throw new
140         NullPointerException("Parser argument must not be null");
141     }
142     this.parser = parser;
143     atts = new AttributesImpl();
144     nsSupport = new NamespaceSupport();
145     attAdapter = new AttributeListAdapter();
146     }
147 
148 
149 
150     ////////////////////////////////////////////////////////////////////
151     // Implementation of org.xml.sax.XMLReader.
152     ////////////////////////////////////////////////////////////////////
153 
154 
155     //
156     // Internal constants for the sake of convenience.
157     //
158     private static final String FEATURES = "http://xml.org/sax/features/";
159     private static final String NAMESPACES = FEATURES + "namespaces";
160     private static final String NAMESPACE_PREFIXES = FEATURES + "namespace-prefixes";
161     private static final String XMLNS_URIs = FEATURES + "xmlns-uris";
162 
163 
164     /**
165      * Set a feature flag for the parser.
166      *
167      * <p>The only features recognized are namespaces and
168      * namespace-prefixes.</p>
169      *
170      * @param name The feature name, as a complete URI.
171      * @param value The requested feature value.
172      * @exception SAXNotRecognizedException If the feature
173      *            can't be assigned or retrieved.
174      * @exception SAXNotSupportedException If the feature
175      *            can't be assigned that value.
176      * @see org.xml.sax.XMLReader#setFeature
177      */
setFeature(String name, boolean value)178     public void setFeature (String name, boolean value)
179     throws SAXNotRecognizedException, SAXNotSupportedException
180     {
181     if (name.equals(NAMESPACES)) {
182         checkNotParsing("feature", name);
183         namespaces = value;
184         if (!namespaces && !prefixes) {
185         prefixes = true;
186         }
187     } else if (name.equals(NAMESPACE_PREFIXES)) {
188         checkNotParsing("feature", name);
189         prefixes = value;
190         if (!prefixes && !namespaces) {
191         namespaces = true;
192         }
193     } else if (name.equals(XMLNS_URIs)) {
194         checkNotParsing("feature", name);
195         uris = value;
196     } else {
197         throw new SAXNotRecognizedException("Feature: " + name);
198     }
199     }
200 
201 
202     /**
203      * Check a parser feature flag.
204      *
205      * <p>The only features recognized are namespaces and
206      * namespace-prefixes.</p>
207      *
208      * @param name The feature name, as a complete URI.
209      * @return The current feature value.
210      * @exception SAXNotRecognizedException If the feature
211      *            value can't be assigned or retrieved.
212      * @exception SAXNotSupportedException If the
213      *            feature is not currently readable.
214      * @see org.xml.sax.XMLReader#setFeature
215      */
getFeature(String name)216     public boolean getFeature (String name)
217     throws SAXNotRecognizedException, SAXNotSupportedException
218     {
219     if (name.equals(NAMESPACES)) {
220         return namespaces;
221     } else if (name.equals(NAMESPACE_PREFIXES)) {
222         return prefixes;
223     } else if (name.equals(XMLNS_URIs)) {
224         return uris;
225     } else {
226         throw new SAXNotRecognizedException("Feature: " + name);
227     }
228     }
229 
230 
231     /**
232      * Set a parser property.
233      *
234      * <p>No properties are currently recognized.</p>
235      *
236      * @param name The property name.
237      * @param value The property value.
238      * @exception SAXNotRecognizedException If the property
239      *            value can't be assigned or retrieved.
240      * @exception SAXNotSupportedException If the property
241      *            can't be assigned that value.
242      * @see org.xml.sax.XMLReader#setProperty
243      */
setProperty(String name, Object value)244     public void setProperty (String name, Object value)
245     throws SAXNotRecognizedException, SAXNotSupportedException
246     {
247     throw new SAXNotRecognizedException("Property: " + name);
248     }
249 
250 
251     /**
252      * Get a parser property.
253      *
254      * <p>No properties are currently recognized.</p>
255      *
256      * @param name The property name.
257      * @return The property value.
258      * @exception SAXNotRecognizedException If the property
259      *            value can't be assigned or retrieved.
260      * @exception SAXNotSupportedException If the property
261      *            value is not currently readable.
262      * @see org.xml.sax.XMLReader#getProperty
263      */
getProperty(String name)264     public Object getProperty (String name)
265     throws SAXNotRecognizedException, SAXNotSupportedException
266     {
267     throw new SAXNotRecognizedException("Property: " + name);
268     }
269 
270 
271     /**
272      * Set the entity resolver.
273      *
274      * @param resolver The new entity resolver.
275      * @see org.xml.sax.XMLReader#setEntityResolver
276      */
setEntityResolver(EntityResolver resolver)277     public void setEntityResolver (EntityResolver resolver)
278     {
279     entityResolver = resolver;
280     }
281 
282 
283     /**
284      * Return the current entity resolver.
285      *
286      * @return The current entity resolver, or null if none was supplied.
287      * @see org.xml.sax.XMLReader#getEntityResolver
288      */
getEntityResolver()289     public EntityResolver getEntityResolver ()
290     {
291     return entityResolver;
292     }
293 
294 
295     /**
296      * Set the DTD handler.
297      *
298      * @param handler the new DTD handler
299      * @see org.xml.sax.XMLReader#setEntityResolver
300      */
setDTDHandler(DTDHandler handler)301     public void setDTDHandler (DTDHandler handler)
302     {
303     dtdHandler = handler;
304     }
305 
306 
307     /**
308      * Return the current DTD handler.
309      *
310      * @return the current DTD handler, or null if none was supplied
311      * @see org.xml.sax.XMLReader#getEntityResolver
312      */
getDTDHandler()313     public DTDHandler getDTDHandler ()
314     {
315     return dtdHandler;
316     }
317 
318 
319     /**
320      * Set the content handler.
321      *
322      * @param handler the new content handler
323      * @see org.xml.sax.XMLReader#setEntityResolver
324      */
setContentHandler(ContentHandler handler)325     public void setContentHandler (ContentHandler handler)
326     {
327     contentHandler = handler;
328     }
329 
330 
331     /**
332      * Return the current content handler.
333      *
334      * @return The current content handler, or null if none was supplied.
335      * @see org.xml.sax.XMLReader#getEntityResolver
336      */
getContentHandler()337     public ContentHandler getContentHandler ()
338     {
339     return contentHandler;
340     }
341 
342 
343     /**
344      * Set the error handler.
345      *
346      * @param handler The new error handler.
347      * @see org.xml.sax.XMLReader#setEntityResolver
348      */
setErrorHandler(ErrorHandler handler)349     public void setErrorHandler (ErrorHandler handler)
350     {
351     errorHandler = handler;
352     }
353 
354 
355     /**
356      * Return the current error handler.
357      *
358      * @return The current error handler, or null if none was supplied.
359      * @see org.xml.sax.XMLReader#getEntityResolver
360      */
getErrorHandler()361     public ErrorHandler getErrorHandler ()
362     {
363     return errorHandler;
364     }
365 
366 
367     /**
368      * Parse an XML document.
369      *
370      * @param systemId The absolute URL of the document.
371      * @exception java.io.IOException If there is a problem reading
372      *            the raw content of the document.
373      * @exception SAXException If there is a problem
374      *            processing the document.
375      * @see #parse(org.xml.sax.InputSource)
376      * @see org.xml.sax.Parser#parse(java.lang.String)
377      */
parse(String systemId)378     public void parse (String systemId)
379     throws IOException, SAXException
380     {
381     parse(new InputSource(systemId));
382     }
383 
384 
385     /**
386      * Parse an XML document.
387      *
388      * @param input An input source for the document.
389      * @exception java.io.IOException If there is a problem reading
390      *            the raw content of the document.
391      * @exception SAXException If there is a problem
392      *            processing the document.
393      * @see #parse(java.lang.String)
394      * @see org.xml.sax.Parser#parse(org.xml.sax.InputSource)
395      */
parse(InputSource input)396     public void parse (InputSource input)
397     throws IOException, SAXException
398     {
399     if (parsing) {
400         throw new SAXException("Parser is already in use");
401     }
402     setupParser();
403     parsing = true;
404     try {
405         parser.parse(input);
406     } finally {
407         parsing = false;
408     }
409     parsing = false;
410     }
411 
412 
413 
414     ////////////////////////////////////////////////////////////////////
415     // Implementation of org.xml.sax.DocumentHandler.
416     ////////////////////////////////////////////////////////////////////
417 
418 
419     /**
420      * Adapter implementation method; do not call.
421      * Adapt a SAX1 document locator event.
422      *
423      * @param locator A document locator.
424      * @see org.xml.sax.ContentHandler#setDocumentLocator
425      */
setDocumentLocator(Locator locator)426     public void setDocumentLocator (Locator locator)
427     {
428     this.locator = locator;
429     if (contentHandler != null) {
430         contentHandler.setDocumentLocator(locator);
431     }
432     }
433 
434 
435     /**
436      * Adapter implementation method; do not call.
437      * Adapt a SAX1 start document event.
438      *
439      * @exception SAXException The client may raise a
440      *            processing exception.
441      * @see org.xml.sax.DocumentHandler#startDocument
442      */
startDocument()443     public void startDocument ()
444     throws SAXException
445     {
446     if (contentHandler != null) {
447         contentHandler.startDocument();
448     }
449     }
450 
451 
452     /**
453      * Adapter implementation method; do not call.
454      * Adapt a SAX1 end document event.
455      *
456      * @exception SAXException The client may raise a
457      *            processing exception.
458      * @see org.xml.sax.DocumentHandler#endDocument
459      */
endDocument()460     public void endDocument ()
461     throws SAXException
462     {
463     if (contentHandler != null) {
464         contentHandler.endDocument();
465     }
466     }
467 
468 
469     /**
470      * Adapter implementation method; do not call.
471      * Adapt a SAX1 startElement event.
472      *
473      * <p>If necessary, perform Namespace processing.</p>
474      *
475      * @param qName The qualified (prefixed) name.
476      * @param qAtts The XML attribute list (with qnames).
477      * @exception SAXException The client may raise a
478      *            processing exception.
479      */
startElement(String qName, AttributeList qAtts)480     public void startElement (String qName, AttributeList qAtts) throws SAXException {
481         // These are exceptions from the
482         // first pass; they should be
483         // ignored if there's a second pass,
484         // but reported otherwise.
485         ArrayList<SAXParseException> exceptions = null;
486 
487                 // If we're not doing Namespace
488                 // processing, dispatch this quickly.
489     if (!namespaces) {
490         if (contentHandler != null) {
491         attAdapter.setAttributeList(qAtts);
492         contentHandler.startElement("", "", qName.intern(),
493                         attAdapter);
494         }
495         return;
496     }
497 
498 
499                 // OK, we're doing Namespace processing.
500     nsSupport.pushContext();
501     int length = qAtts.getLength();
502 
503                 // First pass:  handle NS decls
504     for (int i = 0; i < length; i++) {
505         String attQName = qAtts.getName(i);
506 
507         if (!attQName.startsWith("xmlns"))
508         continue;
509                 // Could be a declaration...
510         String prefix;
511         int n = attQName.indexOf(':');
512 
513                     // xmlns=...
514         if (n == -1 && attQName.length () == 5) {
515         prefix = "";
516         } else if (n != 5) {
517         // XML namespaces spec doesn't discuss "xmlnsf:oo"
518         // (and similarly named) attributes ... at most, warn
519         continue;
520         } else         // xmlns:foo=...
521         prefix = attQName.substring(n+1);
522 
523         String value = qAtts.getValue(i);
524         if (!nsSupport.declarePrefix(prefix, value)) {
525         reportError("Illegal Namespace prefix: " + prefix);
526         continue;
527         }
528         if (contentHandler != null)
529         contentHandler.startPrefixMapping(prefix, value);
530     }
531 
532                 // Second pass: copy all relevant
533                 // attributes into the SAX2 AttributeList
534                 // using updated prefix bindings
535     atts.clear();
536     for (int i = 0; i < length; i++) {
537         String attQName = qAtts.getName(i);
538         String type = qAtts.getType(i);
539         String value = qAtts.getValue(i);
540 
541                 // Declaration?
542         if (attQName.startsWith("xmlns")) {
543         String prefix;
544         int n = attQName.indexOf(':');
545 
546         if (n == -1 && attQName.length () == 5) {
547             prefix = "";
548         } else if (n != 5) {
549             // XML namespaces spec doesn't discuss "xmlnsf:oo"
550             // (and similarly named) attributes ... ignore
551             prefix = null;
552         } else {
553             prefix = attQName.substring(6);
554         }
555                 // Yes, decl:  report or prune
556         if (prefix != null) {
557             if (prefixes) {
558             if (uris)
559                 // note funky case:  localname can be null
560                 // when declaring the default prefix, and
561                 // yet the uri isn't null.
562                 atts.addAttribute (nsSupport.XMLNS, prefix,
563                     attQName.intern(), type, value);
564             else
565                 atts.addAttribute ("", "",
566                     attQName.intern(), type, value);
567             }
568             continue;
569         }
570         }
571 
572                 // Not a declaration -- report
573         try {
574         String attName[] = processName(attQName, true, true);
575         atts.addAttribute(attName[0], attName[1], attName[2],
576                   type, value);
577         } catch (SAXException e) {
578             if (exceptions == null) {
579                 exceptions = new ArrayList<SAXParseException>();
580             }
581             exceptions.add((SAXParseException) e);
582             atts.addAttribute("", attQName, attQName, type, value);
583         }
584     }
585 
586     // now handle the deferred exception reports
587     if (exceptions != null && errorHandler != null) {
588         for (SAXParseException ex : exceptions) {
589             errorHandler.error(ex);
590         }
591     }
592 
593                 // OK, finally report the event.
594     if (contentHandler != null) {
595         String name[] = processName(qName, false, false);
596         contentHandler.startElement(name[0], name[1], name[2], atts);
597     }
598     }
599 
600 
601     /**
602      * Adapter implementation method; do not call.
603      * Adapt a SAX1 end element event.
604      *
605      * @param qName The qualified (prefixed) name.
606      * @exception SAXException The client may raise a
607      *            processing exception.
608      * @see org.xml.sax.DocumentHandler#endElement
609      */
endElement(String qName)610     public void endElement (String qName)
611     throws SAXException
612     {
613                 // If we're not doing Namespace
614                 // processing, dispatch this quickly.
615     if (!namespaces) {
616         if (contentHandler != null) {
617         contentHandler.endElement("", "", qName.intern());
618         }
619         return;
620     }
621 
622                 // Split the name.
623     String names[] = processName(qName, false, false);
624     if (contentHandler != null) {
625         contentHandler.endElement(names[0], names[1], names[2]);
626         Enumeration prefixes = nsSupport.getDeclaredPrefixes();
627         while (prefixes.hasMoreElements()) {
628         String prefix = (String)prefixes.nextElement();
629         contentHandler.endPrefixMapping(prefix);
630         }
631     }
632     nsSupport.popContext();
633     }
634 
635 
636     /**
637      * Adapter implementation method; do not call.
638      * Adapt a SAX1 characters event.
639      *
640      * @param ch An array of characters.
641      * @param start The starting position in the array.
642      * @param length The number of characters to use.
643      * @exception SAXException The client may raise a
644      *            processing exception.
645      * @see org.xml.sax.DocumentHandler#characters
646      */
characters(char ch[], int start, int length)647     public void characters (char ch[], int start, int length)
648     throws SAXException
649     {
650     if (contentHandler != null) {
651         contentHandler.characters(ch, start, length);
652     }
653     }
654 
655 
656     /**
657      * Adapter implementation method; do not call.
658      * Adapt a SAX1 ignorable whitespace event.
659      *
660      * @param ch An array of characters.
661      * @param start The starting position in the array.
662      * @param length The number of characters to use.
663      * @exception SAXException The client may raise a
664      *            processing exception.
665      * @see org.xml.sax.DocumentHandler#ignorableWhitespace
666      */
ignorableWhitespace(char ch[], int start, int length)667     public void ignorableWhitespace (char ch[], int start, int length)
668     throws SAXException
669     {
670     if (contentHandler != null) {
671         contentHandler.ignorableWhitespace(ch, start, length);
672     }
673     }
674 
675 
676     /**
677      * Adapter implementation method; do not call.
678      * Adapt a SAX1 processing instruction event.
679      *
680      * @param target The processing instruction target.
681      * @param data The remainder of the processing instruction
682      * @exception SAXException The client may raise a
683      *            processing exception.
684      * @see org.xml.sax.DocumentHandler#processingInstruction
685      */
processingInstruction(String target, String data)686     public void processingInstruction (String target, String data)
687     throws SAXException
688     {
689     if (contentHandler != null) {
690         contentHandler.processingInstruction(target, data);
691     }
692     }
693 
694 
695 
696     ////////////////////////////////////////////////////////////////////
697     // Internal utility methods.
698     ////////////////////////////////////////////////////////////////////
699 
700 
701     /**
702      * Initialize the parser before each run.
703      */
704     @UnsupportedAppUsage
setupParser()705     private void setupParser ()
706     {
707     // catch an illegal "nonsense" state.
708     if (!prefixes && !namespaces)
709         throw new IllegalStateException ();
710 
711     nsSupport.reset();
712     if (uris)
713         nsSupport.setNamespaceDeclUris (true);
714 
715     if (entityResolver != null) {
716         parser.setEntityResolver(entityResolver);
717     }
718     if (dtdHandler != null) {
719         parser.setDTDHandler(dtdHandler);
720     }
721     if (errorHandler != null) {
722         parser.setErrorHandler(errorHandler);
723     }
724     parser.setDocumentHandler(this);
725     locator = null;
726     }
727 
728 
729     /**
730      * Process a qualified (prefixed) name.
731      *
732      * <p>If the name has an undeclared prefix, use only the qname
733      * and make an ErrorHandler.error callback in case the app is
734      * interested.</p>
735      *
736      * @param qName The qualified (prefixed) name.
737      * @param isAttribute true if this is an attribute name.
738      * @return The name split into three parts.
739      * @exception SAXException The client may throw
740      *            an exception if there is an error callback.
741      */
742     @UnsupportedAppUsage
processName(String qName, boolean isAttribute, boolean useException)743     private String [] processName (String qName, boolean isAttribute,
744                    boolean useException)
745     throws SAXException
746     {
747     String parts[] = nsSupport.processName(qName, nameParts,
748                            isAttribute);
749     if (parts == null) {
750         if (useException)
751         throw makeException("Undeclared prefix: " + qName);
752         reportError("Undeclared prefix: " + qName);
753         parts = new String[3];
754         parts[0] = parts[1] = "";
755         parts[2] = qName.intern();
756     }
757     return parts;
758     }
759 
760 
761     /**
762      * Report a non-fatal error.
763      *
764      * @param message The error message.
765      * @exception SAXException The client may throw
766      *            an exception.
767      */
768     @UnsupportedAppUsage
reportError(String message)769     void reportError (String message)
770     throws SAXException
771     {
772     if (errorHandler != null)
773         errorHandler.error(makeException(message));
774     }
775 
776 
777     /**
778      * Construct an exception for the current context.
779      *
780      * @param message The error message.
781      */
782     @UnsupportedAppUsage
makeException(String message)783     private SAXParseException makeException (String message)
784     {
785     if (locator != null) {
786         return new SAXParseException(message, locator);
787     } else {
788         return new SAXParseException(message, null, null, -1, -1);
789     }
790     }
791 
792 
793     /**
794      * Throw an exception if we are parsing.
795      *
796      * <p>Use this method to detect illegal feature or
797      * property changes.</p>
798      *
799      * @param type The type of thing (feature or property).
800      * @param name The feature or property name.
801      * @exception SAXNotSupportedException If a
802      *            document is currently being parsed.
803      */
804     @UnsupportedAppUsage
checkNotParsing(String type, String name)805     private void checkNotParsing (String type, String name)
806     throws SAXNotSupportedException
807     {
808     if (parsing) {
809         throw new SAXNotSupportedException("Cannot change " +
810                            type + ' ' +
811                            name + " while parsing");
812 
813     }
814     }
815 
816 
817 
818     ////////////////////////////////////////////////////////////////////
819     // Internal state.
820     ////////////////////////////////////////////////////////////////////
821 
822     @UnsupportedAppUsage
823     private NamespaceSupport nsSupport;
824     @UnsupportedAppUsage
825     private AttributeListAdapter attAdapter;
826 
827     @UnsupportedAppUsage
828     private boolean parsing = false;
829     @UnsupportedAppUsage
830     private String nameParts[] = new String[3];
831 
832     @UnsupportedAppUsage
833     private Parser parser = null;
834 
835     @UnsupportedAppUsage
836     private AttributesImpl atts = null;
837 
838                 // Features
839     @UnsupportedAppUsage
840     private boolean namespaces = true;
841     @UnsupportedAppUsage
842     private boolean prefixes = false;
843     @UnsupportedAppUsage
844     private boolean uris = false;
845 
846                 // Properties
847 
848                 // Handlers
849     @UnsupportedAppUsage
850     Locator locator;
851 
852     @UnsupportedAppUsage
853     EntityResolver entityResolver = null;
854     @UnsupportedAppUsage
855     DTDHandler dtdHandler = null;
856     @UnsupportedAppUsage
857     ContentHandler contentHandler = null;
858     @UnsupportedAppUsage
859     ErrorHandler errorHandler = null;
860 
861 
862 
863     ////////////////////////////////////////////////////////////////////
864     // Inner class to wrap an AttributeList when not doing NS proc.
865     ////////////////////////////////////////////////////////////////////
866 
867 
868     /**
869      * Adapt a SAX1 AttributeList as a SAX2 Attributes object.
870      *
871      * <p>This class is in the Public Domain, and comes with NO
872      * WARRANTY of any kind.</p>
873      *
874      * <p>This wrapper class is used only when Namespace support
875      * is disabled -- it provides pretty much a direct mapping
876      * from SAX1 to SAX2, except that names and types are
877      * interned whenever requested.</p>
878      */
879     final class AttributeListAdapter implements Attributes
880     {
881 
882     /**
883      * Construct a new adapter.
884      */
885     @UnsupportedAppUsage
AttributeListAdapter()886     AttributeListAdapter ()
887     {
888     }
889 
890 
891     /**
892      * Set the embedded AttributeList.
893      *
894      * <p>This method must be invoked before any of the others
895      * can be used.</p>
896      *
897      * @param The SAX1 attribute list (with qnames).
898      */
setAttributeList(AttributeList qAtts)899     void setAttributeList (AttributeList qAtts)
900     {
901         this.qAtts = qAtts;
902     }
903 
904 
905     /**
906      * Return the length of the attribute list.
907      *
908      * @return The number of attributes in the list.
909      * @see org.xml.sax.Attributes#getLength
910      */
getLength()911     public int getLength ()
912     {
913         return qAtts.getLength();
914     }
915 
916 
917     /**
918      * Return the Namespace URI of the specified attribute.
919      *
920      * @param The attribute's index.
921      * @return Always the empty string.
922      * @see org.xml.sax.Attributes#getURI
923      */
getURI(int i)924     public String getURI (int i)
925     {
926         return "";
927     }
928 
929 
930     /**
931      * Return the local name of the specified attribute.
932      *
933      * @param The attribute's index.
934      * @return Always the empty string.
935      * @see org.xml.sax.Attributes#getLocalName
936      */
getLocalName(int i)937     public String getLocalName (int i)
938     {
939         return "";
940     }
941 
942 
943     /**
944      * Return the qualified (prefixed) name of the specified attribute.
945      *
946      * @param The attribute's index.
947      * @return The attribute's qualified name, internalized.
948      */
getQName(int i)949     public String getQName (int i)
950     {
951         return qAtts.getName(i).intern();
952     }
953 
954 
955     /**
956      * Return the type of the specified attribute.
957      *
958      * @param The attribute's index.
959      * @return The attribute's type as an internalized string.
960      */
getType(int i)961     public String getType (int i)
962     {
963         return qAtts.getType(i).intern();
964     }
965 
966 
967     /**
968      * Return the value of the specified attribute.
969      *
970      * @param The attribute's index.
971      * @return The attribute's value.
972      */
getValue(int i)973     public String getValue (int i)
974     {
975         return qAtts.getValue(i);
976     }
977 
978 
979     /**
980      * Look up an attribute index by Namespace name.
981      *
982      * @param uri The Namespace URI or the empty string.
983      * @param localName The local name.
984      * @return The attributes index, or -1 if none was found.
985      * @see org.xml.sax.Attributes#getIndex(java.lang.String,java.lang.String)
986      */
getIndex(String uri, String localName)987     public int getIndex (String uri, String localName)
988     {
989         return -1;
990     }
991 
992 
993     /**
994      * Look up an attribute index by qualified (prefixed) name.
995      *
996      * @param qName The qualified name.
997      * @return The attributes index, or -1 if none was found.
998      * @see org.xml.sax.Attributes#getIndex(java.lang.String)
999      */
getIndex(String qName)1000     public int getIndex (String qName)
1001     {
1002         int max = atts.getLength();
1003         for (int i = 0; i < max; i++) {
1004         if (qAtts.getName(i).equals(qName)) {
1005             return i;
1006         }
1007         }
1008         return -1;
1009     }
1010 
1011 
1012     /**
1013      * Look up the type of an attribute by Namespace name.
1014      *
1015      * @param uri The Namespace URI
1016      * @param localName The local name.
1017      * @return The attribute's type as an internalized string.
1018      */
getType(String uri, String localName)1019     public String getType (String uri, String localName)
1020     {
1021         return null;
1022     }
1023 
1024 
1025     /**
1026      * Look up the type of an attribute by qualified (prefixed) name.
1027      *
1028      * @param qName The qualified name.
1029      * @return The attribute's type as an internalized string.
1030      */
getType(String qName)1031     public String getType (String qName)
1032     {
1033         return qAtts.getType(qName).intern();
1034     }
1035 
1036 
1037     /**
1038      * Look up the value of an attribute by Namespace name.
1039      *
1040      * @param uri The Namespace URI
1041      * @param localName The local name.
1042      * @return The attribute's value.
1043      */
getValue(String uri, String localName)1044     public String getValue (String uri, String localName)
1045     {
1046         return null;
1047     }
1048 
1049 
1050     /**
1051      * Look up the value of an attribute by qualified (prefixed) name.
1052      *
1053      * @param qName The qualified name.
1054      * @return The attribute's value.
1055      */
getValue(String qName)1056     public String getValue (String qName)
1057     {
1058         return qAtts.getValue(qName);
1059     }
1060 
1061     private AttributeList qAtts;
1062     }
1063 }
1064 
1065 // end of ParserAdapter.java
1066