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