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