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