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