KickJava   Java API By Example, From Geeks To Geeks.

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


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 java.util.StringTokenizer JavaDoc;
61
62 import org.enhydra.apache.xerces.readers.DefaultEntityHandler;
63 import org.enhydra.apache.xerces.readers.XMLEntityHandler;
64 import org.enhydra.apache.xerces.utils.QName;
65 import org.enhydra.apache.xerces.utils.StringPool;
66 import org.enhydra.apache.xerces.utils.XMLCharacterProperties;
67 import org.enhydra.apache.xerces.utils.XMLMessages;
68 import org.enhydra.apache.xerces.validators.common.GrammarResolver;
69 import org.enhydra.apache.xerces.validators.common.XMLAttributeDecl;
70 import org.enhydra.apache.xerces.validators.common.XMLElementDecl;
71 import org.enhydra.apache.xerces.validators.dtd.DTDGrammar;
72 /**
73  * Default implementation of an XML DTD scanner.
74  * <p>
75  * Clients who wish to scan a DTD should implement
76  * XMLDTDScanner.EventHandler to provide the desired behavior
77  * when various DTD components are encountered.
78  * <p>
79  * To process the DTD, the client application should follow the
80  * following sequence:
81  * <ol>
82  * <li>call scanDocTypeDecl() to scan the DOCTYPE declaration
83  * <li>call getReadingExternalEntity() to determine if scanDocTypeDecl found an
84  * external subset
85  * <li>if scanning an external subset, call scanDecls(true) to process the external subset
86  * </ol>
87  *
88  * @see XMLDTDScanner.EventHandler
89  * @version $Id: XMLDTDScanner.java,v 1.2 2005/01/26 08:28:44 jkjome Exp $
90  */

91 public final class XMLDTDScanner {
92     //
93
// Constants
94
//
95
//
96
// [24] VersionInfo ::= S 'version' Eq (' VersionNum ' | " VersionNum ")
97
//
98
private static final char[] version_string = { 'v','e','r','s','i','o','n' };
99     //
100
// [45] elementdecl ::= '<!ELEMENT' S Name S contentspec S? '>'
101
//
102
private static final char[] element_string = { 'E','L','E','M','E','N','T' };
103     //
104
// [46] contentspec ::= 'EMPTY' | 'ANY' | Mixed | children
105
//
106
private static final char[] empty_string = { 'E','M','P','T','Y' };
107     private static final char[] any_string = { 'A','N','Y' };
108     //
109
// [51] Mixed ::= '(' S? '#PCDATA' (S? '|' S? Name)* S? ')*'
110
// | '(' S? '#PCDATA' S? ')'
111
//
112
private static final char[] pcdata_string = { '#','P','C','D','A','T','A' };
113     //
114
// [52] AttlistDecl ::= '<!ATTLIST' S Name AttDef* S? '>'
115
//
116
private static final char[] attlist_string = { 'A','T','T','L','I','S','T' };
117     //
118
// [55] StringType ::= 'CDATA'
119
//
120
private static final char[] cdata_string = { 'C','D','A','T','A' };
121     //
122
// [56] TokenizedType ::= 'ID' | 'IDREF' | 'IDREFS' | 'ENTITY' | 'ENTITIES'
123
// | 'NMTOKEN' | 'NMTOKENS'
124
//
125
// Note: We search for common substrings always trying to move forward
126
//
127
// 'ID' - Common prefix of ID, IDREF and IDREFS
128
// 'REF' - Common substring of IDREF and IDREFS after matching ID prefix
129
// 'ENTIT' - Common prefix of ENTITY and ENTITIES
130
// 'IES' - Suffix of ENTITIES
131
// 'NMTOKEN' - Common prefix of NMTOKEN and NMTOKENS
132
//
133
private static final char[] id_string = { 'I','D' };
134     private static final char[] ref_string = { 'R','E','F' };
135     private static final char[] entit_string = { 'E','N','T','I','T' };
136     private static final char[] ies_string = { 'I','E','S' };
137     private static final char[] nmtoken_string = { 'N','M','T','O','K','E','N' };
138     //
139
// [58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
140
// [82] NotationDecl ::= '<!NOTATION' S Name S (ExternalID | PublicID) S? '>'
141
//
142
private static final char[] notation_string = { 'N','O','T','A','T','I','O','N' };
143     //
144
// [60] DefaultDecl ::= '#REQUIRED' | '#IMPLIED' | (('#FIXED' S)? AttValue)
145
//
146
private static final char[] required_string = { '#','R','E','Q','U','I','R','E','D' };
147     private static final char[] implied_string = { '#','I','M','P','L','I','E','D' };
148     private static final char[] fixed_string = { '#','F','I','X','E','D' };
149     //
150
// [62] includeSect ::= '<![' S? 'INCLUDE' S? '[' extSubsetDecl ']]>'
151
//
152
private static final char[] include_string = { 'I','N','C','L','U','D','E' };
153     //
154
// [63] ignoreSect ::= '<![' S? 'IGNORE' S? '[' ignoreSectContents* ']]>'
155
//
156
private static final char[] ignore_string = { 'I','G','N','O','R','E' };
157     //
158
// [71] GEDecl ::= '<!ENTITY' S Name S EntityDef S? '>'
159
// [72] PEDecl ::= '<!ENTITY' S '%' S Name S PEDef S? '>'
160
//
161
private static final char[] entity_string = { 'E','N','T','I','T','Y' };
162     //
163
// [75] ExternalID ::= 'SYSTEM' S SystemLiteral
164
// | 'PUBLIC' S PubidLiteral S SystemLiteral
165
// [83] PublicID ::= 'PUBLIC' S PubidLiteral
166
//
167
private static final char[] system_string = { 'S','Y','S','T','E','M' };
168     private static final char[] public_string = { 'P','U','B','L','I','C' };
169     //
170
// [76] NDataDecl ::= S 'NDATA' S Name
171
//
172
private static final char[] ndata_string = { 'N','D','A','T','A' };
173     //
174
// [80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' | "'" EncName "'" )
175
//
176
private static final char[] encoding_string = { 'e','n','c','o','d','i','n','g' };
177     //
178
// Instance Variables
179
//
180
private DTDGrammar fDTDGrammar = null;
181     private GrammarResolver fGrammarResolver = null;
182     private boolean fNamespacesEnabled = false;
183     private boolean fValidationEnabled = false;
184     private boolean fLoadExternalDTD = true;
185     private XMLElementDecl fTempElementDecl = new XMLElementDecl();
186     private XMLAttributeDecl fTempAttributeDecl = new XMLAttributeDecl();
187     private QName fElementQName = new QName();
188     private QName fAttributeQName = new QName();
189     private QName fElementRefQName = new QName();
190     private EventHandler fEventHandler = null;
191     private XMLDocumentHandler.DTDHandler fDTDHandler = null;
192     private StringPool fStringPool = null;
193     private XMLErrorReporter fErrorReporter = null;
194     private XMLEntityHandler fEntityHandler = null;
195     private XMLEntityHandler.EntityReader fEntityReader = null;
196     private XMLEntityHandler.CharBuffer fLiteralData = null;
197     private int fReaderId = -1;
198     private int fSystemLiteral = -1;
199     private int fPubidLiteral = -1;
200     private int[] fOpStack = null;
201     private int[] fNodeIndexStack = null;
202     private int[] fPrevNodeIndexStack = null;
203     private int fScannerState = SCANNER_STATE_INVALID;
204     private int fIncludeSectDepth = 0;
205     private int fDoctypeReader = -1;
206     private int fExternalSubsetReader = -1;
207     private int fDefaultAttValueReader = -1;
208     private int fDefaultAttValueElementType = -1;
209     private int fDefaultAttValueAttrName = -1;
210     private int fDefaultAttValueOffset = -1;
211     private int fDefaultAttValueMark = -1;
212     private int fEntityValueReader = -1;
213     private int fEntityValueMark = -1;
214     private int fXMLSymbol = -1;
215     private int fXMLNamespace = -1;
216     private int fXMLSpace = -1;
217     private int fDefault = -1;
218     private int fPreserve = -1;
219     private int fScannerMarkupDepth = 0;
220     private int fScannerParenDepth = 0;
221     //
222
// Constructors
223
//
224
public XMLDTDScanner(StringPool stringPool,
225                          XMLErrorReporter errorReporter,
226                          XMLEntityHandler entityHandler,
227                          XMLEntityHandler.CharBuffer literalData) {
228         fStringPool = stringPool;
229         fErrorReporter = errorReporter;
230         fEntityHandler = entityHandler;
231         fLiteralData = literalData;
232         init();
233     }
234
235     /**
236      * Set the event handler
237      *
238      * @param eventHandler The place to send our callbacks.
239      */

240     public void setEventHandler(XMLDTDScanner.EventHandler eventHandler) {
241         fEventHandler = eventHandler;
242     }
243
244     /** Set the DTD handler. */
245     public void setDTDHandler(XMLDocumentHandler.DTDHandler dtdHandler) {
246         fDTDHandler = dtdHandler;
247     }
248
249     /** Sets the grammar resolver. */
250     public void setGrammarResolver(GrammarResolver resolver) {
251         fGrammarResolver = resolver;
252     }
253
254     /** set fNamespacesEnabled **/
255     public void setNamespacesEnabled(boolean enabled) {
256         fNamespacesEnabled = enabled;
257     }
258     
259     /** set fValidationEnabled **/
260     public void setValidationEnabled(boolean enabled) {
261         fValidationEnabled = enabled;
262     }
263
264     /** Sets whether the parser loads the external DTD. */
265     public void setLoadExternalDTD(boolean enabled) {
266         fLoadExternalDTD = enabled;
267     }
268
269     /**
270      * Is the XMLDTDScanner reading from an external entity?
271      *
272      * This will be true, in particular if there was an external subset
273      *
274      * @return true if the XMLDTDScanner is reading from an external entity.
275      */

276     public boolean getReadingExternalEntity() {
277         return fReaderId != fDoctypeReader;
278     }
279     /**
280      * Is the scanner reading a ContentSpec?
281      *
282      * @return true if the scanner is reading a ContentSpec
283      */

284     public boolean getReadingContentSpec() {
285         return getScannerState() == SCANNER_STATE_CONTENTSPEC;
286     }
287     /**
288      * Report the markup nesting depth. This allows a client to
289      * perform validation checks for correct markup nesting. This keeps
290      * scanning and validation separate.
291      *
292      * @return the markup nesting depth
293      */

294     public int markupDepth() {
295         return fScannerMarkupDepth;
296     }
297     private int increaseMarkupDepth() {
298         return fScannerMarkupDepth++;
299     }
300     private int decreaseMarkupDepth() {
301         return fScannerMarkupDepth--;
302     }
303     /**
304      * Report the parenthesis nesting depth. This allows a client to
305      * perform validation checks for correct parenthesis balancing. This keeps
306      * scanning and validation separate.
307      *
308      * @return the parenthesis depth
309      */

310     public int parenDepth() {
311         return fScannerParenDepth;
312     }
313     private void setParenDepth(int parenDepth) {
314         fScannerParenDepth = parenDepth;
315     }
316     private void increaseParenDepth() {
317         fScannerParenDepth++;
318     }
319     private void decreaseParenDepth() {
320         fScannerParenDepth--;
321     }
322     //
323
//
324
//
325
/**
326      * Allow XMLDTDScanner to be reused. This method is called from an
327      * XMLParser reset method, which passes the StringPool to be used
328      * by the reset DTD scanner instance.
329      *
330      * @param stringPool the string pool to be used by XMLDTDScanner.
331      */

332     public void reset(StringPool stringPool, XMLEntityHandler.CharBuffer literalData) throws Exception JavaDoc {
333         fStringPool = stringPool;
334         fLiteralData = literalData;
335         fEntityReader = null;
336         fReaderId = -1;
337         fSystemLiteral = -1;
338         fPubidLiteral = -1;
339         fOpStack = null;
340         fNodeIndexStack = null;
341         fPrevNodeIndexStack = null;
342         fScannerState = SCANNER_STATE_INVALID;
343         fIncludeSectDepth = 0;
344         fDoctypeReader = -1;
345         fExternalSubsetReader = -1;
346         fDefaultAttValueReader = -1;
347         fDefaultAttValueElementType = -1;
348         fDefaultAttValueAttrName = -1;
349         fDefaultAttValueOffset = -1;
350         fDefaultAttValueMark = -1;
351         fEntityValueReader = -1;
352         fEntityValueMark = -1;
353         fScannerMarkupDepth = 0;
354         fScannerParenDepth = 0;
355         init();
356     }
357     private void init() {
358         fXMLSymbol = fStringPool.addSymbol("xml");
359         fXMLNamespace = fStringPool.addSymbol("http://www.w3.org/XML/1998/namespace");
360
361         fXMLSpace = fStringPool.addSymbol("xml:space");
362         fDefault = fStringPool.addSymbol("default");
363         fPreserve = fStringPool.addSymbol("preserve");
364     }
365
366     //
367
// Interfaces
368
//
369

370     /**
371      * This interface must be implemented by the users of the XMLDTDScanner class.
372      * These methods form the abstraction between the implementation semantics and the
373      * more generic task of scanning the DTD-specific XML grammar.
374      */

375     public interface EventHandler {
376
377         /** Start of DTD. */
378         public void callStartDTD() throws Exception JavaDoc;
379
380         /** End of DTD. */
381         public void callEndDTD() throws Exception JavaDoc;
382
383         /**
384          * Signal the Text declaration of an external entity.
385          *
386          * @param version the handle in the string pool for the version number
387          * @param encoding the handle in the string pool for the encoding
388          * @exception java.lang.Exception
389          */

390         public void callTextDecl(int version, int encoding) throws Exception JavaDoc;
391         /**
392          * Called when the doctype decl is scanned
393          *
394          * @param rootElementType handle of the rootElement
395          * @param publicId StringPool handle of the public id
396          * @param systemId StringPool handle of the system id
397          * @exception java.lang.Exception
398          */

399         public void doctypeDecl(QName rootElement, int publicId, int systemId) throws Exception JavaDoc;
400         /**
401          * Called when the DTDScanner starts reading from the external subset
402          *
403          * @param publicId StringPool handle of the public id
404          * @param systemId StringPool handle of the system id
405          * @exception java.lang.Exception
406          */

407         public void startReadingFromExternalSubset(int publicId, int systemId) throws Exception JavaDoc;
408         /**
409          * Called when the DTDScanner stop reading from the external subset
410          *
411          * @exception java.lang.Exception
412          */

413         public void stopReadingFromExternalSubset() throws Exception JavaDoc;
414         /**
415          * Add an element declaration (forward reference)
416          *
417          * @param handle to the name of the element being declared
418          * @return handle to the element whose declaration was added
419          * @exception java.lang.Exception
420          */

421         public int addElementDecl(QName elementDecl) throws Exception JavaDoc;
422         /**
423          * Add an element declaration
424          *
425          * @param handle to the name of the element being declared
426          * @param contentSpecType handle to the type name of the content spec
427          * @param ContentSpec handle to the content spec node for the contentSpecType
428          * @return handle to the element declaration that was added
429          * @exception java.lang.Exception
430          */

431         public int addElementDecl(QName elementDecl, int contentSpecType, int contentSpec, boolean isExternal) throws Exception JavaDoc;
432         /**
433          * Add an attribute definition
434          *
435          * @param handle to the element whose attribute is being declared
436          * @param attName StringPool handle to the attribute name being declared
437          * @param attType type of the attribute
438          * @param enumeration StringPool handle of the attribute's enumeration list (if any)
439          * @param attDefaultType an integer value denoting the DefaultDecl value
440          * @param attDefaultValue StringPool handle of this attribute's default value
441          * @return handle to the attribute definition
442          * @exception java.lang.Exception
443          */

444         public int addAttDef(QName elementDecl, QName attributeDecl,
445                              int attType, boolean attList, int enumeration,
446                              int attDefaultType, int attDefaultValue, boolean isExternal) throws Exception JavaDoc;
447         /**
448          * create an XMLContentSpec for a leaf
449          *
450          * @param nameIndex StringPool handle to the name (Element) for the node
451          * @return handle to the newly create XMLContentSpec
452          * @exception java.lang.Exception
453          */

454         public int addUniqueLeafNode(int nameIndex) throws Exception JavaDoc;
455         /**
456          * Create an XMLContentSpec for a single non-leaf
457          *
458          * @param nodeType the type of XMLContentSpec to create - from XMLContentSpec.CONTENTSPECNODE_*
459          * @param nodeValue handle to an XMLContentSpec
460          * @return handle to the newly create XMLContentSpec
461          * @exception java.lang.Exception
462          */

463         public int addContentSpecNode(int nodeType, int nodeValue) throws Exception JavaDoc;
464         /**
465          * Create an XMLContentSpec for a two child leaf
466          *
467          * @param nodeType the type of XMLContentSpec to create - from XMLContentSpec.CONTENTSPECNODE_*
468          * @param leftNodeIndex handle to an XMLContentSpec
469          * @param rightNodeIndex handle to an XMLContentSpec
470          * @return handle to the newly create XMLContentSpec
471          * @exception java.lang.Exception
472          */

473         public int addContentSpecNode(int nodeType, int leftNodeIndex, int rightNodeIndex) throws Exception JavaDoc;
474         /**
475          * Create a string representation of an XMLContentSpec tree
476          *
477          * @param handle to an XMLContentSpec
478          * @return String representation of the content spec tree
479          * @exception java.lang.Exception
480          */

481         public String JavaDoc getContentSpecNodeAsString(int nodeIndex) throws Exception JavaDoc;
482         /**
483          * Start the scope of an entity declaration.
484          *
485          * @return <code>true</code> on success; otherwise
486          * <code>false</code> if the entity declaration is recursive.
487          * @exception java.lang.Exception
488          */

489         public boolean startEntityDecl(boolean isPE, int entityName) throws Exception JavaDoc;
490         /**
491          * End the scope of an entity declaration.
492          * @exception java.lang.Exception
493          */

494         public void endEntityDecl() throws Exception JavaDoc;
495         /**
496          * Add a declaration for an internal parameter entity
497          *
498          * @param name StringPool handle of the parameter entity name
499          * @param value StringPool handle of the parameter entity value
500          * @return handle to the parameter entity declaration
501          * @exception java.lang.Exception
502          */

503         public int addInternalPEDecl(int name, int value) throws Exception JavaDoc;
504         /**
505          * Add a declaration for an external parameter entity
506          *
507          * @param name StringPool handle of the parameter entity name
508          * @param publicId StringPool handle of the publicId
509          * @param systemId StringPool handle of the systemId
510          * @return handle to the parameter entity declaration
511          * @exception java.lang.Exception
512          */

513         public int addExternalPEDecl(int name, int publicId, int systemId) throws Exception JavaDoc;
514         /**
515          * Add a declaration for an internal entity
516          *
517          * @param name StringPool handle of the entity name
518          * @param value StringPool handle of the entity value
519          * @return handle to the entity declaration
520          * @exception java.lang.Exception
521          */

522         public int addInternalEntityDecl(int name, int value) throws Exception JavaDoc;
523         /**
524          * Add a declaration for an entity
525          *
526          * @param name StringPool handle of the entity name
527          * @param publicId StringPool handle of the publicId
528          * @param systemId StringPool handle of the systemId
529          * @return handle to the entity declaration
530          * @exception java.lang.Exception
531          */

532         public int addExternalEntityDecl(int name, int publicId, int systemId) throws Exception JavaDoc;
533         /**
534          * Add a declaration for an unparsed entity
535          *
536          * @param name StringPool handle of the entity name
537          * @param publicId StringPool handle of the publicId
538          * @param systemId StringPool handle of the systemId
539          * @param notationName StringPool handle of the notationName
540          * @return handle to the entity declaration
541          * @exception java.lang.Exception
542          */

543         public int addUnparsedEntityDecl(int name, int publicId, int systemId, int notationName) throws Exception JavaDoc;
544         /**
545          * Called when the scanner start scanning an enumeration
546          * @return StringPool handle to a string list that will hold the enumeration names
547          * @exception java.lang.Exception
548          */

549         public int startEnumeration() throws Exception JavaDoc;
550         /**
551          * Add a name to an enumeration
552          * @param enumIndex StringPool handle to the string list for the enumeration
553          * @param elementType handle to the element that owns the attribute with the enumeration
554          * @param attrName StringPool handle to the name of the attribut with the enumeration
555          * @param nameIndex StringPool handle to the name to be added to the enumeration
556          * @param isNotationType true if the enumeration is an enumeration of NOTATION names
557          * @exception java.lang.Exception
558          */

559         public void addNameToEnumeration(int enumIndex, int elementType, int attrName, int nameIndex, boolean isNotationType) throws Exception JavaDoc;
560         /**
561          * Finish processing an enumeration
562          *
563          * @param enumIndex handle to the string list which holds the enumeration to be finshed.
564          * @exception java.lang.Exception
565          */

566         public void endEnumeration(int enumIndex) throws Exception JavaDoc;
567         /**
568          * Add a declaration for a notation
569          *
570          * @param notationName
571          * @param publicId
572          * @param systemId
573          * @return handle to the notation declaration
574          * @exception java.lang.Exception
575          */

576         public int addNotationDecl(int notationName, int publicId, int systemId) throws Exception JavaDoc;
577         /**
578          * Called when a comment has been scanned
579          *
580          * @param data StringPool handle of the comment text
581          * @exception java.lang.Exception
582          */

583         public void callComment(int data) throws Exception JavaDoc;
584         /**
585          * Called when a processing instruction has been scanned
586          * @param piTarget StringPool handle of the PI target
587          * @param piData StringPool handle of the PI data
588          * @exception java.lang.Exception
589          */

590         public void callProcessingInstruction(int piTarget, int piData) throws Exception JavaDoc;
591         /**
592          * Supports DOM Level 2 internalSubset additions.
593          * Called when the internal subset is completely scanned.
594          */

595         public void internalSubset(int internalSubset) throws Exception JavaDoc;
596     }
597     //
598
//
599
//
600

601     /** Report a recoverable xml error. */
602     protected void reportRecoverableXMLError(int majorCode, int minorCode,
603                                              int stringIndex1)
604         throws Exception JavaDoc {
605
606         Object JavaDoc[] args = { fStringPool.toString(stringIndex1) };
607         fErrorReporter.reportError(fErrorReporter.getLocator(),
608                                    XMLMessages.XML_DOMAIN,
609                                    majorCode,
610                                    minorCode,
611                                    args,
612                                    XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
613
614     } // reportRecoverableXMLError(int,int,int)
615

616     /** Report a recoverable xml error. */
617     protected void reportRecoverableXMLError(int majorCode, int minorCode,
618                                          String JavaDoc string1) throws Exception JavaDoc {
619
620         Object JavaDoc[] args = { string1 };
621         fErrorReporter.reportError(fErrorReporter.getLocator(),
622                                    XMLMessages.XML_DOMAIN,
623                                    majorCode,
624                                    minorCode,
625                                    args,
626                                    XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
627
628     } // reportRecoverableXMLError(int,int,String)
629

630     /** Report a recoverable xml error. */
631     protected void reportRecoverableXMLError(int majorCode, int minorCode,
632                                              String JavaDoc string1, String JavaDoc string2)
633         throws Exception JavaDoc {
634
635         Object JavaDoc[] args = { string1, string2 };
636         fErrorReporter.reportError(fErrorReporter.getLocator(),
637                                    XMLMessages.XML_DOMAIN,
638                                    majorCode,
639                                    minorCode,
640                                    args,
641                                    XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
642
643     } // reportRecoverableXMLError(int,int,String,String)
644

645  
646     private void reportFatalXMLError(int majorCode, int minorCode) throws Exception JavaDoc {
647         fErrorReporter.reportError(fErrorReporter.getLocator(),
648                                    XMLMessages.XML_DOMAIN,
649                                    majorCode,
650                                    minorCode,
651                                    null,
652                                    XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
653     }
654     private void reportFatalXMLError(int majorCode, int minorCode, int stringIndex1) throws Exception JavaDoc {
655         Object JavaDoc[] args = { fStringPool.toString(stringIndex1) };
656         fErrorReporter.reportError(fErrorReporter.getLocator(),
657                                    XMLMessages.XML_DOMAIN,
658                                    majorCode,
659                                    minorCode,
660                                    args,
661                                    XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
662     }
663     private void reportFatalXMLError(int majorCode, int minorCode, String JavaDoc string1) throws Exception JavaDoc {
664         Object JavaDoc[] args = { string1 };
665         fErrorReporter.reportError(fErrorReporter.getLocator(),
666                                    XMLMessages.XML_DOMAIN,
667                                    majorCode,
668                                    minorCode,
669                                    args,
670                                    XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
671     }
672     private void reportFatalXMLError(int majorCode, int minorCode, int stringIndex1, int stringIndex2) throws Exception JavaDoc {
673         Object JavaDoc[] args = { fStringPool.toString(stringIndex1),
674                           fStringPool.toString(stringIndex2) };
675         fErrorReporter.reportError(fErrorReporter.getLocator(),
676                                    XMLMessages.XML_DOMAIN,
677                                    majorCode,
678                                    minorCode,
679                                    args,
680                                    XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
681     }
682     private void reportFatalXMLError(int majorCode, int minorCode, String JavaDoc string1, String JavaDoc string2) throws Exception JavaDoc {
683         Object JavaDoc[] args = { string1, string2 };
684         fErrorReporter.reportError(fErrorReporter.getLocator(),
685                                    XMLMessages.XML_DOMAIN,
686                                    majorCode,
687                                    minorCode,
688                                    args,
689                                    XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
690     }
691     private void reportFatalXMLError(int majorCode, int minorCode, String JavaDoc string1, String JavaDoc string2, String JavaDoc string3) throws Exception JavaDoc {
692         Object JavaDoc[] args = { string1, string2, string3 };
693         fErrorReporter.reportError(fErrorReporter.getLocator(),
694                                    XMLMessages.XML_DOMAIN,
695                                    majorCode,
696                                    minorCode,
697                                    args,
698                                    XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
699     }
700     private void abortMarkup(int majorCode, int minorCode) throws Exception JavaDoc {
701         reportFatalXMLError(majorCode, minorCode);
702         skipPastEndOfCurrentMarkup();
703     }
704     private void abortMarkup(int majorCode, int minorCode, int stringIndex1) throws Exception JavaDoc {
705         reportFatalXMLError(majorCode, minorCode, stringIndex1);
706         skipPastEndOfCurrentMarkup();
707     }
708     private void abortMarkup(int majorCode, int minorCode, String JavaDoc string1) throws Exception JavaDoc {
709         reportFatalXMLError(majorCode, minorCode, string1);
710         skipPastEndOfCurrentMarkup();
711     }
712     private void abortMarkup(int majorCode, int minorCode, int stringIndex1, int stringIndex2) throws Exception JavaDoc {
713         reportFatalXMLError(majorCode, minorCode, stringIndex1, stringIndex2);
714         skipPastEndOfCurrentMarkup();
715     }
716     private void skipPastEndOfCurrentMarkup() throws Exception JavaDoc {
717         fEntityReader.skipToChar('>');
718         if (fEntityReader.lookingAtChar('>', true))
719             decreaseMarkupDepth();
720     }
721     //
722
//
723
//
724
static private final int SCANNER_STATE_INVALID = -1;
725     static private final int SCANNER_STATE_END_OF_INPUT = 0;
726     static private final int SCANNER_STATE_DOCTYPEDECL = 50;
727     static private final int SCANNER_STATE_MARKUP_DECL = 51;
728     static private final int SCANNER_STATE_TEXTDECL = 53;
729     static private final int SCANNER_STATE_COMMENT = 54;
730     static private final int SCANNER_STATE_PI = 55;
731     static private final int SCANNER_STATE_DEFAULT_ATTRIBUTE_VALUE = 56;
732     static private final int SCANNER_STATE_CONTENTSPEC = 57;
733     static private final int SCANNER_STATE_ENTITY_VALUE = 58;
734     static private final int SCANNER_STATE_SYSTEMLITERAL = 59;
735     static private final int SCANNER_STATE_PUBIDLITERAL = 60;
736
737     private int setScannerState(int scannerState) {
738         int prevState = fScannerState;
739         fScannerState = scannerState;
740         return prevState;
741     }
742     private int getScannerState() {
743         return fScannerState;
744     }
745     private void restoreScannerState(int scannerState) {
746         if (fScannerState != SCANNER_STATE_END_OF_INPUT)
747             fScannerState = scannerState;
748     }
749     /**
750      * Change readers
751      *
752      * @param nextReader the new reader that the scanner will use
753      * @param nextReaderId id of the reader to change to
754      * @exception throws java.lang.Exception
755      */

756     public void readerChange(XMLEntityHandler.EntityReader nextReader, int nextReaderId) throws Exception JavaDoc {
757         fEntityReader = nextReader;
758         fReaderId = nextReaderId;
759         if (fScannerState == SCANNER_STATE_DEFAULT_ATTRIBUTE_VALUE) {
760             fDefaultAttValueOffset = fEntityReader.currentOffset();
761             fDefaultAttValueMark = fDefaultAttValueOffset;
762         } else if (fScannerState == SCANNER_STATE_ENTITY_VALUE) {
763             fEntityValueMark = fEntityReader.currentOffset();
764         }
765     }
766     /**
767      * Handle the end of input
768      *
769      * @param entityName the handle in the string pool of the name of the entity which has reached end of input
770      * @param moreToFollow if true, there is still input left to process in other readers
771      * @exception java.lang.Exception
772      */

773     public void endOfInput(int entityNameIndex, boolean moreToFollow) throws Exception JavaDoc {
774         if (fValidationEnabled ) {
775             int readerDepth = fEntityHandler.getReaderDepth();
776             if (getReadingContentSpec()) {
777                 int parenDepth = parenDepth();
778                 if (readerDepth != parenDepth) {
779                     reportRecoverableXMLError(XMLMessages.MSG_IMPROPER_GROUP_NESTING,
780                                                 XMLMessages.VC_PROPER_GROUP_PE_NESTING,
781                                                 entityNameIndex);
782                 }
783             } else {
784                 int markupDepth = markupDepth();
785                 if (readerDepth != markupDepth) {
786                     reportRecoverableXMLError(XMLMessages.MSG_IMPROPER_DECLARATION_NESTING,
787                                                 XMLMessages.VC_PROPER_DECLARATION_PE_NESTING,
788                                                 entityNameIndex);
789                 }
790             }
791         }
792         //REVISIT, why are we doing this?
793
moreToFollow = fReaderId != fExternalSubsetReader;
794
795 // System.out.println("current Scanner state " + getScannerState() +","+ fScannerState + moreToFollow);
796
switch (fScannerState) {
797         case SCANNER_STATE_INVALID:
798             throw new RuntimeException JavaDoc("FWK004 XMLDTDScanner.endOfInput: cannot happen: 2"+"\n2");
799         case SCANNER_STATE_END_OF_INPUT:
800             break;
801         case SCANNER_STATE_MARKUP_DECL:
802             if (!moreToFollow && fIncludeSectDepth > 0) {
803                 reportFatalXMLError(XMLMessages.MSG_INCLUDESECT_UNTERMINATED,
804                                     XMLMessages.P62_UNTERMINATED);
805             }
806             break;
807         case SCANNER_STATE_DOCTYPEDECL:
808             throw new RuntimeException JavaDoc("FWK004 XMLDTDScanner.endOfInput: cannot happen: 2.5"+"\n2.5");
809 // break;
810
case SCANNER_STATE_TEXTDECL:
811 // REVISIT reportFatalXMLError(XMLMessages.MSG_ATTVAL0);
812
break;
813         case SCANNER_STATE_SYSTEMLITERAL:
814             if (!moreToFollow) {
815                 reportFatalXMLError(XMLMessages.MSG_SYSTEMID_UNTERMINATED,
816                                     XMLMessages.P11_UNTERMINATED);
817             } else {
818 // REVISIT reportFatalXMLError(XMLMessages.MSG_ATTVAL0);
819
}
820             break;
821         case SCANNER_STATE_PUBIDLITERAL:
822             if (!moreToFollow) {
823                 reportFatalXMLError(XMLMessages.MSG_PUBLICID_UNTERMINATED,
824                                     XMLMessages.P12_UNTERMINATED);
825             } else {
826 // REVISIT reportFatalXMLError(XMLMessages.MSG_ATTVAL0);
827
}
828             break;
829         case SCANNER_STATE_COMMENT:
830             if (!moreToFollow && !getReadingExternalEntity()) {
831                 reportFatalXMLError(XMLMessages.MSG_COMMENT_UNTERMINATED,
832                                     XMLMessages.P15_UNTERMINATED);
833             } else {
834                 //
835
// REVISIT - HACK !!! code changed to pass incorrect OASIS test 'invalid--001'
836
// Uncomment the next line to conform to the spec...
837
//
838
//reportFatalXMLError(XMLMessages.MSG_COMMENT_NOT_IN_ONE_ENTITY,
839
// XMLMessages.P78_NOT_WELLFORMED);
840
}
841             break;
842         case SCANNER_STATE_PI:
843             if (!moreToFollow) {
844                 reportFatalXMLError(XMLMessages.MSG_PI_UNTERMINATED,
845                                     XMLMessages.P16_UNTERMINATED);
846             } else {
847                 reportFatalXMLError(XMLMessages.MSG_PI_NOT_IN_ONE_ENTITY,
848                                     XMLMessages.P78_NOT_WELLFORMED);
849             }
850             break;
851         case SCANNER_STATE_DEFAULT_ATTRIBUTE_VALUE:
852             if (!moreToFollow) {
853                 reportFatalXMLError(XMLMessages.MSG_ATTRIBUTE_VALUE_UNTERMINATED,
854                                     XMLMessages.P10_UNTERMINATED,
855                                     fDefaultAttValueElementType,
856                                     fDefaultAttValueAttrName);
857             } else if (fReaderId == fDefaultAttValueReader) {
858 // REVISIT reportFatalXMLError(XMLMessages.MSG_ATTVAL0);
859
} else {
860                 fEntityReader.append(fLiteralData, fDefaultAttValueMark, fDefaultAttValueOffset - fDefaultAttValueMark);
861             }
862             break;
863         case SCANNER_STATE_CONTENTSPEC:
864             break;
865         case SCANNER_STATE_ENTITY_VALUE:
866             if (fReaderId == fEntityValueReader) {
867 // REVISIT reportFatalXMLError(XMLMessages.MSG_ATTVAL0);
868
} else {
869                 fEntityReader.append(fLiteralData, fEntityValueMark, fEntityReader.currentOffset() - fEntityValueMark);
870             }
871             break;
872         default:
873             throw new RuntimeException JavaDoc("FWK004 XMLDTDScanner.endOfInput: cannot happen: 3"+"\n3");
874         }
875         if (!moreToFollow) {
876             setScannerState(SCANNER_STATE_END_OF_INPUT);
877         }
878     }
879     //
880
// [66] CharRef ::= '&#' [0-9]+ ';' | '&#x' [0-9a-fA-F]+ ';'
881
//
882
private int scanCharRef() throws Exception JavaDoc {
883         int valueOffset = fEntityReader.currentOffset();
884         boolean hex = fEntityReader.lookingAtChar('x', true);
885         int num = fEntityReader.scanCharRef(hex);
886         if (num < 0) {
887             switch (num) {
888             case XMLEntityHandler.CHARREF_RESULT_SEMICOLON_REQUIRED:
889                 reportFatalXMLError(XMLMessages.MSG_SEMICOLON_REQUIRED_IN_CHARREF,
890                                     XMLMessages.P66_SEMICOLON_REQUIRED);
891                 return -1;
892             case XMLEntityHandler.CHARREF_RESULT_INVALID_CHAR:
893                 int majorCode = hex ? XMLMessages.MSG_HEXDIGIT_REQUIRED_IN_CHARREF :
894                                       XMLMessages.MSG_DIGIT_REQUIRED_IN_CHARREF;
895                 int minorCode = hex ? XMLMessages.P66_HEXDIGIT_REQUIRED :
896                                       XMLMessages.P66_DIGIT_REQUIRED;
897                 reportFatalXMLError(majorCode, minorCode);
898                 return -1;
899             case XMLEntityHandler.CHARREF_RESULT_OUT_OF_RANGE:
900                 num = 0x110000; // this will cause the right error to be reported below...
901
break;
902             }
903         }
904         //
905
// [2] Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] // any Unicode character, excluding the
906
// | [#xE000-#xFFFD] | [#x10000-#x10FFFF] // surrogate blocks, FFFE, and FFFF.
907
//
908
if (num < 0x20) {
909             if (num == 0x09 || num == 0x0A || num == 0x0D) {
910                 return num;
911             }
912         } else if (num <= 0xD7FF || (num >= 0xE000 && (num <= 0xFFFD || (num >= 0x10000 && num <= 0x10FFFF)))) {
913             return num;
914         }
915         int valueLength = fEntityReader.currentOffset() - valueOffset;
916         reportFatalXMLError(XMLMessages.MSG_INVALID_CHARREF,
917                             XMLMessages.WFC_LEGAL_CHARACTER,
918                             fEntityReader.addString(valueOffset, valueLength));
919         return -1;
920     }
921     //
922
// From the standard:
923
//
924
// [15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
925
//
926
// Called after scanning past '<!--'
927
//
928
private void scanComment() throws Exception JavaDoc
929     {
930         int commentOffset = fEntityReader.currentOffset();
931         boolean sawDashDash = false;
932         int previousState = setScannerState(SCANNER_STATE_COMMENT);
933         while (fScannerState == SCANNER_STATE_COMMENT) {
934             if (fEntityReader.lookingAtChar('-', false)) {
935                 int nextEndOffset = fEntityReader.currentOffset();
936                 int endOffset = 0;
937                 fEntityReader.lookingAtChar('-', true);
938                 int offset = fEntityReader.currentOffset();
939                 int count = 1;
940                 while (fEntityReader.lookingAtChar('-', true)) {
941                     count++;
942                     endOffset = nextEndOffset;
943                     nextEndOffset = offset;
944                     offset = fEntityReader.currentOffset();
945                 }
946                 if (count > 1) {
947                     if (fEntityReader.lookingAtChar('>', true)) {
948                         if (!sawDashDash && count > 2) {
949                             reportFatalXMLError(XMLMessages.MSG_DASH_DASH_IN_COMMENT,
950                                                 XMLMessages.P15_DASH_DASH);
951                             sawDashDash = true;
952                         }
953                         decreaseMarkupDepth();
954                         int comment = fEntityReader.addString(commentOffset, endOffset - commentOffset);
955                         fDTDGrammar.callComment(comment);
956                         if (fDTDHandler != null) {
957                             fDTDHandler.comment(comment);
958                         }
959                         restoreScannerState(previousState);
960                         return;
961                     } else if (!sawDashDash) {
962                         reportFatalXMLError(XMLMessages.MSG_DASH_DASH_IN_COMMENT,
963                                             XMLMessages.P15_DASH_DASH);
964                         sawDashDash = true;
965                     }
966                 }
967             } else {
968                 if (!fEntityReader.lookingAtValidChar(true)) {
969                     int invChar = fEntityReader.scanInvalidChar();
970                     if (fScannerState != SCANNER_STATE_END_OF_INPUT) {
971                         if (invChar >= 0) {
972                             reportFatalXMLError(XMLMessages.MSG_INVALID_CHAR_IN_COMMENT,
973                                                 XMLMessages.P15_INVALID_CHARACTER,
974                                                 Integer.toHexString(invChar));
975                         }
976                     }
977                 }
978             }
979         }
980         restoreScannerState(previousState);
981     }
982     //
983
// From the standard:
984
//
985
// [16] PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'
986
// [17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l'))
987
//
988
private void scanPI(int piTarget) throws Exception JavaDoc
989     {
990         String JavaDoc piTargetString = fStringPool.toString(piTarget);
991         if (piTargetString.length() == 3 &&
992             (piTargetString.charAt(0) == 'X' || piTargetString.charAt(0) == 'x') &&
993             (piTargetString.charAt(1) == 'M' || piTargetString.charAt(1) == 'm') &&
994             (piTargetString.charAt(2) == 'L' || piTargetString.charAt(2) == 'l')) {
995             abortMarkup(XMLMessages.MSG_RESERVED_PITARGET,
996                         XMLMessages.P17_RESERVED_PITARGET);
997             return;
998         }
999         int prevState = setScannerState(SCANNER_STATE_PI);
1000        int piDataOffset = -1;
1001        int piDataLength = 0;
1002        if (!fEntityReader.lookingAtSpace(true)) {
1003            if (!fEntityReader.lookingAtChar('?', true) || !fEntityReader.lookingAtChar('>', true)) {
1004                if (fScannerState != SCANNER_STATE_END_OF_INPUT) {
1005                    abortMarkup(XMLMessages.MSG_SPACE_REQUIRED_IN_PI,
1006                                XMLMessages.P16_WHITESPACE_REQUIRED);
1007                    restoreScannerState(prevState);
1008                }
1009                return;
1010            }
1011            decreaseMarkupDepth();
1012            restoreScannerState(prevState);
1013        } else {
1014            fEntityReader.skipPastSpaces();
1015            piDataOffset = fEntityReader.currentOffset();
1016            while (fScannerState == SCANNER_STATE_PI) {
1017                while (fEntityReader.lookingAtChar('?', false)) {
1018                    int offset = fEntityReader.currentOffset();
1019                    fEntityReader.lookingAtChar('?', true);
1020                    if (fEntityReader.lookingAtChar('>', true)) {
1021                        piDataLength = offset - piDataOffset;
1022                        decreaseMarkupDepth();
1023                        restoreScannerState(prevState);
1024                        break;
1025                    }
1026                }
1027                if (fScannerState != SCANNER_STATE_PI)
1028                    break;
1029                if (!fEntityReader.lookingAtValidChar(true)) {
1030                    int invChar = fEntityReader.scanInvalidChar();
1031                    if (fScannerState != SCANNER_STATE_END_OF_INPUT) {
1032                        if (invChar >= 0) {
1033                            reportFatalXMLError(XMLMessages.MSG_INVALID_CHAR_IN_PI,
1034                                                XMLMessages.P16_INVALID_CHARACTER,
1035                                                Integer.toHexString(invChar));
1036                        }
1037                        skipPastEndOfCurrentMarkup();
1038                        restoreScannerState(prevState);
1039                    }
1040                    return;
1041                }
1042            }
1043        }
1044        int piData = piDataLength == 0 ?
1045                     StringPool.EMPTY_STRING : fEntityReader.addString(piDataOffset, piDataLength);
1046        fDTDGrammar.callProcessingInstruction(piTarget, piData);
1047        if (fDTDHandler != null) {
1048            fDTDHandler.processingInstruction(piTarget, piData);
1049        }
1050    }
1051    //
1052
// From the standard:
1053
//
1054
// [28] doctypedecl ::= '<!DOCTYPE' S Name (S ExternalID)? S?
1055
// ('[' (markupdecl | PEReference | S)* ']' S?)? '>'
1056
// [29] markupdecl ::= elementdecl | AttlistDecl | EntityDecl
1057
// | NotationDecl | PI | Comment
1058
//
1059
// Called after scanning '<!DOCTYPE'
1060
//
1061
/**
1062     * This routine is called after the &lt;!DOCTYPE portion of a DOCTYPE
1063     * line has been called. scanDocTypeDecl goes onto scan the rest of the DOCTYPE
1064     * decl. If an internal DTD subset exists, it is scanned. If an external DTD
1065     * subset exists, scanDocTypeDecl sets up the state necessary to process it.
1066     *
1067     * @return true if successful
1068     * @exception java.lang.Exception
1069     */

1070    public boolean scanDoctypeDecl() throws Exception JavaDoc
1071    {
1072        //System.out.println("XMLDTDScanner#scanDoctypeDecl()");
1073

1074        fDTDGrammar = new DTDGrammar(fStringPool);
1075        fDTDGrammar.callStartDTD();
1076        increaseMarkupDepth();
1077        fEntityReader = fEntityHandler.getEntityReader();
1078        fReaderId = fEntityHandler.getReaderId();
1079        fDoctypeReader = fReaderId;
1080        setScannerState(SCANNER_STATE_DOCTYPEDECL);
1081        if (!fEntityReader.lookingAtSpace(true)) {
1082            abortMarkup(XMLMessages.MSG_SPACE_REQUIRED_BEFORE_ROOT_ELEMENT_TYPE_IN_DOCTYPEDECL,
1083                        XMLMessages.P28_SPACE_REQUIRED);
1084            return false;
1085        }
1086        fEntityReader.skipPastSpaces();
1087        scanElementType(fEntityReader, ' ', fElementQName);
1088        if (fElementQName.rawname == -1) {
1089            abortMarkup(XMLMessages.MSG_ROOT_ELEMENT_TYPE_REQUIRED,
1090                        XMLMessages.P28_ROOT_ELEMENT_TYPE_REQUIRED);
1091            return false;
1092        }
1093        boolean lbrkt;
1094        boolean scanExternalSubset = false;
1095        int publicId = -1;
1096        int systemId = -1;
1097        if (fEntityReader.lookingAtSpace(true)) {
1098            fEntityReader.skipPastSpaces();
1099            if (!(lbrkt = fEntityReader.lookingAtChar('[', true)) && !fEntityReader.lookingAtChar('>', false)) {
1100                if (!scanExternalID(false)) {
1101                    skipPastEndOfCurrentMarkup();
1102                    return false;
1103                }
1104                if (fValidationEnabled || fLoadExternalDTD) {
1105                    scanExternalSubset = true;
1106                }
1107                publicId = fPubidLiteral;
1108                systemId = fSystemLiteral;
1109                fEntityReader.skipPastSpaces();
1110                lbrkt = fEntityReader.lookingAtChar('[', true);
1111            }
1112        } else
1113            lbrkt = fEntityReader.lookingAtChar('[', true);
1114        fDTDGrammar.doctypeDecl(fElementQName, publicId, systemId);
1115        if (fDTDHandler != null) {
1116            fDTDHandler.startDTD(fElementQName, publicId, systemId);
1117        }
1118        if (lbrkt) {
1119            scanDecls(false);
1120            fEntityReader.skipPastSpaces();
1121        }
1122        if (!fEntityReader.lookingAtChar('>', true)) {
1123            if (fScannerState != SCANNER_STATE_END_OF_INPUT) {
1124                abortMarkup(XMLMessages.MSG_DOCTYPEDECL_UNTERMINATED,
1125                            XMLMessages.P28_UNTERMINATED,
1126                            fElementQName.rawname);
1127            }
1128            return false;
1129        }
1130
1131        decreaseMarkupDepth();
1132
1133        //System.out.println(" scanExternalSubset: "+scanExternalSubset);
1134
if (scanExternalSubset) {
1135            ((DefaultEntityHandler) fEntityHandler).startReadingFromExternalSubset( fStringPool.toString(publicId),
1136                                                                                    fStringPool.toString(systemId),
1137                                                                                    markupDepth());
1138            fDTDGrammar.startReadingFromExternalSubset(publicId, systemId);
1139        }
1140        else {
1141            fDTDGrammar.callEndDTD();
1142            if (fDTDHandler != null) {
1143                fDTDHandler.endDTD();
1144            }
1145        }
1146
1147        fGrammarResolver.putGrammar("", fDTDGrammar);
1148
1149
1150        return true;
1151    }
1152    //
1153
// [75] ExternalID ::= 'SYSTEM' S SystemLiteral
1154
// | 'PUBLIC' S PubidLiteral S SystemLiteral
1155
// [83] PublicID ::= 'PUBLIC' S PubidLiteral
1156
//
1157
private boolean scanExternalID(boolean scanPublicID) throws Exception JavaDoc
1158    {
1159        fSystemLiteral = -1;
1160        fPubidLiteral = -1;
1161        int offset = fEntityReader.currentOffset();
1162        if (fEntityReader.skippedString(system_string)) {
1163            if (!fEntityReader.lookingAtSpace(true)) {
1164                reportFatalXMLError(XMLMessages.MSG_SPACE_REQUIRED_BEFORE_SYSTEMLITERAL_IN_EXTERNALID,
1165                                    XMLMessages.P75_SPACE_REQUIRED);
1166                return false;
1167            }
1168            fEntityReader.skipPastSpaces();
1169            if( getReadingExternalEntity() == true ) { //Are we in external subset?
1170
checkForPEReference(false);//If so Check for PE Ref
1171
}
1172            return scanSystemLiteral();
1173        }
1174        if (fEntityReader.skippedString(public_string)) {
1175            if (!fEntityReader.lookingAtSpace(true)) {
1176                reportFatalXMLError(XMLMessages.MSG_SPACE_REQUIRED_BEFORE_PUBIDLITERAL_IN_EXTERNALID,
1177                                    XMLMessages.P75_SPACE_REQUIRED);
1178                return false;
1179            }
1180            fEntityReader.skipPastSpaces();
1181            if (!scanPubidLiteral())
1182                return false;
1183            if (scanPublicID) {
1184                //
1185
// [82] NotationDecl ::= '<!NOTATION' S Name S (ExternalID | PublicID) S? '>'
1186
//
1187
if (!fEntityReader.lookingAtSpace(true))
1188                    return true; // no S, not an ExternalID
1189
fEntityReader.skipPastSpaces();
1190                if (fEntityReader.lookingAtChar('>', false)) // matches end of NotationDecl
1191
return true;
1192            } else {
1193                if (!fEntityReader.lookingAtSpace(true)) {
1194                    reportFatalXMLError(XMLMessages.MSG_SPACE_REQUIRED_AFTER_PUBIDLITERAL_IN_EXTERNALID,
1195                                        XMLMessages.P75_SPACE_REQUIRED);
1196                    return false;
1197                }
1198                fEntityReader.skipPastSpaces();
1199            }
1200            return scanSystemLiteral();
1201        }
1202        reportFatalXMLError(XMLMessages.MSG_EXTERNALID_REQUIRED,
1203                            XMLMessages.P75_INVALID);
1204        return false;
1205    }
1206    //
1207
// [11] SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'")
1208
//
1209
// REVISIT - need to look into uri escape mechanism for non-ascii characters.
1210
//
1211
private boolean scanSystemLiteral() throws Exception JavaDoc
1212    {
1213        boolean single;
1214        if (!(single = fEntityReader.lookingAtChar('\'', true)) && !fEntityReader.lookingAtChar('\"', true)) {
1215            reportFatalXMLError(XMLMessages.MSG_QUOTE_REQUIRED_IN_SYSTEMID,
1216                                XMLMessages.P11_QUOTE_REQUIRED);
1217            return false;
1218        }
1219        int prevState = setScannerState(SCANNER_STATE_SYSTEMLITERAL);
1220        int offset = fEntityReader.currentOffset();
1221        char qchar = single ? '\'' : '\"';
1222        boolean dataok = true;
1223        boolean fragment = false;
1224        while (!fEntityReader.lookingAtChar(qchar, false)) {
1225//ericye
1226
//System.out.println("XMLDTDScanner#scanDoctypeDecl() 3333333, "+fReaderId+", " + fScannerState+", " +fExternalSubsetReader);
1227
if (fEntityReader.lookingAtChar('#', true)) {
1228                fragment = true;
1229            } else if (!fEntityReader.lookingAtValidChar(true)) {
1230//System.out.println("XMLDTDScanner#scanDoctypeDecl() 555555 scan state: " + fScannerState);
1231
dataok = false;
1232                int invChar = fEntityReader.scanInvalidChar();
1233                if (fScannerState == SCANNER_STATE_END_OF_INPUT)
1234                    return false;
1235                if (invChar >= 0) {
1236                    reportFatalXMLError(XMLMessages.MSG_INVALID_CHAR_IN_SYSTEMID,
1237                                        XMLMessages.P11_INVALID_CHARACTER,
1238                                        Integer.toHexString(invChar));
1239                }
1240            }
1241        }
1242        if (dataok) {
1243            fSystemLiteral = fEntityReader.addString(offset, fEntityReader.currentOffset() - offset);
1244            if (fragment) {
1245                // NOTE: RECOVERABLE ERROR
1246
Object JavaDoc[] args = { fStringPool.toString(fSystemLiteral) };
1247                fErrorReporter.reportError(fErrorReporter.getLocator(),
1248                                           XMLMessages.XML_DOMAIN,
1249                                           XMLMessages.MSG_URI_FRAGMENT_IN_SYSTEMID,
1250                                           XMLMessages.P11_URI_FRAGMENT,
1251                                           args,
1252                                           XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
1253            }
1254        }
1255        fEntityReader.lookingAtChar(qchar, true);
1256        restoreScannerState(prevState);
1257        return dataok;
1258    }
1259    //
1260
// [12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'"
1261
// [13] PubidChar ::= #x20 | #xD | #xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%]
1262
//
1263
private boolean scanPubidLiteral() throws Exception JavaDoc
1264    {
1265        boolean single;
1266        if (!(single = fEntityReader.lookingAtChar('\'', true)) && !fEntityReader.lookingAtChar('\"', true)) {
1267            reportFatalXMLError(XMLMessages.MSG_QUOTE_REQUIRED_IN_PUBLICID,
1268                                XMLMessages.P12_QUOTE_REQUIRED);
1269            return false;
1270        }
1271        char qchar = single ? '\'' : '\"';
1272        int prevState = setScannerState(SCANNER_STATE_PUBIDLITERAL);
1273        boolean dataok = true;
1274        while (true) {
1275            if (fEntityReader.lookingAtChar((char)0x09, true)) {
1276                dataok = false;
1277                reportFatalXMLError(XMLMessages.MSG_PUBIDCHAR_ILLEGAL,
1278                                    XMLMessages.P12_INVALID_CHARACTER, "9");
1279            }
1280            if (!fEntityReader.lookingAtSpace(true))
1281                break;
1282        }
1283        int offset = fEntityReader.currentOffset();
1284        int dataOffset = fLiteralData.length();
1285        int toCopy = offset;
1286        while (true) {
1287            if (fEntityReader.lookingAtChar(qchar, true)) {
1288                if (dataok && offset - toCopy > 0)
1289                    fEntityReader.append(fLiteralData, toCopy, offset - toCopy);
1290                break;
1291            }
1292            if (fEntityReader.lookingAtChar((char)0x09, true)) {
1293                dataok = false;
1294                reportFatalXMLError(XMLMessages.MSG_PUBIDCHAR_ILLEGAL,
1295                                    XMLMessages.P12_INVALID_CHARACTER, "9");
1296                continue;
1297            }
1298            if (fEntityReader.lookingAtSpace(true)) {
1299                if (dataok && offset - toCopy > 0)
1300                    fEntityReader.append(fLiteralData, toCopy, offset - toCopy);
1301                while (true) {
1302                    if (fEntityReader.lookingAtChar((char)0x09, true)) {
1303                        dataok = false;
1304                        reportFatalXMLError(XMLMessages.MSG_PUBIDCHAR_ILLEGAL,
1305                                            XMLMessages.P12_INVALID_CHARACTER, "9");
1306                        break;
1307                    } else if (!fEntityReader.lookingAtSpace(true)) {
1308                        break;
1309                    }
1310                }
1311                if (fEntityReader.lookingAtChar(qchar, true))
1312                    break;
1313                if (dataok) {
1314                    fLiteralData.append(' ');
1315                    offset = fEntityReader.currentOffset();
1316                    toCopy = offset;
1317                }
1318                continue;
1319            }
1320            if (!fEntityReader.lookingAtValidChar(true)) {
1321                int invChar = fEntityReader.scanInvalidChar();
1322                if (fScannerState == SCANNER_STATE_END_OF_INPUT)
1323                    return false;
1324                dataok = false;
1325                if (invChar >= 0) {
1326                    reportFatalXMLError(XMLMessages.MSG_INVALID_CHAR_IN_PUBLICID,
1327                                        XMLMessages.P12_INVALID_CHARACTER,
1328                                        Integer.toHexString(invChar));
1329                }
1330            }
1331            if (dataok)
1332                offset = fEntityReader.currentOffset();
1333        }
1334        if (dataok) {
1335            int dataLength = fLiteralData.length() - dataOffset;
1336            fPubidLiteral = fLiteralData.addString(dataOffset, dataLength);
1337            String JavaDoc publicId = fStringPool.toString(fPubidLiteral);
1338            int invCharIndex = validPublicId(publicId);
1339            if (invCharIndex >= 0) {
1340                reportFatalXMLError(XMLMessages.MSG_PUBIDCHAR_ILLEGAL,
1341                                    XMLMessages.P12_INVALID_CHARACTER,
1342                                    Integer.toHexString(publicId.charAt(invCharIndex)));
1343                return false;
1344            }
1345        }
1346        restoreScannerState(prevState);
1347        return dataok;
1348    }
1349    //
1350
// [??] intSubsetDecl = '[' (markupdecl | PEReference | S)* ']'
1351
//
1352
// [31] extSubsetDecl ::= ( markupdecl | conditionalSect | PEReference | S )*
1353
// [62] includeSect ::= '<![' S? 'INCLUDE' S? '[' extSubsetDecl ']]>'
1354
//
1355
// [29] markupdecl ::= elementdecl | AttlistDecl | EntityDecl
1356
// | NotationDecl | PI | Comment
1357
//
1358
// [45] elementdecl ::= '<!ELEMENT' S Name S contentspec S? '>'
1359
//
1360
// [52] AttlistDecl ::= '<!ATTLIST' S Name AttDef* S? '>'
1361
//
1362
// [70] EntityDecl ::= GEDecl | PEDecl
1363
// [71] GEDecl ::= '<!ENTITY' S Name S EntityDef S? '>'
1364
// [72] PEDecl ::= '<!ENTITY' S '%' S Name S PEDef S? '>'
1365
//
1366
// [82] NotationDecl ::= '<!NOTATION' S Name S (ExternalID | PublicID) S? '>'
1367
//
1368
// [16] PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'
1369
//
1370
// [15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
1371
//
1372
// [61] conditionalSect ::= includeSect | ignoreSect
1373
// [62] includeSect ::= '<![' S? 'INCLUDE' S? '[' extSubsetDecl ']]>'
1374
// [63] ignoreSect ::= '<![' S? 'IGNORE' S? '[' ignoreSectContents* ']]>'
1375
// [64] ignoreSectContents ::= Ignore ('<![' ignoreSectContents ']]>' Ignore)*
1376
// [65] Ignore ::= Char* - (Char* ('<![' | ']]>') Char*)
1377
//
1378
/**
1379     * Scan markup declarations
1380     *
1381     * @param extSubset true if the scanner is scanning an external subset, false
1382     * if it is scanning an internal subset
1383     * @exception java.lang.Exception
1384     */

1385    public void scanDecls(boolean extSubset) throws Exception JavaDoc
1386    {
1387        int subsetOffset = fEntityReader.currentOffset();
1388        if (extSubset)
1389            fExternalSubsetReader = fReaderId;
1390        fIncludeSectDepth = 0;
1391        boolean parseTextDecl = extSubset;
1392        int prevState = setScannerState(SCANNER_STATE_MARKUP_DECL);
1393        while (fScannerState == SCANNER_STATE_MARKUP_DECL) {
1394
1395            boolean newParseTextDecl = false;
1396            if (fEntityReader.lookingAtChar(']', false) &&
1397                !getReadingExternalEntity()) {
1398                int subsetLength = fEntityReader.currentOffset() - subsetOffset;
1399                int internalSubset = fEntityReader.addString(subsetOffset, subsetLength);
1400                fDTDGrammar.internalSubset(internalSubset);
1401                if (fDTDHandler != null) {
1402                    fDTDHandler.internalSubset(internalSubset);
1403                }
1404                fEntityReader.lookingAtChar(']', true);
1405                restoreScannerState(prevState);
1406                return;
1407            }
1408            if (fEntityReader.lookingAtChar('<', true)) {
1409                int olddepth = markupDepth();
1410                increaseMarkupDepth();
1411                if (fEntityReader.lookingAtChar('!', true)) {
1412                    if (fEntityReader.lookingAtChar('-', true)) {
1413                        if (fEntityReader.lookingAtChar('-', true)) {
1414                            scanComment();
1415                        } else {
1416                            abortMarkup(XMLMessages.MSG_MARKUP_NOT_RECOGNIZED_IN_DTD,
1417                                        XMLMessages.P29_NOT_RECOGNIZED);
1418                        }
1419                    } else if (fEntityReader.lookingAtChar('[', true) && getReadingExternalEntity()) {
1420                        checkForPEReference(false);
1421                        if (fEntityReader.skippedString(include_string)) {
1422                            checkForPEReference(false);
1423                            if (!fEntityReader.lookingAtChar('[', true)) {
1424                                abortMarkup(XMLMessages.MSG_MARKUP_NOT_RECOGNIZED_IN_DTD,
1425                                            XMLMessages.P29_NOT_RECOGNIZED);
1426                            } else {
1427                                fIncludeSectDepth++;
1428                            }
1429                        } else if (fEntityReader.skippedString(ignore_string)) {
1430                            checkForPEReference(false);
1431                            if (!fEntityReader.lookingAtChar('[', true)) {
1432                                abortMarkup(XMLMessages.MSG_MARKUP_NOT_RECOGNIZED_IN_DTD,
1433                                            XMLMessages.P29_NOT_RECOGNIZED);
1434                            } else
1435                                scanIgnoreSectContents();
1436                        } else {
1437                            abortMarkup(XMLMessages.MSG_MARKUP_NOT_RECOGNIZED_IN_DTD,
1438                                        XMLMessages.P29_NOT_RECOGNIZED);
1439                        }
1440                    } else if (fEntityReader.skippedString(element_string)) {
1441                        scanElementDecl();
1442                    }
1443                    else if (fEntityReader.skippedString(attlist_string))
1444                        scanAttlistDecl();
1445                    else if (fEntityReader.skippedString(entity_string))
1446                        scanEntityDecl();
1447                    else if (fEntityReader.skippedString(notation_string))
1448                        scanNotationDecl();
1449                    else {
1450                        abortMarkup(XMLMessages.MSG_MARKUP_NOT_RECOGNIZED_IN_DTD,
1451                                    XMLMessages.P29_NOT_RECOGNIZED);
1452                    }
1453                } else if (fEntityReader.lookingAtChar('?', true)) {
1454                    int piTarget = fEntityReader.scanName(' ');
1455                    if (piTarget == -1) {
1456                        abortMarkup(XMLMessages.MSG_PITARGET_REQUIRED,
1457                                    XMLMessages.P16_REQUIRED);
1458                    } else if ("xml".equals(fStringPool.toString(piTarget))) {
1459                        if (fEntityReader.lookingAtSpace(true)) {
1460                            if (parseTextDecl) { // a TextDecl looks like a PI with the target 'xml'
1461
scanTextDecl();
1462                            } else {
1463                                abortMarkup(XMLMessages.MSG_TEXTDECL_MUST_BE_FIRST,
1464                                            XMLMessages.P30_TEXTDECL_MUST_BE_FIRST);
1465                            }
1466                        } else { // a PI target matching 'xml'
1467
abortMarkup(XMLMessages.MSG_RESERVED_PITARGET,
1468                                        XMLMessages.P17_RESERVED_PITARGET);
1469                        }
1470                    } else // PI
1471
scanPI(piTarget);
1472                } else {
1473                    abortMarkup(XMLMessages.MSG_MARKUP_NOT_RECOGNIZED_IN_DTD,
1474                                XMLMessages.P29_NOT_RECOGNIZED);
1475                }
1476            } else if (fEntityReader.lookingAtSpace(true)) {
1477                fEntityReader.skipPastSpaces();
1478            } else if (fEntityReader.lookingAtChar('%', true)) {
1479                //
1480
// [69] PEReference ::= '%' Name ';'
1481
//
1482
int nameOffset = fEntityReader.currentOffset();
1483                fEntityReader.skipPastName(';');
1484                int nameLength = fEntityReader.currentOffset() - nameOffset;
1485                if (nameLength == 0) {
1486                    reportFatalXMLError(XMLMessages.MSG_NAME_REQUIRED_IN_PEREFERENCE,
1487                                        XMLMessages.P69_NAME_REQUIRED);
1488                } else if (!fEntityReader.lookingAtChar(';', true)) {
1489                    reportFatalXMLError(XMLMessages.MSG_SEMICOLON_REQUIRED_IN_PEREFERENCE,
1490                                        XMLMessages.P69_SEMICOLON_REQUIRED,
1491                                        fEntityReader.addString(nameOffset, nameLength));
1492                } else {
1493                    int peNameIndex = fEntityReader.addSymbol(nameOffset, nameLength);
1494                    newParseTextDecl = fEntityHandler.startReadingFromEntity(peNameIndex, markupDepth(), XMLEntityHandler.ENTITYREF_IN_DTD_AS_MARKUP);
1495                }
1496            } else if (fIncludeSectDepth > 0 && fEntityReader.lookingAtChar(']', true)) {
1497                if (!fEntityReader.lookingAtChar(']', true) || !fEntityReader.lookingAtChar('>', true)) {
1498                    abortMarkup(XMLMessages.MSG_INCLUDESECT_UNTERMINATED,
1499                                XMLMessages.P62_UNTERMINATED);
1500                } else
1501                    decreaseMarkupDepth();
1502                fIncludeSectDepth--;
1503            } else {
1504                if (!fEntityReader.lookingAtValidChar(false)) {
1505                    int invChar = fEntityReader.scanInvalidChar();
1506                    if (fScannerState == SCANNER_STATE_END_OF_INPUT)
1507                        break;
1508                    if (invChar >= 0) {
1509                        if (!extSubset) {
1510                            reportFatalXMLError(XMLMessages.MSG_INVALID_CHAR_IN_INTERNAL_SUBSET,
1511                                                XMLMessages.P28_INVALID_CHARACTER,
1512                                                Integer.toHexString(invChar));
1513                        } else {
1514                            reportFatalXMLError(XMLMessages.MSG_INVALID_CHAR_IN_EXTERNAL_SUBSET,
1515                                                XMLMessages.P30_INVALID_CHARACTER,
1516                                                Integer.toHexString(invChar));
1517                        }
1518                    }
1519                } else {
1520                    reportFatalXMLError(XMLMessages.MSG_MARKUP_NOT_RECOGNIZED_IN_DTD,
1521                                        XMLMessages.P29_NOT_RECOGNIZED);
1522                    fEntityReader.lookingAtValidChar(true);
1523                }
1524            }
1525            parseTextDecl = newParseTextDecl;
1526        }
1527        if (extSubset) {
1528
1529            ((DefaultEntityHandler) fEntityHandler).stopReadingFromExternalSubset();
1530
1531            fDTDGrammar.stopReadingFromExternalSubset();
1532            fDTDGrammar.callEndDTD();
1533            if (fDTDHandler != null) {
1534                fDTDHandler.endDTD();
1535            }
1536            // REVISIT: What should the namspace URI of a DTD be?
1537
fGrammarResolver.putGrammar("", fDTDGrammar);
1538        }
1539    }
1540    //
1541
// [64] ignoreSectContents ::= Ignore ('<![' ignoreSectContents ']]>' Ignore)*
1542
// [65] Ignore ::= Char* - (Char* ('<![' | ']]>') Char*)
1543
//
1544
private void scanIgnoreSectContents() throws Exception JavaDoc
1545    {
1546        int initialDepth = ++fIncludeSectDepth;
1547        while (true) {
1548            if (fEntityReader.lookingAtChar('<', true)) {
1549                //
1550
// These tests are split so that we handle cases like
1551
// '<<![' and '<!<![' which we might otherwise miss.
1552
//
1553
if (fEntityReader.lookingAtChar('!', true) && fEntityReader.lookingAtChar('[', true))
1554                    fIncludeSectDepth++;
1555            } else if (fEntityReader.lookingAtChar(']', true)) {
1556                //
1557
// The same thing goes for ']<![' and '<]]>', etc.
1558
//
1559
if (fEntityReader.lookingAtChar(']', true)) {
1560                    while (fEntityReader.lookingAtChar(']', true)) {
1561                        /* empty loop body */
1562                    }
1563                    if (fEntityReader.lookingAtChar('>', true)) {
1564                        if (fIncludeSectDepth-- == initialDepth) {
1565                            decreaseMarkupDepth();
1566                            return;
1567                        }
1568                    }
1569                }
1570            } else if (!fEntityReader.lookingAtValidChar(true)) {
1571                int invChar = fEntityReader.scanInvalidChar();
1572                if (fScannerState == SCANNER_STATE_END_OF_INPUT)
1573                    return;
1574                if (invChar >= 0) {
1575                    reportFatalXMLError(XMLMessages.MSG_INVALID_CHAR_IN_IGNORESECT,
1576                                        XMLMessages.P65_INVALID_CHARACTER,
1577                                        Integer.toHexString(invChar));
1578                }
1579            }
1580        }
1581    }
1582    //
1583
// From the standard:
1584
//
1585
// [77] TextDecl ::= '<?xml' VersionInfo? EncodingDecl S? '?>'
1586
// [24] VersionInfo ::= S 'version' Eq (' VersionNum ' | " VersionNum ")
1587
// [80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' | "'" EncName "'" )
1588
// [81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*
1589
//
1590
private void scanTextDecl() throws Exception JavaDoc {
1591        int version = -1;
1592        int encoding = -1;
1593        final int TEXTDECL_START = 0;
1594        final int TEXTDECL_VERSION = 1;
1595        final int TEXTDECL_ENCODING = 2;
1596        final int TEXTDECL_FINISHED = 3;
1597        int prevState = setScannerState(SCANNER_STATE_TEXTDECL);
1598        int state = TEXTDECL_START;
1599        do {
1600            fEntityReader.skipPastSpaces();
1601            int offset = fEntityReader.currentOffset();
1602            if (state == TEXTDECL_START && fEntityReader.skippedString(version_string)) {
1603                state = TEXTDECL_VERSION;
1604            } else if (fEntityReader.skippedString(encoding_string)) {
1605                state = TEXTDECL_ENCODING;
1606            } else {
1607                abortMarkup(XMLMessages.MSG_ENCODINGDECL_REQUIRED,
1608                            XMLMessages.P77_ENCODINGDECL_REQUIRED);
1609                restoreScannerState(prevState);
1610                return;
1611            }
1612            int length = fEntityReader.currentOffset() - offset;
1613            fEntityReader.skipPastSpaces();
1614            if (!fEntityReader.lookingAtChar('=', true)) {
1615                int minorCode = state == TEXTDECL_VERSION ?
1616                                XMLMessages.P24_EQ_REQUIRED :
1617                                XMLMessages.P80_EQ_REQUIRED;
1618                abortMarkup(XMLMessages.MSG_EQ_REQUIRED_IN_TEXTDECL, minorCode,
1619                            fEntityReader.addString(offset, length));
1620                restoreScannerState(prevState);
1621                return;
1622            }
1623            fEntityReader.skipPastSpaces();
1624            int result = fEntityReader.scanStringLiteral();
1625            switch (result) {
1626            case XMLEntityHandler.STRINGLIT_RESULT_QUOTE_REQUIRED:
1627            {
1628                int minorCode = state == TEXTDECL_VERSION ?
1629                                XMLMessages.P24_QUOTE_REQUIRED :
1630                                XMLMessages.P80_QUOTE_REQUIRED;
1631                abortMarkup(XMLMessages.MSG_QUOTE_REQUIRED_IN_TEXTDECL, minorCode,
1632                            fEntityReader.addString(offset, length));
1633                restoreScannerState(prevState);
1634                return;
1635            }
1636            case XMLEntityHandler.STRINGLIT_RESULT_INVALID_CHAR:
1637                int invChar = fEntityReader.scanInvalidChar();
1638                if (fScannerState != SCANNER_STATE_END_OF_INPUT) {
1639                    if (invChar >= 0) {
1640                        int minorCode = state == TEXTDECL_VERSION ?
1641                                        XMLMessages.P26_INVALID_CHARACTER :
1642                                        XMLMessages.P81_INVALID_CHARACTER;
1643                        reportFatalXMLError(XMLMessages.MSG_INVALID_CHAR_IN_TEXTDECL, minorCode,
1644                                            Integer.toHexString(invChar));
1645                    }
1646                    skipPastEndOfCurrentMarkup();
1647                    restoreScannerState(prevState);
1648                }
1649                return;
1650            default:
1651                break;
1652            }
1653            switch (state) {
1654            case TEXTDECL_VERSION:
1655                //
1656
// version="..."
1657
//
1658
version = result;
1659                String JavaDoc versionString = fStringPool.toString(version);
1660                if (!"1.0".equals(versionString)) {
1661                    if (!validVersionNum(versionString)) {
1662                        abortMarkup(XMLMessages.MSG_VERSIONINFO_INVALID,
1663                                    XMLMessages.P26_INVALID_VALUE,
1664                                    versionString);
1665                        restoreScannerState(prevState);
1666                        return;
1667                    }
1668                    // NOTE: RECOVERABLE ERROR
1669
Object JavaDoc[] args = { versionString };
1670                    fErrorReporter.reportError(fErrorReporter.getLocator(),
1671                                               XMLMessages.XML_DOMAIN,
1672                                               XMLMessages.MSG_VERSION_NOT_SUPPORTED,
1673                                               XMLMessages.P26_NOT_SUPPORTED,
1674                                               args,
1675                                               XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
1676                    // REVISIT - hope it is a compatible version...
1677
// skipPastEndOfCurrentMarkup();
1678
// return;
1679
}
1680                if (!fEntityReader.lookingAtSpace(true)) {
1681                    abortMarkup(XMLMessages.MSG_SPACE_REQUIRED_IN_TEXTDECL,
1682                                XMLMessages.P80_WHITESPACE_REQUIRED);
1683                    restoreScannerState(prevState);
1684                    return;
1685                }
1686                break;
1687            case TEXTDECL_ENCODING:
1688                //
1689
// encoding = "..."
1690
//
1691
encoding = result;
1692                String JavaDoc encodingString = fStringPool.toString(encoding);
1693                if (!validEncName(encodingString)) {
1694                    abortMarkup(XMLMessages.MSG_ENCODINGDECL_INVALID,
1695                                XMLMessages.P81_INVALID_VALUE,
1696                                encodingString);
1697                    restoreScannerState(prevState);
1698                    return;
1699                }
1700                fEntityReader.skipPastSpaces();
1701                state = TEXTDECL_FINISHED;
1702                break;
1703            }
1704        } while (state != TEXTDECL_FINISHED);
1705        if (!fEntityReader.lookingAtChar('?', true) || !fEntityReader.lookingAtChar('>', true)) {
1706            abortMarkup(XMLMessages.MSG_TEXTDECL_UNTERMINATED,
1707                        XMLMessages.P77_UNTERMINATED);
1708            restoreScannerState(prevState);
1709            return;
1710        }
1711        decreaseMarkupDepth();
1712        fDTDGrammar.callTextDecl(version, encoding);
1713        if (fDTDHandler != null) {
1714            fDTDHandler.textDecl(version, encoding);
1715        }
1716        restoreScannerState(prevState);
1717    }
1718
1719    private QName fElementDeclQName = new QName();
1720
1721    /**
1722     * Scans an element declaration.
1723     * <pre>
1724     * [45] elementdecl ::= '&lt;!ELEMENT' S Name S contentspec S? '&gt;'
1725     * </pre>
1726     */

1727    private void scanElementDecl() throws Exception JavaDoc {
1728        
1729        if (!checkForPEReference(true)) {
1730            abortMarkup(XMLMessages.MSG_SPACE_REQUIRED_BEFORE_ELEMENT_TYPE_IN_ELEMENTDECL,
1731                        XMLMessages.P45_SPACE_REQUIRED);
1732            return;
1733        }
1734        checkForElementTypeWithPEReference(fEntityReader, ' ', fElementQName);
1735        if (fElementQName.rawname == -1) {
1736            abortMarkup(XMLMessages.MSG_ELEMENT_TYPE_REQUIRED_IN_ELEMENTDECL,
1737                        XMLMessages.P45_ELEMENT_TYPE_REQUIRED);
1738            return;
1739        }
1740        if (fDTDHandler != null) {
1741            fElementDeclQName.setValues(fElementQName);
1742        }
1743        if (!checkForPEReference(true)) {
1744            abortMarkup(XMLMessages.MSG_SPACE_REQUIRED_BEFORE_CONTENTSPEC_IN_ELEMENTDECL,
1745                        XMLMessages.P45_SPACE_REQUIRED,
1746                        fElementQName.rawname);
1747            return;
1748        }
1749        int contentSpecType = -1;
1750        int contentSpec = -1;
1751        if (fEntityReader.skippedString(empty_string)) {
1752            contentSpecType = XMLElementDecl.TYPE_EMPTY;
1753        } else if (fEntityReader.skippedString(any_string)) {
1754            contentSpecType = XMLElementDecl.TYPE_ANY;
1755        } else if (!fEntityReader.lookingAtChar('(', true)) {
1756            abortMarkup(XMLMessages.MSG_CONTENTSPEC_REQUIRED_IN_ELEMENTDECL,
1757                        XMLMessages.P45_CONTENTSPEC_REQUIRED,
1758                        fElementQName.rawname);
1759            return;
1760        } else {
1761            int contentSpecReader = fReaderId;
1762            int contentSpecReaderDepth = fEntityHandler.getReaderDepth();
1763            int prevState = setScannerState(SCANNER_STATE_CONTENTSPEC);
1764            int oldDepth = parenDepth();
1765            fEntityHandler.setReaderDepth(oldDepth);
1766            increaseParenDepth();
1767            checkForPEReference(false);
1768            boolean skippedPCDATA = fEntityReader.skippedString(pcdata_string);
1769            if (skippedPCDATA) {
1770                contentSpecType = XMLElementDecl.TYPE_MIXED_SIMPLE;
1771                // REVISIT: Validation. Should we pass in QName?
1772
contentSpec = scanMixed(fElementQName);
1773            } else {
1774                contentSpecType = XMLElementDecl.TYPE_CHILDREN;
1775                // REVISIT: Validation. Should we pass in QName?
1776
contentSpec = scanChildren(fElementQName);
1777            }
1778            boolean success = contentSpec != -1;
1779            restoreScannerState(prevState);
1780            fEntityHandler.setReaderDepth(contentSpecReaderDepth);
1781            if (!success) {
1782                setParenDepth(oldDepth);
1783                skipPastEndOfCurrentMarkup();
1784                return;
1785            } else {
1786                if (parenDepth() != oldDepth) // REVISIT - should not be needed
1787
// System.out.println("nesting depth mismatch");
1788
;
1789            }
1790        }
1791        checkForPEReference(false);
1792        if (!fEntityReader.lookingAtChar('>', true)) {
1793            abortMarkup(XMLMessages.MSG_ELEMENTDECL_UNTERMINATED,
1794                        XMLMessages.P45_UNTERMINATED,
1795                        fElementQName.rawname);
1796            return;
1797        }
1798        decreaseMarkupDepth();
1799        int elementIndex = fDTDGrammar.getElementDeclIndex(fElementQName, -1);
1800        boolean elementDeclIsExternal = getReadingExternalEntity();
1801        if (elementIndex == -1) {
1802            elementIndex = fDTDGrammar.addElementDecl(fElementQName, contentSpecType, contentSpec, elementDeclIsExternal);
1803            //System.out.println("XMLDTDScanner#scanElementDecl->DTDGrammar#addElementDecl: "+elementIndex+" ("+fElementQName.localpart+","+fStringPool.toString(fElementQName.localpart)+')');
1804
}
1805        else {
1806            //now check if we already add this element Decl by foward reference
1807
fDTDGrammar.getElementDecl(elementIndex, fTempElementDecl);
1808            if (fTempElementDecl.type == -1) {
1809                fTempElementDecl.type = contentSpecType;
1810                fTempElementDecl.contentSpecIndex = contentSpec;
1811                fDTDGrammar.setElementDeclDTD(elementIndex, fTempElementDecl);
1812                fDTDGrammar.setElementDeclIsExternal(elementIndex, elementDeclIsExternal);
1813            }
1814            else {
1815                //REVISIT, valiate VC duplicate element type.
1816
if ( fValidationEnabled )
1817                    //&&
1818
// (elemenetDeclIsExternal==fDTDGrammar.getElementDeclIsExternal(elementIndex)
1819
{
1820
1821                    reportRecoverableXMLError(
1822                        XMLMessages.MSG_ELEMENT_ALREADY_DECLARED,
1823                        XMLMessages.VC_UNIQUE_ELEMENT_TYPE_DECLARATION,
1824                        fStringPool.toString(fElementQName.rawname)
1825                        );
1826                }
1827            }
1828        }
1829        if (fDTDHandler != null) {
1830            fDTDGrammar.getElementDecl(elementIndex, fTempElementDecl);
1831            fDTDHandler.elementDecl(fElementDeclQName, contentSpecType, contentSpec, fDTDGrammar);
1832        }
1833
1834    } // scanElementDecl()
1835

1836    
1837    /**
1838     * Scans mixed content model. Called after scanning past '(' S? '#PCDATA'
1839     * <pre>
1840     * [51] Mixed ::= '(' S? '#PCDATA' (S? '|' S? Name)* S? ')*' | '(' S? '#PCDATA' S? ')'
1841     * </pre>
1842     */

1843    private int scanMixed(QName element) throws Exception JavaDoc {
1844
1845        int valueIndex = -1; // -1 is special value for #PCDATA
1846
int prevNodeIndex = -1;
1847        boolean starRequired = false;
1848        int[] valueSeen = new int[32];
1849        int valueCount = 0;
1850        boolean dupAttrType = false;
1851        int nodeIndex = -1;
1852
1853        while (true) {
1854            if (fValidationEnabled) {
1855                for (int i=0; i<valueCount;i++) {
1856                    if ( valueSeen[i] == valueIndex) {
1857                        dupAttrType = true;
1858                        break;
1859                    }
1860                }
1861            }
1862            if (dupAttrType && fValidationEnabled) {
1863                reportRecoverableXMLError(XMLMessages.MSG_DUPLICATE_TYPE_IN_MIXED_CONTENT,
1864                                          XMLMessages.VC_NO_DUPLICATE_TYPES,
1865                                          valueIndex);
1866                dupAttrType = false;
1867
1868            }
1869            else {
1870                try {
1871                    valueSeen[valueCount] = valueIndex;
1872                }
1873                catch (ArrayIndexOutOfBoundsException JavaDoc ae) {
1874                    int[] newArray = new int[valueSeen.length*2];
1875                    System.arraycopy(valueSeen,0,newArray,0,valueSeen.length);
1876                    valueSeen = newArray;
1877                    valueSeen[valueCount] = valueIndex;
1878                }
1879                valueCount++;
1880
1881                nodeIndex = fDTDGrammar.addUniqueLeafNode(valueIndex);
1882            }
1883
1884            checkForPEReference(false);
1885            if (!fEntityReader.lookingAtChar('|', true)) {
1886                if (!fEntityReader.lookingAtChar(')', true)) {
1887                    reportFatalXMLError(XMLMessages.MSG_CLOSE_PAREN_REQUIRED_IN_MIXED,
1888                                        XMLMessages.P51_CLOSE_PAREN_REQUIRED,
1889                                        element.rawname);
1890                    return -1;
1891                }
1892                decreaseParenDepth();
1893                if (nodeIndex == -1) {
1894                    nodeIndex = prevNodeIndex;
1895                } else if (prevNodeIndex != -1) {
1896                    nodeIndex = fDTDGrammar.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_CHOICE, prevNodeIndex, nodeIndex);
1897                }
1898                if (fEntityReader.lookingAtChar('*', true)) {
1899                    nodeIndex = fDTDGrammar.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE, nodeIndex);
1900                } else if (starRequired) {
1901                    reportFatalXMLError(XMLMessages.MSG_MIXED_CONTENT_UNTERMINATED,
1902                                        XMLMessages.P51_UNTERMINATED,
1903                                        fStringPool.toString(element.rawname),
1904                                        fDTDGrammar.getContentSpecNodeAsString(nodeIndex));
1905                    return -1;
1906                }
1907                return nodeIndex;
1908            }
1909            if (nodeIndex != -1) {
1910                if (prevNodeIndex != -1) {
1911                    nodeIndex = fDTDGrammar.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_CHOICE, prevNodeIndex, nodeIndex);
1912                }
1913                prevNodeIndex = nodeIndex;
1914            }
1915            starRequired = true;
1916            checkForPEReference(false);
1917            checkForElementTypeWithPEReference(fEntityReader, ')', fElementRefQName);
1918            valueIndex = fElementRefQName.rawname;
1919            if (valueIndex == -1) {
1920                reportFatalXMLError(XMLMessages.MSG_ELEMENT_TYPE_REQUIRED_IN_MIXED_CONTENT,
1921                                    XMLMessages.P51_ELEMENT_TYPE_REQUIRED,
1922                                    element.rawname);
1923                return -1;
1924            }
1925        }
1926
1927    } // scanMixed(QName):int
1928

1929    /**
1930     * Scans a children content model.
1931     * <pre>
1932     * [47] children ::= (choice | seq) ('?' | '*' | '+')?
1933     * [49] choice ::= '(' S? cp ( S? '|' S? cp )* S? ')'
1934     * [50] seq ::= '(' S? cp ( S? ',' S? cp )* S? ')'
1935     * [48] cp ::= (Name | choice | seq) ('?' | '*' | '+')?
1936     * </pre>
1937     */

1938    private int scanChildren(QName element) throws Exception JavaDoc {
1939        
1940        int depth = 1;
1941        initializeContentModelStack(depth);
1942        while (true) {
1943            if (fEntityReader.lookingAtChar('(', true)) {
1944                increaseParenDepth();
1945                checkForPEReference(false);
1946                depth++;
1947                initializeContentModelStack(depth);
1948                continue;
1949            }
1950            checkForElementTypeWithPEReference(fEntityReader, ')', fElementRefQName);
1951            int valueIndex = fElementRefQName.rawname;
1952            if (valueIndex == -1) {
1953                reportFatalXMLError(XMLMessages.MSG_OPEN_PAREN_OR_ELEMENT_TYPE_REQUIRED_IN_CHILDREN,
1954                                    XMLMessages.P47_OPEN_PAREN_OR_ELEMENT_TYPE_REQUIRED,
1955                                    element.rawname);
1956                return -1;
1957            }
1958            fNodeIndexStack[depth] = fDTDGrammar.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_LEAF, valueIndex);
1959            if (fEntityReader.lookingAtChar('?', true)) {
1960                fNodeIndexStack[depth] = fDTDGrammar.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE, fNodeIndexStack[depth]);
1961            } else if (fEntityReader.lookingAtChar('*', true)) {
1962                fNodeIndexStack[depth] = fDTDGrammar.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE, fNodeIndexStack[depth]);
1963            } else if (fEntityReader.lookingAtChar('+', true)) {
1964                fNodeIndexStack[depth] = fDTDGrammar.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE, fNodeIndexStack[depth]);
1965            }
1966            while (true) {
1967                checkForPEReference(false);
1968                if (fOpStack[depth] != XMLContentSpec.CONTENTSPECNODE_SEQ && fEntityReader.lookingAtChar('|', true)) {
1969                    if (fPrevNodeIndexStack[depth] != -1) {
1970                        fNodeIndexStack[depth] = fDTDGrammar.addContentSpecNode(fOpStack[depth], fPrevNodeIndexStack[depth], fNodeIndexStack[depth]);
1971                    }
1972                    fPrevNodeIndexStack[depth] = fNodeIndexStack[depth];
1973                    fOpStack[depth] = XMLContentSpec.CONTENTSPECNODE_CHOICE;
1974                    break;
1975                } else if (fOpStack[depth] != XMLContentSpec.CONTENTSPECNODE_CHOICE && fEntityReader.lookingAtChar(',', true)) {
1976                    if (fPrevNodeIndexStack[depth] != -1) {
1977                        fNodeIndexStack[depth] = fDTDGrammar.addContentSpecNode(fOpStack[depth], fPrevNodeIndexStack[depth], fNodeIndexStack[depth]);
1978                    }
1979                    fPrevNodeIndexStack[depth] = fNodeIndexStack[depth];
1980                    fOpStack[depth] = XMLContentSpec.CONTENTSPECNODE_SEQ;
1981                    break;
1982                } else {
1983                    if (!fEntityReader.lookingAtChar(')', true)) {
1984                        reportFatalXMLError(XMLMessages.MSG_CLOSE_PAREN_REQUIRED_IN_CHILDREN,
1985                                            XMLMessages.P47_CLOSE_PAREN_REQUIRED,
1986                                            element.rawname);
1987                    }
1988                    decreaseParenDepth();
1989                    if (fPrevNodeIndexStack[depth] != -1) {
1990                        fNodeIndexStack[depth] = fDTDGrammar.addContentSpecNode(fOpStack[depth], fPrevNodeIndexStack[depth], fNodeIndexStack[depth]);
1991                    }
1992                    int nodeIndex = fNodeIndexStack[depth--];
1993                    fNodeIndexStack[depth] = nodeIndex;
1994                    if (fEntityReader.lookingAtChar('?', true)) {
1995                        fNodeIndexStack[depth] = fDTDGrammar.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE, fNodeIndexStack[depth]);
1996                    } else if (fEntityReader.lookingAtChar('*', true)) {
1997                        fNodeIndexStack[depth] = fDTDGrammar.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE, fNodeIndexStack[depth]);
1998                    } else if (fEntityReader.lookingAtChar('+', true)) {
1999                        fNodeIndexStack[depth] = fDTDGrammar.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE, fNodeIndexStack[depth]);
2000                    }
2001                    if (depth == 0) {
2002                        return fNodeIndexStack[0];
2003                    }
2004                }
2005            }
2006            checkForPEReference(false);
2007        }
2008
2009    } // scanChildren(QName):int
2010

2011    //
2012
// [52] AttlistDecl ::= '<!ATTLIST' S Name AttDef* S? '>'
2013
// [53] AttDef ::= S Name S AttType S DefaultDecl
2014
// [60] DefaultDecl ::= '#REQUIRED' | '#IMPLIED' | (('#FIXED' S)? AttValue)
2015
//
2016
private void scanAttlistDecl() throws Exception JavaDoc
2017    {
2018        if (!checkForPEReference(true)) {
2019            abortMarkup(XMLMessages.MSG_SPACE_REQUIRED_BEFORE_ELEMENT_TYPE_IN_ATTLISTDECL,
2020                        XMLMessages.P52_SPACE_REQUIRED);
2021            return;
2022        }
2023        checkForElementTypeWithPEReference(fEntityReader, ' ', fElementQName);
2024        int elementTypeIndex = fElementQName.rawname;
2025        if (elementTypeIndex == -1) {
2026            abortMarkup(XMLMessages.MSG_ELEMENT_TYPE_REQUIRED_IN_ATTLISTDECL,
2027                        XMLMessages.P52_ELEMENT_TYPE_REQUIRED);
2028            return;
2029        }
2030        int elementIndex = fDTDGrammar.getElementDeclIndex(fElementQName, -1);
2031        if (elementIndex == -1) {
2032            elementIndex = fDTDGrammar.addElementDecl(fElementQName);
2033            //System.out.println("XMLDTDScanner#scanAttListDecl->DTDGrammar#addElementDecl: "+elementIndex+" ("+fElementQName.localpart+","+fStringPool.toString(fElementQName.localpart)+')');
2034
}
2035        boolean sawSpace = checkForPEReference(true);
2036        if (fEntityReader.lookingAtChar('>', true)) {
2037            decreaseMarkupDepth();
2038            return;
2039        }
2040        // REVISIT - review this code...
2041
if (!sawSpace) {
2042            if (fEntityReader.lookingAtSpace(true)) {
2043                fEntityReader.skipPastSpaces();
2044            } else
2045                reportFatalXMLError(XMLMessages.MSG_SPACE_REQUIRED_BEFORE_ATTRIBUTE_NAME_IN_ATTDEF,
2046                                    XMLMessages.P53_SPACE_REQUIRED);
2047        } else {
2048            if (fEntityReader.lookingAtSpace(true)) {
2049                fEntityReader.skipPastSpaces();
2050            }
2051        }
2052        if (fEntityReader.lookingAtChar('>', true)) {
2053            decreaseMarkupDepth();
2054            return;
2055        }
2056        while (true) {
2057            checkForAttributeNameWithPEReference(fEntityReader, ' ', fAttributeQName);
2058            int attDefName = fAttributeQName.rawname;
2059            if (attDefName == -1) {
2060                abortMarkup(XMLMessages.MSG_ATTRIBUTE_NAME_REQUIRED_IN_ATTDEF,
2061                            XMLMessages.P53_NAME_REQUIRED,
2062                            fElementQName.rawname);
2063                return;
2064            }
2065            if (!checkForPEReference(true)) {
2066                abortMarkup(XMLMessages.MSG_SPACE_REQUIRED_BEFORE_ATTTYPE_IN_ATTDEF,
2067                            XMLMessages.P53_SPACE_REQUIRED);
2068                return;
2069            }
2070            int attDefType = -1;
2071            boolean attDefList = false;
2072            int attDefEnumeration = -1;
2073            if (fEntityReader.skippedString(cdata_string)) {
2074                attDefType = XMLAttributeDecl.TYPE_CDATA;
2075            } else if (fEntityReader.skippedString(id_string)) {
2076                if (!fEntityReader.skippedString(ref_string)) {
2077                    attDefType = XMLAttributeDecl.TYPE_ID;
2078                } else if (!fEntityReader.lookingAtChar('S', true)) {
2079                    attDefType = XMLAttributeDecl.TYPE_IDREF;
2080                } else {
2081                    attDefType = XMLAttributeDecl.TYPE_IDREF;
2082                    attDefList = true;
2083                }
2084            } else if (fEntityReader.skippedString(entit_string)) {
2085                if (fEntityReader.lookingAtChar('Y', true)) {
2086                    attDefType = XMLAttributeDecl.TYPE_ENTITY;
2087                } else if (fEntityReader.skippedString(ies_string)) {
2088                    attDefType = XMLAttributeDecl.TYPE_ENTITY;
2089                    attDefList = true;
2090                } else {
2091                    abortMarkup(XMLMessages.MSG_ATTTYPE_REQUIRED_IN_ATTDEF,
2092                                XMLMessages.P53_ATTTYPE_REQUIRED,
2093                                elementTypeIndex, attDefName);
2094                    return;
2095                }
2096            } else if (fEntityReader.skippedString(nmtoken_string)) {
2097                if (fEntityReader.lookingAtChar('S', true)) {
2098                    attDefType = XMLAttributeDecl.TYPE_NMTOKEN;
2099                    attDefList = true;
2100                } else {
2101                    attDefType = XMLAttributeDecl.TYPE_NMTOKEN;
2102                }
2103            } else if (fEntityReader.skippedString(notation_string)) {
2104                if (!checkForPEReference(true)) {
2105                    abortMarkup(XMLMessages.MSG_SPACE_REQUIRED_AFTER_NOTATION_IN_NOTATIONTYPE,
2106                                XMLMessages.P58_SPACE_REQUIRED,
2107                                elementTypeIndex, attDefName);
2108                    return;
2109                }
2110                if (!fEntityReader.lookingAtChar('(', true)) {
2111                    abortMarkup(XMLMessages.MSG_OPEN_PAREN_REQUIRED_IN_NOTATIONTYPE,
2112                                XMLMessages.P58_OPEN_PAREN_REQUIRED,
2113                                elementTypeIndex, attDefName);
2114                    return;
2115                }
2116                increaseParenDepth();
2117                attDefType = XMLAttributeDecl.TYPE_NOTATION;
2118                attDefEnumeration = scanEnumeration(elementTypeIndex, attDefName, true);
2119                if (attDefEnumeration == -1) {
2120                    skipPastEndOfCurrentMarkup();
2121                    return;
2122                }
2123            } else if (fEntityReader.lookingAtChar('(', true)) {
2124                increaseParenDepth();
2125                attDefType = XMLAttributeDecl.TYPE_ENUMERATION;
2126                attDefEnumeration = scanEnumeration(elementTypeIndex, attDefName, false);
2127                if (attDefEnumeration == -1) {
2128                    skipPastEndOfCurrentMarkup();
2129                    return;
2130                }
2131            } else {
2132                abortMarkup(XMLMessages.MSG_ATTTYPE_REQUIRED_IN_ATTDEF,
2133                            XMLMessages.P53_ATTTYPE_REQUIRED,
2134                            elementTypeIndex, attDefName);
2135                return;
2136            }
2137            if (!checkForPEReference(true)) {
2138                abortMarkup(XMLMessages.MSG_SPACE_REQUIRED_BEFORE_DEFAULTDECL_IN_ATTDEF,
2139                            XMLMessages.P53_SPACE_REQUIRED,
2140                            elementTypeIndex, attDefName);
2141                return;
2142            }
2143            int attDefDefaultType = -1;
2144            int attDefDefaultValue = -1;
2145            if (fEntityReader.skippedString(required_string)) {
2146                attDefDefaultType = XMLAttributeDecl.DEFAULT_TYPE_REQUIRED;
2147            } else if (fEntityReader.skippedString(implied_string)) {
2148                attDefDefaultType = XMLAttributeDecl.DEFAULT_TYPE_IMPLIED;
2149            } else {
2150                if (fEntityReader.skippedString(fixed_string)) {
2151                    if (!checkForPEReference(true)) {
2152                        abortMarkup(XMLMessages.MSG_SPACE_REQUIRED_AFTER_FIXED_IN_DEFAULTDECL,
2153                                    XMLMessages.P60_SPACE_REQUIRED,
2154                                    elementTypeIndex, attDefName);
2155                        return;
2156                    }
2157                    attDefDefaultType = XMLAttributeDecl.DEFAULT_TYPE_FIXED;
2158                } else
2159                    attDefDefaultType = XMLAttributeDecl.DEFAULT_TYPE_DEFAULT;
2160
2161                //fElementQName.setValues(-1, elementTypeIndex, elementTypeIndex);
2162

2163                // if attribute name has a prefix "xml", bind it to the XML Namespace.
2164
// since this is the only pre-defined namespace.
2165
/***
2166                if (fAttributeQName.prefix == fXMLSymbol) {
2167                    fAttributeQName.uri = fXMLNamespace;
2168                }
2169                else
2170                    fAttributeQName.setValues(-1, attDefName, attDefName);
2171                ****/

2172
2173                attDefDefaultValue = scanDefaultAttValue(fElementQName, fAttributeQName,
2174                                                         attDefType,
2175                                                         attDefEnumeration);
2176
2177                //normalize and check VC: Attribute Default Legal
2178
if (attDefDefaultValue != -1 && attDefType != XMLAttributeDecl.TYPE_CDATA ) {
2179                    attDefDefaultValue = normalizeDefaultAttValue( fAttributeQName, attDefDefaultValue,
2180                                                                attDefType, attDefEnumeration,
2181                                                                attDefList);
2182                }
2183
2184                if (attDefDefaultValue == -1) {
2185                    skipPastEndOfCurrentMarkup();
2186                    return;
2187                }
2188            }
2189            if (attDefName == fXMLSpace) {
2190                boolean ok = false;
2191                if (attDefType == XMLAttributeDecl.TYPE_ENUMERATION) {
2192                    int index = attDefEnumeration;
2193                    if (index != -1) {
2194                        ok = (fStringPool.stringListLength(index) == 1 &&
2195                              (fStringPool.stringInList(index, fDefault) ||
2196                               fStringPool.stringInList(index, fPreserve))) ||
2197                            (fStringPool.stringListLength(index) == 2 &&
2198                             fStringPool.stringInList(index, fDefault) &&
2199                             fStringPool.stringInList(index, fPreserve));
2200                    }
2201                }
2202                if (!ok) {
2203                    reportFatalXMLError(XMLMessages.MSG_XML_SPACE_DECLARATION_ILLEGAL,
2204                                        XMLMessages.S2_10_DECLARATION_ILLEGAL,
2205                                        elementTypeIndex);
2206                }
2207            }
2208            sawSpace = checkForPEReference(true);
2209            
2210            // if attribute name has a prefix "xml", bind it to the XML Namespace.
2211
// since this is the only pre-defined namespace.
2212
if (fAttributeQName.prefix == fXMLSymbol) {
2213                fAttributeQName.uri = fXMLNamespace;
2214            }
2215            
2216            if (fEntityReader.lookingAtChar('>', true)) {
2217                int attDefIndex = addAttDef(fElementQName, fAttributeQName,
2218                                                        attDefType, attDefList, attDefEnumeration,
2219                                                        attDefDefaultType, attDefDefaultValue,
2220                                                        getReadingExternalEntity());
2221                //System.out.println("XMLDTDScanner#scanAttlistDecl->DTDGrammar#addAttDef: "+attDefIndex+
2222
// " ("+fElementQName.localpart+","+fStringPool.toString(fElementQName.rawname)+')'+
2223
// " ("+fAttributeQName.localpart+","+fStringPool.toString(fAttributeQName.rawname)+')');
2224
decreaseMarkupDepth();
2225                return;
2226            }
2227            // REVISIT - review this code...
2228
if (!sawSpace) {
2229                if (fEntityReader.lookingAtSpace(true)) {
2230                    fEntityReader.skipPastSpaces();
2231                } else
2232                    reportFatalXMLError(XMLMessages.MSG_SPACE_REQUIRED_BEFORE_ATTRIBUTE_NAME_IN_ATTDEF,
2233                                        XMLMessages.P53_SPACE_REQUIRED);
2234            } else {
2235                if (fEntityReader.lookingAtSpace(true)) {
2236                    fEntityReader.skipPastSpaces();
2237                }
2238            }
2239            if (fEntityReader.lookingAtChar('>', true)) {
2240                int attDefIndex = addAttDef(fElementQName, fAttributeQName,
2241                                                        attDefType, attDefList, attDefEnumeration,
2242                                                        attDefDefaultType, attDefDefaultValue,
2243                                                        getReadingExternalEntity() );
2244                //System.out.println("XMLDTDScanner#scanAttlistDecl->DTDGrammar#addAttDef: "+attDefIndex+
2245
// " ("+fElementQName.localpart+","+fStringPool.toString(fElementQName.rawname)+')'+
2246
// " ("+fAttributeQName.localpart+","+fStringPool.toString(fAttributeQName.rawname)+')');
2247
decreaseMarkupDepth();
2248                return;
2249            }
2250            int attDefIndex = addAttDef(fElementQName, fAttributeQName,
2251                                                    attDefType, attDefList, attDefEnumeration,
2252                                                    attDefDefaultType, attDefDefaultValue,
2253                                                    getReadingExternalEntity());
2254            //System.out.println("XMLDTDScanner#scanAttlistDecl->DTDGrammar#addAttDef: "+attDefIndex+
2255
// " ("+fElementQName.localpart+","+fStringPool.toString(fElementQName.rawname)+')'+
2256
// " ("+fAttributeQName.localpart+","+fStringPool.toString(fAttributeQName.rawname)+')');
2257
}
2258    }
2259
2260    private int addAttDef(QName element, QName attribute,
2261                          int attDefType, boolean attDefList, int attDefEnumeration,
2262                          int attDefDefaultType, int attDefDefaultValue,
2263                          boolean isExternal ) throws Exception JavaDoc {
2264
2265        if (fDTDHandler != null) {
2266            String JavaDoc enumString = attDefEnumeration != -1 ? fStringPool.stringListAsString(attDefEnumeration) : null;
2267            fDTDHandler.attlistDecl(element, attribute,
2268                                    attDefType, attDefList,
2269                                    enumString,
2270                                    attDefDefaultType, attDefDefaultValue);
2271        }
2272        int elementIndex = fDTDGrammar.getElementDeclIndex(element, -1);
2273        if (elementIndex == -1) {
2274            // REPORT Internal error here
2275
}
2276        else {
2277            int attlistIndex = fDTDGrammar.getFirstAttributeDeclIndex(elementIndex);
2278            int dupID = -1;
2279            int dupNotation = -1;
2280            while (attlistIndex != -1) {
2281                fDTDGrammar.getAttributeDecl(attlistIndex, fTempAttributeDecl);
2282
2283                // REVISIT: Validation. Attributes are also tuples.
2284
if (fStringPool.equalNames(fTempAttributeDecl.name.rawname, attribute.rawname)) {
2285                    /******
2286                    if (fWarningOnDuplicateAttDef) {
2287                        Object[] args = { fStringPool.toString(fElementType[elemChunk][elemIndex]),
2288                                          fStringPool.toString(attributeDecl.rawname) };
2289                        fErrorReporter.reportError(fErrorReporter.getLocator(),
2290                                                   XMLMessages.XML_DOMAIN,
2291                                                   XMLMessages.MSG_DUPLICATE_ATTDEF,
2292                                                   XMLMessages.P53_DUPLICATE,
2293                                                   args,
2294                                                   XMLErrorReporter.ERRORTYPE_WARNING);
2295                    }
2296                    ******/

2297                    return -1;
2298                }
2299
2300                if (fValidationEnabled) {
2301                    if (attDefType == XMLAttributeDecl.TYPE_ID &&
2302                        fTempAttributeDecl.type == XMLAttributeDecl.TYPE_ID ) {
2303                        dupID = fTempAttributeDecl.name.rawname;
2304                    }
2305                    if (attDefType == XMLAttributeDecl.TYPE_NOTATION
2306                        && fTempAttributeDecl.type == XMLAttributeDecl.TYPE_NOTATION) {
2307                        dupNotation = fTempAttributeDecl.name.rawname;
2308                    }
2309                }
2310                attlistIndex = fDTDGrammar.getNextAttributeDeclIndex(attlistIndex);
2311            }
2312            if (fValidationEnabled) {
2313                if (dupID != -1) {
2314                    Object JavaDoc[] args = { fStringPool.toString(element.rawname),
2315                                      fStringPool.toString(dupID),
2316                                      fStringPool.toString(attribute.rawname) };
2317                    fErrorReporter.reportError(fErrorReporter.getLocator(),
2318                                               XMLMessages.XML_DOMAIN,
2319                                               XMLMessages.MSG_MORE_THAN_ONE_ID_ATTRIBUTE,
2320                                               XMLMessages.VC_ONE_ID_PER_ELEMENT_TYPE,
2321                                               args,
2322                                               XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
2323                    return -1;
2324                }
2325                if (dupNotation != -1) {
2326                    Object JavaDoc[] args = { fStringPool.toString(element.rawname),
2327                                      fStringPool.toString(dupNotation),
2328                                      fStringPool.toString(attribute.rawname) };
2329                    fErrorReporter.reportError(fErrorReporter.getLocator(),
2330                                               XMLMessages.XML_DOMAIN,
2331                                               XMLMessages.MSG_MORE_THAN_ONE_NOTATION_ATTRIBUTE,
2332                                               XMLMessages.VC_ONE_NOTATION_PER_ELEMENT_TYPE,
2333                                               args,
2334                                               XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
2335                    return -1;
2336                }
2337            }
2338        }
2339        return fDTDGrammar.addAttDef(element, attribute,
2340                                     attDefType, attDefList, attDefEnumeration,
2341                                     attDefDefaultType, attDefDefaultValue,
2342                                     isExternal);
2343
2344    }
2345    //
2346
// [58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
2347
// [59] Enumeration ::= '(' S? Nmtoken (S? '|' S? Nmtoken)* S? ')'
2348
//
2349
private int scanEnumeration(int elementType, int attrName, boolean isNotationType) throws Exception JavaDoc
2350    {
2351        int enumIndex = fDTDGrammar.startEnumeration();
2352        while (true) {
2353            checkForPEReference(false);
2354            int nameIndex = isNotationType ?
2355                            checkForNameWithPEReference(fEntityReader, ')') :
2356                            checkForNmtokenWithPEReference(fEntityReader, ')');
2357            if (nameIndex == -1) {
2358                if (isNotationType) {
2359                    reportFatalXMLError(XMLMessages.MSG_NAME_REQUIRED_IN_NOTATIONTYPE,
2360                                        XMLMessages.P58_NAME_REQUIRED,
2361                                        elementType,
2362                                        attrName);
2363                } else {
2364                    reportFatalXMLError(XMLMessages.MSG_NMTOKEN_REQUIRED_IN_ENUMERATION,
2365                                        XMLMessages.P59_NMTOKEN_REQUIRED,
2366                                        elementType,
2367                                        attrName);
2368                }
2369                fDTDGrammar.endEnumeration(enumIndex);
2370                return -1;
2371            }
2372            fDTDGrammar.addNameToEnumeration(enumIndex, elementType, attrName, nameIndex, isNotationType);
2373            /*****/
2374            if (isNotationType && !((DefaultEntityHandler)fEntityHandler).isNotationDeclared(nameIndex)) {
2375                Object JavaDoc[] args = { fStringPool.toString(elementType),
2376                    fStringPool.toString(attrName),
2377                    fStringPool.toString(nameIndex) };
2378                    ((DefaultEntityHandler)fEntityHandler).addRequiredNotation(nameIndex,
2379                                                       fErrorReporter.getLocator(),
2380                                                       XMLMessages.MSG_NOTATION_NOT_DECLARED_FOR_NOTATIONTYPE_ATTRIBUTE,
2381                                                       XMLMessages.VC_NOTATION_DECLARED,
2382                                                       args);
2383            }
2384            /*****/
2385            checkForPEReference(false);
2386            if (!fEntityReader.lookingAtChar('|', true)) {
2387                fDTDGrammar.endEnumeration(enumIndex);
2388                if (!fEntityReader.lookingAtChar(')', true)) {
2389                    if (isNotationType) {
2390                        reportFatalXMLError(XMLMessages.MSG_NOTATIONTYPE_UNTERMINATED,
2391                                            XMLMessages.P58_UNTERMINATED,
2392                                        elementType,
2393                                        attrName);
2394                    } else {
2395                        reportFatalXMLError(XMLMessages.MSG_ENUMERATION_UNTERMINATED,
2396                                            XMLMessages.P59_UNTERMINATED,
2397                                        elementType,
2398                                        attrName);
2399                    }
2400                    return -1;
2401                }
2402                decreaseParenDepth();
2403                return enumIndex;
2404            }
2405        }
2406    }
2407    //
2408
// [10] AttValue ::= '"' ([^<&"] | Reference)* '"'
2409
// | "'" ([^<&'] | Reference)* "'"
2410
//
2411
/**
2412     * Scan the default value in an attribute declaration
2413     *
2414     * @param elementType handle to the element that owns the attribute
2415     * @param attrName handle in the string pool for the attribute name
2416     * @return handle in the string pool for the default attribute value
2417     * @exception java.lang.Exception
2418     */

2419    public int scanDefaultAttValue(QName element, QName attribute) throws Exception JavaDoc
2420    {
2421        boolean single;
2422        if (!(single = fEntityReader.lookingAtChar('\'', true)) && !fEntityReader.lookingAtChar('\"', true)) {
2423            reportFatalXMLError(XMLMessages.MSG_QUOTE_REQUIRED_IN_ATTVALUE,
2424                                XMLMessages.P10_QUOTE_REQUIRED,
2425                                element.rawname,
2426                                attribute.rawname);
2427            return -1;
2428        }
2429        int previousState = setScannerState(SCANNER_STATE_DEFAULT_ATTRIBUTE_VALUE);
2430        char qchar = single ? '\'' : '\"';
2431        fDefaultAttValueReader = fReaderId;
2432        fDefaultAttValueElementType = element.rawname;
2433        fDefaultAttValueAttrName = attribute.rawname;
2434        boolean setMark = true;
2435        int dataOffset = fLiteralData.length();
2436        while (true) {
2437            fDefaultAttValueOffset = fEntityReader.currentOffset();
2438            if (setMark) {
2439                fDefaultAttValueMark = fDefaultAttValueOffset;
2440                setMark = false;
2441            }
2442            if (fEntityReader.lookingAtChar(qchar, true)) {
2443                if (fReaderId == fDefaultAttValueReader)
2444                    break;
2445                continue;
2446            }
2447            if (fEntityReader.lookingAtChar(' ', true)) {
2448                continue;
2449            }
2450            boolean skippedCR;
2451            if ((skippedCR = fEntityReader.lookingAtChar((char)0x0D, true)) || fEntityReader.lookingAtSpace(true)) {
2452                if (fDefaultAttValueOffset - fDefaultAttValueMark > 0)
2453                    fEntityReader.append(fLiteralData, fDefaultAttValueMark, fDefaultAttValueOffset - fDefaultAttValueMark);
2454                setMark = true;
2455                fLiteralData.append(' ');
2456                if (skippedCR)
2457                    fEntityReader.lookingAtChar((char)0x0A, true);
2458                continue;
2459            }
2460            if (fEntityReader.lookingAtChar('&', true)) {
2461                if (fDefaultAttValueOffset - fDefaultAttValueMark > 0)
2462                    fEntityReader.append(fLiteralData, fDefaultAttValueMark, fDefaultAttValueOffset - fDefaultAttValueMark);
2463                setMark = true;
2464                //
2465
// Check for character reference first.
2466
//
2467
if (fEntityReader.lookingAtChar('#', true)) {
2468                    int ch = scanCharRef();
2469                    if (ch != -1) {
2470                        if (ch < 0x10000)
2471                            fLiteralData.append((char)ch);
2472                        else {
2473                            fLiteralData.append((char)(((ch-0x00010000)>>10)+0xd800));
2474                            fLiteralData.append((char)(((ch-0x00010000)&0x3ff)+0xdc00));
2475                        }
2476                    }
2477                } else {
2478                    //
2479
// Entity reference
2480
//
2481
int nameOffset = fEntityReader.currentOffset();
2482                    fEntityReader.skipPastName(';');
2483                    int nameLength = fEntityReader.currentOffset() - nameOffset;
2484                    if (nameLength == 0) {
2485                        reportFatalXMLError(XMLMessages.MSG_NAME_REQUIRED_IN_REFERENCE,
2486                                            XMLMessages.P68_NAME_REQUIRED);
2487                    } else if (!fEntityReader.lookingAtChar(';', true)) {
2488                        reportFatalXMLError(XMLMessages.MSG_SEMICOLON_REQUIRED_IN_REFERENCE,
2489                                            XMLMessages.P68_SEMICOLON_REQUIRED,
2490                                            fEntityReader.addString(nameOffset, nameLength));
2491                    } else {
2492                        int entityNameIndex = fEntityReader.addSymbol(nameOffset, nameLength);
2493                        fEntityHandler.startReadingFromEntity(entityNameIndex, markupDepth(), XMLEntityHandler.ENTITYREF_IN_DEFAULTATTVALUE);
2494                    }
2495                }
2496                continue;
2497            }
2498            if (fEntityReader.lookingAtChar('<', true)) {
2499                if (fDefaultAttValueOffset - fDefaultAttValueMark > 0)
2500                    fEntityReader.append(fLiteralData, fDefaultAttValueMark, fDefaultAttValueOffset - fDefaultAttValueMark);
2501                setMark = true;
2502                reportFatalXMLError(XMLMessages.MSG_LESSTHAN_IN_ATTVALUE,
2503                                    XMLMessages.WFC_NO_LESSTHAN_IN_ATTVALUE,
2504                                    element.rawname,
2505                                    attribute.rawname);
2506                continue;
2507            }
2508            if (!fEntityReader.lookingAtValidChar(true)) {
2509                if (fDefaultAttValueOffset - fDefaultAttValueMark > 0)
2510                    fEntityReader.append(fLiteralData, fDefaultAttValueMark, fDefaultAttValueOffset - fDefaultAttValueMark);
2511                setMark = true;
2512                int invChar = fEntityReader.scanInvalidChar();
2513                if (fScannerState == SCANNER_STATE_END_OF_INPUT)
2514                    return -1;
2515                if (invChar >= 0) {
2516                    reportFatalXMLError(XMLMessages.MSG_INVALID_CHAR_IN_ATTVALUE,
2517                                        XMLMessages.P10_INVALID_CHARACTER,
2518                                        fStringPool.toString(element.rawname),
2519                                        fStringPool.toString(attribute.rawname),
2520                                        Integer.toHexString(invChar));
2521                }
2522                continue;
2523            }
2524        }
2525        restoreScannerState(previousState);
2526        int dataLength = fLiteralData.length() - dataOffset;
2527        if (dataLength == 0) {
2528            return fEntityReader.addString(fDefaultAttValueMark, fDefaultAttValueOffset - fDefaultAttValueMark);
2529        }
2530        if (fDefaultAttValueOffset - fDefaultAttValueMark > 0) {
2531            fEntityReader.append(fLiteralData, fDefaultAttValueMark, fDefaultAttValueOffset - fDefaultAttValueMark);
2532            dataLength = fLiteralData.length() - dataOffset;
2533        }
2534        return fLiteralData.addString(dataOffset, dataLength);
2535    }
2536    //
2537
// [82] NotationDecl ::= '<!NOTATION' S Name S (ExternalID | PublicID) S? '>'
2538
//
2539
private void scanNotationDecl() throws Exception JavaDoc
2540    {
2541        if (!checkForPEReference(true)) {
2542            abortMarkup(XMLMessages.MSG_SPACE_REQUIRED_BEFORE_NOTATION_NAME_IN_NOTATIONDECL,
2543                        XMLMessages.P82_SPACE_REQUIRED);
2544            return;
2545        }
2546        int notationName = checkForNameWithPEReference(fEntityReader, ' ');
2547        if (notationName == -1) {
2548            abortMarkup(XMLMessages.MSG_NOTATION_NAME_REQUIRED_IN_NOTATIONDECL,
2549                        XMLMessages.P82_NAME_REQUIRED);
2550            return;
2551        }
2552        if (!checkForPEReference(true)) {
2553            abortMarkup(XMLMessages.MSG_SPACE_REQUIRED_AFTER_NOTATION_NAME_IN_NOTATIONDECL,
2554                        XMLMessages.P82_SPACE_REQUIRED,
2555                        notationName);
2556            return;
2557        }
2558        if (!scanExternalID(true)) {
2559            skipPastEndOfCurrentMarkup();
2560            return;
2561        }
2562        checkForPEReference(false);
2563        if (!fEntityReader.lookingAtChar('>', true)) {
2564            abortMarkup(XMLMessages.MSG_NOTATIONDECL_UNTERMINATED,
2565                        XMLMessages.P82_UNTERMINATED,
2566                        notationName);
2567            return;
2568        }
2569        decreaseMarkupDepth();
2570        /****
2571        System.out.println(fStringPool.toString(notationName)+","
2572                           +fStringPool.toString(fPubidLiteral) + ","
2573                           +fStringPool.toString(fSystemLiteral) + ","
2574                           +getReadingExternalEntity());
2575        /****/

2576
2577        int notationIndex = ((DefaultEntityHandler) fEntityHandler).addNotationDecl( notationName,
2578                                                                                     fPubidLiteral,
2579                                                                                     fSystemLiteral,
2580                                                                                     getReadingExternalEntity());
2581        fDTDGrammar.addNotationDecl(notationName, fPubidLiteral, fSystemLiteral);
2582        if (fDTDHandler != null) {
2583            fDTDHandler.notationDecl(notationName, fPubidLiteral, fSystemLiteral);
2584        }
2585    }
2586    //
2587
// [70] EntityDecl ::= GEDecl | PEDecl
2588
// [71] GEDecl ::= '<!ENTITY' S Name S EntityDef S? '>'
2589
// [72] PEDecl ::= '<!ENTITY' S '%' S Name S PEDef S? '>'
2590
// [73] EntityDef ::= EntityValue | (ExternalID NDataDecl?)
2591
// [74] PEDef ::= EntityValue | ExternalID
2592
// [75] ExternalID ::= 'SYSTEM' S SystemLiteral
2593
// | 'PUBLIC' S PubidLiteral S SystemLiteral
2594
// [76] NDataDecl ::= S 'NDATA' S Name
2595
// [9] EntityValue ::= '"' ([^%&"] | PEReference | Reference)* '"'
2596
// | "'" ([^%&'] | PEReference | Reference)* "'"
2597
//
2598
// Called after scanning 'ENTITY'
2599
//
2600
private void scanEntityDecl() throws Exception JavaDoc
2601    {
2602        boolean isPEDecl = false;
2603        boolean sawPERef = false;
2604        if (fEntityReader.lookingAtSpace(true)) {
2605            fEntityReader.skipPastSpaces();
2606            if (!fEntityReader.lookingAtChar('%', true)) {
2607                isPEDecl = false; // <!ENTITY x "x">
2608
} else if (fEntityReader.lookingAtSpace(true)) {
2609                checkForPEReference(false); // <!ENTITY % x "x">
2610
isPEDecl = true;
2611            } else if (!getReadingExternalEntity()) {
2612                reportFatalXMLError(XMLMessages.MSG_SPACE_REQUIRED_BEFORE_ENTITY_NAME_IN_PEDECL,
2613                                    XMLMessages.P72_SPACE);
2614                isPEDecl = true;
2615            } else if (fEntityReader.lookingAtChar('%', false)) {
2616                checkForPEReference(false); // <!ENTITY %%x; "x"> is legal
2617
isPEDecl = true;
2618            } else {
2619                sawPERef = true;
2620            }
2621        } else if (!getReadingExternalEntity() || !fEntityReader.lookingAtChar('%', true)) {
2622            // <!ENTITY[^ ]...> or <!ENTITY[^ %]...>
2623
reportFatalXMLError(XMLMessages.MSG_SPACE_REQUIRED_BEFORE_ENTITY_NAME_IN_ENTITYDECL,
2624                                XMLMessages.P70_SPACE);
2625            isPEDecl = false;
2626        } else if (fEntityReader.lookingAtSpace(false)) {
2627            // <!ENTITY% ...>
2628
reportFatalXMLError(XMLMessages.MSG_SPACE_REQUIRED_BEFORE_PERCENT_IN_PEDECL,
2629                                XMLMessages.P72_SPACE);
2630            isPEDecl = false;
2631        } else {
2632            sawPERef = true;
2633        }
2634        if (sawPERef) {
2635            while (true) {
2636                int nameOffset = fEntityReader.currentOffset();
2637                fEntityReader.skipPastName(';');
2638                int nameLength = fEntityReader.currentOffset() - nameOffset;
2639                if (nameLength == 0) {
2640                    reportFatalXMLError(XMLMessages.MSG_NAME_REQUIRED_IN_PEREFERENCE,
2641                                        XMLMessages.P69_NAME_REQUIRED);
2642                } else if (!fEntityReader.lookingAtChar(';', true)) {
2643                    reportFatalXMLError(XMLMessages.MSG_SEMICOLON_REQUIRED_IN_PEREFERENCE,
2644                                        XMLMessages.P69_SEMICOLON_REQUIRED,
2645                                        fEntityReader.addString(nameOffset, nameLength));
2646                } else {
2647                    int peNameIndex = fEntityReader.addSymbol(nameOffset, nameLength);
2648                    int readerDepth = (fScannerState == SCANNER_STATE_CONTENTSPEC) ? parenDepth() : markupDepth();
2649                    fEntityHandler.startReadingFromEntity(peNameIndex, readerDepth, XMLEntityHandler.ENTITYREF_IN_DTD_WITHIN_MARKUP);
2650                }
2651                fEntityReader.skipPastSpaces();
2652                if (!fEntityReader.lookingAtChar('%', true))
2653                    break;
2654                if (!isPEDecl) {
2655                    if (fEntityReader.lookingAtSpace(true)) {
2656                        checkForPEReference(false);
2657                        isPEDecl = true;
2658                        break;
2659                    }
2660                    isPEDecl = fEntityReader.lookingAtChar('%', true);
2661                }
2662            }
2663        }
2664        int entityName = checkForNameWithPEReference(fEntityReader, ' ');
2665        if (entityName == -1) {
2666            abortMarkup(XMLMessages.MSG_ENTITY_NAME_REQUIRED_IN_ENTITYDECL,
2667                        XMLMessages.P70_REQUIRED_NAME);
2668            return;
2669        }
2670        if (!fDTDGrammar.startEntityDecl(isPEDecl, entityName)) {
2671            skipPastEndOfCurrentMarkup();
2672            return;
2673        }
2674        if (!checkForPEReference(true)) {
2675            abortMarkup(XMLMessages.MSG_SPACE_REQUIRED_AFTER_ENTITY_NAME_IN_ENTITYDECL,
2676                        XMLMessages.P70_REQUIRED_SPACE,
2677                        entityName);
2678            fDTDGrammar.endEntityDecl();
2679            return;
2680        }
2681        if (isPEDecl) {
2682            boolean single;
2683            if ((single = fEntityReader.lookingAtChar('\'', true)) || fEntityReader.lookingAtChar('\"', true)) {
2684                int value = scanEntityValue(single);
2685                if (value == -1) {
2686                    skipPastEndOfCurrentMarkup();
2687                    fDTDGrammar.endEntityDecl();
2688                    return;
2689                }
2690                checkForPEReference(false);
2691                if (!fEntityReader.lookingAtChar('>', true)) {
2692                    abortMarkup(XMLMessages.MSG_ENTITYDECL_UNTERMINATED,
2693                                XMLMessages.P72_UNTERMINATED,
2694                                entityName);
2695                    fDTDGrammar.endEntityDecl();
2696                    return;
2697                }
2698                decreaseMarkupDepth();
2699                fDTDGrammar.endEntityDecl();
2700
2701                // a hack by Eric
2702
//REVISIT
2703
fDTDGrammar.addInternalPEDecl(entityName, value);
2704                if (fDTDHandler != null) {
2705                    fDTDHandler.internalPEDecl(entityName, value);
2706                }
2707                int entityIndex = ((DefaultEntityHandler) fEntityHandler).addInternalPEDecl(entityName,
2708                                                                                            value,
2709                                                                                            getReadingExternalEntity());
2710
2711            } else {
2712                if (!scanExternalID(false)) {
2713                    skipPastEndOfCurrentMarkup();
2714                    fDTDGrammar.endEntityDecl();
2715                    return;
2716                }
2717                checkForPEReference(false);
2718                if (!fEntityReader.lookingAtChar('>', true)) {
2719                    abortMarkup(XMLMessages.MSG_ENTITYDECL_UNTERMINATED,
2720                                XMLMessages.P72_UNTERMINATED,
2721                                entityName);
2722                    fDTDGrammar.endEntityDecl();
2723                    return;
2724                }
2725                decreaseMarkupDepth();
2726                fDTDGrammar.endEntityDecl();
2727
2728                //a hack by Eric
2729
//REVISIT
2730
fDTDGrammar.addExternalPEDecl(entityName, fPubidLiteral, fSystemLiteral);
2731                if (fDTDHandler != null) {
2732                    fDTDHandler.externalPEDecl(entityName, fPubidLiteral, fSystemLiteral);
2733                }
2734                int entityIndex = ((DefaultEntityHandler) fEntityHandler).addExternalPEDecl(entityName,
2735                                                                                            fPubidLiteral,
2736                                                                                            fSystemLiteral, getReadingExternalEntity());
2737            }
2738        } else {
2739            boolean single;
2740            if ((single = fEntityReader.lookingAtChar('\'', true)) || fEntityReader.lookingAtChar('\"', true)) {
2741                int value = scanEntityValue(single);
2742                if (value == -1) {
2743                    skipPastEndOfCurrentMarkup();
2744                    fDTDGrammar.endEntityDecl();
2745                    return;
2746                }
2747                checkForPEReference(false);
2748                if (!fEntityReader.lookingAtChar('>', true)) {
2749                    abortMarkup(XMLMessages.MSG_ENTITYDECL_UNTERMINATED,
2750                                XMLMessages.P71_UNTERMINATED,
2751                                entityName);
2752                    fDTDGrammar.endEntityDecl();
2753                    return;
2754                }
2755                decreaseMarkupDepth();
2756                fDTDGrammar.endEntityDecl();
2757
2758                //a hack by Eric
2759
//REVISIT
2760
fDTDGrammar.addInternalEntityDecl(entityName, value);
2761                if (fDTDHandler != null) {
2762                    fDTDHandler.internalEntityDecl(entityName, value);
2763                }
2764                int entityIndex = ((DefaultEntityHandler) fEntityHandler).addInternalEntityDecl(entityName,
2765                                                                                                value,
2766                                                                                                getReadingExternalEntity());
2767            } else {
2768                if (!scanExternalID(false)) {
2769                    skipPastEndOfCurrentMarkup();
2770                    fDTDGrammar.endEntityDecl();
2771                    return;
2772                }
2773                boolean unparsed = false;
2774                if (fEntityReader.lookingAtSpace(true)) {
2775                    fEntityReader.skipPastSpaces();
2776                    unparsed = fEntityReader.skippedString(ndata_string);
2777                }
2778                if (!unparsed) {
2779                    checkForPEReference(false);
2780                    if (!fEntityReader.lookingAtChar('>', true)) {
2781                        abortMarkup(XMLMessages.MSG_ENTITYDECL_UNTERMINATED,
2782                                    XMLMessages.P72_UNTERMINATED,
2783                                    entityName);
2784                        fDTDGrammar.endEntityDecl();
2785                        return;
2786                    }
2787                    decreaseMarkupDepth();
2788                    fDTDGrammar.endEntityDecl();
2789
2790                    //a hack by Eric
2791
//REVISIT
2792
fDTDGrammar.addExternalEntityDecl(entityName, fPubidLiteral, fSystemLiteral);
2793                    if (fDTDHandler != null) {
2794                        fDTDHandler.externalEntityDecl(entityName, fPubidLiteral, fSystemLiteral);
2795                    }
2796                    int entityIndex = ((DefaultEntityHandler) fEntityHandler).addExternalEntityDecl(entityName,
2797                                                                                                    fPubidLiteral,
2798                                                                                                    fSystemLiteral,
2799                                                                                                    getReadingExternalEntity());
2800
2801                } else {
2802                    if (!fEntityReader.lookingAtSpace(true)) {
2803                        abortMarkup(XMLMessages.MSG_SPACE_REQUIRED_BEFORE_NOTATION_NAME_IN_UNPARSED_ENTITYDECL,
2804                                    XMLMessages.P76_SPACE_REQUIRED,
2805                                    entityName);
2806                        fDTDGrammar.endEntityDecl();
2807                        return;
2808                    }
2809                    fEntityReader.skipPastSpaces();
2810                    int ndataOffset = fEntityReader.currentOffset();
2811                    fEntityReader.skipPastName('>');
2812                    int ndataLength = fEntityReader.currentOffset() - ndataOffset;
2813                    if (ndataLength == 0) {
2814                        abortMarkup(XMLMessages.MSG_NOTATION_NAME_REQUIRED_FOR_UNPARSED_ENTITYDECL,
2815                                    XMLMessages.P76_REQUIRED,
2816                                    entityName);
2817                        fDTDGrammar.endEntityDecl();
2818                        return;
2819                    }
2820                    int notationName = fEntityReader.addSymbol(ndataOffset, ndataLength);
2821                    checkForPEReference(false);
2822                    if (!fEntityReader.lookingAtChar('>', true)) {
2823                        abortMarkup(XMLMessages.MSG_ENTITYDECL_UNTERMINATED,
2824                                    XMLMessages.P72_UNTERMINATED,
2825                                    entityName);
2826                        fDTDGrammar.endEntityDecl();
2827                        return;
2828                    }
2829                    decreaseMarkupDepth();
2830                    fDTDGrammar.endEntityDecl();
2831                    
2832                    //a hack by Eric
2833
//REVISIT
2834
fDTDGrammar.addUnparsedEntityDecl(entityName, fPubidLiteral, fSystemLiteral, notationName);
2835                    if (fDTDHandler != null) {
2836                        fDTDHandler.unparsedEntityDecl(entityName, fPubidLiteral, fSystemLiteral, notationName);
2837                    }
2838                    /****
2839                    System.out.println("----addUnparsedEntity--- "+ fStringPool.toString(entityName)+","
2840                                       +fStringPool.toString(notationName)+","
2841                                       +fStringPool.toString(fPubidLiteral) + ","
2842                                       +fStringPool.toString(fSystemLiteral) + ","
2843                                       +getReadingExternalEntity());
2844                    /****/

2845                    int entityIndex = ((DefaultEntityHandler) fEntityHandler).addUnparsedEntityDecl(entityName,
2846                                                                                                    fPubidLiteral,
2847                                                                                                    fSystemLiteral,
2848                                                                                                    notationName,
2849                                                                                                    getReadingExternalEntity());
2850                }
2851            }
2852        }
2853    }
2854    //
2855
// [9] EntityValue ::= '"' ([^%&"] | PEReference | Reference)* '"'
2856
// | "'" ([^%&'] | PEReference | Reference)* "'"
2857
//
2858
private int scanEntityValue(boolean single) throws Exception JavaDoc
2859    {
2860        char qchar = single ? '\'' : '\"';
2861        fEntityValueMark = fEntityReader.currentOffset();
2862        int entityValue = fEntityReader.scanEntityValue(qchar, true);
2863        if (entityValue < 0)
2864            entityValue = scanComplexEntityValue(qchar, entityValue);
2865        return entityValue;
2866    }
2867    private int scanComplexEntityValue(char qchar, int result) throws Exception JavaDoc
2868    {
2869        int previousState = setScannerState(SCANNER_STATE_ENTITY_VALUE);
2870        fEntityValueReader = fReaderId;
2871        int dataOffset = fLiteralData.length();
2872        while (true) {
2873            switch (result) {
2874            case XMLEntityHandler.ENTITYVALUE_RESULT_FINISHED:
2875            {
2876                int offset = fEntityReader.currentOffset();
2877                fEntityReader.lookingAtChar(qchar, true);
2878                restoreScannerState(previousState);
2879                int dataLength = fLiteralData.length() - dataOffset;
2880                if (dataLength == 0) {
2881                    return fEntityReader.addString(fEntityValueMark, offset - fEntityValueMark);
2882                }
2883                if (offset - fEntityValueMark > 0) {
2884                    fEntityReader.append(fLiteralData, fEntityValueMark, offset - fEntityValueMark);
2885                    dataLength = fLiteralData.length() - dataOffset;
2886                }
2887                return fLiteralData.addString(dataOffset, dataLength);
2888            }
2889            case XMLEntityHandler.ENTITYVALUE_RESULT_REFERENCE:
2890            {
2891                int offset = fEntityReader.currentOffset();
2892                if (offset - fEntityValueMark > 0)
2893                    fEntityReader.append(fLiteralData, fEntityValueMark, offset - fEntityValueMark);
2894                fEntityReader.lookingAtChar('&', true);
2895                //
2896
// Check for character reference first.
2897
//
2898
if (fEntityReader.lookingAtChar('#', true)) {
2899                    int ch = scanCharRef();
2900                    if (ch != -1) {
2901                        if (ch < 0x10000)
2902                            fLiteralData.append((char)ch);
2903                        else {
2904                            fLiteralData.append((char)(((ch-0x00010000)>>10)+0xd800));
2905                            fLiteralData.append((char)(((ch-0x00010000)&0x3ff)+0xdc00));
2906                        }
2907                    }
2908                    fEntityValueMark = fEntityReader.currentOffset();
2909                } else {
2910                    //
2911
// Entity reference
2912
//
2913
int nameOffset = fEntityReader.currentOffset();
2914                    fEntityReader.skipPastName(';');
2915                    int nameLength = fEntityReader.currentOffset() - nameOffset;
2916                    if (nameLength == 0) {
2917                        reportFatalXMLError(XMLMessages.MSG_NAME_REQUIRED_IN_REFERENCE,
2918                                            XMLMessages.P68_NAME_REQUIRED);
2919                        fEntityValueMark = fEntityReader.currentOffset();
2920                    } else if (!fEntityReader.lookingAtChar(';', true)) {
2921                        reportFatalXMLError(XMLMessages.MSG_SEMICOLON_REQUIRED_IN_REFERENCE,
2922                                            XMLMessages.P68_SEMICOLON_REQUIRED,
2923                                            fEntityReader.addString(nameOffset, nameLength));
2924                        fEntityValueMark = fEntityReader.currentOffset();
2925                    } else {
2926                        //
2927
// 4.4.7 Bypassed
2928
//
2929
// When a general entity reference appears in the EntityValue in an
2930
// entity declaration, it is bypassed and left as is.
2931
//
2932
fEntityValueMark = offset;
2933                    }
2934                }
2935                break;
2936            }
2937            case XMLEntityHandler.ENTITYVALUE_RESULT_PEREF:
2938            {
2939                int offset = fEntityReader.currentOffset();
2940                if (offset - fEntityValueMark > 0)
2941                    fEntityReader.append(fLiteralData, fEntityValueMark, offset - fEntityValueMark);
2942                fEntityReader.lookingAtChar('%', true);
2943                int nameOffset = fEntityReader.currentOffset();
2944                fEntityReader.skipPastName(';');
2945                int nameLength = fEntityReader.currentOffset() - nameOffset;
2946                if (nameLength == 0) {
2947                    reportFatalXMLError(XMLMessages.MSG_NAME_REQUIRED_IN_PEREFERENCE,
2948                                        XMLMessages.P69_NAME_REQUIRED);
2949                } else if (!fEntityReader.lookingAtChar(';', true)) {
2950                    reportFatalXMLError(XMLMessages.MSG_SEMICOLON_REQUIRED_IN_PEREFERENCE,
2951                                        XMLMessages.P69_SEMICOLON_REQUIRED,
2952                                        fEntityReader.addString(nameOffset, nameLength));
2953                } else if (!getReadingExternalEntity()) {
2954                    reportFatalXMLError(XMLMessages.MSG_PEREFERENCE_WITHIN_MARKUP,
2955                                        XMLMessages.WFC_PES_IN_INTERNAL_SUBSET,
2956                                        fEntityReader.addString(nameOffset, nameLength));
2957                } else {
2958                    int peNameIndex = fEntityReader.addSymbol(nameOffset, nameLength);
2959                    fEntityHandler.startReadingFromEntity(peNameIndex, markupDepth(), XMLEntityHandler.ENTITYREF_IN_ENTITYVALUE);
2960                }
2961                fEntityValueMark = fEntityReader.currentOffset();
2962                break;
2963            }
2964            case XMLEntityHandler.ENTITYVALUE_RESULT_INVALID_CHAR:
2965            {
2966                int offset = fEntityReader.currentOffset();
2967                if (offset - fEntityValueMark > 0)
2968                    fEntityReader.append(fLiteralData, fEntityValueMark, offset - fEntityValueMark);
2969                int invChar = fEntityReader.scanInvalidChar();
2970                if (fScannerState == SCANNER_STATE_END_OF_INPUT)
2971                    return -1;
2972                if (invChar >= 0) {
2973                    reportFatalXMLError(XMLMessages.MSG_INVALID_CHAR_IN_ENTITYVALUE,
2974                                        XMLMessages.P9_INVALID_CHARACTER,
2975                                        Integer.toHexString(invChar));
2976                }
2977                fEntityValueMark = fEntityReader.currentOffset();
2978                break;
2979            }
2980            case XMLEntityHandler.ENTITYVALUE_RESULT_END_OF_INPUT:
2981                // all the work is done by the previous reader, just invoke the next one now.
2982
break;
2983            default:
2984                break;
2985            }
2986            result = fEntityReader.scanEntityValue(fReaderId == fEntityValueReader ? qchar : -1, false);
2987        }
2988    }
2989    //
2990
//
2991
//
2992
private boolean checkForPEReference(boolean spaceRequired) throws Exception JavaDoc
2993    {
2994        boolean sawSpace = true;
2995        if (spaceRequired)
2996            sawSpace = fEntityReader.lookingAtSpace(true);
2997        fEntityReader.skipPastSpaces();
2998        if (!getReadingExternalEntity())
2999            return sawSpace;
3000        if (!fEntityReader.lookingAtChar('%', true))
3001            return sawSpace;
3002        while (true) {
3003            int nameOffset = fEntityReader.currentOffset();
3004            fEntityReader.skipPastName(';');
3005            int nameLength = fEntityReader.currentOffset() - nameOffset;
3006            if (nameLength == 0) {
3007                reportFatalXMLError(XMLMessages.MSG_NAME_REQUIRED_IN_PEREFERENCE,
3008                                    XMLMessages.P69_NAME_REQUIRED);
3009            } else if (!fEntityReader.lookingAtChar(';', true)) {
3010                reportFatalXMLError(XMLMessages.MSG_SEMICOLON_REQUIRED_IN_PEREFERENCE,
3011                                    XMLMessages.P69_SEMICOLON_REQUIRED,
3012                                    fEntityReader.addString(nameOffset, nameLength));
3013            } else {
3014                int peNameIndex = fEntityReader.addSymbol(nameOffset, nameLength);
3015                int readerDepth = (fScannerState == SCANNER_STATE_CONTENTSPEC) ? parenDepth() : markupDepth();
3016                fEntityHandler.startReadingFromEntity(peNameIndex, readerDepth, XMLEntityHandler.ENTITYREF_IN_DTD_WITHIN_MARKUP);
3017            }
3018            fEntityReader.skipPastSpaces();
3019            if (!fEntityReader.lookingAtChar('%', true))
3020                return true;
3021        }
3022    }
3023    //
3024
// content model stack
3025
//
3026
private void initializeContentModelStack(int depth) {
3027        if (fOpStack == null) {
3028            fOpStack = new int[8];
3029            fNodeIndexStack = new int[8];
3030            fPrevNodeIndexStack = new int[8];
3031        } else if (depth == fOpStack.length) {
3032            int[] newStack = new int[depth * 2];
3033            System.arraycopy(fOpStack, 0, newStack, 0, depth);
3034            fOpStack = newStack;
3035            newStack = new int[depth * 2];
3036            System.arraycopy(fNodeIndexStack, 0, newStack, 0, depth);
3037            fNodeIndexStack = newStack;
3038            newStack = new int[depth * 2];
3039            System.arraycopy(fPrevNodeIndexStack, 0, newStack, 0, depth);
3040            fPrevNodeIndexStack = newStack;
3041        }
3042        fOpStack[depth] = -1;
3043        fNodeIndexStack[depth] = -1;
3044        fPrevNodeIndexStack[depth] = -1;
3045    }
3046
3047    private boolean validVersionNum(String JavaDoc version) {
3048        return XMLCharacterProperties.validVersionNum(version);
3049    }
3050
3051    private boolean validEncName(String JavaDoc encoding) {
3052        return XMLCharacterProperties.validEncName(encoding);
3053    }
3054
3055    private int validPublicId(String JavaDoc publicId) {
3056        return XMLCharacterProperties.validPublicId(publicId);
3057    }
3058
3059    private void scanElementType(XMLEntityHandler.EntityReader entityReader,
3060                                char fastchar, QName element) throws Exception JavaDoc {
3061
3062        if (!fNamespacesEnabled) {
3063            element.clear();
3064            element.localpart = entityReader.scanName(fastchar);
3065            element.rawname = element.localpart;
3066            return;
3067        }
3068        entityReader.scanQName(fastchar, element);
3069        if (entityReader.lookingAtChar(':', false)) {
3070            fErrorReporter.reportError(fErrorReporter.getLocator(),
3071                                       XMLMessages.XML_DOMAIN,
3072                                       XMLMessages.MSG_TWO_COLONS_IN_QNAME,
3073                                       XMLMessages.P5_INVALID_CHARACTER,
3074                                       null,
3075                                       XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
3076            entityReader.skipPastNmtoken(' ');
3077        }
3078
3079    } // scanElementType(XMLEntityHandler.EntityReader,char,QName)
3080

3081    public void checkForElementTypeWithPEReference(XMLEntityHandler.EntityReader entityReader,
3082                                                   char fastchar, QName element) throws Exception JavaDoc {
3083
3084        if (!fNamespacesEnabled) {
3085            element.clear();
3086            element.localpart = entityReader.scanName(fastchar);
3087            element.rawname = element.localpart;
3088            return;
3089        }
3090        entityReader.scanQName(fastchar, element);
3091        if (entityReader.lookingAtChar(':', false)) {
3092            fErrorReporter.reportError(fErrorReporter.getLocator(),
3093                                       XMLMessages.XML_DOMAIN,
3094                                       XMLMessages.MSG_TWO_COLONS_IN_QNAME,
3095                                       XMLMessages.P5_INVALID_CHARACTER,
3096                                       null,
3097                                       XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
3098            entityReader.skipPastNmtoken(' ');
3099        }
3100
3101    } // checkForElementTypeWithPEReference(XMLEntityHandler.EntityReader,char,QName)
3102

3103    public void checkForAttributeNameWithPEReference(XMLEntityHandler.EntityReader entityReader,
3104                                                     char fastchar, QName attribute) throws Exception JavaDoc {
3105
3106        if (!fNamespacesEnabled) {
3107            attribute.clear();
3108            attribute.localpart = entityReader.scanName(fastchar);
3109            attribute.rawname = attribute.localpart;
3110            return;
3111        }
3112
3113        entityReader.scanQName(fastchar, attribute);
3114        if (entityReader.lookingAtChar(':', false)) {
3115            fErrorReporter.reportError(fErrorReporter.getLocator(),
3116                                       XMLMessages.XML_DOMAIN,
3117                                       XMLMessages.MSG_TWO_COLONS_IN_QNAME,
3118                                       XMLMessages.P5_INVALID_CHARACTER,
3119                                       null,
3120                                       XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
3121            entityReader.skipPastNmtoken(' ');
3122        }
3123
3124    } // checkForAttributeNameWithPEReference(XMLEntityHandler.EntityReader,char,QName)
3125

3126    public int checkForNameWithPEReference(XMLEntityHandler.EntityReader entityReader, char fastcheck) throws Exception JavaDoc {
3127        //
3128
// REVISIT - what does this have to do with PE references?
3129
//
3130
int valueIndex = entityReader.scanName(fastcheck);
3131        return valueIndex;
3132    }
3133
3134    public int checkForNmtokenWithPEReference(XMLEntityHandler.EntityReader entityReader, char fastcheck) throws Exception JavaDoc {
3135        //
3136
// REVISIT - what does this have to do with PE references?
3137
//
3138
int nameOffset = entityReader.currentOffset();
3139        entityReader.skipPastNmtoken(fastcheck);
3140        int nameLength = entityReader.currentOffset() - nameOffset;
3141        if (nameLength == 0)
3142            return -1;
3143        int valueIndex = entityReader.addSymbol(nameOffset, nameLength);
3144        return valueIndex;
3145    }
3146
3147    public int scanDefaultAttValue(QName element, QName attribute,
3148                                   int attType, int enumeration) throws Exception JavaDoc {
3149        /***/
3150        if (fValidationEnabled && attType == XMLAttributeDecl.TYPE_ID) {
3151            reportRecoverableXMLError(XMLMessages.MSG_ID_DEFAULT_TYPE_INVALID,
3152                                      XMLMessages.VC_ID_ATTRIBUTE_DEFAULT,
3153                                      fStringPool.toString(attribute.rawname));
3154        }
3155        /***/
3156        int defaultAttValue = scanDefaultAttValue(element, attribute);
3157        if (defaultAttValue == -1)
3158            return -1;
3159        // REVISIT
3160
/***
3161        if (attType != fCDATASymbol) {
3162            // REVISIT: Validation. Should we pass in the element or is this
3163            // default attribute value normalization?
3164            defaultAttValue = fValidator.normalizeAttValue(null, attribute, defaultAttValue, attType, enumeration);
3165        }
3166        /***/

3167        return defaultAttValue;
3168    }
3169
3170    public int normalizeDefaultAttValue( QName attribute, int defaultAttValue,
3171                                         int attType, int enumeration,
3172                                         boolean list) throws Exception JavaDoc {
3173            //
3174
// Normalize attribute based upon attribute type...
3175
//
3176
String JavaDoc attValue = fStringPool.toString(defaultAttValue);
3177
3178            if (list) {
3179                StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc(attValue);
3180                StringBuffer JavaDoc sb = new StringBuffer JavaDoc(attValue.length());
3181                boolean ok = true;
3182                if (tokenizer.hasMoreTokens()) {
3183                    while (true) {
3184                        String JavaDoc nmtoken = tokenizer.nextToken();
3185                        if (attType == XMLAttributeDecl.TYPE_NMTOKEN) {
3186                            if (fValidationEnabled && !XMLCharacterProperties.validNmtoken(nmtoken)) {
3187                                ok = false;
3188                            }
3189                        }
3190                        else if (attType == XMLAttributeDecl.TYPE_IDREF || attType == XMLAttributeDecl.TYPE_ENTITY) {
3191                            if (fValidationEnabled && !XMLCharacterProperties.validName(nmtoken)) {
3192                                ok = false;
3193                            }
3194                            // REVISIT: a Hack!!! THis is to pass SUN test /invalid/attr11.xml and attr12.xml
3195
// not consistent with XML1.0 spec VC: Attribute Default Legal
3196
if (fValidationEnabled && attType == XMLAttributeDecl.TYPE_ENTITY)
3197                            if (! ((DefaultEntityHandler) fEntityHandler).isUnparsedEntity(defaultAttValue)) {
3198                                reportRecoverableXMLError(XMLMessages.MSG_ENTITY_INVALID,
3199                                                          XMLMessages.VC_ENTITY_NAME,
3200                                                          fStringPool.toString(attribute.rawname), nmtoken);
3201                            }
3202
3203                        }
3204                        sb.append(nmtoken);
3205                        if (!tokenizer.hasMoreTokens()) {
3206                            break;
3207                        }
3208                        sb.append(' ');
3209                    }
3210                }
3211                String JavaDoc newAttValue = sb.toString();
3212                if (fValidationEnabled && (!ok || newAttValue.length() == 0)) {
3213                    reportRecoverableXMLError(XMLMessages.MSG_ATT_DEFAULT_INVALID,
3214                                              XMLMessages.VC_ATTRIBUTE_DEFAULT_LEGAL,
3215                                              fStringPool.toString(attribute.rawname), newAttValue);
3216                }
3217                if (!newAttValue.equals(attValue)) {
3218                    defaultAttValue = fStringPool.addString(newAttValue);
3219                }
3220                return defaultAttValue;
3221            }
3222            else {
3223                String JavaDoc newAttValue = attValue.trim();
3224
3225                if (fValidationEnabled) {
3226                    // REVISIT - can we release the old string?
3227
if (newAttValue != attValue) {
3228                       defaultAttValue = fStringPool.addSymbol(newAttValue);
3229                    }
3230                    else {
3231                       defaultAttValue = fStringPool.addSymbol(defaultAttValue);
3232                    }
3233                    if (attType == XMLAttributeDecl.TYPE_ENTITY ||
3234                        attType == XMLAttributeDecl.TYPE_ID ||
3235                        attType == XMLAttributeDecl.TYPE_IDREF ||
3236                        attType == XMLAttributeDecl.TYPE_NOTATION) {
3237
3238                        // REVISIT: A Hack!!! THis is to pass SUN test /invalid/attr11.xml and attr12.xml
3239
// not consistent with XML1.0 spec VC: Attribute Default Legal
3240
if (attType == XMLAttributeDecl.TYPE_ENTITY)
3241                        if (! ((DefaultEntityHandler) fEntityHandler).isUnparsedEntity(defaultAttValue)) {
3242                            reportRecoverableXMLError(XMLMessages.MSG_ENTITY_INVALID,
3243                                                      XMLMessages.VC_ENTITY_NAME,
3244                                                      fStringPool.toString(attribute.rawname), newAttValue);
3245                        }
3246                        
3247                        if (!XMLCharacterProperties.validName(newAttValue)) {
3248                            reportRecoverableXMLError(XMLMessages.MSG_ATT_DEFAULT_INVALID,
3249                                                      XMLMessages.VC_ATTRIBUTE_DEFAULT_LEGAL,
3250                                                      fStringPool.toString(attribute.rawname), newAttValue);
3251                        }
3252
3253                    }
3254                    else if (attType == XMLAttributeDecl.TYPE_NMTOKEN ||
3255                             attType == XMLAttributeDecl.TYPE_ENUMERATION ) {
3256
3257                        if (!XMLCharacterProperties.validNmtoken(newAttValue)) {
3258                            reportRecoverableXMLError(XMLMessages.MSG_ATT_DEFAULT_INVALID,
3259                                                      XMLMessages.VC_ATTRIBUTE_DEFAULT_LEGAL,
3260                                                      fStringPool.toString(attribute.rawname), newAttValue);
3261                        }
3262                    }
3263                    
3264                    if (attType == XMLAttributeDecl.TYPE_NOTATION ||
3265                        attType == XMLAttributeDecl.TYPE_ENUMERATION ) {
3266
3267                        if ( !fStringPool.stringInList(enumeration, defaultAttValue) ) {
3268                            reportRecoverableXMLError(XMLMessages.MSG_ATT_DEFAULT_INVALID,
3269                                                      XMLMessages.VC_ATTRIBUTE_DEFAULT_LEGAL,
3270                                                      fStringPool.toString(attribute.rawname), newAttValue);
3271                        }
3272                    }
3273
3274                }
3275                else if (newAttValue != attValue) {
3276                    // REVISIT - can we release the old string?
3277
defaultAttValue = fStringPool.addSymbol(newAttValue);
3278                }
3279            }
3280
3281            return defaultAttValue;
3282    }
3283    /***
3284    public boolean scanDoctypeDecl(boolean standalone) throws Exception {
3285        fStandaloneReader = standalone ? fEntityHandler.getReaderId() : -1;
3286        fDeclsAreExternal = false;
3287        if (!fDTDScanner.scanDoctypeDecl()) {
3288            return false;
3289        }
3290        if (fDTDScanner.getReadingExternalEntity()) {
3291            fDTDScanner.scanDecls(true);
3292        }
3293        fDTDHandler.endDTD();
3294        return true;
3295    }
3296    /***/

3297
3298} // class XMLDTDScanner
3299
Popular Tags