aoqi@0: /* aoqi@0: * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved. aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@0: * aoqi@0: * This code is free software; you can redistribute it and/or modify it aoqi@0: * under the terms of the GNU General Public License version 2 only, as aoqi@0: * published by the Free Software Foundation. Oracle designates this aoqi@0: * particular file as subject to the "Classpath" exception as provided aoqi@0: * by Oracle in the LICENSE file that accompanied this code. aoqi@0: * aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that aoqi@0: * accompanied this code). aoqi@0: * aoqi@0: * You should have received a copy of the GNU General Public License version aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@0: * aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@0: * or visit www.oracle.com if you need additional information or have any aoqi@0: * questions. aoqi@0: * aoqi@0: * THIS FILE WAS MODIFIED BY SUN MICROSYSTEMS, INC. aoqi@0: */ aoqi@0: aoqi@0: package com.sun.xml.internal.fastinfoset; aoqi@0: aoqi@0: import com.sun.xml.internal.fastinfoset.alphabet.BuiltInRestrictedAlphabets; aoqi@0: import com.sun.xml.internal.fastinfoset.org.apache.xerces.util.XMLChar; aoqi@0: import com.sun.xml.internal.fastinfoset.util.CharArray; aoqi@0: import com.sun.xml.internal.fastinfoset.util.CharArrayArray; aoqi@0: import com.sun.xml.internal.fastinfoset.util.CharArrayString; aoqi@0: import com.sun.xml.internal.fastinfoset.util.ContiguousCharArrayArray; aoqi@0: import com.sun.xml.internal.fastinfoset.util.DuplicateAttributeVerifier; aoqi@0: import com.sun.xml.internal.fastinfoset.util.PrefixArray; aoqi@0: import com.sun.xml.internal.fastinfoset.util.QualifiedNameArray; aoqi@0: import com.sun.xml.internal.fastinfoset.util.StringArray; aoqi@0: import com.sun.xml.internal.fastinfoset.vocab.ParserVocabulary; aoqi@0: import java.io.EOFException; aoqi@0: import java.io.IOException; aoqi@0: import java.io.InputStream; aoqi@0: import java.util.ArrayList; aoqi@0: import java.util.HashMap; aoqi@0: import java.util.List; aoqi@0: import java.util.Map; aoqi@0: import com.sun.xml.internal.org.jvnet.fastinfoset.FastInfosetException; aoqi@0: import com.sun.xml.internal.org.jvnet.fastinfoset.FastInfosetParser; aoqi@0: aoqi@0: /** aoqi@0: * Abstract decoder for developing concrete encoders. aoqi@0: * aoqi@0: * Concrete implementations extending Decoder will utilize methods on Decoder aoqi@0: * to decode XML infoset according to the Fast Infoset standard. It is the aoqi@0: * responsibility of the concrete implementation to ensure that methods are aoqi@0: * invoked in the correct order to correctly decode a valid fast infoset aoqi@0: * document. aoqi@0: * aoqi@0: *

aoqi@0: * This class extends org.sax.xml.DefaultHandler so that concrete SAX aoqi@0: * implementations can be used with javax.xml.parsers.SAXParser and the parse aoqi@0: * methods that take org.sax.xml.DefaultHandler as a parameter. aoqi@0: * aoqi@0: *

aoqi@0: * Buffering of octets that are read from an {@link java.io.InputStream} is aoqi@0: * supported in a similar manner to a {@link java.io.BufferedInputStream}. aoqi@0: * Combining buffering with decoding enables better performance. aoqi@0: * aoqi@0: *

aoqi@0: * More than one fast infoset document may be decoded from the aoqi@0: * {@link java.io.InputStream}. aoqi@0: */ aoqi@0: public abstract class Decoder implements FastInfosetParser { aoqi@0: aoqi@0: private static final char[] XML_NAMESPACE_NAME_CHARS = aoqi@0: EncodingConstants.XML_NAMESPACE_NAME.toCharArray(); aoqi@0: aoqi@0: private static final char[] XMLNS_NAMESPACE_PREFIX_CHARS = aoqi@0: EncodingConstants.XMLNS_NAMESPACE_PREFIX.toCharArray(); aoqi@0: aoqi@0: private static final char[] XMLNS_NAMESPACE_NAME_CHARS = aoqi@0: EncodingConstants.XMLNS_NAMESPACE_NAME.toCharArray(); aoqi@0: aoqi@0: /** aoqi@0: * String interning system property. aoqi@0: */ aoqi@0: public static final String STRING_INTERNING_SYSTEM_PROPERTY = aoqi@0: "com.sun.xml.internal.fastinfoset.parser.string-interning"; aoqi@0: aoqi@0: /** aoqi@0: * Internal buffer size interning system property. aoqi@0: */ aoqi@0: public static final String BUFFER_SIZE_SYSTEM_PROPERTY = aoqi@0: "com.sun.xml.internal.fastinfoset.parser.buffer-size"; aoqi@0: aoqi@0: private static boolean _stringInterningSystemDefault = false; aoqi@0: aoqi@0: private static int _bufferSizeSystemDefault = 1024; aoqi@0: aoqi@0: static { aoqi@0: String p = System.getProperty(STRING_INTERNING_SYSTEM_PROPERTY, aoqi@0: Boolean.toString(_stringInterningSystemDefault)); aoqi@0: _stringInterningSystemDefault = Boolean.valueOf(p).booleanValue(); aoqi@0: aoqi@0: p = System.getProperty(BUFFER_SIZE_SYSTEM_PROPERTY, aoqi@0: Integer.toString(_bufferSizeSystemDefault)); aoqi@0: try { aoqi@0: int i = Integer.valueOf(p).intValue(); aoqi@0: if (i > 0) { aoqi@0: _bufferSizeSystemDefault = i; aoqi@0: } aoqi@0: } catch (NumberFormatException e) { aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * True if string interning is performed by the decoder. aoqi@0: */ aoqi@0: private boolean _stringInterning = _stringInterningSystemDefault; aoqi@0: aoqi@0: /** aoqi@0: * The input stream from which the fast infoset document is being read. aoqi@0: */ aoqi@0: private InputStream _s; aoqi@0: aoqi@0: /** aoqi@0: * The map of URIs to referenced vocabularies. aoqi@0: */ aoqi@0: private Map _externalVocabularies; aoqi@0: aoqi@0: /** aoqi@0: * True if can parse fragments. aoqi@0: */ aoqi@0: protected boolean _parseFragments; aoqi@0: aoqi@0: /** aoqi@0: * True if needs to close underlying input stream. aoqi@0: */ aoqi@0: protected boolean _needForceStreamClose; aoqi@0: aoqi@0: /** aoqi@0: * True if the vocabulary is internally created by decoder. aoqi@0: */ aoqi@0: private boolean _vIsInternal; aoqi@0: aoqi@0: /** aoqi@0: * The list of Notation Information Items that are part of the aoqi@0: * Document Information Item. aoqi@0: */ aoqi@0: protected List _notations; aoqi@0: aoqi@0: /** aoqi@0: * The list of Unparsed Entity Information Items that are part of the aoqi@0: * Document Information Item. aoqi@0: */ aoqi@0: protected List _unparsedEntities; aoqi@0: aoqi@0: /** aoqi@0: * The map of URIs to registered encoding algorithms. aoqi@0: */ aoqi@0: protected Map _registeredEncodingAlgorithms = new HashMap(); aoqi@0: aoqi@0: /** aoqi@0: * The vocabulary used for decoding. aoqi@0: */ aoqi@0: protected ParserVocabulary _v; aoqi@0: aoqi@0: /** aoqi@0: * The prefix table of the vocabulary. aoqi@0: */ aoqi@0: protected PrefixArray _prefixTable; aoqi@0: aoqi@0: /** aoqi@0: * The element name table of the vocabulary. aoqi@0: */ aoqi@0: protected QualifiedNameArray _elementNameTable; aoqi@0: aoqi@0: /** aoqi@0: * The attribute name table of the vocabulary. aoqi@0: */ aoqi@0: protected QualifiedNameArray _attributeNameTable; aoqi@0: aoqi@0: /** aoqi@0: * The character content chunk table of the vocabulary. aoqi@0: */ aoqi@0: protected ContiguousCharArrayArray _characterContentChunkTable; aoqi@0: aoqi@0: /** aoqi@0: * The attribute value table of the vocabulary. aoqi@0: */ aoqi@0: protected StringArray _attributeValueTable; aoqi@0: aoqi@0: /** aoqi@0: * The current octet that is being read aoqi@0: */ aoqi@0: protected int _b; aoqi@0: aoqi@0: /** aoqi@0: * True if an information item is terminated. aoqi@0: */ aoqi@0: protected boolean _terminate; aoqi@0: aoqi@0: /** aoqi@0: * True if two information item are terminated in direct sequence. aoqi@0: */ aoqi@0: protected boolean _doubleTerminate; aoqi@0: aoqi@0: /** aoqi@0: * True if an entry is required to be added to a table aoqi@0: */ aoqi@0: protected boolean _addToTable; aoqi@0: aoqi@0: /** aoqi@0: * The vocabulary table index to an indexed non identifying string. aoqi@0: */ aoqi@0: protected int _integer; aoqi@0: aoqi@0: /** aoqi@0: * The vocabulary table index of identifying string or the identifier of aoqi@0: * an encoding algorithm or restricted alphabet. aoqi@0: */ aoqi@0: protected int _identifier; aoqi@0: aoqi@0: /** aoqi@0: * The size of the internal buffer. aoqi@0: */ aoqi@0: protected int _bufferSize = _bufferSizeSystemDefault; aoqi@0: aoqi@0: /** aoqi@0: * The internal buffer used for decoding. aoqi@0: */ aoqi@0: protected byte[] _octetBuffer = new byte[_bufferSizeSystemDefault]; aoqi@0: aoqi@0: /** aoqi@0: * A mark into the internal buffer used for decoding encoded algorithm aoqi@0: * or restricted alphabet data. aoqi@0: */ aoqi@0: protected int _octetBufferStart; aoqi@0: aoqi@0: /** aoqi@0: * The offset into the buffer to read the next byte. aoqi@0: */ aoqi@0: protected int _octetBufferOffset; aoqi@0: aoqi@0: /** aoqi@0: * The end of the buffer. aoqi@0: */ aoqi@0: protected int _octetBufferEnd; aoqi@0: aoqi@0: /** aoqi@0: * The length of some octets in the buffer that are to be read. aoqi@0: */ aoqi@0: protected int _octetBufferLength; aoqi@0: aoqi@0: /** aoqi@0: * The internal buffer of characters. aoqi@0: */ aoqi@0: protected char[] _charBuffer = new char[512]; aoqi@0: aoqi@0: /** aoqi@0: * The length of characters in the buffer of characters. aoqi@0: */ aoqi@0: protected int _charBufferLength; aoqi@0: aoqi@0: /** aoqi@0: * Helper class that checks for duplicate attribute information items. aoqi@0: */ aoqi@0: protected DuplicateAttributeVerifier _duplicateAttributeVerifier = new DuplicateAttributeVerifier(); aoqi@0: aoqi@0: /** aoqi@0: * Default constructor for the Decoder. aoqi@0: */ aoqi@0: protected Decoder() { aoqi@0: _v = new ParserVocabulary(); aoqi@0: _prefixTable = _v.prefix; aoqi@0: _elementNameTable = _v.elementName; aoqi@0: _attributeNameTable = _v.attributeName; aoqi@0: _characterContentChunkTable = _v.characterContentChunk; aoqi@0: _attributeValueTable = _v.attributeValue; aoqi@0: _vIsInternal = true; aoqi@0: } aoqi@0: aoqi@0: aoqi@0: // FastInfosetParser interface aoqi@0: aoqi@0: /** aoqi@0: * {@inheritDoc} aoqi@0: */ aoqi@0: public void setStringInterning(boolean stringInterning) { aoqi@0: _stringInterning = stringInterning; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * {@inheritDoc} aoqi@0: */ aoqi@0: public boolean getStringInterning() { aoqi@0: return _stringInterning; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * {@inheritDoc} aoqi@0: */ aoqi@0: public void setBufferSize(int bufferSize) { aoqi@0: if (_bufferSize > _octetBuffer.length) { aoqi@0: _bufferSize = bufferSize; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * {@inheritDoc} aoqi@0: */ aoqi@0: public int getBufferSize() { aoqi@0: return _bufferSize; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * {@inheritDoc} aoqi@0: */ aoqi@0: public void setRegisteredEncodingAlgorithms(Map algorithms) { aoqi@0: _registeredEncodingAlgorithms = algorithms; aoqi@0: if (_registeredEncodingAlgorithms == null) { aoqi@0: _registeredEncodingAlgorithms = new HashMap(); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * {@inheritDoc} aoqi@0: */ aoqi@0: public Map getRegisteredEncodingAlgorithms() { aoqi@0: return _registeredEncodingAlgorithms; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * {@inheritDoc} aoqi@0: */ aoqi@0: public void setExternalVocabularies(Map referencedVocabualries) { aoqi@0: if (referencedVocabualries != null) { aoqi@0: // Clone the input map aoqi@0: _externalVocabularies = new HashMap(); aoqi@0: _externalVocabularies.putAll(referencedVocabualries); aoqi@0: } else { aoqi@0: _externalVocabularies = null; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * {@inheritDoc} aoqi@0: */ aoqi@0: public Map getExternalVocabularies() { aoqi@0: return _externalVocabularies; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * {@inheritDoc} aoqi@0: */ aoqi@0: public void setParseFragments(boolean parseFragments) { aoqi@0: _parseFragments = parseFragments; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * {@inheritDoc} aoqi@0: */ aoqi@0: public boolean getParseFragments() { aoqi@0: return _parseFragments; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * {@inheritDoc} aoqi@0: */ aoqi@0: public void setForceStreamClose(boolean needForceStreamClose) { aoqi@0: _needForceStreamClose = needForceStreamClose; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * {@inheritDoc} aoqi@0: */ aoqi@0: public boolean getForceStreamClose() { aoqi@0: return _needForceStreamClose; aoqi@0: } aoqi@0: aoqi@0: // End FastInfosetParser interface aoqi@0: aoqi@0: /** aoqi@0: * Reset the decoder for reuse decoding another XML infoset. aoqi@0: */ aoqi@0: public void reset() { aoqi@0: _terminate = _doubleTerminate = false; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Set the ParserVocabulary to be used for decoding. aoqi@0: * aoqi@0: * @param v the vocabulary to be used for decoding. aoqi@0: */ aoqi@0: public void setVocabulary(ParserVocabulary v) { aoqi@0: _v = v; aoqi@0: _prefixTable = _v.prefix; aoqi@0: _elementNameTable = _v.elementName; aoqi@0: _attributeNameTable = _v.attributeName; aoqi@0: _characterContentChunkTable = _v.characterContentChunk; aoqi@0: _attributeValueTable = _v.attributeValue; aoqi@0: _vIsInternal = false; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Set the InputStream to decode the fast infoset document. aoqi@0: * aoqi@0: * @param s the InputStream where the fast infoset document is decoded from. aoqi@0: */ aoqi@0: public void setInputStream(InputStream s) { aoqi@0: _s = s; aoqi@0: _octetBufferOffset = 0; aoqi@0: _octetBufferEnd = 0; aoqi@0: if (_vIsInternal == true) { aoqi@0: _v.clear(); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: protected final void decodeDII() throws FastInfosetException, IOException { aoqi@0: final int b = read(); aoqi@0: if (b == EncodingConstants.DOCUMENT_INITIAL_VOCABULARY_FLAG) { aoqi@0: decodeInitialVocabulary(); aoqi@0: } else if (b != 0) { aoqi@0: throw new IOException(CommonResourceBundle.getInstance(). aoqi@0: getString("message.optinalValues")); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: protected final void decodeAdditionalData() throws FastInfosetException, IOException { aoqi@0: final int noOfItems = decodeNumberOfItemsOfSequence(); aoqi@0: aoqi@0: for (int i = 0; i < noOfItems; i++) { aoqi@0: /*String URI = */decodeNonEmptyOctetStringOnSecondBitAsUtf8String(); aoqi@0: aoqi@0: decodeNonEmptyOctetStringLengthOnSecondBit(); aoqi@0: ensureOctetBufferSize(); aoqi@0: _octetBufferStart = _octetBufferOffset; aoqi@0: _octetBufferOffset += _octetBufferLength; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: protected final void decodeInitialVocabulary() throws FastInfosetException, IOException { aoqi@0: // First 5 optionals of 13 bit optional field aoqi@0: int b = read(); aoqi@0: // Next 8 optionals of 13 bit optional field aoqi@0: int b2 = read(); aoqi@0: aoqi@0: // Optimize for the most common case aoqi@0: if (b == EncodingConstants.INITIAL_VOCABULARY_EXTERNAL_VOCABULARY_FLAG && b2 == 0) { aoqi@0: decodeExternalVocabularyURI(); aoqi@0: return; aoqi@0: } aoqi@0: aoqi@0: if ((b & EncodingConstants.INITIAL_VOCABULARY_EXTERNAL_VOCABULARY_FLAG) > 0) { aoqi@0: decodeExternalVocabularyURI(); aoqi@0: } aoqi@0: aoqi@0: if ((b & EncodingConstants.INITIAL_VOCABULARY_RESTRICTED_ALPHABETS_FLAG) > 0) { aoqi@0: decodeTableItems(_v.restrictedAlphabet); aoqi@0: } aoqi@0: aoqi@0: if ((b & EncodingConstants.INITIAL_VOCABULARY_ENCODING_ALGORITHMS_FLAG) > 0) { aoqi@0: decodeTableItems(_v.encodingAlgorithm); aoqi@0: } aoqi@0: aoqi@0: if ((b & EncodingConstants.INITIAL_VOCABULARY_PREFIXES_FLAG) > 0) { aoqi@0: decodeTableItems(_v.prefix); aoqi@0: } aoqi@0: aoqi@0: if ((b & EncodingConstants.INITIAL_VOCABULARY_NAMESPACE_NAMES_FLAG) > 0) { aoqi@0: decodeTableItems(_v.namespaceName); aoqi@0: } aoqi@0: aoqi@0: if ((b2 & EncodingConstants.INITIAL_VOCABULARY_LOCAL_NAMES_FLAG) > 0) { aoqi@0: decodeTableItems(_v.localName); aoqi@0: } aoqi@0: aoqi@0: if ((b2 & EncodingConstants.INITIAL_VOCABULARY_OTHER_NCNAMES_FLAG) > 0) { aoqi@0: decodeTableItems(_v.otherNCName); aoqi@0: } aoqi@0: aoqi@0: if ((b2 & EncodingConstants.INITIAL_VOCABULARY_OTHER_URIS_FLAG) > 0) { aoqi@0: decodeTableItems(_v.otherURI); aoqi@0: } aoqi@0: aoqi@0: if ((b2 & EncodingConstants.INITIAL_VOCABULARY_ATTRIBUTE_VALUES_FLAG) > 0) { aoqi@0: decodeTableItems(_v.attributeValue); aoqi@0: } aoqi@0: aoqi@0: if ((b2 & EncodingConstants.INITIAL_VOCABULARY_CONTENT_CHARACTER_CHUNKS_FLAG) > 0) { aoqi@0: decodeTableItems(_v.characterContentChunk); aoqi@0: } aoqi@0: aoqi@0: if ((b2 & EncodingConstants.INITIAL_VOCABULARY_OTHER_STRINGS_FLAG) > 0) { aoqi@0: decodeTableItems(_v.otherString); aoqi@0: } aoqi@0: aoqi@0: if ((b2 & EncodingConstants.INITIAL_VOCABULARY_ELEMENT_NAME_SURROGATES_FLAG) > 0) { aoqi@0: decodeTableItems(_v.elementName, false); aoqi@0: } aoqi@0: aoqi@0: if ((b2 & EncodingConstants.INITIAL_VOCABULARY_ATTRIBUTE_NAME_SURROGATES_FLAG) > 0) { aoqi@0: decodeTableItems(_v.attributeName, true); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: private void decodeExternalVocabularyURI() throws FastInfosetException, IOException { aoqi@0: if (_externalVocabularies == null) { aoqi@0: throw new IOException(CommonResourceBundle. aoqi@0: getInstance().getString("message.noExternalVocabularies")); aoqi@0: } aoqi@0: aoqi@0: String externalVocabularyURI = aoqi@0: decodeNonEmptyOctetStringOnSecondBitAsUtf8String(); aoqi@0: aoqi@0: Object o = _externalVocabularies.get(externalVocabularyURI); aoqi@0: if (o instanceof ParserVocabulary) { aoqi@0: _v.setReferencedVocabulary(externalVocabularyURI, aoqi@0: (ParserVocabulary)o, false); aoqi@0: } else if (o instanceof com.sun.xml.internal.org.jvnet.fastinfoset.ExternalVocabulary) { aoqi@0: com.sun.xml.internal.org.jvnet.fastinfoset.ExternalVocabulary v = aoqi@0: (com.sun.xml.internal.org.jvnet.fastinfoset.ExternalVocabulary)o; aoqi@0: ParserVocabulary pv = new ParserVocabulary(v.vocabulary); aoqi@0: aoqi@0: _externalVocabularies.put(externalVocabularyURI, pv); aoqi@0: _v.setReferencedVocabulary(externalVocabularyURI, aoqi@0: pv, false); aoqi@0: } else { aoqi@0: throw new FastInfosetException(CommonResourceBundle.getInstance(). aoqi@0: getString("message.externalVocabularyNotRegistered", aoqi@0: new Object[]{externalVocabularyURI})); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: private void decodeTableItems(StringArray array) throws FastInfosetException, IOException { aoqi@0: final int noOfItems = decodeNumberOfItemsOfSequence(); aoqi@0: aoqi@0: for (int i = 0; i < noOfItems; i++) { aoqi@0: array.add(decodeNonEmptyOctetStringOnSecondBitAsUtf8String()); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: private void decodeTableItems(PrefixArray array) throws FastInfosetException, IOException { aoqi@0: final int noOfItems = decodeNumberOfItemsOfSequence(); aoqi@0: aoqi@0: for (int i = 0; i < noOfItems; i++) { aoqi@0: array.add(decodeNonEmptyOctetStringOnSecondBitAsUtf8String()); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: private void decodeTableItems(ContiguousCharArrayArray array) throws FastInfosetException, IOException { aoqi@0: final int noOfItems = decodeNumberOfItemsOfSequence(); aoqi@0: aoqi@0: for (int i = 0; i < noOfItems; i++) { aoqi@0: switch(decodeNonIdentifyingStringOnFirstBit()) { aoqi@0: case NISTRING_STRING: aoqi@0: array.add(_charBuffer, _charBufferLength); aoqi@0: break; aoqi@0: default: aoqi@0: throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.illegalState")); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: private void decodeTableItems(CharArrayArray array) throws FastInfosetException, IOException { aoqi@0: final int noOfItems = decodeNumberOfItemsOfSequence(); aoqi@0: aoqi@0: for (int i = 0; i < noOfItems; i++) { aoqi@0: switch(decodeNonIdentifyingStringOnFirstBit()) { aoqi@0: case NISTRING_STRING: aoqi@0: array.add(new CharArray(_charBuffer, 0, _charBufferLength, true)); aoqi@0: break; aoqi@0: default: aoqi@0: throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.illegalState")); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: private void decodeTableItems(QualifiedNameArray array, boolean isAttribute) throws FastInfosetException, IOException { aoqi@0: final int noOfItems = decodeNumberOfItemsOfSequence(); aoqi@0: aoqi@0: for (int i = 0; i < noOfItems; i++) { aoqi@0: final int b = read(); aoqi@0: aoqi@0: String prefix = ""; aoqi@0: int prefixIndex = -1; aoqi@0: if ((b & EncodingConstants.NAME_SURROGATE_PREFIX_FLAG) > 0) { aoqi@0: prefixIndex = decodeIntegerIndexOnSecondBit(); aoqi@0: prefix = _v.prefix.get(prefixIndex); aoqi@0: } aoqi@0: aoqi@0: String namespaceName = ""; aoqi@0: int namespaceNameIndex = -1; aoqi@0: if ((b & EncodingConstants.NAME_SURROGATE_NAME_FLAG) > 0) { aoqi@0: namespaceNameIndex = decodeIntegerIndexOnSecondBit(); aoqi@0: namespaceName = _v.namespaceName.get(namespaceNameIndex); aoqi@0: } aoqi@0: aoqi@0: if (namespaceName == "" && prefix != "") { aoqi@0: throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.missingNamespace")); aoqi@0: } aoqi@0: aoqi@0: final int localNameIndex = decodeIntegerIndexOnSecondBit(); aoqi@0: final String localName = _v.localName.get(localNameIndex); aoqi@0: aoqi@0: QualifiedName qualifiedName = new QualifiedName(prefix, namespaceName, localName, aoqi@0: prefixIndex, namespaceNameIndex, localNameIndex, aoqi@0: _charBuffer); aoqi@0: if (isAttribute) { aoqi@0: qualifiedName.createAttributeValues(DuplicateAttributeVerifier.MAP_SIZE); aoqi@0: } aoqi@0: array.add(qualifiedName); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: private int decodeNumberOfItemsOfSequence() throws IOException { aoqi@0: final int b = read(); aoqi@0: if (b < 128) { aoqi@0: return b + 1; aoqi@0: } else { aoqi@0: return (((b & 0x0F) << 16) | (read() << 8) | read()) + 129; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: protected final void decodeNotations() throws FastInfosetException, IOException { aoqi@0: if (_notations == null) { aoqi@0: _notations = new ArrayList(); aoqi@0: } else { aoqi@0: _notations.clear(); aoqi@0: } aoqi@0: aoqi@0: int b = read(); aoqi@0: while ((b & EncodingConstants.NOTATIONS_MASK) == EncodingConstants.NOTATIONS) { aoqi@0: String name = decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherNCName); aoqi@0: aoqi@0: String system_identifier = ((_b & EncodingConstants.NOTATIONS_SYSTEM_IDENTIFIER_FLAG) > 0) aoqi@0: ? decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherURI) : ""; aoqi@0: String public_identifier = ((_b & EncodingConstants.NOTATIONS_PUBLIC_IDENTIFIER_FLAG) > 0) aoqi@0: ? decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherURI) : ""; aoqi@0: aoqi@0: Notation notation = new Notation(name, system_identifier, public_identifier); aoqi@0: _notations.add(notation); aoqi@0: aoqi@0: b = read(); aoqi@0: } aoqi@0: if (b != EncodingConstants.TERMINATOR) { aoqi@0: throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.IIsNotTerminatedCorrectly")); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: protected final void decodeUnparsedEntities() throws FastInfosetException, IOException { aoqi@0: if (_unparsedEntities == null) { aoqi@0: _unparsedEntities = new ArrayList(); aoqi@0: } else { aoqi@0: _unparsedEntities.clear(); aoqi@0: } aoqi@0: aoqi@0: int b = read(); aoqi@0: while ((b & EncodingConstants.UNPARSED_ENTITIES_MASK) == EncodingConstants.UNPARSED_ENTITIES) { aoqi@0: String name = decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherNCName); aoqi@0: String system_identifier = decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherURI); aoqi@0: aoqi@0: String public_identifier = ((_b & EncodingConstants.UNPARSED_ENTITIES_PUBLIC_IDENTIFIER_FLAG) > 0) aoqi@0: ? decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherURI) : ""; aoqi@0: aoqi@0: String notation_name = decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherNCName); aoqi@0: aoqi@0: UnparsedEntity unparsedEntity = new UnparsedEntity(name, system_identifier, public_identifier, notation_name); aoqi@0: _unparsedEntities.add(unparsedEntity); aoqi@0: aoqi@0: b = read(); aoqi@0: } aoqi@0: if (b != EncodingConstants.TERMINATOR) { aoqi@0: throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.unparsedEntities")); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: protected final String decodeCharacterEncodingScheme() throws FastInfosetException, IOException { aoqi@0: return decodeNonEmptyOctetStringOnSecondBitAsUtf8String(); aoqi@0: } aoqi@0: aoqi@0: protected final String decodeVersion() throws FastInfosetException, IOException { aoqi@0: switch(decodeNonIdentifyingStringOnFirstBit()) { aoqi@0: case NISTRING_STRING: aoqi@0: final String data = new String(_charBuffer, 0, _charBufferLength); aoqi@0: if (_addToTable) { aoqi@0: _v.otherString.add(new CharArrayString(data)); aoqi@0: } aoqi@0: return data; aoqi@0: case NISTRING_ENCODING_ALGORITHM: aoqi@0: throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.decodingNotSupported")); aoqi@0: case NISTRING_INDEX: aoqi@0: return _v.otherString.get(_integer).toString(); aoqi@0: case NISTRING_EMPTY_STRING: aoqi@0: default: aoqi@0: return ""; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: protected final QualifiedName decodeEIIIndexMedium() throws FastInfosetException, IOException { aoqi@0: final int i = (((_b & EncodingConstants.INTEGER_3RD_BIT_MEDIUM_MASK) << 8) | read()) aoqi@0: + EncodingConstants.INTEGER_3RD_BIT_SMALL_LIMIT; aoqi@0: return _v.elementName._array[i]; aoqi@0: } aoqi@0: aoqi@0: protected final QualifiedName decodeEIIIndexLarge() throws FastInfosetException, IOException { aoqi@0: int i; aoqi@0: if ((_b & EncodingConstants.INTEGER_3RD_BIT_LARGE_LARGE_FLAG) == 0x20) { aoqi@0: // EII large index aoqi@0: i = (((_b & EncodingConstants.INTEGER_3RD_BIT_LARGE_MASK) << 16) | (read() << 8) | read()) aoqi@0: + EncodingConstants.INTEGER_3RD_BIT_MEDIUM_LIMIT; aoqi@0: } else { aoqi@0: // EII large large index aoqi@0: i = (((read() & EncodingConstants.INTEGER_3RD_BIT_LARGE_LARGE_MASK) << 16) | (read() << 8) | read()) aoqi@0: + EncodingConstants.INTEGER_3RD_BIT_LARGE_LIMIT; aoqi@0: } aoqi@0: return _v.elementName._array[i]; aoqi@0: } aoqi@0: aoqi@0: protected final QualifiedName decodeLiteralQualifiedName(int state, QualifiedName q) aoqi@0: throws FastInfosetException, IOException { aoqi@0: if (q == null) q = new QualifiedName(); aoqi@0: switch (state) { aoqi@0: // no prefix, no namespace aoqi@0: case 0: aoqi@0: return q.set( aoqi@0: "", aoqi@0: "", aoqi@0: decodeIdentifyingNonEmptyStringOnFirstBit(_v.localName), aoqi@0: -1, aoqi@0: -1, aoqi@0: _identifier, aoqi@0: null); aoqi@0: // no prefix, namespace aoqi@0: case 1: aoqi@0: return q.set( aoqi@0: "", aoqi@0: decodeIdentifyingNonEmptyStringIndexOnFirstBitAsNamespaceName(false), aoqi@0: decodeIdentifyingNonEmptyStringOnFirstBit(_v.localName), aoqi@0: -1, aoqi@0: _namespaceNameIndex, aoqi@0: _identifier, aoqi@0: null); aoqi@0: // prefix, no namespace aoqi@0: case 2: aoqi@0: throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.qNameMissingNamespaceName")); aoqi@0: // prefix, namespace aoqi@0: case 3: aoqi@0: return q.set( aoqi@0: decodeIdentifyingNonEmptyStringIndexOnFirstBitAsPrefix(true), aoqi@0: decodeIdentifyingNonEmptyStringIndexOnFirstBitAsNamespaceName(true), aoqi@0: decodeIdentifyingNonEmptyStringOnFirstBit(_v.localName), aoqi@0: _prefixIndex, aoqi@0: _namespaceNameIndex, aoqi@0: _identifier, aoqi@0: _charBuffer); aoqi@0: default: aoqi@0: throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.decodingEII")); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: protected static final int NISTRING_STRING = 0; aoqi@0: protected static final int NISTRING_INDEX = 1; aoqi@0: protected static final int NISTRING_ENCODING_ALGORITHM = 2; aoqi@0: protected static final int NISTRING_EMPTY_STRING = 3; aoqi@0: aoqi@0: /* aoqi@0: * C.14 aoqi@0: * decodeNonIdentifyingStringOnFirstBit aoqi@0: */ aoqi@0: protected final int decodeNonIdentifyingStringOnFirstBit() throws FastInfosetException, IOException { aoqi@0: final int b = read(); aoqi@0: switch(DecoderStateTables.NISTRING(b)) { aoqi@0: case DecoderStateTables.NISTRING_UTF8_SMALL_LENGTH: aoqi@0: _addToTable = (b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0; aoqi@0: _octetBufferLength = (b & EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_SMALL_MASK) + 1; aoqi@0: decodeUtf8StringAsCharBuffer(); aoqi@0: return NISTRING_STRING; aoqi@0: case DecoderStateTables.NISTRING_UTF8_MEDIUM_LENGTH: aoqi@0: _addToTable = (b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0; aoqi@0: _octetBufferLength = read() + EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_SMALL_LIMIT; aoqi@0: decodeUtf8StringAsCharBuffer(); aoqi@0: return NISTRING_STRING; aoqi@0: case DecoderStateTables.NISTRING_UTF8_LARGE_LENGTH: aoqi@0: { aoqi@0: _addToTable = (b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0; aoqi@0: final int length = (read() << 24) | aoqi@0: (read() << 16) | aoqi@0: (read() << 8) | aoqi@0: read(); aoqi@0: _octetBufferLength = length + EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_MEDIUM_LIMIT; aoqi@0: decodeUtf8StringAsCharBuffer(); aoqi@0: return NISTRING_STRING; aoqi@0: } aoqi@0: case DecoderStateTables.NISTRING_UTF16_SMALL_LENGTH: aoqi@0: _addToTable = (b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0; aoqi@0: _octetBufferLength = (b & EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_SMALL_MASK) + 1; aoqi@0: decodeUtf16StringAsCharBuffer(); aoqi@0: return NISTRING_STRING; aoqi@0: case DecoderStateTables.NISTRING_UTF16_MEDIUM_LENGTH: aoqi@0: _addToTable = (b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0; aoqi@0: _octetBufferLength = read() + EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_SMALL_LIMIT; aoqi@0: decodeUtf16StringAsCharBuffer(); aoqi@0: return NISTRING_STRING; aoqi@0: case DecoderStateTables.NISTRING_UTF16_LARGE_LENGTH: aoqi@0: { aoqi@0: _addToTable = (b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0; aoqi@0: final int length = (read() << 24) | aoqi@0: (read() << 16) | aoqi@0: (read() << 8) | aoqi@0: read(); aoqi@0: _octetBufferLength = length + EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_MEDIUM_LIMIT; aoqi@0: decodeUtf16StringAsCharBuffer(); aoqi@0: return NISTRING_STRING; aoqi@0: } aoqi@0: case DecoderStateTables.NISTRING_RA: aoqi@0: { aoqi@0: _addToTable = (b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0; aoqi@0: // Decode resitricted alphabet integer aoqi@0: _identifier = (b & 0x0F) << 4; aoqi@0: final int b2 = read(); aoqi@0: _identifier |= (b2 & 0xF0) >> 4; aoqi@0: aoqi@0: decodeOctetsOnFifthBitOfNonIdentifyingStringOnFirstBit(b2); aoqi@0: aoqi@0: decodeRestrictedAlphabetAsCharBuffer(); aoqi@0: return NISTRING_STRING; aoqi@0: } aoqi@0: case DecoderStateTables.NISTRING_EA: aoqi@0: { aoqi@0: _addToTable = (b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0; aoqi@0: // Decode encoding algorithm integer aoqi@0: _identifier = (b & 0x0F) << 4; aoqi@0: final int b2 = read(); aoqi@0: _identifier |= (b2 & 0xF0) >> 4; aoqi@0: aoqi@0: decodeOctetsOnFifthBitOfNonIdentifyingStringOnFirstBit(b2); aoqi@0: return NISTRING_ENCODING_ALGORITHM; aoqi@0: } aoqi@0: case DecoderStateTables.NISTRING_INDEX_SMALL: aoqi@0: _integer = b & EncodingConstants.INTEGER_2ND_BIT_SMALL_MASK; aoqi@0: return NISTRING_INDEX; aoqi@0: case DecoderStateTables.NISTRING_INDEX_MEDIUM: aoqi@0: _integer = (((b & EncodingConstants.INTEGER_2ND_BIT_MEDIUM_MASK) << 8) | read()) aoqi@0: + EncodingConstants.INTEGER_2ND_BIT_SMALL_LIMIT; aoqi@0: return NISTRING_INDEX; aoqi@0: case DecoderStateTables.NISTRING_INDEX_LARGE: aoqi@0: _integer = (((b & EncodingConstants.INTEGER_2ND_BIT_LARGE_MASK) << 16) | (read() << 8) | read()) aoqi@0: + EncodingConstants.INTEGER_2ND_BIT_MEDIUM_LIMIT; aoqi@0: return NISTRING_INDEX; aoqi@0: case DecoderStateTables.NISTRING_EMPTY: aoqi@0: return NISTRING_EMPTY_STRING; aoqi@0: default: aoqi@0: throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.decodingNonIdentifyingString")); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: protected final void decodeOctetsOnFifthBitOfNonIdentifyingStringOnFirstBit(int b) throws FastInfosetException, IOException { aoqi@0: // Remove top 4 bits of restricted alphabet or encoding algorithm integer aoqi@0: b &= 0x0F; aoqi@0: // Reuse UTF8 length states aoqi@0: switch(DecoderStateTables.NISTRING(b)) { aoqi@0: case DecoderStateTables.NISTRING_UTF8_SMALL_LENGTH: aoqi@0: _octetBufferLength = b + 1; aoqi@0: break; aoqi@0: case DecoderStateTables.NISTRING_UTF8_MEDIUM_LENGTH: aoqi@0: _octetBufferLength = read() + EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_SMALL_LIMIT; aoqi@0: break; aoqi@0: case DecoderStateTables.NISTRING_UTF8_LARGE_LENGTH: aoqi@0: final int length = (read() << 24) | aoqi@0: (read() << 16) | aoqi@0: (read() << 8) | aoqi@0: read(); aoqi@0: _octetBufferLength = length + EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_MEDIUM_LIMIT; aoqi@0: break; aoqi@0: default: aoqi@0: throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.decodingOctets")); aoqi@0: } aoqi@0: ensureOctetBufferSize(); aoqi@0: _octetBufferStart = _octetBufferOffset; aoqi@0: _octetBufferOffset += _octetBufferLength; aoqi@0: } aoqi@0: aoqi@0: protected final void decodeOctetsOnSeventhBitOfNonIdentifyingStringOnThirdBit(int b) throws FastInfosetException, IOException { aoqi@0: // Remove top 6 bits of restricted alphabet or encoding algorithm integer aoqi@0: switch (b & 0x03) { aoqi@0: // Small length aoqi@0: case 0: aoqi@0: _octetBufferLength = 1; aoqi@0: break; aoqi@0: // Small length aoqi@0: case 1: aoqi@0: _octetBufferLength = 2; aoqi@0: break; aoqi@0: // Medium length aoqi@0: case 2: aoqi@0: _octetBufferLength = read() + EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_SMALL_LIMIT; aoqi@0: break; aoqi@0: // Large length aoqi@0: case 3: aoqi@0: _octetBufferLength = (read() << 24) | aoqi@0: (read() << 16) | aoqi@0: (read() << 8) | aoqi@0: read(); aoqi@0: _octetBufferLength += EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_MEDIUM_LIMIT; aoqi@0: break; aoqi@0: } aoqi@0: aoqi@0: ensureOctetBufferSize(); aoqi@0: _octetBufferStart = _octetBufferOffset; aoqi@0: _octetBufferOffset += _octetBufferLength; aoqi@0: } aoqi@0: aoqi@0: /* aoqi@0: * C.13 aoqi@0: */ aoqi@0: protected final String decodeIdentifyingNonEmptyStringOnFirstBit(StringArray table) throws FastInfosetException, IOException { aoqi@0: final int b = read(); aoqi@0: switch(DecoderStateTables.ISTRING(b)) { aoqi@0: case DecoderStateTables.ISTRING_SMALL_LENGTH: aoqi@0: { aoqi@0: _octetBufferLength = b + 1; aoqi@0: final String s = (_stringInterning) ? decodeUtf8StringAsString().intern() : decodeUtf8StringAsString(); aoqi@0: _identifier = table.add(s) - 1; aoqi@0: return s; aoqi@0: } aoqi@0: case DecoderStateTables.ISTRING_MEDIUM_LENGTH: aoqi@0: { aoqi@0: _octetBufferLength = read() + EncodingConstants.OCTET_STRING_LENGTH_2ND_BIT_SMALL_LIMIT; aoqi@0: final String s = (_stringInterning) ? decodeUtf8StringAsString().intern() : decodeUtf8StringAsString(); aoqi@0: _identifier = table.add(s) - 1; aoqi@0: return s; aoqi@0: } aoqi@0: case DecoderStateTables.ISTRING_LARGE_LENGTH: aoqi@0: { aoqi@0: final int length = (read() << 24) | aoqi@0: (read() << 16) | aoqi@0: (read() << 8) | aoqi@0: read(); aoqi@0: _octetBufferLength = length + EncodingConstants.OCTET_STRING_LENGTH_2ND_BIT_MEDIUM_LIMIT; aoqi@0: final String s = (_stringInterning) ? decodeUtf8StringAsString().intern() : decodeUtf8StringAsString(); aoqi@0: _identifier = table.add(s) - 1; aoqi@0: return s; aoqi@0: } aoqi@0: case DecoderStateTables.ISTRING_INDEX_SMALL: aoqi@0: _identifier = b & EncodingConstants.INTEGER_2ND_BIT_SMALL_MASK; aoqi@0: return table._array[_identifier]; aoqi@0: case DecoderStateTables.ISTRING_INDEX_MEDIUM: aoqi@0: _identifier = (((b & EncodingConstants.INTEGER_2ND_BIT_MEDIUM_MASK) << 8) | read()) aoqi@0: + EncodingConstants.INTEGER_2ND_BIT_SMALL_LIMIT; aoqi@0: return table._array[_identifier]; aoqi@0: case DecoderStateTables.ISTRING_INDEX_LARGE: aoqi@0: _identifier = (((b & EncodingConstants.INTEGER_2ND_BIT_LARGE_MASK) << 16) | (read() << 8) | read()) aoqi@0: + EncodingConstants.INTEGER_2ND_BIT_MEDIUM_LIMIT; aoqi@0: return table._array[_identifier]; aoqi@0: default: aoqi@0: throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.decodingIdentifyingString")); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: protected int _prefixIndex; aoqi@0: aoqi@0: /* aoqi@0: * C.13 aoqi@0: */ aoqi@0: protected final String decodeIdentifyingNonEmptyStringOnFirstBitAsPrefix(boolean namespaceNamePresent) throws FastInfosetException, IOException { aoqi@0: final int b = read(); aoqi@0: switch(DecoderStateTables.ISTRING_PREFIX_NAMESPACE(b)) { aoqi@0: case DecoderStateTables.ISTRING_PREFIX_NAMESPACE_LENGTH_3: aoqi@0: { aoqi@0: _octetBufferLength = EncodingConstants.XML_NAMESPACE_PREFIX_LENGTH; aoqi@0: decodeUtf8StringAsCharBuffer(); aoqi@0: aoqi@0: if (_charBuffer[0] == 'x' && aoqi@0: _charBuffer[1] == 'm' && aoqi@0: _charBuffer[2] == 'l') { aoqi@0: throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.prefixIllegal")); aoqi@0: } aoqi@0: aoqi@0: final String s = (_stringInterning) ? new String(_charBuffer, 0, _charBufferLength).intern() : aoqi@0: new String(_charBuffer, 0, _charBufferLength); aoqi@0: _prefixIndex = _v.prefix.add(s); aoqi@0: return s; aoqi@0: } aoqi@0: case DecoderStateTables.ISTRING_PREFIX_NAMESPACE_LENGTH_5: aoqi@0: { aoqi@0: _octetBufferLength = EncodingConstants.XMLNS_NAMESPACE_PREFIX_LENGTH; aoqi@0: decodeUtf8StringAsCharBuffer(); aoqi@0: aoqi@0: if (_charBuffer[0] == 'x' && aoqi@0: _charBuffer[1] == 'm' && aoqi@0: _charBuffer[2] == 'l' && aoqi@0: _charBuffer[3] == 'n' && aoqi@0: _charBuffer[4] == 's') { aoqi@0: throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.xmlns")); aoqi@0: } aoqi@0: aoqi@0: final String s = (_stringInterning) ? new String(_charBuffer, 0, _charBufferLength).intern() : aoqi@0: new String(_charBuffer, 0, _charBufferLength); aoqi@0: _prefixIndex = _v.prefix.add(s); aoqi@0: return s; aoqi@0: } aoqi@0: case DecoderStateTables.ISTRING_SMALL_LENGTH: aoqi@0: case DecoderStateTables.ISTRING_PREFIX_NAMESPACE_LENGTH_29: aoqi@0: case DecoderStateTables.ISTRING_PREFIX_NAMESPACE_LENGTH_36: aoqi@0: { aoqi@0: _octetBufferLength = b + 1; aoqi@0: final String s = (_stringInterning) ? decodeUtf8StringAsString().intern() : decodeUtf8StringAsString(); aoqi@0: _prefixIndex = _v.prefix.add(s); aoqi@0: return s; aoqi@0: } aoqi@0: case DecoderStateTables.ISTRING_MEDIUM_LENGTH: aoqi@0: { aoqi@0: _octetBufferLength = read() + EncodingConstants.OCTET_STRING_LENGTH_2ND_BIT_SMALL_LIMIT; aoqi@0: final String s = (_stringInterning) ? decodeUtf8StringAsString().intern() : decodeUtf8StringAsString(); aoqi@0: _prefixIndex = _v.prefix.add(s); aoqi@0: return s; aoqi@0: } aoqi@0: case DecoderStateTables.ISTRING_LARGE_LENGTH: aoqi@0: { aoqi@0: final int length = (read() << 24) | aoqi@0: (read() << 16) | aoqi@0: (read() << 8) | aoqi@0: read(); aoqi@0: _octetBufferLength = length + EncodingConstants.OCTET_STRING_LENGTH_2ND_BIT_MEDIUM_LIMIT; aoqi@0: final String s = (_stringInterning) ? decodeUtf8StringAsString().intern() : decodeUtf8StringAsString(); aoqi@0: _prefixIndex = _v.prefix.add(s); aoqi@0: return s; aoqi@0: } aoqi@0: case DecoderStateTables.ISTRING_PREFIX_NAMESPACE_INDEX_ZERO: aoqi@0: if (namespaceNamePresent) { aoqi@0: _prefixIndex = 0; aoqi@0: // Peak at next byte and check the index of the XML namespace name aoqi@0: if (DecoderStateTables.ISTRING_PREFIX_NAMESPACE(peek()) aoqi@0: != DecoderStateTables.ISTRING_PREFIX_NAMESPACE_INDEX_ZERO) { aoqi@0: throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.wrongNamespaceName")); aoqi@0: } aoqi@0: return EncodingConstants.XML_NAMESPACE_PREFIX; aoqi@0: } else { aoqi@0: throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.missingNamespaceName")); aoqi@0: } aoqi@0: case DecoderStateTables.ISTRING_INDEX_SMALL: aoqi@0: _prefixIndex = b & EncodingConstants.INTEGER_2ND_BIT_SMALL_MASK; aoqi@0: return _v.prefix._array[_prefixIndex - 1]; aoqi@0: case DecoderStateTables.ISTRING_INDEX_MEDIUM: aoqi@0: _prefixIndex = (((b & EncodingConstants.INTEGER_2ND_BIT_MEDIUM_MASK) << 8) | read()) aoqi@0: + EncodingConstants.INTEGER_2ND_BIT_SMALL_LIMIT; aoqi@0: return _v.prefix._array[_prefixIndex - 1]; aoqi@0: case DecoderStateTables.ISTRING_INDEX_LARGE: aoqi@0: _prefixIndex = (((b & EncodingConstants.INTEGER_2ND_BIT_LARGE_MASK) << 16) | (read() << 8) | read()) aoqi@0: + EncodingConstants.INTEGER_2ND_BIT_MEDIUM_LIMIT; aoqi@0: return _v.prefix._array[_prefixIndex - 1]; aoqi@0: default: aoqi@0: throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.decodingIdentifyingStringForPrefix")); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: /* aoqi@0: * C.13 aoqi@0: */ aoqi@0: protected final String decodeIdentifyingNonEmptyStringIndexOnFirstBitAsPrefix(boolean namespaceNamePresent) throws FastInfosetException, IOException { aoqi@0: final int b = read(); aoqi@0: switch(DecoderStateTables.ISTRING_PREFIX_NAMESPACE(b)) { aoqi@0: case DecoderStateTables.ISTRING_PREFIX_NAMESPACE_INDEX_ZERO: aoqi@0: if (namespaceNamePresent) { aoqi@0: _prefixIndex = 0; aoqi@0: // Peak at next byte and check the index of the XML namespace name aoqi@0: if (DecoderStateTables.ISTRING_PREFIX_NAMESPACE(peek()) aoqi@0: != DecoderStateTables.ISTRING_PREFIX_NAMESPACE_INDEX_ZERO) { aoqi@0: throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.wrongNamespaceName")); aoqi@0: } aoqi@0: return EncodingConstants.XML_NAMESPACE_PREFIX; aoqi@0: } else { aoqi@0: throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.missingNamespaceName")); aoqi@0: } aoqi@0: case DecoderStateTables.ISTRING_INDEX_SMALL: aoqi@0: _prefixIndex = b & EncodingConstants.INTEGER_2ND_BIT_SMALL_MASK; aoqi@0: return _v.prefix._array[_prefixIndex - 1]; aoqi@0: case DecoderStateTables.ISTRING_INDEX_MEDIUM: aoqi@0: _prefixIndex = (((b & EncodingConstants.INTEGER_2ND_BIT_MEDIUM_MASK) << 8) | read()) aoqi@0: + EncodingConstants.INTEGER_2ND_BIT_SMALL_LIMIT; aoqi@0: return _v.prefix._array[_prefixIndex - 1]; aoqi@0: case DecoderStateTables.ISTRING_INDEX_LARGE: aoqi@0: _prefixIndex = (((b & EncodingConstants.INTEGER_2ND_BIT_LARGE_MASK) << 16) | (read() << 8) | read()) aoqi@0: + EncodingConstants.INTEGER_2ND_BIT_MEDIUM_LIMIT; aoqi@0: return _v.prefix._array[_prefixIndex - 1]; aoqi@0: default: aoqi@0: throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.decodingIdentifyingStringForPrefix")); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: protected int _namespaceNameIndex; aoqi@0: aoqi@0: /* aoqi@0: * C.13 aoqi@0: */ aoqi@0: protected final String decodeIdentifyingNonEmptyStringOnFirstBitAsNamespaceName(boolean prefixPresent) throws FastInfosetException, IOException { aoqi@0: final int b = read(); aoqi@0: switch(DecoderStateTables.ISTRING_PREFIX_NAMESPACE(b)) { aoqi@0: case DecoderStateTables.ISTRING_PREFIX_NAMESPACE_LENGTH_3: aoqi@0: case DecoderStateTables.ISTRING_PREFIX_NAMESPACE_LENGTH_5: aoqi@0: case DecoderStateTables.ISTRING_SMALL_LENGTH: aoqi@0: { aoqi@0: _octetBufferLength = b + 1; aoqi@0: final String s = (_stringInterning) ? decodeUtf8StringAsString().intern() : decodeUtf8StringAsString(); aoqi@0: _namespaceNameIndex = _v.namespaceName.add(s); aoqi@0: return s; aoqi@0: } aoqi@0: case DecoderStateTables.ISTRING_PREFIX_NAMESPACE_LENGTH_29: aoqi@0: { aoqi@0: _octetBufferLength = EncodingConstants.XMLNS_NAMESPACE_NAME_LENGTH; aoqi@0: decodeUtf8StringAsCharBuffer(); aoqi@0: aoqi@0: if (compareCharsWithCharBufferFromEndToStart(XMLNS_NAMESPACE_NAME_CHARS)) { aoqi@0: throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.xmlnsConnotBeBoundToPrefix")); aoqi@0: } aoqi@0: aoqi@0: final String s = (_stringInterning) ? new String(_charBuffer, 0, _charBufferLength).intern() : aoqi@0: new String(_charBuffer, 0, _charBufferLength); aoqi@0: _namespaceNameIndex = _v.namespaceName.add(s); aoqi@0: return s; aoqi@0: } aoqi@0: case DecoderStateTables.ISTRING_PREFIX_NAMESPACE_LENGTH_36: aoqi@0: { aoqi@0: _octetBufferLength = EncodingConstants.XML_NAMESPACE_NAME_LENGTH; aoqi@0: decodeUtf8StringAsCharBuffer(); aoqi@0: aoqi@0: if (compareCharsWithCharBufferFromEndToStart(XML_NAMESPACE_NAME_CHARS)) { aoqi@0: throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.illegalNamespaceName")); aoqi@0: } aoqi@0: aoqi@0: final String s = (_stringInterning) ? new String(_charBuffer, 0, _charBufferLength).intern() : aoqi@0: new String(_charBuffer, 0, _charBufferLength); aoqi@0: _namespaceNameIndex = _v.namespaceName.add(s); aoqi@0: return s; aoqi@0: } aoqi@0: case DecoderStateTables.ISTRING_MEDIUM_LENGTH: aoqi@0: { aoqi@0: _octetBufferLength = read() + EncodingConstants.OCTET_STRING_LENGTH_2ND_BIT_SMALL_LIMIT; aoqi@0: final String s = (_stringInterning) ? decodeUtf8StringAsString().intern() : decodeUtf8StringAsString(); aoqi@0: _namespaceNameIndex = _v.namespaceName.add(s); aoqi@0: return s; aoqi@0: } aoqi@0: case DecoderStateTables.ISTRING_LARGE_LENGTH: aoqi@0: { aoqi@0: final int length = (read() << 24) | aoqi@0: (read() << 16) | aoqi@0: (read() << 8) | aoqi@0: read(); aoqi@0: _octetBufferLength = length + EncodingConstants.OCTET_STRING_LENGTH_2ND_BIT_MEDIUM_LIMIT; aoqi@0: final String s = (_stringInterning) ? decodeUtf8StringAsString().intern() : decodeUtf8StringAsString(); aoqi@0: _namespaceNameIndex = _v.namespaceName.add(s); aoqi@0: return s; aoqi@0: } aoqi@0: case DecoderStateTables.ISTRING_PREFIX_NAMESPACE_INDEX_ZERO: aoqi@0: if (prefixPresent) { aoqi@0: _namespaceNameIndex = 0; aoqi@0: return EncodingConstants.XML_NAMESPACE_NAME; aoqi@0: } else { aoqi@0: throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.namespaceWithoutPrefix")); aoqi@0: } aoqi@0: case DecoderStateTables.ISTRING_INDEX_SMALL: aoqi@0: _namespaceNameIndex = b & EncodingConstants.INTEGER_2ND_BIT_SMALL_MASK; aoqi@0: return _v.namespaceName._array[_namespaceNameIndex - 1]; aoqi@0: case DecoderStateTables.ISTRING_INDEX_MEDIUM: aoqi@0: _namespaceNameIndex = (((b & EncodingConstants.INTEGER_2ND_BIT_MEDIUM_MASK) << 8) | read()) aoqi@0: + EncodingConstants.INTEGER_2ND_BIT_SMALL_LIMIT; aoqi@0: return _v.namespaceName._array[_namespaceNameIndex - 1]; aoqi@0: case DecoderStateTables.ISTRING_INDEX_LARGE: aoqi@0: _namespaceNameIndex = (((b & EncodingConstants.INTEGER_2ND_BIT_LARGE_MASK) << 16) | (read() << 8) | read()) aoqi@0: + EncodingConstants.INTEGER_2ND_BIT_MEDIUM_LIMIT; aoqi@0: return _v.namespaceName._array[_namespaceNameIndex - 1]; aoqi@0: default: aoqi@0: throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.decodingForNamespaceName")); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: /* aoqi@0: * C.13 aoqi@0: */ aoqi@0: protected final String decodeIdentifyingNonEmptyStringIndexOnFirstBitAsNamespaceName(boolean prefixPresent) throws FastInfosetException, IOException { aoqi@0: final int b = read(); aoqi@0: switch(DecoderStateTables.ISTRING_PREFIX_NAMESPACE(b)) { aoqi@0: case DecoderStateTables.ISTRING_PREFIX_NAMESPACE_INDEX_ZERO: aoqi@0: if (prefixPresent) { aoqi@0: _namespaceNameIndex = 0; aoqi@0: return EncodingConstants.XML_NAMESPACE_NAME; aoqi@0: } else { aoqi@0: throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.namespaceWithoutPrefix")); aoqi@0: } aoqi@0: case DecoderStateTables.ISTRING_INDEX_SMALL: aoqi@0: _namespaceNameIndex = b & EncodingConstants.INTEGER_2ND_BIT_SMALL_MASK; aoqi@0: return _v.namespaceName._array[_namespaceNameIndex - 1]; aoqi@0: case DecoderStateTables.ISTRING_INDEX_MEDIUM: aoqi@0: _namespaceNameIndex = (((b & EncodingConstants.INTEGER_2ND_BIT_MEDIUM_MASK) << 8) | read()) aoqi@0: + EncodingConstants.INTEGER_2ND_BIT_SMALL_LIMIT; aoqi@0: return _v.namespaceName._array[_namespaceNameIndex - 1]; aoqi@0: case DecoderStateTables.ISTRING_INDEX_LARGE: aoqi@0: _namespaceNameIndex = (((b & EncodingConstants.INTEGER_2ND_BIT_LARGE_MASK) << 16) | (read() << 8) | read()) aoqi@0: + EncodingConstants.INTEGER_2ND_BIT_MEDIUM_LIMIT; aoqi@0: return _v.namespaceName._array[_namespaceNameIndex - 1]; aoqi@0: default: aoqi@0: throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.decodingForNamespaceName")); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: private boolean compareCharsWithCharBufferFromEndToStart(char[] c) { aoqi@0: int i = _charBufferLength ; aoqi@0: while (--i >= 0) { aoqi@0: if (c[i] != _charBuffer[i]) { aoqi@0: return false; aoqi@0: } aoqi@0: } aoqi@0: return true; aoqi@0: } aoqi@0: aoqi@0: /* aoqi@0: * C.22 aoqi@0: */ aoqi@0: protected final String decodeNonEmptyOctetStringOnSecondBitAsUtf8String() throws FastInfosetException, IOException { aoqi@0: decodeNonEmptyOctetStringOnSecondBitAsUtf8CharArray(); aoqi@0: return new String(_charBuffer, 0, _charBufferLength); aoqi@0: } aoqi@0: aoqi@0: /* aoqi@0: * C.22 aoqi@0: */ aoqi@0: protected final void decodeNonEmptyOctetStringOnSecondBitAsUtf8CharArray() throws FastInfosetException, IOException { aoqi@0: decodeNonEmptyOctetStringLengthOnSecondBit(); aoqi@0: decodeUtf8StringAsCharBuffer(); aoqi@0: } aoqi@0: aoqi@0: /* aoqi@0: * C.22 aoqi@0: */ aoqi@0: protected final void decodeNonEmptyOctetStringLengthOnSecondBit() throws FastInfosetException, IOException { aoqi@0: final int b = read(); aoqi@0: switch(DecoderStateTables.ISTRING(b)) { aoqi@0: case DecoderStateTables.ISTRING_SMALL_LENGTH: aoqi@0: _octetBufferLength = b + 1; aoqi@0: break; aoqi@0: case DecoderStateTables.ISTRING_MEDIUM_LENGTH: aoqi@0: _octetBufferLength = read() + EncodingConstants.OCTET_STRING_LENGTH_2ND_BIT_SMALL_LIMIT; aoqi@0: break; aoqi@0: case DecoderStateTables.ISTRING_LARGE_LENGTH: aoqi@0: { aoqi@0: final int length = (read() << 24) | aoqi@0: (read() << 16) | aoqi@0: (read() << 8) | aoqi@0: read(); aoqi@0: _octetBufferLength = length + EncodingConstants.OCTET_STRING_LENGTH_2ND_BIT_MEDIUM_LIMIT; aoqi@0: break; aoqi@0: } aoqi@0: case DecoderStateTables.ISTRING_INDEX_SMALL: aoqi@0: case DecoderStateTables.ISTRING_INDEX_MEDIUM: aoqi@0: case DecoderStateTables.ISTRING_INDEX_LARGE: aoqi@0: default: aoqi@0: throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.decodingNonEmptyOctet")); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: /* aoqi@0: * C.25 aoqi@0: */ aoqi@0: protected final int decodeIntegerIndexOnSecondBit() throws FastInfosetException, IOException { aoqi@0: final int b = read() | 0x80; aoqi@0: switch(DecoderStateTables.ISTRING(b)) { aoqi@0: case DecoderStateTables.ISTRING_INDEX_SMALL: aoqi@0: return b & EncodingConstants.INTEGER_2ND_BIT_SMALL_MASK; aoqi@0: case DecoderStateTables.ISTRING_INDEX_MEDIUM: aoqi@0: return (((b & EncodingConstants.INTEGER_2ND_BIT_MEDIUM_MASK) << 8) | read()) aoqi@0: + EncodingConstants.INTEGER_2ND_BIT_SMALL_LIMIT; aoqi@0: case DecoderStateTables.ISTRING_INDEX_LARGE: aoqi@0: return (((b & EncodingConstants.INTEGER_2ND_BIT_LARGE_MASK) << 16) | (read() << 8) | read()) aoqi@0: + EncodingConstants.INTEGER_2ND_BIT_MEDIUM_LIMIT; aoqi@0: case DecoderStateTables.ISTRING_SMALL_LENGTH: aoqi@0: case DecoderStateTables.ISTRING_MEDIUM_LENGTH: aoqi@0: case DecoderStateTables.ISTRING_LARGE_LENGTH: aoqi@0: default: aoqi@0: throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.decodingIndexOnSecondBit")); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: protected final void decodeHeader() throws FastInfosetException, IOException { aoqi@0: if (!_isFastInfosetDocument()) { aoqi@0: throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.notFIDocument")); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: protected final void decodeRestrictedAlphabetAsCharBuffer() throws FastInfosetException, IOException { aoqi@0: if (_identifier <= EncodingConstants.RESTRICTED_ALPHABET_BUILTIN_END) { aoqi@0: decodeFourBitAlphabetOctetsAsCharBuffer(BuiltInRestrictedAlphabets.table[_identifier]); aoqi@0: // decodeAlphabetOctetsAsCharBuffer(BuiltInRestrictedAlphabets.table[_identifier]); aoqi@0: } else if (_identifier >= EncodingConstants.RESTRICTED_ALPHABET_APPLICATION_START) { aoqi@0: CharArray ca = _v.restrictedAlphabet.get(_identifier - EncodingConstants.RESTRICTED_ALPHABET_APPLICATION_START); aoqi@0: if (ca == null) { aoqi@0: throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.alphabetNotPresent", new Object[]{Integer.valueOf(_identifier)})); aoqi@0: } aoqi@0: decodeAlphabetOctetsAsCharBuffer(ca.ch); aoqi@0: } else { aoqi@0: // Reserved built-in algorithms for future use aoqi@0: // TODO should use sax property to decide if event will be aoqi@0: // reported, allows for support through handler if required. aoqi@0: throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.alphabetIdentifiersReserved")); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: protected final String decodeRestrictedAlphabetAsString() throws FastInfosetException, IOException { aoqi@0: decodeRestrictedAlphabetAsCharBuffer(); aoqi@0: return new String(_charBuffer, 0, _charBufferLength); aoqi@0: } aoqi@0: aoqi@0: protected final String decodeRAOctetsAsString(char[] restrictedAlphabet) throws FastInfosetException, IOException { aoqi@0: decodeAlphabetOctetsAsCharBuffer(restrictedAlphabet); aoqi@0: return new String(_charBuffer, 0, _charBufferLength); aoqi@0: } aoqi@0: aoqi@0: protected final void decodeFourBitAlphabetOctetsAsCharBuffer(char[] restrictedAlphabet) throws FastInfosetException, IOException { aoqi@0: _charBufferLength = 0; aoqi@0: final int characters = _octetBufferLength * 2; aoqi@0: if (_charBuffer.length < characters) { aoqi@0: _charBuffer = new char[characters]; aoqi@0: } aoqi@0: aoqi@0: int v = 0; aoqi@0: for (int i = 0; i < _octetBufferLength - 1; i++) { aoqi@0: v = _octetBuffer[_octetBufferStart++] & 0xFF; aoqi@0: _charBuffer[_charBufferLength++] = restrictedAlphabet[v >> 4]; aoqi@0: _charBuffer[_charBufferLength++] = restrictedAlphabet[v & 0x0F]; aoqi@0: } aoqi@0: v = _octetBuffer[_octetBufferStart++] & 0xFF; aoqi@0: _charBuffer[_charBufferLength++] = restrictedAlphabet[v >> 4]; aoqi@0: v &= 0x0F; aoqi@0: if (v != 0x0F) { aoqi@0: _charBuffer[_charBufferLength++] = restrictedAlphabet[v & 0x0F]; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: protected final void decodeAlphabetOctetsAsCharBuffer(char[] restrictedAlphabet) throws FastInfosetException, IOException { aoqi@0: if (restrictedAlphabet.length < 2) { aoqi@0: throw new IllegalArgumentException(CommonResourceBundle.getInstance().getString("message.alphabetMustContain2orMoreChars")); aoqi@0: } aoqi@0: aoqi@0: int bitsPerCharacter = 1; aoqi@0: while ((1 << bitsPerCharacter) <= restrictedAlphabet.length) { aoqi@0: bitsPerCharacter++; aoqi@0: } aoqi@0: final int terminatingValue = (1 << bitsPerCharacter) - 1; aoqi@0: aoqi@0: int characters = (_octetBufferLength << 3) / bitsPerCharacter; aoqi@0: if (characters == 0) { aoqi@0: throw new IOException(""); aoqi@0: } aoqi@0: aoqi@0: _charBufferLength = 0; aoqi@0: if (_charBuffer.length < characters) { aoqi@0: _charBuffer = new char[characters]; aoqi@0: } aoqi@0: aoqi@0: resetBits(); aoqi@0: for (int i = 0; i < characters; i++) { aoqi@0: int value = readBits(bitsPerCharacter); aoqi@0: if (bitsPerCharacter < 8 && value == terminatingValue) { aoqi@0: int octetPosition = (i * bitsPerCharacter) >>> 3; aoqi@0: if (octetPosition != _octetBufferLength - 1) { aoqi@0: throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.alphabetIncorrectlyTerminated")); aoqi@0: } aoqi@0: break; aoqi@0: } aoqi@0: _charBuffer[_charBufferLength++] = restrictedAlphabet[value]; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: private int _bitsLeftInOctet; aoqi@0: aoqi@0: private void resetBits() { aoqi@0: _bitsLeftInOctet = 0; aoqi@0: } aoqi@0: aoqi@0: private int readBits(int bits) throws IOException { aoqi@0: int value = 0; aoqi@0: while (bits > 0) { aoqi@0: if (_bitsLeftInOctet == 0) { aoqi@0: _b = _octetBuffer[_octetBufferStart++] & 0xFF; aoqi@0: _bitsLeftInOctet = 8; aoqi@0: } aoqi@0: int bit = ((_b & (1 << --_bitsLeftInOctet)) > 0) ? 1 : 0; aoqi@0: value |= (bit << --bits); aoqi@0: } aoqi@0: aoqi@0: return value; aoqi@0: } aoqi@0: aoqi@0: protected final void decodeUtf8StringAsCharBuffer() throws IOException { aoqi@0: ensureOctetBufferSize(); aoqi@0: decodeUtf8StringIntoCharBuffer(); aoqi@0: } aoqi@0: aoqi@0: protected final void decodeUtf8StringAsCharBuffer(char[] ch, int offset) throws IOException { aoqi@0: ensureOctetBufferSize(); aoqi@0: decodeUtf8StringIntoCharBuffer(ch, offset); aoqi@0: } aoqi@0: aoqi@0: protected final String decodeUtf8StringAsString() throws IOException { aoqi@0: decodeUtf8StringAsCharBuffer(); aoqi@0: return new String(_charBuffer, 0, _charBufferLength); aoqi@0: } aoqi@0: aoqi@0: protected final void decodeUtf16StringAsCharBuffer() throws IOException { aoqi@0: ensureOctetBufferSize(); aoqi@0: decodeUtf16StringIntoCharBuffer(); aoqi@0: } aoqi@0: aoqi@0: protected final String decodeUtf16StringAsString() throws IOException { aoqi@0: decodeUtf16StringAsCharBuffer(); aoqi@0: return new String(_charBuffer, 0, _charBufferLength); aoqi@0: } aoqi@0: aoqi@0: private void ensureOctetBufferSize() throws IOException { aoqi@0: if (_octetBufferEnd < (_octetBufferOffset + _octetBufferLength)) { aoqi@0: final int octetsInBuffer = _octetBufferEnd - _octetBufferOffset; aoqi@0: aoqi@0: if (_octetBuffer.length < _octetBufferLength) { aoqi@0: // Length to read is too large, resize the buffer aoqi@0: byte[] newOctetBuffer = new byte[_octetBufferLength]; aoqi@0: // Move partially read octets to the start of the buffer aoqi@0: System.arraycopy(_octetBuffer, _octetBufferOffset, newOctetBuffer, 0, octetsInBuffer); aoqi@0: _octetBuffer = newOctetBuffer; aoqi@0: } else { aoqi@0: // Move partially read octets to the start of the buffer aoqi@0: System.arraycopy(_octetBuffer, _octetBufferOffset, _octetBuffer, 0, octetsInBuffer); aoqi@0: } aoqi@0: _octetBufferOffset = 0; aoqi@0: aoqi@0: // Read as many octets as possible to fill the buffer aoqi@0: final int octetsRead = _s.read(_octetBuffer, octetsInBuffer, _octetBuffer.length - octetsInBuffer); aoqi@0: if (octetsRead < 0) { aoqi@0: throw new EOFException("Unexpeceted EOF"); aoqi@0: } aoqi@0: _octetBufferEnd = octetsInBuffer + octetsRead; aoqi@0: aoqi@0: // Check if the number of octets that have been read is not enough aoqi@0: // This can happen when underlying non-blocking is used to read aoqi@0: if (_octetBufferEnd < _octetBufferLength) { aoqi@0: repeatedRead(); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: private void repeatedRead() throws IOException { aoqi@0: // Check if the number of octets that have been read is not enough aoqi@0: while (_octetBufferEnd < _octetBufferLength) { aoqi@0: // Read as many octets as possible to fill the buffer aoqi@0: final int octetsRead = _s.read(_octetBuffer, _octetBufferEnd, _octetBuffer.length - _octetBufferEnd); aoqi@0: if (octetsRead < 0) { aoqi@0: throw new EOFException("Unexpeceted EOF"); aoqi@0: } aoqi@0: _octetBufferEnd += octetsRead; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: protected final void decodeUtf8StringIntoCharBuffer() throws IOException { aoqi@0: if (_charBuffer.length < _octetBufferLength) { aoqi@0: _charBuffer = new char[_octetBufferLength]; aoqi@0: } aoqi@0: aoqi@0: _charBufferLength = 0; aoqi@0: final int end = _octetBufferLength + _octetBufferOffset; aoqi@0: int b1; aoqi@0: while (end != _octetBufferOffset) { aoqi@0: b1 = _octetBuffer[_octetBufferOffset++] & 0xFF; aoqi@0: if (DecoderStateTables.UTF8(b1) == DecoderStateTables.UTF8_ONE_BYTE) { aoqi@0: _charBuffer[_charBufferLength++] = (char) b1; aoqi@0: } else { aoqi@0: decodeTwoToFourByteUtf8Character(b1, end); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: protected final void decodeUtf8StringIntoCharBuffer(char[] ch, int offset) throws IOException { aoqi@0: _charBufferLength = offset; aoqi@0: final int end = _octetBufferLength + _octetBufferOffset; aoqi@0: int b1; aoqi@0: while (end != _octetBufferOffset) { aoqi@0: b1 = _octetBuffer[_octetBufferOffset++] & 0xFF; aoqi@0: if (DecoderStateTables.UTF8(b1) == DecoderStateTables.UTF8_ONE_BYTE) { aoqi@0: ch[_charBufferLength++] = (char) b1; aoqi@0: } else { aoqi@0: decodeTwoToFourByteUtf8Character(ch, b1, end); aoqi@0: } aoqi@0: } aoqi@0: _charBufferLength -= offset; aoqi@0: } aoqi@0: aoqi@0: private void decodeTwoToFourByteUtf8Character(int b1, int end) throws IOException { aoqi@0: switch(DecoderStateTables.UTF8(b1)) { aoqi@0: case DecoderStateTables.UTF8_TWO_BYTES: aoqi@0: { aoqi@0: // Decode byte 2 aoqi@0: if (end == _octetBufferOffset) { aoqi@0: decodeUtf8StringLengthTooSmall(); aoqi@0: } aoqi@0: final int b2 = _octetBuffer[_octetBufferOffset++] & 0xFF; aoqi@0: if ((b2 & 0xC0) != 0x80) { aoqi@0: decodeUtf8StringIllegalState(); aoqi@0: } aoqi@0: aoqi@0: // Character guaranteed to be in [0x20, 0xD7FF] range aoqi@0: // since a character encoded in two bytes will be in the aoqi@0: // range [0x80, 0x1FFF] aoqi@0: _charBuffer[_charBufferLength++] = (char) ( aoqi@0: ((b1 & 0x1F) << 6) aoqi@0: | (b2 & 0x3F)); aoqi@0: break; aoqi@0: } aoqi@0: case DecoderStateTables.UTF8_THREE_BYTES: aoqi@0: final char c = decodeUtf8ThreeByteChar(end, b1); aoqi@0: if (XMLChar.isContent(c)) { aoqi@0: _charBuffer[_charBufferLength++] = c; aoqi@0: } else { aoqi@0: decodeUtf8StringIllegalState(); aoqi@0: } aoqi@0: break; aoqi@0: case DecoderStateTables.UTF8_FOUR_BYTES: aoqi@0: { aoqi@0: final int supplemental = decodeUtf8FourByteChar(end, b1); aoqi@0: if (XMLChar.isContent(supplemental)) { aoqi@0: _charBuffer[_charBufferLength++] = _utf8_highSurrogate; aoqi@0: _charBuffer[_charBufferLength++] = _utf8_lowSurrogate; aoqi@0: } else { aoqi@0: decodeUtf8StringIllegalState(); aoqi@0: } aoqi@0: break; aoqi@0: } aoqi@0: default: aoqi@0: decodeUtf8StringIllegalState(); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: private void decodeTwoToFourByteUtf8Character(char ch[], int b1, int end) throws IOException { aoqi@0: switch(DecoderStateTables.UTF8(b1)) { aoqi@0: case DecoderStateTables.UTF8_TWO_BYTES: aoqi@0: { aoqi@0: // Decode byte 2 aoqi@0: if (end == _octetBufferOffset) { aoqi@0: decodeUtf8StringLengthTooSmall(); aoqi@0: } aoqi@0: final int b2 = _octetBuffer[_octetBufferOffset++] & 0xFF; aoqi@0: if ((b2 & 0xC0) != 0x80) { aoqi@0: decodeUtf8StringIllegalState(); aoqi@0: } aoqi@0: aoqi@0: // Character guaranteed to be in [0x20, 0xD7FF] range aoqi@0: // since a character encoded in two bytes will be in the aoqi@0: // range [0x80, 0x1FFF] aoqi@0: ch[_charBufferLength++] = (char) ( aoqi@0: ((b1 & 0x1F) << 6) aoqi@0: | (b2 & 0x3F)); aoqi@0: break; aoqi@0: } aoqi@0: case DecoderStateTables.UTF8_THREE_BYTES: aoqi@0: final char c = decodeUtf8ThreeByteChar(end, b1); aoqi@0: if (XMLChar.isContent(c)) { aoqi@0: ch[_charBufferLength++] = c; aoqi@0: } else { aoqi@0: decodeUtf8StringIllegalState(); aoqi@0: } aoqi@0: break; aoqi@0: case DecoderStateTables.UTF8_FOUR_BYTES: aoqi@0: { aoqi@0: final int supplemental = decodeUtf8FourByteChar(end, b1); aoqi@0: if (XMLChar.isContent(supplemental)) { aoqi@0: ch[_charBufferLength++] = _utf8_highSurrogate; aoqi@0: ch[_charBufferLength++] = _utf8_lowSurrogate; aoqi@0: } else { aoqi@0: decodeUtf8StringIllegalState(); aoqi@0: } aoqi@0: break; aoqi@0: } aoqi@0: default: aoqi@0: decodeUtf8StringIllegalState(); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: protected final void decodeUtf8NCNameIntoCharBuffer() throws IOException { aoqi@0: _charBufferLength = 0; aoqi@0: if (_charBuffer.length < _octetBufferLength) { aoqi@0: _charBuffer = new char[_octetBufferLength]; aoqi@0: } aoqi@0: aoqi@0: final int end = _octetBufferLength + _octetBufferOffset; aoqi@0: aoqi@0: int b1 = _octetBuffer[_octetBufferOffset++] & 0xFF; aoqi@0: if (DecoderStateTables.UTF8_NCNAME(b1) == DecoderStateTables.UTF8_NCNAME_NCNAME) { aoqi@0: _charBuffer[_charBufferLength++] = (char) b1; aoqi@0: } else { aoqi@0: decodeUtf8NCNameStartTwoToFourByteCharacters(b1, end); aoqi@0: } aoqi@0: aoqi@0: while (end != _octetBufferOffset) { aoqi@0: b1 = _octetBuffer[_octetBufferOffset++] & 0xFF; aoqi@0: if (DecoderStateTables.UTF8_NCNAME(b1) < DecoderStateTables.UTF8_TWO_BYTES) { aoqi@0: _charBuffer[_charBufferLength++] = (char) b1; aoqi@0: } else { aoqi@0: decodeUtf8NCNameTwoToFourByteCharacters(b1, end); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: private void decodeUtf8NCNameStartTwoToFourByteCharacters(int b1, int end) throws IOException { aoqi@0: switch(DecoderStateTables.UTF8_NCNAME(b1)) { aoqi@0: case DecoderStateTables.UTF8_TWO_BYTES: aoqi@0: { aoqi@0: // Decode byte 2 aoqi@0: if (end == _octetBufferOffset) { aoqi@0: decodeUtf8StringLengthTooSmall(); aoqi@0: } aoqi@0: final int b2 = _octetBuffer[_octetBufferOffset++] & 0xFF; aoqi@0: if ((b2 & 0xC0) != 0x80) { aoqi@0: decodeUtf8StringIllegalState(); aoqi@0: } aoqi@0: aoqi@0: final char c = (char) ( aoqi@0: ((b1 & 0x1F) << 6) aoqi@0: | (b2 & 0x3F)); aoqi@0: if (XMLChar.isNCNameStart(c)) { aoqi@0: _charBuffer[_charBufferLength++] = c; aoqi@0: } else { aoqi@0: decodeUtf8NCNameIllegalState(); aoqi@0: } aoqi@0: break; aoqi@0: } aoqi@0: case DecoderStateTables.UTF8_THREE_BYTES: aoqi@0: final char c = decodeUtf8ThreeByteChar(end, b1); aoqi@0: if (XMLChar.isNCNameStart(c)) { aoqi@0: _charBuffer[_charBufferLength++] = c; aoqi@0: } else { aoqi@0: decodeUtf8NCNameIllegalState(); aoqi@0: } aoqi@0: break; aoqi@0: case DecoderStateTables.UTF8_FOUR_BYTES: aoqi@0: { aoqi@0: final int supplemental = decodeUtf8FourByteChar(end, b1); aoqi@0: if (XMLChar.isNCNameStart(supplemental)) { aoqi@0: _charBuffer[_charBufferLength++] = _utf8_highSurrogate; aoqi@0: _charBuffer[_charBufferLength++] = _utf8_lowSurrogate; aoqi@0: } else { aoqi@0: decodeUtf8NCNameIllegalState(); aoqi@0: } aoqi@0: break; aoqi@0: } aoqi@0: case DecoderStateTables.UTF8_NCNAME_NCNAME_CHAR: aoqi@0: default: aoqi@0: decodeUtf8NCNameIllegalState(); aoqi@0: } aoqi@0: aoqi@0: } aoqi@0: aoqi@0: private void decodeUtf8NCNameTwoToFourByteCharacters(int b1, int end) throws IOException { aoqi@0: switch(DecoderStateTables.UTF8_NCNAME(b1)) { aoqi@0: case DecoderStateTables.UTF8_TWO_BYTES: aoqi@0: { aoqi@0: // Decode byte 2 aoqi@0: if (end == _octetBufferOffset) { aoqi@0: decodeUtf8StringLengthTooSmall(); aoqi@0: } aoqi@0: final int b2 = _octetBuffer[_octetBufferOffset++] & 0xFF; aoqi@0: if ((b2 & 0xC0) != 0x80) { aoqi@0: decodeUtf8StringIllegalState(); aoqi@0: } aoqi@0: aoqi@0: final char c = (char) ( aoqi@0: ((b1 & 0x1F) << 6) aoqi@0: | (b2 & 0x3F)); aoqi@0: if (XMLChar.isNCName(c)) { aoqi@0: _charBuffer[_charBufferLength++] = c; aoqi@0: } else { aoqi@0: decodeUtf8NCNameIllegalState(); aoqi@0: } aoqi@0: break; aoqi@0: } aoqi@0: case DecoderStateTables.UTF8_THREE_BYTES: aoqi@0: final char c = decodeUtf8ThreeByteChar(end, b1); aoqi@0: if (XMLChar.isNCName(c)) { aoqi@0: _charBuffer[_charBufferLength++] = c; aoqi@0: } else { aoqi@0: decodeUtf8NCNameIllegalState(); aoqi@0: } aoqi@0: break; aoqi@0: case DecoderStateTables.UTF8_FOUR_BYTES: aoqi@0: { aoqi@0: final int supplemental = decodeUtf8FourByteChar(end, b1); aoqi@0: if (XMLChar.isNCName(supplemental)) { aoqi@0: _charBuffer[_charBufferLength++] = _utf8_highSurrogate; aoqi@0: _charBuffer[_charBufferLength++] = _utf8_lowSurrogate; aoqi@0: } else { aoqi@0: decodeUtf8NCNameIllegalState(); aoqi@0: } aoqi@0: break; aoqi@0: } aoqi@0: default: aoqi@0: decodeUtf8NCNameIllegalState(); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: private char decodeUtf8ThreeByteChar(int end, int b1) throws IOException { aoqi@0: // Decode byte 2 aoqi@0: if (end == _octetBufferOffset) { aoqi@0: decodeUtf8StringLengthTooSmall(); aoqi@0: } aoqi@0: final int b2 = _octetBuffer[_octetBufferOffset++] & 0xFF; aoqi@0: if ((b2 & 0xC0) != 0x80 aoqi@0: || (b1 == 0xED && b2 >= 0xA0) aoqi@0: || ((b1 & 0x0F) == 0 && (b2 & 0x20) == 0)) { aoqi@0: decodeUtf8StringIllegalState(); aoqi@0: } aoqi@0: aoqi@0: // Decode byte 3 aoqi@0: if (end == _octetBufferOffset) { aoqi@0: decodeUtf8StringLengthTooSmall(); aoqi@0: } aoqi@0: final int b3 = _octetBuffer[_octetBufferOffset++] & 0xFF; aoqi@0: if ((b3 & 0xC0) != 0x80) { aoqi@0: decodeUtf8StringIllegalState(); aoqi@0: } aoqi@0: aoqi@0: return (char) ( aoqi@0: (b1 & 0x0F) << 12 aoqi@0: | (b2 & 0x3F) << 6 aoqi@0: | (b3 & 0x3F)); aoqi@0: } aoqi@0: aoqi@0: private char _utf8_highSurrogate; aoqi@0: private char _utf8_lowSurrogate; aoqi@0: aoqi@0: private int decodeUtf8FourByteChar(int end, int b1) throws IOException { aoqi@0: // Decode byte 2 aoqi@0: if (end == _octetBufferOffset) { aoqi@0: decodeUtf8StringLengthTooSmall(); aoqi@0: } aoqi@0: final int b2 = _octetBuffer[_octetBufferOffset++] & 0xFF; aoqi@0: if ((b2 & 0xC0) != 0x80 aoqi@0: || ((b2 & 0x30) == 0 && (b1 & 0x07) == 0)) { aoqi@0: decodeUtf8StringIllegalState(); aoqi@0: } aoqi@0: aoqi@0: // Decode byte 3 aoqi@0: if (end == _octetBufferOffset) { aoqi@0: decodeUtf8StringLengthTooSmall(); aoqi@0: } aoqi@0: final int b3 = _octetBuffer[_octetBufferOffset++] & 0xFF; aoqi@0: if ((b3 & 0xC0) != 0x80) { aoqi@0: decodeUtf8StringIllegalState(); aoqi@0: } aoqi@0: aoqi@0: // Decode byte 4 aoqi@0: if (end == _octetBufferOffset) { aoqi@0: decodeUtf8StringLengthTooSmall(); aoqi@0: } aoqi@0: final int b4 = _octetBuffer[_octetBufferOffset++] & 0xFF; aoqi@0: if ((b4 & 0xC0) != 0x80) { aoqi@0: decodeUtf8StringIllegalState(); aoqi@0: } aoqi@0: aoqi@0: final int uuuuu = ((b1 << 2) & 0x001C) | ((b2 >> 4) & 0x0003); aoqi@0: if (uuuuu > 0x10) { aoqi@0: decodeUtf8StringIllegalState(); aoqi@0: } aoqi@0: final int wwww = uuuuu - 1; aoqi@0: aoqi@0: _utf8_highSurrogate = (char) (0xD800 | aoqi@0: ((wwww << 6) & 0x03C0) | ((b2 << 2) & 0x003C) | aoqi@0: ((b3 >> 4) & 0x0003)); aoqi@0: _utf8_lowSurrogate = (char) (0xDC00 | ((b3 << 6) & 0x03C0) | (b4 & 0x003F)); aoqi@0: aoqi@0: return XMLChar.supplemental(_utf8_highSurrogate, _utf8_lowSurrogate); aoqi@0: } aoqi@0: aoqi@0: private void decodeUtf8StringLengthTooSmall() throws IOException { aoqi@0: throw new IOException(CommonResourceBundle.getInstance().getString("message.deliminatorTooSmall")); aoqi@0: } aoqi@0: aoqi@0: private void decodeUtf8StringIllegalState() throws IOException { aoqi@0: throw new IOException(CommonResourceBundle.getInstance().getString("message.UTF8Encoded")); aoqi@0: } aoqi@0: aoqi@0: private void decodeUtf8NCNameIllegalState() throws IOException { aoqi@0: throw new IOException(CommonResourceBundle.getInstance().getString("message.UTF8EncodedNCName")); aoqi@0: } aoqi@0: aoqi@0: private void decodeUtf16StringIntoCharBuffer() throws IOException { aoqi@0: _charBufferLength = _octetBufferLength / 2; aoqi@0: if (_charBuffer.length < _charBufferLength) { aoqi@0: _charBuffer = new char[_charBufferLength]; aoqi@0: } aoqi@0: aoqi@0: for (int i = 0; i < _charBufferLength; i++) { aoqi@0: final char c = (char)((read() << 8) | read()); aoqi@0: // TODO check c is a valid Char character aoqi@0: _charBuffer[i] = c; aoqi@0: } aoqi@0: aoqi@0: } aoqi@0: aoqi@0: protected String createQualifiedNameString(String second) { aoqi@0: return createQualifiedNameString(XMLNS_NAMESPACE_PREFIX_CHARS, second); aoqi@0: } aoqi@0: aoqi@0: protected String createQualifiedNameString(char[] first, String second) { aoqi@0: final int l1 = first.length; aoqi@0: final int l2 = second.length(); aoqi@0: final int total = l1 + l2 + 1; aoqi@0: if (total < _charBuffer.length) { aoqi@0: System.arraycopy(first, 0, _charBuffer, 0, l1); aoqi@0: _charBuffer[l1] = ':'; aoqi@0: second.getChars(0, l2, _charBuffer, l1 + 1); aoqi@0: return new String(_charBuffer, 0, total); aoqi@0: } else { aoqi@0: StringBuilder b = new StringBuilder(new String(first)); aoqi@0: b.append(':'); aoqi@0: b.append(second); aoqi@0: return b.toString(); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: protected final int read() throws IOException { aoqi@0: if (_octetBufferOffset < _octetBufferEnd) { aoqi@0: return _octetBuffer[_octetBufferOffset++] & 0xFF; aoqi@0: } else { aoqi@0: _octetBufferEnd = _s.read(_octetBuffer); aoqi@0: if (_octetBufferEnd < 0) { aoqi@0: throw new EOFException(CommonResourceBundle.getInstance().getString("message.EOF")); aoqi@0: } aoqi@0: aoqi@0: _octetBufferOffset = 1; aoqi@0: return _octetBuffer[0] & 0xFF; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: protected final void closeIfRequired() throws IOException { aoqi@0: if (_s != null && _needForceStreamClose) { aoqi@0: _s.close(); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: protected final int peek() throws IOException { aoqi@0: return peek(null); aoqi@0: } aoqi@0: aoqi@0: protected final int peek(OctetBufferListener octetBufferListener) throws IOException { aoqi@0: if (_octetBufferOffset < _octetBufferEnd) { aoqi@0: return _octetBuffer[_octetBufferOffset] & 0xFF; aoqi@0: } else { aoqi@0: if (octetBufferListener != null) { aoqi@0: octetBufferListener.onBeforeOctetBufferOverwrite(); aoqi@0: } aoqi@0: aoqi@0: _octetBufferEnd = _s.read(_octetBuffer); aoqi@0: if (_octetBufferEnd < 0) { aoqi@0: throw new EOFException(CommonResourceBundle.getInstance().getString("message.EOF")); aoqi@0: } aoqi@0: aoqi@0: _octetBufferOffset = 0; aoqi@0: return _octetBuffer[0] & 0xFF; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: protected final int peek2(OctetBufferListener octetBufferListener) throws IOException { aoqi@0: if (_octetBufferOffset + 1 < _octetBufferEnd) { aoqi@0: return _octetBuffer[_octetBufferOffset + 1] & 0xFF; aoqi@0: } else { aoqi@0: if (octetBufferListener != null) { aoqi@0: octetBufferListener.onBeforeOctetBufferOverwrite(); aoqi@0: } aoqi@0: aoqi@0: int offset = 0; aoqi@0: if (_octetBufferOffset < _octetBufferEnd) { aoqi@0: _octetBuffer[0] = _octetBuffer[_octetBufferOffset]; aoqi@0: offset = 1; aoqi@0: } aoqi@0: _octetBufferEnd = _s.read(_octetBuffer, offset, _octetBuffer.length - offset); aoqi@0: aoqi@0: if (_octetBufferEnd < 0) { aoqi@0: throw new EOFException(CommonResourceBundle.getInstance().getString("message.EOF")); aoqi@0: } aoqi@0: aoqi@0: _octetBufferOffset = 0; aoqi@0: return _octetBuffer[1] & 0xFF; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: protected class EncodingAlgorithmInputStream extends InputStream { aoqi@0: aoqi@0: public int read() throws IOException { aoqi@0: if (_octetBufferStart < _octetBufferOffset) { aoqi@0: return (_octetBuffer[_octetBufferStart++] & 0xFF); aoqi@0: } else { aoqi@0: return -1; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public int read(byte b[]) throws IOException { aoqi@0: return read(b, 0, b.length); aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public int read(byte b[], int off, int len) throws IOException { aoqi@0: if (b == null) { aoqi@0: throw new NullPointerException(); aoqi@0: } else if ((off < 0) || (off > b.length) || (len < 0) || aoqi@0: ((off + len) > b.length) || ((off + len) < 0)) { aoqi@0: throw new IndexOutOfBoundsException(); aoqi@0: } else if (len == 0) { aoqi@0: return 0; aoqi@0: } aoqi@0: aoqi@0: final int newOctetBufferStart = _octetBufferStart + len; aoqi@0: if (newOctetBufferStart < _octetBufferOffset) { aoqi@0: System.arraycopy(_octetBuffer, _octetBufferStart, b, off, len); aoqi@0: _octetBufferStart = newOctetBufferStart; aoqi@0: return len; aoqi@0: } else if (_octetBufferStart < _octetBufferOffset) { aoqi@0: final int bytesToRead = _octetBufferOffset - _octetBufferStart; aoqi@0: System.arraycopy(_octetBuffer, _octetBufferStart, b, off, bytesToRead); aoqi@0: _octetBufferStart += bytesToRead; aoqi@0: return bytesToRead; aoqi@0: } else { aoqi@0: return -1; aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: protected final boolean _isFastInfosetDocument() throws IOException { aoqi@0: // Fill up the octet buffer aoqi@0: peek(); aoqi@0: aoqi@0: _octetBufferLength = EncodingConstants.BINARY_HEADER.length; aoqi@0: ensureOctetBufferSize(); aoqi@0: _octetBufferOffset += _octetBufferLength; aoqi@0: aoqi@0: // Check for binary header aoqi@0: if (_octetBuffer[0] != EncodingConstants.BINARY_HEADER[0] || aoqi@0: _octetBuffer[1] != EncodingConstants.BINARY_HEADER[1] || aoqi@0: _octetBuffer[2] != EncodingConstants.BINARY_HEADER[2] || aoqi@0: _octetBuffer[3] != EncodingConstants.BINARY_HEADER[3]) { aoqi@0: aoqi@0: // Check for each form of XML declaration aoqi@0: for (int i = 0; i < EncodingConstants.XML_DECLARATION_VALUES.length; i++) { aoqi@0: _octetBufferLength = EncodingConstants.XML_DECLARATION_VALUES[i].length - _octetBufferOffset; aoqi@0: ensureOctetBufferSize(); aoqi@0: _octetBufferOffset += _octetBufferLength; aoqi@0: aoqi@0: // Check XML declaration aoqi@0: if (arrayEquals(_octetBuffer, 0, aoqi@0: EncodingConstants.XML_DECLARATION_VALUES[i], aoqi@0: EncodingConstants.XML_DECLARATION_VALUES[i].length)) { aoqi@0: _octetBufferLength = EncodingConstants.BINARY_HEADER.length; aoqi@0: ensureOctetBufferSize(); aoqi@0: aoqi@0: // Check for binary header aoqi@0: if (_octetBuffer[_octetBufferOffset++] != EncodingConstants.BINARY_HEADER[0] || aoqi@0: _octetBuffer[_octetBufferOffset++] != EncodingConstants.BINARY_HEADER[1] || aoqi@0: _octetBuffer[_octetBufferOffset++] != EncodingConstants.BINARY_HEADER[2] || aoqi@0: _octetBuffer[_octetBufferOffset++] != EncodingConstants.BINARY_HEADER[3]) { aoqi@0: return false; aoqi@0: } else { aoqi@0: // Fast Infoset document with XML declaration and binary header aoqi@0: return true; aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: return false; aoqi@0: } aoqi@0: aoqi@0: // Fast Infoset document with binary header aoqi@0: return true; aoqi@0: } aoqi@0: aoqi@0: private boolean arrayEquals(byte[] b1, int offset, byte[] b2, int length) { aoqi@0: for (int i = 0; i < length; i++) { aoqi@0: if (b1[offset + i] != b2[i]) { aoqi@0: return false; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: return true; aoqi@0: } aoqi@0: aoqi@0: static public boolean isFastInfosetDocument(InputStream s) throws IOException { aoqi@0: // TODO aoqi@0: // Check for