KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > xmlpull > mxp1 > MXParser


1 /* -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- //------100-columns-wide------>|*/
2 /*
3  * Copyright (c) 2002 Extreme! Lab, Indiana University. All rights reserved.
4  *
5  * This software is open source. See the bottom of this file for the licence.
6  *
7  * $Id: MXParser.java,v 1.20 2002/10/10 06:49:21 aslom Exp $
8  */

9
10 package org.xmlpull.mxp1;
11
12 import java.io.EOFException JavaDoc;
13 import java.io.IOException JavaDoc;
14 import java.io.Reader JavaDoc;
15 import java.io.InputStreamReader JavaDoc;
16 import java.io.UnsupportedEncodingException JavaDoc;
17
18 //import java.util.Hashtable;
19

20 import org.xmlpull.v1.XmlPullParser;
21 import org.xmlpull.v1.XmlPullParserException;
22
23 //TODO best handling of interning issues
24
// have isAllNewStringInterned ???
25

26 //TODO handling surrogate pairs: http://www.unicode.org/unicode/faq/utf_bom.html#6
27

28 //TODO review code for use of bufAbsoluteStart when keeping pos between next()/fillBuf()
29

30 /**
31  * Absolutely minimal implementaion of XMLPULL V1 API
32  *
33  * @author <a HREF="http://www.extreme.indiana.edu/~aslom/">Aleksander Slominski</a>
34  */

35
36 public class MXParser
37     implements XmlPullParser
38 {
39     //NOTE: no interning of those strings --> by Java leng spec they MUST be already interned
40
protected final static String JavaDoc XML_URI = "http://www.w3.org/XML/1998/namespace";
41     protected final static String JavaDoc XMLNS_URI = "http://www.w3.org/2000/xmlns/";
42     protected final static String JavaDoc FEATURE_XML_ROUNDTRIP=
43         //"http://xmlpull.org/v1/doc/features.html#xml-roundtrip";
44
"http://xmlpull.org/v1/doc/features.html#xml-roundtrip";
45     protected final static String JavaDoc FEATURE_NAMES_INTERNED =
46         "http://xmlpull.org/v1/doc/features.html#names-interned";
47     protected final static String JavaDoc PROPERTY_XMLDECL_VERSION =
48         "http://xmlpull.org/v1/doc/properties.html#xmldecl-version";
49     protected final static String JavaDoc PROPERTY_XMLDECL_STANDALONE =
50         "http://xmlpull.org/v1/doc/properties.html#xmldecl-standalone";
51     protected final static String JavaDoc PROPERTY_XMLDECL_CONTENT =
52         "http://xmlpull.org/v1/doc/properties.html#xmldecl-content";
53
54
55     /**
56      * Implementation notice:
57      * the is instance variable that controls if newString() is interning.
58      * <p><b>NOTE:</b> newStringIntern <b>always</b> returns interned strings
59      * and newString MAY return interned String depending on this variable.
60      * <p><b>NOTE:</b> by default in this minimal implementation it is false!
61      */

62     protected boolean allStringsInterned;
63
64     protected void resetStringCache() {
65         //System.out.println("resetStringCache() minimum called");
66
}
67
68     protected String JavaDoc newString(char[] cbuf, int off, int len) {
69         return new String JavaDoc(cbuf, off, len);
70     }
71
72     protected String JavaDoc newStringIntern(char[] cbuf, int off, int len) {
73         return (new String JavaDoc(cbuf, off, len)).intern();
74     }
75
76
77     private static final boolean TRACE_SIZING = false;
78
79     // NOTE: features are not resetable and typicaly defaults to false ...
80
protected boolean processNamespaces;
81     protected boolean roundtripSupported;
82
83     // global parser state
84
protected int lineNumber;
85     protected int columnNumber;
86     protected boolean seenRoot;
87     protected boolean reachedEnd;
88     protected int eventType;
89     protected boolean emptyElementTag;
90     // element stack
91
protected int depth;
92     protected char[] elRawName[];
93     protected int elRawNameEnd[];
94     //pnrotected int elRawNameEnd[];
95
protected String JavaDoc elName[];
96     protected String JavaDoc elPrefix[];
97     protected String JavaDoc elUri[];
98     //protected String elValue[];
99
protected int elNamespaceCount[];
100
101
102
103     /**
104      * Make sure that we have enough space to keep element stack if passed size.
105      * It will always create one additional slot then current depth
106      */

107     protected void ensureElementsCapacity() {
108         int elStackSize = elName != null ? elName.length : 0;
109         if( (depth + 1) >= elStackSize) {
110             // we add at least one extra slot ...
111
int newSize = (depth >= 7 ? 2 * depth : 8) + 2; // = lucky 7 + 1 //25
112
if(TRACE_SIZING) {
113                 System.err.println("TRACE_SIZING elStackSize "+elStackSize+" ==> "+newSize);
114             }
115             boolean needsCopying = elStackSize > 0;
116             String JavaDoc[] arr = null;
117             arr = new String JavaDoc[newSize];
118             if(needsCopying) System.arraycopy(elName, 0, arr, 0, elStackSize);
119             elName = arr;
120             arr = new String JavaDoc[newSize];
121             if(needsCopying) System.arraycopy(elPrefix, 0, arr, 0, elStackSize);
122             elPrefix = arr;
123             arr = new String JavaDoc[newSize];
124             if(needsCopying) System.arraycopy(elUri, 0, arr, 0, elStackSize);
125             elUri = arr;
126
127             int[] iarr = new int[newSize];
128             if(needsCopying) {
129                 System.arraycopy(elNamespaceCount, 0, iarr, 0, elStackSize);
130             } else {
131                 // special initialization
132
iarr[0] = 0;
133             }
134             elNamespaceCount = iarr;
135
136             //TODO: avoid using element raw name ...
137
iarr = new int[newSize];
138             if(needsCopying) {
139                 System.arraycopy(elRawNameEnd, 0, iarr, 0, elStackSize);
140             }
141             elRawNameEnd = iarr;
142
143             char[][] carr = new char[newSize][];
144             if(needsCopying) {
145                 System.arraycopy(elRawName, 0, carr, 0, elStackSize);
146             }
147             elRawName = carr;
148             // arr = new String[newSize];
149
// if(needsCopying) System.arraycopy(elLocalName, 0, arr, 0, elStackSize);
150
// elLocalName = arr;
151
// arr = new String[newSize];
152
// if(needsCopying) System.arraycopy(elDefaultNs, 0, arr, 0, elStackSize);
153
// elDefaultNs = arr;
154
// int[] iarr = new int[newSize];
155
// if(needsCopying) System.arraycopy(elNsStackPos, 0, iarr, 0, elStackSize);
156
// for (int i = elStackSize; i < iarr.length; i++)
157
// {
158
// iarr[i] = (i > 0) ? -1 : 0;
159
// }
160
// elNsStackPos = iarr;
161
//assert depth < elName.length;
162
}
163     }
164
165
166     // nameStart / name lookup tables based on XML 1.1 http://www.w3.org/TR/2001/WD-xml11-20011213/
167
protected static final int LOOKUP_MAX = 0x400;
168     protected static final char LOOKUP_MAX_CHAR = (char)LOOKUP_MAX;
169     // protected static int lookupNameStartChar[] = new int[ LOOKUP_MAX_CHAR / 32 ];
170
// protected static int lookupNameChar[] = new int[ LOOKUP_MAX_CHAR / 32 ];
171
protected static boolean lookupNameStartChar[] = new boolean[ LOOKUP_MAX ];
172     protected static boolean lookupNameChar[] = new boolean[ LOOKUP_MAX ];
173
174     private static final void setName(char ch)
175         //{ lookupNameChar[ (int)ch / 32 ] |= (1 << (ch % 32)); }
176
{ lookupNameChar[ ch ] = true; }
177     private static final void setNameStart(char ch)
178         //{ lookupNameStartChar[ (int)ch / 32 ] |= (1 << (ch % 32)); setName(ch); }
179
{ lookupNameStartChar[ ch ] = true; setName(ch); }
180
181     static {
182         setNameStart(':');
183         for (char ch = 'A'; ch <= 'Z'; ++ch) setNameStart(ch);
184         setNameStart('_');
185         for (char ch = 'a'; ch <= 'z'; ++ch) setNameStart(ch);
186         for (char ch = '\u00c0'; ch <= '\u02FF'; ++ch) setNameStart(ch);
187         for (char ch = '\u0370'; ch <= '\u037d'; ++ch) setNameStart(ch);
188         for (char ch = '\u037f'; ch < '\u0400'; ++ch) setNameStart(ch);
189
190         setName('-');
191         setName('.');
192         for (char ch = '0'; ch <= '9'; ++ch) setName(ch);
193         setName('\u00b7');
194         for (char ch = '\u0300'; ch <= '\u036f'; ++ch) setName(ch);
195     }
196
197     //private final static boolean isNameStartChar(char ch) {
198
protected boolean isNameStartChar(char ch) {
199         return (ch < LOOKUP_MAX_CHAR && lookupNameStartChar[ ch ])
200             || (ch >= LOOKUP_MAX_CHAR && ch <= '\u2027')
201             || (ch >= '\u202A' && ch <= '\u218F')
202             || (ch >= '\u2800' && ch <= '\uFFEF')
203             ;
204
205         // if(ch < LOOKUP_MAX_CHAR) return lookupNameStartChar[ ch ];
206
// else return ch <= '\u2027'
207
// || (ch >= '\u202A' && ch <= '\u218F')
208
// || (ch >= '\u2800' && ch <= '\uFFEF')
209
// ;
210
//return false;
211
// return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch == ':'
212
// || (ch >= '0' && ch <= '9');
213
// if(ch < LOOKUP_MAX_CHAR) return (lookupNameStartChar[ (int)ch / 32 ] & (1 << (ch % 32))) != 0;
214
// if(ch <= '\u2027') return true;
215
// //[#x202A-#x218F]
216
// if(ch < '\u202A') return false;
217
// if(ch <= '\u218F') return true;
218
// // added pairts [#x2800-#xD7FF] | [#xE000-#xFDCF] | [#xFDE0-#xFFEF] | [#x10000-#x10FFFF]
219
// if(ch < '\u2800') return false;
220
// if(ch <= '\uFFEF') return true;
221
// return false;
222

223
224         // else return (supportXml11 && ( (ch < '\u2027') || (ch > '\u2029' && ch < '\u2200') ...
225
}
226
227     //private final static boolean isNameChar(char ch) {
228
protected boolean isNameChar(char ch) {
229         //return isNameStartChar(ch);
230

231         // if(ch < LOOKUP_MAX_CHAR) return (lookupNameChar[ (int)ch / 32 ] & (1 << (ch % 32))) != 0;
232

233         return (ch < LOOKUP_MAX_CHAR && lookupNameChar[ ch ])
234             || (ch >= LOOKUP_MAX_CHAR && ch <= '\u2027')
235             || (ch >= '\u202A' && ch <= '\u218F')
236             || (ch >= '\u2800' && ch <= '\uFFEF')
237             ;
238         //return false;
239
// return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch == ':'
240
// || (ch >= '0' && ch <= '9');
241
// if(ch < LOOKUP_MAX_CHAR) return (lookupNameStartChar[ (int)ch / 32 ] & (1 << (ch % 32))) != 0;
242

243         //else return
244
// else if(ch <= '\u2027') return true;
245
// //[#x202A-#x218F]
246
// else if(ch < '\u202A') return false;
247
// else if(ch <= '\u218F') return true;
248
// // added pairts [#x2800-#xD7FF] | [#xE000-#xFDCF] | [#xFDE0-#xFFEF] | [#x10000-#x10FFFF]
249
// else if(ch < '\u2800') return false;
250
// else if(ch <= '\uFFEF') return true;
251
//else return false;
252
}
253
254     protected boolean isS(char ch) {
255         return (ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t');
256         // || (supportXml11 && (ch == '\u0085' || ch == '\u2028');
257
}
258
259     //protected boolean isChar(char ch) { return (ch < '\uD800' || ch > '\uDFFF')
260
// ch != '\u0000' ch < '\uFFFE'
261

262
263     // attribute stack
264
protected int attributeCount;
265     protected String JavaDoc attributeName[];
266     protected int attributeNameHash[];
267     //protected int attributeNameStart[];
268
//protected int attributeNameEnd[];
269
protected String JavaDoc attributePrefix[];
270     protected String JavaDoc attributeUri[];
271     protected String JavaDoc attributeValue[];
272     //protected int attributeValueStart[];
273
//protected int attributeValueEnd[];
274

275
276     /**
277      * Make sure that in attributes temporary array is enough space.
278      */

279     protected void ensureAttributesCapacity(int size) {
280         int attrPosSize = attributeName != null ? attributeName.length : 0;
281         if(size >= attrPosSize) {
282             int newSize = size > 7 ? 2 * size : 8; // = lucky 7 + 1 //25
283
if(TRACE_SIZING) {
284                 System.err.println("TRACE_SIZING attrPosSize "+attrPosSize+" ==> "+newSize);
285             }
286             boolean needsCopying = attrPosSize > 0;
287             String JavaDoc[] arr = null;
288
289             arr = new String JavaDoc[newSize];
290             if(needsCopying) System.arraycopy(attributeName, 0, arr, 0, attrPosSize);
291             attributeName = arr;
292
293             arr = new String JavaDoc[newSize];
294             if(needsCopying) System.arraycopy(attributePrefix, 0, arr, 0, attrPosSize);
295             attributePrefix = arr;
296
297             arr = new String JavaDoc[newSize];
298             if(needsCopying) System.arraycopy(attributeUri, 0, arr, 0, attrPosSize);
299             attributeUri = arr;
300
301             arr = new String JavaDoc[newSize];
302             if(needsCopying) System.arraycopy(attributeValue, 0, arr, 0, attrPosSize);
303             attributeValue = arr;
304
305             if( ! allStringsInterned ) {
306                 int[] iarr = new int[newSize];
307                 if(needsCopying) System.arraycopy(attributeNameHash, 0, iarr, 0, attrPosSize);
308                 attributeNameHash = iarr;
309             }
310
311             arr = null;
312             // //assert attrUri.length > size
313
}
314     }
315
316     // namespace stack
317
protected int namespaceEnd;
318     protected String JavaDoc namespacePrefix[];
319     protected int namespacePrefixHash[];
320     protected String JavaDoc namespaceUri[];
321
322     protected void ensureNamespacesCapacity(int size) {
323         int namespaceSize = namespacePrefix != null ? namespacePrefix.length : 0;
324         if(size >= namespaceSize) {
325             int newSize = size > 7 ? 2 * size : 8; // = lucky 7 + 1 //25
326
if(TRACE_SIZING) {
327                 System.err.println("TRACE_SIZING namespaceSize "+namespaceSize+" ==> "+newSize);
328             }
329             String JavaDoc[] newNamespacePrefix = new String JavaDoc[newSize];
330             String JavaDoc[] newNamespaceUri = new String JavaDoc[newSize];
331             if(namespacePrefix != null) {
332                 System.arraycopy(
333                     namespacePrefix, 0, newNamespacePrefix, 0, namespaceEnd);
334                 System.arraycopy(
335                     namespaceUri, 0, newNamespaceUri, 0, namespaceEnd);
336             }
337             namespacePrefix = newNamespacePrefix;
338             namespaceUri = newNamespaceUri;
339
340
341             if( ! allStringsInterned ) {
342                 int[] newNamespacePrefixHash = new int[newSize];
343                 if(namespacePrefixHash != null) {
344                     System.arraycopy(
345                         namespacePrefixHash, 0, newNamespacePrefixHash, 0, namespaceEnd);
346                 }
347                 namespacePrefixHash = newNamespacePrefixHash;
348             }
349             //prefixesSize = newSize;
350
// //assert nsPrefixes.length > size && nsPrefixes.length == newSize
351
}
352     }
353
354     /**
355      * simplistic implementation of hash function that has <b>constant</b>
356      * time to compute - so it also means diminishing hash quality for long strings
357      * but for XML parsing it should be good enough ...
358      */

359     protected static final int fastHash( char ch[], int off, int len ) {
360         if(len == 0) return 0;
361         //assert len >0
362
int hash = ch[off]; // hash at beginnig
363
//try {
364
hash = (hash << 7) + ch[ off + len - 1 ]; // hash at the end
365
//} catch(ArrayIndexOutOfBoundsException aie) {
366
// aie.printStackTrace(); //should never happen ...
367
// throw new RuntimeException("this is violation of pre-condition");
368
//}
369
if(len > 16) hash = (hash << 7) + ch[ off + (len / 4)]; // 1/4 from beginning
370
if(len > 8) hash = (hash << 7) + ch[ off + (len / 2)]; // 1/2 of string size ...
371
// notice that hash is at most done 3 times <<7 so shifted by 21 bits 8 bit value
372
// so max result == 29 bits so it is quite just below 31 bits for long (2^32) ...
373
//assert hash >= 0;
374
return hash;
375     }
376
377     // entity replacement stack
378
protected int entityEnd;
379     protected String JavaDoc entityName[];
380     protected char[] entityNameBuf[];
381     protected int entityNameHash[];
382     protected char[] entityReplacementBuf[];
383     protected String JavaDoc entityReplacement[];
384
385
386     protected void ensureEntityCapacity() {
387         int entitySize = entityReplacementBuf != null ? entityReplacementBuf.length : 0;
388         if(entityEnd >= entitySize) {
389             int newSize = entityEnd > 7 ? 2 * entityEnd : 8; // = lucky 7 + 1 //25
390
if(TRACE_SIZING) {
391                 System.err.println("TRACE_SIZING entitySize "+entitySize+" ==> "+newSize);
392             }
393             String JavaDoc[] newEntityName = new String JavaDoc[newSize];
394             char[] newEntityNameBuf[] = new char[newSize][];
395             String JavaDoc[] newEntityReplacement = new String JavaDoc[newSize];
396             char[] newEntityReplacementBuf[] = new char[newSize][];
397             if(entityName != null) {
398                 System.arraycopy(entityName, 0, newEntityName, 0, entityEnd);
399                 System.arraycopy(entityReplacementBuf, 0, newEntityReplacement, 0, entityEnd);
400                 System.arraycopy(entityReplacement, 0, newEntityReplacement, 0, entityEnd);
401                 System.arraycopy(entityReplacementBuf, 0, newEntityReplacementBuf, 0, entityEnd);
402             }
403             entityName = newEntityName;
404             entityNameBuf = newEntityNameBuf;
405             entityReplacement = newEntityReplacement;
406             entityReplacementBuf = newEntityReplacementBuf;
407
408             if( ! allStringsInterned ) {
409                 int[] newEntityNameHash = new int[newSize];
410                 if(entityNameHash != null) {
411                     System.arraycopy(entityNameHash, 0, newEntityNameHash, 0, entityEnd);
412                 }
413                 entityNameHash = newEntityNameHash;
414             }
415         }
416     }
417
418     // input buffer management
419
protected static final int READ_CHUNK_SIZE = 8*1024; //max data chars in one read() call
420
protected Reader JavaDoc reader;
421     protected String JavaDoc inputEncoding;
422
423
424     protected int bufLoadFactor = 95; // 99%
425
//protected int bufHardLimit; // only matters when expanding
426

427     protected char buf[] = new char[
428         Runtime.getRuntime().freeMemory() > 1000000L ? READ_CHUNK_SIZE : 256 ];
429     protected int bufSoftLimit = ( bufLoadFactor * buf.length ) /100; // desirable size of buffer
430
protected boolean preventBufferCompaction;
431
432     protected int bufAbsoluteStart; // this is buf
433
protected int bufStart;
434     protected int bufEnd;
435     protected int pos;
436     protected int posStart;
437     protected int posEnd;
438
439     protected char pc[] = new char[
440         Runtime.getRuntime().freeMemory() > 1000000L ? READ_CHUNK_SIZE : 64 ];
441     protected int pcStart;
442     protected int pcEnd;
443
444
445     // parsing state
446
//protected boolean needsMore;
447
//protected boolean seenMarkup;
448
protected boolean usePC;
449
450
451     protected boolean seenStartTag;
452     protected boolean seenEndTag;
453     protected boolean pastEndTag;
454     protected boolean seenAmpersand;
455     protected boolean seenMarkup;
456     protected boolean seenDocdecl;
457
458     // transient variable set during each call to next/Token()
459
protected boolean tokenize;
460     protected String JavaDoc text;
461     protected String JavaDoc entityRefName;
462
463     protected String JavaDoc xmlDeclVersion;
464     protected Boolean JavaDoc xmlDeclStandalone;
465     protected String JavaDoc xmlDeclContent;
466
467     protected void reset() {
468         //System.out.println("reset() called");
469
lineNumber = 1;
470         columnNumber = 0;
471         seenRoot = false;
472         reachedEnd = false;
473         eventType = START_DOCUMENT;
474         emptyElementTag = false;
475
476         depth = 0;
477
478         attributeCount = 0;
479
480         namespaceEnd = 0;
481
482         entityEnd = 0;
483
484         reader = null;
485         inputEncoding = null;
486
487         preventBufferCompaction = false;
488         bufAbsoluteStart = 0;
489         bufEnd = bufStart = 0;
490         pos = posStart = posEnd = 0;
491
492         pcEnd = pcStart = 0;
493
494         usePC = false;
495
496         seenStartTag = false;
497         seenEndTag = false;
498         pastEndTag = false;
499         seenAmpersand = false;
500         seenMarkup = false;
501         seenDocdecl = false;
502
503         xmlDeclVersion = null;
504         xmlDeclStandalone = null;
505         xmlDeclContent = null;
506
507         resetStringCache();
508     }
509
510     public MXParser() {
511     }
512
513
514     /**
515      * Method setFeature
516      *
517      * @param name a String
518      * @param state a boolean
519      *
520      * @throws XmlPullParserException
521      *
522      */

523     public void setFeature(String JavaDoc name,
524                            boolean state) throws XmlPullParserException
525     {
526         if(name == null) throw new IllegalArgumentException JavaDoc("feature name should not be nulll");
527         if(FEATURE_PROCESS_NAMESPACES.equals(name)) {
528             if(eventType != START_DOCUMENT) throw new XmlPullParserException(
529                     "namespace processing feature can only be changed before parsing", this, null);
530             processNamespaces = state;
531             // } else if(FEATURE_REPORT_NAMESPACE_ATTRIBUTES.equals(name)) {
532
// if(type != START_DOCUMENT) throw new XmlPullParserException(
533
// "namespace reporting feature can only be changed before parsing", this, null);
534
// reportNsAttribs = state;
535
} else if(FEATURE_NAMES_INTERNED.equals(name)) {
536             if(state != false) {
537                 throw new XmlPullParserException(
538                     "interning names in this implementation is not supported");
539             }
540         } else if(FEATURE_PROCESS_DOCDECL.equals(name)) {
541             if(state != false) {
542                 throw new XmlPullParserException(
543                     "processing DOCDECL is not supported");
544             }
545             //} else if(REPORT_DOCDECL.equals(name)) {
546
// paramNotifyDoctype = state;
547
} else if(FEATURE_XML_ROUNDTRIP.equals(name)) {
548             //if(state == false) {
549
// throw new XmlPullParserException(
550
// "roundtrip feature can not be switched off");
551
//}
552
roundtripSupported = state;
553         } else {
554             throw new XmlPullParserException("unknown feature "+name);
555         }
556     }
557
558     /** Unknown properties are <string>always</strong> returned as false */
559     public boolean getFeature(String JavaDoc name)
560     {
561         if(name == null) throw new IllegalArgumentException JavaDoc("feature name should not be nulll");
562         if(FEATURE_PROCESS_NAMESPACES.equals(name)) {
563             return processNamespaces;
564             // } else if(FEATURE_REPORT_NAMESPACE_ATTRIBUTES.equals(name)) {
565
// return reportNsAttribs;
566
} else if(FEATURE_NAMES_INTERNED.equals(name)) {
567             return false;
568         } else if(FEATURE_PROCESS_DOCDECL.equals(name)) {
569             return false;
570             //} else if(REPORT_DOCDECL.equals(name)) {
571
// return paramNotifyDoctype;
572
} else if(FEATURE_XML_ROUNDTRIP.equals(name)) {
573             //return true;
574
return roundtripSupported;
575         }
576         return false;
577     }
578
579     public void setProperty(String JavaDoc name,
580                             Object JavaDoc value)
581         throws XmlPullParserException
582     {
583         throw new XmlPullParserException("unsupported property: '"+name+"'");
584     }
585
586
587     public Object JavaDoc getProperty(String JavaDoc name)
588     {
589         if(name == null) throw new IllegalArgumentException JavaDoc("property name should not be nulll");
590         if(PROPERTY_XMLDECL_VERSION.equals(name)) {
591             return xmlDeclVersion;
592         } else if(PROPERTY_XMLDECL_STANDALONE.equals(name)) {
593             return xmlDeclStandalone;
594         } else if(PROPERTY_XMLDECL_CONTENT.equals(name)) {
595             return xmlDeclContent;
596         }
597         return null;
598     }
599
600
601     public void setInput(Reader JavaDoc in) throws XmlPullParserException
602     {
603         reset();
604         reader = in;
605     }
606
607
608     public void setInput(java.io.InputStream JavaDoc inputStream, String JavaDoc inputEncoding)
609         throws XmlPullParserException
610     {
611         if(inputStream == null) {
612             throw new IllegalArgumentException JavaDoc("input stream can not be null");
613         }
614         Reader JavaDoc reader;
615         if(inputEncoding != null) {
616             try {
617                 if(inputEncoding != null) {
618                     reader = new InputStreamReader JavaDoc(inputStream, inputEncoding);
619                 } else {
620                     reader = new InputStreamReader JavaDoc(inputStream);
621                 }
622             } catch (UnsupportedEncodingException JavaDoc une) {
623                 throw new XmlPullParserException(
624                     "could not create reader for encoding "+inputEncoding+" : "+une, this, une);
625             }
626         } else {
627             reader = new InputStreamReader JavaDoc(inputStream);
628         }
629         setInput(reader);
630         //must be here as reest() was called in setInput() and has set this.inputEncoding to null ...
631
this.inputEncoding = inputEncoding;
632     }
633
634     public String JavaDoc getInputEncoding() {
635         return inputEncoding;
636     }
637
638     public void defineEntityReplacementText(String JavaDoc entityName,
639                                             String JavaDoc replacementText)
640         throws XmlPullParserException
641     {
642         // throw new XmlPullParserException("not allowed");
643

644         //protected char[] entityReplacement[];
645
ensureEntityCapacity();
646
647         // this is to make sure that if interning works we wil take advatage of it ...
648
this.entityName[entityEnd] = newString(entityName.toCharArray(), 0, entityName.length());
649         entityNameBuf[entityEnd] = entityName.toCharArray();
650
651         entityReplacement[entityEnd] = replacementText;
652         entityReplacementBuf[entityEnd] = replacementText.toCharArray();
653         if(!allStringsInterned) {
654             entityNameHash[ entityEnd ] =
655                 fastHash(entityNameBuf[entityEnd], 0, entityNameBuf[entityEnd].length);
656         }
657         ++entityEnd;
658         //TODO disallow < or & in entity replacement text (or ]]>???)
659
// TOOD keepEntityNormalizedForAttributeValue cached as well ...
660
}
661
662     public int getNamespaceCount(int depth)
663         throws XmlPullParserException
664     {
665         if(processNamespaces == false || depth == 0) {
666             return 0;
667         }
668         //int maxDepth = eventType == END_TAG ? this.depth + 1 : this.depth;
669
//if(depth < 0 || depth > maxDepth) throw new IllegalArgumentException(
670
if(depth < 0 || depth > this.depth) throw new IllegalArgumentException JavaDoc(
671                 "napespace count mayt be for depth 0.."+this.depth+" not "+depth);
672         return elNamespaceCount[ depth ];
673     }
674
675     public String JavaDoc getNamespacePrefix(int pos)
676         throws XmlPullParserException
677     {
678
679         //int end = eventType == END_TAG ? elNamespaceCount[ depth + 1 ] : namespaceEnd;
680
//if(pos < end) {
681
if(pos < namespaceEnd) {
682             return namespacePrefix[ pos ];
683         } else {
684             throw new XmlPullParserException(
685                 "position "+pos+" exceeded number of available namespaces "+namespaceEnd);
686         }
687     }
688
689     public String JavaDoc getNamespaceUri(int pos) throws XmlPullParserException
690     {
691         //int end = eventType == END_TAG ? elNamespaceCount[ depth + 1 ] : namespaceEnd;
692
//if(pos < end) {
693
if(pos < namespaceEnd) {
694             return namespaceUri[ pos ];
695         } else {
696             throw new XmlPullParserException(
697                 "position "+pos+" exceedded number of available namespaces "+namespaceEnd);
698         }
699     }
700
701     public String JavaDoc getNamespace( String JavaDoc prefix )
702         //throws XmlPullParserException
703
{
704         //int count = namespaceCount[ depth ];
705
if(prefix != null) {
706             for( int i = namespaceEnd -1; i >= 0; i--) {
707                 if( prefix.equals( namespacePrefix[ i ] ) ) {
708                     return namespaceUri[ i ];
709                 }
710             }
711             if("xml".equals( prefix )) {
712                 return XML_URI;
713             } else if("xmlns".equals( prefix )) {
714                 return XMLNS_URI;
715             }
716         } else {
717             for( int i = namespaceEnd -1; i >= 0; i--) {
718                 if( namespacePrefix[ i ] == null ) {
719                     return namespaceUri[ i ];
720                 }
721             }
722
723         }
724         return null;
725     }
726
727
728     public int getDepth()
729     {
730         return depth;
731     }
732
733
734     private static int findFragment(int bufMinPos, char[] b, int start, int end) {
735         //System.err.println("bufStart="+bufStart+" b="+printable(new String(b, start, end - start))+" start="+start+" end="+end);
736
if(start < bufMinPos) {
737             start = bufMinPos;
738             if(start > end) start = end;
739             return start;
740         }
741         if(end - start > 65) {
742             start = end - 10; // try to find good location
743
}
744         int i = start + 1;
745         while(--i > bufMinPos) {
746             if((end - i) > 65) break;
747             char c = b[i];
748             if(c == '<' && (start - i) > 10) break;
749         }
750         return i;
751     }
752
753
754     /**
755      * Return string describing current position of parsers as
756      * text 'STATE [seen %s...] @line:column'.
757      */

758     public String JavaDoc getPositionDescription ()
759     {
760         String JavaDoc fragment = null;
761         if(posStart <= pos) {
762             int start = findFragment(0, buf, posStart, pos);
763             //System.err.println("start="+start);
764
if(start < pos) {
765                 fragment = new String JavaDoc(buf, start, pos - start);
766             }
767             if(bufAbsoluteStart > 0 || start > 0) fragment = "..." + fragment;
768         }
769         // return " at line "+tokenizerPosRow
770
// +" and column "+(tokenizerPosCol-1)
771
// +(fragment != null ? " seen "+printable(fragment)+"..." : "");
772
return " "+TYPES[ eventType ] +
773             (fragment != null ? " seen "+printable(fragment)+"..." : "")+
774             " @"+getLineNumber()+":"+getColumnNumber();
775     }
776
777     public int getLineNumber()
778     {
779         return lineNumber;
780     }
781
782     public int getColumnNumber()
783     {
784         return columnNumber;
785     }
786
787
788     public boolean isWhitespace() throws XmlPullParserException
789     {
790         if(eventType == TEXT || eventType == CDSECT) {
791             if(usePC) {
792