1 /* 2 * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved. 3 */ 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.impl; 22 23 24 import com.sun.xml.internal.stream.Entity; 25 import com.sun.xml.internal.stream.StaxXMLInputSource; 26 import com.sun.xml.internal.stream.dtd.DTDGrammarUtil; 27 import java.io.EOFException; 28 import java.io.IOException; 29 import javax.xml.stream.XMLInputFactory; 30 import javax.xml.stream.events.XMLEvent; 31 32 import com.sun.org.apache.xerces.internal.impl.validation.ValidationManager; 33 import com.sun.org.apache.xerces.internal.util.NamespaceSupport; 34 import com.sun.org.apache.xerces.internal.util.XMLChar; 35 import com.sun.org.apache.xerces.internal.util.XMLResourceIdentifierImpl; 36 import com.sun.org.apache.xerces.internal.util.XMLStringBuffer; 37 import com.sun.org.apache.xerces.internal.xni.NamespaceContext; 38 import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier; 39 import com.sun.org.apache.xerces.internal.xni.XMLString; 40 import com.sun.org.apache.xerces.internal.xni.XNIException; 41 import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource; 42 import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager; 43 import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException; 44 import com.sun.org.apache.xerces.internal.xni.parser.XMLDTDScanner; 45 import com.sun.org.apache.xerces.internal.xni.Augmentations; 46 import com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDDescription; 47 import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentScanner; 48 49 50 /** 51 * This class is responsible for scanning XML document structure 52 * and content. 53 * 54 * This class has been modified as per the new design which is more suited to 55 * efficiently build pull parser. Lot of improvements have been done and 56 * the code has been added to support stax functionality/features. 57 * 58 * @author Neeraj Bajaj, Sun Microsystems 59 * @author K.Venugopal, Sun Microsystems 60 * @author Glenn Marcy, IBM 61 * @author Andy Clark, IBM 62 * @author Arnaud Le Hors, IBM 63 * @author Eric Ye, IBM 64 * @author Sunitha Reddy, Sun Microsystems 65 * 66 * Refer to the table in unit-test javax.xml.stream.XMLStreamReaderTest.SupportDTD for changes 67 * related to property SupportDTD. 68 * @author Joe Wang, Sun Microsystems 69 * @version $Id: XMLDocumentScannerImpl.java,v 1.17 2010-11-01 04:39:41 joehw Exp $ 70 */ 71 public class XMLDocumentScannerImpl 72 extends XMLDocumentFragmentScannerImpl{ 73 74 // 75 // Constants 76 // 77 78 // scanner states 79 80 /** Scanner state: XML declaration. */ 81 protected static final int SCANNER_STATE_XML_DECL = 42; 82 83 /** Scanner state: prolog. */ 84 protected static final int SCANNER_STATE_PROLOG = 43; 85 86 /** Scanner state: trailing misc. */ 87 protected static final int SCANNER_STATE_TRAILING_MISC = 44; 88 89 /** Scanner state: DTD internal declarations. */ 90 protected static final int SCANNER_STATE_DTD_INTERNAL_DECLS = 45; 91 92 /** Scanner state: open DTD external subset. */ 93 protected static final int SCANNER_STATE_DTD_EXTERNAL = 46; 94 95 /** Scanner state: DTD external declarations. */ 96 protected static final int SCANNER_STATE_DTD_EXTERNAL_DECLS = 47; 97 98 /** Scanner state: NO MORE ELEMENTS. */ 99 protected static final int SCANNER_STATE_NO_SUCH_ELEMENT_EXCEPTION = 48; 100 101 // feature identifiers 102 103 /** Property identifier document scanner: */ 104 protected static final String DOCUMENT_SCANNER = 105 Constants.XERCES_PROPERTY_PREFIX + Constants.DOCUMENT_SCANNER_PROPERTY; 106 107 /** Feature identifier: load external DTD. */ 108 protected static final String LOAD_EXTERNAL_DTD = 109 Constants.XERCES_FEATURE_PREFIX + Constants.LOAD_EXTERNAL_DTD_FEATURE; 110 111 /** Feature identifier: load external DTD. */ 112 protected static final String DISALLOW_DOCTYPE_DECL_FEATURE = 113 Constants.XERCES_FEATURE_PREFIX + Constants.DISALLOW_DOCTYPE_DECL_FEATURE; 114 115 // property identifiers 116 117 /** Property identifier: DTD scanner. */ 118 protected static final String DTD_SCANNER = 119 Constants.XERCES_PROPERTY_PREFIX + Constants.DTD_SCANNER_PROPERTY; 120 121 // property identifier: ValidationManager 122 protected static final String VALIDATION_MANAGER = 123 Constants.XERCES_PROPERTY_PREFIX + Constants.VALIDATION_MANAGER_PROPERTY; 124 125 /** property identifier: NamespaceContext */ 126 protected static final String NAMESPACE_CONTEXT = 127 Constants.XERCES_PROPERTY_PREFIX + Constants.NAMESPACE_CONTEXT_PROPERTY; 128 129 // recognized features and properties 130 131 /** Recognized features. */ 132 private static final String[] RECOGNIZED_FEATURES = { 133 LOAD_EXTERNAL_DTD, 134 DISALLOW_DOCTYPE_DECL_FEATURE, 135 }; 136 137 /** Feature defaults. */ 138 private static final Boolean[] FEATURE_DEFAULTS = { 139 Boolean.TRUE, 140 Boolean.FALSE, 141 }; 142 143 /** Recognized properties. */ 144 private static final String[] RECOGNIZED_PROPERTIES = { 145 DTD_SCANNER, 146 VALIDATION_MANAGER 147 }; 148 149 /** Property defaults. */ 150 private static final Object[] PROPERTY_DEFAULTS = { 151 null, 152 null 153 }; 154 155 // 156 // Data((Boolean)propertyManager.getProperty(XMLInputFactory.IS_NAMESPACE_AWARE)).booleanValue(); 157 // 158 159 // properties 160 161 /** DTD scanner. */ 162 protected XMLDTDScanner fDTDScanner = null; 163 164 /** Validation manager . */ 165 //xxx: fValidationManager code needs to be added yet! 166 protected ValidationManager fValidationManager; 167 168 protected XMLStringBuffer fDTDDecl = null; 169 protected boolean fReadingDTD = false; 170 protected boolean fAddedListener = false; 171 172 // protected data 173 174 // other info 175 176 /** Doctype name. */ 177 protected String fDoctypeName; 178 179 /** Doctype declaration public identifier. */ 180 protected String fDoctypePublicId; 181 182 /** Doctype declaration system identifier. */ 183 protected String fDoctypeSystemId; 184 185 /** Namespace support. */ 186 protected NamespaceContext fNamespaceContext = new NamespaceSupport(); 187 188 // features 189 190 /** Load external DTD. */ 191 protected boolean fLoadExternalDTD = true; 192 193 // state 194 195 /** Seen doctype declaration. */ 196 protected boolean fSeenDoctypeDecl; 197 198 protected boolean fScanEndElement; 199 200 //protected int fScannerLastState ; 201 202 // drivers 203 204 /** XML declaration driver. */ 205 protected Driver fXMLDeclDriver = new XMLDeclDriver(); 206 207 /** Prolog driver. */ 208 protected Driver fPrologDriver = new PrologDriver(); 209 210 /** DTD driver. */ 211 protected Driver fDTDDriver = null ; 212 213 /** Trailing miscellaneous section driver. */ 214 protected Driver fTrailingMiscDriver = new TrailingMiscDriver(); 215 protected int fStartPos = 0; 216 protected int fEndPos = 0; 217 protected boolean fSeenInternalSubset= false; 218 // temporary variables 219 220 /** Array of 3 strings. */ 221 private String[] fStrings = new String[3]; 222 223 /** External subset source. */ 224 private XMLInputSource fExternalSubsetSource = null; 225 226 /** A DTD Description. */ 227 private final XMLDTDDescription fDTDDescription = new XMLDTDDescription(null, null, null, null, null); 228 229 /** String. */ 230 private XMLString fString = new XMLString(); 231 232 private static final char [] DOCTYPE = {'D','O','C','T','Y','P','E'}; 233 private static final char [] COMMENTSTRING = {'-','-'}; 234 235 // 236 // Constructors 237 // 238 239 /** Default constructor. */ 240 public XMLDocumentScannerImpl() {} // <init>() 241 242 243 // 244 // XMLDocumentScanner methods 245 // 246 247 248 /** 249 * Sets the input source. 250 * 251 * @param inputSource The input source. 252 * 253 * @throws IOException Thrown on i/o error. 254 */ 255 public void setInputSource(XMLInputSource inputSource) throws IOException { 256 fEntityManager.setEntityHandler(this); 257 //this starts a new entity and sets the current entity to the document entity. 258 fEntityManager.startDocumentEntity(inputSource); 259 // fDocumentSystemId = fEntityManager.expandSystemId(inputSource.getSystemId()); 260 setScannerState(XMLEvent.START_DOCUMENT); 261 } // setInputSource(XMLInputSource) 262 263 264 265 /**return the state of the scanner */ 266 public int getScannetState(){ 267 return fScannerState ; 268 } 269 270 271 272 273 public void reset(PropertyManager propertyManager) { 274 super.reset(propertyManager); 275 // other settings 276 fDoctypeName = null; 277 fDoctypePublicId = null; 278 fDoctypeSystemId = null; 279 fSeenDoctypeDecl = false; 280 fNamespaceContext.reset(); 281 fSupportDTD = ((Boolean)propertyManager.getProperty(XMLInputFactory.SUPPORT_DTD)).booleanValue(); 282 283 // xerces features 284 fLoadExternalDTD = !((Boolean)propertyManager.getProperty(Constants.ZEPHYR_PROPERTY_PREFIX + Constants.IGNORE_EXTERNAL_DTD)).booleanValue(); 285 setScannerState(XMLEvent.START_DOCUMENT); 286 setDriver(fXMLDeclDriver); 287 fSeenInternalSubset = false; 288 if(fDTDScanner != null){ 289 ((XMLDTDScannerImpl)fDTDScanner).reset(propertyManager); 290 } 291 fEndPos = 0; 292 fStartPos = 0; 293 if(fDTDDecl != null){ 294 fDTDDecl.clear(); 295 } 296 297 } 298 299 /** 300 * Resets the component. The component can query the component manager 301 * about any features and properties that affect the operation of the 302 * component. 303 * 304 * @param componentManager The component manager. 305 * 306 * @throws SAXException Thrown by component on initialization error. 307 * For example, if a feature or property is 308 * required for the operation of the component, the 309 * component manager may throw a 310 * SAXNotRecognizedException or a 311 * SAXNotSupportedException. 312 */ 313 public void reset(XMLComponentManager componentManager) 314 throws XMLConfigurationException { 315 316 super.reset(componentManager); 317 318 // other settings 319 fDoctypeName = null; 320 fDoctypePublicId = null; 321 fDoctypeSystemId = null; 322 fSeenDoctypeDecl = false; 323 fExternalSubsetSource = null; 324 325 // xerces features 326 fLoadExternalDTD = componentManager.getFeature(LOAD_EXTERNAL_DTD, true); 327 fDisallowDoctype = componentManager.getFeature(DISALLOW_DOCTYPE_DECL_FEATURE, false); 328 329 fNamespaces = componentManager.getFeature(NAMESPACES, true); 330 331 fSeenInternalSubset = false; 332 // xerces properties 333 fDTDScanner = (XMLDTDScanner)componentManager.getProperty(DTD_SCANNER); 334 335 fValidationManager = (ValidationManager)componentManager.getProperty(VALIDATION_MANAGER, null); 336 337 try { 338 fNamespaceContext = (NamespaceContext)componentManager.getProperty(NAMESPACE_CONTEXT); 339 } 340 catch (XMLConfigurationException e) { } 341 if (fNamespaceContext == null) { 342 fNamespaceContext = new NamespaceSupport(); 343 } 344 fNamespaceContext.reset(); 345 346 fEndPos = 0; 347 fStartPos = 0; 348 if(fDTDDecl != null) 349 fDTDDecl.clear(); 350 351 352 //fEntityScanner.registerListener((XMLBufferListener)componentManager.getProperty(DOCUMENT_SCANNER)); 353 354 // setup driver 355 setScannerState(SCANNER_STATE_XML_DECL); 356 setDriver(fXMLDeclDriver); 357 358 } // reset(XMLComponentManager) 359 360 361 /** 362 * Returns a list of feature identifiers that are recognized by 363 * this component. This method may return null if no features 364 * are recognized by this component. 365 */ 366 public String[] getRecognizedFeatures() { 367 String[] featureIds = super.getRecognizedFeatures(); 368 int length = featureIds != null ? featureIds.length : 0; 369 String[] combinedFeatureIds = new String[length + RECOGNIZED_FEATURES.length]; 370 if (featureIds != null) { 371 System.arraycopy(featureIds, 0, combinedFeatureIds, 0, featureIds.length); 372 } 373 System.arraycopy(RECOGNIZED_FEATURES, 0, combinedFeatureIds, length, RECOGNIZED_FEATURES.length); 374 return combinedFeatureIds; 375 } // getRecognizedFeatures():String[] 376 377 /** 378 * Sets the state of a feature. This method is called by the component 379 * manager any time after reset when a feature changes state. 380 * <p> 381 * <strong>Note:</strong> Components should silently ignore features 382 * that do not affect the operation of the component. 383 * 384 * @param featureId The feature identifier. 385 * @param state The state of the feature. 386 * 387 * @throws SAXNotRecognizedException The component should not throw 388 * this exception. 389 * @throws SAXNotSupportedException The component should not throw 390 * this exception. 391 */ 392 public void setFeature(String featureId, boolean state) 393 throws XMLConfigurationException { 394 395 super.setFeature(featureId, state); 396 397 // Xerces properties 398 if (featureId.startsWith(Constants.XERCES_FEATURE_PREFIX)) { 399 final int suffixLength = featureId.length() - Constants.XERCES_FEATURE_PREFIX.length(); 400 401 if (suffixLength == Constants.LOAD_EXTERNAL_DTD_FEATURE.length() && 402 featureId.endsWith(Constants.LOAD_EXTERNAL_DTD_FEATURE)) { 403 fLoadExternalDTD = state; 404 return; 405 } 406 else if (suffixLength == Constants.DISALLOW_DOCTYPE_DECL_FEATURE.length() && 407 featureId.endsWith(Constants.DISALLOW_DOCTYPE_DECL_FEATURE)) { 408 fDisallowDoctype = state; 409 return; 410 } 411 } 412 413 } // setFeature(String,boolean) 414 415 /** 416 * Returns a list of property identifiers that are recognized by 417 * this component. This method may return null if no properties 418 * are recognized by this component. 419 */ 420 public String[] getRecognizedProperties() { 421 String[] propertyIds = super.getRecognizedProperties(); 422 int length = propertyIds != null ? propertyIds.length : 0; 423 String[] combinedPropertyIds = new String[length + RECOGNIZED_PROPERTIES.length]; 424 if (propertyIds != null) { 425 System.arraycopy(propertyIds, 0, combinedPropertyIds, 0, propertyIds.length); 426 } 427 System.arraycopy(RECOGNIZED_PROPERTIES, 0, combinedPropertyIds, length, RECOGNIZED_PROPERTIES.length); 428 return combinedPropertyIds; 429 } // getRecognizedProperties():String[] 430 431 /** 432 * Sets the value of a property. This method is called by the component 433 * manager any time after reset when a property changes value. 434 * <p> 435 * <strong>Note:</strong> Components should silently ignore properties 436 * that do not affect the operation of the component. 437 * 438 * @param propertyId The property identifier. 439 * @param value The value of the property. 440 * 441 * @throws SAXNotRecognizedException The component should not throw 442 * this exception. 443 * @throws SAXNotSupportedException The component should not throw 444 * this exception. 445 */ 446 public void setProperty(String propertyId, Object value) 447 throws XMLConfigurationException { 448 449 super.setProperty(propertyId, value); 450 451 // Xerces properties 452 if (propertyId.startsWith(Constants.XERCES_PROPERTY_PREFIX)) { 453 final int suffixLength = propertyId.length() - Constants.XERCES_PROPERTY_PREFIX.length(); 454 455 if (suffixLength == Constants.DTD_SCANNER_PROPERTY.length() && 456 propertyId.endsWith(Constants.DTD_SCANNER_PROPERTY)) { 457 fDTDScanner = (XMLDTDScanner)value; 458 } 459 if (suffixLength == Constants.NAMESPACE_CONTEXT_PROPERTY.length() && 460 propertyId.endsWith(Constants.NAMESPACE_CONTEXT_PROPERTY)) { 461 if (value != null) { 462 fNamespaceContext = (NamespaceContext)value; 463 } 464 } 465 466 return; 467 } 468 469 } // setProperty(String,Object) 470 471 /** 472 * Returns the default state for a feature, or null if this 473 * component does not want to report a default value for this 474 * feature. 475 * 476 * @param featureId The feature identifier. 477 * 478 * @since Xerces 2.2.0 479 */ 480 public Boolean getFeatureDefault(String featureId) { 481 482 for (int i = 0; i < RECOGNIZED_FEATURES.length; i++) { 483 if (RECOGNIZED_FEATURES[i].equals(featureId)) { 484 return FEATURE_DEFAULTS[i]; 485 } 486 } 487 return super.getFeatureDefault(featureId); 488 } // getFeatureDefault(String):Boolean 489 490 /** 491 * Returns the default state for a property, or null if this 492 * component does not want to report a default value for this 493 * property. 494 * 495 * @param propertyId The property identifier. 496 * 497 * @since Xerces 2.2.0 498 */ 499 public Object getPropertyDefault(String propertyId) { 500 for (int i = 0; i < RECOGNIZED_PROPERTIES.length; i++) { 501 if (RECOGNIZED_PROPERTIES[i].equals(propertyId)) { 502 return PROPERTY_DEFAULTS[i]; 503 } 504 } 505 return super.getPropertyDefault(propertyId); 506 } // getPropertyDefault(String):Object 507 508 // 509 // XMLEntityHandler methods 510 // 511 512 /** 513 * This method notifies of the start of an entity. The DTD has the 514 * pseudo-name of "[dtd]" parameter entity names start with '%'; and 515 * general entities are just specified by their name. 516 * 517 * @param name The name of the entity. 518 * @param identifier The resource identifier. 519 * @param encoding The auto-detected IANA encoding name of the entity 520 * stream. This value will be null in those situations 521 * where the entity encoding is not auto-detected (e.g. 522 * internal entities or a document entity that is 523 * parsed from a java.io.Reader). 524 * 525 * @throws XNIException Thrown by handler to signal an error. 526 */ 527 public void startEntity(String name, 528 XMLResourceIdentifier identifier, 529 String encoding, Augmentations augs) throws XNIException { 530 531 super.startEntity(name, identifier, encoding,augs); 532 533 //register current document scanner as a listener for XMLEntityScanner 534 fEntityScanner.registerListener(this); 535 536 // prepare to look for a TextDecl if external general entity 537 if (!name.equals("[xml]") && fEntityScanner.isExternal()) { 538 // Don't do this if we're skipping the entity! 539 if (augs == null || !((Boolean) augs.getItem(Constants.ENTITY_SKIPPED)).booleanValue()) { 540 setScannerState(SCANNER_STATE_TEXT_DECL); 541 } 542 } 543 544 // call handler 545 /** comment this part.. LOCATOR problem.. */ 546 if (fDocumentHandler != null && name.equals("[xml]")) { 547 fDocumentHandler.startDocument(fEntityScanner, encoding, fNamespaceContext, null); 548 } 549 550 } // startEntity(String,identifier,String) 551 552 553 /** 554 * This method notifies the end of an entity. The DTD has the pseudo-name 555 * of "[dtd]" parameter entity names start with '%'; and general entities 556 * are just specified by their name. 557 * 558 * @param name The name of the entity. 559 * 560 * @throws XNIException Thrown by handler to signal an error. 561 */ 562 public void endEntity(String name, Augmentations augs) throws IOException, XNIException { 563 564 super.endEntity(name, augs); 565 566 if(name.equals("[xml]")){ 567 //if fMarkupDepth has reached 0. 568 //and driver is fTrailingMiscDriver (which 569 //handles end of document in normal case) 570 //set the scanner state of SCANNER_STATE_TERMINATED 571 if(fMarkupDepth == 0 && fDriver == fTrailingMiscDriver){ 572 //set the scanner set to SCANNER_STATE_TERMINATED 573 setScannerState(SCANNER_STATE_TERMINATED) ; 574 } else{ 575 //else we have reached the end of document prematurely 576 //so throw EOFException. 577 throw new java.io.EOFException(); 578 } 579 580 //this is taken care in wrapper which generates XNI callbacks, There are no next events 581 582 //if (fDocumentHandler != null) { 583 //fDocumentHandler.endDocument(null); 584 //} 585 } 586 } // endEntity(String) 587 588 589 public XMLStringBuffer getDTDDecl(){ 590 Entity entity = fEntityScanner.getCurrentEntity(); 591 fDTDDecl.append(((Entity.ScannedEntity)entity).ch,fStartPos , fEndPos-fStartPos); 592 if(fSeenInternalSubset) 593 fDTDDecl.append("]>"); 594 return fDTDDecl; 595 } 596 597 public String getCharacterEncodingScheme(){ 598 return fDeclaredEncoding; 599 } 600 601 /** return the next state on the input 602 * 603 * @return int 604 */ 605 606 public int next() throws IOException, XNIException { 607 return fDriver.next(); 608 } 609 610 //getNamespaceContext 611 public NamespaceContext getNamespaceContext(){ 612 return fNamespaceContext ; 613 } 614 615 616 617 // 618 // Protected methods 619 // 620 621 // driver factory methods 622 623 /** Creates a content driver. */ 624 protected Driver createContentDriver() { 625 return new ContentDriver(); 626 } // createContentDriver():Driver 627 628 // scanning methods 629 630 /** Scans a doctype declaration. */ 631 protected boolean scanDoctypeDecl(boolean supportDTD) throws IOException, XNIException { 632 633 // spaces 634 if (!fEntityScanner.skipSpaces()) { 635 reportFatalError("MSG_SPACE_REQUIRED_BEFORE_ROOT_ELEMENT_TYPE_IN_DOCTYPEDECL", 636 null); 637 } 638 639 // root element name 640 fDoctypeName = fEntityScanner.scanName(); 641 if (fDoctypeName == null) { 642 reportFatalError("MSG_ROOT_ELEMENT_TYPE_REQUIRED", null); 643 } 644 645 // external id 646 if (fEntityScanner.skipSpaces()) { 647 scanExternalID(fStrings, false); 648 fDoctypeSystemId = fStrings[0]; 649 fDoctypePublicId = fStrings[1]; 650 fEntityScanner.skipSpaces(); 651 } 652 653 fHasExternalDTD = fDoctypeSystemId != null; 654 655 // Attempt to locate an external subset with an external subset resolver. 656 if (supportDTD && !fHasExternalDTD && fExternalSubsetResolver != null) { 657 fDTDDescription.setValues(null, null, fEntityManager.getCurrentResourceIdentifier().getExpandedSystemId(), null); 658 fDTDDescription.setRootName(fDoctypeName); 659 fExternalSubsetSource = fExternalSubsetResolver.getExternalSubset(fDTDDescription); 660 fHasExternalDTD = fExternalSubsetSource != null; 661 } 662 663 // call handler 664 if (supportDTD && fDocumentHandler != null) { 665 // NOTE: I don't like calling the doctypeDecl callback until 666 // end of the *full* doctype line (including internal 667 // subset) is parsed correctly but SAX2 requires that 668 // it knows the root element name and public and system 669 // identifier for the startDTD call. -Ac 670 if (fExternalSubsetSource == null) { 671 fDocumentHandler.doctypeDecl(fDoctypeName, fDoctypePublicId, fDoctypeSystemId, null); 672 } 673 else { 674 fDocumentHandler.doctypeDecl(fDoctypeName, fExternalSubsetSource.getPublicId(), fExternalSubsetSource.getSystemId(), null); 675 } 676 } 677 678 // is there an internal subset? 679 boolean internalSubset = true; 680 if (!fEntityScanner.skipChar('[')) { 681 internalSubset = false; 682 fEntityScanner.skipSpaces(); 683 if (!fEntityScanner.skipChar('>')) { 684 reportFatalError("DoctypedeclUnterminated", new Object[]{fDoctypeName}); 685 } 686 fMarkupDepth--; 687 } 688 return internalSubset; 689 690 } // scanDoctypeDecl():boolean 691 692 // 693 // Private methods 694 // 695 /** Set the scanner state after scanning DTD */ 696 protected void setEndDTDScanState() { 697 setScannerState(SCANNER_STATE_PROLOG); 698 setDriver(fPrologDriver); 699 fEntityManager.setEntityHandler(XMLDocumentScannerImpl.this); 700 fReadingDTD=false; 701 } 702 703 /** Returns the scanner state name. */ 704 protected String getScannerStateName(int state) { 705 706 switch (state) { 707 case SCANNER_STATE_XML_DECL: return "SCANNER_STATE_XML_DECL"; 708 case SCANNER_STATE_PROLOG: return "SCANNER_STATE_PROLOG"; 709 case SCANNER_STATE_TRAILING_MISC: return "SCANNER_STATE_TRAILING_MISC"; 710 case SCANNER_STATE_DTD_INTERNAL_DECLS: return "SCANNER_STATE_DTD_INTERNAL_DECLS"; 711 case SCANNER_STATE_DTD_EXTERNAL: return "SCANNER_STATE_DTD_EXTERNAL"; 712 case SCANNER_STATE_DTD_EXTERNAL_DECLS: return "SCANNER_STATE_DTD_EXTERNAL_DECLS"; 713 } 714 return super.getScannerStateName(state); 715 716 } // getScannerStateName(int):String 717 718 // 719 // Classes 720 // 721 722 /** 723 * Driver to handle XMLDecl scanning. 724 * 725 * This class has been modified as per the new design which is more suited to 726 * efficiently build pull parser. Lots of performance improvements have been done and 727 * the code has been added to support stax functionality/features. 728 * 729 * @author Neeraj Bajaj, Sun Microsystems. 730 * 731 * @author Andy Clark, IBM 732 */ 733 protected final class XMLDeclDriver 734 implements Driver { 735 736 // 737 // Driver methods 738 // 739 740 741 public int next() throws IOException, XNIException { 742 if(DEBUG_NEXT){ 743 System.out.println("NOW IN XMLDeclDriver"); 744 } 745 746 // next driver is prolog regardless of whether there 747 // is an XMLDecl in this document 748 setScannerState(SCANNER_STATE_PROLOG); 749 setDriver(fPrologDriver); 750 751 //System.out.println("fEntityScanner = " + fEntityScanner); 752 // scan XMLDecl 753 try { 754 if (fEntityScanner.skipString(xmlDecl)) { 755 fMarkupDepth++; 756 // NOTE: special case where document starts with a PI 757 // whose name starts with "xml" (e.g. "xmlfoo") 758 if (XMLChar.isName(fEntityScanner.peekChar())) { 759 fStringBuffer.clear(); 760 fStringBuffer.append("xml"); 761 while (XMLChar.isName(fEntityScanner.peekChar())) { 762 fStringBuffer.append((char)fEntityScanner.scanChar()); 763 } 764 String target = fSymbolTable.addSymbol(fStringBuffer.ch, fStringBuffer.offset, fStringBuffer.length); 765 //this function should fill the data.. and set the fEvent object to this event. 766 fContentBuffer.clear() ; 767 scanPIData(target, fContentBuffer); 768 //REVISIT:where else we can set this value to 'true' 769 fEntityManager.fCurrentEntity.mayReadChunks = true; 770 //return PI event since PI was encountered 771 return XMLEvent.PROCESSING_INSTRUCTION ; 772 } 773 // standard XML declaration 774 else { 775 scanXMLDeclOrTextDecl(false); 776 //REVISIT:where else we can set this value to 'true' 777 fEntityManager.fCurrentEntity.mayReadChunks = true; 778 return XMLEvent.START_DOCUMENT; 779 } 780 } else{ 781 //REVISIT:where else we can set this value to 'true' 782 fEntityManager.fCurrentEntity.mayReadChunks = true; 783 //In both case return the START_DOCUMENT. ony difference is that first block will 784 //cosume the XML declaration if any. 785 return XMLEvent.START_DOCUMENT; 786 } 787 788 789 //START_OF_THE_DOCUMENT 790 791 792 } 793 794 // premature end of file 795 catch (EOFException e) { 796 reportFatalError("PrematureEOF", null); 797 return -1; 798 //throw e; 799 } 800 801 } 802 } // class XMLDeclDriver 803 804 /** 805 * Driver to handle prolog scanning. 806 * 807 * @author Andy Clark, IBM 808 */ 809 protected final class PrologDriver 810 implements Driver { 811 812 /** 813 * Drives the parser to the next state/event on the input. Parser is guaranteed 814 * to stop at the next state/event. 815 * 816 * Internally XML document is divided into several states. Each state represents 817 * a sections of XML document. When this functions returns normally, it has read 818 * the section of XML document and returns the state corresponding to section of 819 * document which has been read. For optimizations, a particular driver 820 * can read ahead of the section of document (state returned) just read and 821 * can maintain a different internal state. 822 * 823 * @return state representing the section of document just read. 824 * 825 * @throws IOException Thrown on i/o error. 826 * @throws XNIException Thrown on parse error. 827 */ 828 829 public int next() throws IOException, XNIException { 830 //System.out.println("here in next"); 831 832 if(DEBUG_NEXT){ 833 System.out.println("NOW IN PrologDriver"); 834 } 835 try { 836 do { 837 switch (fScannerState) { 838 case SCANNER_STATE_PROLOG: { 839 fEntityScanner.skipSpaces(); 840 if (fEntityScanner.skipChar('<')) { 841 setScannerState(SCANNER_STATE_START_OF_MARKUP); 842 } else if (fEntityScanner.skipChar('&')) { 843 setScannerState(SCANNER_STATE_REFERENCE); 844 } else { 845 setScannerState(SCANNER_STATE_CONTENT); 846 } 847 break; 848 } 849 850 case SCANNER_STATE_START_OF_MARKUP: { 851 fMarkupDepth++; 852 853 if (fEntityScanner.skipChar('?')) { 854 setScannerState(SCANNER_STATE_PI); 855 } else if (fEntityScanner.skipChar('!')) { 856 if (fEntityScanner.skipChar('-')) { 857 if (!fEntityScanner.skipChar('-')) { 858 reportFatalError("InvalidCommentStart", 859 null); 860 } 861 setScannerState(SCANNER_STATE_COMMENT); 862 } else if (fEntityScanner.skipString(DOCTYPE)) { 863 setScannerState(SCANNER_STATE_DOCTYPE); 864 Entity entity = fEntityScanner.getCurrentEntity(); 865 if(entity instanceof Entity.ScannedEntity){ 866 fStartPos=((Entity.ScannedEntity)entity).position; 867 } 868 fReadingDTD=true; 869 if(fDTDDecl == null) 870 fDTDDecl = new XMLStringBuffer(); 871 fDTDDecl.append("<!DOCTYPE"); 872 873 } else { 874 reportFatalError("MarkupNotRecognizedInProlog", 875 null); 876 } 877 } else if (XMLChar.isNameStart(fEntityScanner.peekChar())) { 878 setScannerState(SCANNER_STATE_ROOT_ELEMENT); 879 setDriver(fContentDriver); 880 //from now onwards this would be handled by fContentDriver,in the same next() call 881 return fContentDriver.next(); 882 883 } else { 884 reportFatalError("MarkupNotRecognizedInProlog", 885 null); 886 } 887 break; 888 } 889 } 890 } while (fScannerState == SCANNER_STATE_PROLOG || fScannerState == SCANNER_STATE_START_OF_MARKUP ); 891 892 switch(fScannerState){ 893 /** 894 //this part is handled by FragmentContentHandler 895 case SCANNER_STATE_ROOT_ELEMENT: { 896 //we have read '<' and beginning of reading the start element tag 897 setScannerState(SCANNER_STATE_START_ELEMENT_TAG); 898 setDriver(fContentDriver); 899 //from now onwards this would be handled by fContentDriver,in the same next() call 900 return fContentDriver.next(); 901 } 902 */ 903 case SCANNER_STATE_COMMENT: { 904 //this function fills the data.. 905 scanComment(); 906 setScannerState(SCANNER_STATE_PROLOG); 907 return XMLEvent.COMMENT; 908 //setScannerState(SCANNER_STATE_PROLOG); 909 //break; 910 } 911 case SCANNER_STATE_PI: { 912 fContentBuffer.clear() ; 913 scanPI(fContentBuffer); 914 setScannerState(SCANNER_STATE_PROLOG); 915 return XMLEvent.PROCESSING_INSTRUCTION; 916 } 917 918 case SCANNER_STATE_DOCTYPE: { 919 if (fDisallowDoctype) { 920 reportFatalError("DoctypeNotAllowed", null); 921 } 922 923 924 if (fSeenDoctypeDecl) { 925 reportFatalError("AlreadySeenDoctype", null); 926 } 927 fSeenDoctypeDecl = true; 928 929 // scanDoctypeDecl() sends XNI doctypeDecl event that 930 // in SAX is converted to startDTD() event. 931 if (scanDoctypeDecl(fSupportDTD)) { 932 //allow parsing of entity decls to continue in order to stay well-formed 933 setScannerState(SCANNER_STATE_DTD_INTERNAL_DECLS); 934 fSeenInternalSubset = true; 935 if(fDTDDriver == null){ 936 fDTDDriver = new DTDDriver(); 937 } 938 setDriver(fContentDriver); 939 //always return DTD event, the event however, will not contain any entities 940 return fDTDDriver.next(); 941 } 942 943 if(fSeenDoctypeDecl){ 944 Entity entity = fEntityScanner.getCurrentEntity(); 945 if(entity instanceof Entity.ScannedEntity){ 946 fEndPos = ((Entity.ScannedEntity)entity).position; 947 } 948 fReadingDTD = false; 949 } 950 951 // handle external subset 952 if (fDoctypeSystemId != null) { 953 if (((fValidation || fLoadExternalDTD) 954 && (fValidationManager == null || !fValidationManager.isCachedDTD()))) { 955 if (fSupportDTD) 956 setScannerState(SCANNER_STATE_DTD_EXTERNAL); 957 else 958 setScannerState(SCANNER_STATE_PROLOG); 959 setDriver(fContentDriver); 960 if(fDTDDriver == null) 961 fDTDDriver = new DTDDriver(); 962 return fDTDDriver.next(); 963 964 } 965 } 966 else if (fExternalSubsetSource != null) { 967 if (((fValidation || fLoadExternalDTD) 968 && (fValidationManager == null || !fValidationManager.isCachedDTD()))) { 969 // This handles the case of a DOCTYPE that had neither an internal subset or an external subset. 970 fDTDScanner.setInputSource(fExternalSubsetSource); 971 fExternalSubsetSource = null; 972 if (fSupportDTD) 973 setScannerState(SCANNER_STATE_DTD_EXTERNAL_DECLS); 974 else 975 setScannerState(SCANNER_STATE_PROLOG); 976 setDriver(fContentDriver); 977 if(fDTDDriver == null) 978 fDTDDriver = new DTDDriver(); 979 return fDTDDriver.next(); 980 } 981 } 982 983 // Send endDTD() call if: 984 // a) systemId is null or if an external subset resolver could not locate an external subset. 985 // b) "load-external-dtd" and validation are false 986 // c) DTD grammar is cached 987 988 // in XNI this results in 3 events: doctypeDecl, startDTD, endDTD 989 // in SAX this results in 2 events: startDTD, endDTD 990 if (fDTDScanner != null) { 991 fDTDScanner.setInputSource(null); 992 } 993 setScannerState(SCANNER_STATE_PROLOG); 994 return XMLEvent.DTD; 995 } 996 997 case SCANNER_STATE_CONTENT: { 998 reportFatalError("ContentIllegalInProlog", null); 999 fEntityScanner.scanChar(); 1000 } 1001 case SCANNER_STATE_REFERENCE: { 1002 reportFatalError("ReferenceIllegalInProlog", null); 1003 } 1004 1005 /** 1006 * if (complete) { 1007 * if (fEntityScanner.scanChar() != '<') { 1008 * reportFatalError("RootElementRequired", null); 1009 * } 1010 * setScannerState(SCANNER_STATE_ROOT_ELEMENT); 1011 * setDriver(fContentDriver); 1012 * } 1013 */ 1014 } 1015 } 1016 // premature end of file 1017 catch (EOFException e) { 1018 reportFatalError("PrematureEOF", null); 1019 //xxx what should be returned here.... ??? 1020 return -1 ; 1021 //throw e; 1022 } 1023 //xxx what should be returned here.... ??? 1024 return -1; 1025 1026 } 1027 1028 1029 } // class PrologDriver 1030 1031 /** 1032 * Driver to handle the internal and external DTD subsets. 1033 * 1034 * @author Andy Clark, IBM 1035 */ 1036 protected final class DTDDriver 1037 implements Driver { 1038 1039 // 1040 // Driver methods 1041 // 1042 1043 public int next() throws IOException, XNIException{ 1044 // throw new XNIException("DTD Parsing is currently not supported"); 1045 if(DEBUG_NEXT){ 1046 System.out.println("Now in DTD Driver"); 1047 } 1048 1049 dispatch(true); 1050 1051 if(DEBUG_NEXT){ 1052 System.out.println("After calling dispatch(true) -- At this point whole DTD is read."); 1053 } 1054 1055 //xxx: remove this hack and align this with reusing DTD components 1056 //currently this routine will only be executed from Stax 1057 if(fPropertyManager != null){ 1058 dtdGrammarUtil = new DTDGrammarUtil(((XMLDTDScannerImpl)fDTDScanner).getGrammar(),fSymbolTable, fNamespaceContext); 1059 } 1060 1061 return XMLEvent.DTD ; 1062 } 1063 1064 /** 1065 * Dispatch an XML "event". 1066 * 1067 * @param complete True if this driver is intended to scan 1068 * and dispatch as much as possible. 1069 * 1070 * @return True if there is more to dispatch either from this 1071 * or a another driver. 1072 * 1073 * @throws IOException Thrown on i/o error. 1074 * @throws XNIException Thrown on parse error. 1075 */ 1076 public boolean dispatch(boolean complete) 1077 throws IOException, XNIException { 1078 fEntityManager.setEntityHandler(null); 1079 try { 1080 boolean again; 1081 XMLResourceIdentifierImpl resourceIdentifier = new XMLResourceIdentifierImpl(); 1082 if( fDTDScanner == null){ 1083 1084 if (fEntityManager.getEntityScanner() instanceof XML11EntityScanner){ 1085 fDTDScanner = new XML11DTDScannerImpl(); 1086 } else 1087 1088 fDTDScanner = new XMLDTDScannerImpl(); 1089 1090 ((XMLDTDScannerImpl)fDTDScanner).reset(fPropertyManager); 1091 } 1092 do { 1093 again = false; 1094 switch (fScannerState) { 1095 case SCANNER_STATE_DTD_INTERNAL_DECLS: { 1096 // REVISIT: Should there be a feature for 1097 // the "complete" parameter? 1098 boolean completeDTD = true; 1099 1100 boolean moreToScan = fDTDScanner.scanDTDInternalSubset(completeDTD, fStandalone, fHasExternalDTD && fLoadExternalDTD); 1101 Entity entity = fEntityScanner.getCurrentEntity(); 1102 if(entity instanceof Entity.ScannedEntity){ 1103 fEndPos=((Entity.ScannedEntity)entity).position; 1104 } 1105 fReadingDTD=false; 1106 if (!moreToScan) { 1107 // end doctype declaration 1108 if (!fEntityScanner.skipChar(']')) { 1109 reportFatalError("EXPECTED_SQUARE_BRACKET_TO_CLOSE_INTERNAL_SUBSET", 1110 null); 1111 } 1112 fEntityScanner.skipSpaces(); 1113 if (!fEntityScanner.skipChar('>')) { 1114 reportFatalError("DoctypedeclUnterminated", new Object[]{fDoctypeName}); 1115 } 1116 fMarkupDepth--; 1117 1118 if (!fSupportDTD) { 1119 //simply reset the entity store without having to mess around 1120 //with the DTD Scanner code 1121 fEntityStore = fEntityManager.getEntityStore(); 1122 fEntityStore.reset(); 1123 } else { 1124 // scan external subset next unless we are ignoring DTDs 1125 if (fDoctypeSystemId != null && (fValidation || fLoadExternalDTD)) { 1126 setScannerState(SCANNER_STATE_DTD_EXTERNAL); 1127 break; 1128 } 1129 } 1130 1131 setEndDTDScanState(); 1132 return true; 1133 1134 } 1135 break; 1136 } 1137 case SCANNER_STATE_DTD_EXTERNAL: { 1138 /** 1139 fDTDDescription.setValues(fDoctypePublicId, fDoctypeSystemId, null, null); 1140 fDTDDescription.setRootName(fDoctypeName); 1141 XMLInputSource xmlInputSource = 1142 fEntityManager.resolveEntity(fDTDDescription); 1143 fDTDScanner.setInputSource(xmlInputSource); 1144 setScannerState(SCANNER_STATE_DTD_EXTERNAL_DECLS); 1145 again = true; 1146 break; 1147 */ 1148 1149 resourceIdentifier.setValues(fDoctypePublicId, fDoctypeSystemId, null, null); 1150 XMLInputSource xmlInputSource = null ; 1151 StaxXMLInputSource staxInputSource = fEntityManager.resolveEntityAsPerStax(resourceIdentifier); 1152 xmlInputSource = staxInputSource.getXMLInputSource(); 1153 fDTDScanner.setInputSource(xmlInputSource); 1154 setScannerState(SCANNER_STATE_DTD_EXTERNAL_DECLS); 1155 again = true; 1156 break; 1157 } 1158 case SCANNER_STATE_DTD_EXTERNAL_DECLS: { 1159 // REVISIT: Should there be a feature for 1160 // the "complete" parameter? 1161 boolean completeDTD = true; 1162 boolean moreToScan = fDTDScanner.scanDTDExternalSubset(completeDTD); 1163 if (!moreToScan) { 1164 setEndDTDScanState(); 1165 return true; 1166 } 1167 break; 1168 } 1169 case SCANNER_STATE_PROLOG : { 1170 // skip entity decls 1171 setEndDTDScanState(); 1172 return true; 1173 } 1174 default: { 1175 throw new XNIException("DTDDriver#dispatch: scanner state="+fScannerState+" ("+getScannerStateName(fScannerState)+')'); 1176 } 1177 } 1178 } while (complete || again); 1179 } 1180 1181 // premature end of file 1182 catch (EOFException e) { 1183 e.printStackTrace(); 1184 reportFatalError("PrematureEOF", null); 1185 return false; 1186 //throw e; 1187 } 1188 1189 // cleanup 1190 finally { 1191 fEntityManager.setEntityHandler(XMLDocumentScannerImpl.this); 1192 } 1193 1194 return true; 1195 1196 } 1197 1198 // dispatch(boolean):boolean 1199 1200 } // class DTDDriver 1201 1202 /** 1203 * Driver to handle content scanning. 1204 * 1205 * @author Andy Clark, IBM 1206 * @author Eric Ye, IBM 1207 */ 1208 protected class ContentDriver 1209 extends FragmentContentDriver { 1210 1211 // 1212 // Protected methods 1213 // 1214 1215 // hooks 1216 1217 // NOTE: These hook methods are added so that the full document 1218 // scanner can share the majority of code with this class. 1219 1220 /** 1221 * Scan for DOCTYPE hook. This method is a hook for subclasses 1222 * to add code to handle scanning for a the "DOCTYPE" string 1223 * after the string "<!" has been scanned. 1224 * 1225 * @return True if the "DOCTYPE" was scanned; false if "DOCTYPE" 1226 * was not scanned. 1227 */ 1228 protected boolean scanForDoctypeHook() 1229 throws IOException, XNIException { 1230 1231 if (fEntityScanner.skipString(DOCTYPE)) { 1232 setScannerState(SCANNER_STATE_DOCTYPE); 1233 // fEntityScanner.markStartOfDTD(); 1234 return true; 1235 } 1236 return false; 1237 1238 } // scanForDoctypeHook():boolean 1239 1240 /** 1241 * Element depth iz zero. This methos is a hook for subclasses 1242 * to add code to handle when the element depth hits zero. When 1243 * scanning a document fragment, an element depth of zero is 1244 * normal. However, when scanning a full XML document, the 1245 * scanner must handle the trailing miscellanous section of 1246 * the document after the end of the document's root element. 1247 * 1248 * @return True if the caller should stop and return true which 1249 * allows the scanner to switch to a new scanning 1250 * driver. A return value of false indicates that 1251 * the content driver should continue as normal. 1252 */ 1253 protected boolean elementDepthIsZeroHook() 1254 throws IOException, XNIException { 1255 1256 setScannerState(SCANNER_STATE_TRAILING_MISC); 1257 setDriver(fTrailingMiscDriver); 1258 return true; 1259 1260 } // elementDepthIsZeroHook():boolean 1261 1262 /** 1263 * Scan for root element hook. This method is a hook for 1264 * subclasses to add code that handles scanning for the root 1265 * element. When scanning a document fragment, there is no 1266 * "root" element. However, when scanning a full XML document, 1267 * the scanner must handle the root element specially. 1268 * 1269 * @return True if the caller should stop and return true which 1270 * allows the scanner to switch to a new scanning 1271 * driver. A return value of false indicates that 1272 * the content driver should continue as normal. 1273 */ 1274 protected boolean scanRootElementHook() 1275 throws IOException, XNIException { 1276 1277 if (scanStartElement()) { 1278 setScannerState(SCANNER_STATE_TRAILING_MISC); 1279 setDriver(fTrailingMiscDriver); 1280 return true; 1281 } 1282 return false; 1283 1284 } // scanRootElementHook():boolean 1285 1286 /** 1287 * End of file hook. This method is a hook for subclasses to 1288 * add code that handles the end of file. The end of file in 1289 * a document fragment is OK if the markup depth is zero. 1290 * However, when scanning a full XML document, an end of file 1291 * is always premature. 1292 */ 1293 protected void endOfFileHook(EOFException e) 1294 throws IOException, XNIException { 1295 1296 reportFatalError("PrematureEOF", null); 1297 // in case continue-after-fatal-error set, should not do this... 1298 //throw e; 1299 1300 } // endOfFileHook() 1301 1302 protected void resolveExternalSubsetAndRead() 1303 throws IOException, XNIException { 1304 1305 fDTDDescription.setValues(null, null, fEntityManager.getCurrentResourceIdentifier().getExpandedSystemId(), null); 1306 fDTDDescription.setRootName(fElementQName.rawname); 1307 XMLInputSource src = fExternalSubsetResolver.getExternalSubset(fDTDDescription); 1308 1309 if (src != null) { 1310 fDoctypeName = fElementQName.rawname; 1311 fDoctypePublicId = src.getPublicId(); 1312 fDoctypeSystemId = src.getSystemId(); 1313 // call document handler 1314 if (fDocumentHandler != null) { 1315 // This inserts a doctypeDecl event into the stream though no 1316 // DOCTYPE existed in the instance document. 1317 fDocumentHandler.doctypeDecl(fDoctypeName, fDoctypePublicId, fDoctypeSystemId, null); 1318 } 1319 try { 1320 fDTDScanner.setInputSource(src); 1321 while (fDTDScanner.scanDTDExternalSubset(true)); 1322 } finally { 1323 fEntityManager.setEntityHandler(XMLDocumentScannerImpl.this); 1324 } 1325 } 1326 } // resolveExternalSubsetAndRead() 1327 1328 1329 1330 } // class ContentDriver 1331 1332 /** 1333 * Driver to handle trailing miscellaneous section scanning. 1334 * 1335 * @author Andy Clark, IBM 1336 * @author Eric Ye, IBM 1337 */ 1338 protected final class TrailingMiscDriver 1339 implements Driver { 1340 1341 // 1342 // Driver methods 1343 // 1344 public int next() throws IOException, XNIException{ 1345 //this could for cases like <foo/> 1346 //look at scanRootElementHook 1347 if(fEmptyElement){ 1348 fEmptyElement = false; 1349 return XMLEvent.END_ELEMENT; 1350 } 1351 1352 try { 1353 if(fScannerState == SCANNER_STATE_TERMINATED){ 1354 return XMLEvent.END_DOCUMENT ;} 1355 do { 1356 switch (fScannerState) { 1357 case SCANNER_STATE_TRAILING_MISC: { 1358 1359 fEntityScanner.skipSpaces(); 1360 //we should have reached the end of the document in 1361 //most cases. 1362 if(fScannerState == SCANNER_STATE_TERMINATED ){ 1363 return XMLEvent.END_DOCUMENT ; 1364 } 1365 if (fEntityScanner.skipChar('<')) { 1366 setScannerState(SCANNER_STATE_START_OF_MARKUP); 1367 } else { 1368 setScannerState(SCANNER_STATE_CONTENT); 1369 } 1370 break; 1371 } 1372 case SCANNER_STATE_START_OF_MARKUP: { 1373 fMarkupDepth++; 1374 if (fEntityScanner.skipChar('?')) { 1375 setScannerState(SCANNER_STATE_PI); 1376 } else if (fEntityScanner.skipChar('!')) { 1377 setScannerState(SCANNER_STATE_COMMENT); 1378 } else if (fEntityScanner.skipChar('/')) { 1379 reportFatalError("MarkupNotRecognizedInMisc", 1380 null); 1381 } else if (XMLChar.isNameStart(fEntityScanner.peekChar())) { 1382 reportFatalError("MarkupNotRecognizedInMisc", 1383 null); 1384 scanStartElement(); 1385 setScannerState(SCANNER_STATE_CONTENT); 1386 } else { 1387 reportFatalError("MarkupNotRecognizedInMisc", 1388 null); 1389 } 1390 break; 1391 } 1392 } 1393 }while(fScannerState == SCANNER_STATE_START_OF_MARKUP || fScannerState == SCANNER_STATE_TRAILING_MISC); 1394 if(DEBUG_NEXT){ 1395 System.out.println("State set by deciding while loop [TrailingMiscellaneous] is = " + getScannerStateName(fScannerState)); 1396 } 1397 switch (fScannerState){ 1398 case SCANNER_STATE_PI: { 1399 fContentBuffer.clear(); 1400 scanPI(fContentBuffer); 1401 setScannerState(SCANNER_STATE_TRAILING_MISC); 1402 return XMLEvent.PROCESSING_INSTRUCTION ; 1403 } 1404 case SCANNER_STATE_COMMENT: { 1405 if (!fEntityScanner.skipString(COMMENTSTRING)) { 1406 reportFatalError("InvalidCommentStart", null); 1407 } 1408 scanComment(); 1409 setScannerState(SCANNER_STATE_TRAILING_MISC); 1410 return XMLEvent.COMMENT; 1411 } 1412 case SCANNER_STATE_CONTENT: { 1413 int ch = fEntityScanner.peekChar(); 1414 if (ch == -1) { 1415 setScannerState(SCANNER_STATE_TERMINATED); 1416 return XMLEvent.END_DOCUMENT ; 1417 } else{ 1418 reportFatalError("ContentIllegalInTrailingMisc", 1419 null); 1420 fEntityScanner.scanChar(); 1421 setScannerState(SCANNER_STATE_TRAILING_MISC); 1422 return XMLEvent.CHARACTERS; 1423 } 1424 1425 } 1426 case SCANNER_STATE_REFERENCE: { 1427 reportFatalError("ReferenceIllegalInTrailingMisc", 1428 null); 1429 setScannerState(SCANNER_STATE_TRAILING_MISC); 1430 return XMLEvent.ENTITY_REFERENCE ; 1431 } 1432 case SCANNER_STATE_TERMINATED: { 1433 //there can't be any element after SCANNER_STATE_TERMINATED or when the parser 1434 //has reached the end of document 1435 setScannerState(SCANNER_STATE_NO_SUCH_ELEMENT_EXCEPTION); 1436 //xxx what to do when the scanner has reached the terminating state. 1437 return XMLEvent.END_DOCUMENT ; 1438 } 1439 case SCANNER_STATE_NO_SUCH_ELEMENT_EXCEPTION:{ 1440 throw new java.util.NoSuchElementException("No more events to be parsed"); 1441 } 1442 default: throw new XNIException("Scanner State " + fScannerState + " not Recognized "); 1443 }//switch 1444 1445 } catch (EOFException e) { 1446 // NOTE: This is the only place we're allowed to reach 1447 // the real end of the document stream. Unless the 1448 // end of file was reached prematurely. 1449 if (fMarkupDepth != 0) { 1450 reportFatalError("PrematureEOF", null); 1451 return -1; 1452 //throw e; 1453 } 1454 //System.out.println("EOFException thrown") ; 1455 setScannerState(SCANNER_STATE_TERMINATED); 1456 } 1457 1458 return XMLEvent.END_DOCUMENT; 1459 1460 }//next 1461 1462 } // class TrailingMiscDriver 1463 1464 /** 1465 * Implements XMLBufferListener interface. 1466 */ 1467 1468 1469 /** 1470 * receives callbacks from {@link XMLEntityReader } when buffer 1471 * is being changed. 1472 * @param refreshPosition 1473 */ 1474 public void refresh(int refreshPosition){ 1475 super.refresh(refreshPosition); 1476 if(fReadingDTD){ 1477 Entity entity = fEntityScanner.getCurrentEntity(); 1478 if(entity instanceof Entity.ScannedEntity){ 1479 fEndPos=((Entity.ScannedEntity)entity).position; 1480 } 1481 fDTDDecl.append(((Entity.ScannedEntity)entity).ch,fStartPos , fEndPos-fStartPos); 1482 fStartPos = refreshPosition; 1483 } 1484 } 1485 1486 } // class XMLDocumentScannerImpl