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