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