KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > org > apache > xerces > internal > impl > XMLEntityScanner


1 /*
2  * The Apache Software License, Version 1.1
3  *
4  *
5  * Copyright (c) 1999-2003 The Apache Software Foundation.
6  * All rights 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 com.sun.org.apache.xerces.internal.impl;
59
60 import java.io.EOFException JavaDoc;
61 import java.io.IOException JavaDoc;
62 import java.util.Locale JavaDoc;
63
64 import com.sun.org.apache.xerces.internal.impl.io.UCSReader;
65 import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter;
66 import com.sun.org.apache.xerces.internal.util.SymbolTable;
67 import com.sun.org.apache.xerces.internal.util.XMLChar;
68 import com.sun.org.apache.xerces.internal.util.XMLStringBuffer;
69 import com.sun.org.apache.xerces.internal.xni.QName;
70 import com.sun.org.apache.xerces.internal.xni.XMLLocator;
71 import com.sun.org.apache.xerces.internal.xni.XMLString;
72
73 /**
74  * Implements the entity scanner methods.
75  *
76  * @author Andy Clark, IBM
77  * @author Neil Graham, IBM
78  * @version $Id: XMLEntityScanner.java,v 1.19 2003/11/13 18:45:59 mrglavas Exp $
79  */

80
81 public class XMLEntityScanner implements XMLLocator {
82
83     // constants
84
private static final boolean DEBUG_ENCODINGS = false;
85     private static final boolean DEBUG_BUFFER = false;
86
87     //
88
// Data
89
//
90

91     private XMLEntityManager fEntityManager = null;
92     protected XMLEntityManager.ScannedEntity fCurrentEntity = null;
93
94     protected SymbolTable fSymbolTable = null;
95
96     protected int fBufferSize = XMLEntityManager.DEFAULT_BUFFER_SIZE;
97
98     /**
99      * Error reporter. This property identifier is:
100      * http://apache.org/xml/properties/internal/error-reporter
101      */

102     protected XMLErrorReporter fErrorReporter;
103     //
104
// Constructors
105
//
106

107     /** Default constructor. */
108     public XMLEntityScanner() {
109     } // <init>()
110

111     //
112
// XMLEntityScanner methods
113
//
114

115     /**
116      * Returns the base system identifier of the currently scanned
117      * entity, or null if none is available.
118      */

119     public String JavaDoc getBaseSystemId() {
120         return (fCurrentEntity != null && fCurrentEntity.entityLocation != null) ? fCurrentEntity.entityLocation.getExpandedSystemId() : null;
121     } // getBaseSystemId():String
122

123     /**
124      * Sets the encoding of the scanner. This method is used by the
125      * scanners if the XMLDecl or TextDecl line contains an encoding
126      * pseudo-attribute.
127      * <p>
128      * <strong>Note:</strong> The underlying character reader on the
129      * current entity will be changed to accomodate the new encoding.
130      * However, the new encoding is ignored if the current reader was
131      * not constructed from an input stream (e.g. an external entity
132      * that is resolved directly to the appropriate java.io.Reader
133      * object).
134      *
135      * @param encoding The IANA encoding name of the new encoding.
136      *
137      * @throws IOException Thrown if the new encoding is not supported.
138      *
139      * @see com.sun.org.apache.xerces.internal.util.EncodingMap
140      */

141     public void setEncoding(String JavaDoc encoding) throws IOException JavaDoc {
142
143         if (DEBUG_ENCODINGS) {
144             System.out.println("$$$ setEncoding: "+encoding);
145         }
146
147         if (fCurrentEntity.stream != null) {
148             // if the encoding is the same, don't change the reader and
149
// re-use the original reader used by the OneCharReader
150
// NOTE: Besides saving an object, this overcomes deficiencies
151
// in the UTF-16 reader supplied with the standard Java
152
// distribution (up to and including 1.3). The UTF-16
153
// decoder buffers 8K blocks even when only asked to read
154
// a single char! -Ac
155
if (fCurrentEntity.encoding == null ||
156                 !fCurrentEntity.encoding.equals(encoding)) {
157                 // UTF-16 is a bit of a special case. If the encoding is UTF-16,
158
// and we know the endian-ness, we shouldn't change readers.
159
// If it's ISO-10646-UCS-(2|4), then we'll have to deduce
160
// the endian-ness from the encoding we presently have.
161
if(fCurrentEntity.encoding != null && fCurrentEntity.encoding.startsWith("UTF-16")) {
162                     String JavaDoc ENCODING = encoding.toUpperCase(Locale.ENGLISH);
163                     if(ENCODING.equals("UTF-16")) return;
164                     if(ENCODING.equals("ISO-10646-UCS-4")) {
165                         if(fCurrentEntity.encoding.equals("UTF-16BE")) {
166                             fCurrentEntity.reader = new UCSReader(fCurrentEntity.stream, UCSReader.UCS4BE);
167                         } else {
168                             fCurrentEntity.reader = new UCSReader(fCurrentEntity.stream, UCSReader.UCS4LE);
169                         }
170                         return;
171                     }
172                     if(ENCODING.equals("ISO-10646-UCS-2")) {
173                         if(fCurrentEntity.encoding.equals("UTF-16BE")) {
174                             fCurrentEntity.reader = new UCSReader(fCurrentEntity.stream, UCSReader.UCS2BE);
175                         } else {
176                             fCurrentEntity.reader = new UCSReader(fCurrentEntity.stream, UCSReader.UCS2LE);
177                         }
178                         return;
179                     }
180                 }
181                 // wrap a new reader around the input stream, changing
182
// the encoding
183
if (DEBUG_ENCODINGS) {
184                     System.out.println("$$$ creating new reader from stream: "+
185                                     fCurrentEntity.stream);
186                 }
187                 //fCurrentEntity.stream.reset();
188
fCurrentEntity.setReader(fCurrentEntity.stream, encoding, null);
189                 fCurrentEntity.encoding = encoding;
190             } else {
191                 if (DEBUG_ENCODINGS)
192                     System.out.println("$$$ reusing old reader on stream");
193             }
194         }
195
196     } // setEncoding(String)
197

198     /** Returns true if the current entity being scanned is external. */
199     public boolean isExternal() {
200         return fCurrentEntity.isExternal();
201     } // isExternal():boolean
202

203     /**
204      * Returns the next character on the input.
205      * <p>
206      * <strong>Note:</strong> The character is <em>not</em> consumed.
207      *
208      * @throws IOException Thrown if i/o error occurs.
209      * @throws EOFException Thrown on end of file.
210      */

211     public int peekChar() throws IOException JavaDoc {
212         if (DEBUG_BUFFER) {
213             System.out.print("(peekChar: ");
214             XMLEntityManager.print(fCurrentEntity);
215             System.out.println();
216         }
217
218         // load more characters, if needed
219
if (fCurrentEntity.position == fCurrentEntity.count) {
220             load(0, true);
221         }
222
223         // peek at character
224
int c = fCurrentEntity.ch[fCurrentEntity.position];
225
226         // return peeked character
227
if (DEBUG_BUFFER) {
228             System.out.print(")peekChar: ");
229             XMLEntityManager.print(fCurrentEntity);
230             if (fCurrentEntity.isExternal()) {
231                 System.out.println(" -> '"+(c!='\r'?(char)c:'\n')+"'");
232             }
233             else {
234                 System.out.println(" -> '"+(char)c+"'");
235             }
236         }
237         if (fCurrentEntity.isExternal()) {
238             return c != '\r' ? c : '\n';
239         }
240         else {
241             return c;
242         }
243
244     } // peekChar():int
245

246     /**
247      * Returns the next character on the input.
248      * <p>
249      * <strong>Note:</strong> The character is consumed.
250      *
251      * @throws IOException Thrown if i/o error occurs.
252      * @throws EOFException Thrown on end of file.
253      */

254     public int scanChar() throws IOException JavaDoc {
255         if (DEBUG_BUFFER) {
256             System.out.print("(scanChar: ");
257             XMLEntityManager.print(fCurrentEntity);
258             System.out.println();
259         }
260
261         // load more characters, if needed
262
if (fCurrentEntity.position == fCurrentEntity.count) {
263             load(0, true);
264         }
265
266         // scan character
267
int c = fCurrentEntity.ch[fCurrentEntity.position++];
268         boolean external = false;
269         if (c == '\n' ||
270             (c == '\r' && (external = fCurrentEntity.isExternal()))) {
271             fCurrentEntity.lineNumber++;
272             fCurrentEntity.columnNumber = 1;
273             if (fCurrentEntity.position == fCurrentEntity.count) {
274                 fCurrentEntity.ch[0] = (char)c;
275                 load(1, false);
276             }
277             if (c == '\r' && external) {
278                 if (fCurrentEntity.ch[fCurrentEntity.position++] != '\n') {
279                     fCurrentEntity.position--;
280                 }
281                 c = '\n';
282             }
283         }
284
285         // return character that was scanned
286
if (DEBUG_BUFFER) {
287             System.out.print(")scanChar: ");
288             XMLEntityManager.print(fCurrentEntity);
289             System.out.println(" -> '"+(char)c+"'");
290         }
291         fCurrentEntity.columnNumber++;
292         return c;
293
294     } // scanChar():int
295

296     /**
297      * Returns a string matching the NMTOKEN production appearing immediately
298      * on the input as a symbol, or null if NMTOKEN Name string is present.
299      * <p>
300      * <strong>Note:</strong> The NMTOKEN characters are consumed.
301      * <p>
302      * <strong>Note:</strong> The string returned must be a symbol. The
303      * SymbolTable can be used for this purpose.
304      *
305      * @throws IOException Thrown if i/o error occurs.
306      * @throws EOFException Thrown on end of file.
307      *
308      * @see com.sun.org.apache.xerces.internal.util.SymbolTable
309      * @see com.sun.org.apache.xerces.internal.util.XMLChar#isName
310      */

311     public String JavaDoc scanNmtoken() throws IOException JavaDoc {
312         if (DEBUG_BUFFER) {
313             System.out.print("(scanNmtoken: ");
314             XMLEntityManager.print(fCurrentEntity);
315             System.out.println();
316         }
317
318         // load more characters, if needed
319
if (fCurrentEntity.position == fCurrentEntity.count) {
320             load(0, true);
321         }
322
323         // scan nmtoken
324
int offset = fCurrentEntity.position;
325         while (XMLChar.isName(fCurrentEntity.ch[fCurrentEntity.position])) {
326             if (++fCurrentEntity.position == fCurrentEntity.count) {
327                 int length = fCurrentEntity.position - offset;
328                 if (length == fCurrentEntity.ch.length) {
329                     // bad luck we have to resize our buffer
330
char[] tmp = new char[fCurrentEntity.ch.length << 1];
331                     System.arraycopy(fCurrentEntity.ch, offset,
332                                      tmp, 0, length);
333                     fCurrentEntity.ch = tmp;
334                 }
335                 else {
336                     System.arraycopy(fCurrentEntity.ch, offset,
337                                      fCurrentEntity.ch, 0, length);
338                 }
339                 offset = 0;
340                 if (load(length, false)) {
341                     break;
342                 }
343             }
344         }
345         int length = fCurrentEntity.position - offset;
346         fCurrentEntity.columnNumber += length;
347
348         // return nmtoken
349
String JavaDoc symbol = null;
350         if (length > 0) {
351             symbol = fSymbolTable.addSymbol(fCurrentEntity.ch, offset, length);
352         }
353         if (DEBUG_BUFFER) {
354             System.out.print(")scanNmtoken: ");
355             XMLEntityManager.print(fCurrentEntity);
356             System.out.println(" -> "+String.valueOf(symbol));
357         }
358         return symbol;
359
360     } // scanNmtoken():String
361

362     /**
363      * Returns a string matching the Name production appearing immediately
364      * on the input as a symbol, or null if no Name string is present.
365      * <p>
366      * <strong>Note:</strong> The Name characters are consumed.
367      * <p>
368      * <strong>Note:</strong> The string returned must be a symbol. The
369      * SymbolTable can be used for this purpose.
370      *
371      * @throws IOException Thrown if i/o error occurs.
372      * @throws EOFException Thrown on end of file.
373      *
374      * @see com.sun.org.apache.xerces.internal.util.SymbolTable
375      * @see com.sun.org.apache.xerces.internal.util.XMLChar#isName
376      * @see com.sun.org.apache.xerces.internal.util.XMLChar#isNameStart
377      */

378     public String JavaDoc scanName() throws IOException JavaDoc {
379         if (DEBUG_BUFFER) {
380             System.out.print("(scanName: ");
381             XMLEntityManager.print(fCurrentEntity);
382             System.out.println();
383         }
384
385         // load more characters, if needed
386
if (fCurrentEntity.position == fCurrentEntity.count) {
387             load(0, true);
388         }
389
390         // scan name
391
int offset = fCurrentEntity.position;
392         if (XMLChar.isNameStart(fCurrentEntity.ch[offset])) {
393             if (++fCurrentEntity.position == fCurrentEntity.count) {
394                 fCurrentEntity.ch[0] = fCurrentEntity.ch[offset];
395                 offset = 0;
396                 if (load(1, false)) {
397                     fCurrentEntity.columnNumber++;
398                     String JavaDoc symbol = fSymbolTable.addSymbol(fCurrentEntity.ch, 0, 1);
399                     if (DEBUG_BUFFER) {
400                         System.out.print(")scanName: ");
401                         XMLEntityManager.print(fCurrentEntity);
402                         System.out.println(" -> "+String.valueOf(symbol));
403                     }
404                     return symbol;
405                 }
406             }
407             while (XMLChar.isName(fCurrentEntity.ch[fCurrentEntity.position])) {
408                 if (++fCurrentEntity.position == fCurrentEntity.count) {
409                     int length = fCurrentEntity.position - offset;
410                     if (length == fCurrentEntity.ch.length) {
411                         // bad luck we have to resize our buffer
412
char[] tmp = new char[fCurrentEntity.ch.length << 1];
413                         System.arraycopy(fCurrentEntity.ch, offset,
414                                          tmp, 0, length);
415                         fCurrentEntity.ch = tmp;
416                     }
417                     else {
418                         System.arraycopy(fCurrentEntity.ch, offset,
419                                          fCurrentEntity.ch, 0, length);
420                     }
421                     offset = 0;
422                     if (load(length, false)) {
423                         break;
424                     }
425                 }
426             }
427         }
428         int length = fCurrentEntity.position - offset;
429         fCurrentEntity.columnNumber += length;
430
431         // return name
432
String JavaDoc symbol = null;
433         if (length > 0) {
434             symbol = fSymbolTable.addSymbol(fCurrentEntity.ch, offset, length);
435         }
436         if (DEBUG_BUFFER) {
437             System.out.print(")scanName: ");
438             XMLEntityManager.print(fCurrentEntity);
439             System.out.println(" -> "+String.valueOf(symbol));
440         }
441         return symbol;
442
443     } // scanName():String
444

445     /**
446      * Returns a string matching the NCName production appearing immediately
447      * on the input as a symbol, or null if no NCName string is present.
448      * <p>
449      * <strong>Note:</strong> The NCName characters are consumed.
450      * <p>
451      * <strong>Note:</strong> The string returned must be a symbol. The
452      * SymbolTable can be used for this purpose.
453      *
454      * @throws IOException Thrown if i/o error occurs.
455      * @throws EOFException Thrown on end of file.
456      *
457      * @see com.sun.org.apache.xerces.internal.util.SymbolTable
458      * @see com.sun.org.apache.xerces.internal.util.XMLChar#isNCName
459      * @see com.sun.org.apache.xerces.internal.util.XMLChar#isNCNameStart
460      */

461     public String JavaDoc scanNCName() throws IOException JavaDoc {
462         if (DEBUG_BUFFER) {
463             System.out.print("(scanNCName: ");
464             XMLEntityManager.print(fCurrentEntity);
465             System.out.println();
466         }
467
468         // load more characters, if needed
469
if (fCurrentEntity.position == fCurrentEntity.count) {
470             load(0, true);
471         }
472
473         // scan name
474
int offset = fCurrentEntity.position;
475         if (XMLChar.isNCNameStart(fCurrentEntity.ch[offset])) {
476             if (++fCurrentEntity.position == fCurrentEntity.count) {
477                 fCurrentEntity.ch[0] = fCurrentEntity.ch[offset];
478                 offset = 0;
479                 if (load(1, false)) {
480                     fCurrentEntity.columnNumber++;
481                     String JavaDoc symbol = fSymbolTable.addSymbol(fCurrentEntity.ch, 0, 1);
482                     if (DEBUG_BUFFER) {
483                         System.out.print(")scanNCName: ");
484                         XMLEntityManager.print(fCurrentEntity);
485                         System.out.println(" -> "+String.valueOf(symbol));
486                     }
487                     return symbol;
488                 }
489             }
490             while (XMLChar.isNCName(fCurrentEntity.ch[fCurrentEntity.position])) {
491                 if (++fCurrentEntity.position == fCurrentEntity.count) {
492                     int length = fCurrentEntity.position - offset;
493                     if (length == fCurrentEntity.ch.length) {
494                         // bad luck we have to resize our buffer
495
char[] tmp = new char[fCurrentEntity.ch.length << 1];
496                         System.arraycopy(fCurrentEntity.ch, offset,
497                                          tmp, 0, length);
498                         fCurrentEntity.ch = tmp;
499                     }
500                     else {
501                         System.arraycopy(fCurrentEntity.ch, offset,
502                                          fCurrentEntity.ch, 0, length);
503                     }
504                     offset = 0;
505                     if (load(length, false)) {
506                         break;
507                     }
508                 }
509             }
510         }
511         int length = fCurrentEntity.position - offset;
512         fCurrentEntity.columnNumber += length;
513
514         // return name
515
String JavaDoc symbol = null;
516         if (length > 0) {
517             symbol = fSymbolTable.addSymbol(fCurrentEntity.ch, offset, length);
518         }
519         if (DEBUG_BUFFER) {
520             System.out.print(")scanNCName: ");
521             XMLEntityManager.print(fCurrentEntity);
522             System.out.println(" -> "+String.valueOf(symbol));
523         }
524         return symbol;
525
526     } // scanNCName():String
527

528     /**
529      * Scans a qualified name from the input, setting the fields of the
530      * QName structure appropriately.
531      * <p>
532      * <strong>Note:</strong> The qualified name characters are consumed.
533      * <p>
534      * <strong>Note:</strong> The strings used to set the values of the
535      * QName structure must be symbols. The SymbolTable can be used for
536      * this purpose.
537      *
538      * @param qname The qualified name structure to fill.
539      *
540      * @return Returns true if a qualified name appeared immediately on
541      * the input and was scanned, false otherwise.
542      *
543      * @throws IOException Thrown if i/o error occurs.
544      * @throws EOFException Thrown on end of file.
545      *
546      * @see com.sun.org.apache.xerces.internal.util.SymbolTable
547      * @see com.sun.org.apache.xerces.internal.util.XMLChar#isName
548      * @see com.sun.org.apache.xerces.internal.util.XMLChar#isNameStart
549      */

550     public boolean scanQName(QName qname) throws IOException JavaDoc {
551         if (DEBUG_BUFFER) {
552             System.out.print("(scanQName, "+qname+": ");
553             XMLEntityManager.print(fCurrentEntity);
554             System.out.println();
555         }
556
557         // load more characters, if needed
558
if (fCurrentEntity.position == fCurrentEntity.count) {
559             load(0, true);
560         }
561
562         // scan qualified name
563
int offset = fCurrentEntity.position;
564         if (XMLChar.isNCNameStart(fCurrentEntity.ch[offset])) {
565             if (++fCurrentEntity.position == fCurrentEntity.count) {
566                 fCurrentEntity.ch[0] = fCurrentEntity.ch[offset];
567                 offset = 0;
568                 if (load(1, false)) {
569                     fCurrentEntity.columnNumber++;
570                     String JavaDoc name =
571                         fSymbolTable.addSymbol(fCurrentEntity.ch, 0, 1);
572                     qname.setValues(null, name, name, null);
573                     if (DEBUG_BUFFER) {
574                         System.out.print(")scanQName, "+qname+": ");
575                         XMLEntityManager.print(fCurrentEntity);
576                         System.out.println(" -> true");
577                     }
578                     return true;
579                 }
580             }
581             int index = -1;
582             while (XMLChar.isName(fCurrentEntity.ch[fCurrentEntity.position])) {
583                 char c = fCurrentEntity.ch[fCurrentEntity.position];
584
585                 if (c == ':') {
586                     if (index != -1) {
587                         break;
588                     }
589                     index = fCurrentEntity.position;
590                 }
591                 if (++fCurrentEntity.position == fCurrentEntity.count) {
592                     int length = fCurrentEntity.position - offset;
593                     if (length == fCurrentEntity.ch.length) {
594                         // bad luck we have to resize our buffer
595
char[] tmp = new char[fCurrentEntity.ch.length << 1];
596                         System.arraycopy(fCurrentEntity.ch, offset,
597                                          tmp, 0, length);
598                         fCurrentEntity.ch = tmp;
599                     }
600                     else {
601                         System.arraycopy(fCurrentEntity.ch, offset,
602                                          fCurrentEntity.ch, 0, length);
603                     }
604                     if (index != -1) {
605                         index = index - offset;
606                     }
607                     offset = 0;
608                     if (load(length, false)) {
609                         break;
610                     }
611                 }
612             }
613             int length = fCurrentEntity.position - offset;
614             fCurrentEntity.columnNumber += length;
615             if (length > 0) {
616                 String JavaDoc prefix = null;
617                 String JavaDoc localpart = null;
618                 String JavaDoc rawname = fSymbolTable.addSymbol(fCurrentEntity.ch,
619                                                         offset, length);
620                 if (index != -1) {
621                     int prefixLength = index - offset;
622                     prefix = fSymbolTable.addSymbol(fCurrentEntity.ch,
623                                                     offset, prefixLength);
624                     int len = length - prefixLength - 1;
625                     int startLocal = index +1;
626                     if (!XMLChar.isNCNameStart(fCurrentEntity.ch[startLocal])){
627                         fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
628                                                  "IllegalQName",
629                                                   null,
630                                                   XMLErrorReporter.SEVERITY_FATAL_ERROR);
631                     }
632                     localpart = fSymbolTable.addSymbol(fCurrentEntity.ch,
633                                                        startLocal, len);
634
635                 }
636                 else {
637                     localpart = rawname;
638                 }
639                 qname.setValues(prefix, localpart, rawname, null);
640                 if (DEBUG_BUFFER) {
641                     System.out.print(")scanQName, "+qname+": ");
642                     XMLEntityManager.print(fCurrentEntity);
643                     System.out.println(" -> true");
644                 }
645                 return true;
646             }
647         }
648
649         // no qualified name found
650
if (DEBUG_BUFFER) {
651             System.out.print(")scanQName, "+qname+": ");
652             XMLEntityManager.print(fCurrentEntity);
653             System.out.println(" -> false");
654         }
655         return false;
656
657     } // scanQName(QName):boolean
658

659     /**
660      * Scans a range of parsed character data, setting the fields of the
661      * XMLString structure, appropriately.
662      * <p>
663      * <strong>Note:</strong> The characters are consumed.
664      * <p>
665      * <strong>Note:</strong> This method does not guarantee to return
666      * the longest run of parsed character data. This method may return
667      * before markup due to reaching the end of the input buffer or any
668      * other reason.
669      * <p>
670      * <strong>Note:</strong> The fields contained in the XMLString
671      * structure are not guaranteed to remain valid upon subsequent calls
672      * to the entity scanner. Therefore, the caller is responsible for
673      * immediately using the returned character data or making a copy of
674      * the character data.
675      *
676      * @param content The content structure to fill.
677      *
678      * @return Returns the next character on the input, if known. This
679      * value may be -1 but this does <em>note</em> designate
680      * end of file.
681      *
682      * @throws IOException Thrown if i/o error occurs.
683      * @throws EOFException Thrown on end of file.
684      */

685     public int scanContent(XMLString content) throws IOException JavaDoc {
686         if (DEBUG_BUFFER) {
687             System.out.print("(scanContent: ");
688             XMLEntityManager.print(fCurrentEntity);
689             System.out.println();
690         }
691
692         // load more characters, if needed
693
if (fCurrentEntity.position == fCurrentEntity.count) {
694             load(0, true);
695         }
696         else if (fCurrentEntity.position == fCurrentEntity.count - 1) {
697             fCurrentEntity.ch[0] = fCurrentEntity.ch[fCurrentEntity.count - 1];
698             load(1, false);
699             fCurrentEntity.position = 0;
700         }
701
702         // normalize newlines
703
int offset = fCurrentEntity.position;
704         int c = fCurrentEntity.ch[offset];
705         int newlines = 0;
706         boolean external = fCurrentEntity.isExternal();
707         if (c == '\n' || (c == '\r' && external)) {
708             if (DEBUG_BUFFER) {
709                 System.out.print("[newline, "+offset+", "+fCurrentEntity.position+": ");
710                 XMLEntityManager.print(fCurrentEntity);
711                 System.out.println();
712             }
713             do {
714                 c = fCurrentEntity.ch[fCurrentEntity.position++];
715                 if (c == '\r' && external) {
716                     newlines++;
717                     fCurrentEntity.lineNumber++;
718                     fCurrentEntity.columnNumber = 1;
719                     if (fCurrentEntity.position == fCurrentEntity.count) {
720                         offset = 0;
721                         fCurrentEntity.position = newlines;
722                         if (load(newlines, false)) {
723                             break;
724                         }
725                     }
726                     if (fCurrentEntity.ch[fCurrentEntity.position] == '\n') {
727                         fCurrentEntity.position++;
728                         offset++;
729                     }
730                     /*** NEWLINE NORMALIZATION ***/
731                     else {
732                         newlines++;
733                     }
734                 }
735                 else if (c == '\n') {
736                     newlines++;
737                     fCurrentEntity.lineNumber++;
738                     fCurrentEntity.columnNumber = 1;
739                     if (fCurrentEntity.position == fCurrentEntity.count) {
740                         offset = 0;
741                         fCurrentEntity.position = newlines;
742                         if (load(newlines, false)) {
743                             break;
744                         }
745                     }
746                 }
747                 else {
748                     fCurrentEntity.position--;
749                     break;
750                 }
751             } while (fCurrentEntity.position < fCurrentEntity.count - 1);
752             for (int i = offset; i < fCurrentEntity.position; i++) {
753                 fCurrentEntity.ch[i] = '\n';
754             }
755             int length = fCurrentEntity.position - offset;
756             if (fCurrentEntity.position == fCurrentEntity.count - 1) {
757                 content.setValues(fCurrentEntity.ch, offset, length);
758                 if (DEBUG_BUFFER) {
759                     System.out.print("]newline, "+offset+", "+fCurrentEntity.position+": ");
760                     XMLEntityManager.print(fCurrentEntity);
761                     System.out.println();
762                 }
763                 return -1;
764             }
765             if (DEBUG_BUFFER) {
766                 System.out.print("]newline, "+offset+", "+fCurrentEntity.position+": ");
767                 XMLEntityManager.print(fCurrentEntity);
768                 System.out.println();
769             }
770         }
771
772         // inner loop, scanning for content
773
while (fCurrentEntity.position < fCurrentEntity.count) {
774             c = fCurrentEntity.ch[fCurrentEntity.position++];
775             if (!XMLChar.isContent(c)) {
776                 fCurrentEntity.position--;
777                 break;
778             }
779         }
780         int length = fCurrentEntity.position - offset;
781         fCurrentEntity.columnNumber += length - newlines;
782         content.setValues(fCurrentEntity.ch, offset, length);
783
784         // return next character
785
if (fCurrentEntity.position != fCurrentEntity.count) {
786             c = fCurrentEntity.ch[fCurrentEntity.position];
787             // REVISIT: Does this need to be updated to fix the
788
// #x0D ^#x0A newline normalization problem? -Ac
789
if (c == '\r' && external) {
790                 c = '\n';
791             }
792         }
793         else {
794             c = -1;
795         }
796         if (DEBUG_BUFFER) {
797             System.out.print(")scanContent: ");
798             XMLEntityManager.print(fCurrentEntity);
799             System.out.println(" -> '"+(char)c+"'");
800         }
801         return c;
802
803     } // scanContent(XMLString):int
804

805     /**
806      * Scans a range of attribute value data, setting the fields of the
807      * XMLString structure, appropriately.
808      * <p>
809      * <strong>Note:</strong> The characters are consumed.
810      * <p>
811      * <strong>Note:</strong> This method does not guarantee to return
812      * the longest run of attribute value data. This method may return
813      * before the quote character due to reaching the end of the input
814      * buffer or any other reason.
815      * <p>
816      * <strong>Note:</strong> The fields contained in the XMLString
817      * structure are not guaranteed to remain valid upon subsequent calls
818      * to the entity scanner. Therefore, the caller is responsible for
819      * immediately using the returned character data or making a copy of
820      * the character data.
821      *
822      * @param quote The quote character that signifies the end of the
823      * attribute value data.
824      * @param content The content structure to fill.
825      *
826      * @return Returns the next character on the input, if known. This
827      * value may be -1 but this does <em>note</em> designate
828      * end of file.
829      *
830      * @throws IOException Thrown if i/o error occurs.
831      * @throws EOFException Thrown on end of file.
832      */

833     public int scanLiteral(int quote, XMLString content)
834         throws IOException JavaDoc {
835         if (DEBUG_BUFFER) {
836             System.out.print("(scanLiteral, '"+(char)quote+"': ");
837             XMLEntityManager.print(fCurrentEntity);
838             System.out.println();
839         }
840
841         // load more characters, if needed
842
if (fCurrentEntity.position == fCurrentEntity.count) {
843             load(0, true);
844         }
845         else if (fCurrentEntity.position == fCurrentEntity.count - 1) {
846             fCurrentEntity.ch[0] = fCurrentEntity.ch[fCurrentEntity.count - 1];
847             load(1, false);
848             fCurrentEntity.position = 0;
849         }
850
851         // normalize newlines
852
int offset = fCurrentEntity.position;
853         int c = fCurrentEntity.ch[offset];
854         int newlines = 0;
855         boolean external = fCurrentEntity.isExternal();
856         if (c == '\n' || (c == '\r' && external)) {
857             if (DEBUG_BUFFER) {
858                 System.out.print("[newline, "+offset+", "+fCurrentEntity.position+": ");
859                 XMLEntityManager.print(fCurrentEntity);
860                 System.out.println();
861             }
862             do {
863                 c = fCurrentEntity.ch[fCurrentEntity.position++];
864                 if (c == '\r' && external) {
865                     newlines++;
866                     fCurrentEntity.lineNumber++;
867                     fCurrentEntity.columnNumber = 1;
868                     if (fCurrentEntity.position == fCurrentEntity.count) {
869                         offset = 0;
870                         fCurrentEntity.position = newlines;
871                         if (load(newlines, false)) {
872                             break;
873                         }
874                     }
875                     if (fCurrentEntity.ch[fCurrentEntity.position] == '\n') {
876                         fCurrentEntity.position++;
877                         offset++;
878                     }
879                     /*** NEWLINE NORMALIZATION ***/
880                     else {
881                         newlines++;
882                     }
883                     /***/
884                 }
885                 else if (c == '\n') {
886                     newlines++;
887                     fCurrentEntity.lineNumber++;
888                     fCurrentEntity.columnNumber = 1;
889                     if (fCurrentEntity.position == fCurrentEntity.count) {
890                         offset = 0;
891                         fCurrentEntity.position = newlines;
892                         if (load(newlines, false)) {
893                             break;
894                         }
895                     }
896                 }
897                 else {
898                     fCurrentEntity.position--;
899                     break;
900                 }
901             } while (fCurrentEntity.position < fCurrentEntity.count - 1);
902             for (int i = offset; i < fCurrentEntity.position; i++) {
903                 fCurrentEntity.ch[i] = '\n';
904             }
905             int length = fCurrentEntity.position - offset;
906             if (fCurrentEntity.position == fCurrentEntity.count - 1) {
907                 content.setValues(fCurrentEntity.ch, offset, length);
908                 if (DEBUG_BUFFER) {
909                     System.out.print("]newline, "+offset+", "+fCurrentEntity.position+": ");
910                     XMLEntityManager.print(fCurrentEntity);
911                     System.out.println();
912                 }
913                 return -1;
914             }
915             if (DEBUG_BUFFER) {
916                 System.out.print("]newline, "+offset+", "+fCurrentEntity.position+": ");
917                 XMLEntityManager.print(fCurrentEntity);
918                 System.out.println();
919             }
920         }
921
922         // scan literal value
923
while (fCurrentEntity.position < fCurrentEntity.count) {
924             c = fCurrentEntity.ch[fCurrentEntity.position++];
925             if ((c == quote &&
926                  (!fCurrentEntity.literal || external))
927                 || c == '%' || !XMLChar.isContent(c)) {
928                 fCurrentEntity.position--;
929                 break;
930             }
931         }
932         int length = fCurrentEntity.position - offset;
933         fCurrentEntity.columnNumber += length - newlines;
934         content.setValues(fCurrentEntity.ch, offset, length);
935
936         // return next character
937
if (fCurrentEntity.position != fCurrentEntity.count) {
938             c = fCurrentEntity.ch[fCurrentEntity.position];
939             // NOTE: We don't want to accidentally signal the
940
// end of the literal if we're expanding an
941
// entity appearing in the literal. -Ac
942
if (c == quote && fCurrentEntity.literal) {
943                 c = -1;
944             }
945         }
946         else {
947             c = -1;
948         }
949         if (DEBUG_BUFFER) {
950             System.out.print(")scanLiteral, '"+(char)quote+"': ");
951             XMLEntityManager.print(fCurrentEntity);
952             System.out.println(" -> '"+(char)c+"'");
953         }
954         return c;
955
956     } // scanLiteral(int,XMLString):int
957

958     /**
959      * Scans a range of character data up to the specified delimiter,
960      * setting the fields of the XMLString structure, appropriately.
961      * <p>
962      * <strong>Note:</strong> The characters are consumed.
963      * <p>
964      * <strong>Note:</strong> This assumes that the internal buffer is
965      * at least the same size, or bigger, than the length of the delimiter
966      * and that the delimiter contains at least one character.
967      * <p>
968      * <strong>Note:</strong> This method does not guarantee to return
969      * the longest run of character data. This method may return before
970      * the delimiter due to reaching the end of the input buffer or any
971      * other reason.
972      * <p>
973      * <strong>Note:</strong> The fields contained in the XMLString
974      * structure are not guaranteed to remain valid upon subsequent calls
975      * to the entity scanner. Therefore, the caller is responsible for
976      * immediately using the returned character data or making a copy of
977      * the character data.
978      *
979      * @param delimiter The string that signifies the end of the character
980      * data to be scanned.
981      * @param data The data structure to fill.
982      *
983      * @return Returns true if there is more data to scan, false otherwise.
984      *
985      * @throws IOException Thrown if i/o error occurs.
986      * @throws EOFException Thrown on end of file.
987      */

988     public boolean scanData(String JavaDoc delimiter, XMLStringBuffer buffer)
989         throws IOException JavaDoc {
990
991         // REVISIT: This method does not need to use a string buffer.
992
// The change would avoid the array copies and increase
993
// performance. -Ac
994
//
995
// Currently, this method is called for scanning CDATA
996
// sections, comments, and processing instruction data.
997
// So if this code is updated to NOT buffer, the scanning
998
// code for comments and processing instructions will
999
// need to be updated to do its own buffering. The code
1000
// for CDATA sections is safe as-is. -Ac
1001

1002        boolean found = false;
1003        int delimLen = delimiter.length();
1004        char charAt0 = delimiter.charAt(0);
1005        boolean external = fCurrentEntity.isExternal();
1006        if (DEBUG_BUFFER) {
1007            System.out.print("(scanData: ");
1008            XMLEntityManager.print(fCurrentEntity);
1009            System.out.println();
1010        }
1011
1012        // load more characters, if needed
1013

1014        if (fCurrentEntity.position == fCurrentEntity.count) {
1015            load(0, true);
1016        }
1017
1018        boolean bNextEntity = false;
1019
1020        while ((fCurrentEntity.position >= fCurrentEntity.count - delimLen)
1021            && (!bNextEntity))
1022        {
1023          System.arraycopy(fCurrentEntity.ch,
1024                           fCurrentEntity.position,
1025                           fCurrentEntity.ch,
1026                           0,
1027                           fCurrentEntity.count - fCurrentEntity.position);
1028
1029          bNextEntity = load(fCurrentEntity.count - fCurrentEntity.position, false);
1030          fCurrentEntity.position = 0;
1031        }
1032
1033        if (fCurrentEntity.position >= fCurrentEntity.count - delimLen) {
1034            // something must be wrong with the input: e.g., file ends an unterminated comment
1035
int length = fCurrentEntity.count - fCurrentEntity.position;
1036            buffer.append (fCurrentEntity.ch, fCurrentEntity.position, length);
1037            fCurrentEntity.columnNumber += fCurrentEntity.count;
1038            fCurrentEntity.position = fCurrentEntity.count;
1039            load(0,true);
1040            return false;
1041        }
1042
1043        // normalize newlines
1044
int offset = fCurrentEntity.position;
1045        int c = fCurrentEntity.ch[offset];
1046        int newlines = 0;
1047        if (c == '\n' || (c == '\r' && external)) {
1048            if (DEBUG_BUFFER) {
1049                System.out.print("[newline, "+offset+", "+fCurrentEntity.position+": ");
1050                XMLEntityManager.print(fCurrentEntity);
1051                System.out.println();
1052            }
1053            do {
1054                c = fCurrentEntity.ch[fCurrentEntity.position++];
1055                if (c == '\r' && external) {
1056                    newlines++;
1057                    fCurrentEntity.lineNumber++;
1058                    fCurrentEntity.columnNumber = 1;
1059                    if (fCurrentEntity.position == fCurrentEntity.count) {
1060                        offset = 0;
1061                        fCurrentEntity.position = newlines;
1062                        if (load(newlines, false)) {
1063                            break;
1064                        }
1065                    }
1066                    if (fCurrentEntity.ch[fCurrentEntity.position] == '\n') {
1067                        fCurrentEntity.position++;
1068                        offset++;
1069                    }
1070                    /*** NEWLINE NORMALIZATION ***/
1071                    else {
1072                        newlines++;
1073                    }
1074                }
1075                else if (c == '\n') {
1076                    newlines++;
1077                    fCurrentEntity.lineNumber++;
1078                    fCurrentEntity.columnNumber = 1;
1079                    if (fCurrentEntity.position == fCurrentEntity.count) {
1080                        offset = 0;
1081                        fCurrentEntity.position = newlines;
1082                        fCurrentEntity.count = newlines;
1083                        if (load(newlines, false)) {
1084                            break;
1085                        }
1086                    }
1087                }
1088                else {
1089                    fCurrentEntity.position--;
1090                    break;
1091                }
1092            } while (fCurrentEntity.position < fCurrentEntity.count - 1);
1093            for (int i = offset; i < fCurrentEntity.position; i++) {
1094                fCurrentEntity.ch[i] = '\n';
1095            }
1096            int length = fCurrentEntity.position - offset;
1097            if (fCurrentEntity.position == fCurrentEntity.count - 1) {
1098                buffer.append(fCurrentEntity.ch, offset, length);
1099                if (DEBUG_BUFFER) {
1100                    System.out.print("]newline, "+offset+", "+fCurrentEntity.position+": ");
1101                    XMLEntityManager.print(fCurrentEntity);
1102                    System.out.println();
1103                }
1104                return true;
1105            }
1106            if (DEBUG_BUFFER) {
1107                System.out.print("]newline, "+offset+", "+fCurrentEntity.position+": ");
1108                XMLEntityManager.print(fCurrentEntity);
1109                System.out.println();
1110            }
1111        }
1112
1113        // iterate over buffer looking for delimiter
1114
OUTER: while (fCurrentEntity.position < fCurrentEntity.count) {
1115            c = fCurrentEntity.ch[fCurrentEntity.position++];
1116            if (c == charAt0) {
1117                // looks like we just hit the delimiter
1118
int delimOffset = fCurrentEntity.position - 1;
1119                for (int i = 1; i < delimLen; i++) {
1120                    if (fCurrentEntity.position == fCurrentEntity.count) {
1121                        fCurrentEntity.position -= i;
1122                        break OUTER;
1123                    }
1124                    c = fCurrentEntity.ch[fCurrentEntity.position++];
1125                    if (delimiter.charAt(i) != c) {
1126                        fCurrentEntity.position--;
1127                        break;
1128                    }
1129                }
1130                if (fCurrentEntity.position == delimOffset + delimLen) {
1131                    found = true;
1132                    break;
1133                }
1134            }
1135            else if (c == '\n' || (external && c == '\r')) {
1136                fCurrentEntity.position--;
1137                break;
1138            }
1139            else if (XMLChar.isInvalid(c)) {
1140                fCurrentEntity.position--;
1141                int length = fCurrentEntity.position - offset;
1142                fCurrentEntity.columnNumber += length - newlines;
1143                buffer.append(fCurrentEntity.ch, offset, length);
1144                return true;
1145            }
1146        }
1147        int length = fCurrentEntity.position - offset;
1148        fCurrentEntity.columnNumber += length - newlines;
1149        if (found) {
1150            length -= delimLen;
1151        }
1152        buffer.append (fCurrentEntity.ch, offset, length);
1153
1154        // return true if string was skipped
1155
if (DEBUG_BUFFER) {
1156            System.out.print(")scanData: ");
1157            XMLEntityManager.print(fCurrentEntity);
1158            System.out.println(" -> " + !found);
1159        }
1160        return !found;
1161
1162    } // scanData(String,XMLString):boolean
1163

1164    /**
1165     * Skips a character appearing immediately on the input.
1166     * <p>
1167     * <strong>Note:</strong> The character is consumed only if it matches
1168     * the specified character.
1169     *
1170     * @param c The character to skip.
1171     *
1172     * @return Returns true if the character was skipped.
1173     *
1174     * @throws IOException Thrown if i/o error occurs.
1175     * @throws EOFException Thrown on end of file.
1176     */

1177    public boolean skipChar(int c) throws IOException JavaDoc {
1178        if (DEBUG_BUFFER) {
1179            System.out.print("(skipChar, '"+(char)c+"': ");
1180            XMLEntityManager.print(fCurrentEntity);
1181            System.out.println();
1182        }
1183
1184        // load more characters, if needed
1185
if (fCurrentEntity.position == fCurrentEntity.count) {
1186            load(0, true);
1187        }
1188
1189        // skip character
1190
int cc = fCurrentEntity.ch[fCurrentEntity.position];
1191        if (cc == c) {
1192            fCurrentEntity.position++;
1193            if (c == '\n') {
1194                fCurrentEntity.lineNumber++;
1195                fCurrentEntity.columnNumber = 1;
1196            }
1197            else {
1198                fCurrentEntity.columnNumber++;
1199            }
1200            if (DEBUG_BUFFER) {
1201                System.out.print(")skipChar, '"+(char)c+"': ");
1202                XMLEntityManager.print(fCurrentEntity);
1203                System.out.println(" -> true");
1204            }
1205            return true;
1206        }
1207        else if (c == '\n' && cc == '\r' && fCurrentEntity.isExternal()) {
1208            // handle newlines
1209
if (fCurrentEntity.position == fCurrentEntity.count) {
1210                fCurrentEntity.ch[0] = (char)cc;
1211                load(1, false);
1212            }
1213            fCurrentEntity.position++;
1214            if (fCurrentEntity.ch[fCurrentEntity.position] == '\n') {
1215                fCurrentEntity.position++;
1216            }
1217            fCurrentEntity.lineNumber++;
1218            fCurrentEntity.columnNumber = 1;
1219            if (DEBUG_BUFFER) {
1220                System.out.print(")skipChar, '"+(char)c+"': ");
1221                XMLEntityManager.print(fCurrentEntity);
1222                System.out.println(" -> true");
1223            }
1224            return true;
1225        }
1226
1227        // character was not skipped
1228
if (DEBUG_BUFFER) {
1229            System.out.print(")skipChar, '"+(char)c+"': ");
1230            XMLEntityManager.print(fCurrentEntity);
1231            System.out.println(" -> false");
1232        }
1233        return false;
1234
1235    } // skipChar(int):boolean
1236

1237    /**
1238     * Skips space characters appearing immediately on the input.
1239     * <p>
1240     * <strong>Note:</strong> The characters are consumed only if they are
1241     * space characters.
1242     *
1243     * @return Returns true if at least one space character was skipped.
1244     *
1245     * @throws IOException Thrown if i/o error occurs.
1246     * @throws EOFException Thrown on end of file.
1247     *
1248     * @see com.sun.org.apache.xerces.internal.util.XMLChar#isSpace
1249     */

1250    public boolean skipSpaces() throws IOException JavaDoc {
1251        if (DEBUG_BUFFER) {
1252            System.out.print("(skipSpaces: ");
1253            XMLEntityManager.print(fCurrentEntity);
1254            System.out.println();
1255        }
1256
1257        // load more characters, if needed
1258
if (fCurrentEntity.position == fCurrentEntity.count) {
1259            load(0, true);
1260        }
1261
1262        // skip spaces
1263
int c = fCurrentEntity.ch[fCurrentEntity.position];
1264        if (XMLChar.isSpace(c)) {
1265            boolean external = fCurrentEntity.isExternal();
1266            do {
1267                boolean entityChanged = false;
1268                // handle newlines
1269
if (c == '\n' || (external && c == '\r')) {
1270                    fCurrentEntity.lineNumber++;
1271                    fCurrentEntity.columnNumber = 1;
1272                    if (fCurrentEntity.position == fCurrentEntity.count - 1) {
1273                        fCurrentEntity.ch[0] = (char)c;
1274                        entityChanged = load(1, true);
1275                        if (!entityChanged)
1276                            // the load change the position to be 1,
1277
// need to restore it when entity not changed
1278
fCurrentEntity.position = 0;
1279                    }
1280                    if (c == '\r' && external) {
1281                        // REVISIT: Does this need to be updated to fix the
1282
// #x0D ^#x0A newline normalization problem? -Ac
1283
if (fCurrentEntity.ch[++fCurrentEntity.position] != '\n') {
1284                            fCurrentEntity.position--;
1285                        }
1286                    }
1287                    /*** NEWLINE NORMALIZATION ***
1288                    else {
1289                        if (fCurrentEntity.ch[fCurrentEntity.position + 1] == '\r'
1290                            && external) {
1291                            fCurrentEntity.position++;
1292                        }
1293                    }
1294                    /***/

1295                }
1296                else {
1297                    fCurrentEntity.columnNumber++;
1298                }
1299                // load more characters, if needed
1300
if (!entityChanged)
1301                    fCurrentEntity.position++;
1302                if (fCurrentEntity.position == fCurrentEntity.count) {
1303                    load(0, true);
1304                }
1305            } while (XMLChar.isSpace(c = fCurrentEntity.ch[fCurrentEntity.position]));
1306            if (DEBUG_BUFFER) {
1307                System.out.print(")skipSpaces: ");
1308                XMLEntityManager.print(fCurrentEntity);
1309                System.out.println(" -> true");
1310            }
1311            return true;
1312        }
1313
1314        // no spaces were found
1315
if (DEBUG_BUFFER) {
1316            System.out.print(")skipSpaces: ");
1317            XMLEntityManager.print(fCurrentEntity);
1318            System.out.println(" -> false");
1319        }
1320        return false;
1321
1322    } // skipSpaces():boolean
1323

1324    /**
1325     * Skips space characters appearing immediately on the input that would
1326     * match non-terminal S (0x09, 0x0A, 0x0D, 0x20) before end of line
1327     * normalization is performed. This is useful when scanning structures
1328     * such as the XMLDecl and TextDecl that can only contain US-ASCII
1329     * characters.
1330     * <p>
1331     * <strong>Note:</strong> The characters are consumed only if they would
1332     * match non-terminal S before end of line normalization is performed.
1333     *
1334     * @return Returns true if at least one space character was skipped.
1335     *
1336     * @throws IOException Thrown if i/o error occurs.
1337     * @throws EOFException Thrown on end of file.
1338     *
1339     * @see com.sun.org.apache.xerces.internal.util.XMLChar#isSpace
1340     */

1341    public boolean skipDeclSpaces() throws IOException JavaDoc {
1342        if (DEBUG_BUFFER) {
1343            System.out.print("(skipDeclSpaces: ");
1344            XMLEntityManager.print(fCurrentEntity);
1345            System.out.println();
1346        }
1347
1348        // load more characters, if needed
1349
if (fCurrentEntity.position == fCurrentEntity.count) {
1350            load(0, true);
1351        }
1352
1353        // skip spaces
1354
int c = fCurrentEntity.ch[fCurrentEntity.position];
1355        if (XMLChar.isSpace(c)) {
1356            boolean external = fCurrentEntity.isExternal();
1357            do {
1358                boolean entityChanged = false;
1359                // handle newlines
1360
if (c == '\n' || (external && c == '\r')) {
1361                    fCurrentEntity.lineNumber++;
1362                    fCurrentEntity.columnNumber = 1;
1363                    if (fCurrentEntity.position == fCurrentEntity.count - 1) {
1364                        fCurrentEntity.ch[0] = (char)c;
1365                        entityChanged = load(1, true);
1366                        if (!entityChanged)
1367                            // the load change the position to be 1,
1368
// need to restore it when entity not changed
1369
fCurrentEntity.position = 0;
1370                    }
1371                    if (c == '\r' && external) {
1372                        // REVISIT: Does this need to be updated to fix the
1373
// #x0D ^#x0A newline normalization problem? -Ac
1374
if (fCurrentEntity.ch[++fCurrentEntity.position] != '\n') {
1375                            fCurrentEntity.position--;
1376                        }
1377                    }
1378                    /*** NEWLINE NORMALIZATION ***
1379                    else {
1380                        if (fCurrentEntity.ch[fCurrentEntity.position + 1] == '\r'
1381                            && external) {
1382                            fCurrentEntity.position++;
1383                        }
1384                    }
1385                    /***/

1386                }
1387                else {
1388                    fCurrentEntity.columnNumber++;
1389                }
1390                // load more characters, if needed
1391
if (!entityChanged)
1392                    fCurrentEntity.position++;
1393                if (fCurrentEntity.position == fCurrentEntity.count) {
1394                    load(0, true);
1395                }
1396            } while (XMLChar.isSpace(c = fCurrentEntity.ch[fCurrentEntity.position]));
1397            if (DEBUG_BUFFER) {
1398                System.out.print(")skipDeclSpaces: ");
1399                XMLEntityManager.print(fCurrentEntity);
1400                System.out.println(" -> true");
1401            }
1402            return true;
1403        }
1404
1405        // no spaces were found
1406
if (DEBUG_BUFFER) {
1407            System.out.print(")skipDeclSpaces: ");
1408            XMLEntityManager.print(fCurrentEntity);
1409            System.out.println(" -> false");
1410        }
1411        return false;
1412
1413    } // skipDeclSpaces():boolean
1414

1415    /**
1416     * Skips the specified string appearing immediately on the input.
1417     * <p>
1418     * <strong>Note:</strong> The characters are consumed only if they are
1419     * space characters.
1420     *
1421     * @param s The string to skip.
1422     *
1423     * @return Returns true if the string was skipped.
1424     *
1425     * @throws IOException Thrown if i/o error occurs.
1426     * @throws EOFException Thrown on end of file.
1427     */

1428    public boolean skipString(String JavaDoc s) throws IOException JavaDoc {
1429        if (DEBUG_BUFFER) {
1430            System.out.print("(skipString, \""+s+"\": ");
1431            XMLEntityManager.print(fCurrentEntity);
1432            System.out.println();
1433        }
1434
1435        // load more characters, if needed
1436
if (fCurrentEntity.position == fCurrentEntity.count) {
1437            load(0, true);
1438        }
1439
1440        // skip string
1441
final int length = s.length();
1442        for (int i = 0; i < length; i++) {
1443            char c = fCurrentEntity.ch[fCurrentEntity.position++];
1444            if (c != s.charAt(i)) {
1445                fCurrentEntity.position -= i + 1;
1446                if (DEBUG_BUFFER) {
1447                    System.out.print(")skipString, \""+s+"\": ");
1448                    XMLEntityManager.print(fCurrentEntity);
1449                    System.out.println(" -> false");
1450                }
1451                return false;
1452            }
1453            if (i < length - 1 && fCurrentEntity.position == fCurrentEntity.count) {
1454                System.arraycopy(fCurrentEntity.ch, fCurrentEntity.count - i - 1, fCurrentEntity.ch, 0, i + 1);
1455                // REVISIT: Can a string to be skipped cross an
1456
// entity boundary? -Ac
1457
if (load(i + 1, false)) {
1458                    fCurrentEntity.position -= i + 1;
1459                    if (DEBUG_BUFFER) {
1460                        System.out.print(")skipString, \""+s+"\": ");
1461                        XMLEntityManager.print(fCurrentEntity);
1462                        System.out.println(" -> false");
1463                    }
1464                    return false;
1465                }
1466            }
1467        }
1468        if (DEBUG_BUFFER) {
1469            System.out.print(")skipString, \""+s+"\": ");
1470            XMLEntityManager.print(fCurrentEntity);
1471            System.out.println(" -> true");
1472        }
1473        fCurrentEntity.columnNumber += length;
1474        return true;
1475
1476    } // skipString(String):boolean
1477

1478    //
1479
// Locator methods
1480
//
1481

1482    /**
1483     * Return the public identifier for the current document event.
1484     * <p>
1485     * The return value is the public identifier of the document
1486     * entity or of the external parsed entity in which the markup
1487     * triggering the event appears.
1488     *
1489     * @return A string containing the public identifier, or
1490     * null if none is available.
1491     */

1492    public String JavaDoc getPublicId() {
1493        return (fCurrentEntity != null && fCurrentEntity.entityLocation != null) ? fCurrentEntity.entityLocation.getPublicId() : null;
1494    } // getPublicId():String
1495

1496    /**
1497     * Return the expanded system identifier for the current document event.
1498     * <p>
1499     * The return value is the expanded system identifier of the document
1500     * entity or of the external parsed entity in which the markup
1501     * triggering the event appears.
1502     * <p>
1503     * If the system identifier is a URL, the parser must resolve it
1504     * fully before passing it to the application.
1505     *
1506     * @return A string containing the expanded system identifier, or null
1507     * if none is available.
1508     */

1509    public String JavaDoc getExpandedSystemId() {
1510        if (fCurrentEntity != null) {
1511            if (fCurrentEntity.entityLocation != null &&
1512                    fCurrentEntity.entityLocation.getExpandedSystemId() != null ) {
1513                return fCurrentEntity.entityLocation.getExpandedSystemId();
1514            }
1515            else {
1516                // get the current entity to return something appropriate:
1517
return fCurrentEntity.getExpandedSystemId();
1518            }
1519        }
1520        return null;
1521    } // getExpandedSystemId():String
1522

1523    /**
1524     * Return the literal system identifier for the current document event.
1525     * <p>
1526     * The return value is the literal system identifier of the document
1527     * entity or of the external parsed entity in which the markup
1528     * triggering the event appears.
1529     * <p>
1530     * @return A string containing the literal system identifier, or null
1531     * if none is available.
1532     */

1533    public String JavaDoc getLiteralSystemId() {
1534        if (fCurrentEntity != null) {
1535            if (fCurrentEntity.entityLocation != null &&
1536                    fCurrentEntity.entityLocation.getLiteralSystemId() != null ) {
1537                return fCurrentEntity.entityLocation.getLiteralSystemId();
1538            }
1539            else {
1540                // get the current entity to do it:
1541
return fCurrentEntity.getLiteralSystemId();
1542            }
1543        }
1544        return null;
1545    } // getLiteralSystemId():String
1546

1547    /**
1548     * Return the line number where the current document event ends.
1549     * <p>
1550     * <strong>Warning:</strong> The return value from the method
1551     * is intended only as an approximation for the sake of error
1552     * reporting; it is not intended to provide sufficient information
1553     * to edit the character content of the original XML document.
1554     * <p>
1555     * The return value is an approximation of the line number
1556     * in the document entity or external parsed entity where the
1557     * markup triggering the event appears.
1558     * <p>
1559     * If possible, the SAX driver should provide the line position
1560     * of the first character after the text associated with the document
1561     * event. The first line in the document is line 1.
1562     *
1563     * @return The line number, or -1 if none is available.
1564     */

1565    public int getLineNumber() {
1566        if (fCurrentEntity != null) {
1567            if (fCurrentEntity.isExternal()) {
1568                return fCurrentEntity.lineNumber;
1569            }
1570            else {
1571                // ask the current entity to return something appropriate:
1572
return fCurrentEntity.getLineNumber();
1573            }
1574        }
1575
1576        return -1;
1577
1578    } // getLineNumber():int
1579

1580    /**
1581     * Return the column number where the current document event ends.
1582     * <p>
1583     * <strong>Warning:</strong> The return value from the method
1584     * is intended only as an approximation for the sake of error
1585     * reporting; it is not intended to provide sufficient information
1586     * to edit the character content of the original XML document.
1587     * <p>
1588     * The return value is an approximation of the column number
1589     * in the document entity or external parsed entity where the
1590     * markup triggering the event appears.
1591     * <p>
1592     * If possible, the SAX driver should provide the line position
1593     * of the first character after the text associated with the document
1594     * event.
1595     * <p>
1596     * If possible, the SAX driver should provide the line position
1597     * of the first character after the text associated with the document
1598     * event. The first column in each line is column 1.
1599     *
1600     * @return The column number, or -1 if none is available.
1601     */

1602    public int getColumnNumber() {
1603        if (fCurrentEntity != null) {
1604            if (fCurrentEntity.isExternal()) {
1605                return fCurrentEntity.columnNumber;
1606            }
1607            else {
1608                // ask current entity to find appropriate column number
1609
return fCurrentEntity.getColumnNumber();
1610            }
1611        }
1612
1613        return -1;
1614    } // getColumnNumber():int
1615

1616    /** Returns the encoding of the current entity.
1617     * Note that, for a given entity, this value can only be
1618     * considered final once the encoding declaration has been read (or once it
1619     * has been determined that there is no such declaration) since, no encoding
1620     * having been specified on the XMLInputSource, the parser
1621     * will make an initial "guess" which could be in error.
1622     */

1623    public String JavaDoc getEncoding() {
1624        if (fCurrentEntity != null) {
1625            if (fCurrentEntity.isExternal()) {
1626                return fCurrentEntity.encoding;
1627            }
1628            else {
1629                // ask current entity to find appropriate column number
1630
return fCurrentEntity.getEncoding();
1631            }
1632        }
1633
1634        return null;
1635    } // getEncoding():String
1636

1637    /**
1638     * @see com.sun.org.apache.xerces.internal.xni.XMLLocator#setColumnNumber(int)
1639     */

1640    public void setColumnNumber(int col) {
1641        // no-op
1642
}
1643
1644    /**
1645     * @see com.sun.org.apache.xerces.internal.xni.XMLLocator#setLineNumber(int)
1646     */

1647    public void setLineNumber(int line) {
1648        //no-op
1649
}
1650    
1651        /**
1652     * @see com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier#setBaseSystemId(String)
1653     */

1654    public void setBaseSystemId(String JavaDoc systemId) {
1655        //no-op
1656
}
1657
1658
1659    /**
1660     * @see com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier#setExpandedSystemId(String)
1661     */

1662    public void setExpandedSystemId(String JavaDoc systemId) {
1663        //no-op
1664
}
1665
1666    /**
1667     * @see com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier#setLiteralSystemId(String)
1668     */

1669    public void setLiteralSystemId(String JavaDoc systemId) {
1670        //no-op
1671
}
1672
1673    /**
1674     * @see com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier#setPublicId(String)
1675     */

1676    public void setPublicId(String JavaDoc publicId) {
1677        //no-op
1678
}
1679
1680    // allow entity manager to tell us what the current entityis:
1681
public void setCurrentEntity(XMLEntityManager.ScannedEntity ent) {
1682        fCurrentEntity = ent;
1683    }
1684
1685    // set buffer size:
1686
public void setBufferSize(int size) {
1687        // REVISIT: Buffer size passed to entity scanner
1688
// was not being kept in synch with the actual size
1689
// of the buffers in each scanned entity. If any
1690
// of the buffers were actually resized, it was possible
1691
// that the parser would throw an ArrayIndexOutOfBoundsException
1692
// for documents which contained names which are longer than
1693
// the current buffer size. Conceivably the buffer size passed
1694
// to entity scanner could be used to determine a minimum size
1695
// for resizing, if doubling its size is smaller than this
1696
// minimum. -- mrglavas
1697
fBufferSize = size;
1698    }
1699
1700    // reset what little state we have...
1701
public void reset(SymbolTable symbolTable, XMLEntityManager entityManager,
1702                        XMLErrorReporter reporter) {
1703        fCurrentEntity = null;
1704        fSymbolTable = symbolTable;
1705        fEntityManager = entityManager;
1706        fErrorReporter = reporter;
1707    }
1708
1709    //
1710
// Private methods
1711
//
1712

1713    /**
1714     * Loads a chunk of text.
1715     *
1716     * @param offset The offset into the character buffer to
1717     * read the next batch of characters.
1718     * @param changeEntity True if the load should change entities
1719     * at the end of the entity, otherwise leave
1720     * the current entity in place and the entity
1721     * boundary will be signaled by the return
1722     * value.
1723     *
1724     * @returns Returns true if the entity changed as a result of this
1725     * load operation.
1726     */

1727    final boolean load(int offset, boolean changeEntity)
1728        throws IOException JavaDoc {
1729        if (DEBUG_BUFFER) {
1730            System.out.print("(load, "+offset+": ");
1731            XMLEntityManager.print(fCurrentEntity);
1732            System.out.println();
1733        }
1734
1735        // read characters
1736
int length = fCurrentEntity.mayReadChunks?
1737                (fCurrentEntity.ch.length - offset):
1738                (XMLEntityManager.DEFAULT_XMLDECL_BUFFER_SIZE);
1739        if (DEBUG_BUFFER) System.out.println(" length to try to read: "+length);
1740        int count = fCurrentEntity.reader.read(fCurrentEntity.ch, offset, length);
1741        if (DEBUG_BUFFER) System.out.println(" length actually read: "+count);
1742
1743        // reset count and position
1744
boolean entityChanged = false;
1745        if (count != -1) {
1746            if (count != 0) {
1747                fCurrentEntity.count = count + offset;
1748                fCurrentEntity.position = offset;
1749            }
1750        }
1751
1752        // end of this entity
1753
else {
1754            fCurrentEntity.count = offset;
1755            fCurrentEntity.position = offset;
1756            entityChanged = true;
1757            if (changeEntity) {
1758                fEntityManager.endEntity();
1759                if (fCurrentEntity == null) {
1760                    throw new EOFException JavaDoc();
1761                }
1762                // handle the trailing edges
1763
if (fCurrentEntity.position == fCurrentEntity.count) {
1764                    load(0, true);
1765                }
1766            }
1767        }
1768        if (DEBUG_BUFFER) {
1769            System.out.print(")load, "+offset+": ");
1770            XMLEntityManager.print(fCurrentEntity);
1771            System.out.println();
1772        }
1773
1774        return entityChanged;
1775
1776    } // load(int, boolean):boolean
1777

1778
1779} // class XMLEntityScanner
1780

1781
Popular Tags