KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > xml > stream > XMLStreamReaderImpl


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  *
23  * Free Software Foundation, Inc.
24  * 59 Temple Place, Suite 330
25  * Boston, MA 02111-1307 USA
26  *
27  * @author Scott Ferguson, Adam Megacz
28  */

29
30 package com.caucho.xml.stream;
31
32 import com.caucho.util.CharBuffer;
33 import com.caucho.util.L10N;
34 import com.caucho.vfs.*;
35
36 import javax.xml.namespace.NamespaceContext JavaDoc;
37 import javax.xml.namespace.QName JavaDoc;
38 import javax.xml.stream.Location;
39 import javax.xml.stream.XMLStreamException;
40 import javax.xml.stream.XMLStreamReader;
41 import java.io.IOException JavaDoc;
42 import java.io.InputStream JavaDoc;
43 import java.io.Reader JavaDoc;
44 import java.util.logging.Logger JavaDoc;
45
46 /**
47  * XML pull-parser interface.
48  */

49 public class XMLStreamReaderImpl implements XMLStreamReader {
50   private static final Logger JavaDoc log
51     = Logger.getLogger(XMLStreamReaderImpl.class.getName());
52   private static final L10N L = new L10N(XMLStreamReaderImpl.class);
53
54   private static final boolean []IS_XML_NAME = new boolean[65536];
55
56   private StaxIntern _intern;
57
58   private ReadStream _is;
59
60   private int _col = 1;
61   private int _row = 1;
62   private int _ofs = 1;
63
64   private NamespaceReaderContext _namespaceTracker;
65
66   private String JavaDoc _version;
67   private String JavaDoc _encoding = "UTF-8";
68   private String JavaDoc _encodingScheme;
69
70   private String JavaDoc _publicId;
71   private String JavaDoc _systemId;
72
73   private boolean _seenDocumentStart = false;
74   private int _current;
75   private int _state;
76   private boolean _isShortTag;
77   private boolean _isWhitespace = false;
78
79   private boolean _eofEncountered = false;
80
81   private String JavaDoc _processingInstructionTarget;
82   private String JavaDoc _processingInstructionData;
83
84   private RawName _rawTagName = new RawName();
85   private QName JavaDoc _name;
86
87   private StaxIntern.Entry []_attrRawNames = new StaxIntern.Entry[16];
88   private QName JavaDoc []_attrNames = new QName JavaDoc[16];
89   private String JavaDoc []_attrValues = new String JavaDoc[16];
90   private int _attrCount;
91   private final StringBuilder JavaDoc _sb = new StringBuilder JavaDoc();
92   
93   private TempCharBuffer _tempInputBuffer;
94   private char []_inputBuf;
95   private int _inputOffset;
96   private int _inputLength;
97
98   private TempCharBuffer _tempCharBuffer;
99   private char []_cBuf;
100   private int _cBufLength;
101
102   public XMLStreamReaderImpl(InputStream JavaDoc is)
103     throws XMLStreamException
104   {
105     this(Vfs.openRead(is));
106   }
107
108   public XMLStreamReaderImpl(Reader r)
109     throws XMLStreamException
110   {
111     this(Vfs.openRead(r));
112   }
113
114   public XMLStreamReaderImpl(InputStream JavaDoc is, String JavaDoc systemId)
115     throws XMLStreamException
116   {
117     this(Vfs.openRead(is));
118     _systemId = systemId;
119   }
120
121   public XMLStreamReaderImpl(Reader r, String JavaDoc systemId)
122     throws XMLStreamException
123   {
124     this(Vfs.openRead(r));
125     _systemId = systemId;
126   }
127
128   public XMLStreamReaderImpl(ReadStream is)
129     throws XMLStreamException
130   {
131     init(is);
132   }
133
134   public void init(ReadStream is)
135     throws XMLStreamException
136   {
137     _namespaceTracker = new NamespaceReaderContext();
138     _intern = new StaxIntern(_namespaceTracker);
139     
140     _is = is;
141
142     _tempCharBuffer = TempCharBuffer.allocate();
143     _cBuf = _tempCharBuffer.getBuffer();
144
145     _tempInputBuffer = TempCharBuffer.allocate();
146     _inputBuf = _tempInputBuffer.getBuffer();
147     _inputOffset = _inputLength = 0;
148
149     readHeader();
150
151     _current = START_DOCUMENT;
152   }
153
154   public int getAttributeCount()
155   {
156     return _attrCount;
157   }
158
159   public String JavaDoc getAttributeLocalName(int index)
160   {
161     if (_attrCount <= index)
162       throw new IllegalArgumentException JavaDoc(L.l("element only has {0} attributes, given index {1}",
163                                                                          _attrCount, index));
164
165     return _attrNames[index].getLocalPart();
166   }
167
168   public QName JavaDoc getAttributeName(int index)
169   {
170     if (_attrCount <= index)
171       throw new IllegalArgumentException JavaDoc(L.l("element only has {0} attributes, given index {1}",
172                                              _attrCount, index));
173
174     return _attrNames[index];
175   }
176
177   public String JavaDoc getAttributeNamespace(int index)
178   {
179     if (_attrCount <= index)
180       throw new IllegalArgumentException JavaDoc(L.l("element only has {0} attributes, given index {1}",
181                                              _attrCount, index));
182
183     String JavaDoc ret = _attrNames[index].getNamespaceURI();
184
185     // API quirk
186
if ("".equals(ret))
187       return null;
188
189     return ret;
190   }
191
192   public String JavaDoc getAttributePrefix(int index)
193   {
194     if (_attrCount <= index)
195       throw new IllegalArgumentException JavaDoc(L.l("element only has {0} attributes, given index {1}",
196                                              _attrCount, index));
197
198     String JavaDoc ret = _attrNames[index].getPrefix();
199
200     return ret;
201   }
202
203   public String JavaDoc getAttributeType(int index)
204   {
205     return "CDATA";
206   }
207
208   public String JavaDoc getAttributeValue(int index)
209   {
210     if (_attrCount <= index)
211       throw new IllegalArgumentException JavaDoc(L.l("element only has {0} attributes, given index {1}",
212                                              _attrCount, index));
213
214     return _attrValues[index];
215   }
216
217   public boolean isAttributeSpecified(int index)
218   {
219     return index < _attrCount;
220   }
221
222   public String JavaDoc getAttributeValue(String JavaDoc namespaceURI, String JavaDoc localName)
223   {
224     for (int i = _attrCount - 1; i >= 0; i--) {
225       QName JavaDoc name = _attrNames[i];
226
227       if (name.getLocalPart().equals(localName) &&
228           name.getNamespaceURI().equals(namespaceURI))
229         return _attrValues[i];
230     }
231
232     return null;
233   }
234
235   public String JavaDoc getCharacterEncodingScheme()
236   {
237     return _encodingScheme;
238   }
239
240   public String JavaDoc getElementText() throws XMLStreamException
241   {
242     return getText();
243   }
244
245   public String JavaDoc getEncoding()
246   {
247     return _encoding;
248   }
249
250   public int getEventType()
251   {
252     return _current;
253   }
254
255   public Location getLocation()
256   {
257     return new StreamReaderLocation(_ofs, _row, _col);
258   }
259
260   public String JavaDoc getLocalName()
261   {
262     if (_name == null)
263       throw new IllegalStateException JavaDoc();
264
265     return _name.getLocalPart();
266   }
267
268   public String JavaDoc getNamespaceURI()
269   {
270     if (_name == null)
271       return null;
272
273     String JavaDoc uri = _name.getNamespaceURI();
274
275     if ("".equals(uri))
276       return null;
277     else
278       return uri;
279   }
280
281   public QName JavaDoc getName()
282   {
283     return _name;
284   }
285
286   public NamespaceContext JavaDoc getNamespaceContext()
287   {
288     return _namespaceTracker;
289   }
290
291   public int getNamespaceCount()
292   {
293     return _namespaceTracker.getNumDecls();
294   }
295
296   public String JavaDoc getNamespacePrefix(int index)
297   {
298     return _namespaceTracker.getPrefix(index);
299   }
300
301   public String JavaDoc getNamespaceURI(int index)
302   {
303     return _namespaceTracker.getUri(index);
304   }
305
306   public String JavaDoc getNamespaceURI(String JavaDoc prefix)
307   {
308     return _namespaceTracker.getUri(prefix);
309   }
310
311   public String JavaDoc getPIData()
312   {
313     if (_current != PROCESSING_INSTRUCTION)
314       return null;
315
316     return _processingInstructionData;
317   }
318
319   public String JavaDoc getPITarget()
320   {
321     if (_current != PROCESSING_INSTRUCTION)
322       return null;
323
324     return _processingInstructionTarget;
325   }
326
327   public String JavaDoc getPrefix()
328   {
329     if (_name == null)
330       return null;
331
332     String JavaDoc prefix = _name.getPrefix();
333
334     // xml/3000, xml/3009
335
if ("" == prefix && "" == _name.getNamespaceURI())
336       return null;
337
338     return prefix;
339   }
340
341   public Object JavaDoc getProperty(String JavaDoc name) throws IllegalArgumentException JavaDoc
342   {
343     if ("javax.xml.stream.notations".equals(name)) {
344       throw new UnsupportedOperationException JavaDoc(getClass().getName());
345     }
346     else if ("javax.xml.stream.entities".equals(name)) {
347       throw new UnsupportedOperationException JavaDoc(getClass().getName());
348     }
349     else {
350       throw
351         new IllegalArgumentException JavaDoc("property \""+name+"+\" not supported");
352     }
353   }
354
355   /**
356    * Returns the current text string.
357    */

358   public String JavaDoc getText()
359   {
360     return new String JavaDoc(_cBuf, 0, _cBufLength);
361   }
362
363   /**
364    * Returns a character buffer for the current text.
365    */

366   public char[] getTextCharacters()
367   {
368     return _cBuf;
369   }
370
371   /**
372    * Reads the current text into a buffer.
373    */

374   public int getTextCharacters(int sourceStart, char[] target,
375                                int targetStart, int length)
376     throws XMLStreamException
377   {
378     int sublen = _cBufLength - sourceStart;
379     
380     if (length < sublen)
381       sublen = length;
382     
383     System.arraycopy(_cBuf, sourceStart, target, targetStart, sublen);
384     
385     return sublen;
386   }
387
388   /**
389    * Returns the length of the current text.
390    */

391   public int getTextLength()
392   {
393     return _cBufLength;
394   }
395
396   /**
397    * Returns the offset of the current text.
398    */

399   public int getTextStart()
400   {
401     return 0;
402   }
403
404   public String JavaDoc getVersion()
405   {
406     return _version;
407   }
408
409   public boolean hasName()
410   {
411     return _name != null;
412   }
413
414   public boolean hasText()
415   {
416     switch(getEventType()) {
417     case CHARACTERS:
418     case DTD:
419     case ENTITY_REFERENCE:
420     case COMMENT:
421     case SPACE:
422       return true;
423     default:
424       return false;
425     }
426   }
427
428   public boolean isCharacters()
429   {
430     return _current == CHARACTERS;
431   }
432
433   public boolean isEndElement()
434   {
435     return _current == END_ELEMENT;
436   }
437
438   public boolean isStandalone()
439   {
440     return false;
441   }
442
443   public boolean isStartElement()
444   {
445     return _current == START_ELEMENT;
446   }
447
448   public boolean isWhiteSpace()
449   {
450     return (_isWhitespace
451         && (_current == CHARACTERS || _current == SPACE));
452   }
453
454   /**
455    * Skips until the next START_ELEMENT or END_ELEMENT
456    */

457   public int nextTag() throws XMLStreamException
458   {
459     while (true) {
460       int tag = next();
461
462       if (tag < 0
463       || tag == START_ELEMENT
464       || tag == END_ELEMENT) {
465     return tag;
466       }
467     }
468   }
469
470   public void require(int type, String JavaDoc namespaceURI, String JavaDoc localName)
471     throws XMLStreamException
472   {
473     if (type != _current)
474       throw new XMLStreamException("expected " + constantToString(type) + ", "+
475                                    "found " + constantToString(_current) +
476                                    " at " + getLocation());
477
478     if (localName != null && !localName.equals(getLocalName()))
479       throw new XMLStreamException("expected <"+localName+">, found " +
480                                    "<"+getLocalName()+"> at " + getLocation());
481
482     if (namespaceURI != null && !namespaceURI.equals(getNamespaceURI()))
483       throw new XMLStreamException("expected xmlns="+namespaceURI+
484                                    ", found xmlns="+getNamespaceURI() +
485                                    " at " + getLocation());
486   }
487
488   public boolean standaloneSet()
489   {
490     return isStandalone();
491   }
492
493   public boolean hasNext() throws XMLStreamException
494   {
495     if (_is == null)
496       return false;
497
498     return _current != END_DOCUMENT;
499   }
500
501   public int next() throws XMLStreamException
502   {
503     try {
504       _current = readNext();
505     } catch (IOException JavaDoc e) {
506       throw new XMLStreamException(e);
507     }
508
509     if (_current > 0)
510       return _current;
511     else {
512       if (_eofEncountered)
513         return _current = -1;
514
515       _eofEncountered = true;
516       
517       return _current = END_DOCUMENT;
518     }
519   }
520
521   private int readNext()
522     throws IOException JavaDoc, XMLStreamException
523   {
524     // we pop the namespace context when the user is finished
525
// working with the END_ELEMENT event
526
if (_current == END_ELEMENT)
527       _namespaceTracker.pop();
528     
529     if (_isShortTag) {
530       _isShortTag = false;
531       return END_ELEMENT;
532     }
533
534     _name = null;
535
536     int ch = read();
537
538     if (ch == '<') {
539       ch = read();
540
541       switch (ch) {
542       case '/':
543         _name = readName(false).getQName();
544
545         expect('>');
546
547         return END_ELEMENT;
548
549       case '!':
550         expect('-');
551         expect('-');
552         return readComment();
553
554       case '?':
555         readProcessingDirective();
556         return PROCESSING_INSTRUCTION;
557
558       default:
559         unread();
560
561         readElementBegin();
562
563         return START_ELEMENT;
564       }
565     }
566     else if (ch < 0) {
567       close();
568       
569       return -1;
570     }
571     else {
572       unread();
573
574       return readData();
575     }
576   }
577
578   private void readElementBegin()
579     throws IOException JavaDoc, XMLStreamException
580   {
581     _namespaceTracker.push();
582     
583     StaxIntern.Entry eltName = readName(false);
584
585     int ch = readAttributes();
586
587     if (ch == '>') {
588     }
589     else if (ch == '/') {
590       _isShortTag = true;
591
592       expect('>');
593     }
594     else
595       throw error(L.l("Expected {0} at {1}", ">", charName(ch)));
596
597     for (int i = _attrCount - 1; i >= 0; i--)
598       _attrNames[i] = _attrRawNames[i].getQName();
599
600     _name = eltName.getQName();
601   }
602
603   private int readAttributes()
604     throws IOException JavaDoc, XMLStreamException
605   {
606     int ch;
607     int attrCount = 0;
608
609     while ((ch = skipWhitespace()) >= 0 && IS_XML_NAME[ch]) {
610       unread();
611
612       if (_attrRawNames.length <= attrCount)
613         extendAttrs();
614
615       StaxIntern.Entry rawName = readName(true);
616
617       ch = skipWhitespace();
618
619       if (ch != '=')
620         throw error(L.l("attribute expects '=' at {0}", charName(ch)));
621
622       ch = skipWhitespace();
623
624       if (ch == '\'' || ch == '"') {
625         if ("xmlns".equals(rawName.getPrefix())) {
626           _namespaceTracker.declare(rawName.getLocalName(), readValue(ch));
627         }
628         else if ("xmlns".equals(rawName.getLocalName())) {
629           _namespaceTracker.declare(null, readValue(ch));
630         }
631         else {
632           _attrRawNames[attrCount] = rawName;
633           _attrValues[attrCount++] = readValue(ch);
634         }
635       }
636       else
637         throw error(L.l("attribute expects value at {0}", charName(ch)));
638     }
639
640     _attrCount = attrCount;
641
642     return ch;
643   }
644
645   private String JavaDoc readValue(int end)
646     throws XMLStreamException
647   {
648     char []valueBuffer = _cBuf;
649     int valueIndex = 0;
650
651     while (true) {
652       int ch = read();
653
654       switch (ch) {
655       case -1:
656     return new String JavaDoc(valueBuffer, 0, valueIndex);
657
658       case '"': case '\'':
659     if (ch == end)
660       return new String JavaDoc(valueBuffer, 0, valueIndex);
661     else
662       valueBuffer[valueIndex++] = (char) ch;
663     break;
664     
665       case '&':
666     valueBuffer[valueIndex++] = (char) ch;
667     break;
668
669       default:
670     valueBuffer[valueIndex++] = (char) ch;
671     break;
672       }
673     }
674   }
675
676   private void extendAttrs()
677   {
678     int length = _attrRawNames.length;
679
680     StaxIntern.Entry []attrRawNames = new StaxIntern.Entry[length + 16];
681     System.arraycopy(_attrRawNames, 0, attrRawNames, 0, length);
682     _attrRawNames = attrRawNames;
683
684     QName JavaDoc []attrNames = new QName JavaDoc[length + 16];
685     System.arraycopy(_attrNames, 0, attrNames, 0, length);
686     _attrNames = attrNames;
687
688     String JavaDoc []attrValues = new String JavaDoc[length + 16];
689     System.arraycopy(_attrValues, 0, attrValues, 0, length);
690     _attrValues = attrValues;
691   }
692
693   private int readData()
694     throws IOException JavaDoc, XMLStreamException
695   {
696     int ch = 0;
697     _isWhitespace = true;
698
699     int index = 0;
700     char []cBuf = _cBuf;
701     int length = cBuf.length;
702     int entity = -1;
703     
704     loop:
705     for (; index < length && (ch = read()) >= 0; index++) {
706       switch (ch) {
707       case '<':
708         unread();
709         break loop;
710     
711       case '&':
712     if (cBuf.length <= index + 256) {
713       unread();
714       break loop;
715     }
716         cBuf[index] = (char) ch;
717         entity = index;
718         break;
719     
720       case '\r':
721         ch = read();
722         if (ch != '\n') { ch = '\r'; unread(); }
723     
724       case ' ': case '\t': case '\n':
725         cBuf[index] = (char) ch;
726         break;
727     
728       case ';':
729         if (entity >= 0) {
730           String JavaDoc resolved = resolveEntity(new String JavaDoc(cBuf, entity + 1, index - entity - 1));
731       index = entity + resolved.length();
732           resolved.getChars(0, resolved.length(), cBuf, entity);
733       entity = -1;
734           break;
735         }
736       default:
737         _isWhitespace = false;
738         cBuf[index] = (char) ch;
739         break;
740       }
741     }
742
743     if (entity > 0)
744       throw new XMLStreamException("XXX: unclosed entity at end of file");
745
746     _cBufLength = index;
747
748     if (ch < 0 && _isWhitespace)
749       return -1;
750
751     // whitespace surrounding the root element is "ignorable" per the XML spec
752
boolean isIgnorableWhitespace
753       = _isWhitespace && _namespaceTracker.getDepth() == 0;
754
755     return isIgnorableWhitespace ? SPACE : CHARACTERS;
756   }
757
758   private String JavaDoc resolveEntity(String JavaDoc s)
759     throws XMLStreamException
760   {
761     if ("amp".equals(s)) return "&";
762     if ("apos".equals(s)) return "\'";
763     if ("quot".equals(s)) return "\"";
764     if ("lt".equals(s)) return "<";
765     if ("gt".equals(s)) return ">";
766     if (s.startsWith("#x"))
767       return ""+((char)Integer.parseInt(s.substring(1), 16));
768     if (s.startsWith("#"))
769       return ""+((char)Integer.parseInt(s.substring(1)));
770
771     throw new XMLStreamException("unknown entity: \"" + s + "\"");
772   }
773
774   private void readProcessingDirective()
775     throws XMLStreamException
776   {
777     CharBuffer target = new CharBuffer();
778     CharBuffer data = null;
779
780     while(true) {
781       int ch = read();
782
783       if (ch == -1)
784         return; /* XXX: error? */
785
786       if (ch == '?') {
787         int next = read();
788         if (next == '>') {
789           _processingInstructionTarget = target.toString();
790           _processingInstructionData = data.toString();
791           return;
792         }
793         unread();
794       }
795
796       if (data == null && (ch == ' ' || ch == '\r' || ch == '\n')) {
797         data = new CharBuffer();
798         continue;
799       }
800
801       if (data != null)
802         data.append((char)ch);
803       else
804         target.append((char)ch);
805     }
806   }
807
808
809   private int readComment()
810     throws XMLStreamException
811   {
812     int ch = 0;
813     int index = 0;
814     char []cBuf = _cBuf;
815     int length = cBuf.length;
816     loop:
817     for (; index < length && (ch = read()) >= 0; index++) {
818       cBuf[index] = (char) ch;
819       if (index > 3
820           && cBuf[index-2] == '-'
821           && cBuf[index-1] == '-'
822           && cBuf[index-0] == '>') {
823         index -= 2;
824         break;
825       }
826     }
827
828     _cBufLength = index;
829
830     return COMMENT;
831   }
832
833   private void readRawName(RawName name)
834     throws IOException JavaDoc, XMLStreamException
835   {
836     int length = 0;
837     char []nameBuffer = name._buffer;
838     int bufferLength = nameBuffer.length;
839     int prefix = -1;
840
841     int ch;
842
843     while ((ch = read()) >= 0 && IS_XML_NAME[ch]) {
844       if (bufferLength <= length) {
845         name.expandCapacity();
846         nameBuffer = name._buffer;
847         bufferLength = nameBuffer.length;
848       }
849
850       if (ch == ':' && prefix < 0)
851         prefix = length;
852
853       nameBuffer[length++] = (char) ch;
854     }
855     unread();
856
857     name._length = length;
858     name._prefix = prefix;
859   }
860
861   /**
862    * Parses a name.
863    */

864   private StaxIntern.Entry readName(boolean isAttribute)
865     throws XMLStreamException
866   {
867     char []inputBuf = _inputBuf;
868     int inputLength = _inputLength;
869     int inputOffset = _inputOffset;
870     
871     char []valueBuf = _cBuf;
872     int valueOffset = 0;
873
874     int colon = 0;
875
876     while (true) {
877       if (inputOffset < inputLength) {
878         char ch = inputBuf[inputOffset++];
879
880         if (IS_XML_NAME[ch]) {
881           valueBuf[valueOffset++] = ch;
882         }
883         else if (ch == ':') {
884           if (colon <= 0)
885             colon = valueOffset;
886
887           valueBuf[valueOffset++] = ch;
888         }
889         else {
890           _inputOffset = inputOffset - 1;
891
892           return _intern.add(valueBuf, 0, valueOffset, colon, isAttribute);
893         }
894       }
895       else if (fillBuffer()) {
896         inputLength = _inputLength;
897         inputOffset = _inputOffset;
898       }
899       else {
900         return _intern.add(valueBuf, 0, valueOffset, colon, isAttribute);
901       }
902     }
903   }
904
905   private static boolean isXmlName(int ch)
906   {
907     return ('a' <= ch && ch <= 'z'
908             || 'A' <= ch && ch <= 'Z'
909             || '0' <= ch && ch <= '9'
910             || ch == ':'
911             || ch == '+'
912             || ch == '_'
913             || ch == '-');
914   }
915
916   private int skipWhitespace()
917     throws XMLStreamException
918   {
919     int ch;
920
921     while ((ch = read()) >= 0 &&
922            (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n')) {
923     }
924
925     return ch;
926   }
927
928   /**
929    * Reads the <?xml ... ?> declaraction
930    */

931   private void readHeader()
932     throws XMLStreamException
933   {
934     // The reading at this point must use the underlying stream because
935
// the encoding is not determined until the end of the declaration
936

937     int ch;
938
939     ch = readByte();
940
941     if (ch == (char)0xFE) {
942       if (readByte() != (char)0xFF) {
943     throw new XMLStreamException("found unrecognized BOM");
944       }
945       ch = readByte();
946     } else if (ch == (char)0xFF) {
947       if (readByte() != (char)0xFE) {
948     throw new UnsupportedOperationException JavaDoc("found byte-swapped BOM");
949       } else {
950     throw new XMLStreamException("found unrecognized BOM");
951       }
952     }
953
954     if (ch != '<') {
955       unreadByte();
956     }
957     else if ((ch = readByte()) != '?') {
958       unreadByte();
959       unreadByte();
960     }
961     else if ((ch = readByte()) != 'x') {
962       unreadByte();
963       unreadByte();
964       unreadByte();
965     }
966     else if ((ch = readByte()) != 'm') {
967       unreadByte();
968       unreadByte();
969       unreadByte();
970       unreadByte();
971     }
972     else if ((ch = readByte()) != 'l') {
973       unreadByte();
974       unreadByte();
975       unreadByte();
976       unreadByte();
977       unreadByte();
978     }
979     else {
980
981       CharBuffer directive = new CharBuffer();
982       while ((ch = readByte()) >= 0 && ch != '?') {
983     directive.append((char)ch);
984       }
985
986       String JavaDoc data = directive.toString().trim();
987       if (data.startsWith("version")) {
988     data = data.substring(7).trim();
989     data = data.substring(1).trim(); // remove "="
990
char quot = data.charAt(0);
991     _version = data.substring(1, data.indexOf(quot, 1));
992     data = data.substring(data.indexOf(quot, 1)+1).trim();
993       }
994       if (data.startsWith("encoding")) {
995     data = data.substring(8).trim();
996     data = data.substring(1).trim(); // remove "="
997
char quot = data.charAt(0);
998     _encoding = data.substring(1, data.indexOf(quot, 1));
999     data = data.substring(data.indexOf(quot, 1)+1).trim();
1000      }
1001
1002      ch = readByte();
1003      if (ch != '>')
1004    throw error(L.l("Expected '>' at end of '<?xml' declaration at {0}",
1005            charName(ch)));
1006    }
1007  }
1008
1009  /**
1010   * Reads and validate next character.
1011   */

1012  private void expect(int expect)
1013    throws XMLStreamException
1014  {
1015    int ch = read();
1016
1017    if (ch != expect)
1018      throw error(L.l("expected {0} at {1}", charName(expect), charName(ch)));
1019  }
1020
1021  /**
1022   * Reads a character.
1023   */

1024  private int read()
1025    throws XMLStreamException
1026  {
1027    if (_inputLength <= _inputOffset && ! fillBuffer())
1028      return -1;
1029
1030    int ch = _inputBuf[_inputOffset++];
1031
1032    return ch;
1033  }
1034
1035  /**
1036   * Reads a character.
1037   */

1038  private void unread()
1039  {
1040    if (_inputOffset > 0)
1041      _inputOffset--;
1042  }
1043
1044  /**
1045   * Reads a character.
1046   */

1047  private int readByte()
1048    throws XMLStreamException
1049  {
1050    try {
1051      if (_inputLength <= _inputOffset) {
1052    int ch = _is.read();
1053
1054    if (ch < 0)
1055      return ch;
1056      
1057    if (_inputBuf.length <= _inputLength)
1058      _inputLength = 0;
1059      
1060    _inputBuf[_inputLength++] = (char) ch;
1061    _inputOffset = _inputLength;
1062
1063    return ch;
1064      }
1065      else
1066    return _inputBuf[_inputOffset++];
1067    } catch (IOException JavaDoc e) {
1068      throw new XMLStreamException(e);
1069    }
1070  }
1071
1072  /**
1073   * Reads a character.
1074   */

1075  private void unreadByte()
1076  {
1077    if (_inputOffset > 0)
1078      _inputOffset--;
1079  }
1080
1081  /**
1082   * Fills the input buffer.
1083   */

1084  private final boolean fillBuffer()
1085    throws XMLStreamException
1086  {
1087    try {
1088      if (_is != null) {
1089    _inputOffset = 0;
1090    _inputLength = _is.read(_inputBuf, 0, _inputBuf.length);
1091
1092    return _inputLength > 0;
1093      }
1094      else {
1095    _inputOffset = 0;
1096    _inputLength = 0;
1097    
1098    return false;
1099      }
1100    } catch (IOException JavaDoc e) {
1101      throw new XMLStreamException(e);
1102    }
1103  }
1104
1105  private String JavaDoc charName(int ch)
1106  {
1107    if (ch > 0x20 && ch <= 0x7f)
1108      return "'" + (char) ch + "'";
1109    else
1110      return "0x" + Integer.toHexString(ch);
1111  }
1112
1113  private XMLStreamException error(String JavaDoc s)
1114  {
1115    return new XMLStreamException(location() + s);
1116  }
1117
1118  private String JavaDoc location()
1119  {
1120    return ":" + _row + ":" + _col + " ";
1121  }
1122
1123  public void close() throws XMLStreamException
1124  {
1125    TempCharBuffer tempCharBuffer = _tempCharBuffer;
1126    _tempCharBuffer = null;
1127    _cBuf = null;
1128      
1129    TempCharBuffer tempInputBuffer = _tempInputBuffer;
1130    _tempInputBuffer = null;
1131    _inputBuf = null;
1132
1133    _inputOffset = _inputLength = 0;
1134      
1135    if (tempCharBuffer != null)
1136      TempCharBuffer.free(tempCharBuffer);
1137      
1138    if (tempInputBuffer != null)
1139      TempCharBuffer.free(tempInputBuffer);
1140      
1141    ReadStream is = _is;
1142    _is = null;
1143
1144    if (is != null)
1145      is.close();
1146  }
1147
1148  static class RawName {
1149    char []_buffer = new char[64];
1150    int _prefix;
1151    int _length;
1152
1153    public QName JavaDoc resolve(NamespaceContext JavaDoc nsc)
1154    {
1155      if (getPrefix() == null)
1156        return new QName JavaDoc(nsc.getNamespaceURI(null),
1157                         getLocalName());
1158      return new QName JavaDoc(nsc.getNamespaceURI(getPrefix()),
1159                       getLocalName(),
1160                       getPrefix());
1161    }
1162
1163    public String JavaDoc toString()
1164    {
1165      return new String JavaDoc(_buffer, 0, _length);
1166    }
1167
1168    String JavaDoc getLocalName()
1169    {
1170      return new String JavaDoc(_buffer, _prefix + 1, _length - _prefix - 1);
1171    }
1172
1173    String JavaDoc getPrefix()
1174    {
1175      if (_prefix==-1) return null;
1176      return new String JavaDoc(_buffer, 0, _prefix);
1177    }
1178
1179    void expandCapacity()
1180    {
1181      char []newBuffer = new char[_buffer.length + 64];
1182
1183      System.arraycopy(_buffer, 0, newBuffer, 0, _buffer.length);
1184
1185      _buffer = newBuffer;
1186    }
1187  }
1188  /*
1189  static class NSContext {
1190
1191    NSContext _parent;
1192
1193    public NSContext(NSContext parent)
1194    {
1195      _parent = parent;
1196    }
1197  }
1198  */

1199  static {
1200    for (int i = 0; i < IS_XML_NAME.length; i++) {
1201      if (isXmlName(i) && i != ':')
1202        IS_XML_NAME[i] = isXmlName(i);
1203    }
1204  }
1205
1206  private class StreamReaderLocation implements Location {
1207
1208    private int _ofs;
1209    private int _row;
1210    private int _col;
1211
1212    public StreamReaderLocation(int ofs, int row, int col)
1213    {
1214      this._ofs = ofs;
1215      this._row = row;
1216      this._col = col;
1217    }
1218
1219    public int getCharacterOffset()
1220    {
1221      return _ofs;
1222    }
1223
1224    public int getColumnNumber()
1225    {
1226      return _col;
1227    }
1228
1229    public int getLineNumber()
1230    {
1231      return _row;
1232    }
1233
1234    public String JavaDoc getPublicId()
1235    {
1236      return _publicId;
1237    }
1238
1239    public String JavaDoc getSystemId()
1240    {
1241      return _systemId;
1242    }
1243
1244    public String JavaDoc toString() {
1245      return _row+":"+_col;
1246    }
1247
1248  }
1249
1250  private static String JavaDoc constantToString(int constant) {
1251
1252    switch(constant) {
1253
1254    case ATTRIBUTE: return "ATTRIBUTE";
1255    case CDATA: return "CDATA";
1256    case CHARACTERS: return "CHARACTERS";
1257    case COMMENT: return "COMMENT";
1258    case DTD: return "DTD";
1259    case END_DOCUMENT: return "END_DOCUMENT";
1260    case END_ELEMENT: return "END_ELEMENT";
1261    case ENTITY_DECLARATION: return "ENTITY_DECLARATION";
1262    case ENTITY_REFERENCE: return "ENTITY_REFERENCE";
1263    case NAMESPACE: return "NAMESPACE";
1264    case NOTATION_DECLARATION: return "NOTATION_DECLARATION";
1265    case PROCESSING_INSTRUCTION: return "PROCESSING_INSTRUCTION";
1266    case SPACE: return "SPACE";
1267    case START_DOCUMENT: return "START_DOCUMENT";
1268    case START_ELEMENT: return "START_ELEMENT";
1269    default:
1270      throw new RuntimeException JavaDoc("constantToString("+constant+") unknown");
1271    }
1272
1273  }
1274
1275}
1276
Popular Tags