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