1 /* 2 * reserved comment block 3 * DO NOT REMOVE OR ALTER! 4 */ 5 /* 6 * Licensed to the Apache Software Foundation (ASF) under one or more 7 * contributor license agreements. See the NOTICE file distributed with 8 * this work for additional information regarding copyright ownership. 9 * The ASF licenses this file to You under the Apache License, Version 2.0 10 * (the "License"); you may not use this file except in compliance with 11 * the License. You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, software 16 * distributed under the License is distributed on an "AS IS" BASIS, 17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 * See the License for the specific language governing permissions and 19 * limitations under the License. 20 */ 21 22 package com.sun.org.apache.xerces.internal.parsers; 23 24 import java.io.IOException; 25 26 import com.sun.org.apache.xerces.internal.impl.Constants; 27 import com.sun.org.apache.xerces.internal.util.EntityResolverWrapper; 28 import com.sun.org.apache.xerces.internal.util.EntityResolver2Wrapper; 29 import com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper; 30 import com.sun.org.apache.xerces.internal.util.SAXMessageFormatter; 31 import com.sun.org.apache.xerces.internal.util.Status; 32 import com.sun.org.apache.xerces.internal.util.SymbolTable; 33 import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager; 34 import com.sun.org.apache.xerces.internal.utils.XMLSecurityPropertyManager; 35 import com.sun.org.apache.xerces.internal.xni.XNIException; 36 import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarPool; 37 import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException; 38 import com.sun.org.apache.xerces.internal.xni.parser.XMLEntityResolver; 39 import com.sun.org.apache.xerces.internal.xni.parser.XMLErrorHandler; 40 import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource; 41 import com.sun.org.apache.xerces.internal.xni.parser.XMLParseException; 42 import com.sun.org.apache.xerces.internal.xni.parser.XMLParserConfiguration; 43 import org.w3c.dom.Node; 44 import org.xml.sax.EntityResolver; 45 import org.xml.sax.ErrorHandler; 46 import org.xml.sax.InputSource; 47 import org.xml.sax.SAXException; 48 import org.xml.sax.SAXNotRecognizedException; 49 import org.xml.sax.SAXNotSupportedException; 50 import org.xml.sax.SAXParseException; 51 import org.xml.sax.ext.EntityResolver2; 52 import org.xml.sax.helpers.LocatorImpl; 53 54 /** 55 * This is the main Xerces DOM parser class. It uses the abstract DOM 56 * parser with a document scanner, a dtd scanner, and a validator, as 57 * well as a grammar pool. 58 * 59 * @author Arnaud Le Hors, IBM 60 * @author Andy Clark, IBM 61 * 62 * @version $Id: DOMParser.java,v 1.7 2010-11-01 04:40:09 joehw Exp $ 63 */ 64 public class DOMParser 65 extends AbstractDOMParser { 66 67 // 68 // Constants 69 // 70 71 // features 72 73 /** Feature identifier: EntityResolver2. */ 74 protected static final String USE_ENTITY_RESOLVER2 = 75 Constants.SAX_FEATURE_PREFIX + Constants.USE_ENTITY_RESOLVER2_FEATURE; 76 77 protected static final String REPORT_WHITESPACE = 78 Constants.SUN_SCHEMA_FEATURE_PREFIX + Constants.SUN_REPORT_IGNORED_ELEMENT_CONTENT_WHITESPACE; 79 80 /** Property identifier: Security property manager. */ 81 private static final String XML_SECURITY_PROPERTY_MANAGER = 82 Constants.XML_SECURITY_PROPERTY_MANAGER; 83 84 // recognized features: 85 private static final String[] RECOGNIZED_FEATURES = { 86 REPORT_WHITESPACE 87 }; 88 89 // properties 90 91 /** Property identifier: symbol table. */ 92 protected static final String SYMBOL_TABLE = 93 Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY; 94 95 /** Property identifier: XML grammar pool. */ 96 protected static final String XMLGRAMMAR_POOL = 97 Constants.XERCES_PROPERTY_PREFIX+Constants.XMLGRAMMAR_POOL_PROPERTY; 98 99 /** Recognized properties. */ 100 private static final String[] RECOGNIZED_PROPERTIES = { 101 SYMBOL_TABLE, 102 XMLGRAMMAR_POOL, 103 }; 104 105 // 106 // Data 107 // 108 109 // features 110 111 /** Use EntityResolver2. */ 112 protected boolean fUseEntityResolver2 = true; 113 114 // 115 // Constructors 116 // 117 118 /** 119 * Constructs a DOM parser using the specified parser configuration. 120 */ 121 public DOMParser(XMLParserConfiguration config) { 122 super(config); 123 } // <init>(XMLParserConfiguration) 124 125 /** 126 * Constructs a DOM parser using the dtd/xml schema parser configuration. 127 */ 128 public DOMParser() { 129 this(null, null); 130 } // <init>() 131 132 /** 133 * Constructs a DOM parser using the specified symbol table. 134 */ 135 public DOMParser(SymbolTable symbolTable) { 136 this(symbolTable, null); 137 } // <init>(SymbolTable) 138 139 140 /** 141 * Constructs a DOM parser using the specified symbol table and 142 * grammar pool. 143 */ 144 public DOMParser(SymbolTable symbolTable, XMLGrammarPool grammarPool) { 145 super(new XIncludeAwareParserConfiguration()); 146 147 // set properties 148 fConfiguration.addRecognizedProperties(RECOGNIZED_PROPERTIES); 149 if (symbolTable != null) { 150 fConfiguration.setProperty(SYMBOL_TABLE, symbolTable); 151 } 152 if (grammarPool != null) { 153 fConfiguration.setProperty(XMLGRAMMAR_POOL, grammarPool); 154 } 155 156 fConfiguration.addRecognizedFeatures(RECOGNIZED_FEATURES); 157 158 } // <init>(SymbolTable,XMLGrammarPool) 159 160 // 161 // XMLReader methods 162 // 163 164 /** 165 * Parses the input source specified by the given system identifier. 166 * <p> 167 * This method is equivalent to the following: 168 * <pre> 169 * parse(new InputSource(systemId)); 170 * </pre> 171 * 172 * @param systemId The system identifier (URI). 173 * 174 * @exception org.xml.sax.SAXException Throws exception on SAX error. 175 * @exception java.io.IOException Throws exception on i/o error. 176 */ 177 public void parse(String systemId) throws SAXException, IOException { 178 179 // parse document 180 XMLInputSource source = new XMLInputSource(null, systemId, null); 181 try { 182 parse(source); 183 } 184 185 // wrap XNI exceptions as SAX exceptions 186 catch (XMLParseException e) { 187 Exception ex = e.getException(); 188 if (ex == null) { 189 // must be a parser exception; mine it for locator info and throw 190 // a SAXParseException 191 LocatorImpl locatorImpl = new LocatorImpl(); 192 locatorImpl.setPublicId(e.getPublicId()); 193 locatorImpl.setSystemId(e.getExpandedSystemId()); 194 locatorImpl.setLineNumber(e.getLineNumber()); 195 locatorImpl.setColumnNumber(e.getColumnNumber()); 196 throw new SAXParseException(e.getMessage(), locatorImpl); 197 } 198 if (ex instanceof SAXException) { 199 // why did we create an XMLParseException? 200 throw (SAXException)ex; 201 } 202 if (ex instanceof IOException) { 203 throw (IOException)ex; 204 } 205 throw new SAXException(ex); 206 } 207 catch (XNIException e) { 208 e.printStackTrace(); 209 Exception ex = e.getException(); 210 if (ex == null) { 211 throw new SAXException(e.getMessage()); 212 } 213 if (ex instanceof SAXException) { 214 throw (SAXException)ex; 215 } 216 if (ex instanceof IOException) { 217 throw (IOException)ex; 218 } 219 throw new SAXException(ex); 220 } 221 222 } // parse(String) 223 224 /** 225 * parse 226 * 227 * @param inputSource 228 * 229 * @exception org.xml.sax.SAXException 230 * @exception java.io.IOException 231 */ 232 public void parse(InputSource inputSource) 233 throws SAXException, IOException { 234 235 // parse document 236 try { 237 XMLInputSource xmlInputSource = 238 new XMLInputSource(inputSource.getPublicId(), 239 inputSource.getSystemId(), 240 null); 241 xmlInputSource.setByteStream(inputSource.getByteStream()); 242 xmlInputSource.setCharacterStream(inputSource.getCharacterStream()); 243 xmlInputSource.setEncoding(inputSource.getEncoding()); 244 parse(xmlInputSource); 245 } 246 247 // wrap XNI exceptions as SAX exceptions 248 catch (XMLParseException e) { 249 Exception ex = e.getException(); 250 if (ex == null) { 251 // must be a parser exception; mine it for locator info and throw 252 // a SAXParseException 253 LocatorImpl locatorImpl = new LocatorImpl(); 254 locatorImpl.setPublicId(e.getPublicId()); 255 locatorImpl.setSystemId(e.getExpandedSystemId()); 256 locatorImpl.setLineNumber(e.getLineNumber()); 257 locatorImpl.setColumnNumber(e.getColumnNumber()); 258 throw new SAXParseException(e.getMessage(), locatorImpl); 259 } 260 if (ex instanceof SAXException) { 261 // why did we create an XMLParseException? 262 throw (SAXException)ex; 263 } 264 if (ex instanceof IOException) { 265 throw (IOException)ex; 266 } 267 throw new SAXException(ex); 268 } 269 catch (XNIException e) { 270 Exception ex = e.getException(); 271 if (ex == null) { 272 throw new SAXException(e.getMessage()); 273 } 274 if (ex instanceof SAXException) { 275 throw (SAXException)ex; 276 } 277 if (ex instanceof IOException) { 278 throw (IOException)ex; 279 } 280 throw new SAXException(ex); 281 } 282 283 } // parse(InputSource) 284 285 /** 286 * Sets the resolver used to resolve external entities. The EntityResolver 287 * interface supports resolution of public and system identifiers. 288 * 289 * @param resolver The new entity resolver. Passing a null value will 290 * uninstall the currently installed resolver. 291 */ 292 public void setEntityResolver(EntityResolver resolver) { 293 294 try { 295 XMLEntityResolver xer = (XMLEntityResolver) fConfiguration.getProperty(ENTITY_RESOLVER); 296 if (fUseEntityResolver2 && resolver instanceof EntityResolver2) { 297 if (xer instanceof EntityResolver2Wrapper) { 298 EntityResolver2Wrapper er2w = (EntityResolver2Wrapper) xer; 299 er2w.setEntityResolver((EntityResolver2) resolver); 300 } 301 else { 302 fConfiguration.setProperty(ENTITY_RESOLVER, 303 new EntityResolver2Wrapper((EntityResolver2) resolver)); 304 } 305 } 306 else { 307 if (xer instanceof EntityResolverWrapper) { 308 EntityResolverWrapper erw = (EntityResolverWrapper) xer; 309 erw.setEntityResolver(resolver); 310 } 311 else { 312 fConfiguration.setProperty(ENTITY_RESOLVER, 313 new EntityResolverWrapper(resolver)); 314 } 315 } 316 } 317 catch (XMLConfigurationException e) { 318 // do nothing 319 } 320 321 } // setEntityResolver(EntityResolver) 322 323 /** 324 * Return the current entity resolver. 325 * 326 * @return The current entity resolver, or null if none 327 * has been registered. 328 * @see #setEntityResolver 329 */ 330 public EntityResolver getEntityResolver() { 331 332 EntityResolver entityResolver = null; 333 try { 334 XMLEntityResolver xmlEntityResolver = 335 (XMLEntityResolver)fConfiguration.getProperty(ENTITY_RESOLVER); 336 if (xmlEntityResolver != null) { 337 if (xmlEntityResolver instanceof EntityResolverWrapper) { 338 entityResolver = 339 ((EntityResolverWrapper) xmlEntityResolver).getEntityResolver(); 340 } 341 else if (xmlEntityResolver instanceof EntityResolver2Wrapper) { 342 entityResolver = 343 ((EntityResolver2Wrapper) xmlEntityResolver).getEntityResolver(); 344 } 345 } 346 } 347 catch (XMLConfigurationException e) { 348 // do nothing 349 } 350 return entityResolver; 351 352 } // getEntityResolver():EntityResolver 353 354 /** 355 * Allow an application to register an error event handler. 356 * 357 * <p>If the application does not register an error handler, all 358 * error events reported by the SAX parser will be silently 359 * ignored; however, normal processing may not continue. It is 360 * highly recommended that all SAX applications implement an 361 * error handler to avoid unexpected bugs.</p> 362 * 363 * <p>Applications may register a new or different handler in the 364 * middle of a parse, and the SAX parser must begin using the new 365 * handler immediately.</p> 366 * 367 * @param errorHandler The error handler. 368 * @exception java.lang.NullPointerException If the handler 369 * argument is null. 370 * @see #getErrorHandler 371 */ 372 public void setErrorHandler(ErrorHandler errorHandler) { 373 374 try { 375 XMLErrorHandler xeh = (XMLErrorHandler) fConfiguration.getProperty(ERROR_HANDLER); 376 if (xeh instanceof ErrorHandlerWrapper) { 377 ErrorHandlerWrapper ehw = (ErrorHandlerWrapper) xeh; 378 ehw.setErrorHandler(errorHandler); 379 } 380 else { 381 fConfiguration.setProperty(ERROR_HANDLER, 382 new ErrorHandlerWrapper(errorHandler)); 383 } 384 } 385 catch (XMLConfigurationException e) { 386 // do nothing 387 } 388 389 } // setErrorHandler(ErrorHandler) 390 391 /** 392 * Return the current error handler. 393 * 394 * @return The current error handler, or null if none 395 * has been registered. 396 * @see #setErrorHandler 397 */ 398 public ErrorHandler getErrorHandler() { 399 400 ErrorHandler errorHandler = null; 401 try { 402 XMLErrorHandler xmlErrorHandler = 403 (XMLErrorHandler)fConfiguration.getProperty(ERROR_HANDLER); 404 if (xmlErrorHandler != null && 405 xmlErrorHandler instanceof ErrorHandlerWrapper) { 406 errorHandler = ((ErrorHandlerWrapper)xmlErrorHandler).getErrorHandler(); 407 } 408 } 409 catch (XMLConfigurationException e) { 410 // do nothing 411 } 412 return errorHandler; 413 414 } // getErrorHandler():ErrorHandler 415 416 /** 417 * Set the state of any feature in a SAX2 parser. The parser 418 * might not recognize the feature, and if it does recognize 419 * it, it might not be able to fulfill the request. 420 * 421 * @param featureId The unique identifier (URI) of the feature. 422 * @param state The requested state of the feature (true or false). 423 * 424 * @exception SAXNotRecognizedException If the 425 * requested feature is not known. 426 * @exception SAXNotSupportedException If the 427 * requested feature is known, but the requested 428 * state is not supported. 429 */ 430 public void setFeature(String featureId, boolean state) 431 throws SAXNotRecognizedException, SAXNotSupportedException { 432 433 try { 434 435 // http://xml.org/sax/features/use-entity-resolver2 436 // controls whether the methods of an object implementing 437 // org.xml.sax.ext.EntityResolver2 will be used by the parser. 438 // 439 if (featureId.equals(USE_ENTITY_RESOLVER2)) { 440 if (state != fUseEntityResolver2) { 441 fUseEntityResolver2 = state; 442 // Refresh EntityResolver wrapper. 443 setEntityResolver(getEntityResolver()); 444 } 445 return; 446 } 447 448 // 449 // Default handling 450 // 451 452 fConfiguration.setFeature(featureId, state); 453 } 454 catch (XMLConfigurationException e) { 455 String identifier = e.getIdentifier(); 456 if (e.getType() == Status.NOT_RECOGNIZED) { 457 throw new SAXNotRecognizedException( 458 SAXMessageFormatter.formatMessage(fConfiguration.getLocale(), 459 "feature-not-recognized", new Object [] {identifier})); 460 } 461 else { 462 throw new SAXNotSupportedException( 463 SAXMessageFormatter.formatMessage(fConfiguration.getLocale(), 464 "feature-not-supported", new Object [] {identifier})); 465 } 466 } 467 468 } // setFeature(String,boolean) 469 470 /** 471 * Query the state of a feature. 472 * 473 * Query the current state of any feature in a SAX2 parser. The 474 * parser might not recognize the feature. 475 * 476 * @param featureId The unique identifier (URI) of the feature 477 * being set. 478 * @return The current state of the feature. 479 * @exception org.xml.sax.SAXNotRecognizedException If the 480 * requested feature is not known. 481 * @exception SAXNotSupportedException If the 482 * requested feature is known but not supported. 483 */ 484 public boolean getFeature(String featureId) 485 throws SAXNotRecognizedException, SAXNotSupportedException { 486 487 try { 488 489 // http://xml.org/sax/features/use-entity-resolver2 490 // controls whether the methods of an object implementing 491 // org.xml.sax.ext.EntityResolver2 will be used by the parser. 492 // 493 if (featureId.equals(USE_ENTITY_RESOLVER2)) { 494 return fUseEntityResolver2; 495 } 496 497 // 498 // Default handling 499 // 500 501 return fConfiguration.getFeature(featureId); 502 } 503 catch (XMLConfigurationException e) { 504 String identifier = e.getIdentifier(); 505 if (e.getType() == Status.NOT_RECOGNIZED) { 506 throw new SAXNotRecognizedException( 507 SAXMessageFormatter.formatMessage(fConfiguration.getLocale(), 508 "feature-not-recognized", new Object [] {identifier})); 509 } 510 else { 511 throw new SAXNotSupportedException( 512 SAXMessageFormatter.formatMessage(fConfiguration.getLocale(), 513 "feature-not-supported", new Object [] {identifier})); 514 } 515 } 516 517 } // getFeature(String):boolean 518 519 /** 520 * Set the value of any property in a SAX2 parser. The parser 521 * might not recognize the property, and if it does recognize 522 * it, it might not support the requested value. 523 * 524 * @param propertyId The unique identifier (URI) of the property 525 * being set. 526 * @param value The value to which the property is being set. 527 * 528 * @exception SAXNotRecognizedException If the 529 * requested property is not known. 530 * @exception SAXNotSupportedException If the 531 * requested property is known, but the requested 532 * value is not supported. 533 */ 534 public void setProperty(String propertyId, Object value) 535 throws SAXNotRecognizedException, SAXNotSupportedException { 536 /** 537 * It's possible for users to set a security manager through the interface. 538 * If it's the old SecurityManager, convert it to the new XMLSecurityManager 539 */ 540 if (propertyId.equals(Constants.SECURITY_MANAGER)) { 541 securityManager = XMLSecurityManager.convert(value, securityManager); 542 setProperty0(Constants.SECURITY_MANAGER, securityManager); 543 return; 544 } 545 if (propertyId.equals(Constants.XML_SECURITY_PROPERTY_MANAGER)) { 546 if (value == null) { 547 securityPropertyManager = new XMLSecurityPropertyManager(); 548 } else { 549 securityPropertyManager = (XMLSecurityPropertyManager)value; 550 } 551 setProperty0(Constants.XML_SECURITY_PROPERTY_MANAGER, securityPropertyManager); 552 return; 553 } 554 555 if (securityManager == null) { 556 securityManager = new XMLSecurityManager(true); 557 setProperty0(Constants.SECURITY_MANAGER, securityManager); 558 } 559 560 if (securityPropertyManager == null) { 561 securityPropertyManager = new XMLSecurityPropertyManager(); 562 setProperty0(Constants.XML_SECURITY_PROPERTY_MANAGER, securityPropertyManager); 563 } 564 int index = securityPropertyManager.getIndex(propertyId); 565 566 if (index > -1) { 567 /** 568 * this is a direct call to this parser, not a subclass since 569 * internally the support of this property is done through 570 * XMLSecurityPropertyManager 571 */ 572 securityPropertyManager.setValue(index, XMLSecurityPropertyManager.State.APIPROPERTY, (String)value); 573 } else { 574 //check if the property is managed by security manager 575 if (!securityManager.setLimit(propertyId, XMLSecurityManager.State.APIPROPERTY, value)) { 576 //fall back to the default configuration to handle the property 577 setProperty0(propertyId, value); 578 } 579 } 580 } 581 582 public void setProperty0(String propertyId, Object value) 583 throws SAXNotRecognizedException, SAXNotSupportedException { 584 try { 585 fConfiguration.setProperty(propertyId, value); 586 } 587 catch (XMLConfigurationException e) { 588 String identifier = e.getIdentifier(); 589 if (e.getType() == Status.NOT_RECOGNIZED) { 590 throw new SAXNotRecognizedException( 591 SAXMessageFormatter.formatMessage(fConfiguration.getLocale(), 592 "property-not-recognized", new Object [] {identifier})); 593 } 594 else { 595 throw new SAXNotSupportedException( 596 SAXMessageFormatter.formatMessage(fConfiguration.getLocale(), 597 "property-not-supported", new Object [] {identifier})); 598 } 599 } 600 601 } // setProperty(String,Object) 602 603 /** 604 * Query the value of a property. 605 * 606 * Return the current value of a property in a SAX2 parser. 607 * The parser might not recognize the property. 608 * 609 * @param propertyId The unique identifier (URI) of the property 610 * being set. 611 * @return The current value of the property. 612 * @exception org.xml.sax.SAXNotRecognizedException If the 613 * requested property is not known. 614 * @exception SAXNotSupportedException If the 615 * requested property is known but not supported. 616 */ 617 public Object getProperty(String propertyId) 618 throws SAXNotRecognizedException, SAXNotSupportedException { 619 620 if (propertyId.equals(CURRENT_ELEMENT_NODE)) { 621 boolean deferred = false; 622 try { 623 deferred = getFeature(DEFER_NODE_EXPANSION); 624 } 625 catch (XMLConfigurationException e){ 626 // ignore 627 } 628 if (deferred) { 629 throw new SAXNotSupportedException("Current element node cannot be queried when node expansion is deferred."); 630 } 631 return (fCurrentNode!=null && 632 fCurrentNode.getNodeType() == Node.ELEMENT_NODE)? fCurrentNode:null; 633 } 634 635 try { 636 XMLSecurityPropertyManager spm = (XMLSecurityPropertyManager) 637 fConfiguration.getProperty(XML_SECURITY_PROPERTY_MANAGER); 638 int index = spm.getIndex(propertyId); 639 if (index > -1) { 640 return spm.getValueByIndex(index); 641 } 642 643 return fConfiguration.getProperty(propertyId); 644 } 645 catch (XMLConfigurationException e) { 646 String identifier = e.getIdentifier(); 647 if (e.getType() == Status.NOT_RECOGNIZED) { 648 throw new SAXNotRecognizedException( 649 SAXMessageFormatter.formatMessage(fConfiguration.getLocale(), 650 "property-not-recognized", new Object [] {identifier})); 651 } 652 else { 653 throw new SAXNotSupportedException( 654 SAXMessageFormatter.formatMessage(fConfiguration.getLocale(), 655 "property-not-supported", new Object [] {identifier})); 656 } 657 } 658 659 } // getProperty(String):Object 660 661 /** 662 * Returns this parser's XMLParserConfiguration. 663 */ 664 public XMLParserConfiguration getXMLParserConfiguration() { 665 return fConfiguration; 666 } // getXMLParserConfiguration():XMLParserConfiguration 667 668 } // class DOMParser