0001: /*
0002: * Fast Infoset ver. 0.1 software ("Software")
0003: *
0004: * Copyright, 2004-2005 Sun Microsystems, Inc. All Rights Reserved.
0005: *
0006: * Software is licensed under the Apache License, Version 2.0 (the "License");
0007: * you may not use this file except in compliance with the License. You may
0008: * obtain a copy of the License at:
0009: *
0010: * http://www.apache.org/licenses/LICENSE-2.0
0011: *
0012: * Unless required by applicable law or agreed to in writing, software
0013: * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
0014: * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
0015: * License for the specific language governing permissions and limitations.
0016: *
0017: * Sun supports and benefits from the global community of open source
0018: * developers, and thanks the community for its important contributions and
0019: * open standards-based technology, which Sun has adopted into many of its
0020: * products.
0021: *
0022: * Please note that portions of Software may be provided with notices and
0023: * open source licenses from such communities and third parties that govern the
0024: * use of those portions, and any licenses granted hereunder do not alter any
0025: * rights and obligations you may have under such open source licenses,
0026: * however, the disclaimer of warranty and limitation of liability provisions
0027: * in this License will apply to all Software in this distribution.
0028: *
0029: * You acknowledge that the Software is not designed, licensed or intended
0030: * for use in the design, construction, operation or maintenance of any nuclear
0031: * facility.
0032: *
0033: * Apache License
0034: * Version 2.0, January 2004
0035: * http://www.apache.org/licenses/
0036: *
0037: */
0038:
0039: package com.sun.xml.fastinfoset.stax;
0040:
0041: import com.sun.xml.fastinfoset.Decoder;
0042: import com.sun.xml.fastinfoset.DecoderStateTables;
0043: import com.sun.xml.fastinfoset.EncodingConstants;
0044: import com.sun.xml.fastinfoset.OctetBufferListener;
0045: import com.sun.xml.fastinfoset.QualifiedName;
0046: import com.sun.xml.fastinfoset.algorithm.BuiltInEncodingAlgorithmFactory;
0047: import com.sun.xml.fastinfoset.sax.AttributesHolder;
0048: import com.sun.xml.fastinfoset.util.CharArray;
0049: import com.sun.xml.fastinfoset.util.CharArrayString;
0050: import java.io.IOException;
0051: import java.io.InputStream;
0052: import java.util.Iterator;
0053: import java.util.NoSuchElementException;
0054: import javax.xml.namespace.NamespaceContext;
0055: import javax.xml.namespace.QName;
0056: import javax.xml.stream.Location;
0057: import javax.xml.stream.XMLStreamException;
0058: import javax.xml.stream.XMLStreamReader;
0059: import org.jvnet.fastinfoset.EncodingAlgorithm;
0060: import org.jvnet.fastinfoset.EncodingAlgorithmException;
0061: import org.jvnet.fastinfoset.EncodingAlgorithmIndexes;
0062: import org.jvnet.fastinfoset.FastInfosetException;
0063: import com.sun.xml.fastinfoset.CommonResourceBundle;
0064: import com.sun.xml.fastinfoset.org.apache.xerces.util.XMLChar;
0065: import org.jvnet.fastinfoset.stax.FastInfosetStreamReader;
0066:
0067: /**
0068: * The Fast Infoset StAX parser.
0069: * <p>
0070: * Instantiate this parser to parse a fast infoset document in accordance
0071: * with the StAX API.
0072: *
0073: * <p>
0074: * More than one fast infoset document may be decoded from the
0075: * {@link java.io.InputStream}.
0076: */
0077: public class StAXDocumentParser extends Decoder implements
0078: XMLStreamReader, FastInfosetStreamReader, OctetBufferListener {
0079: protected static final int INTERNAL_STATE_START_DOCUMENT = 0;
0080: protected static final int INTERNAL_STATE_START_ELEMENT_TERMINATE = 1;
0081: protected static final int INTERNAL_STATE_SINGLE_TERMINATE_ELEMENT_WITH_NAMESPACES = 2;
0082: protected static final int INTERNAL_STATE_DOUBLE_TERMINATE_ELEMENT = 3;
0083: protected static final int INTERNAL_STATE_END_DOCUMENT = 4;
0084: protected static final int INTERNAL_STATE_VOID = -1;
0085:
0086: protected int _internalState;
0087:
0088: /**
0089: * Current event
0090: */
0091: protected int _eventType;
0092:
0093: /**
0094: * Stack of qualified names and namespaces
0095: */
0096: protected QualifiedName[] _qNameStack = new QualifiedName[32];
0097: protected int[] _namespaceAIIsStartStack = new int[32];
0098: protected int[] _namespaceAIIsEndStack = new int[32];
0099: protected int _stackCount = -1;
0100:
0101: protected String[] _namespaceAIIsPrefix = new String[32];
0102: protected String[] _namespaceAIIsNamespaceName = new String[32];
0103: protected int[] _namespaceAIIsPrefixIndex = new int[32];
0104: protected int _namespaceAIIsIndex;
0105:
0106: /**
0107: * Namespaces associated with START_ELEMENT or END_ELEMENT
0108: */
0109: protected int _currentNamespaceAIIsStart;
0110: protected int _currentNamespaceAIIsEnd;
0111:
0112: /**
0113: * Qualified name associated with START_ELEMENT or END_ELEMENT.
0114: */
0115: protected QualifiedName _qualifiedName;
0116:
0117: /**
0118: * List of attributes
0119: */
0120: protected AttributesHolder _attributes = new AttributesHolder();
0121:
0122: protected boolean _clearAttributes = false;
0123:
0124: /**
0125: * Characters associated with event.
0126: */
0127: protected char[] _characters;
0128: protected int _charactersOffset;
0129:
0130: protected String _algorithmURI;
0131: protected int _algorithmId;
0132: protected boolean _isAlgorithmDataCloned;
0133: protected byte[] _algorithmData;
0134: protected int _algorithmDataOffset;
0135: protected int _algorithmDataLength;
0136:
0137: /**
0138: * State for processing instruction
0139: */
0140: protected String _piTarget;
0141: protected String _piData;
0142:
0143: protected NamespaceContextImpl _nsContext = new NamespaceContextImpl();
0144:
0145: protected String _characterEncodingScheme;
0146:
0147: protected StAXManager _manager;
0148:
0149: public StAXDocumentParser() {
0150: reset();
0151: _manager = new StAXManager(StAXManager.CONTEXT_READER);
0152: }
0153:
0154: public StAXDocumentParser(InputStream s) {
0155: this ();
0156: setInputStream(s);
0157: _manager = new StAXManager(StAXManager.CONTEXT_READER);
0158: }
0159:
0160: public StAXDocumentParser(InputStream s, StAXManager manager) {
0161: this (s);
0162: _manager = manager;
0163: }
0164:
0165: public void setInputStream(InputStream s) {
0166: super .setInputStream(s);
0167: reset();
0168: }
0169:
0170: public void reset() {
0171: super .reset();
0172: if (_internalState != INTERNAL_STATE_START_DOCUMENT
0173: && _internalState != INTERNAL_STATE_END_DOCUMENT) {
0174:
0175: for (int i = _namespaceAIIsIndex - 1; i >= 0; i--) {
0176: _prefixTable
0177: .popScopeWithPrefixEntry(_namespaceAIIsPrefixIndex[i]);
0178: }
0179:
0180: _stackCount = -1;
0181:
0182: _namespaceAIIsIndex = 0;
0183: _characters = null;
0184: _algorithmData = null;
0185: }
0186:
0187: _characterEncodingScheme = "UTF-8";
0188: _eventType = START_DOCUMENT;
0189: _internalState = INTERNAL_STATE_START_DOCUMENT;
0190: }
0191:
0192: protected void resetOnError() {
0193: super .reset();
0194:
0195: if (_v != null) {
0196: _prefixTable.clearCompletely();
0197: }
0198: _duplicateAttributeVerifier.clear();
0199:
0200: _stackCount = -1;
0201:
0202: _namespaceAIIsIndex = 0;
0203: _characters = null;
0204: _algorithmData = null;
0205:
0206: _eventType = START_DOCUMENT;
0207: _internalState = INTERNAL_STATE_START_DOCUMENT;
0208: }
0209:
0210: // -- XMLStreamReader Interface -------------------------------------------
0211:
0212: public Object getProperty(java.lang.String name)
0213: throws java.lang.IllegalArgumentException {
0214: if (_manager != null) {
0215: return _manager.getProperty(name);
0216: }
0217: return null;
0218: }
0219:
0220: public int next() throws XMLStreamException {
0221: try {
0222: if (_internalState != INTERNAL_STATE_VOID) {
0223: switch (_internalState) {
0224: case INTERNAL_STATE_START_DOCUMENT:
0225: decodeHeader();
0226: processDII();
0227:
0228: _internalState = INTERNAL_STATE_VOID;
0229: break;
0230: case INTERNAL_STATE_START_ELEMENT_TERMINATE:
0231: if (_currentNamespaceAIIsEnd > 0) {
0232: for (int i = _currentNamespaceAIIsEnd - 1; i >= _currentNamespaceAIIsStart; i--) {
0233: _prefixTable
0234: .popScopeWithPrefixEntry(_namespaceAIIsPrefixIndex[i]);
0235: }
0236: _namespaceAIIsIndex = _currentNamespaceAIIsStart;
0237: }
0238:
0239: // Pop information off the stack
0240: popStack();
0241:
0242: _internalState = INTERNAL_STATE_VOID;
0243: return _eventType = END_ELEMENT;
0244: case INTERNAL_STATE_SINGLE_TERMINATE_ELEMENT_WITH_NAMESPACES:
0245: // Undeclare namespaces
0246: for (int i = _currentNamespaceAIIsEnd - 1; i >= _currentNamespaceAIIsStart; i--) {
0247: _prefixTable
0248: .popScopeWithPrefixEntry(_namespaceAIIsPrefixIndex[i]);
0249: }
0250: _namespaceAIIsIndex = _currentNamespaceAIIsStart;
0251: _internalState = INTERNAL_STATE_VOID;
0252: break;
0253: case INTERNAL_STATE_DOUBLE_TERMINATE_ELEMENT:
0254: // Undeclare namespaces
0255: if (_currentNamespaceAIIsEnd > 0) {
0256: for (int i = _currentNamespaceAIIsEnd - 1; i >= _currentNamespaceAIIsStart; i--) {
0257: _prefixTable
0258: .popScopeWithPrefixEntry(_namespaceAIIsPrefixIndex[i]);
0259: }
0260: _namespaceAIIsIndex = _currentNamespaceAIIsStart;
0261: }
0262:
0263: if (_stackCount == -1) {
0264: _internalState = INTERNAL_STATE_END_DOCUMENT;
0265: return _eventType = END_DOCUMENT;
0266: }
0267:
0268: // Pop information off the stack
0269: popStack();
0270:
0271: _internalState = (_currentNamespaceAIIsEnd > 0) ? INTERNAL_STATE_SINGLE_TERMINATE_ELEMENT_WITH_NAMESPACES
0272: : INTERNAL_STATE_VOID;
0273: return _eventType = END_ELEMENT;
0274: case INTERNAL_STATE_END_DOCUMENT:
0275: throw new NoSuchElementException(
0276: CommonResourceBundle.getInstance()
0277: .getString("message.noMoreEvents"));
0278: }
0279: }
0280:
0281: // Reset internal state
0282: _characters = null;
0283: _algorithmData = null;
0284: _currentNamespaceAIIsEnd = 0;
0285:
0286: // Process information item
0287: final int b = read();
0288: switch (DecoderStateTables.EII[b]) {
0289: case DecoderStateTables.EII_NO_AIIS_INDEX_SMALL:
0290: processEII(_elementNameTable._array[b], false);
0291: return _eventType;
0292: case DecoderStateTables.EII_AIIS_INDEX_SMALL:
0293: processEII(
0294: _elementNameTable._array[b
0295: & EncodingConstants.INTEGER_3RD_BIT_SMALL_MASK],
0296: true);
0297: return _eventType;
0298: case DecoderStateTables.EII_INDEX_MEDIUM:
0299: processEII(
0300: processEIIIndexMedium(b),
0301: (b & EncodingConstants.ELEMENT_ATTRIBUTE_FLAG) > 0);
0302: return _eventType;
0303: case DecoderStateTables.EII_INDEX_LARGE:
0304: processEII(
0305: processEIIIndexLarge(b),
0306: (b & EncodingConstants.ELEMENT_ATTRIBUTE_FLAG) > 0);
0307: return _eventType;
0308: case DecoderStateTables.EII_LITERAL: {
0309: final QualifiedName qn = processLiteralQualifiedName(
0310: b
0311: & EncodingConstants.LITERAL_QNAME_PREFIX_NAMESPACE_NAME_MASK,
0312: _elementNameTable.getNext());
0313: _elementNameTable.add(qn);
0314: processEII(
0315: qn,
0316: (b & EncodingConstants.ELEMENT_ATTRIBUTE_FLAG) > 0);
0317: return _eventType;
0318: }
0319: case DecoderStateTables.EII_NAMESPACES:
0320: processEIIWithNamespaces((b & EncodingConstants.ELEMENT_ATTRIBUTE_FLAG) > 0);
0321: return _eventType;
0322: case DecoderStateTables.CII_UTF8_SMALL_LENGTH:
0323: _octetBufferLength = (b & EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_SMALL_MASK) + 1;
0324: processUtf8CharacterString(b);
0325: return _eventType = CHARACTERS;
0326: case DecoderStateTables.CII_UTF8_MEDIUM_LENGTH:
0327: _octetBufferLength = read()
0328: + EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_SMALL_LIMIT;
0329: processUtf8CharacterString(b);
0330: return _eventType = CHARACTERS;
0331: case DecoderStateTables.CII_UTF8_LARGE_LENGTH:
0332: _octetBufferLength = ((read() << 24) | (read() << 16)
0333: | (read() << 8) | read())
0334: + EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_MEDIUM_LIMIT;
0335: processUtf8CharacterString(b);
0336: return _eventType = CHARACTERS;
0337: case DecoderStateTables.CII_UTF16_SMALL_LENGTH:
0338: _octetBufferLength = (b & EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_SMALL_MASK) + 1;
0339: processUtf16CharacterString(b);
0340: return _eventType = CHARACTERS;
0341: case DecoderStateTables.CII_UTF16_MEDIUM_LENGTH:
0342: _octetBufferLength = read()
0343: + EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_SMALL_LIMIT;
0344: processUtf16CharacterString(b);
0345: return _eventType = CHARACTERS;
0346: case DecoderStateTables.CII_UTF16_LARGE_LENGTH:
0347: _octetBufferLength = ((read() << 24) | (read() << 16)
0348: | (read() << 8) | read())
0349: + EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_MEDIUM_LIMIT;
0350: processUtf16CharacterString(b);
0351: return _eventType = CHARACTERS;
0352: case DecoderStateTables.CII_RA: {
0353: final boolean addToTable = (b & EncodingConstants.CHARACTER_CHUNK_ADD_TO_TABLE_FLAG) > 0;
0354:
0355: _identifier = (b & 0x02) << 6;
0356: final int b2 = read();
0357: _identifier |= (b2 & 0xFC) >> 2;
0358:
0359: decodeOctetsOnSeventhBitOfNonIdentifyingStringOnThirdBit(b2);
0360:
0361: decodeRestrictedAlphabetAsCharBuffer();
0362:
0363: if (addToTable) {
0364: _charactersOffset = _characterContentChunkTable
0365: .add(_charBuffer, _charBufferLength);
0366: _characters = _characterContentChunkTable._array;
0367: } else {
0368: _characters = _charBuffer;
0369: _charactersOffset = 0;
0370: }
0371: return _eventType = CHARACTERS;
0372: }
0373: case DecoderStateTables.CII_EA: {
0374: if ((b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0) {
0375: throw new EncodingAlgorithmException(
0376: CommonResourceBundle
0377: .getInstance()
0378: .getString(
0379: "message.addToTableNotSupported"));
0380: }
0381:
0382: // Decode encoding algorithm integer
0383: _algorithmId = (b & 0x02) << 6;
0384: final int b2 = read();
0385: _algorithmId |= (b2 & 0xFC) >> 2;
0386:
0387: decodeOctetsOnSeventhBitOfNonIdentifyingStringOnThirdBit(b2);
0388: processCIIEncodingAlgorithm();
0389:
0390: return _eventType = CHARACTERS;
0391: }
0392: case DecoderStateTables.CII_INDEX_SMALL: {
0393: final int index = b
0394: & EncodingConstants.INTEGER_4TH_BIT_SMALL_MASK;
0395: _characterContentChunkTable._cachedIndex = index;
0396:
0397: _characters = _characterContentChunkTable._array;
0398: _charactersOffset = _characterContentChunkTable._offset[index];
0399: _charBufferLength = _characterContentChunkTable._length[index];
0400: return _eventType = CHARACTERS;
0401: }
0402: case DecoderStateTables.CII_INDEX_MEDIUM: {
0403: final int index = (((b & EncodingConstants.INTEGER_4TH_BIT_MEDIUM_MASK) << 8) | read())
0404: + EncodingConstants.INTEGER_4TH_BIT_SMALL_LIMIT;
0405: _characterContentChunkTable._cachedIndex = index;
0406:
0407: _characters = _characterContentChunkTable._array;
0408: _charactersOffset = _characterContentChunkTable._offset[index];
0409: _charBufferLength = _characterContentChunkTable._length[index];
0410: return _eventType = CHARACTERS;
0411: }
0412: case DecoderStateTables.CII_INDEX_LARGE: {
0413: final int index = (((b & EncodingConstants.INTEGER_4TH_BIT_LARGE_MASK) << 16)
0414: | (read() << 8) | read())
0415: + EncodingConstants.INTEGER_4TH_BIT_MEDIUM_LIMIT;
0416: _characterContentChunkTable._cachedIndex = index;
0417:
0418: _characters = _characterContentChunkTable._array;
0419: _charactersOffset = _characterContentChunkTable._offset[index];
0420: _charBufferLength = _characterContentChunkTable._length[index];
0421: return _eventType = CHARACTERS;
0422: }
0423: case DecoderStateTables.CII_INDEX_LARGE_LARGE: {
0424: final int index = ((read() << 16) | (read() << 8) | read())
0425: + EncodingConstants.INTEGER_4TH_BIT_LARGE_LIMIT;
0426: _characterContentChunkTable._cachedIndex = index;
0427:
0428: _characters = _characterContentChunkTable._array;
0429: _charactersOffset = _characterContentChunkTable._offset[index];
0430: _charBufferLength = _characterContentChunkTable._length[index];
0431: return _eventType = CHARACTERS;
0432: }
0433: case DecoderStateTables.COMMENT_II:
0434: processCommentII();
0435: return _eventType;
0436: case DecoderStateTables.PROCESSING_INSTRUCTION_II:
0437: processProcessingII();
0438: return _eventType;
0439: case DecoderStateTables.UNEXPANDED_ENTITY_REFERENCE_II: {
0440: processUnexpandedEntityReference(b);
0441: // Skip the reference
0442: return next();
0443: }
0444: case DecoderStateTables.TERMINATOR_DOUBLE:
0445: if (_stackCount != -1) {
0446: // Pop information off the stack
0447: popStack();
0448:
0449: _internalState = INTERNAL_STATE_DOUBLE_TERMINATE_ELEMENT;
0450: return _eventType = END_ELEMENT;
0451: }
0452:
0453: _internalState = INTERNAL_STATE_END_DOCUMENT;
0454: return _eventType = END_DOCUMENT;
0455: case DecoderStateTables.TERMINATOR_SINGLE:
0456: if (_stackCount != -1) {
0457: // Pop information off the stack
0458: popStack();
0459:
0460: if (_currentNamespaceAIIsEnd > 0) {
0461: _internalState = INTERNAL_STATE_SINGLE_TERMINATE_ELEMENT_WITH_NAMESPACES;
0462: }
0463: return _eventType = END_ELEMENT;
0464: }
0465:
0466: _internalState = INTERNAL_STATE_END_DOCUMENT;
0467: return _eventType = END_DOCUMENT;
0468: default:
0469: throw new FastInfosetException(CommonResourceBundle
0470: .getInstance().getString(
0471: "message.IllegalStateDecodingEII"));
0472: }
0473: } catch (IOException e) {
0474: resetOnError();
0475: e.printStackTrace();
0476: throw new XMLStreamException(e);
0477: } catch (FastInfosetException e) {
0478: resetOnError();
0479: e.printStackTrace();
0480: throw new XMLStreamException(e);
0481: } catch (RuntimeException e) {
0482: resetOnError();
0483: e.printStackTrace();
0484: throw e;
0485: }
0486: }
0487:
0488: private final void processUtf8CharacterString(final int b)
0489: throws IOException {
0490: if ((b & EncodingConstants.CHARACTER_CHUNK_ADD_TO_TABLE_FLAG) > 0) {
0491: _characterContentChunkTable.ensureSize(_octetBufferLength);
0492: _characters = _characterContentChunkTable._array;
0493: _charactersOffset = _characterContentChunkTable._arrayIndex;
0494: decodeUtf8StringAsCharBuffer(
0495: _characterContentChunkTable._array,
0496: _charactersOffset);
0497: _characterContentChunkTable.add(_charBufferLength);
0498: } else {
0499: decodeUtf8StringAsCharBuffer();
0500: _characters = _charBuffer;
0501: _charactersOffset = 0;
0502: }
0503: }
0504:
0505: private final void processUtf16CharacterString(final int b)
0506: throws IOException {
0507: decodeUtf16StringAsCharBuffer();
0508: if ((b & EncodingConstants.CHARACTER_CHUNK_ADD_TO_TABLE_FLAG) > 0) {
0509: _charactersOffset = _characterContentChunkTable.add(
0510: _charBuffer, _charBufferLength);
0511: _characters = _characterContentChunkTable._array;
0512: } else {
0513: _characters = _charBuffer;
0514: _charactersOffset = 0;
0515: }
0516: }
0517:
0518: private final void popStack() {
0519: // Pop information off the stack
0520: _qualifiedName = _qNameStack[_stackCount];
0521: _currentNamespaceAIIsStart = _namespaceAIIsStartStack[_stackCount];
0522: _currentNamespaceAIIsEnd = _namespaceAIIsEndStack[_stackCount];
0523: _qNameStack[_stackCount--] = null;
0524: }
0525:
0526: /** 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.
0527: * If the namespaceURI is null it is not checked for equality, if the localName is null it is not checked for equality.
0528: * @param type the event type
0529: * @param namespaceURI the uri of the event, may be null
0530: * @param localName the localName of the event, may be null
0531: * @throws XMLStreamException if the required values are not matched.
0532: */
0533: public final void require(int type, String namespaceURI,
0534: String localName) throws XMLStreamException {
0535: if (type != _eventType)
0536: throw new XMLStreamException(CommonResourceBundle
0537: .getInstance().getString(
0538: "message.eventTypeNotMatch",
0539: new Object[] { getEventTypeString(type) }));
0540: if (namespaceURI != null
0541: && !namespaceURI.equals(getNamespaceURI()))
0542: throw new XMLStreamException(CommonResourceBundle
0543: .getInstance().getString(
0544: "message.namespaceURINotMatch",
0545: new Object[] { namespaceURI }));
0546: if (localName != null && !localName.equals(getLocalName()))
0547: throw new XMLStreamException(CommonResourceBundle
0548: .getInstance().getString(
0549: "message.localNameNotMatch",
0550: new Object[] { localName }));
0551:
0552: return;
0553: }
0554:
0555: /** Reads the content of a text-only element. Precondition:
0556: * the current event is START_ELEMENT. Postcondition:
0557: * The current event is the corresponding END_ELEMENT.
0558: * @throws XMLStreamException if the current event is not a START_ELEMENT or if
0559: * a non text element is encountered
0560: */
0561: public final String getElementText() throws XMLStreamException {
0562:
0563: if (getEventType() != START_ELEMENT) {
0564: throw new XMLStreamException(CommonResourceBundle
0565: .getInstance().getString(
0566: "message.mustBeOnSTARTELEMENT"),
0567: getLocation());
0568: }
0569: //current is StartElement, move to the next
0570: next();
0571: return getElementText(true);
0572: }
0573:
0574: /**
0575: * @param startElementRead flag if start element has already been read
0576: */
0577: public final String getElementText(boolean startElementRead)
0578: throws XMLStreamException {
0579: if (!startElementRead) {
0580: throw new XMLStreamException(CommonResourceBundle
0581: .getInstance().getString(
0582: "message.mustBeOnSTARTELEMENT"),
0583: getLocation());
0584: }
0585: int eventType = getEventType();
0586: StringBuffer content = new StringBuffer();
0587: while (eventType != END_ELEMENT) {
0588: if (eventType == CHARACTERS || eventType == CDATA
0589: || eventType == SPACE
0590: || eventType == ENTITY_REFERENCE) {
0591: content.append(getText());
0592: } else if (eventType == PROCESSING_INSTRUCTION
0593: || eventType == COMMENT) {
0594: // skipping
0595: } else if (eventType == END_DOCUMENT) {
0596: throw new XMLStreamException(CommonResourceBundle
0597: .getInstance().getString(
0598: "message.unexpectedEOF"));
0599: } else if (eventType == START_ELEMENT) {
0600: throw new XMLStreamException(
0601: CommonResourceBundle.getInstance().getString(
0602: "message.getElementTextExpectTextOnly"),
0603: getLocation());
0604: } else {
0605: throw new XMLStreamException(CommonResourceBundle
0606: .getInstance().getString(
0607: "message.unexpectedEventType")
0608: + getEventTypeString(eventType), getLocation());
0609: }
0610: eventType = next();
0611: }
0612: return content.toString();
0613: }
0614:
0615: /** Skips any white space (isWhiteSpace() returns true), COMMENT,
0616: * or PROCESSING_INSTRUCTION,
0617: * until a START_ELEMENT or END_ELEMENT is reached.
0618: * If other than white space characters, COMMENT, PROCESSING_INSTRUCTION, START_ELEMENT, END_ELEMENT
0619: * are encountered, an exception is thrown. This method should
0620: * be used when processing element-only content seperated by white space.
0621: * This method should
0622: * be used when processing element-only content because
0623: * the parser is not able to recognize ignorable whitespace if
0624: * then DTD is missing or not interpreted.
0625: * @return the event type of the element read
0626: * @throws XMLStreamException if the current event is not white space
0627: */
0628: public final int nextTag() throws XMLStreamException {
0629: next();
0630: return nextTag(true);
0631: }
0632:
0633: /** if the current tag has already read, such as in the case EventReader's
0634: * peek() has been called, the current cursor should not move before the loop
0635: */
0636: public final int nextTag(boolean currentTagRead)
0637: throws XMLStreamException {
0638: int eventType = getEventType();
0639: if (!currentTagRead) {
0640: eventType = next();
0641: }
0642: while ((eventType == CHARACTERS && isWhiteSpace()) // skip whitespace
0643: || (eventType == CDATA && isWhiteSpace())
0644: || eventType == SPACE
0645: || eventType == PROCESSING_INSTRUCTION
0646: || eventType == COMMENT) {
0647: eventType = next();
0648: }
0649: if (eventType != START_ELEMENT && eventType != END_ELEMENT) {
0650: throw new XMLStreamException(CommonResourceBundle
0651: .getInstance().getString(
0652: "message.expectedStartOrEnd"),
0653: getLocation());
0654: }
0655: return eventType;
0656: }
0657:
0658: public final boolean hasNext() throws XMLStreamException {
0659: return (_eventType != END_DOCUMENT);
0660: }
0661:
0662: public void close() throws XMLStreamException {
0663: try {
0664: super .closeIfRequired();
0665: } catch (IOException ex) {
0666: }
0667: }
0668:
0669: public final String getNamespaceURI(String prefix) {
0670: String namespace = getNamespaceDecl(prefix);
0671: if (namespace == null) {
0672: if (prefix == null) {
0673: throw new IllegalArgumentException(CommonResourceBundle
0674: .getInstance().getString("message.nullPrefix"));
0675: }
0676: return null; // unbound
0677: }
0678: return namespace;
0679: }
0680:
0681: public final boolean isStartElement() {
0682: return (_eventType == START_ELEMENT);
0683: }
0684:
0685: public final boolean isEndElement() {
0686: return (_eventType == END_ELEMENT);
0687: }
0688:
0689: public final boolean isCharacters() {
0690: return (_eventType == CHARACTERS);
0691: }
0692:
0693: /**
0694: * Returns true if the cursor points to a character data event that consists of all whitespace
0695: * Application calling this method needs to cache the value and avoid calling this method again
0696: * for the same event.
0697: * @return true if the cursor points to all whitespace, false otherwise
0698: */
0699: public final boolean isWhiteSpace() {
0700: if (isCharacters() || (_eventType == CDATA)) {
0701: char[] ch = this .getTextCharacters();
0702: int start = this .getTextStart();
0703: int length = this .getTextLength();
0704: for (int i = start; i < length; i++) {
0705: if (!XMLChar.isSpace(ch[i])) {
0706: return false;
0707: }
0708: }
0709: return true;
0710: }
0711: return false;
0712: }
0713:
0714: public final String getAttributeValue(String namespaceURI,
0715: String localName) {
0716: if (_eventType != START_ELEMENT) {
0717: throw new IllegalStateException(CommonResourceBundle
0718: .getInstance().getString(
0719: "message.invalidCallingGetAttributeValue"));
0720: }
0721:
0722: if (localName == null)
0723: throw new IllegalArgumentException();
0724:
0725: // Search for the attributes in _attributes
0726: if (namespaceURI != null) {
0727: for (int i = 0; i < _attributes.getLength(); i++) {
0728: if (_attributes.getLocalName(i).equals(localName)
0729: && _attributes.getURI(i).equals(namespaceURI)) {
0730: return _attributes.getValue(i);
0731: }
0732: }
0733: } else {
0734: for (int i = 0; i < _attributes.getLength(); i++) {
0735: if (_attributes.getLocalName(i).equals(localName)) {
0736: return _attributes.getValue(i);
0737: }
0738: }
0739: }
0740:
0741: return null;
0742: }
0743:
0744: public final int getAttributeCount() {
0745: if (_eventType != START_ELEMENT) {
0746: throw new IllegalStateException(CommonResourceBundle
0747: .getInstance().getString(
0748: "message.invalidCallingGetAttributeValue"));
0749: }
0750:
0751: return _attributes.getLength();
0752: }
0753:
0754: public final javax.xml.namespace.QName getAttributeName(int index) {
0755: if (_eventType != START_ELEMENT) {
0756: throw new IllegalStateException(CommonResourceBundle
0757: .getInstance().getString(
0758: "message.invalidCallingGetAttributeValue"));
0759: }
0760: return _attributes.getQualifiedName(index).getQName();
0761: }
0762:
0763: public final String getAttributeNamespace(int index) {
0764: if (_eventType != START_ELEMENT) {
0765: throw new IllegalStateException(CommonResourceBundle
0766: .getInstance().getString(
0767: "message.invalidCallingGetAttributeValue"));
0768: }
0769:
0770: return _attributes.getURI(index);
0771: }
0772:
0773: public final String getAttributeLocalName(int index) {
0774: if (_eventType != START_ELEMENT) {
0775: throw new IllegalStateException(CommonResourceBundle
0776: .getInstance().getString(
0777: "message.invalidCallingGetAttributeValue"));
0778: }
0779: return _attributes.getLocalName(index);
0780: }
0781:
0782: public final String getAttributePrefix(int index) {
0783: if (_eventType != START_ELEMENT) {
0784: throw new IllegalStateException(CommonResourceBundle
0785: .getInstance().getString(
0786: "message.invalidCallingGetAttributeValue"));
0787: }
0788: return _attributes.getPrefix(index);
0789: }
0790:
0791: public final String getAttributeType(int index) {
0792: if (_eventType != START_ELEMENT) {
0793: throw new IllegalStateException(CommonResourceBundle
0794: .getInstance().getString(
0795: "message.invalidCallingGetAttributeValue"));
0796: }
0797: return _attributes.getType(index);
0798: }
0799:
0800: public final String getAttributeValue(int index) {
0801: if (_eventType != START_ELEMENT) {
0802: throw new IllegalStateException(CommonResourceBundle
0803: .getInstance().getString(
0804: "message.invalidCallingGetAttributeValue"));
0805: }
0806: return _attributes.getValue(index);
0807: }
0808:
0809: public final boolean isAttributeSpecified(int index) {
0810: return false; // non-validating parser
0811: }
0812:
0813: public final int getNamespaceCount() {
0814: if (_eventType == START_ELEMENT || _eventType == END_ELEMENT) {
0815: return (_currentNamespaceAIIsEnd > 0) ? (_currentNamespaceAIIsEnd - _currentNamespaceAIIsStart)
0816: : 0;
0817: } else {
0818: throw new IllegalStateException(CommonResourceBundle
0819: .getInstance().getString(
0820: "message.invalidCallingGetNamespaceCount"));
0821: }
0822: }
0823:
0824: public final String getNamespacePrefix(int index) {
0825: if (_eventType == START_ELEMENT || _eventType == END_ELEMENT) {
0826: return _namespaceAIIsPrefix[_currentNamespaceAIIsStart
0827: + index];
0828: } else {
0829: throw new IllegalStateException(CommonResourceBundle
0830: .getInstance().getString(
0831: "message.invalidCallingGetNamespacePrefix"));
0832: }
0833: }
0834:
0835: public final String getNamespaceURI(int index) {
0836: if (_eventType == START_ELEMENT || _eventType == END_ELEMENT) {
0837: return _namespaceAIIsNamespaceName[_currentNamespaceAIIsStart
0838: + index];
0839: } else {
0840: throw new IllegalStateException(CommonResourceBundle
0841: .getInstance().getString(
0842: "message.invalidCallingGetNamespacePrefix"));
0843: }
0844: }
0845:
0846: public final NamespaceContext getNamespaceContext() {
0847: return _nsContext;
0848: }
0849:
0850: public final int getEventType() {
0851: return _eventType;
0852: }
0853:
0854: public final String getText() {
0855: if (_characters == null) {
0856: checkTextState();
0857: }
0858:
0859: if (_characters == _characterContentChunkTable._array) {
0860: return _characterContentChunkTable
0861: .getString(_characterContentChunkTable._cachedIndex);
0862: } else {
0863: return new String(_characters, _charactersOffset,
0864: _charBufferLength);
0865: }
0866: }
0867:
0868: public final char[] getTextCharacters() {
0869: if (_characters == null) {
0870: checkTextState();
0871: }
0872:
0873: return _characters;
0874: }
0875:
0876: public final int getTextStart() {
0877: if (_characters == null) {
0878: checkTextState();
0879: }
0880:
0881: return _charactersOffset;
0882: }
0883:
0884: public final int getTextLength() {
0885: if (_characters == null) {
0886: checkTextState();
0887: }
0888:
0889: return _charBufferLength;
0890: }
0891:
0892: public final int getTextCharacters(int sourceStart, char[] target,
0893: int targetStart, int length) throws XMLStreamException {
0894: if (_characters == null) {
0895: checkTextState();
0896: }
0897:
0898: try {
0899: System.arraycopy(_characters, sourceStart, target,
0900: targetStart, length);
0901: return length;
0902: } catch (IndexOutOfBoundsException e) {
0903: throw new XMLStreamException(e);
0904: }
0905: }
0906:
0907: protected final void checkTextState() {
0908: if (_algorithmData == null) {
0909: throw new IllegalStateException(CommonResourceBundle
0910: .getInstance().getString(
0911: "message.InvalidStateForText"));
0912: }
0913:
0914: try {
0915: convertEncodingAlgorithmDataToCharacters();
0916: } catch (Exception e) {
0917: throw new IllegalStateException(CommonResourceBundle
0918: .getInstance().getString(
0919: "message.InvalidStateForText"));
0920: }
0921: }
0922:
0923: public final String getEncoding() {
0924: return _characterEncodingScheme;
0925: }
0926:
0927: public final boolean hasText() {
0928: return (_characters != null);
0929: }
0930:
0931: public final Location getLocation() {
0932: //location should be created in next()
0933: //returns a nil location for now
0934: return EventLocation.getNilLocation();
0935: }
0936:
0937: public final QName getName() {
0938: if (_eventType == START_ELEMENT || _eventType == END_ELEMENT) {
0939: return _qualifiedName.getQName();
0940: } else {
0941: throw new IllegalStateException(CommonResourceBundle
0942: .getInstance().getString(
0943: "message.invalidCallingGetName"));
0944: }
0945: }
0946:
0947: public final String getLocalName() {
0948: if (_eventType == START_ELEMENT || _eventType == END_ELEMENT) {
0949: return _qualifiedName.localName;
0950: } else {
0951: throw new IllegalStateException(CommonResourceBundle
0952: .getInstance().getString(
0953: "message.invalidCallingGetLocalName"));
0954: }
0955: }
0956:
0957: public final boolean hasName() {
0958: return (_eventType == START_ELEMENT || _eventType == END_ELEMENT);
0959: }
0960:
0961: public final String getNamespaceURI() {
0962: if (_eventType == START_ELEMENT || _eventType == END_ELEMENT) {
0963: return _qualifiedName.namespaceName;
0964: } else {
0965: throw new IllegalStateException(CommonResourceBundle
0966: .getInstance().getString(
0967: "message.invalidCallingGetNamespaceURI"));
0968: }
0969: }
0970:
0971: public final String getPrefix() {
0972: if (_eventType == START_ELEMENT || _eventType == END_ELEMENT) {
0973: return _qualifiedName.prefix;
0974: } else {
0975: throw new IllegalStateException(CommonResourceBundle
0976: .getInstance().getString(
0977: "message.invalidCallingGetPrefix"));
0978: }
0979: }
0980:
0981: public final String getVersion() {
0982: return null;
0983: }
0984:
0985: public final boolean isStandalone() {
0986: return false;
0987: }
0988:
0989: public final boolean standaloneSet() {
0990: return false;
0991: }
0992:
0993: public final String getCharacterEncodingScheme() {
0994: return null;
0995: }
0996:
0997: public final String getPITarget() {
0998: if (_eventType != PROCESSING_INSTRUCTION) {
0999: throw new IllegalStateException(CommonResourceBundle
1000: .getInstance().getString(
1001: "message.invalidCallingGetPITarget"));
1002: }
1003:
1004: return _piTarget;
1005: }
1006:
1007: public final String getPIData() {
1008: if (_eventType != PROCESSING_INSTRUCTION) {
1009: throw new IllegalStateException(CommonResourceBundle
1010: .getInstance().getString(
1011: "message.invalidCallingGetPIData"));
1012: }
1013:
1014: return _piData;
1015: }
1016:
1017: public final String getNameString() {
1018: if (_eventType == START_ELEMENT || _eventType == END_ELEMENT) {
1019: return _qualifiedName.getQNameString();
1020: } else {
1021: throw new IllegalStateException(CommonResourceBundle
1022: .getInstance().getString(
1023: "message.invalidCallingGetName"));
1024: }
1025: }
1026:
1027: public final String getAttributeNameString(int index) {
1028: if (_eventType != START_ELEMENT) {
1029: throw new IllegalStateException(CommonResourceBundle
1030: .getInstance().getString(
1031: "message.invalidCallingGetAttributeValue"));
1032: }
1033: return _attributes.getQualifiedName(index).getQNameString();
1034: }
1035:
1036: public final String getTextAlgorithmURI() {
1037: return _algorithmURI;
1038: }
1039:
1040: public final int getTextAlgorithmIndex() {
1041: return _algorithmId;
1042: }
1043:
1044: public final byte[] getTextAlgorithmBytes() {
1045: return _algorithmData;
1046: }
1047:
1048: public final byte[] getTextAlgorithmBytesClone() {
1049: if (_algorithmData == null) {
1050: return null;
1051: }
1052:
1053: byte[] algorithmData = new byte[_algorithmDataLength];
1054: System.arraycopy(_algorithmData, _algorithmDataOffset,
1055: algorithmData, 0, _algorithmDataLength);
1056: return algorithmData;
1057: }
1058:
1059: public final int getTextAlgorithmStart() {
1060: return _algorithmDataOffset;
1061: }
1062:
1063: public final int getTextAlgorithmLength() {
1064: return _algorithmDataLength;
1065: }
1066:
1067: public final int getTextAlgorithmBytes(int sourceStart,
1068: byte[] target, int targetStart, int length)
1069: throws XMLStreamException {
1070: try {
1071: System.arraycopy(_algorithmData, sourceStart, target,
1072: targetStart, length);
1073: return length;
1074: } catch (IndexOutOfBoundsException e) {
1075: throw new XMLStreamException(e);
1076: }
1077: }
1078:
1079: // FastInfosetStreamReader impl
1080:
1081: public final int peekNext() throws XMLStreamException {
1082: try {
1083: switch (DecoderStateTables.EII[peek(this )]) {
1084: case DecoderStateTables.EII_NO_AIIS_INDEX_SMALL:
1085: case DecoderStateTables.EII_AIIS_INDEX_SMALL:
1086: case DecoderStateTables.EII_INDEX_MEDIUM:
1087: case DecoderStateTables.EII_INDEX_LARGE:
1088: case DecoderStateTables.EII_LITERAL:
1089: case DecoderStateTables.EII_NAMESPACES:
1090: return START_ELEMENT;
1091: case DecoderStateTables.CII_UTF8_SMALL_LENGTH:
1092: case DecoderStateTables.CII_UTF8_MEDIUM_LENGTH:
1093: case DecoderStateTables.CII_UTF8_LARGE_LENGTH:
1094: case DecoderStateTables.CII_UTF16_SMALL_LENGTH:
1095: case DecoderStateTables.CII_UTF16_MEDIUM_LENGTH:
1096: case DecoderStateTables.CII_UTF16_LARGE_LENGTH:
1097: case DecoderStateTables.CII_RA:
1098: case DecoderStateTables.CII_EA:
1099: case DecoderStateTables.CII_INDEX_SMALL:
1100: case DecoderStateTables.CII_INDEX_MEDIUM:
1101: case DecoderStateTables.CII_INDEX_LARGE:
1102: case DecoderStateTables.CII_INDEX_LARGE_LARGE:
1103: return CHARACTERS;
1104: case DecoderStateTables.COMMENT_II:
1105: return COMMENT;
1106: case DecoderStateTables.PROCESSING_INSTRUCTION_II:
1107: return PROCESSING_INSTRUCTION;
1108: case DecoderStateTables.UNEXPANDED_ENTITY_REFERENCE_II:
1109: return ENTITY_REFERENCE;
1110: case DecoderStateTables.TERMINATOR_DOUBLE:
1111: case DecoderStateTables.TERMINATOR_SINGLE:
1112: return (_stackCount != -1) ? END_ELEMENT : END_DOCUMENT;
1113: default:
1114: throw new FastInfosetException(CommonResourceBundle
1115: .getInstance().getString(
1116: "message.IllegalStateDecodingEII"));
1117: }
1118: } catch (IOException e) {
1119: throw new XMLStreamException(e);
1120: } catch (FastInfosetException e) {
1121: throw new XMLStreamException(e);
1122: }
1123: }
1124:
1125: public void onBeforeOctetBufferOverwrite() {
1126: if (_algorithmData != null) {
1127: _algorithmData = getTextAlgorithmBytesClone();
1128: _algorithmDataOffset = 0;
1129: _isAlgorithmDataCloned = true;
1130: }
1131: }
1132:
1133: // Faster access methods without checks
1134:
1135: public final int accessNamespaceCount() {
1136: return (_currentNamespaceAIIsEnd > 0) ? (_currentNamespaceAIIsEnd - _currentNamespaceAIIsStart)
1137: : 0;
1138: }
1139:
1140: public final String accessLocalName() {
1141: return _qualifiedName.localName;
1142: }
1143:
1144: public final String accessNamespaceURI() {
1145: return _qualifiedName.namespaceName;
1146: }
1147:
1148: public final String accessPrefix() {
1149: return _qualifiedName.prefix;
1150: }
1151:
1152: public final char[] accessTextCharacters() {
1153: return _characters;
1154: }
1155:
1156: public final int accessTextStart() {
1157: return _charactersOffset;
1158: }
1159:
1160: public final int accessTextLength() {
1161: return _charBufferLength;
1162: }
1163:
1164: //
1165:
1166: protected final void processDII() throws FastInfosetException,
1167: IOException {
1168: final int b = read();
1169: if (b > 0) {
1170: processDIIOptionalProperties(b);
1171: }
1172: }
1173:
1174: protected final void processDIIOptionalProperties(int b)
1175: throws FastInfosetException, IOException {
1176: // Optimize for the most common case
1177: if (b == EncodingConstants.DOCUMENT_INITIAL_VOCABULARY_FLAG) {
1178: decodeInitialVocabulary();
1179: return;
1180: }
1181:
1182: if ((b & EncodingConstants.DOCUMENT_ADDITIONAL_DATA_FLAG) > 0) {
1183: decodeAdditionalData();
1184: /*
1185: * TODO
1186: * how to report the additional data?
1187: */
1188: }
1189:
1190: if ((b & EncodingConstants.DOCUMENT_INITIAL_VOCABULARY_FLAG) > 0) {
1191: decodeInitialVocabulary();
1192: }
1193:
1194: if ((b & EncodingConstants.DOCUMENT_NOTATIONS_FLAG) > 0) {
1195: decodeNotations();
1196: /*
1197: try {
1198: _dtdHandler.notationDecl(name, public_identifier, system_identifier);
1199: } catch (SAXException e) {
1200: throw new IOException("NotationsDeclarationII");
1201: }
1202: */
1203: }
1204:
1205: if ((b & EncodingConstants.DOCUMENT_UNPARSED_ENTITIES_FLAG) > 0) {
1206: decodeUnparsedEntities();
1207: /*
1208: try {
1209: _dtdHandler.unparsedEntityDecl(name, public_identifier, system_identifier, notation_name);
1210: } catch (SAXException e) {
1211: throw new IOException("UnparsedEntitiesII");
1212: }
1213: */
1214: }
1215:
1216: if ((b & EncodingConstants.DOCUMENT_CHARACTER_ENCODING_SCHEME) > 0) {
1217: _characterEncodingScheme = decodeCharacterEncodingScheme();
1218: }
1219:
1220: if ((b & EncodingConstants.DOCUMENT_STANDALONE_FLAG) > 0) {
1221: boolean standalone = (read() > 0) ? true : false;
1222: /*
1223: * TODO
1224: * how to report the standalone flag?
1225: */
1226: }
1227:
1228: if ((b & EncodingConstants.DOCUMENT_VERSION_FLAG) > 0) {
1229: decodeVersion();
1230: /*
1231: * TODO
1232: * how to report the standalone flag?
1233: */
1234: }
1235: }
1236:
1237: protected final void resizeNamespaceAIIs() {
1238: final String[] namespaceAIIsPrefix = new String[_namespaceAIIsIndex * 2];
1239: System.arraycopy(_namespaceAIIsPrefix, 0, namespaceAIIsPrefix,
1240: 0, _namespaceAIIsIndex);
1241: _namespaceAIIsPrefix = namespaceAIIsPrefix;
1242:
1243: final String[] namespaceAIIsNamespaceName = new String[_namespaceAIIsIndex * 2];
1244: System.arraycopy(_namespaceAIIsNamespaceName, 0,
1245: namespaceAIIsNamespaceName, 0, _namespaceAIIsIndex);
1246: _namespaceAIIsNamespaceName = namespaceAIIsNamespaceName;
1247:
1248: final int[] namespaceAIIsPrefixIndex = new int[_namespaceAIIsIndex * 2];
1249: System.arraycopy(_namespaceAIIsPrefixIndex, 0,
1250: namespaceAIIsPrefixIndex, 0, _namespaceAIIsIndex);
1251: _namespaceAIIsPrefixIndex = namespaceAIIsPrefixIndex;
1252: }
1253:
1254: protected final void processEIIWithNamespaces(boolean hasAttributes)
1255: throws FastInfosetException, IOException {
1256: if (++_prefixTable._declarationId == Integer.MAX_VALUE) {
1257: _prefixTable.clearDeclarationIds();
1258: }
1259:
1260: _currentNamespaceAIIsStart = _namespaceAIIsIndex;
1261: String prefix = "", namespaceName = "";
1262: int b = read();
1263: while ((b & EncodingConstants.NAMESPACE_ATTRIBUTE_MASK) == EncodingConstants.NAMESPACE_ATTRIBUTE) {
1264: if (_namespaceAIIsIndex == _namespaceAIIsPrefix.length) {
1265: resizeNamespaceAIIs();
1266: }
1267:
1268: switch (b
1269: & EncodingConstants.NAMESPACE_ATTRIBUTE_PREFIX_NAME_MASK) {
1270: // no prefix, no namespace
1271: // Undeclaration of default namespace
1272: case 0:
1273: prefix = namespaceName = _namespaceAIIsPrefix[_namespaceAIIsIndex] = _namespaceAIIsNamespaceName[_namespaceAIIsIndex] = "";
1274:
1275: _namespaceNameIndex = _prefixIndex = _namespaceAIIsPrefixIndex[_namespaceAIIsIndex++] = -1;
1276: break;
1277: // no prefix, namespace
1278: // Declaration of default namespace
1279: case 1:
1280: prefix = _namespaceAIIsPrefix[_namespaceAIIsIndex] = "";
1281: namespaceName = _namespaceAIIsNamespaceName[_namespaceAIIsIndex] = decodeIdentifyingNonEmptyStringOnFirstBitAsNamespaceName(false);
1282:
1283: _prefixIndex = _namespaceAIIsPrefixIndex[_namespaceAIIsIndex++] = -1;
1284: break;
1285: // prefix, no namespace
1286: // Undeclaration of namespace
1287: case 2:
1288: prefix = _namespaceAIIsPrefix[_namespaceAIIsIndex] = decodeIdentifyingNonEmptyStringOnFirstBitAsPrefix(false);
1289: namespaceName = _namespaceAIIsNamespaceName[_namespaceAIIsIndex] = "";
1290:
1291: _namespaceNameIndex = -1;
1292: _namespaceAIIsPrefixIndex[_namespaceAIIsIndex++] = _prefixIndex;
1293: break;
1294: // prefix, namespace
1295: // Declaration of prefixed namespace
1296: case 3:
1297: prefix = _namespaceAIIsPrefix[_namespaceAIIsIndex] = decodeIdentifyingNonEmptyStringOnFirstBitAsPrefix(true);
1298: namespaceName = _namespaceAIIsNamespaceName[_namespaceAIIsIndex] = decodeIdentifyingNonEmptyStringOnFirstBitAsNamespaceName(true);
1299:
1300: _namespaceAIIsPrefixIndex[_namespaceAIIsIndex++] = _prefixIndex;
1301: break;
1302: }
1303:
1304: // Push namespace declarations onto the stack
1305: _prefixTable.pushScopeWithPrefixEntry(prefix,
1306: namespaceName, _prefixIndex, _namespaceNameIndex);
1307:
1308: b = read();
1309: }
1310: if (b != EncodingConstants.TERMINATOR) {
1311: throw new FastInfosetException(
1312: CommonResourceBundle
1313: .getInstance()
1314: .getString(
1315: "message.EIInamespaceNameNotTerminatedCorrectly"));
1316: }
1317: _currentNamespaceAIIsEnd = _namespaceAIIsIndex;
1318:
1319: b = read();
1320: switch (DecoderStateTables.EII[b]) {
1321: case DecoderStateTables.EII_NO_AIIS_INDEX_SMALL:
1322: processEII(_elementNameTable._array[b], hasAttributes);
1323: break;
1324: case DecoderStateTables.EII_INDEX_MEDIUM:
1325: processEII(processEIIIndexMedium(b), hasAttributes);
1326: break;
1327: case DecoderStateTables.EII_INDEX_LARGE:
1328: processEII(processEIIIndexLarge(b), hasAttributes);
1329: break;
1330: case DecoderStateTables.EII_LITERAL: {
1331: final QualifiedName qn = processLiteralQualifiedName(
1332: b
1333: & EncodingConstants.LITERAL_QNAME_PREFIX_NAMESPACE_NAME_MASK,
1334: _elementNameTable.getNext());
1335: _elementNameTable.add(qn);
1336: processEII(qn, hasAttributes);
1337: break;
1338: }
1339: default:
1340: throw new FastInfosetException(CommonResourceBundle
1341: .getInstance().getString(
1342: "message.IllegalStateDecodingEIIAfterAIIs"));
1343: }
1344: }
1345:
1346: protected final void processEII(QualifiedName name,
1347: boolean hasAttributes) throws FastInfosetException,
1348: IOException {
1349: if (_prefixTable._currentInScope[name.prefixIndex] != name.namespaceNameIndex) {
1350: throw new FastInfosetException(CommonResourceBundle
1351: .getInstance().getString(
1352: "message.qnameOfEIINotInScope"));
1353: }
1354:
1355: _eventType = START_ELEMENT;
1356: _qualifiedName = name;
1357:
1358: if (_clearAttributes) {
1359: _attributes.clear();
1360: _clearAttributes = false;
1361: }
1362:
1363: if (hasAttributes) {
1364: processAIIs();
1365: }
1366:
1367: // Push element holder onto the stack
1368: _stackCount++;
1369: if (_stackCount == _qNameStack.length) {
1370: QualifiedName[] qNameStack = new QualifiedName[_qNameStack.length * 2];
1371: System.arraycopy(_qNameStack, 0, qNameStack, 0,
1372: _qNameStack.length);
1373: _qNameStack = qNameStack;
1374:
1375: int[] namespaceAIIsStartStack = new int[_namespaceAIIsStartStack.length * 2];
1376: System.arraycopy(_namespaceAIIsStartStack, 0,
1377: namespaceAIIsStartStack, 0,
1378: _namespaceAIIsStartStack.length);
1379: _namespaceAIIsStartStack = namespaceAIIsStartStack;
1380:
1381: int[] namespaceAIIsEndStack = new int[_namespaceAIIsEndStack.length * 2];
1382: System.arraycopy(_namespaceAIIsEndStack, 0,
1383: namespaceAIIsEndStack, 0,
1384: _namespaceAIIsEndStack.length);
1385: _namespaceAIIsEndStack = namespaceAIIsEndStack;
1386: }
1387: _qNameStack[_stackCount] = _qualifiedName;
1388: _namespaceAIIsStartStack[_stackCount] = _currentNamespaceAIIsStart;
1389: _namespaceAIIsEndStack[_stackCount] = _currentNamespaceAIIsEnd;
1390: }
1391:
1392: protected final void processAIIs() throws FastInfosetException,
1393: IOException {
1394: QualifiedName name;
1395: int b;
1396: String value;
1397:
1398: if (++_duplicateAttributeVerifier._currentIteration == Integer.MAX_VALUE) {
1399: _duplicateAttributeVerifier.clear();
1400: }
1401:
1402: _clearAttributes = true;
1403: boolean terminate = false;
1404: do {
1405: // AII qualified name
1406: b = read();
1407: switch (DecoderStateTables.AII[b]) {
1408: case DecoderStateTables.AII_INDEX_SMALL:
1409: name = _attributeNameTable._array[b];
1410: break;
1411: case DecoderStateTables.AII_INDEX_MEDIUM: {
1412: final int i = (((b & EncodingConstants.INTEGER_2ND_BIT_MEDIUM_MASK) << 8) | read())
1413: + EncodingConstants.INTEGER_2ND_BIT_SMALL_LIMIT;
1414: name = _attributeNameTable._array[i];
1415: break;
1416: }
1417: case DecoderStateTables.AII_INDEX_LARGE: {
1418: final int i = (((b & EncodingConstants.INTEGER_2ND_BIT_LARGE_MASK) << 16)
1419: | (read() << 8) | read())
1420: + EncodingConstants.INTEGER_2ND_BIT_MEDIUM_LIMIT;
1421: name = _attributeNameTable._array[i];
1422: break;
1423: }
1424: case DecoderStateTables.AII_LITERAL:
1425: name = processLiteralQualifiedName(
1426: b
1427: & EncodingConstants.LITERAL_QNAME_PREFIX_NAMESPACE_NAME_MASK,
1428: _attributeNameTable.getNext());
1429: name
1430: .createAttributeValues(_duplicateAttributeVerifier.MAP_SIZE);
1431: _attributeNameTable.add(name);
1432: break;
1433: case DecoderStateTables.AII_TERMINATOR_DOUBLE:
1434: _internalState = INTERNAL_STATE_START_ELEMENT_TERMINATE;
1435: case DecoderStateTables.AII_TERMINATOR_SINGLE:
1436: terminate = true;
1437: // AIIs have finished break out of loop
1438: continue;
1439: default:
1440: throw new FastInfosetException(CommonResourceBundle
1441: .getInstance()
1442: .getString("message.decodingAIIs"));
1443: }
1444:
1445: // [normalized value] of AII
1446:
1447: if (name.prefixIndex > 0
1448: && _prefixTable._currentInScope[name.prefixIndex] != name.namespaceNameIndex) {
1449: throw new FastInfosetException(CommonResourceBundle
1450: .getInstance().getString(
1451: "message.AIIqNameNotInScope"));
1452: }
1453:
1454: _duplicateAttributeVerifier.checkForDuplicateAttribute(
1455: name.attributeHash, name.attributeId);
1456:
1457: b = read();
1458: switch (DecoderStateTables.NISTRING[b]) {
1459: case DecoderStateTables.NISTRING_UTF8_SMALL_LENGTH:
1460: _octetBufferLength = (b & EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_SMALL_MASK) + 1;
1461: value = decodeUtf8StringAsString();
1462: if ((b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0) {
1463: _attributeValueTable.add(value);
1464: }
1465:
1466: _attributes.addAttribute(name, value);
1467: break;
1468: case DecoderStateTables.NISTRING_UTF8_MEDIUM_LENGTH:
1469: _octetBufferLength = read()
1470: + EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_SMALL_LIMIT;
1471: value = decodeUtf8StringAsString();
1472: if ((b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0) {
1473: _attributeValueTable.add(value);
1474: }
1475:
1476: _attributes.addAttribute(name, value);
1477: break;
1478: case DecoderStateTables.NISTRING_UTF8_LARGE_LENGTH:
1479: _octetBufferLength = ((read() << 24) | (read() << 16)
1480: | (read() << 8) | read())
1481: + EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_MEDIUM_LIMIT;
1482: value = decodeUtf8StringAsString();
1483: if ((b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0) {
1484: _attributeValueTable.add(value);
1485: }
1486:
1487: _attributes.addAttribute(name, value);
1488: break;
1489: case DecoderStateTables.NISTRING_UTF16_SMALL_LENGTH:
1490: _octetBufferLength = (b & EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_SMALL_MASK) + 1;
1491: value = decodeUtf16StringAsString();
1492: if ((b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0) {
1493: _attributeValueTable.add(value);
1494: }
1495:
1496: _attributes.addAttribute(name, value);
1497: break;
1498: case DecoderStateTables.NISTRING_UTF16_MEDIUM_LENGTH:
1499: _octetBufferLength = read()
1500: + EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_SMALL_LIMIT;
1501: value = decodeUtf16StringAsString();
1502: if ((b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0) {
1503: _attributeValueTable.add(value);
1504: }
1505:
1506: _attributes.addAttribute(name, value);
1507: break;
1508: case DecoderStateTables.NISTRING_UTF16_LARGE_LENGTH:
1509: _octetBufferLength = ((read() << 24) | (read() << 16)
1510: | (read() << 8) | read())
1511: + EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_MEDIUM_LIMIT;
1512: value = decodeUtf16StringAsString();
1513: if ((b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0) {
1514: _attributeValueTable.add(value);
1515: }
1516:
1517: _attributes.addAttribute(name, value);
1518: break;
1519: case DecoderStateTables.NISTRING_RA: {
1520: final boolean addToTable = (b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0;
1521: // Decode resitricted alphabet integer
1522: _identifier = (b & 0x0F) << 4;
1523: b = read();
1524: _identifier |= (b & 0xF0) >> 4;
1525:
1526: decodeOctetsOnFifthBitOfNonIdentifyingStringOnFirstBit(b);
1527:
1528: value = decodeRestrictedAlphabetAsString();
1529: if (addToTable) {
1530: _attributeValueTable.add(value);
1531: }
1532:
1533: _attributes.addAttribute(name, value);
1534: break;
1535: }
1536: case DecoderStateTables.NISTRING_EA: {
1537: if ((b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0) {
1538: throw new EncodingAlgorithmException(
1539: CommonResourceBundle
1540: .getInstance()
1541: .getString(
1542: "message.addToTableNotSupported"));
1543: }
1544:
1545: // Decode encoding algorithm integer
1546: _identifier = (b & 0x0F) << 4;
1547: b = read();
1548: _identifier |= (b & 0xF0) >> 4;
1549:
1550: decodeOctetsOnFifthBitOfNonIdentifyingStringOnFirstBit(b);
1551: processAIIEncodingAlgorithm(name);
1552: break;
1553: }
1554: case DecoderStateTables.NISTRING_INDEX_SMALL:
1555: _attributes
1556: .addAttribute(
1557: name,
1558: _attributeValueTable._array[b
1559: & EncodingConstants.INTEGER_2ND_BIT_SMALL_MASK]);
1560: break;
1561: case DecoderStateTables.NISTRING_INDEX_MEDIUM: {
1562: final int index = (((b & EncodingConstants.INTEGER_2ND_BIT_MEDIUM_MASK) << 8) | read())
1563: + EncodingConstants.INTEGER_2ND_BIT_SMALL_LIMIT;
1564:
1565: _attributes.addAttribute(name,
1566: _attributeValueTable._array[index]);
1567: break;
1568: }
1569: case DecoderStateTables.NISTRING_INDEX_LARGE: {
1570: final int index = (((b & EncodingConstants.INTEGER_2ND_BIT_LARGE_MASK) << 16)
1571: | (read() << 8) | read())
1572: + EncodingConstants.INTEGER_2ND_BIT_MEDIUM_LIMIT;
1573:
1574: _attributes.addAttribute(name,
1575: _attributeValueTable._array[index]);
1576: break;
1577: }
1578: case DecoderStateTables.NISTRING_EMPTY:
1579: _attributes.addAttribute(name, "");
1580: break;
1581: default:
1582: throw new FastInfosetException(CommonResourceBundle
1583: .getInstance().getString(
1584: "message.decodingAIIValue"));
1585: }
1586:
1587: } while (!terminate);
1588:
1589: // Reset duplication attribute verfifier
1590: _duplicateAttributeVerifier._poolCurrent = _duplicateAttributeVerifier._poolHead;
1591: }
1592:
1593: protected final QualifiedName processEIIIndexMedium(int b)
1594: throws FastInfosetException, IOException {
1595: final int i = (((b & EncodingConstants.INTEGER_3RD_BIT_MEDIUM_MASK) << 8) | read())
1596: + EncodingConstants.INTEGER_3RD_BIT_SMALL_LIMIT;
1597: return _elementNameTable._array[i];
1598: }
1599:
1600: protected final QualifiedName processEIIIndexLarge(int b)
1601: throws FastInfosetException, IOException {
1602: int i;
1603: if ((b & EncodingConstants.INTEGER_3RD_BIT_LARGE_LARGE_FLAG) == 0x20) {
1604: // EII large index
1605: i = (((b & EncodingConstants.INTEGER_3RD_BIT_LARGE_MASK) << 16)
1606: | (read() << 8) | read())
1607: + EncodingConstants.INTEGER_3RD_BIT_MEDIUM_LIMIT;
1608: } else {
1609: // EII large large index
1610: i = (((read() & EncodingConstants.INTEGER_3RD_BIT_LARGE_LARGE_MASK) << 16)
1611: | (read() << 8) | read())
1612: + EncodingConstants.INTEGER_3RD_BIT_LARGE_LIMIT;
1613: }
1614: return _elementNameTable._array[i];
1615: }
1616:
1617: protected final QualifiedName processLiteralQualifiedName(
1618: int state, QualifiedName q) throws FastInfosetException,
1619: IOException {
1620: if (q == null)
1621: q = new QualifiedName();
1622:
1623: switch (state) {
1624: // no prefix, no namespace
1625: case 0:
1626: return q
1627: .set(
1628: "",
1629: "",
1630: decodeIdentifyingNonEmptyStringOnFirstBit(_v.localName),
1631: "", 0, -1, -1, _identifier);
1632: // no prefix, namespace
1633: case 1:
1634: return q
1635: .set(
1636: "",
1637: decodeIdentifyingNonEmptyStringIndexOnFirstBitAsNamespaceName(false),
1638: decodeIdentifyingNonEmptyStringOnFirstBit(_v.localName),
1639: "", 0, -1, _namespaceNameIndex, _identifier);
1640: // prefix, no namespace
1641: case 2:
1642: throw new FastInfosetException(CommonResourceBundle
1643: .getInstance().getString(
1644: "message.qNameMissingNamespaceName"));
1645: // prefix, namespace
1646: case 3:
1647: return q
1648: .set(
1649: decodeIdentifyingNonEmptyStringIndexOnFirstBitAsPrefix(true),
1650: decodeIdentifyingNonEmptyStringIndexOnFirstBitAsNamespaceName(true),
1651: decodeIdentifyingNonEmptyStringOnFirstBit(_v.localName),
1652: "", 0, _prefixIndex, _namespaceNameIndex,
1653: _identifier);
1654: default:
1655: throw new FastInfosetException(CommonResourceBundle
1656: .getInstance().getString("message.decodingEII"));
1657: }
1658: }
1659:
1660: protected final void processCommentII()
1661: throws FastInfosetException, IOException {
1662: _eventType = COMMENT;
1663:
1664: switch (decodeNonIdentifyingStringOnFirstBit()) {
1665: case NISTRING_STRING:
1666: if (_addToTable) {
1667: _v.otherString.add(new CharArray(_charBuffer, 0,
1668: _charBufferLength, true));
1669: }
1670:
1671: _characters = _charBuffer;
1672: _charactersOffset = 0;
1673: break;
1674: case NISTRING_ENCODING_ALGORITHM:
1675: throw new FastInfosetException(CommonResourceBundle
1676: .getInstance().getString(
1677: "message.commentIIAlgorithmNotSupported"));
1678: case NISTRING_INDEX:
1679: final CharArray ca = _v.otherString.get(_integer);
1680:
1681: _characters = ca.ch;
1682: _charactersOffset = ca.start;
1683: _charBufferLength = ca.length;
1684: break;
1685: case NISTRING_EMPTY_STRING:
1686: _characters = _charBuffer;
1687: _charactersOffset = 0;
1688: _charBufferLength = 0;
1689: break;
1690: }
1691: }
1692:
1693: protected final void processProcessingII()
1694: throws FastInfosetException, IOException {
1695: _eventType = PROCESSING_INSTRUCTION;
1696:
1697: _piTarget = decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherNCName);
1698:
1699: switch (decodeNonIdentifyingStringOnFirstBit()) {
1700: case NISTRING_STRING:
1701: _piData = new String(_charBuffer, 0, _charBufferLength);
1702: if (_addToTable) {
1703: _v.otherString.add(new CharArrayString(_piData));
1704: }
1705: break;
1706: case NISTRING_ENCODING_ALGORITHM:
1707: throw new FastInfosetException(
1708: CommonResourceBundle
1709: .getInstance()
1710: .getString(
1711: "message.processingIIWithEncodingAlgorithm"));
1712: case NISTRING_INDEX:
1713: _piData = _v.otherString.get(_integer).toString();
1714: break;
1715: case NISTRING_EMPTY_STRING:
1716: _piData = "";
1717: break;
1718: }
1719: }
1720:
1721: protected final void processUnexpandedEntityReference(final int b)
1722: throws FastInfosetException, IOException {
1723: _eventType = ENTITY_REFERENCE;
1724:
1725: /*
1726: * TODO
1727: * How does StAX report such events?
1728: */
1729: String entity_reference_name = decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherNCName);
1730:
1731: String system_identifier = ((b & EncodingConstants.UNEXPANDED_ENTITY_SYSTEM_IDENTIFIER_FLAG) > 0) ? decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherURI)
1732: : "";
1733: String public_identifier = ((b & EncodingConstants.UNEXPANDED_ENTITY_PUBLIC_IDENTIFIER_FLAG) > 0) ? decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherURI)
1734: : "";
1735: }
1736:
1737: protected final void processCIIEncodingAlgorithm()
1738: throws FastInfosetException, IOException {
1739: _algorithmData = _octetBuffer;
1740: _algorithmDataOffset = _octetBufferStart;
1741: _algorithmDataLength = _octetBufferLength;
1742: _isAlgorithmDataCloned = false;
1743:
1744: if (_algorithmId >= EncodingConstants.ENCODING_ALGORITHM_APPLICATION_START) {
1745: _algorithmURI = _v.encodingAlgorithm
1746: .get(_algorithmId
1747: - EncodingConstants.ENCODING_ALGORITHM_APPLICATION_START);
1748: if (_algorithmURI == null) {
1749: throw new EncodingAlgorithmException(
1750: CommonResourceBundle.getInstance().getString(
1751: "message.URINotPresent",
1752: new Object[] { Integer
1753: .valueOf(_identifier) }));
1754: }
1755: } else if (_algorithmId > EncodingConstants.ENCODING_ALGORITHM_BUILTIN_END) {
1756: // Reserved built-in algorithms for future use
1757: // TODO should use sax property to decide if event will be
1758: // reported, allows for support through handler if required.
1759: throw new EncodingAlgorithmException(CommonResourceBundle
1760: .getInstance().getString(
1761: "message.identifiers10to31Reserved"));
1762: }
1763: }
1764:
1765: protected final void processAIIEncodingAlgorithm(QualifiedName name)
1766: throws FastInfosetException, IOException {
1767: String URI = null;
1768: if (_identifier >= EncodingConstants.ENCODING_ALGORITHM_APPLICATION_START) {
1769: URI = _v.encodingAlgorithm
1770: .get(_identifier
1771: - EncodingConstants.ENCODING_ALGORITHM_APPLICATION_START);
1772: if (URI == null) {
1773: throw new EncodingAlgorithmException(
1774: CommonResourceBundle.getInstance().getString(
1775: "message.URINotPresent",
1776: new Object[] { Integer
1777: .valueOf(_identifier) }));
1778: }
1779: } else if (_identifier >= EncodingConstants.ENCODING_ALGORITHM_BUILTIN_END) {
1780: if (_identifier == EncodingAlgorithmIndexes.CDATA) {
1781: throw new EncodingAlgorithmException(
1782: CommonResourceBundle.getInstance().getString(
1783: "message.CDATAAlgorithmNotSupported"));
1784: }
1785:
1786: // Reserved built-in algorithms for future use
1787: // TODO should use sax property to decide if event will be
1788: // reported, allows for support through handler if required.
1789: throw new EncodingAlgorithmException(CommonResourceBundle
1790: .getInstance().getString(
1791: "message.identifiers10to31Reserved"));
1792: }
1793:
1794: final byte[] data = new byte[_octetBufferLength];
1795: System.arraycopy(_octetBuffer, _octetBufferStart, data, 0,
1796: _octetBufferLength);
1797: _attributes.addAttributeWithAlgorithmData(name, URI,
1798: _identifier, data);
1799: }
1800:
1801: protected final void convertEncodingAlgorithmDataToCharacters()
1802: throws FastInfosetException, IOException {
1803: StringBuffer buffer = new StringBuffer();
1804: if (_algorithmId == EncodingAlgorithmIndexes.BASE64) {
1805: convertBase64AlorithmDataToCharacters(buffer);
1806: } else if (_algorithmId < EncodingConstants.ENCODING_ALGORITHM_BUILTIN_END) {
1807: Object array = BuiltInEncodingAlgorithmFactory.table[_algorithmId]
1808: .decodeFromBytes(_algorithmData,
1809: _algorithmDataOffset, _algorithmDataLength);
1810: BuiltInEncodingAlgorithmFactory.table[_algorithmId]
1811: .convertToCharacters(array, buffer);
1812: } else if (_algorithmId == EncodingAlgorithmIndexes.CDATA) {
1813: _octetBufferOffset -= _octetBufferLength;
1814: decodeUtf8StringIntoCharBuffer();
1815:
1816: _characters = _charBuffer;
1817: _charactersOffset = 0;
1818: return;
1819: } else if (_algorithmId >= EncodingConstants.ENCODING_ALGORITHM_APPLICATION_START) {
1820: final EncodingAlgorithm ea = (EncodingAlgorithm) _registeredEncodingAlgorithms
1821: .get(_algorithmURI);
1822: if (ea != null) {
1823: final Object data = ea.decodeFromBytes(_octetBuffer,
1824: _octetBufferStart, _octetBufferLength);
1825: ea.convertToCharacters(data, buffer);
1826: } else {
1827: throw new EncodingAlgorithmException(
1828: CommonResourceBundle
1829: .getInstance()
1830: .getString(
1831: "message.algorithmDataCannotBeReported"));
1832: }
1833: }
1834:
1835: _characters = new char[buffer.length()];
1836: buffer.getChars(0, buffer.length(), _characters, 0);
1837: _charactersOffset = 0;
1838: _charBufferLength = _characters.length;
1839: }
1840:
1841: /* If base64 data comes is chunks, bytes, which were cut to align 3,
1842: * from prev. base64 chunk are stored in this buffer */
1843: private byte[] base64TaleBytes = new byte[3];
1844: private int base64TaleLength;
1845:
1846: /*
1847: * Method converts _algorithmData to base64 encoded String
1848: * Counts with base64 data coming in chunks, aligning input chunks by 3,
1849: * avoiding double cloning, happening after possible peek, peek2 cloning by Base64 algorithm
1850: */
1851: protected void convertBase64AlorithmDataToCharacters(
1852: StringBuffer buffer) throws EncodingAlgorithmException,
1853: IOException {
1854: // How much new came data was serialized with prev. tale
1855: int afterTaleOffset = 0;
1856:
1857: if (base64TaleLength > 0) {
1858: // Serialize tale left from prev. chunk
1859: int bytesToCopy = Math.min(3 - base64TaleLength,
1860: _algorithmDataLength);
1861: System.arraycopy(_algorithmData, _algorithmDataOffset,
1862: base64TaleBytes, base64TaleLength, bytesToCopy);
1863: if (base64TaleLength + bytesToCopy == 3) {
1864: base64DecodeWithCloning(buffer, base64TaleBytes, 0, 3);
1865: } else if (!isBase64Follows()) {
1866: // End of text was read to temp array
1867: base64DecodeWithCloning(buffer, base64TaleBytes, 0,
1868: base64TaleLength + bytesToCopy);
1869: return;
1870: } else {
1871: // If the end of chunk fit to tmp array, but next chunk is expected
1872: base64TaleLength += bytesToCopy;
1873: return;
1874: }
1875:
1876: afterTaleOffset = bytesToCopy;
1877: base64TaleLength = 0;
1878: }
1879:
1880: int taleBytesRemaining = isBase64Follows() ? (_algorithmDataLength - afterTaleOffset) % 3
1881: : 0;
1882:
1883: if (_isAlgorithmDataCloned) {
1884: base64DecodeWithoutCloning(buffer, _algorithmData,
1885: _algorithmDataOffset + afterTaleOffset,
1886: _algorithmDataLength - afterTaleOffset
1887: - taleBytesRemaining);
1888: } else {
1889: base64DecodeWithCloning(buffer, _algorithmData,
1890: _algorithmDataOffset + afterTaleOffset,
1891: _algorithmDataLength - afterTaleOffset
1892: - taleBytesRemaining);
1893: }
1894:
1895: if (taleBytesRemaining > 0) {
1896: System.arraycopy(_algorithmData, _algorithmDataOffset
1897: + _algorithmDataLength - taleBytesRemaining,
1898: base64TaleBytes, 0, taleBytesRemaining);
1899: base64TaleLength = taleBytesRemaining;
1900: }
1901: }
1902:
1903: /*
1904: * Encodes incoming data to Base64 string.
1905: * Method performs additional input data cloning
1906: */
1907: private void base64DecodeWithCloning(StringBuffer dstBuffer,
1908: byte[] data, int offset, int length)
1909: throws EncodingAlgorithmException {
1910: Object array = BuiltInEncodingAlgorithmFactory.base64EncodingAlgorithm
1911: .decodeFromBytes(data, offset, length);
1912: BuiltInEncodingAlgorithmFactory.base64EncodingAlgorithm
1913: .convertToCharacters(array, dstBuffer);
1914: }
1915:
1916: /*
1917: * Encodes incoming data to Base64 string.
1918: * Avoids input data cloning
1919: */
1920: private void base64DecodeWithoutCloning(StringBuffer dstBuffer,
1921: byte[] data, int offset, int length)
1922: throws EncodingAlgorithmException {
1923: BuiltInEncodingAlgorithmFactory.base64EncodingAlgorithm
1924: .convertToCharacters(data, offset, length, dstBuffer);
1925: }
1926:
1927: /*
1928: * Looks ahead in InputStream, whether next data is Base64 chunk
1929: */
1930: public boolean isBase64Follows() throws IOException {
1931: // Process information item
1932: int b = peek(this );
1933: switch (DecoderStateTables.EII[b]) {
1934: case DecoderStateTables.CII_EA:
1935: int algorithmId = (b & 0x02) << 6;
1936: int b2 = peek2(this );
1937: algorithmId |= (b2 & 0xFC) >> 2;
1938:
1939: return algorithmId == EncodingAlgorithmIndexes.BASE64;
1940: default:
1941: return false;
1942: }
1943: }
1944:
1945: protected class NamespaceContextImpl implements NamespaceContext {
1946: public final String getNamespaceURI(String prefix) {
1947: return _prefixTable.getNamespaceFromPrefix(prefix);
1948: }
1949:
1950: public final String getPrefix(String namespaceURI) {
1951: return _prefixTable.getPrefixFromNamespace(namespaceURI);
1952: }
1953:
1954: public final Iterator getPrefixes(String namespaceURI) {
1955: return _prefixTable.getPrefixesFromNamespace(namespaceURI);
1956: }
1957: }
1958:
1959: public final String getNamespaceDecl(String prefix) {
1960: return _prefixTable.getNamespaceFromPrefix(prefix);
1961: }
1962:
1963: public final String getURI(String prefix) {
1964: return getNamespaceDecl(prefix);
1965: }
1966:
1967: public final Iterator getPrefixes() {
1968: return _prefixTable.getPrefixes();
1969: }
1970:
1971: public final AttributesHolder getAttributesHolder() {
1972: return _attributes;
1973: }
1974:
1975: public final void setManager(StAXManager manager) {
1976: _manager = manager;
1977: }
1978:
1979: final static String getEventTypeString(int eventType) {
1980: switch (eventType) {
1981: case START_ELEMENT:
1982: return "START_ELEMENT";
1983: case END_ELEMENT:
1984: return "END_ELEMENT";
1985: case PROCESSING_INSTRUCTION:
1986: return "PROCESSING_INSTRUCTION";
1987: case CHARACTERS:
1988: return "CHARACTERS";
1989: case COMMENT:
1990: return "COMMENT";
1991: case START_DOCUMENT:
1992: return "START_DOCUMENT";
1993: case END_DOCUMENT:
1994: return "END_DOCUMENT";
1995: case ENTITY_REFERENCE:
1996: return "ENTITY_REFERENCE";
1997: case ATTRIBUTE:
1998: return "ATTRIBUTE";
1999: case DTD:
2000: return "DTD";
2001: case CDATA:
2002: return "CDATA";
2003: }
2004: return "UNKNOWN_EVENT_TYPE";
2005: }
2006: }
|