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