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