KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > xerces > impl > XMLDocumentScannerImpl


1 /*
2  * Copyright 1999-2005 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.apache.xerces.impl;
18
19 import java.io.CharConversionException JavaDoc;
20 import java.io.EOFException JavaDoc;
21 import java.io.IOException JavaDoc;
22
23 import org.apache.xerces.impl.dtd.XMLDTDDescription;
24 import org.apache.xerces.impl.io.MalformedByteSequenceException;
25 import org.apache.xerces.impl.validation.ValidationManager;
26 import org.apache.xerces.util.NamespaceSupport;
27 import org.apache.xerces.util.XMLChar;
28 import org.apache.xerces.util.XMLStringBuffer;
29 import org.apache.xerces.xni.Augmentations;
30 import org.apache.xerces.xni.NamespaceContext;
31 import org.apache.xerces.xni.XMLResourceIdentifier;
32 import org.apache.xerces.xni.XMLString;
33 import org.apache.xerces.xni.XNIException;
34 import org.apache.xerces.xni.parser.XMLComponentManager;
35 import org.apache.xerces.xni.parser.XMLConfigurationException;
36 import org.apache.xerces.xni.parser.XMLDTDScanner;
37 import org.apache.xerces.xni.parser.XMLInputSource;
38
39 /**
40  * This class is responsible for scanning XML document structure
41  * and content. The scanner acts as the source for the document
42  * information which is communicated to the document handler.
43  * <p>
44  * This component requires the following features and properties from the
45  * component manager that uses it:
46  * <ul>
47  * <li>http://xml.org/sax/features/namespaces</li>
48  * <li>http://xml.org/sax/features/validation</li>
49  * <li>http://apache.org/xml/features/nonvalidating/load-external-dtd</li>
50  * <li>http://apache.org/xml/features/scanner/notify-char-refs</li>
51  * <li>http://apache.org/xml/features/scanner/notify-builtin-refs</li>
52  * <li>http://apache.org/xml/properties/internal/symbol-table</li>
53  * <li>http://apache.org/xml/properties/internal/error-reporter</li>
54  * <li>http://apache.org/xml/properties/internal/entity-manager</li>
55  * <li>http://apache.org/xml/properties/internal/dtd-scanner</li>
56  * </ul>
57  *
58  * @xerces.internal
59  *
60  * @author Glenn Marcy, IBM
61  * @author Andy Clark, IBM
62  * @author Arnaud Le Hors, IBM
63  * @author Eric Ye, IBM
64  *
65  * @version $Id: XMLDocumentScannerImpl.java,v 1.51 2005/02/24 19:03:49 mrglavas Exp $
66  */

67 public class XMLDocumentScannerImpl
68     extends XMLDocumentFragmentScannerImpl {
69
70     //
71
// Constants
72
//
73

74     // scanner states
75

76     /** Scanner state: XML declaration. */
77     protected static final int SCANNER_STATE_XML_DECL = 0;
78
79     /** Scanner state: prolog. */
80     protected static final int SCANNER_STATE_PROLOG = 5;
81
82     /** Scanner state: trailing misc. */
83     protected static final int SCANNER_STATE_TRAILING_MISC = 12;
84
85     /** Scanner state: DTD internal declarations. */
86     protected static final int SCANNER_STATE_DTD_INTERNAL_DECLS = 17;
87
88     /** Scanner state: open DTD external subset. */
89     protected static final int SCANNER_STATE_DTD_EXTERNAL = 18;
90
91     /** Scanner state: DTD external declarations. */
92     protected static final int SCANNER_STATE_DTD_EXTERNAL_DECLS = 19;
93
94     // feature identifiers
95

96     /** Feature identifier: load external DTD. */
97     protected static final String JavaDoc LOAD_EXTERNAL_DTD =
98         Constants.XERCES_FEATURE_PREFIX + Constants.LOAD_EXTERNAL_DTD_FEATURE;
99
100     /** Feature identifier: load external DTD. */
101     protected static final String JavaDoc DISALLOW_DOCTYPE_DECL_FEATURE =
102         Constants.XERCES_FEATURE_PREFIX + Constants.DISALLOW_DOCTYPE_DECL_FEATURE;
103
104     // property identifiers
105

106     /** Property identifier: DTD scanner. */
107     protected static final String JavaDoc DTD_SCANNER =
108         Constants.XERCES_PROPERTY_PREFIX + Constants.DTD_SCANNER_PROPERTY;
109
110     /** property identifier: ValidationManager */
111     protected static final String JavaDoc VALIDATION_MANAGER =
112         Constants.XERCES_PROPERTY_PREFIX + Constants.VALIDATION_MANAGER_PROPERTY;
113
114     /** property identifier: NamespaceContext */
115     protected static final String JavaDoc NAMESPACE_CONTEXT =
116         Constants.XERCES_PROPERTY_PREFIX + Constants.NAMESPACE_CONTEXT_PROPERTY;
117         
118
119
120     // recognized features and properties
121

122     /** Recognized features. */
123     private static final String JavaDoc[] RECOGNIZED_FEATURES = {
124         LOAD_EXTERNAL_DTD,
125         DISALLOW_DOCTYPE_DECL_FEATURE,
126     };
127
128     /** Feature defaults. */
129     private static final Boolean JavaDoc[] FEATURE_DEFAULTS = {
130         Boolean.TRUE,
131         Boolean.FALSE,
132     };
133
134     /** Recognized properties. */
135     private static final String JavaDoc[] RECOGNIZED_PROPERTIES = {
136         DTD_SCANNER,
137         VALIDATION_MANAGER,
138         NAMESPACE_CONTEXT,
139     };
140
141     /** Property defaults. */
142     private static final Object JavaDoc[] PROPERTY_DEFAULTS = {
143         null,
144         null,
145         null,
146     };
147
148     //
149
// Data
150
//
151

152     // properties
153

154     /** DTD scanner. */
155     protected XMLDTDScanner fDTDScanner;
156     /** Validation manager . */
157     protected ValidationManager fValidationManager;
158
159     // protected data
160

161     /** Scanning DTD. */
162     protected boolean fScanningDTD;
163
164     // other info
165

166     /** Doctype name. */
167     protected String JavaDoc fDoctypeName;
168
169     /** Doctype declaration public identifier. */
170     protected String JavaDoc fDoctypePublicId;
171
172     /** Doctype declaration system identifier. */
173     protected String JavaDoc fDoctypeSystemId;
174
175     /** Namespace support. */
176     protected NamespaceContext fNamespaceContext = new NamespaceSupport();
177
178     // features
179

180     /** Load external DTD. */
181     protected boolean fLoadExternalDTD = true;
182
183     /** Disallow doctype declaration. */
184     protected boolean fDisallowDoctype = false;
185
186     // state
187

188     /** Seen doctype declaration. */
189     protected boolean fSeenDoctypeDecl;
190
191     // dispatchers
192

193     /** XML declaration dispatcher. */
194     protected Dispatcher fXMLDeclDispatcher = new XMLDeclDispatcher();
195
196     /** Prolog dispatcher. */
197     protected Dispatcher fPrologDispatcher = new PrologDispatcher();
198
199     /** DTD dispatcher. */
200     protected Dispatcher fDTDDispatcher = new DTDDispatcher();
201
202     /** Trailing miscellaneous section dispatcher. */
203     protected Dispatcher fTrailingMiscDispatcher = new TrailingMiscDispatcher();
204
205     // temporary variables
206

207     /** Array of 3 strings. */
208     private final String JavaDoc[] fStrings = new String JavaDoc[3];
209
210     /** String. */
211     private final XMLString fString = new XMLString();
212
213     /** String buffer. */
214     private final XMLStringBuffer fStringBuffer = new XMLStringBuffer();
215     
216     /** External subset source. */
217     private XMLInputSource fExternalSubsetSource = null;
218     
219     /** A DTD Description. */
220     private final XMLDTDDescription fDTDDescription = new XMLDTDDescription(null, null, null, null, null);
221
222     //
223
// Constructors
224
//
225

226     /** Default constructor. */
227     public XMLDocumentScannerImpl() {} // <init>()
228

229     //
230
// XMLDocumentScanner methods
231
//
232

233     /**
234      * Sets the input source.
235      *
236      * @param inputSource The input source.
237      *
238      * @throws IOException Thrown on i/o error.
239      */

240     public void setInputSource(XMLInputSource inputSource) throws IOException JavaDoc {
241         fEntityManager.setEntityHandler(this);
242         fEntityManager.startDocumentEntity(inputSource);
243         //fDocumentSystemId = fEntityManager.expandSystemId(inputSource.getSystemId());
244
} // setInputSource(XMLInputSource)
245

246     //
247
// XMLComponent methods
248
//
249

250     /**
251      * Resets the component. The component can query the component manager
252      * about any features and properties that affect the operation of the
253      * component.
254      *
255      * @param componentManager The component manager.
256      *
257      * @throws SAXException Thrown by component on initialization error.
258      * For example, if a feature or property is
259      * required for the operation of the component, the
260      * component manager may throw a
261      * SAXNotRecognizedException or a
262      * SAXNotSupportedException.
263      */

264     public void reset(XMLComponentManager componentManager)
265         throws XMLConfigurationException {
266
267         super.reset(componentManager);
268
269         // other settings
270
fDoctypeName = null;
271         fDoctypePublicId = null;
272         fDoctypeSystemId = null;
273         fSeenDoctypeDecl = false;
274         fScanningDTD = false;
275         fExternalSubsetSource = null;
276
277         if (!fParserSettings) {
278             // parser settings have not been changed
279
fNamespaceContext.reset();
280             // setup dispatcher
281
setScannerState(SCANNER_STATE_XML_DECL);
282             setDispatcher(fXMLDeclDispatcher);
283             return;
284         }
285
286         // xerces features
287
try {
288             fLoadExternalDTD = componentManager.getFeature(LOAD_EXTERNAL_DTD);
289         }
290         catch (XMLConfigurationException e) {
291             fLoadExternalDTD = true;
292         }
293         try {
294             fDisallowDoctype = componentManager.getFeature(DISALLOW_DOCTYPE_DECL_FEATURE);
295         }
296         catch (XMLConfigurationException e) {
297             fDisallowDoctype = false;
298         }
299
300         // xerces properties
301
fDTDScanner = (XMLDTDScanner)componentManager.getProperty(DTD_SCANNER);
302         try {
303             fValidationManager = (ValidationManager)componentManager.getProperty(VALIDATION_MANAGER);
304         }
305         catch (XMLConfigurationException e) {
306             fValidationManager = null;
307         }
308
309         try {
310             fNamespaceContext = (NamespaceContext)componentManager.getProperty(NAMESPACE_CONTEXT);
311         }
312         catch (XMLConfigurationException e) { }
313         if (fNamespaceContext == null) {
314             fNamespaceContext = new NamespaceSupport();
315         }
316         fNamespaceContext.reset();
317         
318         // setup dispatcher
319
setScannerState(SCANNER_STATE_XML_DECL);
320         setDispatcher(fXMLDeclDispatcher);
321
322     } // reset(XMLComponentManager)
323

324     /**
325      * Returns a list of feature identifiers that are recognized by
326      * this component. This method may return null if no features
327      * are recognized by this component.
328      */

329     public String JavaDoc[] getRecognizedFeatures() {
330         String JavaDoc[] featureIds = super.getRecognizedFeatures();
331         int length = featureIds != null ? featureIds.length : 0;
332         String JavaDoc[] combinedFeatureIds = new String JavaDoc[length + RECOGNIZED_FEATURES.length];
333         if (featureIds != null) {
334             System.arraycopy(featureIds, 0, combinedFeatureIds, 0, featureIds.length);
335         }
336         System.arraycopy(RECOGNIZED_FEATURES, 0, combinedFeatureIds, length, RECOGNIZED_FEATURES.length);
337         return combinedFeatureIds;
338     } // getRecognizedFeatures():String[]
339

340     /**
341      * Sets the state of a feature. This method is called by the component
342      * manager any time after reset when a feature changes state.
343      * <p>
344      * <strong>Note:</strong> Components should silently ignore features
345      * that do not affect the operation of the component.
346      *
347      * @param featureId The feature identifier.
348      * @param state The state of the feature.
349      *
350      * @throws SAXNotRecognizedException The component should not throw
351      * this exception.
352      * @throws SAXNotSupportedException The component should not throw
353      * this exception.
354      */

355     public void setFeature(String JavaDoc featureId, boolean state)
356         throws XMLConfigurationException {
357
358         super.setFeature(featureId, state);
359
360         // Xerces properties
361
if (featureId.startsWith(Constants.XERCES_FEATURE_PREFIX)) {
362             final int suffixLength = featureId.length() - Constants.XERCES_FEATURE_PREFIX.length();
363             
364             if (suffixLength == Constants.LOAD_EXTERNAL_DTD_FEATURE.length() &&
365                 featureId.endsWith(Constants.LOAD_EXTERNAL_DTD_FEATURE)) {
366                 fLoadExternalDTD = state;
367                 return;
368             }
369             else if (suffixLength == Constants.DISALLOW_DOCTYPE_DECL_FEATURE.length() &&
370                 featureId.endsWith(Constants.DISALLOW_DOCTYPE_DECL_FEATURE)) {
371                 fDisallowDoctype = state;
372                 return;
373             }
374         }
375
376     } // setFeature(String,boolean)
377

378     /**
379      * Returns a list of property identifiers that are recognized by
380      * this component. This method may return null if no properties
381      * are recognized by this component.
382      */

383     public String JavaDoc[] getRecognizedProperties() {
384         String JavaDoc[] propertyIds = super.getRecognizedProperties();
385         int length = propertyIds != null ? propertyIds.length : 0;
386         String JavaDoc[] combinedPropertyIds = new String JavaDoc[length + RECOGNIZED_PROPERTIES.length];
387         if (propertyIds != null) {
388             System.arraycopy(propertyIds, 0, combinedPropertyIds, 0, propertyIds.length);
389         }
390         System.arraycopy(RECOGNIZED_PROPERTIES, 0, combinedPropertyIds, length, RECOGNIZED_PROPERTIES.length);
391         return combinedPropertyIds;
392     } // getRecognizedProperties():String[]
393

394     /**
395      * Sets the value of a property. This method is called by the component
396      * manager any time after reset when a property changes value.
397      * <p>
398      * <strong>Note:</strong> Components should silently ignore properties
399      * that do not affect the operation of the component.
400      *
401      * @param propertyId The property identifier.
402      * @param value The value of the property.
403      *
404      * @throws SAXNotRecognizedException The component should not throw
405      * this exception.
406      * @throws SAXNotSupportedException The component should not throw
407      * this exception.
408      */

409     public void setProperty(String JavaDoc propertyId, Object JavaDoc value)
410         throws XMLConfigurationException {
411
412         super.setProperty(propertyId, value);
413
414         // Xerces properties
415
if (propertyId.startsWith(Constants.XERCES_PROPERTY_PREFIX)) {
416             final int suffixLength = propertyId.length() - Constants.XERCES_PROPERTY_PREFIX.length();
417             
418             if (suffixLength == Constants.DTD_SCANNER_PROPERTY.length() &&
419                 propertyId.endsWith(Constants.DTD_SCANNER_PROPERTY)) {
420                 fDTDScanner = (XMLDTDScanner)value;
421             }
422             if (suffixLength == Constants.NAMESPACE_CONTEXT_PROPERTY.length() &&
423                 propertyId.endsWith(Constants.NAMESPACE_CONTEXT_PROPERTY)) {
424                 if (value != null) {
425                     fNamespaceContext = (NamespaceContext)value;
426                 }
427             }
428
429             return;
430         }
431
432     } // setProperty(String,Object)
433

434     /**
435      * Returns the default state for a feature, or null if this
436      * component does not want to report a default value for this
437      * feature.
438      *
439      * @param featureId The feature identifier.
440      *
441      * @since Xerces 2.2.0
442      */

443     public Boolean JavaDoc getFeatureDefault(String JavaDoc featureId) {
444
445         for (int i = 0; i < RECOGNIZED_FEATURES.length; i++) {
446             if (RECOGNIZED_FEATURES[i].equals(featureId)) {
447                 return FEATURE_DEFAULTS[i];
448             }
449         }
450         return super.getFeatureDefault(featureId);
451     } // getFeatureDefault(String):Boolean
452

453     /**
454      * Returns the default state for a property, or null if this
455      * component does not want to report a default value for this
456      * property.
457      *
458      * @param propertyId The property identifier.
459      *
460      * @since Xerces 2.2.0
461      */

462     public Object JavaDoc getPropertyDefault(String JavaDoc propertyId) {
463         for (int i = 0; i < RECOGNIZED_PROPERTIES.length; i++) {
464             if (RECOGNIZED_PROPERTIES[i].equals(propertyId)) {
465                 return PROPERTY_DEFAULTS[i];
466             }
467         }
468         return super.getPropertyDefault(propertyId);
469     } // getPropertyDefault(String):Object
470

471     //
472
// XMLEntityHandler methods
473
//
474

475     /**
476      * This method notifies of the start of an entity. The DTD has the
477      * pseudo-name of "[dtd]" parameter entity names start with '%'; and
478      * general entities are just specified by their name.
479      *
480      * @param name The name of the entity.
481      * @param identifier The resource identifier.
482      * @param encoding The auto-detected IANA encoding name of the entity
483      * stream. This value will be null in those situations
484      * where the entity encoding is not auto-detected (e.g.
485      * internal entities or a document entity that is
486      * parsed from a java.io.Reader).
487      *
488      * @throws XNIException Thrown by handler to signal an error.
489      */

490     public void startEntity(String JavaDoc name,
491                             XMLResourceIdentifier identifier,
492                             String JavaDoc encoding, Augmentations augs) throws XNIException {
493
494         super.startEntity(name, identifier, encoding, augs);
495
496         // prepare to look for a TextDecl if external general entity
497
if (!name.equals("[xml]") && fEntityScanner.isExternal()) {
498             setScannerState(SCANNER_STATE_TEXT_DECL);
499         }
500
501         // call handler
502
if (fDocumentHandler != null && name.equals("[xml]")) {
503             fDocumentHandler.startDocument(fEntityScanner, encoding, fNamespaceContext, null);
504         }
505
506     } // startEntity(String,identifier,String)
507

508     /**
509      * This method notifies the end of an entity. The DTD has the pseudo-name
510      * of "[dtd]" parameter entity names start with '%'; and general entities
511      * are just specified by their name.
512      *
513      * @param name The name of the entity.
514      *
515      * @throws XNIException Thrown by handler to signal an error.
516      */

517     public void endEntity(String JavaDoc name, Augmentations augs) throws XNIException {
518
519         super.endEntity(name, augs);
520
521         // call handler
522
if (fDocumentHandler != null && name.equals("[xml]")) {
523             fDocumentHandler.endDocument(null);
524         }
525
526     } // endEntity(String)
527

528     //
529
// Protected methods
530
//
531

532     // dispatcher factory methods
533

534     /** Creates a content dispatcher. */
535     protected Dispatcher createContentDispatcher() {
536         return new ContentDispatcher();
537     } // createContentDispatcher():Dispatcher
538

539     // scanning methods
540

541     /** Scans a doctype declaration. */
542     protected boolean scanDoctypeDecl() throws IOException JavaDoc, XNIException {
543
544         // spaces
545
if (!fEntityScanner.skipSpaces()) {
546             reportFatalError("MSG_SPACE_REQUIRED_BEFORE_ROOT_ELEMENT_TYPE_IN_DOCTYPEDECL",
547                              null);
548         }
549
550         // root element name
551
fDoctypeName = fEntityScanner.scanName();
552         if (fDoctypeName == null) {
553             reportFatalError("MSG_ROOT_ELEMENT_TYPE_REQUIRED", null);
554         }
555
556         // external id
557
if (fEntityScanner.skipSpaces()) {
558             scanExternalID(fStrings, false);
559             fDoctypeSystemId = fStrings[0];
560             fDoctypePublicId = fStrings[1];
561             fEntityScanner.skipSpaces();
562         }
563
564         fHasExternalDTD = fDoctypeSystemId != null;
565         
566         // Attempt to locate an external subset with an external subset resolver.
567
if (!fHasExternalDTD && fExternalSubsetResolver != null) {
568             fDTDDescription.setValues(null, null, fEntityManager.getCurrentResourceIdentifier().getExpandedSystemId(), null);
569             fDTDDescription.setRootName(fDoctypeName);
570             fExternalSubsetSource = fExternalSubsetResolver.getExternalSubset(fDTDDescription);
571             fHasExternalDTD = fExternalSubsetSource != null;
572         }
573
574         // call handler
575
if (fDocumentHandler != null) {
576             // NOTE: I don't like calling the doctypeDecl callback until
577
// end of the *full* doctype line (including internal
578
// subset) is parsed correctly but SAX2 requires that
579
// it knows the root element name and public and system
580
// identifier for the startDTD call. -Ac
581
if (fExternalSubsetSource == null) {
582                 fDocumentHandler.doctypeDecl(fDoctypeName, fDoctypePublicId, fDoctypeSystemId, null);
583             }
584             else {
585                 fDocumentHandler.doctypeDecl(fDoctypeName, fExternalSubsetSource.getPublicId(), fExternalSubsetSource.getSystemId(), null);
586             }
587         }
588
589         // is there an internal subset?
590
boolean internalSubset = true;
591         if (!fEntityScanner.skipChar('[')) {
592             internalSubset = false;
593             fEntityScanner.skipSpaces();
594             if (!fEntityScanner.skipChar('>')) {
595                 reportFatalError("DoctypedeclUnterminated", new Object JavaDoc[]{fDoctypeName});
596             }
597             fMarkupDepth--;
598         }
599
600         return internalSubset;
601
602     } // scanDoctypeDecl():boolean
603

604     //
605
// Private methods
606
//
607

608     /** Returns the scanner state name. */
609     protected String JavaDoc getScannerStateName(int state) {
610
611         switch (state) {
612             case SCANNER_STATE_XML_DECL: return "SCANNER_STATE_XML_DECL";
613             case SCANNER_STATE_PROLOG: return "SCANNER_STATE_PROLOG";
614             case SCANNER_STATE_TRAILING_MISC: return "SCANNER_STATE_TRAILING_MISC";
615             case SCANNER_STATE_DTD_INTERNAL_DECLS: return "SCANNER_STATE_DTD_INTERNAL_DECLS";
616             case SCANNER_STATE_DTD_EXTERNAL: return "SCANNER_STATE_DTD_EXTERNAL";
617             case SCANNER_STATE_DTD_EXTERNAL_DECLS: return "SCANNER_STATE_DTD_EXTERNAL_DECLS";
618         }
619         return super.getScannerStateName(state);
620
621     } // getScannerStateName(int):String
622

623     //
624
// Classes
625
//
626

627     /**
628      * Dispatcher to handle XMLDecl scanning.
629      *
630      * @author Andy Clark, IBM
631      */

632     protected final class XMLDeclDispatcher
633         implements Dispatcher {
634
635         //
636
// Dispatcher methods
637
//
638

639         /**
640          * Dispatch an XML "event".
641          *
642          * @param complete True if this dispatcher is intended to scan
643          * and dispatch as much as possible.
644          *
645          * @return True if there is more to dispatch either from this
646          * or a another dispatcher.
647          *
648          * @throws IOException Thrown on i/o error.
649          * @throws XNIException Thrown on parse error.
650          */

651         public boolean dispatch(boolean complete)
652             throws IOException JavaDoc, XNIException {
653
654             // next dispatcher is prolog regardless of whether there
655
// is an XMLDecl in this document
656
setScannerState(SCANNER_STATE_PROLOG);
657             setDispatcher(fPrologDispatcher);
658
659             // scan XMLDecl
660
try {
661                 if (fEntityScanner.skipString("<?xml")) {
662                     fMarkupDepth++;
663                     // NOTE: special case where document starts with a PI
664
// whose name starts with "xml" (e.g. "xmlfoo")
665
if (XMLChar.isName(fEntityScanner.peekChar())) {
666                         fStringBuffer.clear();
667                         fStringBuffer.append("xml");
668                         if (fNamespaces) {
669                             while (XMLChar.isNCName(fEntityScanner.peekChar())) {
670                                 fStringBuffer.append((char)fEntityScanner.scanChar());
671                             }
672                         }
673                         else {
674                             while (XMLChar.isName(fEntityScanner.peekChar())) {
675                                 fStringBuffer.append((char)fEntityScanner.scanChar());
676                             }
677                         }
678                         String JavaDoc target = fSymbolTable.addSymbol(fStringBuffer.ch, fStringBuffer.offset, fStringBuffer.length);
679                         scanPIData(target, fString);
680                     }
681
682                     // standard XML declaration
683
else {
684                         scanXMLDeclOrTextDecl(false);
685                     }
686                 }
687                 fEntityManager.fCurrentEntity.mayReadChunks = true;
688
689                 // if no XMLDecl, then scan piece of prolog
690
return true;
691             }
692             // encoding errors
693
catch (MalformedByteSequenceException e) {
694                 fErrorReporter.reportError(e.getDomain(), e.getKey(),
695                     e.getArguments(), XMLErrorReporter.SEVERITY_FATAL_ERROR);
696                 return false;
697             }
698             catch (CharConversionException JavaDoc e) {
699                 reportFatalError("CharConversionFailure", null);
700                 return false;
701             }
702             // premature end of file
703
catch (EOFException JavaDoc e) {
704                 reportFatalError("PrematureEOF", null);
705                 return false;
706                 //throw e;
707
}
708
709
710         } // dispatch(boolean):boolean
711

712     } // class XMLDeclDispatcher
713

714     /**
715      * Dispatcher to handle prolog scanning.
716      *
717      * @author Andy Clark, IBM
718      */

719     protected final class PrologDispatcher
720         implements Dispatcher {
721
722         //
723
// Dispatcher methods
724
//
725

726         /**
727          * Dispatch an XML "event".
728          *
729          * @param complete True if this dispatcher is intended to scan
730          * and dispatch as much as possible.
731          *
732          * @return True if there is more to dispatch either from this
733          * or a another dispatcher.
734          *
735          * @throws IOException Thrown on i/o error.
736          * @throws XNIException Thrown on parse error.
737          */

738         public boolean dispatch(boolean complete)
739             throws IOException JavaDoc, XNIException {
740
741             try {
742                 boolean again;
743                 do {
744                     again = false;
745                     switch (fScannerState) {
746                         case SCANNER_STATE_PROLOG: {
747                             fEntityScanner.skipSpaces();
748                             if (fEntityScanner.skipChar('<')) {
749                                 setScannerState(SCANNER_STATE_START_OF_MARKUP);
750                                 again = true;
751                             }
752                             else if (fEntityScanner.skipChar('&')) {
753                                 setScannerState(SCANNER_STATE_REFERENCE);
754                                 again = true;
755                             }
756                             else {
757                                 setScannerState(SCANNER_STATE_CONTENT);
758                                 again = true;
759                             }
760                             break;
761                         }
762                         case SCANNER_STATE_START_OF_MARKUP: {
763                             fMarkupDepth++;
764                             if (fEntityScanner.skipChar('!')) {
765                                 if (fEntityScanner.skipChar('-')) {
766                                     if (!fEntityScanner.skipChar('-')) {
767                                         reportFatalError("InvalidCommentStart",
768                                                          null);
769                                     }
770                                     setScannerState(SCANNER_STATE_COMMENT);
771                                     again = true;
772                                 }
773                                 else if (fEntityScanner.skipString("DOCTYPE")) {
774                                     setScannerState(SCANNER_STATE_DOCTYPE);
775                                     again = true;
776                                 }
777                                 else {
778                                     reportFatalError("MarkupNotRecognizedInProlog",
779                                                      null);
780                                 }
781                             }
782                             else if (isValidNameStartChar(fEntityScanner.peekChar())) {
783                                 setScannerState(SCANNER_STATE_ROOT_ELEMENT);
784                                 setDispatcher(fContentDispatcher);
785                                 return true;
786                             }
787                             else if (fEntityScanner.skipChar('?')) {
788                                 setScannerState(SCANNER_STATE_PI);
789                                 again = true;
790                             }
791                             else if (isValidNameStartHighSurrogate(fEntityScanner.peekChar())) {
792                                 setScannerState(SCANNER_STATE_ROOT_ELEMENT);
793                                 setDispatcher(fContentDispatcher);
794                                 return true;
795                             }
796                             else {
797                                 reportFatalError("MarkupNotRecognizedInProlog",
798                                                  null);
799                             }
800                             break;
801                         }
802                         case SCANNER_STATE_COMMENT: {
803                             scanComment();
804                             setScannerState(SCANNER_STATE_PROLOG);
805                             break;
806                         }
807                         case SCANNER_STATE_PI: {
808                             scanPI();
809                             setScannerState(SCANNER_STATE_PROLOG);
810                             break;
811                         }
812                         case SCANNER_STATE_DOCTYPE: {
813                             if (fDisallowDoctype) {
814                                 reportFatalError("DoctypeNotAllowed", null);
815                             }
816                             if (fSeenDoctypeDecl) {
817                                 reportFatalError("AlreadySeenDoctype", null);
818                             }
819                             fSeenDoctypeDecl = true;
820
821                  &