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