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