src/share/jaxws_classes/com/sun/xml/internal/fastinfoset/stax/StAXDocumentParser.java

changeset 0
373ffda63c9a
child 637
9c07ef4934dd
equal deleted inserted replaced
-1:000000000000 0:373ffda63c9a
1 /*
2 * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 *
25 * THIS FILE WAS MODIFIED BY SUN MICROSYSTEMS, INC.
26 */
27
28 package com.sun.xml.internal.fastinfoset.stax;
29
30 import com.sun.xml.internal.fastinfoset.Decoder;
31 import com.sun.xml.internal.fastinfoset.DecoderStateTables;
32 import com.sun.xml.internal.fastinfoset.EncodingConstants;
33 import com.sun.xml.internal.fastinfoset.OctetBufferListener;
34 import com.sun.xml.internal.fastinfoset.QualifiedName;
35 import com.sun.xml.internal.fastinfoset.algorithm.BuiltInEncodingAlgorithmFactory;
36 import com.sun.xml.internal.fastinfoset.sax.AttributesHolder;
37 import com.sun.xml.internal.fastinfoset.util.CharArray;
38 import com.sun.xml.internal.fastinfoset.util.CharArrayString;
39 import java.io.IOException;
40 import java.io.InputStream;
41 import java.util.Iterator;
42 import java.util.NoSuchElementException;
43 import javax.xml.namespace.NamespaceContext;
44 import javax.xml.namespace.QName;
45 import javax.xml.stream.Location;
46 import javax.xml.stream.XMLStreamException;
47 import javax.xml.stream.XMLStreamReader;
48 import com.sun.xml.internal.org.jvnet.fastinfoset.EncodingAlgorithm;
49 import com.sun.xml.internal.org.jvnet.fastinfoset.EncodingAlgorithmException;
50 import com.sun.xml.internal.org.jvnet.fastinfoset.EncodingAlgorithmIndexes;
51 import com.sun.xml.internal.org.jvnet.fastinfoset.FastInfosetException;
52 import com.sun.xml.internal.fastinfoset.CommonResourceBundle;
53 import com.sun.xml.internal.fastinfoset.org.apache.xerces.util.XMLChar;
54 import com.sun.xml.internal.fastinfoset.util.DuplicateAttributeVerifier;
55 import java.util.logging.Level;
56 import java.util.logging.Logger;
57 import com.sun.xml.internal.org.jvnet.fastinfoset.stax.FastInfosetStreamReader;
58
59 /**
60 * The Fast Infoset StAX parser.
61 * <p>
62 * Instantiate this parser to parse a fast infoset document in accordance
63 * with the StAX API.
64 *
65 * <p>
66 * More than one fast infoset document may be decoded from the
67 * {@link java.io.InputStream}.
68 */
69 public class StAXDocumentParser extends Decoder
70 implements XMLStreamReader, FastInfosetStreamReader, OctetBufferListener {
71 private static final Logger logger = Logger.getLogger(StAXDocumentParser.class.getName());
72
73 protected static final int INTERNAL_STATE_START_DOCUMENT = 0;
74 protected static final int INTERNAL_STATE_START_ELEMENT_TERMINATE = 1;
75 protected static final int INTERNAL_STATE_SINGLE_TERMINATE_ELEMENT_WITH_NAMESPACES = 2;
76 protected static final int INTERNAL_STATE_DOUBLE_TERMINATE_ELEMENT = 3;
77 protected static final int INTERNAL_STATE_END_DOCUMENT = 4;
78 protected static final int INTERNAL_STATE_VOID = -1;
79
80 protected int _internalState;
81
82 /**
83 * Current event
84 */
85 protected int _eventType;
86
87 /**
88 * Stack of qualified names and namespaces
89 */
90 protected QualifiedName[] _qNameStack = new QualifiedName[32];
91 protected int[] _namespaceAIIsStartStack = new int[32];
92 protected int[] _namespaceAIIsEndStack = new int[32];
93 protected int _stackCount = -1;
94
95 protected String[] _namespaceAIIsPrefix = new String[32];
96 protected String[] _namespaceAIIsNamespaceName = new String[32];
97 protected int[] _namespaceAIIsPrefixIndex = new int[32];
98 protected int _namespaceAIIsIndex;
99
100 /**
101 * Namespaces associated with START_ELEMENT or END_ELEMENT
102 */
103 protected int _currentNamespaceAIIsStart;
104 protected int _currentNamespaceAIIsEnd;
105
106 /**
107 * Qualified name associated with START_ELEMENT or END_ELEMENT.
108 */
109 protected QualifiedName _qualifiedName;
110
111 /**
112 * List of attributes
113 */
114 protected AttributesHolder _attributes = new AttributesHolder();
115
116 protected boolean _clearAttributes = false;
117
118 /**
119 * Characters associated with event.
120 */
121 protected char[] _characters;
122 protected int _charactersOffset;
123
124 protected String _algorithmURI;
125 protected int _algorithmId;
126 protected boolean _isAlgorithmDataCloned;
127 protected byte[] _algorithmData;
128 protected int _algorithmDataOffset;
129 protected int _algorithmDataLength;
130
131 /**
132 * State for processing instruction
133 */
134 protected String _piTarget;
135 protected String _piData;
136
137 protected NamespaceContextImpl _nsContext = new NamespaceContextImpl();
138
139 protected String _characterEncodingScheme;
140
141 protected StAXManager _manager;
142
143 public StAXDocumentParser() {
144 reset();
145 _manager = new StAXManager(StAXManager.CONTEXT_READER);
146 }
147
148 public StAXDocumentParser(InputStream s) {
149 this();
150 setInputStream(s);
151 _manager = new StAXManager(StAXManager.CONTEXT_READER);
152 }
153
154 public StAXDocumentParser(InputStream s, StAXManager manager) {
155 this(s);
156 _manager = manager;
157 }
158
159 @Override
160 public void setInputStream(InputStream s) {
161 super.setInputStream(s);
162 reset();
163 }
164
165 @Override
166 public void reset() {
167 super.reset();
168 if (_internalState != INTERNAL_STATE_START_DOCUMENT &&
169 _internalState != INTERNAL_STATE_END_DOCUMENT) {
170
171 for (int i = _namespaceAIIsIndex - 1; i >= 0; i--) {
172 _prefixTable.popScopeWithPrefixEntry(_namespaceAIIsPrefixIndex[i]);
173 }
174
175 _stackCount = -1;
176
177 _namespaceAIIsIndex = 0;
178 _characters = null;
179 _algorithmData = null;
180 }
181
182 _characterEncodingScheme = "UTF-8";
183 _eventType = START_DOCUMENT;
184 _internalState = INTERNAL_STATE_START_DOCUMENT;
185 }
186
187 protected void resetOnError() {
188 super.reset();
189
190 if (_v != null) {
191 _prefixTable.clearCompletely();
192 }
193 _duplicateAttributeVerifier.clear();
194
195 _stackCount = -1;
196
197 _namespaceAIIsIndex = 0;
198 _characters = null;
199 _algorithmData = null;
200
201 _eventType = START_DOCUMENT;
202 _internalState = INTERNAL_STATE_START_DOCUMENT;
203 }
204
205 // -- XMLStreamReader Interface -------------------------------------------
206
207 public Object getProperty(java.lang.String name)
208 throws java.lang.IllegalArgumentException {
209 if (_manager != null) {
210 return _manager.getProperty(name);
211 }
212 return null;
213 }
214
215 public int next() throws XMLStreamException {
216 try {
217 if (_internalState != INTERNAL_STATE_VOID) {
218 switch (_internalState) {
219 case INTERNAL_STATE_START_DOCUMENT:
220 decodeHeader();
221 processDII();
222
223 _internalState = INTERNAL_STATE_VOID;
224 break;
225 case INTERNAL_STATE_START_ELEMENT_TERMINATE:
226 if (_currentNamespaceAIIsEnd > 0) {
227 for (int i = _currentNamespaceAIIsEnd - 1; i >= _currentNamespaceAIIsStart; i--) {
228 _prefixTable.popScopeWithPrefixEntry(_namespaceAIIsPrefixIndex[i]);
229 }
230 _namespaceAIIsIndex = _currentNamespaceAIIsStart;
231 }
232
233 // Pop information off the stack
234 popStack();
235
236 _internalState = INTERNAL_STATE_VOID;
237 return _eventType = END_ELEMENT;
238 case INTERNAL_STATE_SINGLE_TERMINATE_ELEMENT_WITH_NAMESPACES:
239 // Undeclare namespaces
240 for (int i = _currentNamespaceAIIsEnd - 1; i >= _currentNamespaceAIIsStart; i--) {
241 _prefixTable.popScopeWithPrefixEntry(_namespaceAIIsPrefixIndex[i]);
242 }
243 _namespaceAIIsIndex = _currentNamespaceAIIsStart;
244 _internalState = INTERNAL_STATE_VOID;
245 break;
246 case INTERNAL_STATE_DOUBLE_TERMINATE_ELEMENT:
247 // Undeclare namespaces
248 if (_currentNamespaceAIIsEnd > 0) {
249 for (int i = _currentNamespaceAIIsEnd - 1; i >= _currentNamespaceAIIsStart; i--) {
250 _prefixTable.popScopeWithPrefixEntry(_namespaceAIIsPrefixIndex[i]);
251 }
252 _namespaceAIIsIndex = _currentNamespaceAIIsStart;
253 }
254
255 if (_stackCount == -1) {
256 _internalState = INTERNAL_STATE_END_DOCUMENT;
257 return _eventType = END_DOCUMENT;
258 }
259
260 // Pop information off the stack
261 popStack();
262
263 _internalState = (_currentNamespaceAIIsEnd > 0) ?
264 INTERNAL_STATE_SINGLE_TERMINATE_ELEMENT_WITH_NAMESPACES :
265 INTERNAL_STATE_VOID;
266 return _eventType = END_ELEMENT;
267 case INTERNAL_STATE_END_DOCUMENT:
268 throw new NoSuchElementException(CommonResourceBundle.getInstance().getString("message.noMoreEvents"));
269 }
270 }
271
272 // Reset internal state
273 _characters = null;
274 _algorithmData = null;
275 _currentNamespaceAIIsEnd = 0;
276
277 // Process information item
278 final int b = read();
279 switch(DecoderStateTables.EII(b)) {
280 case DecoderStateTables.EII_NO_AIIS_INDEX_SMALL:
281 processEII(_elementNameTable._array[b], false);
282 return _eventType;
283 case DecoderStateTables.EII_AIIS_INDEX_SMALL:
284 processEII(_elementNameTable._array[b & EncodingConstants.INTEGER_3RD_BIT_SMALL_MASK], true);
285 return _eventType;
286 case DecoderStateTables.EII_INDEX_MEDIUM:
287 processEII(processEIIIndexMedium(b), (b & EncodingConstants.ELEMENT_ATTRIBUTE_FLAG) > 0);
288 return _eventType;
289 case DecoderStateTables.EII_INDEX_LARGE:
290 processEII(processEIIIndexLarge(b), (b & EncodingConstants.ELEMENT_ATTRIBUTE_FLAG) > 0);
291 return _eventType;
292 case DecoderStateTables.EII_LITERAL:
293 {
294 final QualifiedName qn = processLiteralQualifiedName(
295 b & EncodingConstants.LITERAL_QNAME_PREFIX_NAMESPACE_NAME_MASK,
296 _elementNameTable.getNext());
297 _elementNameTable.add(qn);
298 processEII(qn, (b & EncodingConstants.ELEMENT_ATTRIBUTE_FLAG) > 0);
299 return _eventType;
300 }
301 case DecoderStateTables.EII_NAMESPACES:
302 processEIIWithNamespaces((b & EncodingConstants.ELEMENT_ATTRIBUTE_FLAG) > 0);
303 return _eventType;
304 case DecoderStateTables.CII_UTF8_SMALL_LENGTH:
305 _octetBufferLength = (b & EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_SMALL_MASK)
306 + 1;
307 processUtf8CharacterString(b);
308 return _eventType = CHARACTERS;
309 case DecoderStateTables.CII_UTF8_MEDIUM_LENGTH:
310 _octetBufferLength = read() + EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_SMALL_LIMIT;
311 processUtf8CharacterString(b);
312 return _eventType = CHARACTERS;
313 case DecoderStateTables.CII_UTF8_LARGE_LENGTH:
314 _octetBufferLength = ((read() << 24) |
315 (read() << 16) |
316 (read() << 8) |
317 read())
318 + EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_MEDIUM_LIMIT;
319 processUtf8CharacterString(b);
320 return _eventType = CHARACTERS;
321 case DecoderStateTables.CII_UTF16_SMALL_LENGTH:
322 _octetBufferLength = (b & EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_SMALL_MASK)
323 + 1;
324 processUtf16CharacterString(b);
325 return _eventType = CHARACTERS;
326 case DecoderStateTables.CII_UTF16_MEDIUM_LENGTH:
327 _octetBufferLength = read() + EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_SMALL_LIMIT;
328 processUtf16CharacterString(b);
329 return _eventType = CHARACTERS;
330 case DecoderStateTables.CII_UTF16_LARGE_LENGTH:
331 _octetBufferLength = ((read() << 24) |
332 (read() << 16) |
333 (read() << 8) |
334 read())
335 + EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_MEDIUM_LIMIT;
336 processUtf16CharacterString(b);
337 return _eventType = CHARACTERS;
338 case DecoderStateTables.CII_RA:
339 {
340 final boolean addToTable = (b & EncodingConstants.CHARACTER_CHUNK_ADD_TO_TABLE_FLAG) > 0;
341
342 _identifier = (b & 0x02) << 6;
343 final int b2 = read();
344 _identifier |= (b2 & 0xFC) >> 2;
345
346 decodeOctetsOnSeventhBitOfNonIdentifyingStringOnThirdBit(b2);
347
348 decodeRestrictedAlphabetAsCharBuffer();
349
350 if (addToTable) {
351 _charactersOffset = _characterContentChunkTable.add(_charBuffer, _charBufferLength);
352 _characters = _characterContentChunkTable._array;
353 } else {
354 _characters = _charBuffer;
355 _charactersOffset = 0;
356 }
357 return _eventType = CHARACTERS;
358 }
359 case DecoderStateTables.CII_EA:
360 {
361 final boolean addToTable = (b & EncodingConstants.CHARACTER_CHUNK_ADD_TO_TABLE_FLAG) > 0;
362 // Decode encoding algorithm integer
363 _algorithmId = (b & 0x02) << 6;
364 final int b2 = read();
365 _algorithmId |= (b2 & 0xFC) >> 2;
366
367 decodeOctetsOnSeventhBitOfNonIdentifyingStringOnThirdBit(b2);
368 processCIIEncodingAlgorithm(addToTable);
369
370 if (_algorithmId == EncodingAlgorithmIndexes.CDATA) {
371 return _eventType = CDATA;
372 }
373
374 return _eventType = CHARACTERS;
375 }
376 case DecoderStateTables.CII_INDEX_SMALL:
377 {
378 final int index = b & EncodingConstants.INTEGER_4TH_BIT_SMALL_MASK;
379 _characterContentChunkTable._cachedIndex = index;
380
381 _characters = _characterContentChunkTable._array;
382 _charactersOffset = _characterContentChunkTable._offset[index];
383 _charBufferLength = _characterContentChunkTable._length[index];
384 return _eventType = CHARACTERS;
385 }
386 case DecoderStateTables.CII_INDEX_MEDIUM:
387 {
388 final int index = (((b & EncodingConstants.INTEGER_4TH_BIT_MEDIUM_MASK) << 8) | read())
389 + EncodingConstants.INTEGER_4TH_BIT_SMALL_LIMIT;
390 _characterContentChunkTable._cachedIndex = index;
391
392 _characters = _characterContentChunkTable._array;
393 _charactersOffset = _characterContentChunkTable._offset[index];
394 _charBufferLength = _characterContentChunkTable._length[index];
395 return _eventType = CHARACTERS;
396 }
397 case DecoderStateTables.CII_INDEX_LARGE:
398 {
399 final int index = (((b & EncodingConstants.INTEGER_4TH_BIT_LARGE_MASK) << 16) |
400 (read() << 8) |
401 read())
402 + EncodingConstants.INTEGER_4TH_BIT_MEDIUM_LIMIT;
403 _characterContentChunkTable._cachedIndex = index;
404
405 _characters = _characterContentChunkTable._array;
406 _charactersOffset = _characterContentChunkTable._offset[index];
407 _charBufferLength = _characterContentChunkTable._length[index];
408 return _eventType = CHARACTERS;
409 }
410 case DecoderStateTables.CII_INDEX_LARGE_LARGE:
411 {
412 final int index = ((read() << 16) |
413 (read() << 8) |
414 read())
415 + EncodingConstants.INTEGER_4TH_BIT_LARGE_LIMIT;
416 _characterContentChunkTable._cachedIndex = index;
417
418 _characters = _characterContentChunkTable._array;
419 _charactersOffset = _characterContentChunkTable._offset[index];
420 _charBufferLength = _characterContentChunkTable._length[index];
421 return _eventType = CHARACTERS;
422 }
423 case DecoderStateTables.COMMENT_II:
424 processCommentII();
425 return _eventType;
426 case DecoderStateTables.PROCESSING_INSTRUCTION_II:
427 processProcessingII();
428 return _eventType;
429 case DecoderStateTables.UNEXPANDED_ENTITY_REFERENCE_II:
430 {
431 processUnexpandedEntityReference(b);
432 // Skip the reference
433 return next();
434 }
435 case DecoderStateTables.TERMINATOR_DOUBLE:
436 if (_stackCount != -1) {
437 // Pop information off the stack
438 popStack();
439
440 _internalState = INTERNAL_STATE_DOUBLE_TERMINATE_ELEMENT;
441 return _eventType = END_ELEMENT;
442 }
443
444 _internalState = INTERNAL_STATE_END_DOCUMENT;
445 return _eventType = END_DOCUMENT;
446 case DecoderStateTables.TERMINATOR_SINGLE:
447 if (_stackCount != -1) {
448 // Pop information off the stack
449 popStack();
450
451 if (_currentNamespaceAIIsEnd > 0) {
452 _internalState = INTERNAL_STATE_SINGLE_TERMINATE_ELEMENT_WITH_NAMESPACES;
453 }
454 return _eventType = END_ELEMENT;
455 }
456
457 _internalState = INTERNAL_STATE_END_DOCUMENT;
458 return _eventType = END_DOCUMENT;
459 default:
460 throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.IllegalStateDecodingEII"));
461 }
462 } catch (IOException e) {
463 resetOnError();
464 logger.log(Level.FINE, "next() exception", e);
465 throw new XMLStreamException(e);
466 } catch (FastInfosetException e) {
467 resetOnError();
468 logger.log(Level.FINE, "next() exception", e);
469 throw new XMLStreamException(e);
470 } catch (RuntimeException e) {
471 resetOnError();
472 logger.log(Level.FINE, "next() exception", e);
473 throw e;
474 }
475 }
476
477 private final void processUtf8CharacterString(final int b) throws IOException {
478 if ((b & EncodingConstants.CHARACTER_CHUNK_ADD_TO_TABLE_FLAG) > 0) {
479 _characterContentChunkTable.ensureSize(_octetBufferLength);
480 _characters = _characterContentChunkTable._array;
481 _charactersOffset = _characterContentChunkTable._arrayIndex;
482 decodeUtf8StringAsCharBuffer(_characterContentChunkTable._array, _charactersOffset);
483 _characterContentChunkTable.add(_charBufferLength);
484 } else {
485 decodeUtf8StringAsCharBuffer();
486 _characters = _charBuffer;
487 _charactersOffset = 0;
488 }
489 }
490
491 private final void processUtf16CharacterString(final int b) throws IOException {
492 decodeUtf16StringAsCharBuffer();
493 if ((b & EncodingConstants.CHARACTER_CHUNK_ADD_TO_TABLE_FLAG) > 0) {
494 _charactersOffset = _characterContentChunkTable.add(_charBuffer, _charBufferLength);
495 _characters = _characterContentChunkTable._array;
496 } else {
497 _characters = _charBuffer;
498 _charactersOffset = 0;
499 }
500 }
501
502 private void popStack() {
503 // Pop information off the stack
504 _qualifiedName = _qNameStack[_stackCount];
505 _currentNamespaceAIIsStart = _namespaceAIIsStartStack[_stackCount];
506 _currentNamespaceAIIsEnd = _namespaceAIIsEndStack[_stackCount];
507 _qNameStack[_stackCount--] = null;
508 }
509
510 /** Test if the current event is of the given type and if the namespace and name match the current namespace and name of the current event.
511 * If the namespaceURI is null it is not checked for equality, if the localName is null it is not checked for equality.
512 * @param type the event type
513 * @param namespaceURI the uri of the event, may be null
514 * @param localName the localName of the event, may be null
515 * @throws XMLStreamException if the required values are not matched.
516 */
517 public final void require(int type, String namespaceURI, String localName)
518 throws XMLStreamException {
519 if( type != _eventType)
520 throw new XMLStreamException(CommonResourceBundle.getInstance().getString("message.eventTypeNotMatch", new Object[]{getEventTypeString(type)}));
521 if( namespaceURI != null && !namespaceURI.equals(getNamespaceURI()) )
522 throw new XMLStreamException(CommonResourceBundle.getInstance().getString("message.namespaceURINotMatch", new Object[]{namespaceURI}));
523 if(localName != null && !localName.equals(getLocalName()))
524 throw new XMLStreamException(CommonResourceBundle.getInstance().getString("message.localNameNotMatch", new Object[]{localName}));
525 }
526
527 /** Reads the content of a text-only element. Precondition:
528 * the current event is START_ELEMENT. Postcondition:
529 * The current event is the corresponding END_ELEMENT.
530 * @throws XMLStreamException if the current event is not a START_ELEMENT or if
531 * a non text element is encountered
532 */
533 public final String getElementText() throws XMLStreamException {
534
535 if(getEventType() != START_ELEMENT) {
536 throw new XMLStreamException(
537 CommonResourceBundle.getInstance().getString("message.mustBeOnSTARTELEMENT"), getLocation());
538 }
539 //current is StartElement, move to the next
540 next();
541 return getElementText(true);
542 }
543 /**
544 * @param startElementRead flag if start element has already been read
545 */
546 public final String getElementText(boolean startElementRead) throws XMLStreamException {
547 if (!startElementRead) {
548 throw new XMLStreamException(
549 CommonResourceBundle.getInstance().getString("message.mustBeOnSTARTELEMENT"), getLocation());
550 }
551 int eventType = getEventType();
552 StringBuilder content = new StringBuilder();
553 while(eventType != END_ELEMENT ) {
554 if(eventType == CHARACTERS
555 || eventType == CDATA
556 || eventType == SPACE
557 || eventType == ENTITY_REFERENCE) {
558 content.append(getText());
559 } else if(eventType == PROCESSING_INSTRUCTION
560 || eventType == COMMENT) {
561 // skipping
562 } else if(eventType == END_DOCUMENT) {
563 throw new XMLStreamException(CommonResourceBundle.getInstance().getString("message.unexpectedEOF"));
564 } else if(eventType == START_ELEMENT) {
565 throw new XMLStreamException(
566 CommonResourceBundle.getInstance().getString("message.getElementTextExpectTextOnly"), getLocation());
567 } else {
568 throw new XMLStreamException(
569 CommonResourceBundle.getInstance().getString("message.unexpectedEventType")+ getEventTypeString(eventType), getLocation());
570 }
571 eventType = next();
572 }
573 return content.toString();
574 }
575
576 /** Skips any white space (isWhiteSpace() returns true), COMMENT,
577 * or PROCESSING_INSTRUCTION,
578 * until a START_ELEMENT or END_ELEMENT is reached.
579 * If other than white space characters, COMMENT, PROCESSING_INSTRUCTION, START_ELEMENT, END_ELEMENT
580 * are encountered, an exception is thrown. This method should
581 * be used when processing element-only content seperated by white space.
582 * This method should
583 * be used when processing element-only content because
584 * the parser is not able to recognize ignorable whitespace if
585 * then DTD is missing or not interpreted.
586 * @return the event type of the element read
587 * @throws XMLStreamException if the current event is not white space
588 */
589 public final int nextTag() throws XMLStreamException {
590 next();
591 return nextTag(true);
592 }
593 /** if the current tag has already read, such as in the case EventReader's
594 * peek() has been called, the current cursor should not move before the loop
595 */
596 public final int nextTag(boolean currentTagRead) throws XMLStreamException {
597 int eventType = getEventType();
598 if (!currentTagRead) {
599 eventType = next();
600 }
601 while((eventType == CHARACTERS && isWhiteSpace()) // skip whitespace
602 || (eventType == CDATA && isWhiteSpace())
603 || eventType == SPACE
604 || eventType == PROCESSING_INSTRUCTION
605 || eventType == COMMENT) {
606 eventType = next();
607 }
608 if (eventType != START_ELEMENT && eventType != END_ELEMENT) {
609 throw new XMLStreamException(CommonResourceBundle.getInstance().getString("message.expectedStartOrEnd"), getLocation());
610 }
611 return eventType;
612 }
613
614 public final boolean hasNext() throws XMLStreamException {
615 return (_eventType != END_DOCUMENT);
616 }
617
618 public void close() throws XMLStreamException {
619 try {
620 super.closeIfRequired();
621 } catch (IOException ex) {
622 }
623 }
624
625 public final String getNamespaceURI(String prefix) {
626 String namespace = getNamespaceDecl(prefix);
627 if (namespace == null) {
628 if (prefix == null) {
629 throw new IllegalArgumentException(CommonResourceBundle.getInstance().getString("message.nullPrefix"));
630 }
631 return null; // unbound
632 }
633 return namespace;
634 }
635
636 public final boolean isStartElement() {
637 return (_eventType == START_ELEMENT);
638 }
639
640 public final boolean isEndElement() {
641 return (_eventType == END_ELEMENT);
642 }
643
644 public final boolean isCharacters() {
645 return (_eventType == CHARACTERS);
646 }
647
648 /**
649 * Returns true if the cursor points to a character data event that consists of all whitespace
650 * Application calling this method needs to cache the value and avoid calling this method again
651 * for the same event.
652 * @return true if the cursor points to all whitespace, false otherwise
653 */
654 public final boolean isWhiteSpace() {
655 if(isCharacters() || (_eventType == CDATA)){
656 char [] ch = this.getTextCharacters();
657 int start = this.getTextStart();
658 int length = this.getTextLength();
659 for (int i = start; i < start + length; i++){
660 if(!XMLChar.isSpace(ch[i])){
661 return false;
662 }
663 }
664 return true;
665 }
666 return false;
667 }
668
669 public final String getAttributeValue(String namespaceURI, String localName) {
670 if (_eventType != START_ELEMENT) {
671 throw new IllegalStateException(CommonResourceBundle.getInstance().getString("message.invalidCallingGetAttributeValue"));
672 }
673
674 if (localName == null)
675 throw new IllegalArgumentException();
676
677 // Search for the attributes in _attributes
678 if (namespaceURI != null) {
679 for (int i = 0; i < _attributes.getLength(); i++) {
680 if (_attributes.getLocalName(i).equals(localName) &&
681 _attributes.getURI(i).equals(namespaceURI)) {
682 return _attributes.getValue(i);
683 }
684 }
685 } else {
686 for (int i = 0; i < _attributes.getLength(); i++) {
687 if (_attributes.getLocalName(i).equals(localName)) {
688 return _attributes.getValue(i);
689 }
690 }
691 }
692
693 return null;
694 }
695
696 public final int getAttributeCount() {
697 if (_eventType != START_ELEMENT) {
698 throw new IllegalStateException(CommonResourceBundle.getInstance().getString("message.invalidCallingGetAttributeValue"));
699 }
700
701 return _attributes.getLength();
702 }
703
704 public final javax.xml.namespace.QName getAttributeName(int index) {
705 if (_eventType != START_ELEMENT) {
706 throw new IllegalStateException(CommonResourceBundle.getInstance().getString("message.invalidCallingGetAttributeValue"));
707 }
708 return _attributes.getQualifiedName(index).getQName();
709 }
710
711 public final String getAttributeNamespace(int index) {
712 if (_eventType != START_ELEMENT) {
713 throw new IllegalStateException(CommonResourceBundle.getInstance().getString("message.invalidCallingGetAttributeValue"));
714 }
715
716 return _attributes.getURI(index);
717 }
718
719 public final String getAttributeLocalName(int index) {
720 if (_eventType != START_ELEMENT) {
721 throw new IllegalStateException(CommonResourceBundle.getInstance().getString("message.invalidCallingGetAttributeValue"));
722 }
723 return _attributes.getLocalName(index);
724 }
725
726 public final String getAttributePrefix(int index) {
727 if (_eventType != START_ELEMENT) {
728 throw new IllegalStateException(CommonResourceBundle.getInstance().getString("message.invalidCallingGetAttributeValue"));
729 }
730 return _attributes.getPrefix(index);
731 }
732
733 public final String getAttributeType(int index) {
734 if (_eventType != START_ELEMENT) {
735 throw new IllegalStateException(CommonResourceBundle.getInstance().getString("message.invalidCallingGetAttributeValue"));
736 }
737 return _attributes.getType(index);
738 }
739
740 public final String getAttributeValue(int index) {
741 if (_eventType != START_ELEMENT) {
742 throw new IllegalStateException(CommonResourceBundle.getInstance().getString("message.invalidCallingGetAttributeValue"));
743 }
744 return _attributes.getValue(index);
745 }
746
747 public final boolean isAttributeSpecified(int index) {
748 return false; // non-validating parser
749 }
750
751 public final int getNamespaceCount() {
752 if (_eventType == START_ELEMENT || _eventType == END_ELEMENT) {
753 return (_currentNamespaceAIIsEnd > 0) ? (_currentNamespaceAIIsEnd - _currentNamespaceAIIsStart) : 0;
754 } else {
755 throw new IllegalStateException(CommonResourceBundle.getInstance().getString("message.invalidCallingGetNamespaceCount"));
756 }
757 }
758
759 public final String getNamespacePrefix(int index) {
760 if (_eventType == START_ELEMENT || _eventType == END_ELEMENT) {
761 return _namespaceAIIsPrefix[_currentNamespaceAIIsStart + index];
762 } else {
763 throw new IllegalStateException(CommonResourceBundle.getInstance().getString("message.invalidCallingGetNamespacePrefix"));
764 }
765 }
766
767 public final String getNamespaceURI(int index) {
768 if (_eventType == START_ELEMENT || _eventType == END_ELEMENT) {
769 return _namespaceAIIsNamespaceName[_currentNamespaceAIIsStart + index];
770 } else {
771 throw new IllegalStateException(CommonResourceBundle.getInstance().getString("message.invalidCallingGetNamespacePrefix"));
772 }
773 }
774
775 public final NamespaceContext getNamespaceContext() {
776 return _nsContext;
777 }
778
779 public final int getEventType() {
780 return _eventType;
781 }
782
783 public final String getText() {
784 if (_characters == null) {
785 checkTextState();
786 }
787
788 if (_characters == _characterContentChunkTable._array) {
789 return _characterContentChunkTable.getString(_characterContentChunkTable._cachedIndex);
790 } else {
791 return new String(_characters, _charactersOffset, _charBufferLength);
792 }
793 }
794
795 public final char[] getTextCharacters() {
796 if (_characters == null) {
797 checkTextState();
798 }
799
800 return _characters;
801 }
802
803 public final int getTextStart() {
804 if (_characters == null) {
805 checkTextState();
806 }
807
808 return _charactersOffset;
809 }
810
811 public final int getTextLength() {
812 if (_characters == null) {
813 checkTextState();
814 }
815
816 return _charBufferLength;
817 }
818
819 public final int getTextCharacters(int sourceStart, char[] target,
820 int targetStart, int length) throws XMLStreamException {
821 if (_characters == null) {
822 checkTextState();
823 }
824
825 try {
826 int bytesToCopy = Math.min(_charBufferLength, length);
827 System.arraycopy(_characters, _charactersOffset + sourceStart,
828 target, targetStart, bytesToCopy);
829 return bytesToCopy;
830 } catch (IndexOutOfBoundsException e) {
831 throw new XMLStreamException(e);
832 }
833 }
834
835 protected final void checkTextState() {
836 if (_algorithmData == null) {
837 throw new IllegalStateException(CommonResourceBundle.getInstance().getString("message.InvalidStateForText"));
838 }
839
840 try {
841 convertEncodingAlgorithmDataToCharacters();
842 } catch (Exception e) {
843 throw new IllegalStateException(CommonResourceBundle.getInstance().getString("message.InvalidStateForText"));
844 }
845 }
846
847 public final String getEncoding() {
848 return _characterEncodingScheme;
849 }
850
851 public final boolean hasText() {
852 return (_characters != null);
853 }
854
855 public final Location getLocation() {
856 //location should be created in next()
857 //returns a nil location for now
858 return EventLocation.getNilLocation();
859 }
860
861 public final QName getName() {
862 if (_eventType == START_ELEMENT || _eventType == END_ELEMENT) {
863 return _qualifiedName.getQName();
864 } else {
865 throw new IllegalStateException(CommonResourceBundle.getInstance().getString("message.invalidCallingGetName"));
866 }
867 }
868
869 public final String getLocalName() {
870 if (_eventType == START_ELEMENT || _eventType == END_ELEMENT) {
871 return _qualifiedName.localName;
872 } else {
873 throw new IllegalStateException(CommonResourceBundle.getInstance().getString("message.invalidCallingGetLocalName"));
874 }
875 }
876
877 public final boolean hasName() {
878 return (_eventType == START_ELEMENT || _eventType == END_ELEMENT);
879 }
880
881 public final String getNamespaceURI() {
882 if (_eventType == START_ELEMENT || _eventType == END_ELEMENT) {
883 return _qualifiedName.namespaceName;
884 } else {
885 throw new IllegalStateException(CommonResourceBundle.getInstance().getString("message.invalidCallingGetNamespaceURI"));
886 }
887 }
888
889 public final String getPrefix() {
890 if (_eventType == START_ELEMENT || _eventType == END_ELEMENT) {
891 return _qualifiedName.prefix;
892 } else {
893 throw new IllegalStateException(CommonResourceBundle.getInstance().getString("message.invalidCallingGetPrefix"));
894 }
895 }
896
897 public final String getVersion() {
898 return null;
899 }
900
901 public final boolean isStandalone() {
902 return false;
903 }
904
905 public final boolean standaloneSet() {
906 return false;
907 }
908
909 public final String getCharacterEncodingScheme() {
910 return null;
911 }
912
913 public final String getPITarget() {
914 if (_eventType != PROCESSING_INSTRUCTION) {
915 throw new IllegalStateException(CommonResourceBundle.getInstance().getString("message.invalidCallingGetPITarget"));
916 }
917
918 return _piTarget;
919 }
920
921 public final String getPIData() {
922 if (_eventType != PROCESSING_INSTRUCTION) {
923 throw new IllegalStateException(CommonResourceBundle.getInstance().getString("message.invalidCallingGetPIData"));
924 }
925
926 return _piData;
927 }
928
929
930
931
932 public final String getNameString() {
933 if (_eventType == START_ELEMENT || _eventType == END_ELEMENT) {
934 return _qualifiedName.getQNameString();
935 } else {
936 throw new IllegalStateException(CommonResourceBundle.getInstance().getString("message.invalidCallingGetName"));
937 }
938 }
939
940 public final String getAttributeNameString(int index) {
941 if (_eventType != START_ELEMENT) {
942 throw new IllegalStateException(CommonResourceBundle.getInstance().getString("message.invalidCallingGetAttributeValue"));
943 }
944 return _attributes.getQualifiedName(index).getQNameString();
945 }
946
947
948 public final String getTextAlgorithmURI() {
949 return _algorithmURI;
950 }
951
952 public final int getTextAlgorithmIndex() {
953 return _algorithmId;
954 }
955
956 public final boolean hasTextAlgorithmBytes() {
957 return _algorithmData != null;
958 }
959
960
961 /**
962 * Returns the byte[], which represents text algorithms.
963 * @deprecated was deprecated due to security reasons. Now the method return cloned byte[].
964 *
965 * @return
966 */
967 public final byte[] getTextAlgorithmBytes() {
968 // Do not return the actual _algorithmData due to security reasons
969 // return _algorithmData;
970 if (_algorithmData == null) {
971 return null;
972 }
973
974 final byte[] algorithmData = new byte[_algorithmData.length];
975 System.arraycopy(_algorithmData, 0, algorithmData, 0, _algorithmData.length);
976 return algorithmData;
977 }
978
979 public final byte[] getTextAlgorithmBytesClone() {
980 if (_algorithmData == null) {
981 return null;
982 }
983
984 byte[] algorithmData = new byte[_algorithmDataLength];
985 System.arraycopy(_algorithmData, _algorithmDataOffset, algorithmData, 0, _algorithmDataLength);
986 return algorithmData;
987 }
988
989 public final int getTextAlgorithmStart() {
990 return _algorithmDataOffset;
991 }
992
993 public final int getTextAlgorithmLength() {
994 return _algorithmDataLength;
995 }
996
997 public final int getTextAlgorithmBytes(int sourceStart, byte[] target,
998 int targetStart, int length) throws XMLStreamException {
999 try {
1000 System.arraycopy(_algorithmData, sourceStart, target,
1001 targetStart, length);
1002 return length;
1003 } catch (IndexOutOfBoundsException e) {
1004 throw new XMLStreamException(e);
1005 }
1006 }
1007
1008 // FastInfosetStreamReader impl
1009
1010 public final int peekNext() throws XMLStreamException {
1011 try {
1012 switch(DecoderStateTables.EII(peek(this))) {
1013 case DecoderStateTables.EII_NO_AIIS_INDEX_SMALL:
1014 case DecoderStateTables.EII_AIIS_INDEX_SMALL:
1015 case DecoderStateTables.EII_INDEX_MEDIUM:
1016 case DecoderStateTables.EII_INDEX_LARGE:
1017 case DecoderStateTables.EII_LITERAL:
1018 case DecoderStateTables.EII_NAMESPACES:
1019 return START_ELEMENT;
1020 case DecoderStateTables.CII_UTF8_SMALL_LENGTH:
1021 case DecoderStateTables.CII_UTF8_MEDIUM_LENGTH:
1022 case DecoderStateTables.CII_UTF8_LARGE_LENGTH:
1023 case DecoderStateTables.CII_UTF16_SMALL_LENGTH:
1024 case DecoderStateTables.CII_UTF16_MEDIUM_LENGTH:
1025 case DecoderStateTables.CII_UTF16_LARGE_LENGTH:
1026 case DecoderStateTables.CII_RA:
1027 case DecoderStateTables.CII_EA:
1028 case DecoderStateTables.CII_INDEX_SMALL:
1029 case DecoderStateTables.CII_INDEX_MEDIUM:
1030 case DecoderStateTables.CII_INDEX_LARGE:
1031 case DecoderStateTables.CII_INDEX_LARGE_LARGE:
1032 return CHARACTERS;
1033 case DecoderStateTables.COMMENT_II:
1034 return COMMENT;
1035 case DecoderStateTables.PROCESSING_INSTRUCTION_II:
1036 return PROCESSING_INSTRUCTION;
1037 case DecoderStateTables.UNEXPANDED_ENTITY_REFERENCE_II:
1038 return ENTITY_REFERENCE;
1039 case DecoderStateTables.TERMINATOR_DOUBLE:
1040 case DecoderStateTables.TERMINATOR_SINGLE:
1041 return (_stackCount != -1) ? END_ELEMENT : END_DOCUMENT;
1042 default:
1043 throw new FastInfosetException(
1044 CommonResourceBundle.getInstance().getString("message.IllegalStateDecodingEII"));
1045 }
1046 } catch (IOException e) {
1047 throw new XMLStreamException(e);
1048 } catch (FastInfosetException e) {
1049 throw new XMLStreamException(e);
1050 }
1051 }
1052
1053 public void onBeforeOctetBufferOverwrite() {
1054 if (_algorithmData != null) {
1055 _algorithmData = getTextAlgorithmBytesClone();
1056 _algorithmDataOffset = 0;
1057 _isAlgorithmDataCloned = true;
1058 }
1059 }
1060
1061 // Faster access methods without checks
1062
1063 public final int accessNamespaceCount() {
1064 return (_currentNamespaceAIIsEnd > 0) ? (_currentNamespaceAIIsEnd - _currentNamespaceAIIsStart) : 0;
1065 }
1066
1067 public final String accessLocalName() {
1068 return _qualifiedName.localName;
1069 }
1070
1071 public final String accessNamespaceURI() {
1072 return _qualifiedName.namespaceName;
1073 }
1074
1075 public final String accessPrefix() {
1076 return _qualifiedName.prefix;
1077 }
1078
1079 public final char[] accessTextCharacters() {
1080 if (_characters == null) return null;
1081
1082 // we return a cloned version of _characters
1083 final char[] clonedCharacters = new char[_characters.length];
1084 System.arraycopy(_characters, 0, clonedCharacters, 0, _characters.length);
1085 return clonedCharacters;
1086 }
1087
1088 public final int accessTextStart() {
1089 return _charactersOffset;
1090 }
1091
1092 public final int accessTextLength() {
1093 return _charBufferLength;
1094 }
1095
1096 //
1097
1098 protected final void processDII() throws FastInfosetException, IOException {
1099 final int b = read();
1100 if (b > 0) {
1101 processDIIOptionalProperties(b);
1102 }
1103 }
1104
1105 protected final void processDIIOptionalProperties(int b) throws FastInfosetException, IOException {
1106 // Optimize for the most common case
1107 if (b == EncodingConstants.DOCUMENT_INITIAL_VOCABULARY_FLAG) {
1108 decodeInitialVocabulary();
1109 return;
1110 }
1111
1112 if ((b & EncodingConstants.DOCUMENT_ADDITIONAL_DATA_FLAG) > 0) {
1113 decodeAdditionalData();
1114 /*
1115 * TODO
1116 * how to report the additional data?
1117 */
1118 }
1119
1120 if ((b & EncodingConstants.DOCUMENT_INITIAL_VOCABULARY_FLAG) > 0) {
1121 decodeInitialVocabulary();
1122 }
1123
1124 if ((b & EncodingConstants.DOCUMENT_NOTATIONS_FLAG) > 0) {
1125 decodeNotations();
1126 /*
1127 try {
1128 _dtdHandler.notationDecl(name, public_identifier, system_identifier);
1129 } catch (SAXException e) {
1130 throw new IOException("NotationsDeclarationII");
1131 }
1132 */
1133 }
1134
1135 if ((b & EncodingConstants.DOCUMENT_UNPARSED_ENTITIES_FLAG) > 0) {
1136 decodeUnparsedEntities();
1137 /*
1138 try {
1139 _dtdHandler.unparsedEntityDecl(name, public_identifier, system_identifier, notation_name);
1140 } catch (SAXException e) {
1141 throw new IOException("UnparsedEntitiesII");
1142 }
1143 */
1144 }
1145
1146 if ((b & EncodingConstants.DOCUMENT_CHARACTER_ENCODING_SCHEME) > 0) {
1147 _characterEncodingScheme = decodeCharacterEncodingScheme();
1148 }
1149
1150 if ((b & EncodingConstants.DOCUMENT_STANDALONE_FLAG) > 0) {
1151 boolean standalone = (read() > 0) ? true : false ;
1152 /*
1153 * TODO
1154 * how to report the standalone flag?
1155 */
1156 }
1157
1158 if ((b & EncodingConstants.DOCUMENT_VERSION_FLAG) > 0) {
1159 decodeVersion();
1160 /*
1161 * TODO
1162 * how to report the standalone flag?
1163 */
1164 }
1165 }
1166
1167
1168 protected final void resizeNamespaceAIIs() {
1169 final String[] namespaceAIIsPrefix = new String[_namespaceAIIsIndex * 2];
1170 System.arraycopy(_namespaceAIIsPrefix, 0, namespaceAIIsPrefix, 0, _namespaceAIIsIndex);
1171 _namespaceAIIsPrefix = namespaceAIIsPrefix;
1172
1173 final String[] namespaceAIIsNamespaceName = new String[_namespaceAIIsIndex * 2];
1174 System.arraycopy(_namespaceAIIsNamespaceName, 0, namespaceAIIsNamespaceName, 0, _namespaceAIIsIndex);
1175 _namespaceAIIsNamespaceName = namespaceAIIsNamespaceName;
1176
1177 final int[] namespaceAIIsPrefixIndex = new int[_namespaceAIIsIndex * 2];
1178 System.arraycopy(_namespaceAIIsPrefixIndex, 0, namespaceAIIsPrefixIndex, 0, _namespaceAIIsIndex);
1179 _namespaceAIIsPrefixIndex = namespaceAIIsPrefixIndex;
1180 }
1181
1182 protected final void processEIIWithNamespaces(boolean hasAttributes) throws FastInfosetException, IOException {
1183 if (++_prefixTable._declarationId == Integer.MAX_VALUE) {
1184 _prefixTable.clearDeclarationIds();
1185 }
1186
1187 _currentNamespaceAIIsStart = _namespaceAIIsIndex;
1188 String prefix = "", namespaceName = "";
1189 int b = read();
1190 while ((b & EncodingConstants.NAMESPACE_ATTRIBUTE_MASK) == EncodingConstants.NAMESPACE_ATTRIBUTE) {
1191 if (_namespaceAIIsIndex == _namespaceAIIsPrefix.length) {
1192 resizeNamespaceAIIs();
1193 }
1194
1195 switch (b & EncodingConstants.NAMESPACE_ATTRIBUTE_PREFIX_NAME_MASK) {
1196 // no prefix, no namespace
1197 // Undeclaration of default namespace
1198 case 0:
1199 prefix = namespaceName =
1200 _namespaceAIIsPrefix[_namespaceAIIsIndex] =
1201 _namespaceAIIsNamespaceName[_namespaceAIIsIndex] = "";
1202
1203 _namespaceNameIndex = _prefixIndex = _namespaceAIIsPrefixIndex[_namespaceAIIsIndex++] = -1;
1204 break;
1205 // no prefix, namespace
1206 // Declaration of default namespace
1207 case 1:
1208 prefix = _namespaceAIIsPrefix[_namespaceAIIsIndex] = "";
1209 namespaceName = _namespaceAIIsNamespaceName[_namespaceAIIsIndex] =
1210 decodeIdentifyingNonEmptyStringOnFirstBitAsNamespaceName(false);
1211
1212 _prefixIndex = _namespaceAIIsPrefixIndex[_namespaceAIIsIndex++] = -1;
1213 break;
1214 // prefix, no namespace
1215 // Undeclaration of namespace
1216 case 2:
1217 prefix = _namespaceAIIsPrefix[_namespaceAIIsIndex] =
1218 decodeIdentifyingNonEmptyStringOnFirstBitAsPrefix(false);
1219 namespaceName = _namespaceAIIsNamespaceName[_namespaceAIIsIndex] = "";
1220
1221 _namespaceNameIndex = -1;
1222 _namespaceAIIsPrefixIndex[_namespaceAIIsIndex++] = _prefixIndex;
1223 break;
1224 // prefix, namespace
1225 // Declaration of prefixed namespace
1226 case 3:
1227 prefix = _namespaceAIIsPrefix[_namespaceAIIsIndex] =
1228 decodeIdentifyingNonEmptyStringOnFirstBitAsPrefix(true);
1229 namespaceName = _namespaceAIIsNamespaceName[_namespaceAIIsIndex] =
1230 decodeIdentifyingNonEmptyStringOnFirstBitAsNamespaceName(true);
1231
1232 _namespaceAIIsPrefixIndex[_namespaceAIIsIndex++] = _prefixIndex;
1233 break;
1234 }
1235
1236 // Push namespace declarations onto the stack
1237 _prefixTable.pushScopeWithPrefixEntry(prefix, namespaceName, _prefixIndex, _namespaceNameIndex);
1238
1239 b = read();
1240 }
1241 if (b != EncodingConstants.TERMINATOR) {
1242 throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.EIInamespaceNameNotTerminatedCorrectly"));
1243 }
1244 _currentNamespaceAIIsEnd = _namespaceAIIsIndex;
1245
1246 b = read();
1247 switch(DecoderStateTables.EII(b)) {
1248 case DecoderStateTables.EII_NO_AIIS_INDEX_SMALL:
1249 processEII(_elementNameTable._array[b], hasAttributes);
1250 break;
1251 case DecoderStateTables.EII_INDEX_MEDIUM:
1252 processEII(processEIIIndexMedium(b), hasAttributes);
1253 break;
1254 case DecoderStateTables.EII_INDEX_LARGE:
1255 processEII(processEIIIndexLarge(b), hasAttributes);
1256 break;
1257 case DecoderStateTables.EII_LITERAL:
1258 {
1259 final QualifiedName qn = processLiteralQualifiedName(
1260 b & EncodingConstants.LITERAL_QNAME_PREFIX_NAMESPACE_NAME_MASK,
1261 _elementNameTable.getNext());
1262 _elementNameTable.add(qn);
1263 processEII(qn, hasAttributes);
1264 break;
1265 }
1266 default:
1267 throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.IllegalStateDecodingEIIAfterAIIs"));
1268 }
1269 }
1270
1271 protected final void processEII(QualifiedName name, boolean hasAttributes) throws FastInfosetException, IOException {
1272 if (_prefixTable._currentInScope[name.prefixIndex] != name.namespaceNameIndex) {
1273 throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.qnameOfEIINotInScope"));
1274 }
1275
1276 _eventType = START_ELEMENT;
1277 _qualifiedName = name;
1278
1279 if (_clearAttributes) {
1280 _attributes.clear();
1281 _clearAttributes = false;
1282 }
1283
1284 if (hasAttributes) {
1285 processAIIs();
1286 }
1287
1288 // Push element holder onto the stack
1289 _stackCount++;
1290 if (_stackCount == _qNameStack.length) {
1291 QualifiedName[] qNameStack = new QualifiedName[_qNameStack.length * 2];
1292 System.arraycopy(_qNameStack, 0, qNameStack, 0, _qNameStack.length);
1293 _qNameStack = qNameStack;
1294
1295 int[] namespaceAIIsStartStack = new int[_namespaceAIIsStartStack.length * 2];
1296 System.arraycopy(_namespaceAIIsStartStack, 0, namespaceAIIsStartStack, 0, _namespaceAIIsStartStack.length);
1297 _namespaceAIIsStartStack = namespaceAIIsStartStack;
1298
1299 int[] namespaceAIIsEndStack = new int[_namespaceAIIsEndStack.length * 2];
1300 System.arraycopy(_namespaceAIIsEndStack, 0, namespaceAIIsEndStack, 0, _namespaceAIIsEndStack.length);
1301 _namespaceAIIsEndStack = namespaceAIIsEndStack;
1302 }
1303 _qNameStack[_stackCount] = _qualifiedName;
1304 _namespaceAIIsStartStack[_stackCount] = _currentNamespaceAIIsStart;
1305 _namespaceAIIsEndStack[_stackCount] = _currentNamespaceAIIsEnd;
1306 }
1307
1308 protected final void processAIIs() throws FastInfosetException, IOException {
1309 QualifiedName name;
1310 int b;
1311 String value;
1312
1313 if (++_duplicateAttributeVerifier._currentIteration == Integer.MAX_VALUE) {
1314 _duplicateAttributeVerifier.clear();
1315 }
1316
1317 _clearAttributes = true;
1318 boolean terminate = false;
1319 do {
1320 // AII qualified name
1321 b = read();
1322 switch (DecoderStateTables.AII(b)) {
1323 case DecoderStateTables.AII_INDEX_SMALL:
1324 name = _attributeNameTable._array[b];
1325 break;
1326 case DecoderStateTables.AII_INDEX_MEDIUM:
1327 {
1328 final int i = (((b & EncodingConstants.INTEGER_2ND_BIT_MEDIUM_MASK) << 8) | read())
1329 + EncodingConstants.INTEGER_2ND_BIT_SMALL_LIMIT;
1330 name = _attributeNameTable._array[i];
1331 break;
1332 }
1333 case DecoderStateTables.AII_INDEX_LARGE:
1334 {
1335 final int i = (((b & EncodingConstants.INTEGER_2ND_BIT_LARGE_MASK) << 16) | (read() << 8) | read())
1336 + EncodingConstants.INTEGER_2ND_BIT_MEDIUM_LIMIT;
1337 name = _attributeNameTable._array[i];
1338 break;
1339 }
1340 case DecoderStateTables.AII_LITERAL:
1341 name = processLiteralQualifiedName(
1342 b & EncodingConstants.LITERAL_QNAME_PREFIX_NAMESPACE_NAME_MASK,
1343 _attributeNameTable.getNext());
1344 name.createAttributeValues(DuplicateAttributeVerifier.MAP_SIZE);
1345 _attributeNameTable.add(name);
1346 break;
1347 case DecoderStateTables.AII_TERMINATOR_DOUBLE:
1348 _internalState = INTERNAL_STATE_START_ELEMENT_TERMINATE;
1349 case DecoderStateTables.AII_TERMINATOR_SINGLE:
1350 terminate = true;
1351 // AIIs have finished break out of loop
1352 continue;
1353 default:
1354 throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.decodingAIIs"));
1355 }
1356
1357 // [normalized value] of AII
1358
1359 if (name.prefixIndex > 0 && _prefixTable._currentInScope[name.prefixIndex] != name.namespaceNameIndex) {
1360 throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.AIIqNameNotInScope"));
1361 }
1362
1363 _duplicateAttributeVerifier.checkForDuplicateAttribute(name.attributeHash, name.attributeId);
1364
1365 b = read();
1366 switch(DecoderStateTables.NISTRING(b)) {
1367 case DecoderStateTables.NISTRING_UTF8_SMALL_LENGTH:
1368 _octetBufferLength = (b & EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_SMALL_MASK) + 1;
1369 value = decodeUtf8StringAsString();
1370 if ((b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0) {
1371 _attributeValueTable.add(value);
1372 }
1373
1374 _attributes.addAttribute(name, value);
1375 break;
1376 case DecoderStateTables.NISTRING_UTF8_MEDIUM_LENGTH:
1377 _octetBufferLength = read() + EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_SMALL_LIMIT;
1378 value = decodeUtf8StringAsString();
1379 if ((b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0) {
1380 _attributeValueTable.add(value);
1381 }
1382
1383 _attributes.addAttribute(name, value);
1384 break;
1385 case DecoderStateTables.NISTRING_UTF8_LARGE_LENGTH:
1386 _octetBufferLength = ((read() << 24) |
1387 (read() << 16) |
1388 (read() << 8) |
1389 read())
1390 + EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_MEDIUM_LIMIT;
1391 value = decodeUtf8StringAsString();
1392 if ((b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0) {
1393 _attributeValueTable.add(value);
1394 }
1395
1396 _attributes.addAttribute(name, value);
1397 break;
1398 case DecoderStateTables.NISTRING_UTF16_SMALL_LENGTH:
1399 _octetBufferLength = (b & EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_SMALL_MASK) + 1;
1400 value = decodeUtf16StringAsString();
1401 if ((b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0) {
1402 _attributeValueTable.add(value);
1403 }
1404
1405 _attributes.addAttribute(name, value);
1406 break;
1407 case DecoderStateTables.NISTRING_UTF16_MEDIUM_LENGTH:
1408 _octetBufferLength = read() + EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_SMALL_LIMIT;
1409 value = decodeUtf16StringAsString();
1410 if ((b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0) {
1411 _attributeValueTable.add(value);
1412 }
1413
1414 _attributes.addAttribute(name, value);
1415 break;
1416 case DecoderStateTables.NISTRING_UTF16_LARGE_LENGTH:
1417 _octetBufferLength = ((read() << 24) |
1418 (read() << 16) |
1419 (read() << 8) |
1420 read())
1421 + EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_MEDIUM_LIMIT;
1422 value = decodeUtf16StringAsString();
1423 if ((b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0) {
1424 _attributeValueTable.add(value);
1425 }
1426
1427 _attributes.addAttribute(name, value);
1428 break;
1429 case DecoderStateTables.NISTRING_RA:
1430 {
1431 final boolean addToTable = (b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0;
1432 // Decode resitricted alphabet integer
1433 _identifier = (b & 0x0F) << 4;
1434 b = read();
1435 _identifier |= (b & 0xF0) >> 4;
1436
1437 decodeOctetsOnFifthBitOfNonIdentifyingStringOnFirstBit(b);
1438
1439 value = decodeRestrictedAlphabetAsString();
1440 if (addToTable) {
1441 _attributeValueTable.add(value);
1442 }
1443
1444 _attributes.addAttribute(name, value);
1445 break;
1446 }
1447 case DecoderStateTables.NISTRING_EA:
1448 {
1449 final boolean addToTable = (b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0;
1450 // Decode encoding algorithm integer
1451 _identifier = (b & 0x0F) << 4;
1452 b = read();
1453 _identifier |= (b & 0xF0) >> 4;
1454
1455 decodeOctetsOnFifthBitOfNonIdentifyingStringOnFirstBit(b);
1456 processAIIEncodingAlgorithm(name, addToTable);
1457 break;
1458 }
1459 case DecoderStateTables.NISTRING_INDEX_SMALL:
1460 _attributes.addAttribute(name,
1461 _attributeValueTable._array[b & EncodingConstants.INTEGER_2ND_BIT_SMALL_MASK]);
1462 break;
1463 case DecoderStateTables.NISTRING_INDEX_MEDIUM:
1464 {
1465 final int index = (((b & EncodingConstants.INTEGER_2ND_BIT_MEDIUM_MASK) << 8) | read())
1466 + EncodingConstants.INTEGER_2ND_BIT_SMALL_LIMIT;
1467
1468 _attributes.addAttribute(name,
1469 _attributeValueTable._array[index]);
1470 break;
1471 }
1472 case DecoderStateTables.NISTRING_INDEX_LARGE:
1473 {
1474 final int index = (((b & EncodingConstants.INTEGER_2ND_BIT_LARGE_MASK) << 16) | (read() << 8) | read())
1475 + EncodingConstants.INTEGER_2ND_BIT_MEDIUM_LIMIT;
1476
1477 _attributes.addAttribute(name,
1478 _attributeValueTable._array[index]);
1479 break;
1480 }
1481 case DecoderStateTables.NISTRING_EMPTY:
1482 _attributes.addAttribute(name, "");
1483 break;
1484 default:
1485 throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.decodingAIIValue"));
1486 }
1487
1488 } while (!terminate);
1489
1490 // Reset duplication attribute verfifier
1491 _duplicateAttributeVerifier._poolCurrent = _duplicateAttributeVerifier._poolHead;
1492 }
1493
1494 protected final QualifiedName processEIIIndexMedium(int b) throws FastInfosetException, IOException {
1495 final int i = (((b & EncodingConstants.INTEGER_3RD_BIT_MEDIUM_MASK) << 8) | read())
1496 + EncodingConstants.INTEGER_3RD_BIT_SMALL_LIMIT;
1497 return _elementNameTable._array[i];
1498 }
1499
1500 protected final QualifiedName processEIIIndexLarge(int b) throws FastInfosetException, IOException {
1501 int i;
1502 if ((b & EncodingConstants.INTEGER_3RD_BIT_LARGE_LARGE_FLAG) == 0x20) {
1503 // EII large index
1504 i = (((b & EncodingConstants.INTEGER_3RD_BIT_LARGE_MASK) << 16) | (read() << 8) | read())
1505 + EncodingConstants.INTEGER_3RD_BIT_MEDIUM_LIMIT;
1506 } else {
1507 // EII large large index
1508 i = (((read() & EncodingConstants.INTEGER_3RD_BIT_LARGE_LARGE_MASK) << 16) | (read() << 8) | read())
1509 + EncodingConstants.INTEGER_3RD_BIT_LARGE_LIMIT;
1510 }
1511 return _elementNameTable._array[i];
1512 }
1513
1514 protected final QualifiedName processLiteralQualifiedName(int state, QualifiedName q)
1515 throws FastInfosetException, IOException {
1516 if (q == null) q = new QualifiedName();
1517
1518 switch (state) {
1519 // no prefix, no namespace
1520 case 0:
1521 return q.set(
1522 "",
1523 "",
1524 decodeIdentifyingNonEmptyStringOnFirstBit(_v.localName),
1525 "",
1526 0,
1527 -1,
1528 -1,
1529 _identifier);
1530 // no prefix, namespace
1531 case 1:
1532 return q.set(
1533 "",
1534 decodeIdentifyingNonEmptyStringIndexOnFirstBitAsNamespaceName(false),
1535 decodeIdentifyingNonEmptyStringOnFirstBit(_v.localName),
1536 "",
1537 0,
1538 -1,
1539 _namespaceNameIndex,
1540 _identifier);
1541 // prefix, no namespace
1542 case 2:
1543 throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.qNameMissingNamespaceName"));
1544 // prefix, namespace
1545 case 3:
1546 return q.set(
1547 decodeIdentifyingNonEmptyStringIndexOnFirstBitAsPrefix(true),
1548 decodeIdentifyingNonEmptyStringIndexOnFirstBitAsNamespaceName(true),
1549 decodeIdentifyingNonEmptyStringOnFirstBit(_v.localName),
1550 "",
1551 0,
1552 _prefixIndex,
1553 _namespaceNameIndex,
1554 _identifier);
1555 default:
1556 throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.decodingEII"));
1557 }
1558 }
1559
1560 protected final void processCommentII() throws FastInfosetException, IOException {
1561 _eventType = COMMENT;
1562
1563 switch(decodeNonIdentifyingStringOnFirstBit()) {
1564 case NISTRING_STRING:
1565 if (_addToTable) {
1566 _v.otherString.add(new CharArray(_charBuffer, 0, _charBufferLength, true));
1567 }
1568
1569 _characters = _charBuffer;
1570 _charactersOffset = 0;
1571 break;
1572 case NISTRING_ENCODING_ALGORITHM:
1573 throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.commentIIAlgorithmNotSupported"));
1574 case NISTRING_INDEX:
1575 final CharArray ca = _v.otherString.get(_integer);
1576
1577 _characters = ca.ch;
1578 _charactersOffset = ca.start;
1579 _charBufferLength = ca.length;
1580 break;
1581 case NISTRING_EMPTY_STRING:
1582 _characters = _charBuffer;
1583 _charactersOffset = 0;
1584 _charBufferLength = 0;
1585 break;
1586 }
1587 }
1588
1589 protected final void processProcessingII() throws FastInfosetException, IOException {
1590 _eventType = PROCESSING_INSTRUCTION;
1591
1592 _piTarget = decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherNCName);
1593
1594 switch(decodeNonIdentifyingStringOnFirstBit()) {
1595 case NISTRING_STRING:
1596 _piData = new String(_charBuffer, 0, _charBufferLength);
1597 if (_addToTable) {
1598 _v.otherString.add(new CharArrayString(_piData));
1599 }
1600 break;
1601 case NISTRING_ENCODING_ALGORITHM:
1602 throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.processingIIWithEncodingAlgorithm"));
1603 case NISTRING_INDEX:
1604 _piData = _v.otherString.get(_integer).toString();
1605 break;
1606 case NISTRING_EMPTY_STRING:
1607 _piData = "";
1608 break;
1609 }
1610 }
1611
1612 protected final void processUnexpandedEntityReference(final int b) throws FastInfosetException, IOException {
1613 _eventType = ENTITY_REFERENCE;
1614
1615 /*
1616 * TODO
1617 * How does StAX report such events?
1618 */
1619 String entity_reference_name = decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherNCName);
1620
1621 String system_identifier = ((b & EncodingConstants.UNEXPANDED_ENTITY_SYSTEM_IDENTIFIER_FLAG) > 0)
1622 ? decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherURI) : "";
1623 String public_identifier = ((b & EncodingConstants.UNEXPANDED_ENTITY_PUBLIC_IDENTIFIER_FLAG) > 0)
1624 ? decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherURI) : "";
1625
1626 if (logger.isLoggable(Level.FINEST)) {
1627 logger.log(Level.FINEST, "processUnexpandedEntityReference: entity_reference_name={0} system_identifier={1}public_identifier={2}",
1628 new Object[]{entity_reference_name, system_identifier, public_identifier});
1629 }
1630 }
1631
1632 protected final void processCIIEncodingAlgorithm(boolean addToTable) throws FastInfosetException, IOException {
1633 _algorithmData = _octetBuffer;
1634 _algorithmDataOffset = _octetBufferStart;
1635 _algorithmDataLength = _octetBufferLength;
1636 _isAlgorithmDataCloned = false;
1637
1638 if (_algorithmId >= EncodingConstants.ENCODING_ALGORITHM_APPLICATION_START) {
1639 _algorithmURI = _v.encodingAlgorithm.get(_algorithmId - EncodingConstants.ENCODING_ALGORITHM_APPLICATION_START);
1640 if (_algorithmURI == null) {
1641 throw new EncodingAlgorithmException(CommonResourceBundle.getInstance().getString("message.URINotPresent", new Object[]{Integer.valueOf(_identifier)}));
1642 }
1643 } else if (_algorithmId > EncodingConstants.ENCODING_ALGORITHM_BUILTIN_END) {
1644 // Reserved built-in algorithms for future use
1645 // TODO should use sax property to decide if event will be
1646 // reported, allows for support through handler if required.
1647 throw new EncodingAlgorithmException(CommonResourceBundle.getInstance().getString("message.identifiers10to31Reserved"));
1648 }
1649
1650 if (addToTable) {
1651 convertEncodingAlgorithmDataToCharacters();
1652 _characterContentChunkTable.add(_characters, _characters.length);
1653 }
1654 }
1655
1656 protected final void processAIIEncodingAlgorithm(QualifiedName name, boolean addToTable) throws FastInfosetException, IOException {
1657 EncodingAlgorithm ea = null;
1658 String URI = null;
1659 if (_identifier >= EncodingConstants.ENCODING_ALGORITHM_APPLICATION_START) {
1660 URI = _v.encodingAlgorithm.get(_identifier - EncodingConstants.ENCODING_ALGORITHM_APPLICATION_START);
1661 if (URI == null) {
1662 throw new EncodingAlgorithmException(CommonResourceBundle.getInstance().getString("message.URINotPresent", new Object[]{Integer.valueOf(_identifier)}));
1663 } else if (_registeredEncodingAlgorithms != null) {
1664 ea = (EncodingAlgorithm)_registeredEncodingAlgorithms.get(URI);
1665 }
1666 } else if (_identifier >= EncodingConstants.ENCODING_ALGORITHM_BUILTIN_END) {
1667 if (_identifier == EncodingAlgorithmIndexes.CDATA) {
1668 throw new EncodingAlgorithmException(CommonResourceBundle.getInstance().getString("message.CDATAAlgorithmNotSupported"));
1669 }
1670
1671 // Reserved built-in algorithms for future use
1672 // TODO should use sax property to decide if event will be
1673 // reported, allows for support through handler if required.
1674 throw new EncodingAlgorithmException(CommonResourceBundle.getInstance().getString("message.identifiers10to31Reserved"));
1675 } else {
1676 ea = BuiltInEncodingAlgorithmFactory.getAlgorithm(_identifier);
1677 }
1678
1679 Object algorithmData;
1680
1681 if (ea != null) {
1682 algorithmData = ea.decodeFromBytes(_octetBuffer, _octetBufferStart,
1683 _octetBufferLength);
1684 } else {
1685 final byte[] data = new byte[_octetBufferLength];
1686 System.arraycopy(_octetBuffer, _octetBufferStart, data, 0,
1687 _octetBufferLength);
1688 algorithmData = data;
1689 }
1690
1691 _attributes.addAttributeWithAlgorithmData(name, URI, _identifier,
1692 algorithmData);
1693 if (addToTable) {
1694 _attributeValueTable.add(_attributes.getValue(_attributes.getIndex(name.qName)));
1695 }
1696 }
1697
1698 protected final void convertEncodingAlgorithmDataToCharacters() throws FastInfosetException, IOException {
1699 StringBuffer buffer = new StringBuffer();
1700 if (_algorithmId == EncodingAlgorithmIndexes.BASE64) {
1701 convertBase64AlorithmDataToCharacters(buffer);
1702 } else if (_algorithmId < EncodingConstants.ENCODING_ALGORITHM_BUILTIN_END) {
1703 Object array = BuiltInEncodingAlgorithmFactory.getAlgorithm(_algorithmId).
1704 decodeFromBytes(_algorithmData, _algorithmDataOffset, _algorithmDataLength);
1705 BuiltInEncodingAlgorithmFactory.getAlgorithm(_algorithmId).convertToCharacters(array, buffer);
1706 } else if (_algorithmId == EncodingAlgorithmIndexes.CDATA) {
1707 _octetBufferOffset -= _octetBufferLength;
1708 decodeUtf8StringIntoCharBuffer();
1709
1710 _characters = _charBuffer;
1711 _charactersOffset = 0;
1712 return;
1713 } else if (_algorithmId >= EncodingConstants.ENCODING_ALGORITHM_APPLICATION_START) {
1714 final EncodingAlgorithm ea = (EncodingAlgorithm)_registeredEncodingAlgorithms.get(_algorithmURI);
1715 if (ea != null) {
1716 final Object data = ea.decodeFromBytes(_octetBuffer, _octetBufferStart, _octetBufferLength);
1717 ea.convertToCharacters(data, buffer);
1718 } else {
1719 throw new EncodingAlgorithmException(
1720 CommonResourceBundle.getInstance().getString("message.algorithmDataCannotBeReported"));
1721 }
1722 }
1723
1724 _characters = new char[buffer.length()];
1725 buffer.getChars(0, buffer.length(), _characters, 0);
1726 _charactersOffset = 0;
1727 _charBufferLength = _characters.length;
1728 }
1729
1730 /* If base64 data comes is chunks, bytes, which were cut to align 3,
1731 * from prev. base64 chunk are stored in this buffer */
1732 private byte[] base64TaleBytes = new byte[3];
1733 private int base64TaleLength;
1734 /*
1735 * Method converts _algorithmData to base64 encoded String
1736 * Counts with base64 data coming in chunks, aligning input chunks by 3,
1737 * avoiding double cloning, happening after possible peek, peek2 cloning by Base64 algorithm
1738 */
1739 protected void convertBase64AlorithmDataToCharacters(StringBuffer buffer) throws EncodingAlgorithmException, IOException {
1740 // How much new came data was serialized with prev. tale
1741 int afterTaleOffset = 0;
1742
1743 if (base64TaleLength > 0) {
1744 // Serialize tale left from prev. chunk
1745 int bytesToCopy = Math.min(3 - base64TaleLength, _algorithmDataLength);
1746 System.arraycopy(_algorithmData, _algorithmDataOffset, base64TaleBytes, base64TaleLength, bytesToCopy);
1747 if (base64TaleLength + bytesToCopy == 3) {
1748 base64DecodeWithCloning(buffer, base64TaleBytes, 0, 3);
1749 } else if (!isBase64Follows()) {
1750 // End of text was read to temp array
1751 base64DecodeWithCloning(buffer, base64TaleBytes, 0, base64TaleLength + bytesToCopy);
1752 return;
1753 } else {
1754 // If the end of chunk fit to tmp array, but next chunk is expected
1755 base64TaleLength += bytesToCopy;
1756 return;
1757 }
1758
1759 afterTaleOffset = bytesToCopy;
1760 base64TaleLength = 0;
1761 }
1762
1763 int taleBytesRemaining = isBase64Follows() ? (_algorithmDataLength - afterTaleOffset) % 3 : 0;
1764
1765 if (_isAlgorithmDataCloned) {
1766 base64DecodeWithoutCloning(buffer, _algorithmData, _algorithmDataOffset + afterTaleOffset,
1767 _algorithmDataLength - afterTaleOffset - taleBytesRemaining);
1768 } else {
1769 base64DecodeWithCloning(buffer, _algorithmData, _algorithmDataOffset + afterTaleOffset,
1770 _algorithmDataLength - afterTaleOffset - taleBytesRemaining);
1771 }
1772
1773 if (taleBytesRemaining > 0) {
1774 System.arraycopy(_algorithmData, _algorithmDataOffset + _algorithmDataLength - taleBytesRemaining,
1775 base64TaleBytes, 0, taleBytesRemaining);
1776 base64TaleLength = taleBytesRemaining;
1777 }
1778 }
1779
1780 /*
1781 * Encodes incoming data to Base64 string.
1782 * Method performs additional input data cloning
1783 */
1784 private void base64DecodeWithCloning(StringBuffer dstBuffer, byte[] data, int offset, int length) throws EncodingAlgorithmException {
1785 Object array = BuiltInEncodingAlgorithmFactory.base64EncodingAlgorithm.
1786 decodeFromBytes(data, offset, length);
1787 BuiltInEncodingAlgorithmFactory.base64EncodingAlgorithm.convertToCharacters(array, dstBuffer);
1788 }
1789
1790 /*
1791 * Encodes incoming data to Base64 string.
1792 * Avoids input data cloning
1793 */
1794 private void base64DecodeWithoutCloning(StringBuffer dstBuffer, byte[] data, int offset, int length) throws EncodingAlgorithmException {
1795 BuiltInEncodingAlgorithmFactory.base64EncodingAlgorithm.convertToCharacters(data, offset, length, dstBuffer);
1796 }
1797
1798
1799 /*
1800 * Looks ahead in InputStream, whether next data is Base64 chunk
1801 */
1802 public boolean isBase64Follows() throws IOException {
1803 // Process information item
1804 int b = peek(this);
1805 switch (DecoderStateTables.EII(b)) {
1806 case DecoderStateTables.CII_EA:
1807 int algorithmId = (b & 0x02) << 6;
1808 int b2 = peek2(this);
1809 algorithmId |= (b2 & 0xFC) >> 2;
1810
1811 return algorithmId == EncodingAlgorithmIndexes.BASE64;
1812 default:
1813 return false;
1814 }
1815 }
1816
1817 protected class NamespaceContextImpl implements NamespaceContext {
1818 public final String getNamespaceURI(String prefix) {
1819 return _prefixTable.getNamespaceFromPrefix(prefix);
1820 }
1821
1822 public final String getPrefix(String namespaceURI) {
1823 return _prefixTable.getPrefixFromNamespace(namespaceURI);
1824 }
1825
1826 public final Iterator getPrefixes(String namespaceURI) {
1827 return _prefixTable.getPrefixesFromNamespace(namespaceURI);
1828 }
1829 }
1830
1831 public final String getNamespaceDecl(String prefix) {
1832 return _prefixTable.getNamespaceFromPrefix(prefix);
1833 }
1834
1835 public final String getURI(String prefix) {
1836 return getNamespaceDecl(prefix);
1837 }
1838
1839 public final Iterator getPrefixes() {
1840 return _prefixTable.getPrefixes();
1841 }
1842
1843 public final AttributesHolder getAttributesHolder() {
1844 return _attributes;
1845 }
1846
1847 public final void setManager(StAXManager manager) {
1848 _manager = manager;
1849 }
1850
1851 final static String getEventTypeString(int eventType) {
1852 switch (eventType){
1853 case START_ELEMENT:
1854 return "START_ELEMENT";
1855 case END_ELEMENT:
1856 return "END_ELEMENT";
1857 case PROCESSING_INSTRUCTION:
1858 return "PROCESSING_INSTRUCTION";
1859 case CHARACTERS:
1860 return "CHARACTERS";
1861 case COMMENT:
1862 return "COMMENT";
1863 case START_DOCUMENT:
1864 return "START_DOCUMENT";
1865 case END_DOCUMENT:
1866 return "END_DOCUMENT";
1867 case ENTITY_REFERENCE:
1868 return "ENTITY_REFERENCE";
1869 case ATTRIBUTE:
1870 return "ATTRIBUTE";
1871 case DTD:
1872 return "DTD";
1873 case CDATA:
1874 return "CDATA";
1875 }
1876 return "UNKNOWN_EVENT_TYPE";
1877 }
1878 }

mercurial