1/* 2 * reserved comment block 3 * DO NOT REMOVE OR ALTER! 4 */ 5/* 6 * Licensed to the Apache Software Foundation (ASF) under one or more 7 * contributor license agreements. See the NOTICE file distributed with 8 * this work for additional information regarding copyright ownership. 9 * The ASF licenses this file to You under the Apache License, Version 2.0 10 * (the "License"); you may not use this file except in compliance with 11 * the License. You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, software 16 * distributed under the License is distributed on an "AS IS" BASIS, 17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 * See the License for the specific language governing permissions and 19 * limitations under the License. 20 */ 21 22package com.sun.org.apache.xerces.internal.parsers; 23 24import com.sun.org.apache.xerces.internal.impl.Constants; 25import com.sun.org.apache.xerces.internal.util.EntityResolver2Wrapper; 26import com.sun.org.apache.xerces.internal.util.EntityResolverWrapper; 27import com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper; 28import com.sun.org.apache.xerces.internal.util.SAXMessageFormatter; 29import com.sun.org.apache.xerces.internal.util.Status; 30import com.sun.org.apache.xerces.internal.util.SymbolHash; 31import com.sun.org.apache.xerces.internal.util.XMLSymbols; 32import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager; 33import com.sun.org.apache.xerces.internal.xni.Augmentations; 34import com.sun.org.apache.xerces.internal.xni.NamespaceContext; 35import com.sun.org.apache.xerces.internal.xni.QName; 36import com.sun.org.apache.xerces.internal.xni.XMLAttributes; 37import com.sun.org.apache.xerces.internal.xni.XMLLocator; 38import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier; 39import com.sun.org.apache.xerces.internal.xni.XMLString; 40import com.sun.org.apache.xerces.internal.xni.XNIException; 41import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException; 42import com.sun.org.apache.xerces.internal.xni.parser.XMLEntityResolver; 43import com.sun.org.apache.xerces.internal.xni.parser.XMLErrorHandler; 44import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource; 45import com.sun.org.apache.xerces.internal.xni.parser.XMLParseException; 46import com.sun.org.apache.xerces.internal.xni.parser.XMLParserConfiguration; 47import com.sun.org.apache.xerces.internal.xs.AttributePSVI; 48import com.sun.org.apache.xerces.internal.xs.ElementPSVI; 49import com.sun.org.apache.xerces.internal.xs.PSVIProvider; 50import java.io.IOException; 51import java.util.Locale; 52import javax.xml.XMLConstants; 53import org.xml.sax.AttributeList; 54import org.xml.sax.ContentHandler; 55import org.xml.sax.DTDHandler; 56import org.xml.sax.DocumentHandler; 57import org.xml.sax.EntityResolver; 58import org.xml.sax.ErrorHandler; 59import org.xml.sax.InputSource; 60import org.xml.sax.Parser; 61import org.xml.sax.SAXException; 62import org.xml.sax.SAXNotRecognizedException; 63import org.xml.sax.SAXNotSupportedException; 64import org.xml.sax.SAXParseException; 65import org.xml.sax.XMLReader; 66import org.xml.sax.ext.Attributes2; 67import org.xml.sax.ext.DeclHandler; 68import org.xml.sax.ext.EntityResolver2; 69import org.xml.sax.ext.LexicalHandler; 70import org.xml.sax.ext.Locator2; 71import org.xml.sax.helpers.LocatorImpl; 72 73/** 74 * This is the base class of all SAX parsers. It implements both the 75 * SAX1 and SAX2 parser functionality, while the actual pipeline is 76 * defined in the parser configuration. 77 * 78 * @author Arnaud Le Hors, IBM 79 * @author Andy Clark, IBM 80 * 81 */ 82public abstract class AbstractSAXParser 83 extends AbstractXMLDocumentParser 84 implements PSVIProvider, // PSVI 85 Parser, XMLReader // SAX1, SAX2 86{ 87 88 // 89 // Constants 90 // 91 92 // features 93 94 /** Feature identifier: namespaces. */ 95 protected static final String NAMESPACES = 96 Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACES_FEATURE; 97 98 /** Feature identifier: namespace prefixes. */ 99 protected static final String NAMESPACE_PREFIXES = 100 Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACE_PREFIXES_FEATURE; 101 102 /** Feature id: string interning. */ 103 protected static final String STRING_INTERNING = 104 Constants.SAX_FEATURE_PREFIX + Constants.STRING_INTERNING_FEATURE; 105 106 /** Feature identifier: allow notation and unparsed entity events to be sent out of order. */ 107 // this is not meant to be a recognized feature, but we need it here to use 108 // if it is already a recognized feature for the pipeline 109 protected static final String ALLOW_UE_AND_NOTATION_EVENTS = 110 Constants.SAX_FEATURE_PREFIX + Constants.ALLOW_DTD_EVENTS_AFTER_ENDDTD_FEATURE; 111 112 /** Recognized features. */ 113 private static final String[] RECOGNIZED_FEATURES = { 114 NAMESPACES, 115 NAMESPACE_PREFIXES, 116 STRING_INTERNING, 117 }; 118 119 // properties 120 121 /** Property id: lexical handler. */ 122 protected static final String LEXICAL_HANDLER = 123 Constants.SAX_PROPERTY_PREFIX + Constants.LEXICAL_HANDLER_PROPERTY; 124 125 /** Property id: declaration handler. */ 126 protected static final String DECLARATION_HANDLER = 127 Constants.SAX_PROPERTY_PREFIX + Constants.DECLARATION_HANDLER_PROPERTY; 128 129 /** Property id: DOM node. */ 130 protected static final String DOM_NODE = 131 Constants.SAX_PROPERTY_PREFIX + Constants.DOM_NODE_PROPERTY; 132 133 /** Property id: security manager. */ 134 private static final String SECURITY_MANAGER = 135 Constants.XERCES_PROPERTY_PREFIX + Constants.SECURITY_MANAGER_PROPERTY; 136 137 /** Recognized properties. */ 138 private static final String[] RECOGNIZED_PROPERTIES = { 139 LEXICAL_HANDLER, 140 DECLARATION_HANDLER, 141 DOM_NODE, 142 }; 143 144 // 145 // Data 146 // 147 148 // features 149 150 /** Namespaces. */ 151 protected boolean fNamespaces; 152 153 /** Namespace prefixes. */ 154 protected boolean fNamespacePrefixes = false; 155 156 /** Lexical handler parameter entities. */ 157 protected boolean fLexicalHandlerParameterEntities = true; 158 159 /** Standalone document declaration. */ 160 protected boolean fStandalone; 161 162 /** Resolve DTD URIs. */ 163 protected boolean fResolveDTDURIs = true; 164 165 /** Use EntityResolver2. */ 166 protected boolean fUseEntityResolver2 = true; 167 168 /** 169 * XMLNS URIs: Namespace declarations in the 170 * http://www.w3.org/2000/xmlns/ namespace. 171 */ 172 protected boolean fXMLNSURIs = false; 173 174 // parser handlers 175 176 /** Content handler. */ 177 protected ContentHandler fContentHandler; 178 179 /** Document handler. */ 180 protected DocumentHandler fDocumentHandler; 181 182 /** Namespace context */ 183 protected NamespaceContext fNamespaceContext; 184 185 /** DTD handler. */ 186 protected org.xml.sax.DTDHandler fDTDHandler; 187 188 /** Decl handler. */ 189 protected DeclHandler fDeclHandler; 190 191 /** Lexical handler. */ 192 protected LexicalHandler fLexicalHandler; 193 194 protected QName fQName = new QName(); 195 196 // state 197 198 /** 199 * True if a parse is in progress. This state is needed because 200 * some features/properties cannot be set while parsing (e.g. 201 * validation and namespaces). 202 */ 203 protected boolean fParseInProgress = false; 204 205 // track the version of the document being parsed 206 protected String fVersion; 207 208 // temp vars 209 private final AttributesProxy fAttributesProxy = new AttributesProxy(); 210 private Augmentations fAugmentations = null; 211 212 213 // temporary buffer for sending normalized values 214 // REVISIT: what should be the size of the buffer? 215 private static final int BUFFER_SIZE = 20; 216 private char[] fCharBuffer = new char[BUFFER_SIZE]; 217 218 // allows us to keep track of whether an attribute has 219 // been declared twice, so that we can avoid exposing the 220 // second declaration to any registered DeclHandler 221 protected SymbolHash fDeclaredAttrs = null; 222 223 // 224 // Constructors 225 // 226 227 /** Default constructor. */ 228 protected AbstractSAXParser(XMLParserConfiguration config) { 229 super(config); 230 231 config.addRecognizedFeatures(RECOGNIZED_FEATURES); 232 config.addRecognizedProperties(RECOGNIZED_PROPERTIES); 233 234 try { 235 config.setFeature(ALLOW_UE_AND_NOTATION_EVENTS, false); 236 } 237 catch (XMLConfigurationException e) { 238 // it wasn't a recognized feature, so we don't worry about it 239 } 240 } // <init>(XMLParserConfiguration) 241 242 // 243 // XMLDocumentHandler methods 244 // 245 246 /** 247 * The start of the document. 248 * 249 * @param locator The document locator, or null if the document 250 * location cannot be reported during the parsing 251 * of this document. However, it is <em>strongly</em> 252 * recommended that a locator be supplied that can 253 * at least report the system identifier of the 254 * document. 255 * @param encoding The auto-detected IANA encoding name of the entity 256 * stream. This value will be null in those situations 257 * where the entity encoding is not auto-detected (e.g. 258 * internal entities or a document entity that is 259 * parsed from a java.io.Reader). 260 * @param namespaceContext 261 * The namespace context in effect at the 262 * start of this document. 263 * This object represents the current context. 264 * Implementors of this class are responsible 265 * for copying the namespace bindings from the 266 * the current context (and its parent contexts) 267 * if that information is important. 268 * @param augs Additional information that may include infoset augmentations 269 * 270 * @throws XNIException Thrown by handler to signal an error. 271 */ 272 public void startDocument(XMLLocator locator, String encoding, 273 NamespaceContext namespaceContext, Augmentations augs) 274 throws XNIException { 275 276 fNamespaceContext = namespaceContext; 277 278 try { 279 // SAX1 280 if (fDocumentHandler != null) { 281 if (locator != null) { 282 fDocumentHandler.setDocumentLocator(new LocatorProxy(locator)); 283 } 284 fDocumentHandler.startDocument(); 285 } 286 287 // SAX2 288 if (fContentHandler != null) { 289 if (locator != null) { 290 fContentHandler.setDocumentLocator(new LocatorProxy(locator)); 291 } 292 fContentHandler.startDocument(); 293 } 294 } 295 catch (SAXException e) { 296 throw new XNIException(e); 297 } 298 299 } // startDocument(locator,encoding,augs) 300 301 /** 302 * Notifies of the presence of an XMLDecl line in the document. If 303 * present, this method will be called immediately following the 304 * startDocument call. 305 * 306 * @param version The XML version. 307 * @param encoding The IANA encoding name of the document, or null if 308 * not specified. 309 * @param standalone The standalone value, or null if not specified. 310 * @param augs Additional information that may include infoset augmentations 311 * 312 * @throws XNIException Thrown by handler to signal an error. 313 */ 314 public void xmlDecl(String version, String encoding, String standalone, Augmentations augs) 315 throws XNIException { 316 // the version need only be set once; if 317 // document's XML 1.0|1.1, that's how it'll stay 318 fVersion = version; 319 fStandalone = "yes".equals(standalone); 320 } // xmlDecl(String,String,String) 321 322 /** 323 * Notifies of the presence of the DOCTYPE line in the document. 324 * 325 * @param rootElement The name of the root element. 326 * @param publicId The public identifier if an external DTD or null 327 * if the external DTD is specified using SYSTEM. 328 * @param systemId The system identifier if an external DTD, null 329 * otherwise. 330 * @param augs Additional information that may include infoset augmentations 331 * 332 * @throws XNIException Thrown by handler to signal an error. 333 */ 334 public void doctypeDecl(String rootElement, 335 String publicId, String systemId, Augmentations augs) 336 throws XNIException { 337 fInDTD = true; 338 339 try { 340 // SAX2 extension 341 if (fLexicalHandler != null) { 342 fLexicalHandler.startDTD(rootElement, publicId, systemId); 343 } 344 } 345 catch (SAXException e) { 346 throw new XNIException(e); 347 } 348 349 // is there a DeclHandler? 350 if(fDeclHandler != null) { 351 fDeclaredAttrs = new SymbolHash(); 352 } 353 354 } // doctypeDecl(String,String,String) 355 356 /** 357 * This method notifies of the start of an entity. The DTD has the 358 * pseudo-name of "[dtd]" parameter entity names start with '%'; and 359 * general entity names are just the entity name. 360 * <p> 361 * <strong>Note:</strong> Since the document is an entity, the handler 362 * will be notified of the start of the document entity by calling the 363 * startEntity method with the entity name "[xml]" <em>before</em> calling 364 * the startDocument method. When exposing entity boundaries through the 365 * SAX API, the document entity is never reported, however. 366 * <p> 367 * <strong>Note:</strong> This method is not called for entity references 368 * appearing as part of attribute values. 369 * 370 * @param name The name of the entity. 371 * @param identifier The resource identifier. 372 * @param encoding The auto-detected IANA encoding name of the entity 373 * stream. This value will be null in those situations 374 * where the entity encoding is not auto-detected (e.g. 375 * internal parameter entities). 376 * @param augs Additional information that may include infoset augmentations 377 * 378 * @throws XNIException Thrown by handler to signal an error. 379 */ 380 public void startGeneralEntity(String name, XMLResourceIdentifier identifier, 381 String encoding, Augmentations augs) 382 throws XNIException { 383 384 try { 385 // Only report startEntity if this entity was actually read. 386 if (augs != null && Boolean.TRUE.equals(augs.getItem(Constants.ENTITY_SKIPPED))) { 387 // report skipped entity to content handler 388 if (fContentHandler != null) { 389 fContentHandler.skippedEntity(name); 390 } 391 } 392 else { 393 // SAX2 extension 394 if (fLexicalHandler != null) { 395 fLexicalHandler.startEntity(name); 396 } 397 } 398 } 399 catch (SAXException e) { 400 throw new XNIException(e); 401 } 402 403 } // startGeneralEntity(String,String,String,String,String) 404 405 /** 406 * This method notifies the end of an entity. The DTD has the pseudo-name 407 * of "[dtd]" parameter entity names start with '%'; and general entity 408 * names are just the entity name. 409 * <p> 410 * <strong>Note:</strong> Since the document is an entity, the handler 411 * will be notified of the end of the document entity by calling the 412 * endEntity method with the entity name "[xml]" <em>after</em> calling 413 * the endDocument method. When exposing entity boundaries through the 414 * SAX API, the document entity is never reported, however. 415 * <p> 416 * <strong>Note:</strong> This method is not called for entity references 417 * appearing as part of attribute values. 418 * 419 * @param name The name of the entity. 420 * @param augs Additional information that may include infoset augmentations 421 * 422 * @throws XNIException Thrown by handler to signal an error. 423 */ 424 public void endGeneralEntity(String name, Augmentations augs) throws XNIException { 425 426 try { 427 // Only report endEntity if this entity was actually read. 428 if (augs == null || !Boolean.TRUE.equals(augs.getItem(Constants.ENTITY_SKIPPED))) { 429 // SAX2 extension 430 if (fLexicalHandler != null) { 431 fLexicalHandler.endEntity(name); 432 } 433 } 434 } 435 catch (SAXException e) { 436 throw new XNIException(e); 437 } 438 439 } // endEntity(String) 440 441 /** 442 * The start of an element. If the document specifies the start element 443 * by using an empty tag, then the startElement method will immediately 444 * be followed by the endElement method, with no intervening methods. 445 * 446 * @param element The name of the element. 447 * @param attributes The element attributes. 448 * @param augs Additional information that may include infoset augmentations 449 * 450 * @throws XNIException Thrown by handler to signal an error. 451 */ 452 public void startElement(QName element, XMLAttributes attributes, Augmentations augs) 453 throws XNIException { 454 455 try { 456 // SAX1 457 if (fDocumentHandler != null) { 458 // REVISIT: should we support schema-normalized-value for SAX1 events 459 // 460 fAttributesProxy.setAttributes(attributes); 461 fDocumentHandler.startElement(element.rawname, fAttributesProxy); 462 } 463 464 // SAX2 465 if (fContentHandler != null) { 466 467 if (fNamespaces) { 468 // send prefix mapping events 469 startNamespaceMapping(); 470 471 // REVISIT: It should not be necessary to iterate over the attribute 472 // list when the set of [namespace attributes] is empty for this 473 // element. This should be computable from the NamespaceContext, but 474 // since we currently don't report the mappings for the xml prefix 475 // we cannot use the declared prefix count for the current context 476 // to skip this section. -- mrglavas 477 int len = attributes.getLength(); 478 if (!fNamespacePrefixes) { 479 for (int i = len - 1; i >= 0; --i) { 480 attributes.getName(i, fQName); 481 if ((fQName.prefix == XMLSymbols.PREFIX_XMLNS) || 482 (fQName.rawname == XMLSymbols.PREFIX_XMLNS)) { 483 // remove namespace declaration attributes 484 attributes.removeAttributeAt(i); 485 } 486 } 487 } 488 else if (!fXMLNSURIs) { 489 for (int i = len - 1; i >= 0; --i) { 490 attributes.getName(i, fQName); 491 if ((fQName.prefix == XMLSymbols.PREFIX_XMLNS) || 492 (fQName.rawname == XMLSymbols.PREFIX_XMLNS)) { 493 // localpart should be empty string as per SAX documentation: 494 // http://www.saxproject.org/?selected=namespaces 495 fQName.prefix = ""; 496 fQName.uri = ""; 497 fQName.localpart = ""; 498 attributes.setName(i, fQName); 499 } 500 } 501 } 502 } 503 504 fAugmentations = augs; 505 506 String uri = element.uri != null ? element.uri : ""; 507 String localpart = fNamespaces ? element.localpart : ""; 508 fAttributesProxy.setAttributes(attributes); 509 fContentHandler.startElement(uri, localpart, element.rawname, 510 fAttributesProxy); 511 } 512 } 513 catch (SAXException e) { 514 throw new XNIException(e); 515 } 516 517 } // startElement(QName,XMLAttributes) 518 519 /** 520 * Character content. 521 * 522 * @param text The content. 523 * @param augs Additional information that may include infoset augmentations 524 * 525 * @throws XNIException Thrown by handler to signal an error. 526 */ 527 public void characters(XMLString text, Augmentations augs) throws XNIException { 528 529 // if type is union (XML Schema) it is possible that we receive 530 // character call with empty data 531 if (text.length == 0) { 532 return; 533 } 534 535 536 try { 537 // SAX1 538 if (fDocumentHandler != null) { 539 // REVISIT: should we support schema-normalized-value for SAX1 events 540 // 541 fDocumentHandler.characters(text.ch, text.offset, text.length); 542 } 543 544 // SAX2 545 if (fContentHandler != null) { 546 fContentHandler.characters(text.ch, text.offset, text.length); 547 } 548 } 549 catch (SAXException e) { 550 throw new XNIException(e); 551 } 552 553 } // characters(XMLString) 554 555 /** 556 * Ignorable whitespace. For this method to be called, the document 557 * source must have some way of determining that the text containing 558 * only whitespace characters should be considered ignorable. For 559 * example, the validator can determine if a length of whitespace 560 * characters in the document are ignorable based on the element 561 * content model. 562 * 563 * @param text The ignorable whitespace. 564 * @param augs Additional information that may include infoset augmentations 565 * 566 * @throws XNIException Thrown by handler to signal an error. 567 */ 568 public void ignorableWhitespace(XMLString text, Augmentations augs) throws XNIException { 569 570 try { 571 // SAX1 572 if (fDocumentHandler != null) { 573 fDocumentHandler.ignorableWhitespace(text.ch, text.offset, text.length); 574 } 575 576 // SAX2 577 if (fContentHandler != null) { 578 fContentHandler.ignorableWhitespace(text.ch, text.offset, text.length); 579 } 580 } 581 catch (SAXException e) { 582 throw new XNIException(e); 583 } 584 585 } // ignorableWhitespace(XMLString) 586 587 /** 588 * The end of an element. 589 * 590 * @param element The name of the element. 591 * @param augs Additional information that may include infoset augmentations 592 * 593 * @throws XNIException Thrown by handler to signal an error. 594 */ 595 public void endElement(QName element, Augmentations augs) throws XNIException { 596 597 598 try { 599 // SAX1 600 if (fDocumentHandler != null) { 601 fDocumentHandler.endElement(element.rawname); 602 } 603 604 // SAX2 605 if (fContentHandler != null) { 606 fAugmentations = augs; 607 String uri = element.uri != null ? element.uri : ""; 608 String localpart = fNamespaces ? element.localpart : ""; 609 fContentHandler.endElement(uri, localpart, 610 element.rawname); 611 if (fNamespaces) { 612 endNamespaceMapping(); 613 } 614 } 615 } 616 catch (SAXException e) { 617 throw new XNIException(e); 618 } 619 620 } // endElement(QName) 621 622 /** 623 * The start of a CDATA section. 624 * @param augs Additional information that may include infoset augmentations 625 * 626 * @throws XNIException Thrown by handler to signal an error. 627 */ 628 public void startCDATA(Augmentations augs) throws XNIException { 629 630 try { 631 // SAX2 extension 632 if (fLexicalHandler != null) { 633 fLexicalHandler.startCDATA(); 634 } 635 } 636 catch (SAXException e) { 637 throw new XNIException(e); 638 } 639 640 } // startCDATA() 641 642 /** 643 * The end of a CDATA section. 644 * @param augs Additional information that may include infoset augmentations 645 * 646 * @throws XNIException Thrown by handler to signal an error. 647 */ 648 public void endCDATA(Augmentations augs) throws XNIException { 649 650 try { 651 // SAX2 extension 652 if (fLexicalHandler != null) { 653 fLexicalHandler.endCDATA(); 654 } 655 } 656 catch (SAXException e) { 657 throw new XNIException(e); 658 } 659 660 } // endCDATA() 661 662 /** 663 * A comment. 664 * 665 * @param text The text in the comment. 666 * @param augs Additional information that may include infoset augmentations 667 * 668 * @throws XNIException Thrown by application to signal an error. 669 */ 670 public void comment(XMLString text, Augmentations augs) throws XNIException { 671 672 try { 673 // SAX2 extension 674 if (fLexicalHandler != null) { 675 fLexicalHandler.comment(text.ch, 0, text.length); 676 } 677 } 678 catch (SAXException e) { 679 throw new XNIException(e); 680 } 681 682 } // comment(XMLString) 683 684 /** 685 * A processing instruction. Processing instructions consist of a 686 * target name and, optionally, text data. The data is only meaningful 687 * to the application. 688 * <p> 689 * Typically, a processing instruction's data will contain a series 690 * of pseudo-attributes. These pseudo-attributes follow the form of 691 * element attributes but are <strong>not</strong> parsed or presented 692 * to the application as anything other than text. The application is 693 * responsible for parsing the data. 694 * 695 * @param target The target. 696 * @param data The data or null if none specified. 697 * @param augs Additional information that may include infoset augmentations 698 * 699 * @throws XNIException Thrown by handler to signal an error. 700 */ 701 public void processingInstruction(String target, XMLString data, Augmentations augs) 702 throws XNIException { 703 704 // 705 // REVISIT - I keep running into SAX apps that expect 706 // null data to be an empty string, which is contrary 707 // to the comment for this method in the SAX API. 708 // 709 710 try { 711 // SAX1 712 if (fDocumentHandler != null) { 713 fDocumentHandler.processingInstruction(target, 714 data.toString()); 715 } 716 717 // SAX2 718 if (fContentHandler != null) { 719 fContentHandler.processingInstruction(target, data.toString()); 720 } 721 } 722 catch (SAXException e) { 723 throw new XNIException(e); 724 } 725 726 } // processingInstruction(String,XMLString) 727 728 729 /** 730 * The end of the document. 731 * @param augs Additional information that may include infoset augmentations 732 * 733 * @throws XNIException Thrown by handler to signal an error. 734 */ 735 public void endDocument(Augmentations augs) throws XNIException { 736 737 try { 738 // SAX1 739 if (fDocumentHandler != null) { 740 fDocumentHandler.endDocument(); 741 } 742 743 // SAX2 744 if (fContentHandler != null) { 745 fContentHandler.endDocument(); 746 } 747 } 748 catch (SAXException e) { 749 throw new XNIException(e); 750 } 751 752 } // endDocument() 753 754 // 755 // XMLDTDHandler methods 756 // 757 758 /** 759 * The start of the DTD external subset. 760 * 761 * @param augs Additional information that may include infoset 762 * augmentations. 763 * 764 * @throws XNIException Thrown by handler to signal an error. 765 */ 766 public void startExternalSubset(XMLResourceIdentifier identifier, 767 Augmentations augs) throws XNIException { 768 startParameterEntity("[dtd]", null, null, augs); 769 } 770 771 /** 772 * The end of the DTD external subset. 773 * 774 * @param augs Additional information that may include infoset 775 * augmentations. 776 * 777 * @throws XNIException Thrown by handler to signal an error. 778 */ 779 public void endExternalSubset(Augmentations augs) throws XNIException { 780 endParameterEntity("[dtd]", augs); 781 } 782 783 /** 784 * This method notifies of the start of parameter entity. The DTD has the 785 * pseudo-name of "[dtd]" parameter entity names start with '%'; and 786 * general entity names are just the entity name. 787 * <p> 788 * <strong>Note:</strong> Since the document is an entity, the handler 789 * will be notified of the start of the document entity by calling the 790 * startEntity method with the entity name "[xml]" <em>before</em> calling 791 * the startDocument method. When exposing entity boundaries through the 792 * SAX API, the document entity is never reported, however. 793 * <p> 794 * <strong>Note:</strong> This method is not called for entity references 795 * appearing as part of attribute values. 796 * 797 * @param name The name of the parameter entity. 798 * @param identifier The resource identifier. 799 * @param encoding The auto-detected IANA encoding name of the entity 800 * stream. This value will be null in those situations 801 * where the entity encoding is not auto-detected (e.g. 802 * internal parameter entities). 803 * @param augs Additional information that may include infoset 804 * augmentations. 805 * 806 * @throws XNIException Thrown by handler to signal an error. 807 */ 808 public void startParameterEntity(String name, 809 XMLResourceIdentifier identifier, 810 String encoding, Augmentations augs) 811 throws XNIException { 812 813 try { 814 // Only report startEntity if this entity was actually read. 815 if (augs != null && Boolean.TRUE.equals(augs.getItem(Constants.ENTITY_SKIPPED))) { 816 // report skipped entity to content handler 817 if (fContentHandler != null) { 818 fContentHandler.skippedEntity(name); 819 } 820 } 821 else { 822 // SAX2 extension 823 if (fLexicalHandler != null && fLexicalHandlerParameterEntities) { 824 fLexicalHandler.startEntity(name); 825 } 826 } 827 } 828 catch (SAXException e) { 829 throw new XNIException(e); 830 } 831 832 } // startParameterEntity(String,identifier,String,Augmentation) 833 834 /** 835 * This method notifies the end of an entity. The DTD has the pseudo-name 836 * of "[dtd]" parameter entity names start with '%'; and general entity 837 * names are just the entity name. 838 * <p> 839 * <strong>Note:</strong> Since the document is an entity, the handler 840 * will be notified of the end of the document entity by calling the 841 * endEntity method with the entity name "[xml]" <em>after</em> calling 842 * the endDocument method. When exposing entity boundaries through the 843 * SAX API, the document entity is never reported, however. 844 * <p> 845 * <strong>Note:</strong> This method is not called for entity references 846 * appearing as part of attribute values. 847 * 848 * @param name The name of the parameter entity. 849 * @param augs Additional information that may include infoset 850 * augmentations. 851 * 852 * @throws XNIException Thrown by handler to signal an error. 853 */ 854 public void endParameterEntity(String name, Augmentations augs) throws XNIException { 855 856 try { 857 // Only report endEntity if this entity was actually read. 858 if (augs == null || !Boolean.TRUE.equals(augs.getItem(Constants.ENTITY_SKIPPED))) { 859 // SAX2 extension 860 if (fLexicalHandler != null && fLexicalHandlerParameterEntities) { 861 fLexicalHandler.endEntity(name); 862 } 863 } 864 } 865 catch (SAXException e) { 866 throw new XNIException(e); 867 } 868 869 } // endEntity(String) 870 871 /** 872 * An element declaration. 873 * 874 * @param name The name of the element. 875 * @param contentModel The element content model. 876 * 877 * @param augs Additional information that may include infoset 878 * augmentations. 879 * 880 * @throws XNIException Thrown by handler to signal an error. 881 */ 882 public void elementDecl(String name, String contentModel, Augmentations augs) 883 throws XNIException { 884 885 try { 886 // SAX2 extension 887 if (fDeclHandler != null) { 888 fDeclHandler.elementDecl(name, contentModel); 889 } 890 } 891 catch (SAXException e) { 892 throw new XNIException(e); 893 } 894 895 } // elementDecl(String,String, Augmentations) 896 897 /** 898 * An attribute declaration. 899 * 900 * @param elementName The name of the element that this attribute 901 * is associated with. 902 * @param attributeName The name of the attribute. 903 * @param type The attribute type. This value will be one of 904 * the following: "CDATA", "ENTITY", "ENTITIES", 905 * "ENUMERATION", "ID", "IDREF", "IDREFS", 906 * "NMTOKEN", "NMTOKENS", or "NOTATION". 907 * @param enumeration If the type has the value "ENUMERATION" or 908 * "NOTATION", this array holds the allowed attribute 909 * values; otherwise, this array is null. 910 * @param defaultType The attribute default type. This value will be 911 * one of the following: "#FIXED", "#IMPLIED", 912 * "#REQUIRED", or null. 913 * @param defaultValue The attribute default value, or null if no 914 * default value is specified. 915 * 916 * @param nonNormalizedDefaultValue The attribute default value with no normalization 917 * performed, or null if no default value is specified. 918 * @param augs Additional information that may include infoset 919 * augmentations. 920 * 921 * @throws XNIException Thrown by handler to signal an error. 922 */ 923 public void attributeDecl(String elementName, String attributeName, 924 String type, String[] enumeration, 925 String defaultType, XMLString defaultValue, 926 XMLString nonNormalizedDefaultValue, Augmentations augs) throws XNIException { 927 928 try { 929 // SAX2 extension 930 if (fDeclHandler != null) { 931 // used as a key to detect duplicate attribute definitions. 932 String elemAttr = new StringBuffer(elementName).append("<").append(attributeName).toString(); 933 if(fDeclaredAttrs.get(elemAttr) != null) { 934 // we aren't permitted to return duplicate attribute definitions 935 return; 936 } 937 fDeclaredAttrs.put(elemAttr, Boolean.TRUE); 938 if (type.equals("NOTATION") || 939 type.equals("ENUMERATION")) { 940 941 StringBuffer str = new StringBuffer(); 942 if (type.equals("NOTATION")) { 943 str.append(type); 944 str.append(" ("); 945 } 946 else { 947 str.append("("); 948 } 949 for (int i = 0; i < enumeration.length; i++) { 950 str.append(enumeration[i]); 951 if (i < enumeration.length - 1) { 952 str.append('|'); 953 } 954 } 955 str.append(')'); 956 type = str.toString(); 957 } 958 String value = (defaultValue==null) ? null : defaultValue.toString(); 959 fDeclHandler.attributeDecl(elementName, attributeName, 960 type, defaultType, value); 961 } 962 } 963 catch (SAXException e) { 964 throw new XNIException(e); 965 } 966 967 } // attributeDecl(String,String,String,String[],String,XMLString, XMLString, Augmentations) 968 969 /** 970 * An internal entity declaration. 971 * 972 * @param name The name of the entity. Parameter entity names start with 973 * '%', whereas the name of a general entity is just the 974 * entity name. 975 * @param text The value of the entity. 976 * @param nonNormalizedText The non-normalized value of the entity. This 977 * value contains the same sequence of characters that was in 978 * the internal entity declaration, without any entity 979 * references expanded. 980 * 981 * @param augs Additional information that may include infoset 982 * augmentations. 983 * 984 * @throws XNIException Thrown by handler to signal an error. 985 */ 986 public void internalEntityDecl(String name, XMLString text, 987 XMLString nonNormalizedText, 988 Augmentations augs) throws XNIException { 989 990 try { 991 // SAX2 extensions 992 if (fDeclHandler != null) { 993 fDeclHandler.internalEntityDecl(name, text.toString()); 994 } 995 } 996 catch (SAXException e) { 997 throw new XNIException(e); 998 } 999 1000 } // internalEntityDecl(String,XMLString,XMLString) 1001 1002 /** 1003 * An external entity declaration. 1004 * 1005 * @param name The name of the entity. Parameter entity names start 1006 * with '%', whereas the name of a general entity is just 1007 * the entity name. 1008 * @param identifier An object containing all location information 1009 * pertinent to this entity. 1010 * @param augs Additional information that may include infoset 1011 * augmentations. 1012 * 1013 * @throws XNIException Thrown by handler to signal an error. 1014 */ 1015 public void externalEntityDecl(String name, XMLResourceIdentifier identifier, 1016 Augmentations augs) throws XNIException { 1017 try { 1018 // SAX2 extension 1019 if (fDeclHandler != null) { 1020 String publicId = identifier.getPublicId(); 1021 String systemId = fResolveDTDURIs ? 1022 identifier.getExpandedSystemId() : identifier.getLiteralSystemId(); 1023 fDeclHandler.externalEntityDecl(name, publicId, systemId); 1024 } 1025 } 1026 catch (SAXException e) { 1027 throw new XNIException(e); 1028 } 1029 1030 } // externalEntityDecl(String,,XMLResourceIdentifier, Augmentations) 1031 1032 /** 1033 * An unparsed entity declaration. 1034 * 1035 * @param name The name of the entity. 1036 * @param identifier An object containing all location information 1037 * pertinent to this entity. 1038 * @param notation The name of the notation. 1039 * 1040 * @param augs Additional information that may include infoset 1041 * augmentations. 1042 * 1043 * @throws XNIException Thrown by handler to signal an error. 1044 */ 1045 public void unparsedEntityDecl(String name, XMLResourceIdentifier identifier, 1046 String notation, 1047 Augmentations augs) throws XNIException { 1048 try { 1049 // SAX2 extension 1050 if (fDTDHandler != null) { 1051 String publicId = identifier.getPublicId(); 1052 String systemId = fResolveDTDURIs ? 1053 identifier.getExpandedSystemId() : identifier.getLiteralSystemId(); 1054 fDTDHandler.unparsedEntityDecl(name, publicId, systemId, notation); 1055 } 1056 } 1057 catch (SAXException e) { 1058 throw new XNIException(e); 1059 } 1060 1061 } // unparsedEntityDecl(String,XMLResourceIdentifier, String, Augmentations) 1062 1063 /** 1064 * A notation declaration 1065 * 1066 * @param name The name of the notation. 1067 * @param identifier An object containing all location information 1068 * pertinent to this notation. 1069 * @param augs Additional information that may include infoset 1070 * augmentations. 1071 * 1072 * @throws XNIException Thrown by handler to signal an error. 1073 */ 1074 public void notationDecl(String name, XMLResourceIdentifier identifier, 1075 Augmentations augs) throws XNIException { 1076 try { 1077 // SAX1 and SAX2 1078 if (fDTDHandler != null) { 1079 String publicId = identifier.getPublicId(); 1080 String systemId = fResolveDTDURIs ? 1081 identifier.getExpandedSystemId() : identifier.getLiteralSystemId(); 1082 fDTDHandler.notationDecl(name, publicId, systemId); 1083 } 1084 } 1085 catch (SAXException e) { 1086 throw new XNIException(e); 1087 } 1088 1089 } // notationDecl(String,XMLResourceIdentifier, Augmentations) 1090 1091 /** 1092 * The end of the DTD. 1093 * 1094 * @param augs Additional information that may include infoset 1095 * augmentations. 1096 * 1097 * @throws XNIException Thrown by handler to signal an error. 1098 */ 1099 public void endDTD(Augmentations augs) throws XNIException { 1100 fInDTD = false; 1101 1102 try { 1103 // SAX2 extension 1104 if (fLexicalHandler != null) { 1105 fLexicalHandler.endDTD(); 1106 } 1107 } 1108 catch (SAXException e) { 1109 throw new XNIException(e); 1110 } 1111 if(fDeclaredAttrs != null) { 1112 // help out the GC 1113 fDeclaredAttrs.clear(); 1114 } 1115 1116 } // endDTD() 1117 1118 // 1119 // Parser and XMLReader methods 1120 // 1121 1122 /** 1123 * Parses the input source specified by the given system identifier. 1124 * <p> 1125 * This method is equivalent to the following: 1126 * <pre> 1127 * parse(new InputSource(systemId)); 1128 * </pre> 1129 * 1130 * @param systemId The system identifier (URI). 1131 * 1132 * @exception org.xml.sax.SAXException Throws exception on SAX error. 1133 * @exception java.io.IOException Throws exception on i/o error. 1134 */ 1135 public void parse(String systemId) throws SAXException, IOException { 1136 1137 // parse document 1138 XMLInputSource source = new XMLInputSource(null, systemId, null, false); 1139 try { 1140 parse(source); 1141 } 1142 1143 // wrap XNI exceptions as SAX exceptions 1144 catch (XMLParseException e) { 1145 Exception ex = e.getException(); 1146 if (ex == null) { 1147 // must be a parser exception; mine it for locator info and throw 1148 // a SAXParseException 1149 LocatorImpl locatorImpl = new LocatorImpl(){ 1150 public String getXMLVersion() { 1151 return fVersion; 1152 } 1153 // since XMLParseExceptions know nothing about encoding, 1154 // we cannot return anything meaningful in this context. 1155 // We *could* consult the LocatorProxy, but the 1156 // application can do this itself if it wishes to possibly 1157 // be mislead. 1158 public String getEncoding() { 1159 return null; 1160 } 1161 }; 1162 locatorImpl.setPublicId(e.getPublicId()); 1163 locatorImpl.setSystemId(e.getExpandedSystemId()); 1164 locatorImpl.setLineNumber(e.getLineNumber()); 1165 locatorImpl.setColumnNumber(e.getColumnNumber()); 1166 throw new SAXParseException(e.getMessage(), locatorImpl); 1167 } 1168 if (ex instanceof SAXException) { 1169 // why did we create an XMLParseException? 1170 throw (SAXException)ex; 1171 } 1172 if (ex instanceof IOException) { 1173 throw (IOException)ex; 1174 } 1175 throw new SAXException(ex); 1176 } 1177 catch (XNIException e) { 1178 Exception ex = e.getException(); 1179 if (ex == null) { 1180 throw new SAXException(e.getMessage()); 1181 } 1182 if (ex instanceof SAXException) { 1183 throw (SAXException)ex; 1184 } 1185 if (ex instanceof IOException) { 1186 throw (IOException)ex; 1187 } 1188 throw new SAXException(ex); 1189 } 1190 1191 } // parse(String) 1192 1193 /** 1194 * parse 1195 * 1196 * @param inputSource 1197 * 1198 * @exception org.xml.sax.SAXException 1199 * @exception java.io.IOException 1200 */ 1201 public void parse(InputSource inputSource) 1202 throws SAXException, IOException { 1203 1204 // parse document 1205 try { 1206 XMLInputSource xmlInputSource = 1207 new XMLInputSource(inputSource.getPublicId(), 1208 inputSource.getSystemId(), 1209 null, false); 1210 xmlInputSource.setByteStream(inputSource.getByteStream()); 1211 xmlInputSource.setCharacterStream(inputSource.getCharacterStream()); 1212 xmlInputSource.setEncoding(inputSource.getEncoding()); 1213 parse(xmlInputSource); 1214 } 1215 1216 // wrap XNI exceptions as SAX exceptions 1217 catch (XMLParseException e) { 1218 Exception ex = e.getException(); 1219 if (ex == null) { 1220 // must be a parser exception; mine it for locator info and throw 1221 // a SAXParseException 1222 LocatorImpl locatorImpl = new LocatorImpl() { 1223 public String getXMLVersion() { 1224 return fVersion; 1225 } 1226 // since XMLParseExceptions know nothing about encoding, 1227 // we cannot return anything meaningful in this context. 1228 // We *could* consult the LocatorProxy, but the 1229 // application can do this itself if it wishes to possibly 1230 // be mislead. 1231 public String getEncoding() { 1232 return null; 1233 } 1234 }; 1235 locatorImpl.setPublicId(e.getPublicId()); 1236 locatorImpl.setSystemId(e.getExpandedSystemId()); 1237 locatorImpl.setLineNumber(e.getLineNumber()); 1238 locatorImpl.setColumnNumber(e.getColumnNumber()); 1239 throw new SAXParseException(e.getMessage(), locatorImpl); 1240 } 1241 if (ex instanceof SAXException) { 1242 // why did we create an XMLParseException? 1243 throw (SAXException)ex; 1244 } 1245 if (ex instanceof IOException) { 1246 throw (IOException)ex; 1247 } 1248 throw new SAXException(ex); 1249 } 1250 catch (XNIException e) { 1251 Exception ex = e.getException(); 1252 if (ex == null) { 1253 throw new SAXException(e.getMessage()); 1254 } 1255 if (ex instanceof SAXException) { 1256 throw (SAXException)ex; 1257 } 1258 if (ex instanceof IOException) { 1259 throw (IOException)ex; 1260 } 1261 throw new SAXException(ex); 1262 } 1263 1264 } // parse(InputSource) 1265 1266 /** 1267 * Sets the resolver used to resolve external entities. The EntityResolver 1268 * interface supports resolution of public and system identifiers. 1269 * 1270 * @param resolver The new entity resolver. Passing a null value will 1271 * uninstall the currently installed resolver. 1272 */ 1273 public void setEntityResolver(EntityResolver resolver) { 1274 1275 try { 1276 XMLEntityResolver xer = (XMLEntityResolver) fConfiguration.getProperty(ENTITY_RESOLVER); 1277 if (fUseEntityResolver2 && resolver instanceof EntityResolver2) { 1278 if (xer instanceof EntityResolver2Wrapper) { 1279 EntityResolver2Wrapper er2w = (EntityResolver2Wrapper) xer; 1280 er2w.setEntityResolver((EntityResolver2) resolver); 1281 } 1282 else { 1283 fConfiguration.setProperty(ENTITY_RESOLVER, 1284 new EntityResolver2Wrapper((EntityResolver2) resolver)); 1285 } 1286 } 1287 else { 1288 if (xer instanceof EntityResolverWrapper) { 1289 EntityResolverWrapper erw = (EntityResolverWrapper) xer; 1290 erw.setEntityResolver(resolver); 1291 } 1292 else { 1293 fConfiguration.setProperty(ENTITY_RESOLVER, 1294 new EntityResolverWrapper(resolver)); 1295 } 1296 } 1297 } 1298 catch (XMLConfigurationException e) { 1299 // do nothing 1300 } 1301 1302 } // setEntityResolver(EntityResolver) 1303 1304 /** 1305 * Return the current entity resolver. 1306 * 1307 * @return The current entity resolver, or null if none 1308 * has been registered. 1309 * @see #setEntityResolver 1310 */ 1311 public EntityResolver getEntityResolver() { 1312 1313 EntityResolver entityResolver = null; 1314 try { 1315 XMLEntityResolver xmlEntityResolver = 1316 (XMLEntityResolver)fConfiguration.getProperty(ENTITY_RESOLVER); 1317 if (xmlEntityResolver != null) { 1318 if (xmlEntityResolver instanceof EntityResolverWrapper) { 1319 entityResolver = 1320 ((EntityResolverWrapper) xmlEntityResolver).getEntityResolver(); 1321 } 1322 else if (xmlEntityResolver instanceof EntityResolver2Wrapper) { 1323 entityResolver = 1324 ((EntityResolver2Wrapper) xmlEntityResolver).getEntityResolver(); 1325 } 1326 } 1327 } 1328 catch (XMLConfigurationException e) { 1329 // do nothing 1330 } 1331 return entityResolver; 1332 1333 } // getEntityResolver():EntityResolver 1334 1335 /** 1336 * Allow an application to register an error event handler. 1337 * 1338 * <p>If the application does not register an error handler, all 1339 * error events reported by the SAX parser will be silently 1340 * ignored; however, normal processing may not continue. It is 1341 * highly recommended that all SAX applications implement an 1342 * error handler to avoid unexpected bugs.</p> 1343 * 1344 * <p>Applications may register a new or different handler in the 1345 * middle of a parse, and the SAX parser must begin using the new 1346 * handler immediately.</p> 1347 * 1348 * @param errorHandler The error handler. 1349 * @see #getErrorHandler 1350 */ 1351 public void setErrorHandler(ErrorHandler errorHandler) { 1352 1353 try { 1354 XMLErrorHandler xeh = (XMLErrorHandler) fConfiguration.getProperty(ERROR_HANDLER); 1355 if (xeh instanceof ErrorHandlerWrapper) { 1356 ErrorHandlerWrapper ehw = (ErrorHandlerWrapper) xeh; 1357 ehw.setErrorHandler(errorHandler); 1358 } 1359 else { 1360 fConfiguration.setProperty(ERROR_HANDLER, 1361 new ErrorHandlerWrapper(errorHandler)); 1362 } 1363 } 1364 catch (XMLConfigurationException e) { 1365 // do nothing 1366 } 1367 1368 } // setErrorHandler(ErrorHandler) 1369 1370 /** 1371 * Return the current error handler. 1372 * 1373 * @return The current error handler, or null if none 1374 * has been registered. 1375 * @see #setErrorHandler 1376 */ 1377 public ErrorHandler getErrorHandler() { 1378 1379 ErrorHandler errorHandler = null; 1380 try { 1381 XMLErrorHandler xmlErrorHandler = 1382 (XMLErrorHandler)fConfiguration.getProperty(ERROR_HANDLER); 1383 if (xmlErrorHandler != null && 1384 xmlErrorHandler instanceof ErrorHandlerWrapper) { 1385 errorHandler = ((ErrorHandlerWrapper)xmlErrorHandler).getErrorHandler(); 1386 } 1387 } 1388 catch (XMLConfigurationException e) { 1389 // do nothing 1390 } 1391 return errorHandler; 1392 1393 } // getErrorHandler():ErrorHandler 1394 1395 /** 1396 * Set the locale to use for messages. 1397 * 1398 * @param locale The locale object to use for localization of messages. 1399 * 1400 * @exception SAXException An exception thrown if the parser does not 1401 * support the specified locale. 1402 * 1403 * @see org.xml.sax.Parser 1404 */ 1405 public void setLocale(Locale locale) throws SAXException { 1406 //REVISIT:this methods is not part of SAX2 interfaces, we should throw exception 1407 //if any application uses SAX2 and sets locale also. -nb 1408 fConfiguration.setLocale(locale); 1409 1410 } // setLocale(Locale) 1411 1412 /** 1413 * Allow an application to register a DTD event handler. 1414 * <p> 1415 * If the application does not register a DTD handler, all DTD 1416 * events reported by the SAX parser will be silently ignored. 1417 * <p> 1418 * Applications may register a new or different handler in the 1419 * middle of a parse, and the SAX parser must begin using the new 1420 * handler immediately. 1421 * 1422 * @param dtdHandler The DTD handler. 1423 * 1424 1425 * @see #getDTDHandler 1426 */ 1427 public void setDTDHandler(DTDHandler dtdHandler) { 1428 fDTDHandler = dtdHandler; 1429 } // setDTDHandler(DTDHandler) 1430 1431 // 1432 // Parser methods 1433 // 1434 1435 /** 1436 * Allow an application to register a document event handler. 1437 * <p> 1438 * If the application does not register a document handler, all 1439 * document events reported by the SAX parser will be silently 1440 * ignored (this is the default behaviour implemented by 1441 * HandlerBase). 1442 * <p> 1443 * Applications may register a new or different handler in the 1444 * middle of a parse, and the SAX parser must begin using the new 1445 * handler immediately. 1446 * 1447 * @param documentHandler The document handler. 1448 */ 1449 public void setDocumentHandler(DocumentHandler documentHandler) { 1450 fDocumentHandler = documentHandler; 1451 } // setDocumentHandler(DocumentHandler) 1452 1453 // 1454 // XMLReader methods 1455 // 1456 1457 /** 1458 * Allow an application to register a content event handler. 1459 * <p> 1460 * If the application does not register a content handler, all 1461 * content events reported by the SAX parser will be silently 1462 * ignored. 1463 * <p> 1464 * Applications may register a new or different handler in the 1465 * middle of a parse, and the SAX parser must begin using the new 1466 * handler immediately. 1467 * 1468 * @param contentHandler The content handler. 1469 * 1470 * @see #getContentHandler 1471 */ 1472 public void setContentHandler(ContentHandler contentHandler) { 1473 fContentHandler = contentHandler; 1474 } // setContentHandler(ContentHandler) 1475 1476 /** 1477 * Return the current content handler. 1478 * 1479 * @return The current content handler, or null if none 1480 * has been registered. 1481 * 1482 * @see #setContentHandler 1483 */ 1484 public ContentHandler getContentHandler() { 1485 return fContentHandler; 1486 } // getContentHandler():ContentHandler 1487 1488 /** 1489 * Return the current DTD handler. 1490 * 1491 * @return The current DTD handler, or null if none 1492 * has been registered. 1493 * @see #setDTDHandler 1494 */ 1495 public DTDHandler getDTDHandler() { 1496 return fDTDHandler; 1497 } // getDTDHandler():DTDHandler 1498 1499 /** 1500 * Set the state of any feature in a SAX2 parser. The parser 1501 * might not recognize the feature, and if it does recognize 1502 * it, it might not be able to fulfill the request. 1503 * 1504 * @param featureId The unique identifier (URI) of the feature. 1505 * @param state The requested state of the feature (true or false). 1506 * 1507 * @exception SAXNotRecognizedException If the 1508 * requested feature is not known. 1509 * @exception SAXNotSupportedException If the 1510 * requested feature is known, but the requested 1511 * state is not supported. 1512 */ 1513 public void setFeature(String featureId, boolean state) 1514 throws SAXNotRecognizedException, SAXNotSupportedException { 1515 1516 try { 1517 // 1518 // SAX2 Features 1519 // 1520 1521 if (featureId.startsWith(Constants.SAX_FEATURE_PREFIX)) { 1522 final int suffixLength = featureId.length() - Constants.SAX_FEATURE_PREFIX.length(); 1523 1524 // http://xml.org/sax/features/namespaces 1525 if (suffixLength == Constants.NAMESPACES_FEATURE.length() && 1526 featureId.endsWith(Constants.NAMESPACES_FEATURE)) { 1527 fConfiguration.setFeature(featureId, state); 1528 fNamespaces = state; 1529 return; 1530 } 1531 1532 // http://xml.org/sax/features/namespace-prefixes 1533 // controls the reporting of raw prefixed names and Namespace 1534 // declarations (xmlns* attributes): when this feature is false 1535 // (the default), raw prefixed names may optionally be reported, 1536 // and xmlns* attributes must not be reported. 1537 // 1538 if (suffixLength == Constants.NAMESPACE_PREFIXES_FEATURE.length() && 1539 featureId.endsWith(Constants.NAMESPACE_PREFIXES_FEATURE)) { 1540 fConfiguration.setFeature(featureId, state); 1541 fNamespacePrefixes = state; 1542 return; 1543 } 1544 1545 // http://xml.org/sax/features/string-interning 1546 // controls the use of java.lang.String#intern() for strings 1547 // passed to SAX handlers. 1548 // 1549 if (suffixLength == Constants.STRING_INTERNING_FEATURE.length() && 1550 featureId.endsWith(Constants.STRING_INTERNING_FEATURE)) { 1551 if (!state) { 1552 throw new SAXNotSupportedException( 1553 SAXMessageFormatter.formatMessage(fConfiguration.getLocale(), 1554 "false-not-supported", new Object [] {featureId})); 1555 } 1556 return; 1557 } 1558 1559 // http://xml.org/sax/features/lexical-handler/parameter-entities 1560 // controls whether the beginning and end of parameter entities 1561 // will be reported to the LexicalHandler. 1562 // 1563 if (suffixLength == Constants.LEXICAL_HANDLER_PARAMETER_ENTITIES_FEATURE.length() && 1564 featureId.endsWith(Constants.LEXICAL_HANDLER_PARAMETER_ENTITIES_FEATURE)) { 1565 fLexicalHandlerParameterEntities = state; 1566 return; 1567 } 1568 1569 // http://xml.org/sax/features/resolve-dtd-uris 1570 // controls whether system identifiers will be absolutized relative to 1571 // their base URIs before reporting. 1572 // 1573 if (suffixLength == Constants.RESOLVE_DTD_URIS_FEATURE.length() && 1574 featureId.endsWith(Constants.RESOLVE_DTD_URIS_FEATURE)) { 1575 fResolveDTDURIs = state; 1576 return; 1577 } 1578 1579 // http://xml.org/sax/features/unicode-normalization-checking 1580 // controls whether Unicode normalization checking is performed 1581 // as per Appendix B of the XML 1.1 specification 1582 // 1583 if (suffixLength == Constants.UNICODE_NORMALIZATION_CHECKING_FEATURE.length() && 1584 featureId.endsWith(Constants.UNICODE_NORMALIZATION_CHECKING_FEATURE)) { 1585 // REVISIT: Allow this feature to be set once Unicode normalization 1586 // checking is supported -- mrglavas. 1587 if (state) { 1588 throw new SAXNotSupportedException( 1589 SAXMessageFormatter.formatMessage(fConfiguration.getLocale(), 1590 "true-not-supported", new Object [] {featureId})); 1591 } 1592 return; 1593 } 1594 1595 // http://xml.org/sax/features/xmlns-uris 1596 // controls whether the parser reports that namespace declaration 1597 // attributes as being in the namespace: http://www.w3.org/2000/xmlns/ 1598 // 1599 if (suffixLength == Constants.XMLNS_URIS_FEATURE.length() && 1600 featureId.endsWith(Constants.XMLNS_URIS_FEATURE)) { 1601 fXMLNSURIs = state; 1602 return; 1603 } 1604 1605 // http://xml.org/sax/features/use-entity-resolver2 1606 // controls whether the methods of an object implementing 1607 // org.xml.sax.ext.EntityResolver2 will be used by the parser. 1608 // 1609 if (suffixLength == Constants.USE_ENTITY_RESOLVER2_FEATURE.length() && 1610 featureId.endsWith(Constants.USE_ENTITY_RESOLVER2_FEATURE)) { 1611 if (state != fUseEntityResolver2) { 1612 fUseEntityResolver2 = state; 1613 // Refresh EntityResolver wrapper. 1614 setEntityResolver(getEntityResolver()); 1615 } 1616 return; 1617 } 1618 1619 // 1620 // Read only features. 1621 // 1622 1623 // http://xml.org/sax/features/is-standalone 1624 // reports whether the document specified a standalone document declaration. 1625 // http://xml.org/sax/features/use-attributes2 1626 // reports whether Attributes objects passed to startElement also implement 1627 // the org.xml.sax.ext.Attributes2 interface. 1628 // http://xml.org/sax/features/use-locator2 1629 // reports whether Locator objects passed to setDocumentLocator also implement 1630 // the org.xml.sax.ext.Locator2 interface. 1631 // http://xml.org/sax/features/xml-1.1 1632 // reports whether the parser supports both XML 1.1 and XML 1.0. 1633 if ((suffixLength == Constants.IS_STANDALONE_FEATURE.length() && 1634 featureId.endsWith(Constants.IS_STANDALONE_FEATURE)) || 1635 (suffixLength == Constants.USE_ATTRIBUTES2_FEATURE.length() && 1636 featureId.endsWith(Constants.USE_ATTRIBUTES2_FEATURE)) || 1637 (suffixLength == Constants.USE_LOCATOR2_FEATURE.length() && 1638 featureId.endsWith(Constants.USE_LOCATOR2_FEATURE)) || 1639 (suffixLength == Constants.XML_11_FEATURE.length() && 1640 featureId.endsWith(Constants.XML_11_FEATURE))) { 1641 throw new SAXNotSupportedException( 1642 SAXMessageFormatter.formatMessage(fConfiguration.getLocale(), 1643 "feature-read-only", new Object [] {featureId})); 1644 } 1645 1646 1647 // 1648 // Drop through and perform default processing 1649 // 1650 } 1651 else if (featureId.equals(XMLConstants.FEATURE_SECURE_PROCESSING)) { 1652 if (state) { 1653 if (fConfiguration.getProperty(SECURITY_MANAGER )==null) { 1654 fConfiguration.setProperty(SECURITY_MANAGER, new XMLSecurityManager()); 1655 } 1656 } 1657 } 1658 1659 // 1660 // Default handling 1661 // 1662 1663 fConfiguration.setFeature(featureId, state); 1664 } 1665 catch (XMLConfigurationException e) { 1666 String identifier = e.getIdentifier(); 1667 if (e.getType() == Status.NOT_RECOGNIZED) { 1668 throw new SAXNotRecognizedException( 1669 SAXMessageFormatter.formatMessage(fConfiguration.getLocale(), 1670 "feature-not-recognized", new Object [] {identifier})); 1671 } 1672 else { 1673 throw new SAXNotSupportedException( 1674 SAXMessageFormatter.formatMessage(fConfiguration.getLocale(), 1675 "feature-not-supported", new Object [] {identifier})); 1676 } 1677 } 1678 1679 } // setFeature(String,boolean) 1680 1681 /** 1682 * Query the state of a feature. 1683 * 1684 * Query the current state of any feature in a SAX2 parser. The 1685 * parser might not recognize the feature. 1686 * 1687 * @param featureId The unique identifier (URI) of the feature 1688 * being set. 1689 * @return The current state of the feature. 1690 * @exception org.xml.sax.SAXNotRecognizedException If the 1691 * requested feature is not known. 1692 * @exception SAXNotSupportedException If the 1693 * requested feature is known but not supported. 1694 */ 1695 public boolean getFeature(String featureId) 1696 throws SAXNotRecognizedException, SAXNotSupportedException { 1697 1698 try { 1699 // 1700 // SAX2 Features 1701 // 1702 1703 if (featureId.startsWith(Constants.SAX_FEATURE_PREFIX)) { 1704 final int suffixLength = featureId.length() - Constants.SAX_FEATURE_PREFIX.length(); 1705 1706 // http://xml.org/sax/features/namespace-prefixes 1707 // controls the reporting of raw prefixed names and Namespace 1708 // declarations (xmlns* attributes): when this feature is false 1709 // (the default), raw prefixed names may optionally be reported, 1710 // and xmlns* attributes must not be reported. 1711 // 1712 if (suffixLength == Constants.NAMESPACE_PREFIXES_FEATURE.length() && 1713 featureId.endsWith(Constants.NAMESPACE_PREFIXES_FEATURE)) { 1714 boolean state = fConfiguration.getFeature(featureId); 1715 return state; 1716 } 1717 // http://xml.org/sax/features/string-interning 1718 // controls the use of java.lang.String#intern() for strings 1719 // passed to SAX handlers. 1720 // 1721 if (suffixLength == Constants.STRING_INTERNING_FEATURE.length() && 1722 featureId.endsWith(Constants.STRING_INTERNING_FEATURE)) { 1723 return true; 1724 } 1725 1726 // http://xml.org/sax/features/is-standalone 1727 // reports whether the document specified a standalone document declaration. 1728 // 1729 if (suffixLength == Constants.IS_STANDALONE_FEATURE.length() && 1730 featureId.endsWith(Constants.IS_STANDALONE_FEATURE)) { 1731 return fStandalone; 1732 } 1733 1734 // http://xml.org/sax/features/xml-1.1 1735 // reports whether the parser supports both XML 1.1 and XML 1.0. 1736 // 1737 if (suffixLength == Constants.XML_11_FEATURE.length() && 1738 featureId.endsWith(Constants.XML_11_FEATURE)) { 1739 return (fConfiguration instanceof XML11Configurable); 1740 } 1741 1742 // http://xml.org/sax/features/lexical-handler/parameter-entities 1743 // controls whether the beginning and end of parameter entities 1744 // will be reported to the LexicalHandler. 1745 // 1746 if (suffixLength == Constants.LEXICAL_HANDLER_PARAMETER_ENTITIES_FEATURE.length() && 1747 featureId.endsWith(Constants.LEXICAL_HANDLER_PARAMETER_ENTITIES_FEATURE)) { 1748 return fLexicalHandlerParameterEntities; 1749 } 1750 1751 // http://xml.org/sax/features/resolve-dtd-uris 1752 // controls whether system identifiers will be absolutized relative to 1753 // their base URIs before reporting. 1754 if (suffixLength == Constants.RESOLVE_DTD_URIS_FEATURE.length() && 1755 featureId.endsWith(Constants.RESOLVE_DTD_URIS_FEATURE)) { 1756 return fResolveDTDURIs; 1757 } 1758 1759 // http://xml.org/sax/features/xmlns-uris 1760 // controls whether the parser reports that namespace declaration 1761 // attributes as being in the namespace: http://www.w3.org/2000/xmlns/ 1762 // 1763 if (suffixLength == Constants.XMLNS_URIS_FEATURE.length() && 1764 featureId.endsWith(Constants.XMLNS_URIS_FEATURE)) { 1765 return fXMLNSURIs; 1766 } 1767 1768 // http://xml.org/sax/features/unicode-normalization-checking 1769 // controls whether Unicode normalization checking is performed 1770 // as per Appendix B of the XML 1.1 specification 1771 // 1772 if (suffixLength == Constants.UNICODE_NORMALIZATION_CHECKING_FEATURE.length() && 1773 featureId.endsWith(Constants.UNICODE_NORMALIZATION_CHECKING_FEATURE)) { 1774 // REVISIT: Allow this feature to be set once Unicode normalization 1775 // checking is supported -- mrglavas. 1776 return false; 1777 } 1778 1779 // http://xml.org/sax/features/use-entity-resolver2 1780 // controls whether the methods of an object implementing 1781 // org.xml.sax.ext.EntityResolver2 will be used by the parser. 1782 // 1783 if (suffixLength == Constants.USE_ENTITY_RESOLVER2_FEATURE.length() && 1784 featureId.endsWith(Constants.USE_ENTITY_RESOLVER2_FEATURE)) { 1785 return fUseEntityResolver2; 1786 } 1787 1788 // http://xml.org/sax/features/use-attributes2 1789 // reports whether Attributes objects passed to startElement also implement 1790 // the org.xml.sax.ext.Attributes2 interface. 1791 // http://xml.org/sax/features/use-locator2 1792 // reports whether Locator objects passed to setDocumentLocator also implement 1793 // the org.xml.sax.ext.Locator2 interface. 1794 // 1795 if ((suffixLength == Constants.USE_ATTRIBUTES2_FEATURE.length() && 1796 featureId.endsWith(Constants.USE_ATTRIBUTES2_FEATURE)) || 1797 (suffixLength == Constants.USE_LOCATOR2_FEATURE.length() && 1798 featureId.endsWith(Constants.USE_LOCATOR2_FEATURE))) { 1799 return true; 1800 } 1801 1802 1803 // 1804 // Drop through and perform default processing 1805 // 1806 } 1807 1808 // 1809 // Xerces Features 1810 // 1811 1812 /* 1813 else if (featureId.startsWith(XERCES_FEATURES_PREFIX)) { 1814 // 1815 // Drop through and perform default processing 1816 // 1817 } 1818 */ 1819 1820 return fConfiguration.getFeature(featureId); 1821 } 1822 catch (XMLConfigurationException e) { 1823 String identifier = e.getIdentifier(); 1824 if (e.getType() == Status.NOT_RECOGNIZED) { 1825 throw new SAXNotRecognizedException( 1826 SAXMessageFormatter.formatMessage(fConfiguration.getLocale(), 1827 "feature-not-recognized", new Object [] {identifier})); 1828 } 1829 else { 1830 throw new SAXNotSupportedException( 1831 SAXMessageFormatter.formatMessage(fConfiguration.getLocale(), 1832 "feature-not-supported", new Object [] {identifier})); 1833 } 1834 } 1835 1836 } // getFeature(String):boolean 1837 1838 /** 1839 * Set the value of any property in a SAX2 parser. The parser 1840 * might not recognize the property, and if it does recognize 1841 * it, it might not support the requested value. 1842 * 1843 * @param propertyId The unique identifier (URI) of the property 1844 * being set. 1845 * @param value The value to which the property is being set. 1846 * 1847 * @exception SAXNotRecognizedException If the 1848 * requested property is not known. 1849 * @exception SAXNotSupportedException If the 1850 * requested property is known, but the requested 1851 * value is not supported. 1852 */ 1853 public void setProperty(String propertyId, Object value) 1854 throws SAXNotRecognizedException, SAXNotSupportedException { 1855 1856 try { 1857 // 1858 // SAX2 core properties 1859 // 1860 1861 if (propertyId.startsWith(Constants.SAX_PROPERTY_PREFIX)) { 1862 final int suffixLength = propertyId.length() - Constants.SAX_PROPERTY_PREFIX.length(); 1863 1864 // 1865 // http://xml.org/sax/properties/lexical-handler 1866 // Value type: org.xml.sax.ext.LexicalHandler 1867 // Access: read/write, pre-parse only 1868 // Set the lexical event handler. 1869 // 1870 if (suffixLength == Constants.LEXICAL_HANDLER_PROPERTY.length() && 1871 propertyId.endsWith(Constants.LEXICAL_HANDLER_PROPERTY)) { 1872 try { 1873 setLexicalHandler((LexicalHandler)value); 1874 } 1875 catch (ClassCastException e) { 1876 throw new SAXNotSupportedException( 1877 SAXMessageFormatter.formatMessage(fConfiguration.getLocale(), 1878 "incompatible-class", new Object [] {propertyId, "org.xml.sax.ext.LexicalHandler"})); 1879 } 1880 return; 1881 } 1882 // 1883 // http://xml.org/sax/properties/declaration-handler 1884 // Value type: org.xml.sax.ext.DeclHandler 1885 // Access: read/write, pre-parse only 1886 // Set the DTD declaration event handler. 1887 // 1888 if (suffixLength == Constants.DECLARATION_HANDLER_PROPERTY.length() && 1889 propertyId.endsWith(Constants.DECLARATION_HANDLER_PROPERTY)) { 1890 try { 1891 setDeclHandler((DeclHandler)value); 1892 } 1893 catch (ClassCastException e) { 1894 throw new SAXNotSupportedException( 1895 SAXMessageFormatter.formatMessage(fConfiguration.getLocale(), 1896 "incompatible-class", new Object [] {propertyId, "org.xml.sax.ext.DeclHandler"})); 1897 } 1898 return; 1899 } 1900 // 1901 // http://xml.org/sax/properties/dom-node 1902 // Value type: DOM Node 1903 // Access: read-only 1904 // Get the DOM node currently being visited, if the SAX parser is 1905 // iterating over a DOM tree. If the parser recognises and 1906 // supports this property but is not currently visiting a DOM 1907 // node, it should return null (this is a good way to check for 1908 // availability before the parse begins). 1909 // http://xml.org/sax/properties/document-xml-version 1910 // Value type: java.lang.String 1911 // Access: read-only 1912 // The literal string describing the actual XML version of the document. 1913 // 1914 if ((suffixLength == Constants.DOM_NODE_PROPERTY.length() && 1915 propertyId.endsWith(Constants.DOM_NODE_PROPERTY)) || 1916 (suffixLength == Constants.DOCUMENT_XML_VERSION_PROPERTY.length() && 1917 propertyId.endsWith(Constants.DOCUMENT_XML_VERSION_PROPERTY))) { 1918 throw new SAXNotSupportedException( 1919 SAXMessageFormatter.formatMessage(fConfiguration.getLocale(), 1920 "property-read-only", new Object [] {propertyId})); 1921 } 1922 // 1923 // Drop through and perform default processing 1924 // 1925 } 1926 1927 // 1928 // Xerces Properties 1929 // 1930 1931 /* 1932 else if (propertyId.startsWith(XERCES_PROPERTIES_PREFIX)) { 1933 // 1934 // Drop through and perform default processing 1935 // 1936 } 1937 */ 1938 1939 // 1940 // Perform default processing 1941 // 1942 1943 fConfiguration.setProperty(propertyId, value); 1944 } 1945 catch (XMLConfigurationException e) { 1946 String identifier = e.getIdentifier(); 1947 if (e.getType() == Status.NOT_RECOGNIZED) { 1948 throw new SAXNotRecognizedException( 1949 SAXMessageFormatter.formatMessage(fConfiguration.getLocale(), 1950 "property-not-recognized", new Object [] {identifier})); 1951 } 1952 else { 1953 throw new SAXNotSupportedException( 1954 SAXMessageFormatter.formatMessage(fConfiguration.getLocale(), 1955 "property-not-supported", new Object [] {identifier})); 1956 } 1957 } 1958 1959 } // setProperty(String,Object) 1960 1961 /** 1962 * Query the value of a property. 1963 * 1964 * Return the current value of a property in a SAX2 parser. 1965 * The parser might not recognize the property. 1966 * 1967 * @param propertyId The unique identifier (URI) of the property 1968 * being set. 1969 * @return The current value of the property. 1970 * @exception org.xml.sax.SAXNotRecognizedException If the 1971 * requested property is not known. 1972 * @exception SAXNotSupportedException If the 1973 * requested property is known but not supported. 1974 */ 1975 public Object getProperty(String propertyId) 1976 throws SAXNotRecognizedException, SAXNotSupportedException { 1977 1978 try { 1979 // 1980 // SAX2 core properties 1981 // 1982 1983 if (propertyId.startsWith(Constants.SAX_PROPERTY_PREFIX)) { 1984 final int suffixLength = propertyId.length() - Constants.SAX_PROPERTY_PREFIX.length(); 1985 1986 // 1987 // http://xml.org/sax/properties/document-xml-version 1988 // Value type: java.lang.String 1989 // Access: read-only 1990 // The literal string describing the actual XML version of the document. 1991 // 1992 if (suffixLength == Constants.DOCUMENT_XML_VERSION_PROPERTY.length() && 1993 propertyId.endsWith(Constants.DOCUMENT_XML_VERSION_PROPERTY)) { 1994 return fVersion; 1995 } 1996 1997 // 1998 // http://xml.org/sax/properties/lexical-handler 1999 // Value type: org.xml.sax.ext.LexicalHandler 2000 // Access: read/write, pre-parse only 2001 // Set the lexical event handler. 2002 // 2003 if (suffixLength == Constants.LEXICAL_HANDLER_PROPERTY.length() && 2004 propertyId.endsWith(Constants.LEXICAL_HANDLER_PROPERTY)) { 2005 return getLexicalHandler(); 2006 } 2007 // 2008 // http://xml.org/sax/properties/declaration-handler 2009 // Value type: org.xml.sax.ext.DeclHandler 2010 // Access: read/write, pre-parse only 2011 // Set the DTD declaration event handler. 2012 // 2013 if (suffixLength == Constants.DECLARATION_HANDLER_PROPERTY.length() && 2014 propertyId.endsWith(Constants.DECLARATION_HANDLER_PROPERTY)) { 2015 return getDeclHandler(); 2016 } 2017 2018 // 2019 // http://xml.org/sax/properties/dom-node 2020 // Value type: DOM Node 2021 // Access: read-only 2022 // Get the DOM node currently being visited, if the SAX parser is 2023 // iterating over a DOM tree. If the parser recognises and 2024 // supports this property but is not currently visiting a DOM 2025 // node, it should return null (this is a good way to check for 2026 // availability before the parse begins). 2027 // 2028 if (suffixLength == Constants.DOM_NODE_PROPERTY.length() && 2029 propertyId.endsWith(Constants.DOM_NODE_PROPERTY)) { 2030 // we are not iterating a DOM tree 2031 throw new SAXNotSupportedException( 2032 SAXMessageFormatter.formatMessage(fConfiguration.getLocale(), 2033 "dom-node-read-not-supported", null)); 2034 } 2035 2036 // 2037 // Drop through and perform default processing 2038 // 2039 } 2040 2041 // 2042 // Xerces properties 2043 // 2044 2045 /* 2046 else if (propertyId.startsWith(XERCES_PROPERTIES_PREFIX)) { 2047 // 2048 // Drop through and perform default processing 2049 // 2050 } 2051 */ 2052 2053 // 2054 // Perform default processing 2055 // 2056 2057 return fConfiguration.getProperty(propertyId); 2058 } 2059 catch (XMLConfigurationException e) { 2060 String identifier = e.getIdentifier(); 2061 if (e.getType() == Status.NOT_RECOGNIZED) { 2062 throw new SAXNotRecognizedException( 2063 SAXMessageFormatter.formatMessage(fConfiguration.getLocale(), 2064 "property-not-recognized", new Object [] {identifier})); 2065 } 2066 else { 2067 throw new SAXNotSupportedException( 2068 SAXMessageFormatter.formatMessage(fConfiguration.getLocale(), 2069 "property-not-supported", new Object [] {identifier})); 2070 } 2071 } 2072 2073 } // getProperty(String):Object 2074 2075 // 2076 // Protected methods 2077 // 2078 2079 // SAX2 core properties 2080 2081 /** 2082 * Set the DTD declaration event handler. 2083 * <p> 2084 * This method is the equivalent to the property: 2085 * <pre> 2086 * http://xml.org/sax/properties/declaration-handler 2087 * </pre> 2088 * 2089 * @param handler The new handler. 2090 * 2091 * @see #getDeclHandler 2092 * @see #setProperty 2093 */ 2094 protected void setDeclHandler(DeclHandler handler) 2095 throws SAXNotRecognizedException, SAXNotSupportedException { 2096 2097 if (fParseInProgress) { 2098 throw new SAXNotSupportedException( 2099 SAXMessageFormatter.formatMessage(fConfiguration.getLocale(), 2100 "property-not-parsing-supported", 2101 new Object [] {"http://xml.org/sax/properties/declaration-handler"})); 2102 } 2103 fDeclHandler = handler; 2104 2105 } // setDeclHandler(DeclHandler) 2106 2107 /** 2108 * Returns the DTD declaration event handler. 2109 * 2110 * @see #setDeclHandler 2111 */ 2112 protected DeclHandler getDeclHandler() 2113 throws SAXNotRecognizedException, SAXNotSupportedException { 2114 return fDeclHandler; 2115 } // getDeclHandler():DeclHandler 2116 2117 /** 2118 * Set the lexical event handler. 2119 * <p> 2120 * This method is the equivalent to the property: 2121 * <pre> 2122 * http://xml.org/sax/properties/lexical-handler 2123 * </pre> 2124 * 2125 * @param handler lexical event handler 2126 * 2127 * @see #getLexicalHandler 2128 * @see #setProperty 2129 */ 2130 protected void setLexicalHandler(LexicalHandler handler) 2131 throws SAXNotRecognizedException, SAXNotSupportedException { 2132 2133 if (fParseInProgress) { 2134 throw new SAXNotSupportedException( 2135 SAXMessageFormatter.formatMessage(fConfiguration.getLocale(), 2136 "property-not-parsing-supported", 2137 new Object [] {"http://xml.org/sax/properties/lexical-handler"})); 2138 } 2139 fLexicalHandler = handler; 2140 2141 } // setLexicalHandler(LexicalHandler) 2142 2143 /** 2144 * Returns the lexical handler. 2145 * 2146 * @see #setLexicalHandler 2147 */ 2148 protected LexicalHandler getLexicalHandler() 2149 throws SAXNotRecognizedException, SAXNotSupportedException { 2150 return fLexicalHandler; 2151 } // getLexicalHandler():LexicalHandler 2152 2153 /** 2154 * Send startPrefixMapping events 2155 */ 2156 protected final void startNamespaceMapping() throws SAXException{ 2157 int count = fNamespaceContext.getDeclaredPrefixCount(); 2158 if (count > 0) { 2159 String prefix = null; 2160 String uri = null; 2161 for (int i = 0; i < count; i++) { 2162 prefix = fNamespaceContext.getDeclaredPrefixAt(i); 2163 uri = fNamespaceContext.getURI(prefix); 2164 fContentHandler.startPrefixMapping(prefix, 2165 (uri == null) ? "" : uri); 2166 } 2167 } 2168 } 2169 2170 /** 2171 * Send endPrefixMapping events 2172 */ 2173 protected final void endNamespaceMapping() throws SAXException { 2174 int count = fNamespaceContext.getDeclaredPrefixCount(); 2175 if (count > 0) { 2176 for (int i = 0; i < count; i++) { 2177 fContentHandler.endPrefixMapping(fNamespaceContext.getDeclaredPrefixAt(i)); 2178 } 2179 } 2180 } 2181 2182 // 2183 // XMLDocumentParser methods 2184 // 2185 2186 /** 2187 * Reset all components before parsing. 2188 * 2189 * @throws XNIException Thrown if an error occurs during initialization. 2190 */ 2191 public void reset() throws XNIException { 2192 super.reset(); 2193 2194 // reset state 2195 fInDTD = false; 2196 fVersion = "1.0"; 2197 fStandalone = false; 2198 2199 // features 2200 fNamespaces = fConfiguration.getFeature(NAMESPACES); 2201 fNamespacePrefixes = fConfiguration.getFeature(NAMESPACE_PREFIXES); 2202 fAugmentations = null; 2203 fDeclaredAttrs = null; 2204 2205 } // reset() 2206 2207 // 2208 // Classes 2209 // 2210 2211 protected class LocatorProxy 2212 implements Locator2 { 2213 2214 // 2215 // Data 2216 // 2217 2218 /** XML locator. */ 2219 protected XMLLocator fLocator; 2220 2221 // 2222 // Constructors 2223 // 2224 2225 /** Constructs an XML locator proxy. */ 2226 public LocatorProxy(XMLLocator locator) { 2227 fLocator = locator; 2228 } 2229 2230 // 2231 // Locator methods 2232 // 2233 2234 /** Public identifier. */ 2235 public String getPublicId() { 2236 return fLocator.getPublicId(); 2237 } 2238 2239 /** System identifier. */ 2240 public String getSystemId() { 2241 return fLocator.getExpandedSystemId(); 2242 } 2243 /** Line number. */ 2244 public int getLineNumber() { 2245 return fLocator.getLineNumber(); 2246 } 2247 2248 /** Column number. */ 2249 public int getColumnNumber() { 2250 return fLocator.getColumnNumber(); 2251 } 2252 2253 // Locator2 methods 2254 public String getXMLVersion() { 2255 return fLocator.getXMLVersion(); 2256 } 2257 2258 public String getEncoding() { 2259 return fLocator.getEncoding(); 2260 } 2261 2262 } // class LocatorProxy 2263 2264 protected static final class AttributesProxy 2265 implements AttributeList, Attributes2 { 2266 2267 // 2268 // Data 2269 // 2270 2271 /** XML attributes. */ 2272 protected XMLAttributes fAttributes; 2273 2274 // 2275 // Public methods 2276 // 2277 2278 /** Sets the XML attributes. */ 2279 public void setAttributes(XMLAttributes attributes) { 2280 fAttributes = attributes; 2281 } // setAttributes(XMLAttributes) 2282 2283 public int getLength() { 2284 return fAttributes.getLength(); 2285 } 2286 2287 public String getName(int i) { 2288 return fAttributes.getQName(i); 2289 } 2290 2291 public String getQName(int index) { 2292 return fAttributes.getQName(index); 2293 } 2294 2295 public String getURI(int index) { 2296 // REVISIT: this hides the fact that internally we use 2297 // null instead of empty string 2298 // SAX requires URI to be a string or an empty string 2299 String uri= fAttributes.getURI(index); 2300 return uri != null ? uri : ""; 2301 } 2302 2303 public String getLocalName(int index) { 2304 return fAttributes.getLocalName(index); 2305 } 2306 2307 public String getType(int i) { 2308 return fAttributes.getType(i); 2309 } 2310 2311 public String getType(String name) { 2312 return fAttributes.getType(name); 2313 } 2314 2315 public String getType(String uri, String localName) { 2316 return uri.equals("") ? fAttributes.getType(null, localName) : 2317 fAttributes.getType(uri, localName); 2318 } 2319 2320 public String getValue(int i) { 2321 return fAttributes.getValue(i); 2322 } 2323 2324 public String getValue(String name) { 2325 return fAttributes.getValue(name); 2326 } 2327 2328 public String getValue(String uri, String localName) { 2329 return uri.equals("") ? fAttributes.getValue(null, localName) : 2330 fAttributes.getValue(uri, localName); 2331 } 2332 2333 public int getIndex(String qName) { 2334 return fAttributes.getIndex(qName); 2335 } 2336 2337 public int getIndex(String uri, String localPart) { 2338 return uri.equals("") ? fAttributes.getIndex(null, localPart) : 2339 fAttributes.getIndex(uri, localPart); 2340 } 2341 2342 // Attributes2 methods 2343 // REVISIT: Localize exception messages. -- mrglavas 2344 public boolean isDeclared(int index) { 2345 if (index < 0 || index >= fAttributes.getLength()) { 2346 throw new ArrayIndexOutOfBoundsException(index); 2347 } 2348 return Boolean.TRUE.equals( 2349 fAttributes.getAugmentations(index).getItem( 2350 Constants.ATTRIBUTE_DECLARED)); 2351 } 2352 2353 public boolean isDeclared(String qName) { 2354 int index = getIndex(qName); 2355 if (index == -1) { 2356 throw new IllegalArgumentException(qName); 2357 } 2358 return Boolean.TRUE.equals( 2359 fAttributes.getAugmentations(index).getItem( 2360 Constants.ATTRIBUTE_DECLARED)); 2361 } 2362 2363 public boolean isDeclared(String uri, String localName) { 2364 int index = getIndex(uri, localName); 2365 if (index == -1) { 2366 throw new IllegalArgumentException(localName); 2367 } 2368 return Boolean.TRUE.equals( 2369 fAttributes.getAugmentations(index).getItem( 2370 Constants.ATTRIBUTE_DECLARED)); 2371 } 2372 2373 public boolean isSpecified(int index) { 2374 if (index < 0 || index >= fAttributes.getLength()) { 2375 throw new ArrayIndexOutOfBoundsException(index); 2376 } 2377 return fAttributes.isSpecified(index); 2378 } 2379 2380 public boolean isSpecified(String qName) { 2381 int index = getIndex(qName); 2382 if (index == -1) { 2383 throw new IllegalArgumentException(qName); 2384 } 2385 return fAttributes.isSpecified(index); 2386 } 2387 2388 public boolean isSpecified(String uri, String localName) { 2389 int index = getIndex(uri, localName); 2390 if (index == -1) { 2391 throw new IllegalArgumentException(localName); 2392 } 2393 return fAttributes.isSpecified(index); 2394 } 2395 2396 } // class AttributesProxy 2397 2398 2399 // PSVIProvider methods 2400 2401 public ElementPSVI getElementPSVI(){ 2402 return (fAugmentations != null)?(ElementPSVI)fAugmentations.getItem(Constants.ELEMENT_PSVI):null; 2403 } 2404 2405 2406 public AttributePSVI getAttributePSVI(int index){ 2407 2408 return (AttributePSVI)fAttributesProxy.fAttributes.getAugmentations(index).getItem(Constants.ATTRIBUTE_PSVI); 2409 } 2410 2411 2412 public AttributePSVI getAttributePSVIByName(String uri, 2413 String localname){ 2414 return (AttributePSVI)fAttributesProxy.fAttributes.getAugmentations(uri, localname).getItem(Constants.ATTRIBUTE_PSVI); 2415 } 2416 2417} // class AbstractSAXParser 2418