| 1 16 17 package org.apache.xerces.impl; 18 19 import java.io.CharConversionException ; 20 import java.io.EOFException ; 21 import java.io.IOException ; 22 23 import org.apache.xerces.impl.dtd.XMLDTDDescription; 24 import org.apache.xerces.impl.io.MalformedByteSequenceException; 25 import org.apache.xerces.impl.validation.ValidationManager; 26 import org.apache.xerces.util.NamespaceSupport; 27 import org.apache.xerces.util.XMLChar; 28 import org.apache.xerces.util.XMLStringBuffer; 29 import org.apache.xerces.xni.Augmentations; 30 import org.apache.xerces.xni.NamespaceContext; 31 import org.apache.xerces.xni.XMLResourceIdentifier; 32 import org.apache.xerces.xni.XMLString; 33 import org.apache.xerces.xni.XNIException; 34 import org.apache.xerces.xni.parser.XMLComponentManager; 35 import org.apache.xerces.xni.parser.XMLConfigurationException; 36 import org.apache.xerces.xni.parser.XMLDTDScanner; 37 import org.apache.xerces.xni.parser.XMLInputSource; 38 39 67 public class XMLDocumentScannerImpl 68 extends XMLDocumentFragmentScannerImpl { 69 70 74 76 77 protected static final int SCANNER_STATE_XML_DECL = 0; 78 79 80 protected static final int SCANNER_STATE_PROLOG = 5; 81 82 83 protected static final int SCANNER_STATE_TRAILING_MISC = 12; 84 85 86 protected static final int SCANNER_STATE_DTD_INTERNAL_DECLS = 17; 87 88 89 protected static final int SCANNER_STATE_DTD_EXTERNAL = 18; 90 91 92 protected static final int SCANNER_STATE_DTD_EXTERNAL_DECLS = 19; 93 94 96 97 protected static final String LOAD_EXTERNAL_DTD = 98 Constants.XERCES_FEATURE_PREFIX + Constants.LOAD_EXTERNAL_DTD_FEATURE; 99 100 101 protected static final String DISALLOW_DOCTYPE_DECL_FEATURE = 102 Constants.XERCES_FEATURE_PREFIX + Constants.DISALLOW_DOCTYPE_DECL_FEATURE; 103 104 106 107 protected static final String DTD_SCANNER = 108 Constants.XERCES_PROPERTY_PREFIX + Constants.DTD_SCANNER_PROPERTY; 109 110 111 protected static final String VALIDATION_MANAGER = 112 Constants.XERCES_PROPERTY_PREFIX + Constants.VALIDATION_MANAGER_PROPERTY; 113 114 115 protected static final String NAMESPACE_CONTEXT = 116 Constants.XERCES_PROPERTY_PREFIX + Constants.NAMESPACE_CONTEXT_PROPERTY; 117 118 119 120 122 123 private static final String [] RECOGNIZED_FEATURES = { 124 LOAD_EXTERNAL_DTD, 125 DISALLOW_DOCTYPE_DECL_FEATURE, 126 }; 127 128 129 private static final Boolean [] FEATURE_DEFAULTS = { 130 Boolean.TRUE, 131 Boolean.FALSE, 132 }; 133 134 135 private static final String [] RECOGNIZED_PROPERTIES = { 136 DTD_SCANNER, 137 VALIDATION_MANAGER, 138 NAMESPACE_CONTEXT, 139 }; 140 141 142 private static final Object [] PROPERTY_DEFAULTS = { 143 null, 144 null, 145 null, 146 }; 147 148 152 154 155 protected XMLDTDScanner fDTDScanner; 156 157 protected ValidationManager fValidationManager; 158 159 161 162 protected boolean fScanningDTD; 163 164 166 167 protected String fDoctypeName; 168 169 170 protected String fDoctypePublicId; 171 172 173 protected String fDoctypeSystemId; 174 175 176 protected NamespaceContext fNamespaceContext = new NamespaceSupport(); 177 178 180 181 protected boolean fLoadExternalDTD = true; 182 183 184 protected boolean fDisallowDoctype = false; 185 186 188 189 protected boolean fSeenDoctypeDecl; 190 191 193 194 protected Dispatcher fXMLDeclDispatcher = new XMLDeclDispatcher(); 195 196 197 protected Dispatcher fPrologDispatcher = new PrologDispatcher(); 198 199 200 protected Dispatcher fDTDDispatcher = new DTDDispatcher(); 201 202 203 protected Dispatcher fTrailingMiscDispatcher = new TrailingMiscDispatcher(); 204 205 207 208 private final String [] fStrings = new String [3]; 209 210 211 private final XMLString fString = new XMLString(); 212 213 214 private final XMLStringBuffer fStringBuffer = new XMLStringBuffer(); 215 216 217 private XMLInputSource fExternalSubsetSource = null; 218 219 220 private final XMLDTDDescription fDTDDescription = new XMLDTDDescription(null, null, null, null, null); 221 222 226 227 public XMLDocumentScannerImpl() {} 229 233 240 public void setInputSource(XMLInputSource inputSource) throws IOException { 241 fEntityManager.setEntityHandler(this); 242 fEntityManager.startDocumentEntity(inputSource); 243 } 246 250 264 public void reset(XMLComponentManager componentManager) 265 throws XMLConfigurationException { 266 267 super.reset(componentManager); 268 269 fDoctypeName = null; 271 fDoctypePublicId = null; 272 fDoctypeSystemId = null; 273 fSeenDoctypeDecl = false; 274 fScanningDTD = false; 275 fExternalSubsetSource = null; 276 277 if (!fParserSettings) { 278 fNamespaceContext.reset(); 280 setScannerState(SCANNER_STATE_XML_DECL); 282 setDispatcher(fXMLDeclDispatcher); 283 return; 284 } 285 286 try { 288 fLoadExternalDTD = componentManager.getFeature(LOAD_EXTERNAL_DTD); 289 } 290 catch (XMLConfigurationException e) { 291 fLoadExternalDTD = true; 292 } 293 try { 294 fDisallowDoctype = componentManager.getFeature(DISALLOW_DOCTYPE_DECL_FEATURE); 295 } 296 catch (XMLConfigurationException e) { 297 fDisallowDoctype = false; 298 } 299 300 fDTDScanner = (XMLDTDScanner)componentManager.getProperty(DTD_SCANNER); 302 try { 303 fValidationManager = (ValidationManager)componentManager.getProperty(VALIDATION_MANAGER); 304 } 305 catch (XMLConfigurationException e) { 306 fValidationManager = null; 307 } 308 309 try { 310 fNamespaceContext = (NamespaceContext)componentManager.getProperty(NAMESPACE_CONTEXT); 311 } 312 catch (XMLConfigurationException e) { } 313 if (fNamespaceContext == null) { 314 fNamespaceContext = new NamespaceSupport(); 315 } 316 fNamespaceContext.reset(); 317 318 setScannerState(SCANNER_STATE_XML_DECL); 320 setDispatcher(fXMLDeclDispatcher); 321 322 } 324 329 public String [] getRecognizedFeatures() { 330 String [] featureIds = super.getRecognizedFeatures(); 331 int length = featureIds != null ? featureIds.length : 0; 332 String [] combinedFeatureIds = new String [length + RECOGNIZED_FEATURES.length]; 333 if (featureIds != null) { 334 System.arraycopy(featureIds, 0, combinedFeatureIds, 0, featureIds.length); 335 } 336 System.arraycopy(RECOGNIZED_FEATURES, 0, combinedFeatureIds, length, RECOGNIZED_FEATURES.length); 337 return combinedFeatureIds; 338 } 340 355 public void setFeature(String featureId, boolean state) 356 throws XMLConfigurationException { 357 358 super.setFeature(featureId, state); 359 360 if (featureId.startsWith(Constants.XERCES_FEATURE_PREFIX)) { 362 final int suffixLength = featureId.length() - Constants.XERCES_FEATURE_PREFIX.length(); 363 364 if (suffixLength == Constants.LOAD_EXTERNAL_DTD_FEATURE.length() && 365 featureId.endsWith(Constants.LOAD_EXTERNAL_DTD_FEATURE)) { 366 fLoadExternalDTD = state; 367 return; 368 } 369 else if (suffixLength == Constants.DISALLOW_DOCTYPE_DECL_FEATURE.length() && 370 featureId.endsWith(Constants.DISALLOW_DOCTYPE_DECL_FEATURE)) { 371 fDisallowDoctype = state; 372 return; 373 } 374 } 375 376 } 378 383 public String [] getRecognizedProperties() { 384 String [] propertyIds = super.getRecognizedProperties(); 385 int length = propertyIds != null ? propertyIds.length : 0; 386 String [] combinedPropertyIds = new String [length + RECOGNIZED_PROPERTIES.length]; 387 if (propertyIds != null) { 388 System.arraycopy(propertyIds, 0, combinedPropertyIds, 0, propertyIds.length); 389 } 390 System.arraycopy(RECOGNIZED_PROPERTIES, 0, combinedPropertyIds, length, RECOGNIZED_PROPERTIES.length); 391 return combinedPropertyIds; 392 } 394 409 public void setProperty(String propertyId, Object value) 410 throws XMLConfigurationException { 411 412 super.setProperty(propertyId, value); 413 414 if (propertyId.startsWith(Constants.XERCES_PROPERTY_PREFIX)) { 416 final int suffixLength = propertyId.length() - Constants.XERCES_PROPERTY_PREFIX.length(); 417 418 if (suffixLength == Constants.DTD_SCANNER_PROPERTY.length() && 419 propertyId.endsWith(Constants.DTD_SCANNER_PROPERTY)) { 420 fDTDScanner = (XMLDTDScanner)value; 421 } 422 if (suffixLength == Constants.NAMESPACE_CONTEXT_PROPERTY.length() && 423 propertyId.endsWith(Constants.NAMESPACE_CONTEXT_PROPERTY)) { 424 if (value != null) { 425 fNamespaceContext = (NamespaceContext)value; 426 } 427 } 428 429 return; 430 } 431 432 } 434 443 public Boolean getFeatureDefault(String featureId) { 444 445 for (int i = 0; i < RECOGNIZED_FEATURES.length; i++) { 446 if (RECOGNIZED_FEATURES[i].equals(featureId)) { 447 return FEATURE_DEFAULTS[i]; 448 } 449 } 450 return super.getFeatureDefault(featureId); 451 } 453 462 public Object getPropertyDefault(String propertyId) { 463 for (int i = 0; i < RECOGNIZED_PROPERTIES.length; i++) { 464 if (RECOGNIZED_PROPERTIES[i].equals(propertyId)) { 465 return PROPERTY_DEFAULTS[i]; 466 } 467 } 468 return super.getPropertyDefault(propertyId); 469 } 471 475 490 public void startEntity(String name, 491 XMLResourceIdentifier identifier, 492 String encoding, Augmentations augs) throws XNIException { 493 494 super.startEntity(name, identifier, encoding, augs); 495 496 if (!name.equals("[xml]") && fEntityScanner.isExternal()) { 498 setScannerState(SCANNER_STATE_TEXT_DECL); 499 } 500 501 if (fDocumentHandler != null && name.equals("[xml]")) { 503 fDocumentHandler.startDocument(fEntityScanner, encoding, fNamespaceContext, null); 504 } 505 506 } 508 517 public void endEntity(String name, Augmentations augs) throws XNIException { 518 519 super.endEntity(name, augs); 520 521 if (fDocumentHandler != null && name.equals("[xml]")) { 523 fDocumentHandler.endDocument(null); 524 } 525 526 } 528 532 534 535 protected Dispatcher createContentDispatcher() { 536 return new ContentDispatcher(); 537 } 539 541 542 protected boolean scanDoctypeDecl() throws IOException , XNIException { 543 544 if (!fEntityScanner.skipSpaces()) { 546 reportFatalError("MSG_SPACE_REQUIRED_BEFORE_ROOT_ELEMENT_TYPE_IN_DOCTYPEDECL", 547 null); 548 } 549 550 fDoctypeName = fEntityScanner.scanName(); 552 if (fDoctypeName == null) { 553 reportFatalError("MSG_ROOT_ELEMENT_TYPE_REQUIRED", null); 554 } 555 556 if (fEntityScanner.skipSpaces()) { 558 scanExternalID(fStrings, false); 559 fDoctypeSystemId = fStrings[0]; 560 fDoctypePublicId = fStrings[1]; 561 fEntityScanner.skipSpaces(); 562 } 563 564 fHasExternalDTD = fDoctypeSystemId != null; 565 566 if (!fHasExternalDTD && fExternalSubsetResolver != null) { 568 fDTDDescription.setValues(null, null, fEntityManager.getCurrentResourceIdentifier().getExpandedSystemId(), null); 569 fDTDDescription.setRootName(fDoctypeName); 570 fExternalSubsetSource = fExternalSubsetResolver.getExternalSubset(fDTDDescription); 571 fHasExternalDTD = fExternalSubsetSource != null; 572 } 573 574 if (fDocumentHandler != null) { 576 if (fExternalSubsetSource == null) { 582 fDocumentHandler.doctypeDecl(fDoctypeName, fDoctypePublicId, fDoctypeSystemId, null); 583 } 584 else { 585 fDocumentHandler.doctypeDecl(fDoctypeName, fExternalSubsetSource.getPublicId(), fExternalSubsetSource.getSystemId(), null); 586 } 587 } 588 589 boolean internalSubset = true; 591 if (!fEntityScanner.skipChar('[')) { 592 internalSubset = false; 593 fEntityScanner.skipSpaces(); 594 if (!fEntityScanner.skipChar('>')) { 595 reportFatalError("DoctypedeclUnterminated", new Object []{fDoctypeName}); 596 } 597 fMarkupDepth--; 598 } 599 600 return internalSubset; 601 602 } 604 608 609 protected String getScannerStateName(int state) { 610 611 switch (state) { 612 case SCANNER_STATE_XML_DECL: return "SCANNER_STATE_XML_DECL"; 613 case SCANNER_STATE_PROLOG: return "SCANNER_STATE_PROLOG"; 614 case SCANNER_STATE_TRAILING_MISC: return "SCANNER_STATE_TRAILING_MISC"; 615 case SCANNER_STATE_DTD_INTERNAL_DECLS: return "SCANNER_STATE_DTD_INTERNAL_DECLS"; 616 case SCANNER_STATE_DTD_EXTERNAL: return "SCANNER_STATE_DTD_EXTERNAL"; 617 case SCANNER_STATE_DTD_EXTERNAL_DECLS: return "SCANNER_STATE_DTD_EXTERNAL_DECLS"; 618 } 619 return super.getScannerStateName(state); 620 621 } 623 627 632 protected final class XMLDeclDispatcher 633 implements Dispatcher { 634 635 639 651 public boolean dispatch(boolean complete) 652 throws IOException , XNIException { 653 654 setScannerState(SCANNER_STATE_PROLOG); 657 setDispatcher(fPrologDispatcher); 658 659 try { 661 if (fEntityScanner.skipString("<?xml")) { 662 fMarkupDepth++; 663 if (XMLChar.isName(fEntityScanner.peekChar())) { 666 fStringBuffer.clear(); 667 fStringBuffer.append("xml"); 668 if (fNamespaces) { 669 while (XMLChar.isNCName(fEntityScanner.peekChar())) { 670 fStringBuffer.append((char)fEntityScanner.scanChar()); 671 } 672 } 673 else { 674 while (XMLChar.isName(fEntityScanner.peekChar())) { 675 fStringBuffer.append((char)fEntityScanner.scanChar()); 676 } 677 } 678 String target = fSymbolTable.addSymbol(fStringBuffer.ch, fStringBuffer.offset, fStringBuffer.length); 679 scanPIData(target, fString); 680 } 681 682 else { 684 scanXMLDeclOrTextDecl(false); 685 } 686 } 687 fEntityManager.fCurrentEntity.mayReadChunks = true; 688 689 return true; 691 } 692 catch (MalformedByteSequenceException e) { 694 fErrorReporter.reportError(e.getDomain(), e.getKey(), 695 e.getArguments(), XMLErrorReporter.SEVERITY_FATAL_ERROR); 696 return false; 697 } 698 catch (CharConversionException e) { 699 reportFatalError("CharConversionFailure", null); 700 return false; 701 } 702 catch (EOFException e) { 704 reportFatalError("PrematureEOF", null); 705 return false; 706 } 708 709 710 } 712 } 714 719 protected final class PrologDispatcher 720 implements Dispatcher { 721 722 726 738 public boolean dispatch(boolean complete) 739 throws IOException , XNIException { 740 741 try { 742 boolean again; 743 do { 744 again = false; 745 switch (fScannerState) { 746 case SCANNER_STATE_PROLOG: { 747 fEntityScanner.skipSpaces(); 748 if (fEntityScanner.skipChar('<')) { 749 setScannerState(SCANNER_STATE_START_OF_MARKUP); 750 again = true; 751 } 752 else if (fEntityScanner.skipChar('&')) { 753 setScannerState(SCANNER_STATE_REFERENCE); 754 again = true; 755 } 756 else { 757 setScannerState(SCANNER_STATE_CONTENT); 758 again = true; 759 } 760 break; 761 } 762 case SCANNER_STATE_START_OF_MARKUP: { 763 fMarkupDepth++; 764 if (fEntityScanner.skipChar('!')) { 765 if (fEntityScanner.skipChar('-')) { 766 if (!fEntityScanner.skipChar('-')) { 767 reportFatalError("InvalidCommentStart", 768 null); 769 } 770 setScannerState(SCANNER_STATE_COMMENT); 771 again = true; 772 } 773 else if (fEntityScanner.skipString("DOCTYPE")) { 774 setScannerState(SCANNER_STATE_DOCTYPE); 775 again = true; 776 } 777 else { 778 reportFatalError("MarkupNotRecognizedInProlog", 779 null); 780 } 781 } 782 else if (isValidNameStartChar(fEntityScanner.peekChar())) { 783 setScannerState(SCANNER_STATE_ROOT_ELEMENT); 784 setDispatcher(fContentDispatcher); 785 return true; 786 } 787 else if (fEntityScanner.skipChar('?')) { 788 setScannerState(SCANNER_STATE_PI); 789 again = true; 790 } 791 else if (isValidNameStartHighSurrogate(fEntityScanner.peekChar())) { 792 setScannerState(SCANNER_STATE_ROOT_ELEMENT); 793 setDispatcher(fContentDispatcher); 794 return true; 795 } 796 else { 797 reportFatalError("MarkupNotRecognizedInProlog", 798 null); 799 } 800 break; 801 } 802 case SCANNER_STATE_COMMENT: { 803 scanComment(); 804 setScannerState(SCANNER_STATE_PROLOG); 805 break; 806 } 807 case SCANNER_STATE_PI: { 808 scanPI(); 809 setScannerState(SCANNER_STATE_PROLOG); 810 break; 811 } 812 case SCANNER_STATE_DOCTYPE: { 813 if (fDisallowDoctype) { 814 reportFatalError("DoctypeNotAllowed", null); 815 } 816 if (fSeenDoctypeDecl) { 817 reportFatalError("AlreadySeenDoctype", null); 818 } 819 fSeenDoctypeDecl = true; 820 821 &
|