Frames | No Frames |
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.1 2004/12/23 22:38:42 mark Exp $ 6: 7: package org.xml.sax.helpers; 8: 9: import java.io.IOException; 10: import java.util.Enumeration; 11: import java.util.Vector; 12: 13: import org.xml.sax.Parser; // deprecated 14: import org.xml.sax.InputSource; 15: import org.xml.sax.Locator; 16: import org.xml.sax.AttributeList; // deprecated 17: import org.xml.sax.EntityResolver; 18: import org.xml.sax.DTDHandler; 19: import org.xml.sax.DocumentHandler; // deprecated 20: import org.xml.sax.ErrorHandler; 21: import org.xml.sax.SAXException; 22: import org.xml.sax.SAXParseException; 23: 24: import org.xml.sax.XMLReader; 25: import org.xml.sax.Attributes; 26: import org.xml.sax.ContentHandler; 27: import org.xml.sax.SAXNotRecognizedException; 28: import org.xml.sax.SAXNotSupportedException; 29: 30: 31: /** 32: * Adapt a SAX1 Parser as a SAX2 XMLReader. 33: * 34: * <blockquote> 35: * <em>This module, both source code and documentation, is in the 36: * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em> 37: * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a> 38: * for further information. 39: * </blockquote> 40: * 41: * <p>This class wraps a SAX1 {@link org.xml.sax.Parser Parser} 42: * and makes it act as a SAX2 {@link org.xml.sax.XMLReader XMLReader}, 43: * with feature, property, and Namespace support. Note 44: * that it is not possible to report {@link org.xml.sax.ContentHandler#skippedEntity 45: * skippedEntity} events, since SAX1 does not make that information available.</p> 46: * 47: * <p>This adapter does not test for duplicate Namespace-qualified 48: * attribute names.</p> 49: * 50: * @since SAX 2.0 51: * @author David Megginson 52: * @version 2.0.1 (sax2r2) 53: * @see org.xml.sax.helpers.XMLReaderAdapter 54: * @see org.xml.sax.XMLReader 55: * @see org.xml.sax.Parser 56: */ 57: public class ParserAdapter implements XMLReader, DocumentHandler 58: { 59: 60: 61: //////////////////////////////////////////////////////////////////// 62: // Constructors. 63: //////////////////////////////////////////////////////////////////// 64: 65: 66: /** 67: * Construct a new parser adapter. 68: * 69: * <p>Use the "org.xml.sax.parser" property to locate the 70: * embedded SAX1 driver.</p> 71: * 72: * @exception SAXException If the embedded driver 73: * cannot be instantiated or if the 74: * org.xml.sax.parser property is not specified. 75: */ 76: public ParserAdapter () 77: throws SAXException 78: { 79: super(); 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: */ 122: public ParserAdapter (Parser parser) 123: { 124: super(); 125: setup(parser); 126: } 127: 128: 129: /** 130: * Internal setup method. 131: * 132: * @param parser The embedded parser. 133: * @exception java.lang.NullPointerException If the parser parameter 134: * is null. 135: */ 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 final static String FEATURES = "http://xml.org/sax/features/"; 159: private final static String NAMESPACES = FEATURES + "namespaces"; 160: private final static String NAMESPACE_PREFIXES = FEATURES + "namespace-prefixes"; 161: private final static 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 480: public void startElement (String qName, AttributeList qAtts) 481: throws SAXException 482: { 483: // These are exceptions from the 484: // first pass; they should be 485: // ignored if there's a second pass, 486: // but reported otherwise. 487: Vector exceptions = null; 488: 489: // If we're not doing Namespace 490: // processing, dispatch this quickly. 491: if (!namespaces) { 492: if (contentHandler != null) { 493: attAdapter.setAttributeList(qAtts); 494: contentHandler.startElement("", "", qName.intern(), 495: attAdapter); 496: } 497: return; 498: } 499: 500: 501: // OK, we're doing Namespace processing. 502: nsSupport.pushContext(); 503: int length = qAtts.getLength(); 504: 505: // First pass: handle NS decls 506: for (int i = 0; i < length; i++) { 507: String attQName = qAtts.getName(i); 508: 509: if (!attQName.startsWith("xmlns")) 510: continue; 511: // Could be a declaration... 512: String prefix; 513: int n = attQName.indexOf(':'); 514: 515: // xmlns=... 516: if (n == -1 && attQName.length () == 5) { 517: prefix = ""; 518: } else if (n != 5) { 519: // XML namespaces spec doesn't discuss "xmlnsf:oo" 520: // (and similarly named) attributes ... at most, warn 521: continue; 522: } else // xmlns:foo=... 523: prefix = attQName.substring(n+1); 524: 525: String value = qAtts.getValue(i); 526: if (!nsSupport.declarePrefix(prefix, value)) { 527: reportError("Illegal Namespace prefix: " + prefix); 528: continue; 529: } 530: if (contentHandler != null) 531: contentHandler.startPrefixMapping(prefix, value); 532: } 533: 534: // Second pass: copy all relevant 535: // attributes into the SAX2 AttributeList 536: // using updated prefix bindings 537: atts.clear(); 538: for (int i = 0; i < length; i++) { 539: String attQName = qAtts.getName(i); 540: String type = qAtts.getType(i); 541: String value = qAtts.getValue(i); 542: 543: // Declaration? 544: if (attQName.startsWith("xmlns")) { 545: String prefix; 546: int n = attQName.indexOf(':'); 547: 548: if (n == -1 && attQName.length () == 5) { 549: prefix = ""; 550: } else if (n != 5) { 551: // XML namespaces spec doesn't discuss "xmlnsf:oo" 552: // (and similarly named) attributes ... ignore 553: prefix = null; 554: } else { 555: prefix = attQName.substring(6); 556: } 557: // Yes, decl: report or prune 558: if (prefix != null) { 559: if (prefixes) { 560: if (uris) 561: // note funky case: localname can be null 562: // when declaring the default prefix, and 563: // yet the uri isn't null. 564: atts.addAttribute (nsSupport.XMLNS, prefix, 565: attQName.intern(), type, value); 566: else 567: atts.addAttribute ("", "", 568: attQName.intern(), type, value); 569: } 570: continue; 571: } 572: } 573: 574: // Not a declaration -- report 575: try { 576: String attName[] = processName(attQName, true, true); 577: atts.addAttribute(attName[0], attName[1], attName[2], 578: type, value); 579: } catch (SAXException e) { 580: if (exceptions == null) 581: exceptions = new Vector(); 582: exceptions.addElement(e); 583: atts.addAttribute("", attQName, attQName, type, value); 584: } 585: } 586: 587: // now handle the deferred exception reports 588: if (exceptions != null && errorHandler != null) { 589: for (int i = 0; i < exceptions.size(); i++) 590: errorHandler.error((SAXParseException) 591: (exceptions.elementAt(i))); 592: } 593: 594: // OK, finally report the event. 595: if (contentHandler != null) { 596: String name[] = processName(qName, false, false); 597: contentHandler.startElement(name[0], name[1], name[2], atts); 598: } 599: } 600: 601: 602: /** 603: * Adapter implementation method; do not call. 604: * Adapt a SAX1 end element event. 605: * 606: * @param qName The qualified (prefixed) name. 607: * @exception SAXException The client may raise a 608: * processing exception. 609: * @see org.xml.sax.DocumentHandler#endElement 610: */ 611: public void endElement (String qName) 612: throws SAXException 613: { 614: // If we're not doing Namespace 615: // processing, dispatch this quickly. 616: if (!namespaces) { 617: if (contentHandler != null) { 618: contentHandler.endElement("", "", qName.intern()); 619: } 620: return; 621: } 622: 623: // Split the name. 624: String names[] = processName(qName, false, false); 625: if (contentHandler != null) { 626: contentHandler.endElement(names[0], names[1], names[2]); 627: Enumeration prefixes = nsSupport.getDeclaredPrefixes(); 628: while (prefixes.hasMoreElements()) { 629: String prefix = (String)prefixes.nextElement(); 630: contentHandler.endPrefixMapping(prefix); 631: } 632: } 633: nsSupport.popContext(); 634: } 635: 636: 637: /** 638: * Adapter implementation method; do not call. 639: * Adapt a SAX1 characters event. 640: * 641: * @param ch An array of characters. 642: * @param start The starting position in the array. 643: * @param length The number of characters to use. 644: * @exception SAXException The client may raise a 645: * processing exception. 646: * @see org.xml.sax.DocumentHandler#characters 647: */ 648: public void characters (char ch[], int start, int length) 649: throws SAXException 650: { 651: if (contentHandler != null) { 652: contentHandler.characters(ch, start, length); 653: } 654: } 655: 656: 657: /** 658: * Adapter implementation method; do not call. 659: * Adapt a SAX1 ignorable whitespace event. 660: * 661: * @param ch An array of characters. 662: * @param start The starting position in the array. 663: * @param length The number of characters to use. 664: * @exception SAXException The client may raise a 665: * processing exception. 666: * @see org.xml.sax.DocumentHandler#ignorableWhitespace 667: */ 668: public void ignorableWhitespace (char ch[], int start, int length) 669: throws SAXException 670: { 671: if (contentHandler != null) { 672: contentHandler.ignorableWhitespace(ch, start, length); 673: } 674: } 675: 676: 677: /** 678: * Adapter implementation method; do not call. 679: * Adapt a SAX1 processing instruction event. 680: * 681: * @param target The processing instruction target. 682: * @param data The remainder of the processing instruction 683: * @exception SAXException The client may raise a 684: * processing exception. 685: * @see org.xml.sax.DocumentHandler#processingInstruction 686: */ 687: public void processingInstruction (String target, String data) 688: throws SAXException 689: { 690: if (contentHandler != null) { 691: contentHandler.processingInstruction(target, data); 692: } 693: } 694: 695: 696: 697: //////////////////////////////////////////////////////////////////// 698: // Internal utility methods. 699: //////////////////////////////////////////////////////////////////// 700: 701: 702: /** 703: * Initialize the parser before each run. 704: */ 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: private String [] processName (String qName, boolean isAttribute, 743: boolean useException) 744: throws SAXException 745: { 746: String parts[] = nsSupport.processName(qName, nameParts, 747: isAttribute); 748: if (parts == null) { 749: if (useException) 750: throw makeException("Undeclared prefix: " + qName); 751: reportError("Undeclared prefix: " + qName); 752: parts = new String[3]; 753: parts[0] = parts[1] = ""; 754: parts[2] = qName.intern(); 755: } 756: return parts; 757: } 758: 759: 760: /** 761: * Report a non-fatal error. 762: * 763: * @param message The error message. 764: * @exception SAXException The client may throw 765: * an exception. 766: */ 767: void reportError (String message) 768: throws SAXException 769: { 770: if (errorHandler != null) 771: errorHandler.error(makeException(message)); 772: } 773: 774: 775: /** 776: * Construct an exception for the current context. 777: * 778: * @param message The error message. 779: */ 780: private SAXParseException makeException (String message) 781: { 782: if (locator != null) { 783: return new SAXParseException(message, locator); 784: } else { 785: return new SAXParseException(message, null, null, -1, -1); 786: } 787: } 788: 789: 790: /** 791: * Throw an exception if we are parsing. 792: * 793: * <p>Use this method to detect illegal feature or 794: * property changes.</p> 795: * 796: * @param type The type of thing (feature or property). 797: * @param name The feature or property name. 798: * @exception SAXNotSupportedException If a 799: * document is currently being parsed. 800: */ 801: private void checkNotParsing (String type, String name) 802: throws SAXNotSupportedException 803: { 804: if (parsing) { 805: throw new SAXNotSupportedException("Cannot change " + 806: type + ' ' + 807: name + " while parsing"); 808: 809: } 810: } 811: 812: 813: 814: //////////////////////////////////////////////////////////////////// 815: // Internal state. 816: //////////////////////////////////////////////////////////////////// 817: 818: private NamespaceSupport nsSupport; 819: private AttributeListAdapter attAdapter; 820: 821: private boolean parsing = false; 822: private String nameParts[] = new String[3]; 823: 824: private Parser parser = null; 825: 826: private AttributesImpl atts = null; 827: 828: // Features 829: private boolean namespaces = true; 830: private boolean prefixes = false; 831: private boolean uris = false; 832: 833: // Properties 834: 835: // Handlers 836: Locator locator; 837: 838: EntityResolver entityResolver = null; 839: DTDHandler dtdHandler = null; 840: ContentHandler contentHandler = null; 841: ErrorHandler errorHandler = null; 842: 843: 844: 845: //////////////////////////////////////////////////////////////////// 846: // Inner class to wrap an AttributeList when not doing NS proc. 847: //////////////////////////////////////////////////////////////////// 848: 849: 850: /** 851: * Adapt a SAX1 AttributeList as a SAX2 Attributes object. 852: * 853: * <p>This class is in the Public Domain, and comes with NO 854: * WARRANTY of any kind.</p> 855: * 856: * <p>This wrapper class is used only when Namespace support 857: * is disabled -- it provides pretty much a direct mapping 858: * from SAX1 to SAX2, except that names and types are 859: * interned whenever requested.</p> 860: */ 861: final class AttributeListAdapter implements Attributes 862: { 863: 864: /** 865: * Construct a new adapter. 866: */ 867: AttributeListAdapter () 868: { 869: } 870: 871: 872: /** 873: * Set the embedded AttributeList. 874: * 875: * <p>This method must be invoked before any of the others 876: * can be used.</p> 877: * 878: * @param The SAX1 attribute list (with qnames). 879: */ 880: void setAttributeList (AttributeList qAtts) 881: { 882: this.qAtts = qAtts; 883: } 884: 885: 886: /** 887: * Return the length of the attribute list. 888: * 889: * @return The number of attributes in the list. 890: * @see org.xml.sax.Attributes#getLength 891: */ 892: public int getLength () 893: { 894: return qAtts.getLength(); 895: } 896: 897: 898: /** 899: * Return the Namespace URI of the specified attribute. 900: * 901: * @param The attribute's index. 902: * @return Always the empty string. 903: * @see org.xml.sax.Attributes#getURI 904: */ 905: public String getURI (int i) 906: { 907: return ""; 908: } 909: 910: 911: /** 912: * Return the local name of the specified attribute. 913: * 914: * @param The attribute's index. 915: * @return Always the empty string. 916: * @see org.xml.sax.Attributes#getLocalName 917: */ 918: public String getLocalName (int i) 919: { 920: return ""; 921: } 922: 923: 924: /** 925: * Return the qualified (prefixed) name of the specified attribute. 926: * 927: * @param The attribute's index. 928: * @return The attribute's qualified name, internalized. 929: */ 930: public String getQName (int i) 931: { 932: return qAtts.getName(i).intern(); 933: } 934: 935: 936: /** 937: * Return the type of the specified attribute. 938: * 939: * @param The attribute's index. 940: * @return The attribute's type as an internalized string. 941: */ 942: public String getType (int i) 943: { 944: return qAtts.getType(i).intern(); 945: } 946: 947: 948: /** 949: * Return the value of the specified attribute. 950: * 951: * @param The attribute's index. 952: * @return The attribute's value. 953: */ 954: public String getValue (int i) 955: { 956: return qAtts.getValue(i); 957: } 958: 959: 960: /** 961: * Look up an attribute index by Namespace name. 962: * 963: * @param uri The Namespace URI or the empty string. 964: * @param localName The local name. 965: * @return The attributes index, or -1 if none was found. 966: * @see org.xml.sax.Attributes#getIndex(java.lang.String,java.lang.String) 967: */ 968: public int getIndex (String uri, String localName) 969: { 970: return -1; 971: } 972: 973: 974: /** 975: * Look up an attribute index by qualified (prefixed) name. 976: * 977: * @param qName The qualified name. 978: * @return The attributes index, or -1 if none was found. 979: * @see org.xml.sax.Attributes#getIndex(java.lang.String) 980: */ 981: public int getIndex (String qName) 982: { 983: int max = atts.getLength(); 984: for (int i = 0; i < max; i++) { 985: if (qAtts.getName(i).equals(qName)) { 986: return i; 987: } 988: } 989: return -1; 990: } 991: 992: 993: /** 994: * Look up the type of an attribute by Namespace name. 995: * 996: * @param uri The Namespace URI 997: * @param localName The local name. 998: * @return The attribute's type as an internalized string. 999: */ 1000: public String getType (String uri, String localName) 1001: { 1002: return null; 1003: } 1004: 1005: 1006: /** 1007: * Look up the type of an attribute by qualified (prefixed) name. 1008: * 1009: * @param qName The qualified name. 1010: * @return The attribute's type as an internalized string. 1011: */ 1012: public String getType (String qName) 1013: { 1014: return qAtts.getType(qName).intern(); 1015: } 1016: 1017: 1018: /** 1019: * Look up the value of an attribute by Namespace name. 1020: * 1021: * @param uri The Namespace URI 1022: * @param localName The local name. 1023: * @return The attribute's value. 1024: */ 1025: public String getValue (String uri, String localName) 1026: { 1027: return null; 1028: } 1029: 1030: 1031: /** 1032: * Look up the value of an attribute by qualified (prefixed) name. 1033: * 1034: * @param qName The qualified name. 1035: * @return The attribute's value. 1036: */ 1037: public String getValue (String qName) 1038: { 1039: return qAtts.getValue(qName); 1040: } 1041: 1042: private AttributeList qAtts; 1043: } 1044: } 1045: 1046: // end of ParserAdapter.java