1 /* 2 * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. 3 */ 4 /* 5 * Copyright 2005 The Apache Software Foundation. 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 */ 19 20 package com.sun.org.apache.xerces.internal.jaxp.validation; 21 22 import java.io.IOException; 23 import java.io.InputStream; 24 import java.io.Reader; 25 import java.io.StringReader; 26 import java.util.HashMap; 27 28 import javax.xml.XMLConstants; 29 import javax.xml.parsers.FactoryConfigurationError; 30 import javax.xml.transform.Result; 31 import javax.xml.transform.Source; 32 import javax.xml.transform.sax.SAXResult; 33 import javax.xml.transform.sax.SAXSource; 34 import javax.xml.validation.TypeInfoProvider; 35 import javax.xml.validation.ValidatorHandler; 36 import jdk.xml.internal.JdkXmlUtils; 37 38 import com.sun.org.apache.xerces.internal.impl.Constants; 39 import com.sun.org.apache.xerces.internal.impl.XMLEntityManager; 40 import com.sun.org.apache.xerces.internal.impl.XMLErrorReporter; 41 import com.sun.org.apache.xerces.internal.impl.dv.XSSimpleType; 42 import com.sun.org.apache.xerces.internal.impl.validation.EntityState; 43 import com.sun.org.apache.xerces.internal.impl.validation.ValidationManager; 44 import com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator; 45 import com.sun.org.apache.xerces.internal.util.AttributesProxy; 46 import com.sun.org.apache.xerces.internal.util.SAXLocatorWrapper; 47 import com.sun.org.apache.xerces.internal.util.SAXMessageFormatter; 48 import com.sun.org.apache.xerces.internal.util.Status; 49 import com.sun.org.apache.xerces.internal.util.SymbolTable; 50 import com.sun.org.apache.xerces.internal.util.URI; 51 import com.sun.org.apache.xerces.internal.util.XMLAttributesImpl; 52 import com.sun.org.apache.xerces.internal.util.XMLSymbols; 53 import com.sun.org.apache.xerces.internal.utils.XMLSecurityPropertyManager; 54 import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager; 55 import com.sun.org.apache.xerces.internal.xni.Augmentations; 56 import com.sun.org.apache.xerces.internal.xni.NamespaceContext; 57 import com.sun.org.apache.xerces.internal.xni.QName; 58 import com.sun.org.apache.xerces.internal.xni.XMLAttributes; 59 import com.sun.org.apache.xerces.internal.xni.XMLDocumentHandler; 60 import com.sun.org.apache.xerces.internal.xni.XMLLocator; 61 import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier; 62 import com.sun.org.apache.xerces.internal.xni.XMLString; 63 import com.sun.org.apache.xerces.internal.xni.XNIException; 64 import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException; 65 import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentSource; 66 import com.sun.org.apache.xerces.internal.xni.parser.XMLParseException; 67 import com.sun.org.apache.xerces.internal.xs.AttributePSVI; 68 import com.sun.org.apache.xerces.internal.xs.ElementPSVI; 69 import com.sun.org.apache.xerces.internal.xs.ItemPSVI; 70 import com.sun.org.apache.xerces.internal.xs.PSVIProvider; 71 import com.sun.org.apache.xerces.internal.xs.XSTypeDefinition; 72 import org.w3c.dom.TypeInfo; 73 import org.w3c.dom.ls.LSInput; 74 import org.w3c.dom.ls.LSResourceResolver; 75 import org.xml.sax.Attributes; 76 import org.xml.sax.ContentHandler; 77 import org.xml.sax.DTDHandler; 78 import org.xml.sax.ErrorHandler; 79 import org.xml.sax.InputSource; 80 import org.xml.sax.Locator; 81 import org.xml.sax.SAXException; 82 import org.xml.sax.SAXNotRecognizedException; 83 import org.xml.sax.SAXNotSupportedException; 84 import org.xml.sax.XMLReader; 85 import org.xml.sax.ext.Attributes2; 86 import org.xml.sax.ext.EntityResolver2; 87 88 /** 89 * <p>Implementation of ValidatorHandler for W3C XML Schemas and 90 * also a validator helper for <code>SAXSource</code>s.</p> 91 * 92 * @author Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com) 93 * @author Michael Glavassevich, IBM 94 * 95 * @version $Id: ValidatorHandlerImpl.java,v 1.10 2010-11-01 04:40:08 joehw Exp $ 96 */ 97 final class ValidatorHandlerImpl extends ValidatorHandler implements 98 DTDHandler, EntityState, PSVIProvider, ValidatorHelper, XMLDocumentHandler { 99 100 // feature identifiers 101 102 /** Feature identifier: namespace prefixes. */ 103 private static final String NAMESPACE_PREFIXES = 104 Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACE_PREFIXES_FEATURE; 105 106 /** Feature identifier: string interning. */ 107 protected static final String STRING_INTERNING = 108 Constants.SAX_FEATURE_PREFIX + Constants.STRING_INTERNING_FEATURE; 109 110 // property identifiers 111 112 /** Property identifier: error reporter. */ 113 private static final String ERROR_REPORTER = 114 Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY; 115 116 /** Property identifier: namespace context. */ 117 private static final String NAMESPACE_CONTEXT = 118 Constants.XERCES_PROPERTY_PREFIX + Constants.NAMESPACE_CONTEXT_PROPERTY; 119 120 /** Property identifier: XML Schema validator. */ 121 private static final String SCHEMA_VALIDATOR = 122 Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_VALIDATOR_PROPERTY; 123 124 /** Property identifier: security manager. */ 125 private static final String SECURITY_MANAGER = 126 Constants.XERCES_PROPERTY_PREFIX + Constants.SECURITY_MANAGER_PROPERTY; 127 128 /** Property identifier: symbol table. */ 129 private static final String SYMBOL_TABLE = 130 Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY; 131 132 /** Property identifier: validation manager. */ 133 private static final String VALIDATION_MANAGER = 134 Constants.XERCES_PROPERTY_PREFIX + Constants.VALIDATION_MANAGER_PROPERTY; 135 136 /** Property identifier: Security property manager. */ 137 private static final String XML_SECURITY_PROPERTY_MANAGER = 138 Constants.XML_SECURITY_PROPERTY_MANAGER; 139 140 // 141 // Data 142 // 143 144 /** Error reporter. */ 145 private XMLErrorReporter fErrorReporter; 146 147 /** The namespace context of this document: stores namespaces in scope */ 148 private NamespaceContext fNamespaceContext; 149 150 /** Schema validator. **/ 151 private XMLSchemaValidator fSchemaValidator; 152 153 /** Symbol table **/ 154 private SymbolTable fSymbolTable; 155 156 /** Validation manager. */ 157 private ValidationManager fValidationManager; 158 159 /** Component manager. **/ 160 private XMLSchemaValidatorComponentManager fComponentManager; 161 162 /** XML Locator wrapper for SAX. **/ 163 private final SAXLocatorWrapper fSAXLocatorWrapper = new SAXLocatorWrapper(); 164 165 /** Flag used to track whether the namespace context needs to be pushed. */ 166 private boolean fNeedPushNSContext = true; 167 168 /** Map for tracking unparsed entities. */ 169 private HashMap fUnparsedEntities = null; 170 171 /** Flag used to track whether XML names and Namespace URIs have been internalized. */ 172 private boolean fStringsInternalized = false; 173 174 /** Fields for start element, end element and characters. */ 175 private final QName fElementQName = new QName(); 176 private final QName fAttributeQName = new QName(); 177 private final XMLAttributesImpl fAttributes = new XMLAttributesImpl(); 178 private final AttributesProxy fAttrAdapter = new AttributesProxy(fAttributes); 179 private final XMLString fTempString = new XMLString(); 180 181 // 182 // User Objects 183 // 184 185 private ContentHandler fContentHandler = null; 186 187 /* 188 * Constructors 189 */ 190 191 public ValidatorHandlerImpl(XSGrammarPoolContainer grammarContainer) { 192 this(new XMLSchemaValidatorComponentManager(grammarContainer)); 193 fComponentManager.addRecognizedFeatures(new String [] {NAMESPACE_PREFIXES}); 194 fComponentManager.setFeature(NAMESPACE_PREFIXES, false); 195 setErrorHandler(null); 196 setResourceResolver(null); 197 } 198 199 public ValidatorHandlerImpl(XMLSchemaValidatorComponentManager componentManager) { 200 fComponentManager = componentManager; 201 fErrorReporter = (XMLErrorReporter) fComponentManager.getProperty(ERROR_REPORTER); 202 fNamespaceContext = (NamespaceContext) fComponentManager.getProperty(NAMESPACE_CONTEXT); 203 fSchemaValidator = (XMLSchemaValidator) fComponentManager.getProperty(SCHEMA_VALIDATOR); 204 fSymbolTable = (SymbolTable) fComponentManager.getProperty(SYMBOL_TABLE); 205 fValidationManager = (ValidationManager) fComponentManager.getProperty(VALIDATION_MANAGER); 206 } 207 208 /* 209 * ValidatorHandler methods 210 */ 211 212 public void setContentHandler(ContentHandler receiver) { 213 fContentHandler = receiver; 214 } 215 216 public ContentHandler getContentHandler() { 217 return fContentHandler; 218 } 219 220 public void setErrorHandler(ErrorHandler errorHandler) { 221 fComponentManager.setErrorHandler(errorHandler); 222 } 223 224 public ErrorHandler getErrorHandler() { 225 return fComponentManager.getErrorHandler(); 226 } 227 228 public void setResourceResolver(LSResourceResolver resourceResolver) { 229 fComponentManager.setResourceResolver(resourceResolver); 230 } 231 232 public LSResourceResolver getResourceResolver() { 233 return fComponentManager.getResourceResolver(); 234 } 235 236 public TypeInfoProvider getTypeInfoProvider() { 237 return fTypeInfoProvider; 238 } 239 240 public boolean getFeature(String name) 241 throws SAXNotRecognizedException, SAXNotSupportedException { 242 if (name == null) { 243 throw new NullPointerException(); 244 } 245 try { 246 return fComponentManager.getFeature(name); 247 } 248 catch (XMLConfigurationException e) { 249 final String identifier = e.getIdentifier(); 250 final String key = e.getType() == Status.NOT_RECOGNIZED ? 251 "feature-not-recognized" : "feature-not-supported"; 252 throw new SAXNotRecognizedException( 253 SAXMessageFormatter.formatMessage(fComponentManager.getLocale(), 254 key, new Object [] {identifier})); 255 } 256 } 257 258 public void setFeature(String name, boolean value) 259 throws SAXNotRecognizedException, SAXNotSupportedException { 260 if (name == null) { 261 throw new NullPointerException(); 262 } 263 try { 264 fComponentManager.setFeature(name, value); 265 } 266 catch (XMLConfigurationException e) { 267 final String identifier = e.getIdentifier(); 268 final String key; 269 if (e.getType() == Status.NOT_ALLOWED) { 270 //for now, the identifier can only be (XMLConstants.FEATURE_SECURE_PROCESSING) 271 throw new SAXNotSupportedException( 272 SAXMessageFormatter.formatMessage(fComponentManager.getLocale(), 273 "jaxp-secureprocessing-feature", null)); 274 } else if (e.getType() == Status.NOT_RECOGNIZED) { 275 key = "feature-not-recognized"; 276 } else { 277 key = "feature-not-supported"; 278 } 279 throw new SAXNotRecognizedException( 280 SAXMessageFormatter.formatMessage(fComponentManager.getLocale(), 281 key, new Object [] {identifier})); 282 } 283 } 284 285 public Object getProperty(String name) 286 throws SAXNotRecognizedException, SAXNotSupportedException { 287 if (name == null) { 288 throw new NullPointerException(); 289 } 290 try { 291 return fComponentManager.getProperty(name); 292 } 293 catch (XMLConfigurationException e) { 294 final String identifier = e.getIdentifier(); 295 final String key = e.getType() == Status.NOT_RECOGNIZED ? 296 "property-not-recognized" : "property-not-supported"; 297 throw new SAXNotRecognizedException( 298 SAXMessageFormatter.formatMessage(fComponentManager.getLocale(), 299 key, new Object [] {identifier})); 300 } 301 } 302 303 public void setProperty(String name, Object object) 304 throws SAXNotRecognizedException, SAXNotSupportedException { 305 if (name == null) { 306 throw new NullPointerException(); 307 } 308 try { 309 fComponentManager.setProperty(name, object); 310 } 311 catch (XMLConfigurationException e) { 312 final String identifier = e.getIdentifier(); 313 final String key = e.getType() == Status.NOT_RECOGNIZED ? 314 "property-not-recognized" : "property-not-supported"; 315 throw new SAXNotRecognizedException( 316 SAXMessageFormatter.formatMessage(fComponentManager.getLocale(), 317 key, new Object [] {identifier})); 318 } 319 } 320 321 /* 322 * EntityState methods 323 */ 324 325 public boolean isEntityDeclared(String name) { 326 return false; 327 } 328 329 public boolean isEntityUnparsed(String name) { 330 if (fUnparsedEntities != null) { 331 return fUnparsedEntities.containsKey(name); 332 } 333 return false; 334 } 335 336 /* 337 * XMLDocumentHandler methods 338 */ 339 340 public void startDocument(XMLLocator locator, String encoding, 341 NamespaceContext namespaceContext, Augmentations augs) 342 throws XNIException { 343 if (fContentHandler != null) { 344 try { 345 fContentHandler.startDocument(); 346 } 347 catch (SAXException e) { 348 throw new XNIException(e); 349 } 350 } 351 } 352 353 public void xmlDecl(String version, String encoding, String standalone, 354 Augmentations augs) throws XNIException {} 355 356 public void doctypeDecl(String rootElement, String publicId, 357 String systemId, Augmentations augs) throws XNIException {} 358 359 public void comment(XMLString text, Augmentations augs) throws XNIException {} 360 361 public void processingInstruction(String target, XMLString data, 362 Augmentations augs) throws XNIException { 363 if (fContentHandler != null) { 364 try { 365 fContentHandler.processingInstruction(target, data.toString()); 366 } 367 catch (SAXException e) { 368 throw new XNIException(e); 369 } 370 } 371 } 372 373 public void startElement(QName element, XMLAttributes attributes, 374 Augmentations augs) throws XNIException { 375 if (fContentHandler != null) { 376 try { 377 fTypeInfoProvider.beginStartElement(augs, attributes); 378 fContentHandler.startElement((element.uri != null) ? element.uri : XMLSymbols.EMPTY_STRING, 379 element.localpart, element.rawname, fAttrAdapter); 380 } 381 catch (SAXException e) { 382 throw new XNIException(e); 383 } 384 finally { 385 fTypeInfoProvider.finishStartElement(); 386 } 387 } 388 } 389 390 public void emptyElement(QName element, XMLAttributes attributes, 391 Augmentations augs) throws XNIException { 392 /** Split empty element event. **/ 393 startElement(element, attributes, augs); 394 endElement(element, augs); 395 } 396 397 public void startGeneralEntity(String name, 398 XMLResourceIdentifier identifier, String encoding, 399 Augmentations augs) throws XNIException {} 400 401 public void textDecl(String version, String encoding, Augmentations augs) 402 throws XNIException {} 403 404 public void endGeneralEntity(String name, Augmentations augs) 405 throws XNIException {} 406 407 public void characters(XMLString text, Augmentations augs) 408 throws XNIException { 409 if (fContentHandler != null) { 410 // if the type is union it is possible that we receive 411 // a character call with empty data 412 if (text.length == 0) { 413 return; 414 } 415 try { 416 fContentHandler.characters(text.ch, text.offset, text.length); 417 } 418 catch (SAXException e) { 419 throw new XNIException(e); 420 } 421 } 422 } 423 424 public void ignorableWhitespace(XMLString text, Augmentations augs) 425 throws XNIException { 426 if (fContentHandler != null) { 427 try { 428 fContentHandler.ignorableWhitespace(text.ch, text.offset, text.length); 429 } 430 catch (SAXException e) { 431 throw new XNIException(e); 432 } 433 } 434 } 435 436 public void endElement(QName element, Augmentations augs) 437 throws XNIException { 438 if (fContentHandler != null) { 439 try { 440 fTypeInfoProvider.beginEndElement(augs); 441 fContentHandler.endElement((element.uri != null) ? element.uri : XMLSymbols.EMPTY_STRING, 442 element.localpart, element.rawname); 443 } 444 catch (SAXException e) { 445 throw new XNIException(e); 446 } 447 finally { 448 fTypeInfoProvider.finishEndElement(); 449 } 450 } 451 } 452 453 public void startCDATA(Augmentations augs) throws XNIException {} 454 455 public void endCDATA(Augmentations augs) throws XNIException {} 456 457 public void endDocument(Augmentations augs) throws XNIException { 458 if (fContentHandler != null) { 459 try { 460 fContentHandler.endDocument(); 461 } 462 catch (SAXException e) { 463 throw new XNIException(e); 464 } 465 } 466 } 467 468 // NO-OP 469 public void setDocumentSource(XMLDocumentSource source) {} 470 471 public XMLDocumentSource getDocumentSource() { 472 return fSchemaValidator; 473 } 474 475 /* 476 * ContentHandler methods 477 */ 478 479 public void setDocumentLocator(Locator locator) { 480 fSAXLocatorWrapper.setLocator(locator); 481 if (fContentHandler != null) { 482 fContentHandler.setDocumentLocator(locator); 483 } 484 } 485 486 public void startDocument() throws SAXException { 487 fComponentManager.reset(); 488 fSchemaValidator.setDocumentHandler(this); 489 fValidationManager.setEntityState(this); 490 fTypeInfoProvider.finishStartElement(); // cleans up TypeInfoProvider 491 fNeedPushNSContext = true; 492 if (fUnparsedEntities != null && !fUnparsedEntities.isEmpty()) { 493 // should only clear this if the last document contained unparsed entities 494 fUnparsedEntities.clear(); 495 } 496 fErrorReporter.setDocumentLocator(fSAXLocatorWrapper); 497 try { 498 fSchemaValidator.startDocument(fSAXLocatorWrapper, fSAXLocatorWrapper.getEncoding(), fNamespaceContext, null); 499 } 500 catch (XMLParseException e) { 501 throw Util.toSAXParseException(e); 502 } 503 catch (XNIException e) { 504 throw Util.toSAXException(e); 505 } 506 } 507 508 public void endDocument() throws SAXException { 509 fSAXLocatorWrapper.setLocator(null); 510 try { 511 fSchemaValidator.endDocument(null); 512 } 513 catch (XMLParseException e) { 514 throw Util.toSAXParseException(e); 515 } 516 catch (XNIException e) { 517 throw Util.toSAXException(e); 518 } 519 } 520 521 public void startPrefixMapping(String prefix, String uri) 522 throws SAXException { 523 String prefixSymbol; 524 String uriSymbol; 525 if (!fStringsInternalized) { 526 prefixSymbol = (prefix != null) ? fSymbolTable.addSymbol(prefix) : XMLSymbols.EMPTY_STRING; 527 uriSymbol = (uri != null && uri.length() > 0) ? fSymbolTable.addSymbol(uri) : null; 528 } 529 else { 530 prefixSymbol = (prefix != null) ? prefix : XMLSymbols.EMPTY_STRING; 531 uriSymbol = (uri != null && uri.length() > 0) ? uri : null; 532 } 533 if (fNeedPushNSContext) { 534 fNeedPushNSContext = false; 535 fNamespaceContext.pushContext(); 536 } 537 fNamespaceContext.declarePrefix(prefixSymbol, uriSymbol); 538 if (fContentHandler != null) { 539 fContentHandler.startPrefixMapping(prefix, uri); 540 } 541 } 542 543 public void endPrefixMapping(String prefix) throws SAXException { 544 if (fContentHandler != null) { 545 fContentHandler.endPrefixMapping(prefix); 546 } 547 } 548 549 public void startElement(String uri, String localName, String qName, 550 Attributes atts) throws SAXException { 551 if (fNeedPushNSContext) { 552 fNamespaceContext.pushContext(); 553 } 554 fNeedPushNSContext = true; 555 556 // Fill element QName 557 fillQName(fElementQName, uri, localName, qName); 558 559 // Fill XMLAttributes 560 if (atts instanceof Attributes2) { 561 fillXMLAttributes2((Attributes2) atts); 562 } 563 else { 564 fillXMLAttributes(atts); 565 } 566 567 try { 568 fSchemaValidator.startElement(fElementQName, fAttributes, null); 569 } 570 catch (XMLParseException e) { 571 throw Util.toSAXParseException(e); 572 } 573 catch (XNIException e) { 574 throw Util.toSAXException(e); 575 } 576 } 577 578 public void endElement(String uri, String localName, String qName) 579 throws SAXException { 580 fillQName(fElementQName, uri, localName, qName); 581 try { 582 fSchemaValidator.endElement(fElementQName, null); 583 } 584 catch (XMLParseException e) { 585 throw Util.toSAXParseException(e); 586 } 587 catch (XNIException e) { 588 throw Util.toSAXException(e); 589 } 590 finally { 591 fNamespaceContext.popContext(); 592 } 593 } 594 595 public void characters(char[] ch, int start, int length) 596 throws SAXException { 597 try { 598 fTempString.setValues(ch, start, length); 599 fSchemaValidator.characters(fTempString, null); 600 } 601 catch (XMLParseException e) { 602 throw Util.toSAXParseException(e); 603 } 604 catch (XNIException e) { 605 throw Util.toSAXException(e); 606 } 607 } 608 609 public void ignorableWhitespace(char[] ch, int start, int length) 610 throws SAXException { 611 try { 612 fTempString.setValues(ch, start, length); 613 fSchemaValidator.ignorableWhitespace(fTempString, null); 614 } 615 catch (XMLParseException e) { 616 throw Util.toSAXParseException(e); 617 } 618 catch (XNIException e) { 619 throw Util.toSAXException(e); 620 } 621 } 622 623 public void processingInstruction(String target, String data) 624 throws SAXException { 625 /** 626 * Processing instructions do not participate in schema validation, 627 * so just forward the event to the application's content 628 * handler. 629 */ 630 if (fContentHandler != null) { 631 fContentHandler.processingInstruction(target, data); 632 } 633 } 634 635 public void skippedEntity(String name) throws SAXException { 636 // there seems to be no corresponding method on XMLDocumentFilter. 637 // just pass it down to the output, if any. 638 if (fContentHandler != null) { 639 fContentHandler.skippedEntity(name); 640 } 641 } 642 643 /* 644 * DTDHandler methods 645 */ 646 647 public void notationDecl(String name, String publicId, 648 String systemId) throws SAXException {} 649 650 public void unparsedEntityDecl(String name, String publicId, 651 String systemId, String notationName) throws SAXException { 652 if (fUnparsedEntities == null) { 653 fUnparsedEntities = new HashMap(); 654 } 655 fUnparsedEntities.put(name, name); 656 } 657 658 /* 659 * ValidatorHelper methods 660 */ 661 662 public void validate(Source source, Result result) 663 throws SAXException, IOException { 664 if (result instanceof SAXResult || result == null) { 665 final SAXSource saxSource = (SAXSource) source; 666 final SAXResult saxResult = (SAXResult) result; 667 668 if (result != null) { 669 setContentHandler(saxResult.getHandler()); 670 } 671 672 try { 673 XMLReader reader = saxSource.getXMLReader(); 674 if( reader==null ) { 675 // create one now 676 reader = JdkXmlUtils.getXMLReader(fComponentManager.getFeature(JdkXmlUtils.OVERRIDE_PARSER), 677 fComponentManager.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING)); 678 679 try { 680 // If this is a Xerces SAX parser, set the security manager if there is one 681 if (reader instanceof com.sun.org.apache.xerces.internal.parsers.SAXParser) { 682 XMLSecurityManager securityManager = 683 (XMLSecurityManager) fComponentManager.getProperty(SECURITY_MANAGER); 684 if (securityManager != null) { 685 try { 686 reader.setProperty(SECURITY_MANAGER, securityManager); 687 } 688 // Ignore the exception if the security manager cannot be set. 689 catch (SAXException exc) {} 690 } 691 try { 692 XMLSecurityPropertyManager spm = (XMLSecurityPropertyManager) 693 fComponentManager.getProperty(XML_SECURITY_PROPERTY_MANAGER); 694 reader.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, 695 spm.getValue(XMLSecurityPropertyManager.Property.ACCESS_EXTERNAL_DTD)); 696 } catch (SAXException exc) { 697 XMLSecurityManager.printWarning(reader.getClass().getName(), 698 XMLConstants.ACCESS_EXTERNAL_DTD, exc); 699 } 700 } 701 } catch( Exception e ) { 702 // this is impossible, but better safe than sorry 703 throw new FactoryConfigurationError(e); 704 } 705 } 706 707 // If XML names and Namespace URIs are already internalized we 708 // can avoid running them through the SymbolTable. 709 try { 710 fStringsInternalized = reader.getFeature(STRING_INTERNING); 711 } 712 catch (SAXException exc) { 713 // The feature isn't recognized or getting it is not supported. 714 // In either case, assume that strings are not internalized. 715 fStringsInternalized = false; 716 } 717 718 ErrorHandler errorHandler = fComponentManager.getErrorHandler(); 719 reader.setErrorHandler(errorHandler != null ? errorHandler : DraconianErrorHandler.getInstance()); 720 reader.setEntityResolver(fResolutionForwarder); 721 fResolutionForwarder.setEntityResolver(fComponentManager.getResourceResolver()); 722 reader.setContentHandler(this); 723 reader.setDTDHandler(this); 724 725 InputSource is = saxSource.getInputSource(); 726 reader.parse(is); 727 } 728 finally { 729 // release the reference to user's handler ASAP 730 setContentHandler(null); 731 } 732 return; 733 } 734 throw new IllegalArgumentException(JAXPValidationMessageFormatter.formatMessage(fComponentManager.getLocale(), 735 "SourceResultMismatch", 736 new Object [] {source.getClass().getName(), result.getClass().getName()})); 737 } 738 739 /* 740 * PSVIProvider methods 741 */ 742 743 public ElementPSVI getElementPSVI() { 744 return fTypeInfoProvider.getElementPSVI(); 745 } 746 747 public AttributePSVI getAttributePSVI(int index) { 748 return fTypeInfoProvider.getAttributePSVI(index); 749 } 750 751 public AttributePSVI getAttributePSVIByName(String uri, String localname) { 752 return fTypeInfoProvider.getAttributePSVIByName(uri, localname); 753 } 754 755 // 756 // 757 // helper methods 758 // 759 // 760 761 /** Fills in a QName object. */ 762 private void fillQName(QName toFill, String uri, String localpart, String raw) { 763 if (!fStringsInternalized) { 764 uri = (uri != null && uri.length() > 0) ? fSymbolTable.addSymbol(uri) : null; 765 localpart = (localpart != null) ? fSymbolTable.addSymbol(localpart) : XMLSymbols.EMPTY_STRING; 766 raw = (raw != null) ? fSymbolTable.addSymbol(raw) : XMLSymbols.EMPTY_STRING; 767 } 768 else { 769 if (uri != null && uri.length() == 0) { 770 uri = null; 771 } 772 if (localpart == null) { 773 localpart = XMLSymbols.EMPTY_STRING; 774 } 775 if (raw == null) { 776 raw = XMLSymbols.EMPTY_STRING; 777 } 778 } 779 String prefix = XMLSymbols.EMPTY_STRING; 780 int prefixIdx = raw.indexOf(':'); 781 if (prefixIdx != -1) { 782 prefix = fSymbolTable.addSymbol(raw.substring(0, prefixIdx)); 783 } 784 toFill.setValues(prefix, localpart, raw, uri); 785 } 786 787 /** Fills in the XMLAttributes object. */ 788 private void fillXMLAttributes(Attributes att) { 789 fAttributes.removeAllAttributes(); 790 final int len = att.getLength(); 791 for (int i = 0; i < len; ++i) { 792 fillXMLAttribute(att, i); 793 fAttributes.setSpecified(i, true); 794 } 795 } 796 797 /** Fills in the XMLAttributes object. */ 798 private void fillXMLAttributes2(Attributes2 att) { 799 fAttributes.removeAllAttributes(); 800 final int len = att.getLength(); 801 for (int i = 0; i < len; ++i) { 802 fillXMLAttribute(att, i); 803 fAttributes.setSpecified(i, att.isSpecified(i)); 804 if (att.isDeclared(i)) { 805 fAttributes.getAugmentations(i).putItem(Constants.ATTRIBUTE_DECLARED, Boolean.TRUE); 806 } 807 } 808 } 809 810 /** Adds an attribute to the XMLAttributes object. */ 811 private void fillXMLAttribute(Attributes att, int index) { 812 fillQName(fAttributeQName, att.getURI(index), att.getLocalName(index), att.getQName(index)); 813 String type = att.getType(index); 814 fAttributes.addAttributeNS(fAttributeQName, (type != null) ? type : XMLSymbols.fCDATASymbol, att.getValue(index)); 815 } 816 817 /** 818 * {@link TypeInfoProvider} implementation. 819 * 820 * REVISIT: I'm not sure if this code should belong here. 821 */ 822 private final XMLSchemaTypeInfoProvider fTypeInfoProvider = new XMLSchemaTypeInfoProvider(); 823 private class XMLSchemaTypeInfoProvider extends TypeInfoProvider { 824 825 /** Element augmentations: contains ElementPSVI. **/ 826 private Augmentations fElementAugs; 827 828 /** Attributes: augmentations for each attribute contain AttributePSVI. **/ 829 private XMLAttributes fAttributes; 830 831 /** In start element. **/ 832 private boolean fInStartElement = false; 833 834 /** In end element. **/ 835 private boolean fInEndElement = false; 836 837 /** Initializes the TypeInfoProvider with type information for the current element. **/ 838 void beginStartElement(Augmentations elementAugs, XMLAttributes attributes) { 839 fInStartElement = true; 840 fElementAugs = elementAugs; 841 fAttributes = attributes; 842 } 843 844 /** Cleanup at the end of start element. **/ 845 void finishStartElement() { 846 fInStartElement = false; 847 fElementAugs = null; 848 fAttributes = null; 849 } 850 851 /** Initializes the TypeInfoProvider with type information for the current element. **/ 852 void beginEndElement(Augmentations elementAugs) { 853 fInEndElement = true; 854 fElementAugs = elementAugs; 855 } 856 857 /** Cleanup at the end of end element. **/ 858 void finishEndElement() { 859 fInEndElement = false; 860 fElementAugs = null; 861 } 862 863 /** 864 * Throws a {@link IllegalStateException} if we are not in 865 * the startElement callback. the JAXP API requires this 866 * for most of the public methods. 867 */ 868 private void checkState(boolean forElementInfo) { 869 if (! (fInStartElement || (fInEndElement && forElementInfo))) { 870 throw new IllegalStateException(JAXPValidationMessageFormatter.formatMessage(fComponentManager.getLocale(), 871 "TypeInfoProviderIllegalState", null)); 872 } 873 } 874 875 public TypeInfo getAttributeTypeInfo(int index) { 876 checkState(false); 877 return getAttributeType(index); 878 } 879 880 private TypeInfo getAttributeType( int index ) { 881 checkState(false); 882 if( index<0 || fAttributes.getLength()<=index ) 883 throw new IndexOutOfBoundsException(Integer.toString(index)); 884 Augmentations augs = fAttributes.getAugmentations(index); 885 if (augs == null) return null; 886 AttributePSVI psvi = (AttributePSVI)augs.getItem(Constants.ATTRIBUTE_PSVI); 887 return getTypeInfoFromPSVI(psvi); 888 } 889 890 public TypeInfo getAttributeTypeInfo(String attributeUri, String attributeLocalName) { 891 checkState(false); 892 return getAttributeTypeInfo(fAttributes.getIndex(attributeUri,attributeLocalName)); 893 } 894 895 public TypeInfo getAttributeTypeInfo(String attributeQName) { 896 checkState(false); 897 return getAttributeTypeInfo(fAttributes.getIndex(attributeQName)); 898 } 899 900 public TypeInfo getElementTypeInfo() { 901 checkState(true); 902 if (fElementAugs == null) return null; 903 ElementPSVI psvi = (ElementPSVI)fElementAugs.getItem(Constants.ELEMENT_PSVI); 904 return getTypeInfoFromPSVI(psvi); 905 } 906 907 private TypeInfo getTypeInfoFromPSVI( ItemPSVI psvi ) { 908 if(psvi==null) return null; 909 910 // TODO: make sure if this is correct. 911 // TODO: since the number of types in a schema is quite limited, 912 // TypeInfoImpl should be pooled. Even better, it should be a part 913 // of the element decl. 914 if( psvi.getValidity()== ElementPSVI.VALIDITY_VALID ) { 915 XSTypeDefinition t = psvi.getMemberTypeDefinition(); 916 if (t != null) { 917 return (t instanceof TypeInfo) ? (TypeInfo) t : null; 918 } 919 } 920 921 XSTypeDefinition t = psvi.getTypeDefinition(); 922 // TODO: can t be null? 923 if (t != null) { 924 return (t instanceof TypeInfo) ? (TypeInfo) t : null; 925 } 926 return null; 927 } 928 929 public boolean isIdAttribute(int index) { 930 checkState(false); 931 XSSimpleType type = (XSSimpleType)getAttributeType(index); 932 if(type==null) return false; 933 return type.isIDType(); 934 } 935 936 public boolean isSpecified(int index) { 937 checkState(false); 938 return fAttributes.isSpecified(index); 939 } 940 941 /* 942 * Other methods 943 */ 944 945 // PSVIProvider support 946 ElementPSVI getElementPSVI() { 947 return (fElementAugs != null) ? (ElementPSVI) fElementAugs.getItem(Constants.ELEMENT_PSVI) : null; 948 } 949 950 AttributePSVI getAttributePSVI(int index) { 951 if (fAttributes != null) { 952 Augmentations augs = fAttributes.getAugmentations(index); 953 if (augs != null) { 954 return (AttributePSVI) augs.getItem(Constants.ATTRIBUTE_PSVI); 955 } 956 } 957 return null; 958 } 959 960 AttributePSVI getAttributePSVIByName(String uri, String localname) { 961 if (fAttributes != null) { 962 Augmentations augs = fAttributes.getAugmentations(uri, localname); 963 if (augs != null) { 964 return (AttributePSVI) augs.getItem(Constants.ATTRIBUTE_PSVI); 965 } 966 } 967 return null; 968 } 969 } 970 971 /** SAX adapter for an LSResourceResolver. */ 972 private final ResolutionForwarder fResolutionForwarder = new ResolutionForwarder(null); 973 static final class ResolutionForwarder 974 implements EntityResolver2 { 975 976 // 977 // Data 978 // 979 980 /** XML 1.0 type constant according to DOM L3 LS REC spec "http://www.w3.org/TR/2004/REC-DOM-Level-3-LS-20040407/" */ 981 private static final String XML_TYPE = "http://www.w3.org/TR/REC-xml"; 982 983 /** The DOM entity resolver. */ 984 protected LSResourceResolver fEntityResolver; 985 986 // 987 // Constructors 988 // 989 990 /** Default constructor. */ 991 public ResolutionForwarder() {} 992 993 /** Wraps the specified DOM entity resolver. */ 994 public ResolutionForwarder(LSResourceResolver entityResolver) { 995 setEntityResolver(entityResolver); 996 } 997 998 // 999 // Public methods 1000 // 1001 1002 /** Sets the DOM entity resolver. */ 1003 public void setEntityResolver(LSResourceResolver entityResolver) { 1004 fEntityResolver = entityResolver; 1005 } // setEntityResolver(LSResourceResolver) 1006 1007 /** Returns the DOM entity resolver. */ 1008 public LSResourceResolver getEntityResolver() { 1009 return fEntityResolver; 1010 } // getEntityResolver():LSResourceResolver 1011 1012 /** 1013 * Always returns <code>null</code>. An LSResourceResolver has no corresponding method. 1014 */ 1015 public InputSource getExternalSubset(String name, String baseURI) 1016 throws SAXException, IOException { 1017 return null; 1018 } 1019 1020 /** 1021 * Resolves the given resource and adapts the <code>LSInput</code> 1022 * returned into an <code>InputSource</code>. 1023 */ 1024 public InputSource resolveEntity(String name, String publicId, 1025 String baseURI, String systemId) throws SAXException, IOException { 1026 if (fEntityResolver != null) { 1027 LSInput lsInput = fEntityResolver.resolveResource(XML_TYPE, null, publicId, systemId, baseURI); 1028 if (lsInput != null) { 1029 final String pubId = lsInput.getPublicId(); 1030 final String sysId = lsInput.getSystemId(); 1031 final String baseSystemId = lsInput.getBaseURI(); 1032 final Reader charStream = lsInput.getCharacterStream(); 1033 final InputStream byteStream = lsInput.getByteStream(); 1034 final String data = lsInput.getStringData(); 1035 final String encoding = lsInput.getEncoding(); 1036 1037 /** 1038 * An LSParser looks at inputs specified in LSInput in 1039 * the following order: characterStream, byteStream, 1040 * stringData, systemId, publicId. For consistency 1041 * with the DOM Level 3 Load and Save Recommendation 1042 * use the same lookup order here. 1043 */ 1044 InputSource inputSource = new InputSource(); 1045 inputSource.setPublicId(pubId); 1046 inputSource.setSystemId((baseSystemId != null) ? resolveSystemId(systemId, baseSystemId) : systemId); 1047 1048 if (charStream != null) { 1049 inputSource.setCharacterStream(charStream); 1050 } 1051 else if (byteStream != null) { 1052 inputSource.setByteStream(byteStream); 1053 } 1054 else if (data != null && data.length() != 0) { 1055 inputSource.setCharacterStream(new StringReader(data)); 1056 } 1057 inputSource.setEncoding(encoding); 1058 return inputSource; 1059 } 1060 } 1061 return null; 1062 } 1063 1064 /** Delegates to EntityResolver2.resolveEntity(String, String, String, String). */ 1065 public InputSource resolveEntity(String publicId, String systemId) 1066 throws SAXException, IOException { 1067 return resolveEntity(null, publicId, null, systemId); 1068 } 1069 1070 /** Resolves a system identifier against a base URI. */ 1071 private String resolveSystemId(String systemId, String baseURI) { 1072 try { 1073 return XMLEntityManager.expandSystemId(systemId, baseURI, false); 1074 } 1075 // In the event that resolution failed against the 1076 // base URI, just return the system id as is. There's not 1077 // much else we can do. 1078 catch (URI.MalformedURIException ex) { 1079 return systemId; 1080 } 1081 } 1082 } 1083 }