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