KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > enhydra > apache > xerces > framework > XMLDocumentScanner


1 /*
2  * The Apache Software License, Version 1.1
3  *
4  *
5  * Copyright (c) 1999,2000 The Apache Software Foundation. All rights
6  * reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Apache Software Foundation (http://www.apache.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Xerces" and "Apache Software Foundation" must
28  * not be used to endorse or promote products derived from this
29  * software without prior written permission. For written
30  * permission, please contact apache@apache.org.
31  *
32  * 5. Products derived from this software may not be called "Apache",
33  * nor may "Apache" appear in their name, without prior written
34  * permission of the Apache Software Foundation.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
40  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47  * SUCH DAMAGE.
48  * ====================================================================
49  *
50  * This software consists of voluntary contributions made by many
51  * individuals on behalf of the Apache Software Foundation and was
52  * originally based on software copyright (c) 1999, International
53  * Business Machines, Inc., http://www.apache.org. For more
54  * information on the Apache Software Foundation, please see
55  * <http://www.apache.org/>.
56  */

57
58 package org.enhydra.apache.xerces.framework;
59
60 import org.enhydra.apache.xerces.readers.DefaultEntityHandler;
61 import org.enhydra.apache.xerces.readers.XMLEntityHandler;
62 import org.enhydra.apache.xerces.utils.ChunkyCharArray;
63 import org.enhydra.apache.xerces.utils.QName;
64 import org.enhydra.apache.xerces.utils.StringPool;
65 import org.enhydra.apache.xerces.utils.XMLCharacterProperties;
66 import org.enhydra.apache.xerces.utils.XMLMessages;
67 import org.enhydra.apache.xerces.validators.common.GrammarResolver;
68
69 /**
70  * This class recognizes most of the grammer for an XML processor.
71  * Additional support is provided by the XMLEntityHandler, via the
72  * XMLEntityReader instances it creates, which are used to process
73  * simple constructs like string literals and character data between
74  * markup. The XMLDTDScanner class contains the remaining support
75  * for the grammer of DTD declarations. When a &lt;!DOCTYPE ...&gt; is
76  * found in the document, the scanDoctypeDecl method will then be
77  * called and the XMLDocumentScanner subclass is responsible for
78  * "connecting" that method to the corresponding method provided
79  * by the XMLDTDScanner class.
80  *
81  * @version $Id: XMLDocumentScanner.java,v 1.2 2005/01/26 08:28:44 jkjome Exp $
82  */

83 public final class XMLDocumentScanner {
84     //
85
// Constants
86
//
87

88     //
89
// These character arrays are used as parameters for calls to the
90
// XMLEntityHandler.EntityReader skippedString() method. Some have
91
// package access for use by the inner dispatcher classes.
92
//
93

94     //
95
// [19] CDStart ::= '<![CDATA['
96
//
97
static final char[] cdata_string = { '[','C','D','A','T','A','[' };
98     //
99
// [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'
100
// [77] TextDecl ::= '<?xml' VersionInfo? EncodingDecl S? '?>'
101
//
102
static final char[] xml_string = { 'x','m','l' };
103     //
104
// [24] VersionInfo ::= S 'version' Eq (' VersionNum ' | " VersionNum ")
105
//
106
private static final char[] version_string = { 'v','e','r','s','i','o','n' };
107     //
108
// [28] doctypedecl ::= '<!DOCTYPE' S Name (S ExternalID)? S?
109
// ('[' (markupdecl | PEReference | S)* ']' S?)? '>'
110
//
111
static final char[] doctype_string = { 'D','O','C','T','Y','P','E' };
112     //
113
// [32] SDDecl ::= S 'standalone' Eq (("'" ('yes' | 'no') "'")
114
// | ('"' ('yes' | 'no') '"'))
115
//
116
private static final char[] standalone_string = { 's','t','a','n','d','a','l','o','n','e' };
117     //
118
// [80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' | "'" EncName "'" )
119
//
120
private static final char[] encoding_string = { 'e','n','c','o','d','i','n','g' };
121
122     /*
123      * Return values for the EventHandler scanAttValue method.
124      */

125     public static final int
126         RESULT_SUCCESS = 0,
127         RESULT_FAILURE = -1,
128         RESULT_DUPLICATE_ATTR = -2;
129
130     /** Scanner states */
131     static final int
132         SCANNER_STATE_XML_DECL = 0,
133         SCANNER_STATE_START_OF_MARKUP = 1,
134         SCANNER_STATE_COMMENT = 2,
135         SCANNER_STATE_PI = 3,
136         SCANNER_STATE_DOCTYPE = 4,
137         SCANNER_STATE_PROLOG = 5,
138         SCANNER_STATE_ROOT_ELEMENT = 6,
139         SCANNER_STATE_CONTENT = 7,
140         SCANNER_STATE_REFERENCE = 8,
141         SCANNER_STATE_ATTRIBUTE_LIST = 9,
142         SCANNER_STATE_ATTRIBUTE_NAME = 10,
143         SCANNER_STATE_ATTRIBUTE_VALUE = 11,
144         SCANNER_STATE_TRAILING_MISC = 12,
145         SCANNER_STATE_END_OF_INPUT = 13,
146         SCANNER_STATE_TERMINATED = 14;
147
148     //
149
// Instance Variables
150
//
151
/***/
152     // NOTE: Used by old implementation of scanElementType method. -Ac
153
private StringPool.CharArrayRange fCurrentElementCharArrayRange = null;
154     /***/
155     int fAttrListHandle = -1;
156     XMLAttrList fAttrList = null;
157     GrammarResolver fGrammarResolver = null;
158     XMLDTDScanner fDTDScanner = null;
159     boolean fNamespacesEnabled = false;
160     boolean fValidationEnabled = false;
161     boolean fLoadExternalDTD = true;
162     QName fElementQName = new QName();
163     QName fAttributeQName = new QName();
164     QName fCurrentElementQName = new QName();
165     ScannerDispatcher fDispatcher = null;
166     EventHandler fEventHandler = null;
167     XMLDocumentHandler.DTDHandler fDTDHandler = null;
168     StringPool fStringPool = null;
169     XMLErrorReporter fErrorReporter = null;
170     XMLEntityHandler fEntityHandler = null;
171     XMLEntityHandler.EntityReader fEntityReader = null;
172     XMLEntityHandler.CharBuffer fLiteralData = null;
173     boolean fSeenRootElement = false;
174     boolean fSeenDoctypeDecl = false;
175     boolean fStandalone = false;
176     boolean fParseTextDecl = false;
177     boolean fScanningDTD = false;
178     int fScannerState = SCANNER_STATE_XML_DECL;
179     int fReaderId = -1;
180     int fAttValueReader = -1;
181     int fAttValueElementType = -1;
182     int fAttValueAttrName = -1;
183     int fAttValueOffset = -1;
184     int fAttValueMark = -1;
185     int fScannerMarkupDepth = 0;
186
187     //
188
// Interfaces
189
//
190

191     /**
192      * This interface must be implemented by the users of the XMLDocumentScanner class.
193      * These methods form the abstraction between the implementation semantics and the
194      * more generic task of scanning the XML non-DTD grammar.
195      */

196     public interface EventHandler {
197         /**
198          * Signal standalone = "yes"
199          *
200          * @exception java.lang.Exception
201          */

202         public void callStandaloneIsYes() throws Exception JavaDoc;
203
204         /**
205          * Signal the start of a document
206          *
207          * @exception java.lang.Exception
208          */

209         public void callStartDocument() throws Exception JavaDoc;
210         /**
211          * Signal the end of a document
212          *
213          * @exception java.lang.Exception
214          */

215         public void callEndDocument() throws Exception JavaDoc;
216         /**
217          * Signal the XML declaration of a document
218          *
219          * @param version the handle in the string pool for the version number
220          * @param encoding the handle in the string pool for the encoding
221          * @param standalong the handle in the string pool for the standalone value
222          * @exception java.lang.Exception
223          */

224         public void callXMLDecl(int version, int encoding, int standalone) throws Exception JavaDoc;
225         /**
226          * Signal the Text declaration of an external entity.
227          *
228          * @param version the handle in the string pool for the version number
229          * @param encoding the handle in the string pool for the encoding
230          * @exception java.lang.Exception
231          */

232         public void callTextDecl(int version, int encoding) throws Exception JavaDoc;
233         /**
234          * signal the scanning of a start element tag
235          *
236          * @param element Element name scanned.
237          * @exception java.lang.Exception
238          */

239         public void callStartElement(QName element) throws Exception JavaDoc;
240         /**
241          * Signal the scanning of an element name in a start element tag.
242          *
243          * @param element Element name scanned.
244          */

245         public void element(QName element) throws Exception JavaDoc;
246         /**
247          * Signal the scanning of an attribute associated to the previous
248          * start element tag.
249          *
250          * @param element Element name scanned.
251          * @param attrName Attribute name scanned.
252          * @param attrValue The string pool index of the attribute value.
253          */

254         public boolean attribute(QName element, QName attrName, int attrValue) throws Exception JavaDoc;
255         /**
256          * signal the scanning of an end element tag
257          *
258          * @param readerId the Id of the reader being used to scan the end tag.
259          * @exception java.lang.Exception
260          */

261         public void callEndElement(int readerId) throws Exception JavaDoc;
262         /**
263          * Signal the start of a CDATA section
264          * @exception java.lang.Exception
265          */

266         public void callStartCDATA() throws Exception JavaDoc;
267         /**
268          * Signal the end of a CDATA section
269          * @exception java.lang.Exception
270          */

271         public void callEndCDATA() throws Exception JavaDoc;
272         /**
273          * Report the scanning of character data
274          *
275          * @param ch the handle in the string pool of the character data that was scanned
276          * @exception java.lang.Exception
277          */

278         public void callCharacters(int ch) throws Exception JavaDoc;
279         /**
280          * Report the scanning of a processing instruction
281          *
282          * @param piTarget the handle in the string pool of the processing instruction targe
283          * @param piData the handle in the string pool of the processing instruction data
284          * @exception java.lang.Exception
285          */

286         public void callProcessingInstruction(int piTarget, int piData) throws Exception JavaDoc;
287         /**
288          * Report the scanning of a comment
289          *
290          * @param data the handle in the string pool of the comment text
291          * @exception java.lang.Exception
292          */

293         public void callComment(int data) throws Exception JavaDoc;
294     }
295
296     /**
297      * Constructor
298      */

299     public XMLDocumentScanner(StringPool stringPool,
300                               XMLErrorReporter errorReporter,
301                               XMLEntityHandler entityHandler,
302                               XMLEntityHandler.CharBuffer literalData) {
303         fStringPool = stringPool;
304         fErrorReporter = errorReporter;
305         fEntityHandler = entityHandler;
306         fLiteralData = literalData;
307         fDispatcher = new XMLDeclDispatcher();
308         fAttrList = new XMLAttrList(fStringPool);
309     }
310
311     /**
312      * Set the event handler
313      *
314      * @param eventHandler The place to send our callbacks.
315      */

316     public void setEventHandler(XMLDocumentScanner.EventHandler eventHandler) {
317         fEventHandler = eventHandler;
318     }
319
320     /** Set the DTD handler. */
321     public void setDTDHandler(XMLDocumentHandler.DTDHandler dtdHandler) {
322         fDTDHandler = dtdHandler;
323     }
324
325     /** Sets the grammar resolver. */
326     public void setGrammarResolver(GrammarResolver resolver) {
327         fGrammarResolver = resolver;
328     }
329
330     /**
331      * reset the parser so that the instance can be reused
332      *
333      * @param stringPool the string pool instance to be used by the reset parser
334      */

335     public void reset(StringPool stringPool, XMLEntityHandler.CharBuffer literalData) {
336         fStringPool = stringPool;
337         fLiteralData = literalData;
338         fParseTextDecl = false;
339         fSeenRootElement = false;
340         fSeenDoctypeDecl = false;
341         fStandalone = false;
342         fScanningDTD = false;
343         fDispatcher = new XMLDeclDispatcher();
344         fScannerState = SCANNER_STATE_XML_DECL;
345         fScannerMarkupDepth = 0;
346         fAttrList = new XMLAttrList(fStringPool);
347     }
348
349     //
350
// From the standard:
351
//
352
// [1] document ::= prolog element Misc*
353
//
354
// [22] prolog ::= XMLDecl? Misc* (doctypedecl Misc*)?
355
// [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'
356
// [24] VersionInfo ::= S 'version' Eq (' VersionNum ' | " VersionNum ")
357
//
358
// The beginning of XMLDecl simplifies to:
359
// '<?xml' S ...
360
//
361
// [27] Misc ::= Comment | PI | S
362
// [15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
363
// [16] PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'
364
// [17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l'))
365
//
366
// [28] doctypedecl ::= '<!DOCTYPE' S Name (S ExternalID)? S?
367
// ('[' (markupdecl | PEReference | S)* ']' S?)? '>'
368
//
369
/**
370      * Entry point for parsing
371      *
372      * @param doItAll if true the entire document is parsed otherwise just
373      * the next segment of the document is parsed
374      */

375     public boolean parseSome(boolean doItAll) throws Exception JavaDoc
376     {
377         do {
378             if (!fDispatcher.dispatch(doItAll))
379                 return false;
380         } while (doItAll);
381         return true;
382     }
383
384     /**
385      * Change readers
386      *
387      * @param nextReader the new reader that the scanner will use
388      * @param nextReaderId id of the reader to change to
389      * @exception throws java.lang.Exception
390      */

391     public void readerChange(XMLEntityHandler.EntityReader nextReader, int nextReaderId) throws Exception JavaDoc {
392         fEntityReader = nextReader;
393         fReaderId = nextReaderId;
394         if (fScannerState == SCANNER_STATE_ATTRIBUTE_VALUE) {
395             fAttValueOffset = fEntityReader.currentOffset();
396             fAttValueMark = fAttValueOffset;
397         }
398
399         //also propagate the change to DTDScanner if there is one
400
if (fDTDScanner != null && fScanningDTD)
401             fDTDScanner.readerChange(nextReader, nextReaderId);
402     }
403
404     /**
405      * Handle the end of input
406      *
407      * @param entityName the handle in the string pool of the name of the entity which has reached end of input
408      * @param moreToFollow if true, there is still input left to process in other readers
409      * @exception java.lang.Exception
410      */

411     public void endOfInput(int entityName, boolean moreToFollow) throws Exception JavaDoc {
412         if (fDTDScanner != null && fScanningDTD){
413             fDTDScanner.endOfInput(entityName, moreToFollow);
414         }
415         fDispatcher.endOfInput(entityName, moreToFollow);
416     }
417
418     /**
419      * Tell if scanner has reached end of input
420      * @return true if scanner has reached end of input.
421      */

422     public boolean atEndOfInput() {
423         return fScannerState == SCANNER_STATE_END_OF_INPUT;
424     }
425
426     //
427
// [10] AttValue ::= '"' ([^<&"] | Reference)* '"' | "'" ([^<&'] | Reference)* "'"
428
//
429
/**
430      * Scan an attribute value
431      *
432      * @param elementType handle to the element whose attribute value is being scanned
433      * @param attrName handle in the string pool of the name of attribute being scanned
434      * @param asSymbol controls whether the value is a string (duplicates allowed) or a symbol (duplicates not allowed)
435      * @return handle in the string pool of the scanned value
436      * @exception java.lang.Exception
437      */

438     public int scanAttValue(QName element, QName attribute, boolean asSymbol) throws Exception JavaDoc {
439         boolean single;
440         if (!(single = fEntityReader.lookingAtChar('\'', true)) && !fEntityReader.lookingAtChar('\"', true)) {
441             reportFatalXMLError(XMLMessages.MSG_QUOTE_REQUIRED_IN_ATTVALUE,
442                                 XMLMessages.P10_QUOTE_REQUIRED,
443                                 element.rawname,
444                                 attribute.rawname);
445             return -1;
446         }
447         char qchar = single ? '\'' : '\"';
448         fAttValueMark = fEntityReader.currentOffset();
449         int attValue = fEntityReader.scanAttValue(qchar, asSymbol);
450         if (attValue >= 0)
451             return attValue;
452         int previousState = setScannerState(SCANNER_STATE_ATTRIBUTE_VALUE);
453         fAttValueReader = fReaderId;
454         // REVISIT: What should this be?
455
fAttValueElementType = element.rawname;
456         // REVISIT: What should this be?
457
fAttValueAttrName = attribute.rawname;
458         fAttValueOffset = fEntityReader.currentOffset();
459         int dataOffset = fLiteralData.length();
460         if (fAttValueOffset - fAttValueMark > 0)
461             fEntityReader.append(fLiteralData, fAttValueMark, fAttValueOffset - fAttValueMark);
462         fAttValueMark = fAttValueOffset;
463         boolean setMark = false;
464         boolean skippedCR;
465         while (true) {
466             if (fEntityReader.lookingAtChar(qchar, true)) {
467                 if (fReaderId == fAttValueReader)
468                     break;
469             } else if (fEntityReader.lookingAtChar(' ', true)) {
470                 //
471
// no action required
472
//
473
} else if ((skippedCR = fEntityReader.lookingAtChar((char)0x0D, true)) || fEntityReader.lookingAtSpace(true)) {
474                 if (fAttValueOffset - fAttValueMark > 0)
475                     fEntityReader.append(fLiteralData, fAttValueMark, fAttValueOffset - fAttValueMark);
476                 setMark = true;
477                 fLiteralData.append(' ');
478                 if (skippedCR) {
479                     //
480
// REVISIT - HACK !!! code changed to pass incorrect OASIS test 'valid-sa-110'
481
// Uncomment the next line to conform to the spec...
482
//
483
//fEntityReader.lookingAtChar((char)0x0A, true);
484
}
485             } else if (fEntityReader.lookingAtChar('&', true)) {
486                 if (fAttValueOffset - fAttValueMark > 0)
487                     fEntityReader.append(fLiteralData, fAttValueMark, fAttValueOffset - fAttValueMark);
488                 setMark = true;
489                 //
490
// Check for character reference first.
491
//
492
if (fEntityReader.lookingAtChar('#', true)) {
493                     int ch = scanCharRef();
494                     if (ch != -1) {
495                         if (ch < 0x10000)
496                             fLiteralData.append((char)ch);
497                         else {
498                             fLiteralData.append((char)(((ch-0x00010000)>>10)+0xd800));
499                             fLiteralData.append((char)(((ch-0x00010000)&0x3ff)+0xdc00));
500                         }
501                     }
502                 } else {
503                     //
504
// Entity reference
505
//
506
int nameOffset = fEntityReader.currentOffset();
507                     fEntityReader.skipPastName(';');
508                     int nameLength = fEntityReader.currentOffset() - nameOffset;
509                     if (nameLength == 0) {
510                         reportFatalXMLError(XMLMessages.MSG_NAME_REQUIRED_IN_REFERENCE,
511                                             XMLMessages.P68_NAME_REQUIRED);
512                     } else if (!fEntityReader.lookingAtChar(';', true)) {
513                         reportFatalXMLError(XMLMessages.MSG_SEMICOLON_REQUIRED_IN_REFERENCE,
514                                             XMLMessages.P68_SEMICOLON_REQUIRED,
515                                             fEntityReader.addString(nameOffset, nameLength));
516                     } else {
517                         int entityName = fEntityReader.addSymbol(nameOffset, nameLength);
518                         fEntityHandler.startReadingFromEntity(entityName, fScannerMarkupDepth, XMLEntityHandler.ENTITYREF_IN_ATTVALUE);
519                     }
520                 }
521             } else if (fEntityReader.lookingAtChar('<', true)) {
522                 if (fAttValueOffset - fAttValueMark > 0)
523                     fEntityReader.append(fLiteralData, fAttValueMark, fAttValueOffset - fAttValueMark);
524                 setMark = true;
525                 reportFatalXMLError(XMLMessages.MSG_LESSTHAN_IN_ATTVALUE,
526                                     XMLMessages.WFC_NO_LESSTHAN_IN_ATTVALUE,
527                                     element.rawname,
528                                     attribute.rawname);
529             } else if (!fEntityReader.lookingAtValidChar(true)) {
530                 if (fAttValueOffset - fAttValueMark > 0)
531                     fEntityReader.append(fLiteralData, fAttValueMark, fAttValueOffset - fAttValueMark);
532                 setMark = true;
533                 int invChar = fEntityReader.scanInvalidChar();
534                 if (fScannerState == SCANNER_STATE_END_OF_INPUT)
535                     return -1;
536                 if (invChar >= 0) {
537                     reportFatalXMLError(XMLMessages.MSG_INVALID_CHAR_IN_ATTVALUE,
538                                         XMLMessages.P10_INVALID_CHARACTER,
539                                         fStringPool.toString(element.rawname),
540                                         fStringPool.toString(attribute.rawname),
541                                         Integer.toHexString(invChar));
542                 }
543             }
544             fAttValueOffset = fEntityReader.currentOffset();
545             if (setMark) {
546                 fAttValueMark = fAttValueOffset;
547                 setMark = false;
548             }
549         }
550         restoreScannerState(previousState);
551         int dataLength = fLiteralData.length() - dataOffset;
552         if (dataLength == 0) {
553             return fEntityReader.addString(fAttValueMark, fAttValueOffset - fAttValueMark);
554         }
555         if (fAttValueOffset - fAttValueMark > 0) {
556             fEntityReader.append(fLiteralData, fAttValueMark, fAttValueOffset - fAttValueMark);
557             dataLength = fLiteralData.length() - dataOffset;
558         }
559         int value = fLiteralData.addString(dataOffset, dataLength);
560         return value;
561     }
562
563     //
564
//
565
//
566
void reportFatalXMLError(int majorCode, int minorCode) throws Exception JavaDoc {
567         fErrorReporter.reportError(fErrorReporter.getLocator(),
568                                    XMLMessages.XML_DOMAIN,
569                                    majorCode,
570                                    minorCode,
571                                    null,
572                                    XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
573     }
574     void reportFatalXMLError(int majorCode, int minorCode, int stringIndex1) throws Exception JavaDoc {
575         Object JavaDoc[] args = { fStringPool.toString(stringIndex1) };
576         fErrorReporter.reportError(fErrorReporter.getLocator(),
577                                    XMLMessages.XML_DOMAIN,
578                                    majorCode,
579                                    minorCode,
580                                    args,
581                                    XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
582     }
583     void reportFatalXMLError(int majorCode, int minorCode, String JavaDoc string1) throws Exception JavaDoc {
584         Object JavaDoc[] args = { string1 };
585         fErrorReporter.reportError(fErrorReporter.getLocator(),
586                                    XMLMessages.XML_DOMAIN,
587                                    majorCode,
588                                    minorCode,
589                                    args,
590                                    XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
591     }
592     void reportFatalXMLError(int majorCode, int minorCode, int stringIndex1, int stringIndex2) throws Exception JavaDoc {
593         Object JavaDoc[] args = { fStringPool.toString(stringIndex1),
594                           fStringPool.toString(stringIndex2) };
595         fErrorReporter.reportError(fErrorReporter.getLocator(),
596                                    XMLMessages.XML_DOMAIN,
597                                    majorCode,
598                                    minorCode,
599                                    args,
600                                    XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
601     }
602     void reportFatalXMLError(int majorCode, int minorCode, String JavaDoc string1, String JavaDoc string2) throws Exception JavaDoc {
603         Object JavaDoc[] args = { string1, string2 };
604         fErrorReporter.reportError(fErrorReporter.getLocator(),
605                                    XMLMessages.XML_DOMAIN,
606                                    majorCode,
607                                    minorCode,
608                                    args,
609                                    XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
610     }
611     void reportFatalXMLError(int majorCode, int minorCode, String JavaDoc string1, String JavaDoc string2, String JavaDoc string3) throws Exception JavaDoc {
612         Object JavaDoc[] args = { string1, string2, string3 };
613         fErrorReporter.reportError(fErrorReporter.getLocator(),
614                                    XMLMessages.XML_DOMAIN,
615                                    majorCode,
616                                    minorCode,
617                                    args,
618                                    XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
619     }
620     void abortMarkup(int majorCode, int minorCode) throws Exception JavaDoc {
621         reportFatalXMLError(majorCode, minorCode);
622         skipPastEndOfCurrentMarkup();
623     }
624     void abortMarkup(int majorCode, int minorCode, int stringIndex1) throws Exception JavaDoc {
625         reportFatalXMLError(majorCode, minorCode, stringIndex1);
626         skipPastEndOfCurrentMarkup();
627     }
628     void abortMarkup(int majorCode, int minorCode, String JavaDoc string1) throws Exception JavaDoc {
629         reportFatalXMLError(majorCode, minorCode, string1);
630         skipPastEndOfCurrentMarkup();
631     }
632     void abortMarkup(int majorCode, int minorCode, int stringIndex1, int stringIndex2) throws Exception JavaDoc {
633         reportFatalXMLError(majorCode, minorCode, stringIndex1, stringIndex2);
634         skipPastEndOfCurrentMarkup();
635     }
636     void skipPastEndOfCurrentMarkup() throws Exception JavaDoc {
637         fEntityReader.skipToChar('>');
638         if (fEntityReader.lookingAtChar('>', true))
639             fScannerMarkupDepth--;
640     }
641     //
642
//
643
//
644
int setScannerState(int state) {
645         int oldState = fScannerState;
646         fScannerState = state;
647         return oldState;
648     }
649     void restoreScannerState(int state) {
650         if (fScannerState != SCANNER_STATE_END_OF_INPUT)
651             fScannerState = state;
652     }
653     //
654
//
655
//
656
/**
657      * The main loop of the scanner is implemented by calling the dispatch method
658      * of ScannerDispatcher with a flag which tells the dispatcher whether to continue
659      * or return. The scanner logic is split up into dispatchers for various syntatic
660      * components of XML. //REVISIT more rationale needed
661      */

662     interface ScannerDispatcher {
663         /**
664          * scan an XML syntactic component
665          *
666          * @param keepgoing if true continue on to the next dispatcher, otherwise return
667          * @return true if scanning was successful //REVISIT - does it ever return false or does it just throw?
668          * @exception java.lang.Exception
669          */

670         boolean dispatch(boolean keepgoing) throws Exception JavaDoc;
671         /**
672          * endOfInput encapsulates the end of entity handling for each dispatcher
673          *
674          * @param entityName StringPool handle of the entity that has reached the end
675          * @param moreToFollow true if there is more input to be read
676          * @exception
677          */

678         void endOfInput(int entityName, boolean moreToFollow) throws Exception JavaDoc;
679     }
680     final class XMLDeclDispatcher implements ScannerDispatcher {
681         public boolean dispatch(boolean keepgoing) throws Exception JavaDoc {
682             fEventHandler.callStartDocument();
683             if (fEntityReader.lookingAtChar('<', true)) {
684                 fScannerMarkupDepth++;
685                 setScannerState(SCANNER_STATE_START_OF_MARKUP);
686                 if (fEntityReader.lookingAtChar('?', true)) {
687                     int piTarget = fEntityReader.scanName(' ');
688                     if (piTarget == -1) {
689                         abortMarkup(XMLMessages.MSG_PITARGET_REQUIRED,
690                                     XMLMessages.P16_PITARGET_REQUIRED);
691                     } else if ("xml".equals(fStringPool.toString(piTarget))) {
692                         if (fEntityReader.lookingAtSpace(true)) { // an XMLDecl looks like a PI with the target 'xml'
693
scanXMLDeclOrTextDecl(false);
694                         } else { // a PI target matching 'xml'
695
abortMarkup(XMLMessages.MSG_RESERVED_PITARGET,
696                                         XMLMessages.P17_RESERVED_PITARGET);
697                         }
698                     } else { // PI
699
scanPI(piTarget);
700                     }
701                     fDispatcher = new PrologDispatcher();
702                     restoreScannerState(SCANNER_STATE_PROLOG);
703                     return true;
704                 }
705                 if (fEntityReader.lookingAtChar('!', true)) {
706                     if (fEntityReader.lookingAtChar('-', true)) { // comment ?
707
if (fEntityReader.lookingAtChar('-', true)) {
708                             scanComment(); // scan through the closing '-->'
709
} else {
710                             abortMarkup(XMLMessages.MSG_MARKUP_NOT_RECOGNIZED_IN_PROLOG,
711                                         XMLMessages.P22_NOT_RECOGNIZED);
712                         }
713                     } else {
714                         if (fEntityReader.skippedString(doctype_string)) {
715                             setScannerState(SCANNER_STATE_DOCTYPE);
716                             fSeenDoctypeDecl = true;
717                             scanDoctypeDecl(fStandalone); // scan through the closing '>'
718
fScannerMarkupDepth--;
719                             fDispatcher = new PrologDispatcher();
720                             restoreScannerState(SCANNER_STATE_PROLOG);
721                             return true;
722                         } else {
723                             abortMarkup(XMLMessages.MSG_MARKUP_NOT_RECOGNIZED_IN_PROLOG,
724                                         XMLMessages.P22_NOT_RECOGNIZED);
725                         }
726                     }
727                 } else {
728                     fDispatcher = new ContentDispatcher();
729                     restoreScannerState(SCANNER_STATE_ROOT_ELEMENT);
730                     return true;
731                 }
732             } else {
733                 if (fEntityReader.lookingAtSpace(true)) {
734                     fEntityReader.skipPastSpaces();
735                 } else if (!fEntityReader.lookingAtValidChar(false)) {
736                     int invChar = fEntityReader.scanInvalidChar();
737                     if (fScannerState != SCANNER_STATE_END_OF_INPUT) {
738                         if (invChar >= 0) {
739                             String JavaDoc arg = Integer.toHexString(invChar);
740                             reportFatalXMLError(XMLMessages.MSG_INVALID_CHAR_IN_PROLOG,
741                                                 XMLMessages.P22_INVALID_CHARACTER,
742                                                 arg);
743                         }
744                     } else {
745                         fDispatcher = new EndOfInputDispatcher();
746                         setScannerState(SCANNER_STATE_END_OF_INPUT);
747                         return true;
748                     }
749                 } else {
750                     reportFatalXMLError(XMLMessages.MSG_MARKUP_NOT_RECOGNIZED_IN_PROLOG,
751                                         XMLMessages.P22_NOT_RECOGNIZED);
752                     fEntityReader.lookingAtValidChar(true);
753                 }
754             }
755             fDispatcher = new PrologDispatcher();
756             restoreScannerState(SCANNER_STATE_PROLOG);
757             return true;
758         }
759         public void endOfInput(int entityName, boolean moreToFollow) throws Exception JavaDoc {
760             switch (fScannerState) {
761             case SCANNER_STATE_XML_DECL:
762             case SCANNER_STATE_START_OF_MARKUP:
763             case SCANNER_STATE_DOCTYPE:
764                 break;
765             case SCANNER_STATE_COMMENT:
766                 if (!moreToFollow) {
767                     reportFatalXMLError(XMLMessages.MSG_COMMENT_UNTERMINATED,
768                                         XMLMessages.P15_UNTERMINATED);
769                 } else {
770                     reportFatalXMLError(XMLMessages.MSG_COMMENT_NOT_IN_ONE_ENTITY,
771                                         XMLMessages.P78_NOT_WELLFORMED);
772                 }
773                 break;
774             case SCANNER_STATE_PI:
775                 if (!moreToFollow) {
776                     reportFatalXMLError(XMLMessages.MSG_PI_UNTERMINATED,
777                                         XMLMessages.P16_UNTERMINATED);
778                 } else {
779                     reportFatalXMLError(XMLMessages.MSG_PI_NOT_IN_ONE_ENTITY,
780                                         XMLMessages.P78_NOT_WELLFORMED);
781                 }
782                 break;
783             default:
784                 throw new RuntimeException JavaDoc("FWK001 1] ScannerState="+fScannerState+"\n" + "1\t"+fScannerState);
785             }
786             if (!moreToFollow) {
787                 reportFatalXMLError(XMLMessages.MSG_ROOT_ELEMENT_REQUIRED,
788                                     XMLMessages.P1_ELEMENT_REQUIRED);
789                 fDispatcher = new EndOfInputDispatcher();
790                 setScannerState(SCANNER_STATE_END_OF_INPUT);
791             }
792         }
793     }
794     final class PrologDispatcher implements ScannerDispatcher {
795         public boolean dispatch(boolean keepgoing) throws Exception JavaDoc {
796             do {
797                 if (fEntityReader.lookingAtChar('<', true)) {
798                     fScannerMarkupDepth++;
799                     setScannerState(SCANNER_STATE_START_OF_MARKUP);
800                     if (fEntityReader.lookingAtChar('?', true)) {
801                         int piTarget = fEntityReader.scanName(' ');
802                         if (piTarget == -1) {
803                             abortMarkup(XMLMessages.MSG_PITARGET_REQUIRED,
804                                         XMLMessages.P16_PITARGET_REQUIRED);
805                         } else if ("xml".equals(fStringPool.toString(piTarget))) {
806                             if (fEntityReader.lookingAtSpace(true)) { // an XMLDecl looks like a PI with the target 'xml'
807
abortMarkup(XMLMessages.MSG_XMLDECL_MUST_BE_FIRST,
808                                             XMLMessages.P22_XMLDECL_MUST_BE_FIRST);
809                             } else { // a PI target matching 'xml'
810
abortMarkup(XMLMessages.MSG_RESERVED_PITARGET,
811                                             XMLMessages.P17_RESERVED_PITARGET);
812                             }
813                         } else { // PI
814
scanPI(piTarget);
815                         }
816                     } else if (fEntityReader.lookingAtChar('!', true)) {
817                         if (fEntityReader.lookingAtChar('-', true)) { // comment ?
818
if (fEntityReader.lookingAtChar('-', true)) {
819                                 scanComment(); // scan through the closing '-->'
820
} else {
821                                 abortMarkup(XMLMessages.MSG_MARKUP_NOT_RECOGNIZED_IN_PROLOG,
822                                             XMLMessages.P22_NOT_RECOGNIZED);
823                             }
824                         } else {
825                             if (!fSeenDoctypeDecl && fEntityReader.skippedString(doctype_string)) {
826                                 setScannerState(SCANNER_STATE_DOCTYPE);
827                                 fSeenDoctypeDecl = true;
828                                 scanDoctypeDecl(fStandalone); // scan through the closing '>'
829
fScannerMarkupDepth--;
830                             } else {
831                                 abortMarkup(XMLMessages.MSG_MARKUP_NOT_RECOGNIZED_IN_PROLOG,
832                                             XMLMessages.P22_NOT_RECOGNIZED);
833                             }
834                         }
835                     } else {
836                         fDispatcher = new ContentDispatcher();
837                         restoreScannerState(SCANNER_STATE_ROOT_ELEMENT);
838                         return true;
839                     }
840                     restoreScannerState(SCANNER_STATE_PROLOG);
841                 } else if (fEntityReader.lookingAtSpace(true)) {
842                     fEntityReader.skipPastSpaces();
843                 } else if (!fEntityReader.lookingAtValidChar(false)) {
844                     int invChar = fEntityReader.scanInvalidChar();
845                     if (fScannerState != SCANNER_STATE_END_OF_INPUT) {
846                         if (invChar >= 0) {
847                             String JavaDoc arg = Integer.toHexString(invChar);
848                             reportFatalXMLError(XMLMessages.MSG_INVALID_CHAR_IN_PROLOG,
849                                                 XMLMessages.P22_INVALID_CHARACTER,
850                                                 arg);
851                         }
852                     }
853                 } else {
854                     reportFatalXMLError(XMLMessages.MSG_MARKUP_NOT_RECOGNIZED_IN_PROLOG,
855                                         XMLMessages.P22_NOT_RECOGNIZED);
856                     fEntityReader.lookingAtValidChar(true);
857                 }
858             } while (fScannerState != SCANNER_STATE_END_OF_INPUT && keepgoing);
859             return true;
860         }
861         public void endOfInput(int entityName, boolean moreToFollow) throws Exception JavaDoc {
862             switch (fScannerState) {
863             case SCANNER_STATE_PROLOG:
864             case SCANNER_STATE_START_OF_MARKUP:
865             case SCANNER_STATE_DOCTYPE:
866                 break;
867             case SCANNER_STATE_COMMENT:
868                 if (!moreToFollow) {
869                     reportFatalXMLError(XMLMessages.MSG_COMMENT_UNTERMINATED,
870                                         XMLMessages.P15_UNTERMINATED);
871                 } else {
872                     reportFatalXMLError(XMLMessages.MSG_COMMENT_NOT_IN_ONE_ENTITY,
873                                         XMLMessages.P78_NOT_WELLFORMED);
874                 }
875                 break;
876             case SCANNER_STATE_PI:
877                 if (!moreToFollow) {
878                     reportFatalXMLError(XMLMessages.MSG_PI_UNTERMINATED,
879                                         XMLMessages.P16_UNTERMINATED);
880                 } else {
881                     reportFatalXMLError(XMLMessages.MSG_PI_NOT_IN_ONE_ENTITY,
882                                         XMLMessages.P78_NOT_WELLFORMED);
883                 }
884                 break;
885             default:
886                 throw new RuntimeException JavaDoc("FWK001 2] ScannerState="+fScannerState+"\n" + "2\t"+fScannerState);
887             }
888             if (!moreToFollow) {
889                 reportFatalXMLError(XMLMessages.MSG_ROOT_ELEMENT_REQUIRED,
890                                     XMLMessages.P1_ELEMENT_REQUIRED);
891                 fDispatcher = new EndOfInputDispatcher();
892                 setScannerState(SCANNER_STATE_END_OF_INPUT);
893             }
894         }
895     }
896     int fCurrentElementType = -1;
897     public int getCurrentElementType() {
898         return fCurrentElementType;
899     }
900     final class ContentDispatcher implements ScannerDispatcher {
901         private int fContentReader = -1;
902         private int fElementDepth = 0;
903         private int[] fElementTypeStack = new int[8];
904
905         void popElementType() {
906             if (fElementDepth-- == 0) {
907                 throw new RuntimeException JavaDoc("FWK002 popElementType: fElementDepth-- == 0.");
908             }
909             if (fElementDepth == 0) {
910                 fCurrentElementType = - 1;
911             } else {
912                 fCurrentElementType = fElementTypeStack[fElementDepth - 1];
913             }
914         }
915
916         public boolean dispatch(boolean keepgoing) throws Exception JavaDoc {
917             do {
918                 switch (fScannerState) {
919                 case SCANNER_STATE_ROOT_ELEMENT:
920                 {
921                     scanElementType(fEntityReader, '>', fElementQName);
922                     if (fElementQName.rawname != -1) {
923                         //
924
// root element
925
//
926
fContentReader = fReaderId;
927                         fSeenRootElement = true;
928                         //
929
// scan element
930
//
931
if (fEntityReader.lookingAtChar('>', true)) {
932                             //
933
// we have more content
934
//
935
fEventHandler.callStartElement(fElementQName);
936                             fScannerMarkupDepth--;
937                             if (fElementDepth == fElementTypeStack.length) {
938                                 int[] newStack = new int[fElementDepth * 2];
939                                 System.arraycopy(fElementTypeStack, 0, newStack, 0, fElementDepth);
940                                 fElementTypeStack = newStack;
941                             }
942                             fCurrentElementType = fElementQName.rawname;
943                             fElementTypeStack[fElementDepth] = fElementQName.rawname;
944                             fElementDepth++;
945                             restoreScannerState(SCANNER_STATE_CONTENT);
946                         } else if (scanElement(fElementQName)) {
947                             //
948
// we have more content
949
//
950
if (fElementDepth == fElementTypeStack.length) {
951                                 int[] newStack = new int[fElementDepth * 2];
952                                 System.arraycopy(fElementTypeStack, 0, newStack, 0, fElementDepth);
953                                 fElementTypeStack = newStack;
954                             }
955                             fCurrentElementType = fElementQName.rawname;
956                             fElementTypeStack[fElementDepth] = fElementQName.rawname;
957                             fElementDepth++;
958                             restoreScannerState(SCANNER_STATE_CONTENT);
959                         } else {
960                             fDispatcher = new TrailingMiscDispatcher();
961                             restoreScannerState(SCANNER_STATE_TRAILING_MISC);
962                             return true;
963                         }
964                     } else {
965                         reportFatalXMLError(XMLMessages.MSG_MARKUP_NOT_RECOGNIZED_IN_PROLOG,
966                                             XMLMessages.P22_NOT_RECOGNIZED);
967                         fDispatcher = new PrologDispatcher();
968                         restoreScannerState(SCANNER_STATE_PROLOG);
969                         return true;
970                     }
971                     break;
972                 }
973                 case SCANNER_STATE_START_OF_MARKUP:
974                     if (fEntityReader.lookingAtChar('?', true)) {
975                         int piTarget = fEntityReader.scanName(' ');
976                         if (piTarget == -1) {
977                             abortMarkup(XMLMessages.MSG_PITARGET_REQUIRED,
978                                         XMLMessages.P16_PITARGET_REQUIRED);
979                         } else if ("xml".equals(fStringPool.toString(piTarget))) {
980                             if (fEntityReader.lookingAtSpace(true)) { // an XMLDecl looks like a PI with the target 'xml'
981
if (fParseTextDecl) {
982                                     scanXMLDeclOrTextDecl(true);
983                                     fParseTextDecl = false;
984                                 } else {
985                                     abortMarkup(XMLMessages.MSG_TEXTDECL_MUST_BE_FIRST,
986                                                 XMLMessages.P30_TEXTDECL_MUST_BE_FIRST);
987                                 }
988                             } else { // a PI target matching 'xml'
989
abortMarkup(XMLMessages.MSG_RESERVED_PITARGET,
990                                             XMLMessages.P17_RESERVED_PITARGET);
991                             }
992                         } else { // PI
993
scanPI(piTarget);
994                         }
995                         restoreScannerState(SCANNER_STATE_CONTENT);
996                     } else if (fEntityReader.lookingAtChar('!', true)) {
997                         if (fEntityReader.lookingAtChar('-', true)) { // comment ?
998
if (fEntityReader.lookingAtChar('-', true)) {
999                                 scanComment(); // scan through the closing '-->'
1000
} else {
1001                                abortMarkup(XMLMessages.MSG_MARKUP_NOT_RECOGNIZED_IN_CONTENT,
1002                                            XMLMessages.P43_NOT_RECOGNIZED);
1003                            }
1004                        } else {
1005                            if (fEntityReader.skippedString(cdata_string)) {
1006                                fEntityReader.setInCDSect(true);
1007                                fEventHandler.callStartCDATA();
1008                            } else {
1009                                abortMarkup(XMLMessages.MSG_MARKUP_NOT_RECOGNIZED_IN_CONTENT,
1010                                            XMLMessages.P43_NOT_RECOGNIZED);
1011                            }
1012                        }
1013                    } else {
1014                        if (fEntityReader.lookingAtChar('/', true)) {
1015                            //
1016
// [42] ETag ::= '</' Name S? '>'
1017
//
1018
if (!scanExpectedElementType(fEntityReader, '>', fCurrentElementType)) {
1019                                abortMarkup(XMLMessages.MSG_ETAG_REQUIRED,
1020                                            XMLMessages.P39_UNTERMINATED,
1021                                            fCurrentElementType);
1022                            } else {
1023                                if (!fEntityReader.lookingAtChar('>', true)) {
1024                                    fEntityReader.skipPastSpaces();
1025                                    if (!fEntityReader.lookingAtChar('>', true)) {
1026                                        reportFatalXMLError(XMLMessages.MSG_ETAG_UNTERMINATED,
1027                                                            XMLMessages.P42_UNTERMINATED,
1028                                                            fCurrentElementType);
1029                                    }
1030                                }
1031                                fScannerMarkupDepth--;
1032                                fEventHandler.callEndElement(fReaderId);
1033                                if (fElementDepth-- == 0) {
1034                                    throw new RuntimeException JavaDoc("FWK002 popElementType: fElementDepth-- == 0.");
1035                                }
1036                                if (fElementDepth == 0) {
1037                                    fCurrentElementType = - 1;
1038                                    fDispatcher = new TrailingMiscDispatcher();
1039                                    restoreScannerState(SCANNER_STATE_TRAILING_MISC);
1040                                    return true;
1041                                } else {
1042                                    fCurrentElementType = fElementTypeStack[fElementDepth - 1];
1043                                }
1044                            }
1045                        } else {
1046                            scanElementType(fEntityReader, '>', fElementQName);
1047                            if (fElementQName.rawname != -1) {
1048                                //
1049
// element
1050
//
1051
if (fEntityReader.lookingAtChar('>', true)) {
1052                                    fEventHandler.callStartElement(fElementQName);
1053                                    fScannerMarkupDepth--;
1054                                    if (fElementDepth == fElementTypeStack.length) {
1055                                        int[] newStack = new int[fElementDepth * 2];
1056                                        System.arraycopy(fElementTypeStack, 0, newStack, 0, fElementDepth);
1057                                        fElementTypeStack = newStack;
1058                                    }
1059                                    fCurrentElementType = fElementQName.rawname;
1060                                    fElementTypeStack[fElementDepth] = fElementQName.rawname;
1061                                    fElementDepth++;
1062                                } else {
1063                                    if (scanElement(fElementQName)) {
1064                                        if (fElementDepth == fElementTypeStack.length) {
1065                                            int[] newStack = new int[fElementDepth * 2];
1066                                            System.arraycopy(fElementTypeStack, 0, newStack, 0, fElementDepth);
1067                                            fElementTypeStack = newStack;
1068                                        }
1069                                        fCurrentElementType = fElementQName.rawname;
1070                                        fElementTypeStack[fElementDepth] = fElementQName.rawname;
1071                                        fElementDepth++;
1072                                    }
1073                                }
1074                            } else {
1075                                abortMarkup(XMLMessages.MSG_MARKUP_NOT_RECOGNIZED_IN_CONTENT,
1076                                            XMLMessages.P43_NOT_RECOGNIZED);
1077                            }
1078                        }
1079                    }
1080                    restoreScannerState(SCANNER_STATE_CONTENT);
1081                    break;
1082                case SCANNER_STATE_CONTENT:
1083                    if (fParseTextDecl && fEntityReader.lookingAtChar('<', true)) {
1084                        fScannerMarkupDepth++;
1085                        setScannerState(SCANNER_STATE_START_OF_MARKUP);
1086                        continue;
1087                    }
1088                    // REVISIT: Is this the right thing to do? Do we need to
1089
// save more information on the stack?
1090
fCurrentElementQName.setValues(-1, -1, fCurrentElementType);
1091                    switch (fEntityReader.scanContent(fCurrentElementQName)) {
1092                    case XMLEntityHandler.CONTENT_RESULT_START_OF_PI:
1093                        fScannerMarkupDepth++;
1094                        int piTarget = fEntityReader.scanName(' ');
1095                        if (piTarget == -1) {
1096                            abortMarkup(XMLMessages.MSG_PITARGET_REQUIRED,
1097                                        XMLMessages.P16_PITARGET_REQUIRED);
1098                        } else if ("xml".equals(fStringPool.toString(piTarget))) {
1099                            if (fEntityReader.lookingAtSpace(true)) { // an XMLDecl looks like a PI with the target 'xml'
1100
if (fReaderId == fContentReader) {
1101                                    abortMarkup(XMLMessages.MSG_XMLDECL_MUST_BE_FIRST,
1102                                                XMLMessages.P22_XMLDECL_MUST_BE_FIRST);
1103                                } else {
1104                                    abortMarkup(XMLMessages.MSG_TEXTDECL_MUST_BE_FIRST,
1105                                                XMLMessages.P30_TEXTDECL_MUST_BE_FIRST);
1106                                }
1107                            } else { // a PI target matching 'xml'
1108
abortMarkup(XMLMessages.MSG_RESERVED_PITARGET,
1109                                            XMLMessages.P17_RESERVED_PITARGET);
1110                            }
1111                        } else { // PI
1112
scanPI(piTarget);
1113                        }
1114                        break;
1115                    case XMLEntityHandler.CONTENT_RESULT_START_OF_COMMENT:
1116                        fScannerMarkupDepth++;
1117                        fParseTextDecl = false;
1118                        scanComment(); // scan through the closing '-->'
1119
break;
1120                    case XMLEntityHandler.CONTENT_RESULT_START_OF_CDSECT:
1121                        fScannerMarkupDepth++;
1122                        fParseTextDecl = false;
1123                        fEntityReader.setInCDSect(true);
1124                        fEventHandler.callStartCDATA();
1125                        break;
1126                    case XMLEntityHandler.CONTENT_RESULT_START_OF_ETAG:
1127                        fScannerMarkupDepth++;
1128                        fParseTextDecl = false;
1129                        //
1130
// [42] ETag ::= '</' Name S? '>'
1131
//
1132
if (!scanExpectedElementType(fEntityReader, '>', fCurrentElementType)) {
1133                            abortMarkup(XMLMessages.MSG_ETAG_REQUIRED,
1134                                        XMLMessages.P39_UNTERMINATED,
1135                                        fCurrentElementType);
1136                        } else {
1137                            if (!fEntityReader.lookingAtChar('>', true)) {
1138                                fEntityReader.skipPastSpaces();
1139                                if (!fEntityReader.lookingAtChar('>', true)) {
1140                                    reportFatalXMLError(XMLMessages.MSG_ETAG_UNTERMINATED,
1141                                                        XMLMessages.P42_UNTERMINATED,
1142                                                        fCurrentElementType);
1143                                }
1144                            }
1145                            fScannerMarkupDepth--;
1146                            fEventHandler.callEndElement(fReaderId);
1147                            if (fElementDepth-- == 0) {
1148                                throw new RuntimeException JavaDoc("FWK002 popElementType: fElementDepth-- == 0.");
1149                            }
1150                            if (fElementDepth == 0) {
1151                                fCurrentElementType = - 1;
1152                                fDispatcher = new TrailingMiscDispatcher();
1153                                restoreScannerState(SCANNER_STATE_TRAILING_MISC);
1154                                return true;
1155                            } else {
1156                                fCurrentElementType = fElementTypeStack[fElementDepth - 1];
1157                            }
1158                        }
1159                        restoreScannerState(SCANNER_STATE_CONTENT);
1160                        break;
1161                    case XMLEntityHandler.CONTENT_RESULT_START_OF_ELEMENT:
1162                    {
1163                        fScannerMarkupDepth++;
1164                        fParseTextDecl = false;
1165                        scanElementType(fEntityReader, '>', fElementQName);
1166                        if (fElementQName.rawname != -1) {
1167                            if (fEntityReader.lookingAtChar('>', true)) {
1168                                fEventHandler.callStartElement(fElementQName);
1169                                fScannerMarkupDepth--;
1170                                if (fElementDepth == fElementTypeStack.length) {
1171                                    int[] newStack = new int[fElementDepth * 2];
1172                                    System.arraycopy(fElementTypeStack, 0, newStack, 0, fElementDepth);
1173                                    fElementTypeStack = newStack;
1174                                }
1175                                fCurrentElementType = fElementQName.rawname;
1176                                fElementTypeStack[fElementDepth] = fElementQName.rawname;
1177                                fElementDepth++;
1178                            } else {
1179                                if (scanElement(fElementQName)) {
1180                                    if (fElementDepth == fElementTypeStack.length) {
1181                                        int[] newStack = new int[fElementDepth * 2];
1182                                        System.arraycopy(fElementTypeStack, 0, newStack, 0, fElementDepth);
1183                                        fElementTypeStack = newStack;
1184                                    }
1185                                    fCurrentElementType = fElementQName.rawname;
1186                                    fElementTypeStack[fElementDepth] = fElementQName.rawname;
1187                                    fElementDepth++;
1188                                }
1189                            }
1190                        } else {
1191                            abortMarkup(XMLMessages.MSG_MARKUP_NOT_RECOGNIZED_IN_CONTENT,
1192                                        XMLMessages.P43_NOT_RECOGNIZED);
1193                        }
1194                        if (fScannerState != SCANNER_STATE_END_OF_INPUT)
1195                            fScannerState = SCANNER_STATE_CONTENT;
1196                        break;
1197                    }
1198                    case XMLEntityHandler.CONTENT_RESULT_MATCHING_ETAG:
1199                    {
1200                        fParseTextDecl = false;
1201                        fEventHandler.callEndElement(fReaderId);
1202                        if (fElementDepth-- == 0) {
1203                            throw new RuntimeException JavaDoc("FWK002 popElementType: fElementDepth-- == 0.");
1204                        }
1205                        if (fElementDepth == 0) {
1206                            fCurrentElementType = - 1;
1207                            if (fScannerState != SCANNER_STATE_END_OF_INPUT) {
1208                                fDispatcher = new TrailingMiscDispatcher();
1209                                fScannerState = SCANNER_STATE_TRAILING_MISC;
1210                            }
1211                            return true;
1212                        } else {
1213                            fCurrentElementType = fElementTypeStack[fElementDepth - 1];
1214                        }
1215                        if (fScannerState != SCANNER_STATE_END_OF_INPUT)
1216                            fScannerState = SCANNER_STATE_CONTENT;
1217                        break;
1218                    }
1219                    case XMLEntityHandler.CONTENT_RESULT_START_OF_CHARREF:
1220                        fParseTextDecl = false;
1221                        //
1222
// [67] Reference ::= EntityRef | CharRef
1223
// [68] EntityRef ::= '&' Name ';'
1224
// [66] CharRef ::= '&#' [0-9]+ ';' | '&#x' [0-9a-fA-F]+ ';'
1225
//
1226
setScannerState(SCANNER_STATE_REFERENCE);
1227                        int num = scanCharRef();
1228                        // if (num == -1) num = 0xfffd; // REVISIT - alternative is to use Unicode replacement char
1229
if (num != -1)
1230                            fEventHandler.callCharacters(num);
1231                        restoreScannerState(SCANNER_STATE_CONTENT);
1232                        break;
1233                    case XMLEntityHandler.CONTENT_RESULT_REFERENCE_END_OF_INPUT:
1234                        // REVISIT - This should hopefully get us the "reference not
1235
// contained in one entity" error when endOfInput is called.
1236
// Test that this is so...
1237
//
1238
// fall through...
1239
//
1240
case XMLEntityHandler.CONTENT_RESULT_START_OF_ENTITYREF:
1241                        fParseTextDecl = false;
1242                        //
1243
// [68] EntityRef ::= '&' Name ';'
1244
//
1245
setScannerState(SCANNER_STATE_REFERENCE);
1246                        int nameOffset = fEntityReader.currentOffset();
1247                        fEntityReader.skipPastName(';');
1248                        int nameLength = fEntityReader.currentOffset() - nameOffset;
1249                        if (nameLength == 0) {
1250                            reportFatalXMLError(XMLMessages.MSG_NAME_REQUIRED_IN_REFERENCE,
1251                                                XMLMessages.P68_NAME_REQUIRED);
1252                            restoreScannerState(SCANNER_STATE_CONTENT);
1253                        } else if (!fEntityReader.lookingAtChar(';', true)) {
1254                            reportFatalXMLError(XMLMessages.MSG_SEMICOLON_REQUIRED_IN_REFERENCE,
1255                                                XMLMessages.P68_SEMICOLON_REQUIRED,
1256                                                fEntityReader.addString(nameOffset, nameLength));
1257                            restoreScannerState(SCANNER_STATE_CONTENT);
1258                        } else {
1259                            restoreScannerState(SCANNER_STATE_CONTENT);
1260                            int entityName = fEntityReader.addSymbol(nameOffset, nameLength);
1261                            fParseTextDecl = fEntityHandler.startReadingFromEntity(entityName, fElementDepth, XMLEntityHandler.ENTITYREF_IN_CONTENT);
1262                        }
1263                        break;
1264                    case XMLEntityHandler.CONTENT_RESULT_END_OF_CDSECT:
1265                        fParseTextDecl = false;
1266                        //
1267
// [14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*)
1268
// [21] CDEnd ::= ']]>'
1269
//
1270
if (fEntityReader.getInCDSect()) {
1271                            fEntityReader.setInCDSect(false);
1272                            fEventHandler.callEndCDATA();
1273                            fScannerMarkupDepth--;
1274                        } else {
1275                            reportFatalXMLError(XMLMessages.MSG_CDEND_IN_CONTENT,
1276                                                XMLMessages.P14_INVALID);
1277                        }
1278                        restoreScannerState(SCANNER_STATE_CONTENT);
1279                        break;
1280                    case XMLEntityHandler.CONTENT_RESULT_INVALID_CHAR:
1281                        fParseTextDecl = false;
1282                        //
1283
// The reader will also use this state if it
1284
// encounters the end of input while reading
1285
// content. We need to check for this case.
1286
//
1287
if (fScannerState != SCANNER_STATE_END_OF_INPUT) {
1288                            if (!fEntityReader.lookingAtValidChar(false)) {
1289                                //
1290
// [2] Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] // any Unicode character, excluding the
1291
// | [#xE000-#xFFFD] | [#x10000-#x10FFFF] // surrogate blocks, FFFE, and FFFF.
1292
//
1293
int invChar = fEntityReader.scanInvalidChar();
1294                                if (fScannerState != SCANNER_STATE_END_OF_INPUT) {
1295                                    if (invChar >= 0) {
1296                                        if (fEntityReader.getInCDSect()) {
1297                                            reportFatalXMLError(XMLMessages.MSG_INVALID_CHAR_IN_CDSECT,
1298                                                                XMLMessages.P20_INVALID_CHARACTER,
1299                                                                Integer.toHexString(invChar));
1300                                        } else {
1301                                            reportFatalXMLError(XMLMessages.MSG_INVALID_CHAR_IN_CONTENT,
1302                                                                XMLMessages.P43_INVALID_CHARACTER,
1303                                                                Integer.toHexString(invChar));
1304                                        }
1305                                    }
1306                                }
1307                            }
1308                            restoreScannerState(SCANNER_STATE_CONTENT);
1309                        }
1310                        break;
1311                    case XMLEntityHandler.CONTENT_RESULT_MARKUP_NOT_RECOGNIZED:
1312                        fParseTextDecl = false;
1313                        abortMarkup(XMLMessages.MSG_MARKUP_NOT_RECOGNIZED_IN_CONTENT,
1314                                    XMLMessages.P43_NOT_RECOGNIZED);
1315                        break;
1316                    case XMLEntityHandler.CONTENT_RESULT_MARKUP_END_OF_INPUT:
1317                        // REVISIT - This should hopefully get us the "markup not
1318
// contained in one entity" error when endOfInput is called.
1319
// Test that this is so...
1320
fScannerMarkupDepth++;
1321                        fParseTextDecl = false;
1322                        fScannerState = SCANNER_STATE_START_OF_MARKUP;
1323                        break;
1324                    default:
1325                        throw new RuntimeException JavaDoc("FWK001 3] ScannerState="+fScannerState+"\n" + "3\t"+fScannerState); // should not happen
1326
}
1327                    break;
1328                default:
1329                    throw new RuntimeException JavaDoc("FWK001 4] ScannerState="+fScannerState+"\n" + "4\t"+fScannerState);
1330                }
1331            } while (fScannerState != SCANNER_STATE_END_OF_INPUT && keepgoing);
1332            return true;
1333        }
1334        public void endOfInput(int entityName, boolean moreToFollow) throws Exception JavaDoc {
1335            switch (fScannerState) {
1336            case SCANNER_STATE_ROOT_ELEMENT:
1337            case SCANNER_STATE_START_OF_MARKUP:
1338                break;
1339            case SCANNER_STATE_CONTENT:
1340                if (fEntityReader.getInCDSect()) {
1341                    reportFatalXMLError(XMLMessages.MSG_CDSECT_UNTERMINATED,
1342                                        XMLMessages.P18_UNTERMINATED);
1343                }
1344                break;
1345            case SCANNER_STATE_ATTRIBUTE_LIST:
1346                if (!moreToFollow) {
1347// REVISIT reportFatalXMLError(XMLMessages.MSG_TAG1);
1348
} else {
1349// REVISIT reportFatalXMLError(XMLMessages.MSG_TAG1);
1350
}
1351                break;
1352            case SCANNER_STATE_ATTRIBUTE_NAME:
1353                if (!moreToFollow) {
1354// REVISIT reportFatalXMLError(XMLMessages.MSG_ATTVAL0);
1355
} else {
1356// REVISIT reportFatalXMLError(XMLMessages.MSG_ATTVAL0);
1357
}
1358                break;
1359            case SCANNER_STATE_ATTRIBUTE_VALUE:
1360                if (!moreToFollow) {
1361                    reportFatalXMLError(XMLMessages.MSG_ATTRIBUTE_VALUE_UNTERMINATED,
1362                                        XMLMessages.P10_UNTERMINATED,
1363                                        fAttValueElementType,
1364                                        fAttValueAttrName);
1365                } else if (fReaderId == fAttValueReader) {
1366// REVISIT reportFatalXMLError(XMLMessages.MSG_ATTVAL0);
1367
} else {
1368                    fEntityReader.append(fLiteralData, fAttValueMark, fAttValueOffset - fAttValueMark);
1369                }
1370                break;
1371            case SCANNER_STATE_COMMENT:
1372                if (!moreToFollow) {
1373                    reportFatalXMLError(XMLMessages.MSG_COMMENT_UNTERMINATED,
1374                                        XMLMessages.P15_UNTERMINATED);
1375                } else {
1376                    reportFatalXMLError(XMLMessages.MSG_COMMENT_NOT_IN_ONE_ENTITY,
1377                                        XMLMessages.P78_NOT_WELLFORMED);
1378                }
1379                break;
1380            case SCANNER_STATE_PI:
1381                if (!moreToFollow) {
1382                    reportFatalXMLError(XMLMessages.MSG_PI_UNTERMINATED,
1383                                        XMLMessages.P16_UNTERMINATED);
1384                } else {
1385                    reportFatalXMLError(XMLMessages.MSG_PI_NOT_IN_ONE_ENTITY,
1386                                        XMLMessages.P78_NOT_WELLFORMED);
1387                }
1388                break;
1389            case SCANNER_STATE_REFERENCE:
1390                if (!moreToFollow) {
1391                    reportFatalXMLError(XMLMessages.MSG_REFERENCE_UNTERMINATED,
1392                                        XMLMessages.P67_UNTERMINATED);
1393                } else {
1394                    reportFatalXMLError(XMLMessages.MSG_REFERENCE_NOT_IN_ONE_ENTITY,
1395                                        XMLMessages.P78_NOT_WELLFORMED);
1396                }
1397                break;
1398            default:
1399                throw new RuntimeException JavaDoc("FWK001 5] ScannerState="+fScannerState+"\n" + "5\t"+fScannerState);
1400            }
1401            if (!moreToFollow) {
1402                if (fElementDepth > 0) {
1403                    reportFatalXMLError(XMLMessages.MSG_ETAG_REQUIRED,
1404                                        XMLMessages.P39_UNTERMINATED,
1405                                        fCurrentElementType);
1406                } else {
1407                    reportFatalXMLError(XMLMessages.MSG_ROOT_ELEMENT_REQUIRED,
1408                                        XMLMessages.P1_ELEMENT_REQUIRED,
1409                                        null);
1410                }
1411                fDispatcher = new EndOfInputDispatcher();
1412                setScannerState(SCANNER_STATE_END_OF_INPUT);
1413            }
1414        }
1415    }
1416    final class TrailingMiscDispatcher implements ScannerDispatcher {
1417        public boolean dispatch(boolean keepgoing) throws Exception JavaDoc {
1418            do {
1419                if (fEntityReader.lookingAtChar('<', true)) {
1420                    fScannerMarkupDepth++;
1421                    setScannerState(SCANNER_STATE_START_OF_MARKUP);
1422                    if (fEntityReader.lookingAtChar('?', true)) {
1423                        int piTarget = fEntityReader.scanName(' ');
1424                        if (piTarget == -1) {
1425                            abortMarkup(XMLMessages.MSG_PITARGET_REQUIRED,
1426                                        XMLMessages.P16_PITARGET_REQUIRED);
1427                        } else if ("xml".equals(fStringPool.toString(piTarget))) {
1428                            if (fEntityReader.lookingAtSpace(true)) { // an XMLDecl looks like a PI with the target 'xml'
1429
abortMarkup(XMLMessages.MSG_XMLDECL_MUST_BE_FIRST,
1430                                            XMLMessages.P22_XMLDECL_MUST_BE_FIRST);
1431                            } else { // a PI target matching 'xml'
1432
abortMarkup(XMLMessages.MSG_RESERVED_PITARGET,
1433                                            XMLMessages.P17_RESERVED_PITARGET);
1434                            }
1435                        } else { // PI
1436
scanPI(piTarget);
1437                        }
1438                    } else if (fEntityReader.lookingAtChar('!', true)) {
1439                        if (fEntityReader.lookingAtChar('-', true) &&
1440                            fEntityReader.lookingAtChar('-', true)) { // comment ?
1441
scanComment(); // scan through the closing '-->'
1442
} else {
1443                            abortMarkup(XMLMessages.MSG_MARKUP_NOT_RECOGNIZED_IN_MISC,
1444                                        XMLMessages.P27_NOT_RECOGNIZED);
1445                        }
1446                    } else {
1447                        abortMarkup(XMLMessages.MSG_MARKUP_NOT_RECOGNIZED_IN_MISC,
1448                                    XMLMessages.P27_NOT_RECOGNIZED);
1449                    }
1450                    restoreScannerState(SCANNER_STATE_TRAILING_MISC);
1451                } else if (fEntityReader.lookingAtSpace(true)) {
1452                    fEntityReader.skipPastSpaces();
1453                } else if (!fEntityReader.lookingAtValidChar(false)) {
1454                    int invChar = fEntityReader.scanInvalidChar();
1455                    if (fScannerState != SCANNER_STATE_END_OF_INPUT) {
1456                        if (invChar >= 0) {
1457                            String JavaDoc arg = Integer.toHexString(invChar);
1458                            reportFatalXMLError(XMLMessages.MSG_INVALID_CHAR_IN_MISC,
1459                                                XMLMessages.P27_INVALID_CHARACTER,
1460                                                arg);
1461                        }
1462                    }
1463                } else {
1464                    reportFatalXMLError(XMLMessages.MSG_MARKUP_NOT_RECOGNIZED_IN_MISC,
1465                                        XMLMessages.P27_NOT_RECOGNIZED);
1466                    fEntityReader.lookingAtValidChar(true);
1467                }
1468            } while (fScannerState != SCANNER_STATE_END_OF_INPUT && keepgoing);
1469            return true;
1470        }
1471        public void endOfInput(int entityName, boolean moreToFollow) throws Exception JavaDoc {
1472            if (moreToFollow)
1473                throw new RuntimeException JavaDoc("FWK003 TrailingMiscDispatcher.endOfInput moreToFollow");
1474            switch (fScannerState) {
1475            case SCANNER_STATE_TRAILING_MISC:
1476            case SCANNER_STATE_START_OF_MARKUP:
1477                break;
1478            case SCANNER_STATE_COMMENT:
1479                reportFatalXMLError(XMLMessages.MSG_COMMENT_UNTERMINATED,
1480                                    XMLMessages.P15_UNTERMINATED);
1481                break;
1482            case SCANNER_STATE_PI:
1483                reportFatalXMLError(XMLMessages.MSG_PI_UNTERMINATED,
1484                                    XMLMessages.P16_UNTERMINATED);
1485                break;
1486            default:
1487                throw new RuntimeException JavaDoc("FWK001 6] ScannerState="+fScannerState+"\n" + "6\t"+fScannerState);
1488            }
1489            fDispatcher = new EndOfInputDispatcher();
1490            setScannerState(SCANNER_STATE_END_OF_INPUT);
1491        }
1492    }
1493    final class EndOfInputDispatcher implements ScannerDispatcher {
1494        public boolean dispatch(boolean keepgoing) throws Exception JavaDoc {
1495            if (fScannerState != SCANNER_STATE_TERMINATED)
1496                fEventHandler.callEndDocument();
1497            setScannerState(SCANNER_STATE_TERMINATED);
1498            return false;
1499        }
1500        public void endOfInput(int entityName, boolean moreToFollow) throws Exception JavaDoc {
1501            throw new RuntimeException JavaDoc("FWK001 7] ScannerState="+fScannerState+"\n" + "7\t"+fScannerState);
1502        }
1503    }
1504    //
1505
// From the standard:
1506
//
1507
// [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'
1508
// [24] VersionInfo ::= S 'version' Eq (' VersionNum ' | " VersionNum ")
1509
// [80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' | "'" EncName "'" )
1510
// [81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*
1511
// [32] SDDecl ::= S 'standalone' Eq (("'" ('yes' | 'no') "'")
1512
// | ('"' ('yes' | 'no') '"'))
1513
//
1514
// [77] TextDecl ::= '<?xml' VersionInfo? EncodingDecl S? '?>'
1515
//
1516
void scanXMLDeclOrTextDecl(boolean scanningTextDecl) throws Exception JavaDoc
1517    {
1518        int version = -1;
1519        int encoding = -1;
1520        int standalone = -1;
1521        final int XMLDECL_START = 0;
1522        final int XMLDECL_VERSION = 1;
1523        final int XMLDECL_ENCODING = 2;
1524        final int XMLDECL_STANDALONE = 3;
1525        final int XMLDECL_FINISHED = 4;
1526        int state = XMLDECL_START;
1527        do {
1528            fEntityReader.skipPastSpaces();
1529            int offset = fEntityReader.currentOffset();
1530            if (scanningTextDecl) {
1531                if (state == XMLDECL_START && fEntityReader.skippedString(version_string)) {
1532                    state = XMLDECL_VERSION;
1533                } else if (fEntityReader.skippedString(encoding_string)) {
1534                    state = XMLDECL_ENCODING;
1535                } else {
1536                    abortMarkup(XMLMessages.MSG_ENCODINGDECL_REQUIRED,
1537                                XMLMessages.P77_ENCODINGDECL_REQUIRED);
1538                    return;
1539                }
1540            } else {
1541                if (state == XMLDECL_START) {
1542                    if (!fEntityReader.skippedString(version_string)) {
1543                        abortMarkup(XMLMessages.MSG_VERSIONINFO_REQUIRED,
1544                                    XMLMessages.P23_VERSIONINFO_REQUIRED);
1545                        return;
1546                    }
1547                    state = XMLDECL_VERSION;
1548                } else {
1549                    if (state == XMLDECL_VERSION) {
1550                        if (fEntityReader.skippedString(encoding_string))
1551                            state = XMLDECL_ENCODING;
1552                        else
1553                            state = XMLDECL_STANDALONE;
1554                    } else
1555                        state = XMLDECL_STANDALONE;
1556                    if (state == XMLDECL_STANDALONE && !fEntityReader.skippedString(standalone_string))
1557                        break;
1558                }
1559            }
1560            int length = fEntityReader.currentOffset() - offset;
1561            fEntityReader.skipPastSpaces();
1562            if (!fEntityReader.lookingAtChar('=', true)) {
1563                int majorCode = scanningTextDecl ?
1564                                XMLMessages.MSG_EQ_REQUIRED_IN_TEXTDECL :
1565                                XMLMessages.MSG_EQ_REQUIRED_IN_XMLDECL;
1566                int minorCode = state == XMLDECL_VERSION ?
1567                                XMLMessages.P24_EQ_REQUIRED :
1568                                (state == XMLDECL_ENCODING ?
1569                                 XMLMessages.P80_EQ_REQUIRED :
1570                                 XMLMessages.P32_EQ_REQUIRED);
1571                abortMarkup(majorCode, minorCode, fEntityReader.addString(offset, length));
1572                return;
1573            }
1574            fEntityReader.skipPastSpaces();
1575            int result = fEntityReader.scanStringLiteral();
1576            switch (result) {
1577            case XMLEntityHandler.STRINGLIT_RESULT_QUOTE_REQUIRED:
1578            {
1579                int majorCode = scanningTextDecl ?
1580                                XMLMessages.MSG_QUOTE_REQUIRED_IN_TEXTDECL :
1581                                XMLMessages.MSG_QUOTE_REQUIRED_IN_XMLDECL;
1582                int minorCode = state == XMLDECL_VERSION ?
1583                                XMLMessages.P24_QUOTE_REQUIRED :
1584                                (state == XMLDECL_ENCODING ?
1585                                 XMLMessages.P80_QUOTE_REQUIRED :
1586                                 XMLMessages.P32_QUOTE_REQUIRED);
1587                abortMarkup(majorCode, minorCode, fEntityReader.addString(offset, length));
1588                return;
1589            }
1590            case XMLEntityHandler.STRINGLIT_RESULT_INVALID_CHAR:
1591                int invChar = fEntityReader.scanInvalidChar();
1592                if (fScannerState != SCANNER_STATE_END_OF_INPUT) {
1593                    if (invChar >= 0) {
1594                        int majorCode = scanningTextDecl ?
1595                                        XMLMessages.MSG_INVALID_CHAR_IN_TEXTDECL :
1596                                        XMLMessages.MSG_INVALID_CHAR_IN_XMLDECL;
1597                        int minorCode = state == XMLDECL_VERSION ?
1598                                        XMLMessages.P26_INVALID_CHARACTER :
1599                                        (state == XMLDECL_ENCODING ?
1600                                         XMLMessages.P81_INVALID_CHARACTER :
1601                                         XMLMessages.P32_INVALID_CHARACTER);
1602                        reportFatalXMLError(majorCode, minorCode, Integer.toHexString(invChar));
1603                    }
1604                    skipPastEndOfCurrentMarkup();
1605                }
1606                return;
1607            default:
1608                break;
1609            }
1610            switch (state) {
1611            case XMLDECL_VERSION:
1612                //
1613
// version="..."
1614
//
1615
version = result;
1616                String JavaDoc versionString = fStringPool.toString(version);
1617                if (!"1.0".equals(versionString)) {
1618                    if (!validVersionNum(versionString)) {
1619                        abortMarkup(XMLMessages.MSG_VERSIONINFO_INVALID,
1620                                            XMLMessages.P26_INVALID_VALUE,
1621                                            versionString);
1622                        return;
1623                    }
1624                    // NOTE: RECOVERABLE ERROR
1625
Object JavaDoc[] args = { versionString };
1626                    fErrorReporter.reportError(fErrorReporter.getLocator(),
1627                                               XMLMessages.XML_DOMAIN,
1628                                               XMLMessages.MSG_VERSION_NOT_SUPPORTED,
1629                                               XMLMessages.P26_NOT_SUPPORTED,
1630                                               args,
1631                                               XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
1632                    // REVISIT - hope it is compatible...
1633
// skipPastEndOfCurrentMarkup();
1634
// return;
1635
}
1636                if (!fEntityReader.lookingAtSpace(true)) {
1637                    if (scanningTextDecl) {
1638                        abortMarkup(XMLMessages.MSG_SPACE_REQUIRED_IN_TEXTDECL,
1639                                    XMLMessages.P80_WHITESPACE_REQUIRED);
1640                        return;
1641                    }
1642                    state = XMLDECL_FINISHED;
1643                }
1644                break;
1645            case XMLDECL_ENCODING:
1646                //
1647
// encoding = "..."
1648
//
1649
encoding = result;
1650                String JavaDoc encodingString = fStringPool.toString(encoding);
1651                if (!validEncName(encodingString)) {
1652                    abortMarkup(XMLMessages.MSG_ENCODINGDECL_INVALID,
1653                                XMLMessages.P81_INVALID_VALUE,
1654                                encodingString);
1655                    return;
1656                }
1657                if (!fEntityReader.lookingAtSpace(true)) {
1658                    state = XMLDECL_FINISHED;
1659                } else if (scanningTextDecl) {
1660                    fEntityReader.skipPastSpaces();
1661                    state = XMLDECL_FINISHED;
1662                }
1663                break;
1664            case XMLDECL_STANDALONE:
1665                //
1666
// standalone="..."
1667
//
1668
standalone = result;
1669                String JavaDoc standaloneString = fStringPool.toString(standalone);
1670                boolean yes = "yes".equals(standaloneString);
1671                if (!yes && !"no".equals(standaloneString)) {
1672                    abortMarkup(XMLMessages.MSG_SDDECL_INVALID,
1673                                XMLMessages.P32_INVALID_VALUE,
1674                                standaloneString);
1675                    return;
1676                }
1677                fStandalone = yes;
1678                fEntityReader.skipPastSpaces();
1679                state = XMLDECL_FINISHED;
1680                break;
1681            }
1682        } while (state != XMLDECL_FINISHED);
1683        if (!fEntityReader.lookingAtChar('?', true) || !fEntityReader.lookingAtChar('>', true)) {
1684            int majorCode, minorCode;
1685            if (scanningTextDecl) {
1686                majorCode = XMLMessages.MSG_TEXTDECL_UNTERMINATED;
1687                minorCode = XMLMessages.P77_UNTERMINATED;
1688            } else {
1689                majorCode = XMLMessages.MSG_XMLDECL_UNTERMINATED;
1690                minorCode = XMLMessages.P23_UNTERMINATED;
1691            }
1692            abortMarkup(majorCode, minorCode);
1693            return;
1694        }
1695        fScannerMarkupDepth--;
1696        if (scanningTextDecl) {
1697            fEventHandler.callTextDecl(version, encoding);
1698        } else {
1699            //
1700
// Now that we have hit '?>' we are done with XML decl. Call the
1701
// handler before returning.
1702
//
1703
fEventHandler.callXMLDecl(version, encoding, standalone);
1704            // if we see standalone = 'yes', call the eventHandler - XMLValidator
1705
if (fStandalone) {
1706                fEventHandler.callStandaloneIsYes();
1707            }
1708        }
1709    }
1710    //
1711
// From the standard:
1712
//
1713
// [39] element ::= EmptyElemTag | STag content ETag
1714
// [44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>'
1715
// [40] STag ::= '<' Name (S Attribute)* S? '>'
1716
// [41] Attribute ::= Name Eq AttValue
1717
// [10] AttValue ::= '"' ([^<&"] | Reference)* '"' | "'" ([^<&'] | Reference)* "'"
1718
// [67] Reference ::= EntityRef | CharRef
1719
// [68] EntityRef ::= '&' Name ';'
1720
// [66] CharRef ::= '&#' [0-9]+ ';' | '&#x' [0-9a-fA-F]+ ';'
1721
// [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
1722
// [42] ETag ::= '</' Name S? '>'
1723
//
1724
// Note: We have already scanned Name.
1725
//
1726
boolean scanElement(QName element) throws Exception JavaDoc
1727    {
1728        //
1729
// Scan for attributes
1730
//
1731
boolean greater = false;
1732        boolean slash = false;
1733        if (greater = fEntityReader.lookingAtChar('>', true)) {
1734            // no attributes
1735
} else if (fEntityReader.lookingAtSpace(true)) {
1736            int previousState = setScannerState(SCANNER_STATE_ATTRIBUTE_LIST);
1737            while (true) {
1738                fEntityReader.skipPastSpaces();
1739                //
1740
// [41] Attribute ::= Name Eq AttValue
1741
//
1742
if ((greater = fEntityReader.lookingAtChar('>', true)) || (slash = fEntityReader.lookingAtChar('/', true)))
1743                    break;
1744                //
1745
// Name
1746
//
1747
setScannerState(SCANNER_STATE_ATTRIBUTE_NAME);
1748                scanAttributeName(fEntityReader, element, fAttributeQName);
1749                if (fAttributeQName.rawname == -1) {
1750                    break;
1751                }
1752                //
1753
// Eq
1754
//
1755
fEntityReader.skipPastSpaces();
1756                if (!fEntityReader.lookingAtChar('=', true)) {
1757                    if (fScannerState != SCANNER_STATE_END_OF_INPUT) {
1758                        abortMarkup(XMLMessages.MSG_EQ_REQUIRED_IN_ATTRIBUTE,
1759                                    XMLMessages.P41_EQ_REQUIRED,
1760                                    element.rawname, fAttributeQName.rawname);
1761                        restoreScannerState(previousState);
1762                    }
1763                    return false;
1764                }
1765                fEntityReader.skipPastSpaces();
1766                int result = scanAttValue(element, fAttributeQName, false);
1767                if (result == RESULT_FAILURE) {
1768                    if (fScannerState != SCANNER_STATE_END_OF_INPUT) {
1769                        skipPastEndOfCurrentMarkup();
1770                        restoreScannerState(previousState);
1771                    }
1772                    return false;
1773                } else if (result == RESULT_DUPLICATE_ATTR) {
1774                    reportFatalXMLError(XMLMessages.MSG_ATTRIBUTE_NOT_UNIQUE,
1775                                        XMLMessages.WFC_UNIQUE_ATT_SPEC,
1776                                        element.rawname, fAttributeQName.rawname);
1777                }
1778                //The validator will check whether we have a duplicate attr in the start tag.
1779
if ( fEventHandler.attribute(element, fAttributeQName, result) ) {
1780                    reportFatalXMLError(XMLMessages.MSG_ATTRIBUTE_NOT_UNIQUE,
1781                                        XMLMessages.WFC_UNIQUE_ATT_SPEC,
1782                                        element.rawname, fAttributeQName.rawname);
1783                }
1784                restoreScannerState(SCANNER_STATE_ATTRIBUTE_LIST);
1785                if (!fEntityReader.lookingAtSpace(true)) {
1786                    if (!(greater = fEntityReader.lookingAtChar('>', true)))
1787                        slash = fEntityReader.lookingAtChar('/', true);
1788                    break;
1789                }
1790            }
1791            restoreScannerState(previousState);
1792        } else {
1793            slash = fEntityReader.lookingAtChar('/', true);
1794        }
1795        if (!greater && (!slash || !fEntityReader.lookingAtChar('>', true))) { // '>' or '/>'
1796
if (fScannerState != SCANNER_STATE_END_OF_INPUT) {
1797                abortMarkup(XMLMessages.MSG_ELEMENT_UNTERMINATED,
1798                            XMLMessages.P40_UNTERMINATED,
1799                            element.rawname);
1800            }
1801            return false;
1802        }
1803        fEventHandler.callStartElement(element);
1804        fScannerMarkupDepth--;
1805        if (slash) { // '/>'
1806
fEventHandler.callEndElement(fReaderId);
1807            return false;
1808        } else {
1809            return true;
1810        }
1811    }
1812    //
1813
// [66] CharRef ::= '&#' [0-9]+ ';' | '&#x' [0-9a-fA-F]+ ';'
1814
//
1815
int scanCharRef() throws Exception JavaDoc {
1816        int valueOffset = fEntityReader.currentOffset();
1817        boolean hex = fEntityReader.lookingAtChar('x', true);
1818        int num = fEntityReader.scanCharRef(hex);
1819        if (num < 0) {
1820            switch (num) {
1821            case XMLEntityHandler.CHARREF_RESULT_SEMICOLON_REQUIRED:
1822                reportFatalXMLError(XMLMessages.MSG_SEMICOLON_REQUIRED_IN_CHARREF,
1823                                    XMLMessages.P66_SEMICOLON_REQUIRED);
1824                return -1;
1825            case XMLEntityHandler.CHARREF_RESULT_INVALID_CHAR:
1826                int majorCode = hex ? XMLMessages.MSG_HEXDIGIT_REQUIRED_IN_CHARREF :
1827                                      XMLMessages.MSG_DIGIT_REQUIRED_IN_CHARREF;
1828                int minorCode = hex ? XMLMessages.P66_HEXDIGIT_REQUIRED :
1829                                      XMLMessages.P66_DIGIT_REQUIRED;
1830                reportFatalXMLError(majorCode, minorCode);
1831                return -1;
1832            case XMLEntityHandler.CHARREF_RESULT_OUT_OF_RANGE:
1833                num = 0x110000; // this will cause the right error to be reported below...
1834
break;
1835            }
1836        }
1837        //
1838
// [2] Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] // any Unicode character, excluding the
1839
// | [#xE000-#xFFFD] | [#x10000-#x10FFFF] // surrogate blocks, FFFE, and FFFF.
1840
//
1841
if (num < 0x20) {
1842            if (num == 0x09 || num == 0x0A || num == 0x0D) {
1843                return num;
1844            }
1845        } else if (num <= 0xD7FF || (num >= 0xE000 && (num <= 0xFFFD || (num >= 0x10000 && num <= 0x10FFFF)))) {
1846            return num;
1847        }
1848        int valueLength = fEntityReader.currentOffset() - valueOffset;
1849        reportFatalXMLError(XMLMessages.MSG_INVALID_CHARREF,
1850                            XMLMessages.WFC_LEGAL_CHARACTER,
1851                            fEntityReader.addString(valueOffset, valueLength));
1852        return -1;
1853    }
1854    //
1855
// From the standard:
1856
//
1857
// [15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
1858
//
1859
// Called after scanning past '<!--'
1860
//
1861
void scanComment() throws Exception JavaDoc
1862    {
1863        int commentOffset = fEntityReader.currentOffset();
1864        boolean sawDashDash = false;
1865        int previousState = setScannerState(SCANNER_STATE_COMMENT);
1866        while (fScannerState == SCANNER_STATE_COMMENT) {
1867            if (fEntityReader.lookingAtChar('-', false)) {
1868                int nextEndOffset = fEntityReader.currentOffset();
1869                int endOffset = 0;
1870                fEntityReader.lookingAtChar('-', true);
1871                int offset = fEntityReader.currentOffset();
1872                int count = 1;
1873                while (fEntityReader.lookingAtChar('-', true)) {
1874                    count++;
1875                    endOffset = nextEndOffset;
1876                    nextEndOffset = offset;
1877                    offset = fEntityReader.currentOffset();
1878                }
1879                if (count > 1) {
1880                    if (fEntityReader.lookingAtChar('>', true)) {
1881                        if (!sawDashDash && count > 2) {
1882                            reportFatalXMLError(XMLMessages.MSG_DASH_DASH_IN_COMMENT,
1883                                                XMLMessages.P15_DASH_DASH);
1884                            sawDashDash = true;
1885                        }
1886                        fScannerMarkupDepth--;
1887                        fEventHandler.callComment(fEntityReader.addString(commentOffset, endOffset - commentOffset));
1888                        restoreScannerState(previousState);
1889                        return;
1890                    } else if (!sawDashDash) {
1891                        reportFatalXMLError(XMLMessages.MSG_DASH_DASH_IN_COMMENT,
1892                                            XMLMessages.P15_DASH_DASH);
1893                        sawDashDash = true;
1894                    }
1895                }
1896            } else {
1897                if (!fEntityReader.lookingAtValidChar(true)) {
1898                    int invChar = fEntityReader.scanInvalidChar();
1899                    if (fScannerState != SCANNER_STATE_END_OF_INPUT) {
1900                        if (invChar >= 0) {
1901                            reportFatalXMLError(XMLMessages.MSG_INVALID_CHAR_IN_COMMENT,
1902                                                XMLMessages.P15_INVALID_CHARACTER,
1903                                                Integer.toHexString(invChar));
1904                        }
1905                    }
1906                }
1907            }
1908        }
1909        restoreScannerState(previousState);
1910    }
1911    //
1912
// From the standard:
1913
//
1914
// [16] PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'
1915
// [17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l'))
1916
//
1917
void scanPI(int piTarget) throws Exception JavaDoc
1918    {
1919        String JavaDoc piTargetString = fStringPool.toString(piTarget);
1920        if (piTargetString.length() == 3 &&
1921            (piTargetString.charAt(0) == 'X' || piTargetString.charAt(0) == 'x') &&
1922            (piTargetString.charAt(1) == 'M' || piTargetString.charAt(1) == 'm') &&
1923            (piTargetString.charAt(2) == 'L' || piTargetString.charAt(2) == 'l')) {
1924            abortMarkup(XMLMessages.MSG_RESERVED_PITARGET,
1925                        XMLMessages.P17_RESERVED_PITARGET);
1926            return;
1927        }
1928        int prevState = setScannerState(SCANNER_STATE_PI);
1929        int piDataOffset = -1;
1930        int piDataLength = -1;
1931        if (!fEntityReader.lookingAtSpace(true)) {
1932            if (!fEntityReader.lookingAtChar('?', true) || !fEntityReader.lookingAtChar('>', true)) {
1933                if (fScannerState != SCANNER_STATE_END_OF_INPUT) {
1934                    abortMarkup(XMLMessages.MSG_SPACE_REQUIRED_IN_PI,
1935                                XMLMessages.P16_WHITESPACE_REQUIRED);
1936                    restoreScannerState(prevState);
1937                }
1938                return;
1939            }
1940            piDataLength = 0;
1941        } else {
1942            fEntityReader.skipPastSpaces();
1943            piDataOffset = fEntityReader.currentOffset();
1944            while (fScannerState == SCANNER_STATE_PI) {
1945                while (fEntityReader.lookingAtChar('?', false)) {
1946                    int offset = fEntityReader.currentOffset();
1947                    fEntityReader.lookingAtChar('?', true);
1948                    if (fEntityReader.lookingAtChar('>', true)) {
1949                        piDataLength = offset - piDataOffset;
1950                        break;
1951                    }
1952                }
1953                if (piDataLength >= 0)
1954                    break;
1955                if (!fEntityReader.lookingAtValidChar(true)) {
1956                    int invChar = fEntityReader.scanInvalidChar();
1957                    if (fScannerState != SCANNER_STATE_END_OF_INPUT) {
1958                        if (invChar >= 0) {
1959                            reportFatalXMLError(XMLMessages.MSG_INVALID_CHAR_IN_PI,
1960                                                XMLMessages.P16_INVALID_CHARACTER,
1961                                                Integer.toHexString(invChar));
1962                        }
1963                        skipPastEndOfCurrentMarkup();
1964                        restoreScannerState(prevState);
1965                    }
1966                    return;
1967                }
1968            }
1969        }
1970        fScannerMarkupDepth--;
1971        restoreScannerState(prevState);
1972        int piData = piDataLength == 0 ?
1973                     StringPool.EMPTY_STRING : fEntityReader.addString(piDataOffset, piDataLength);
1974        fEventHandler.callProcessingInstruction(piTarget, piData);
1975    }
1976
1977    /** Sets whether the parser preprocesses namespaces. */
1978    public void setNamespacesEnabled(boolean enabled) {
1979        fNamespacesEnabled = enabled;
1980    }
1981
1982    /** Returns whether the parser processes namespaces. */
1983    public boolean getNamespacesEnabled() {
1984        return fNamespacesEnabled;
1985    }
1986
1987    /** Sets whether the parser validates. */
1988    public void setValidationEnabled(boolean enabled) {
1989        fValidationEnabled = enabled;
1990        if (fDTDScanner != null) {
1991            fDTDScanner.setValidationEnabled(enabled);
1992        }
1993    }
1994
1995    /** Returns true if validation is turned on. */
1996    public boolean getValidationEnabled() {
1997        return fValidationEnabled;
1998    }
1999
2000    /** Sets whether the parser loads the external DTD. */
2001    public void setLoadExternalDTD(boolean enabled) {
2002        fLoadExternalDTD = enabled;
2003        if (fDTDScanner != null) {
2004            fDTDScanner.setLoadExternalDTD(enabled);
2005        }
2006    }
2007
2008    /** Returns true if loading the external DTD is turned on. */
2009    public boolean getLoadExternalDTD() {
2010        return fLoadExternalDTD;
2011    }
2012
2013    // old EventHandler methods pushed back into scanner
2014

2015    /** Scans element type. */
2016    private void scanElementType(XMLEntityHandler.EntityReader entityReader,
2017                                char fastchar, QName element) throws Exception JavaDoc {
2018
2019        if (!fNamespacesEnabled) {
2020            element.clear();
2021            element.localpart = entityReader.scanName(fastchar);
2022            element.rawname = element.localpart;
2023        }
2024        else {
2025            entityReader.scanQName(fastchar, element);
2026            if (entityReader.lookingAtChar(':', false)) {
2027                fErrorReporter.reportError(fErrorReporter.getLocator(),
2028                                           XMLMessages.XML_DOMAIN,
2029                                           XMLMessages.MSG_TWO_COLONS_IN_QNAME,
2030                                           XMLMessages.P5_INVALID_CHARACTER,
2031                                           null,
2032                                           XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
2033                 entityReader.skipPastNmtoken(' ');
2034            }
2035        }
2036
2037        fEventHandler.element(element);
2038
2039    } // scanElementType(XMLEntityHandler.EntityReader,char,QName)
2040

2041    /** Scans expected element type. */
2042    private boolean scanExpectedElementType(XMLEntityHandler.EntityReader entityReader,
2043                                           char fastchar, int elementType)
2044        throws Exception JavaDoc {
2045
2046        /***/
2047        // REVISIT: Why aren't we using the 'element' parameter? -Ac
2048
// REVISIT: I replaced the 'fCurrentElement' with 'element' parameter, still working,
2049
// just wondering Why are we using CharArrayRange in the first place? -ericye
2050
if (fCurrentElementCharArrayRange == null) {
2051            fCurrentElementCharArrayRange = fStringPool.createCharArrayRange();
2052        }
2053        fStringPool.getCharArrayRange(elementType, fCurrentElementCharArrayRange);
2054        return entityReader.scanExpectedName(fastchar, fCurrentElementCharArrayRange);
2055        /***
2056        entityReader.scanQName(fastchar, element);
2057        return true;
2058        /***/

2059
2060    } // scanExpectedElementType(XMLEntityHandler.EntityReader,char,QName)
2061

2062    /** Scans attribute name. */
2063    private void scanAttributeName(XMLEntityHandler.EntityReader entityReader,
2064                                  QName element, QName attribute)
2065        throws Exception JavaDoc {
2066
2067        /***
2068        // REVISIT: What's this check for?
2069        if (!fSeenRootElement) {
2070            fSeenRootElement = true;
2071            rootElementSpecified(element);
2072            fStringPool.resetShuffleCount();
2073        }
2074        /***/

2075
2076        if (!fNamespacesEnabled) {
2077            attribute.clear();
2078            attribute.localpart = entityReader.scanName('=');
2079            attribute.rawname = attribute.localpart;
2080        }
2081        else {
2082            entityReader.scanQName('=', attribute);
2083            if (entityReader.lookingAtChar(':', false)) {
2084                fErrorReporter.reportError(fErrorReporter.getLocator(),
2085                                           XMLMessages.XML_DOMAIN,
2086                                           XMLMessages.MSG_TWO_COLONS_IN_QNAME,
2087                                           XMLMessages.P5_INVALID_CHARACTER,
2088                                           null,
2089                                           XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
2090                entityReader.skipPastNmtoken(' ');
2091            }
2092        }
2093
2094    } // scanAttributeName(XMLEntityHandler.EntityReader,QName,QName)
2095

2096    /** Scan doctype declaration. */
2097    private void scanDoctypeDecl(boolean standalone) throws Exception JavaDoc {
2098        
2099        fScanningDTD = true;
2100
2101        /***
2102        fScanningDTD = true;
2103        fCheckedForSchema = true;
2104        /***/

2105        fSeenDoctypeDecl = true;
2106        /***
2107        fStandaloneReader = standalone ? fEntityHandler.getReaderId() : -1;
2108        fDeclsAreExternal = false;
2109        if (fDTDImporter == null) {
2110            fDTDImporter = new DTDImporter(fStringPool, fErrorReporter, fEntityHandler, this);
2111        }
2112        else {
2113            fDTDImporter.reset(fStringPool);
2114        }
2115        fDTDImporter.initHandlers(fDTDHandler);
2116        fDTDImporter.setValidating(fValidating);
2117        fDTDImporter.setNamespacesEnabled(fNamespacesEnabled);
2118        if (fDTDImporter.scanDoctypeDecl(standalone) && fValidating) {
2119            // check declared elements
2120            if (fWarningOnUndeclaredElements) {
2121                // REVISIT: comment out because won't compile
2122                // checkDeclaredElements();
2123            }
2124
2125            // check required notations
2126            fEntityHandler.checkRequiredNotations();
2127        }
2128        fScanningDTD = false;
2129        /***/

2130        if (fDTDScanner == null) {
2131            fDTDScanner = new XMLDTDScanner(fStringPool, fErrorReporter, fEntityHandler, new ChunkyCharArray(fStringPool));
2132            fDTDScanner.setValidationEnabled(fValidationEnabled);
2133            fDTDScanner.setNamespacesEnabled(fNamespacesEnabled);
2134            fDTDScanner.setLoadExternalDTD(fLoadExternalDTD);
2135        }
2136        else {
2137            fDTDScanner.reset(fStringPool, new ChunkyCharArray(fStringPool));
2138        }
2139        fDTDScanner.setDTDHandler(fDTDHandler);
2140        fDTDScanner.setGrammarResolver(fGrammarResolver);
2141        // REVISIT: What about standalone?
2142
if (fDTDScanner.scanDoctypeDecl()) {
2143            if (fDTDScanner.getReadingExternalEntity()) {
2144                fDTDScanner.scanDecls(true);
2145            }
2146            // REVISIT: What about validation and checking stuff?
2147
}
2148        //VC_NOTATION_DECLARED
2149
if (fValidationEnabled) {
2150            ((DefaultEntityHandler)fEntityHandler).checkRequiredNotations();
2151        }
2152        /***/
2153        fScanningDTD = false;
2154
2155    } // scanDoctypeDecl(boolean)
2156

2157    /** Scan attribute value. */
2158    private int scanAttValue(QName element, QName attribute) throws Exception JavaDoc {
2159
2160        //fAttrNameLocator = getLocatorImpl(fAttrNameLocator);
2161
int attValue = scanAttValue(element, attribute, fValidationEnabled);
2162        if (attValue == -1) {
2163            return XMLDocumentScanner.RESULT_FAILURE;
2164        }
2165
2166
2167        /***
2168        // REVISIT: This is validation related.
2169        if (!fValidating && fAttDefCount == 0) {
2170            int attType = fCDATASymbol;
2171            if (fAttrListHandle == -1)
2172                fAttrListHandle = fAttrList.startAttrList();
2173            // REVISIT: Should this be localpart or rawname?
2174            if (fAttrList.addAttr(attribute, attValue, attType, true, true) == -1) {
2175                return XMLDocumentScanner.RESULT_DUPLICATE_ATTR;
2176            }
2177            return XMLDocumentScanner.RESULT_SUCCESS;
2178        }
2179        /****/

2180
2181        /****
2182        // REVISIT: Validation. What should these be?
2183        int attDefIndex = getAttDef(element, attribute);
2184        if (attDefIndex == -1) {
2185
2186            if (fValidating) {
2187                // REVISIT - cache the elem/attr tuple so that we only give
2188                // this error once for each unique occurrence
2189                Object[] args = { fStringPool.toString(element.rawname),
2190                                  fStringPool.toString(attribute.rawname) };
2191                fErrorReporter.reportError(fAttrNameLocator,
2192                                           XMLMessages.XML_DOMAIN,
2193                                           XMLMessages.MSG_ATTRIBUTE_NOT_DECLARED,
2194                                           XMLMessages.VC_ATTRIBUTE_VALUE_TYPE,
2195                                           args,
2196                                           XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
2197            }
2198
2199            int attType = fCDATASymbol;
2200            if (fAttrListHandle == -1) {
2201                fAttrListHandle = fAttrList.startAttrList();
2202            }
2203            // REVISIT: Validation. What should the name be?
2204            if (fAttrList.addAttr(attribute, attValue, attType, true, true) == -1) {
2205                return XMLDocumentScanner.RESULT_DUPLICATE_ATTR;
2206            }
2207            return XMLDocumentScanner.RESULT_SUCCESS;
2208        }
2209        /****/

2210
2211        /****
2212        int attType = getAttType(attDefIndex);
2213        if (attType != fCDATASymbol) {
2214            AttributeValidator av = getAttributeValidator(attDefIndex);
2215            int enumHandle = getEnumeration(attDefIndex);
2216            // REVISIT: Validation. What should these be?
2217            attValue = av.normalize(element, attribute,
2218                                    attValue, attType, enumHandle);
2219        }
2220
2221        if (fAttrListHandle == -1) {
2222            fAttrListHandle = fAttrList.startAttrList();
2223        }
2224        // REVISIT: Validation. What should the name be?
2225        if (fAttrList.addAttr(attribute, attValue, attType, true, true) == -1) {
2226            return XMLDocumentScanner.RESULT_DUPLICATE_ATTR;
2227        }
2228        /***/

2229
2230        return XMLDocumentScanner.RESULT_SUCCESS;
2231
2232    } // scanAttValue(QName,QName):int
2233

2234    /** Returns true if the version number is valid. */
2235    private boolean validVersionNum(String JavaDoc version) {
2236        return XMLCharacterProperties.validVersionNum(version);
2237    }
2238
2239    /** Returns true if the encoding name is valid. */
2240    private boolean validEncName(String JavaDoc encoding) {
2241        return XMLCharacterProperties.validEncName(encoding);
2242    }
2243
2244} // class XMLDocumentScanner
2245
Popular Tags