com.sun.xml.fastinfoset.dom.DOMDocumentParser Maven / Gradle / Ivy
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2004, 2022 Oracle and/or its affiliates. All rights reserved.
*
* Oracle licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.sun.xml.fastinfoset.dom;
import com.sun.xml.fastinfoset.Decoder;
import com.sun.xml.fastinfoset.DecoderStateTables;
import com.sun.xml.fastinfoset.EncodingConstants;
import com.sun.xml.fastinfoset.QualifiedName;
import com.sun.xml.fastinfoset.algorithm.BuiltInEncodingAlgorithmFactory;
import com.sun.xml.fastinfoset.util.CharArray;
import com.sun.xml.fastinfoset.util.CharArrayString;
import java.io.IOException;
import java.io.InputStream;
import org.jvnet.fastinfoset.EncodingAlgorithm;
import org.jvnet.fastinfoset.EncodingAlgorithmException;
import org.jvnet.fastinfoset.EncodingAlgorithmIndexes;
import org.jvnet.fastinfoset.FastInfosetException;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import com.sun.xml.fastinfoset.CommonResourceBundle;
import com.sun.xml.fastinfoset.util.DuplicateAttributeVerifier;
import org.w3c.dom.Text;
/**
* The Fast Infoset DOM parser.
*
* Instantiate this parser to parse a fast infoset document in accordance
* with the DOM API.
*
*/
public class DOMDocumentParser extends Decoder {
protected Document _document;
protected Node _currentNode;
protected Element _currentElement;
protected Attr[] _namespaceAttributes = new Attr[16];
protected int _namespaceAttributesIndex;
protected int[] _namespacePrefixes = new int[16];
protected int _namespacePrefixesIndex;
/**
* Parse a fast infoset document into a {@link Document} instance.
*
* {@link Node}s will be created and appended to the {@link Document}
* instance.
*
* @param d the {@link Document} instance.
* @param s the input stream containing the fast infoset document.
*/
public void parse(Document d, InputStream s) throws FastInfosetException, IOException {
_currentNode = _document = d;
_namespaceAttributesIndex = 0;
parse(s);
}
protected final void parse(InputStream s) throws FastInfosetException, IOException {
setInputStream(s);
parse();
}
protected void resetOnError() {
_namespacePrefixesIndex = 0;
if (_v == null) {
_prefixTable.clearCompletely();
}
_duplicateAttributeVerifier.clear();
}
protected final void parse() throws FastInfosetException, IOException {
try {
reset();
decodeHeader();
processDII();
} catch (RuntimeException e) {
resetOnError();
// Wrap runtime exception
throw new FastInfosetException(e);
} catch (FastInfosetException e) {
resetOnError();
throw e;
} catch (IOException e) {
resetOnError();
throw e;
}
}
@SuppressWarnings("fallthrough")
protected final void processDII() throws FastInfosetException, IOException {
_b = read();
if (_b > 0) {
processDIIOptionalProperties();
}
// Decode one Document Type II, Comment IIs, PI IIs and one EII
boolean firstElementHasOccured = false;
boolean documentTypeDeclarationOccured = false;
while(!_terminate || !firstElementHasOccured) {
_b = read();
switch(DecoderStateTables.DII(_b)) {
case DecoderStateTables.EII_NO_AIIS_INDEX_SMALL:
processEII(_elementNameTable._array[_b], false);
firstElementHasOccured = true;
break;
case DecoderStateTables.EII_AIIS_INDEX_SMALL:
processEII(_elementNameTable._array[_b & EncodingConstants.INTEGER_3RD_BIT_SMALL_MASK], true);
firstElementHasOccured = true;
break;
case DecoderStateTables.EII_INDEX_MEDIUM:
processEII(decodeEIIIndexMedium(), (_b & EncodingConstants.ELEMENT_ATTRIBUTE_FLAG) > 0);
firstElementHasOccured = true;
break;
case DecoderStateTables.EII_INDEX_LARGE:
processEII(decodeEIIIndexLarge(), (_b & EncodingConstants.ELEMENT_ATTRIBUTE_FLAG) > 0);
firstElementHasOccured = true;
break;
case DecoderStateTables.EII_LITERAL:
{
final QualifiedName qn = processLiteralQualifiedName(
_b & EncodingConstants.LITERAL_QNAME_PREFIX_NAMESPACE_NAME_MASK,
_elementNameTable.getNext());
_elementNameTable.add(qn);
processEII(qn, (_b & EncodingConstants.ELEMENT_ATTRIBUTE_FLAG) > 0);
firstElementHasOccured = true;
break;
}
case DecoderStateTables.EII_NAMESPACES:
processEIIWithNamespaces();
firstElementHasOccured = true;
break;
case DecoderStateTables.DOCUMENT_TYPE_DECLARATION_II:
{
if (documentTypeDeclarationOccured) {
throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.secondOccurenceOfDTDII"));
}
documentTypeDeclarationOccured = true;
String system_identifier = ((_b & EncodingConstants.DOCUMENT_TYPE_SYSTEM_IDENTIFIER_FLAG) > 0)
? decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherURI) : null;
String public_identifier = ((_b & EncodingConstants.DOCUMENT_TYPE_PUBLIC_IDENTIFIER_FLAG) > 0)
? decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherURI) : null;
_b = read();
while (_b == EncodingConstants.PROCESSING_INSTRUCTION) {
switch(decodeNonIdentifyingStringOnFirstBit()) {
case NISTRING_STRING:
if (_addToTable) {
_v.otherString.add(new CharArray(_charBuffer, 0, _charBufferLength, true));
}
break;
case NISTRING_ENCODING_ALGORITHM:
throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.processingIIWithEncodingAlgorithm"));
case NISTRING_INDEX:
break;
case NISTRING_EMPTY_STRING:
break;
}
_b = read();
}
if ((_b & EncodingConstants.TERMINATOR) != EncodingConstants.TERMINATOR) {
throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.processingInstructionIIsNotTerminatedCorrectly"));
}
if (_b == EncodingConstants.DOUBLE_TERMINATOR) {
_terminate = true;
}
_notations.clear();
_unparsedEntities.clear();
/*
* TODO
* Report All events associated with DTD, PIs, notations etc
*/
break;
}
case DecoderStateTables.COMMENT_II:
processCommentII();
break;
case DecoderStateTables.PROCESSING_INSTRUCTION_II:
processProcessingII();
break;
case DecoderStateTables.TERMINATOR_DOUBLE:
_doubleTerminate = true;
case DecoderStateTables.TERMINATOR_SINGLE:
_terminate = true;
break;
default:
throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.IllegalStateDecodingDII"));
}
}
// Decode any remaining Comment IIs, PI IIs
while(!_terminate) {
_b = read();
switch(DecoderStateTables.DII(_b)) {
case DecoderStateTables.COMMENT_II:
processCommentII();
break;
case DecoderStateTables.PROCESSING_INSTRUCTION_II:
processProcessingII();
break;
case DecoderStateTables.TERMINATOR_DOUBLE:
_doubleTerminate = true;
case DecoderStateTables.TERMINATOR_SINGLE:
_terminate = true;
break;
default:
throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.IllegalStateDecodingDII"));
}
}
}
protected final void processDIIOptionalProperties() throws FastInfosetException, IOException {
// Optimize for the most common case
if (_b == EncodingConstants.DOCUMENT_INITIAL_VOCABULARY_FLAG) {
decodeInitialVocabulary();
return;
}
if ((_b & EncodingConstants.DOCUMENT_ADDITIONAL_DATA_FLAG) > 0) {
decodeAdditionalData();
/*
* TODO
* how to report the additional data?
*/
}
if ((_b & EncodingConstants.DOCUMENT_INITIAL_VOCABULARY_FLAG) > 0) {
decodeInitialVocabulary();
}
if ((_b & EncodingConstants.DOCUMENT_NOTATIONS_FLAG) > 0) {
decodeNotations();
// TODO Report notations
}
if ((_b & EncodingConstants.DOCUMENT_UNPARSED_ENTITIES_FLAG) > 0) {
decodeUnparsedEntities();
// TODO Report unparsed entities
}
if ((_b & EncodingConstants.DOCUMENT_CHARACTER_ENCODING_SCHEME) > 0) {
/*String version = */decodeCharacterEncodingScheme();
/*
* TODO
* how to report the character encoding scheme?
*/
}
if ((_b & EncodingConstants.DOCUMENT_STANDALONE_FLAG) > 0) {
/*boolean standalone = (*/read()/* > 0) ? true : false*/ ;
/*
* TODO
* how to report the standalone flag?
*/
}
if ((_b & EncodingConstants.DOCUMENT_VERSION_FLAG) > 0) {
decodeVersion();
/*
* TODO
* how to report the document version?
*/
}
}
@SuppressWarnings("fallthrough")
protected final void processEII(QualifiedName name, boolean hasAttributes) throws FastInfosetException, IOException {
if (_prefixTable._currentInScope[name.prefixIndex] != name.namespaceNameIndex) {
throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.qnameOfEIINotInScope"));
}
final Node parentCurrentNode = _currentNode;
_currentNode = _currentElement = createElement(name.namespaceName, name.qName, name.localName);
if (_namespaceAttributesIndex > 0) {
for (int i = 0; i < _namespaceAttributesIndex; i++) {
_currentElement.setAttributeNode(_namespaceAttributes[i]);
_namespaceAttributes[i] = null;
}
_namespaceAttributesIndex = 0;
}
if (hasAttributes) {
processAIIs();
}
parentCurrentNode.appendChild(_currentElement);
while(!_terminate) {
_b = read();
switch(DecoderStateTables.EII(_b)) {
case DecoderStateTables.EII_NO_AIIS_INDEX_SMALL:
processEII(_elementNameTable._array[_b], false);
break;
case DecoderStateTables.EII_AIIS_INDEX_SMALL:
processEII(_elementNameTable._array[_b & EncodingConstants.INTEGER_3RD_BIT_SMALL_MASK], true);
break;
case DecoderStateTables.EII_INDEX_MEDIUM:
processEII(decodeEIIIndexMedium(), (_b & EncodingConstants.ELEMENT_ATTRIBUTE_FLAG) > 0);
break;
case DecoderStateTables.EII_INDEX_LARGE:
processEII(decodeEIIIndexLarge(), (_b & EncodingConstants.ELEMENT_ATTRIBUTE_FLAG) > 0);
break;
case DecoderStateTables.EII_LITERAL:
{
final QualifiedName qn = processLiteralQualifiedName(
_b & EncodingConstants.LITERAL_QNAME_PREFIX_NAMESPACE_NAME_MASK,
_elementNameTable.getNext());
_elementNameTable.add(qn);
processEII(qn, (_b & EncodingConstants.ELEMENT_ATTRIBUTE_FLAG) > 0);
break;
}
case DecoderStateTables.EII_NAMESPACES:
processEIIWithNamespaces();
break;
case DecoderStateTables.CII_UTF8_SMALL_LENGTH:
{
_octetBufferLength = (_b & EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_SMALL_MASK)
+ 1;
appendOrCreateTextData(processUtf8CharacterString());
break;
}
case DecoderStateTables.CII_UTF8_MEDIUM_LENGTH:
{
_octetBufferLength = read() + EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_SMALL_LIMIT;
appendOrCreateTextData(processUtf8CharacterString());
break;
}
case DecoderStateTables.CII_UTF8_LARGE_LENGTH:
{
_octetBufferLength = (read() << 24) |
(read() << 16) |
(read() << 8) |
read();
_octetBufferLength += EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_MEDIUM_LIMIT;
appendOrCreateTextData(processUtf8CharacterString());
break;
}
case DecoderStateTables.CII_UTF16_SMALL_LENGTH:
{
_octetBufferLength = (_b & EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_SMALL_MASK)
+ 1;
String v = decodeUtf16StringAsString();
if ((_b & EncodingConstants.CHARACTER_CHUNK_ADD_TO_TABLE_FLAG) > 0) {
_characterContentChunkTable.add(_charBuffer, _charBufferLength);
}
appendOrCreateTextData(v);
break;
}
case DecoderStateTables.CII_UTF16_MEDIUM_LENGTH:
{
_octetBufferLength = read() + EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_SMALL_LIMIT;
String v = decodeUtf16StringAsString();
if ((_b & EncodingConstants.CHARACTER_CHUNK_ADD_TO_TABLE_FLAG) > 0) {
_characterContentChunkTable.add(_charBuffer, _charBufferLength);
}
appendOrCreateTextData(v);
break;
}
case DecoderStateTables.CII_UTF16_LARGE_LENGTH:
{
_octetBufferLength = (read() << 24) |
(read() << 16) |
(read() << 8) |
read();
_octetBufferLength += EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_MEDIUM_LIMIT;
String v = decodeUtf16StringAsString();
if ((_b & EncodingConstants.CHARACTER_CHUNK_ADD_TO_TABLE_FLAG) > 0) {
_characterContentChunkTable.add(_charBuffer, _charBufferLength);
}
appendOrCreateTextData(v);
break;
}
case DecoderStateTables.CII_RA:
{
final boolean addToTable = (_b & EncodingConstants.CHARACTER_CHUNK_ADD_TO_TABLE_FLAG) > 0;
// Decode resitricted alphabet integer
_identifier = (_b & 0x02) << 6;
_b = read();
_identifier |= (_b & 0xFC) >> 2;
decodeOctetsOnSeventhBitOfNonIdentifyingStringOnThirdBit(_b);
String v = decodeRestrictedAlphabetAsString();
if (addToTable) {
_characterContentChunkTable.add(_charBuffer, _charBufferLength);
}
appendOrCreateTextData(v);
break;
}
case DecoderStateTables.CII_EA:
{
final boolean addToTable = (_b & EncodingConstants.CHARACTER_CHUNK_ADD_TO_TABLE_FLAG) > 0;
// Decode encoding algorithm integer
_identifier = (_b & 0x02) << 6;
_b = read();
_identifier |= (_b & 0xFC) >> 2;
decodeOctetsOnSeventhBitOfNonIdentifyingStringOnThirdBit(_b);
final String s = convertEncodingAlgorithmDataToCharacters(false);
if (addToTable) {
_characterContentChunkTable.add(s.toCharArray(), s.length());
}
appendOrCreateTextData(s);
break;
}
case DecoderStateTables.CII_INDEX_SMALL:
{
final String s = _characterContentChunkTable.getString(_b & EncodingConstants.INTEGER_4TH_BIT_SMALL_MASK);
appendOrCreateTextData(s);
break;
}
case DecoderStateTables.CII_INDEX_MEDIUM:
{
final int index = (((_b & EncodingConstants.INTEGER_4TH_BIT_MEDIUM_MASK) << 8) | read())
+ EncodingConstants.INTEGER_4TH_BIT_SMALL_LIMIT;
final String s = _characterContentChunkTable.getString(index);
appendOrCreateTextData(s);
break;
}
case DecoderStateTables.CII_INDEX_LARGE:
{
int index = ((_b & EncodingConstants.INTEGER_4TH_BIT_LARGE_MASK) << 16) |
(read() << 8) |
read();
index += EncodingConstants.INTEGER_4TH_BIT_MEDIUM_LIMIT;
final String s = _characterContentChunkTable.getString(index);
appendOrCreateTextData(s);
break;
}
case DecoderStateTables.CII_INDEX_LARGE_LARGE:
{
int index = (read() << 16) |
(read() << 8) |
read();
index += EncodingConstants.INTEGER_4TH_BIT_LARGE_LIMIT;
final String s = _characterContentChunkTable.getString(index);
appendOrCreateTextData(s);
break;
}
case DecoderStateTables.COMMENT_II:
processCommentII();
break;
case DecoderStateTables.PROCESSING_INSTRUCTION_II:
processProcessingII();
break;
case DecoderStateTables.UNEXPANDED_ENTITY_REFERENCE_II:
{
String entity_reference_name = decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherNCName);
String system_identifier = ((_b & EncodingConstants.UNEXPANDED_ENTITY_SYSTEM_IDENTIFIER_FLAG) > 0)
? decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherURI) : null;
String public_identifier = ((_b & EncodingConstants.UNEXPANDED_ENTITY_PUBLIC_IDENTIFIER_FLAG) > 0)
? decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherURI) : null;
// TODO create Node
break;
}
case DecoderStateTables.TERMINATOR_DOUBLE:
_doubleTerminate = true;
case DecoderStateTables.TERMINATOR_SINGLE:
_terminate = true;
break;
default:
throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.IllegalStateDecodingEII"));
}
}
_terminate = _doubleTerminate;
_doubleTerminate = false;
_currentNode = parentCurrentNode;
}
private void appendOrCreateTextData(String textData) {
Node lastChild = _currentNode.getLastChild();
if (lastChild instanceof Text) {
((Text) lastChild).appendData(textData);
} else {
_currentNode.appendChild(
_document.createTextNode(textData));
}
}
private String processUtf8CharacterString() throws FastInfosetException, IOException {
if ((_b & EncodingConstants.CHARACTER_CHUNK_ADD_TO_TABLE_FLAG) > 0) {
_characterContentChunkTable.ensureSize(_octetBufferLength);
final int charactersOffset = _characterContentChunkTable._arrayIndex;
decodeUtf8StringAsCharBuffer(_characterContentChunkTable._array, charactersOffset);
_characterContentChunkTable.add(_charBufferLength);
return _characterContentChunkTable.getString(_characterContentChunkTable._cachedIndex);
} else {
decodeUtf8StringAsCharBuffer();
return new String(_charBuffer, 0, _charBufferLength);
}
}
protected final void processEIIWithNamespaces() throws FastInfosetException, IOException {
final boolean hasAttributes = (_b & EncodingConstants.ELEMENT_ATTRIBUTE_FLAG) > 0;
if (++_prefixTable._declarationId == Integer.MAX_VALUE) {
_prefixTable.clearDeclarationIds();
}
String prefix;
Attr a = null;
final int start = _namespacePrefixesIndex;
int b = read();
while ((b & EncodingConstants.NAMESPACE_ATTRIBUTE_MASK) == EncodingConstants.NAMESPACE_ATTRIBUTE) {
if (_namespaceAttributesIndex == _namespaceAttributes.length) {
final Attr[] newNamespaceAttributes = new Attr[_namespaceAttributesIndex * 3 / 2 + 1];
System.arraycopy(_namespaceAttributes, 0, newNamespaceAttributes, 0, _namespaceAttributesIndex);
_namespaceAttributes = newNamespaceAttributes;
}
if (_namespacePrefixesIndex == _namespacePrefixes.length) {
final int[] namespaceAIIs = new int[_namespacePrefixesIndex * 3 / 2 + 1];
System.arraycopy(_namespacePrefixes, 0, namespaceAIIs, 0, _namespacePrefixesIndex);
_namespacePrefixes = namespaceAIIs;
}
switch (b & EncodingConstants.NAMESPACE_ATTRIBUTE_PREFIX_NAME_MASK) {
// no prefix, no namespace
// Undeclaration of default namespace
case 0:
a = createAttribute(
EncodingConstants.XMLNS_NAMESPACE_NAME,
EncodingConstants.XMLNS_NAMESPACE_PREFIX,
EncodingConstants.XMLNS_NAMESPACE_PREFIX);
a.setValue("");
_prefixIndex = _namespaceNameIndex = _namespacePrefixes[_namespacePrefixesIndex++] = -1;
break;
// no prefix, namespace
// Declaration of default namespace
case 1:
a = createAttribute(
EncodingConstants.XMLNS_NAMESPACE_NAME,
EncodingConstants.XMLNS_NAMESPACE_PREFIX,
EncodingConstants.XMLNS_NAMESPACE_PREFIX);
a.setValue(decodeIdentifyingNonEmptyStringOnFirstBitAsNamespaceName(false));
_prefixIndex = _namespacePrefixes[_namespacePrefixesIndex++] = -1;
break;
// prefix, no namespace
// Undeclaration of namespace
case 2:
prefix = decodeIdentifyingNonEmptyStringOnFirstBitAsPrefix(false);
a = createAttribute(
EncodingConstants.XMLNS_NAMESPACE_NAME,
createQualifiedNameString(prefix),
prefix);
a.setValue("");
_namespaceNameIndex = -1;
_namespacePrefixes[_namespacePrefixesIndex++] = _prefixIndex;
break;
// prefix, namespace
// Declaration of prefixed namespace
case 3:
prefix = decodeIdentifyingNonEmptyStringOnFirstBitAsPrefix(true);
a = createAttribute(
EncodingConstants.XMLNS_NAMESPACE_NAME,
createQualifiedNameString(prefix),
prefix);
a.setValue(decodeIdentifyingNonEmptyStringOnFirstBitAsNamespaceName(true));
_namespacePrefixes[_namespacePrefixesIndex++] = _prefixIndex;
break;
}
_prefixTable.pushScope(_prefixIndex, _namespaceNameIndex);
_namespaceAttributes[_namespaceAttributesIndex++] = a;
b = read();
}
if (b != EncodingConstants.TERMINATOR) {
throw new IOException(CommonResourceBundle.getInstance().getString("message.EIInamespaceNameNotTerminatedCorrectly"));
}
final int end = _namespacePrefixesIndex;
_b = read();
switch(DecoderStateTables.EII(_b)) {
case DecoderStateTables.EII_NO_AIIS_INDEX_SMALL:
processEII(_elementNameTable._array[_b], hasAttributes);
break;
case DecoderStateTables.EII_INDEX_MEDIUM:
processEII(decodeEIIIndexMedium(), hasAttributes);
break;
case DecoderStateTables.EII_INDEX_LARGE:
processEII(decodeEIIIndexLarge(), hasAttributes);
break;
case DecoderStateTables.EII_LITERAL:
{
final QualifiedName qn = processLiteralQualifiedName(
_b & EncodingConstants.LITERAL_QNAME_PREFIX_NAMESPACE_NAME_MASK,
_elementNameTable.getNext());
_elementNameTable.add(qn);
processEII(qn, hasAttributes);
break;
}
default:
throw new IOException(CommonResourceBundle.getInstance().getString("message.IllegalStateDecodingEIIAfterAIIs"));
}
for (int i = start; i < end; i++) {
_prefixTable.popScope(_namespacePrefixes[i]);
}
_namespacePrefixesIndex = start;
}
protected final QualifiedName processLiteralQualifiedName(int state, QualifiedName q)
throws FastInfosetException, IOException {
if (q == null) q = new QualifiedName();
switch (state) {
// no prefix, no namespace
case 0:
return q.set(
null,
null,
decodeIdentifyingNonEmptyStringOnFirstBit(_v.localName),
-1,
-1,
_identifier,
null);
// no prefix, namespace
case 1:
return q.set(
null,
decodeIdentifyingNonEmptyStringIndexOnFirstBitAsNamespaceName(false),
decodeIdentifyingNonEmptyStringOnFirstBit(_v.localName),
-1,
_namespaceNameIndex,
_identifier,
null);
// prefix, no namespace
case 2:
throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.qNameMissingNamespaceName"));
// prefix, namespace
case 3:
return q.set(
decodeIdentifyingNonEmptyStringIndexOnFirstBitAsPrefix(true),
decodeIdentifyingNonEmptyStringIndexOnFirstBitAsNamespaceName(true),
decodeIdentifyingNonEmptyStringOnFirstBit(_v.localName),
_prefixIndex,
_namespaceNameIndex,
_identifier,
_charBuffer);
default:
throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.decodingEII"));
}
}
protected final QualifiedName processLiteralQualifiedName(int state)
throws FastInfosetException, IOException {
switch (state) {
// no prefix, no namespace
case 0:
return new QualifiedName(
null,
null,
decodeIdentifyingNonEmptyStringOnFirstBit(_v.localName),
-1,
-1,
_identifier,
null);
// no prefix, namespace
case 1:
return new QualifiedName(
null,
decodeIdentifyingNonEmptyStringIndexOnFirstBitAsNamespaceName(false),
decodeIdentifyingNonEmptyStringOnFirstBit(_v.localName),
-1,
_namespaceNameIndex,
_identifier,
null);
// prefix, no namespace
case 2:
throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.qNameMissingNamespaceName"));
// prefix, namespace
case 3:
return new QualifiedName(
decodeIdentifyingNonEmptyStringIndexOnFirstBitAsPrefix(true),
decodeIdentifyingNonEmptyStringIndexOnFirstBitAsNamespaceName(true),
decodeIdentifyingNonEmptyStringOnFirstBit(_v.localName),
_prefixIndex,
_namespaceNameIndex,
_identifier,
_charBuffer);
default:
throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.decodingEII"));
}
}
@SuppressWarnings("fallthrough")
protected final void processAIIs() throws FastInfosetException, IOException {
QualifiedName name;
int b;
String value;
if (++_duplicateAttributeVerifier._currentIteration == Integer.MAX_VALUE) {
_duplicateAttributeVerifier.clear();
}
do {
// AII qualified name
b = read();
switch (DecoderStateTables.AII(b)) {
case DecoderStateTables.AII_INDEX_SMALL:
name = _attributeNameTable._array[b];
break;
case DecoderStateTables.AII_INDEX_MEDIUM:
{
final int i = (((b & EncodingConstants.INTEGER_2ND_BIT_MEDIUM_MASK) << 8) | read())
+ EncodingConstants.INTEGER_2ND_BIT_SMALL_LIMIT;
name = _attributeNameTable._array[i];
break;
}
case DecoderStateTables.AII_INDEX_LARGE:
{
final int i = (((b & EncodingConstants.INTEGER_2ND_BIT_LARGE_MASK) << 16) | (read() << 8) | read())
+ EncodingConstants.INTEGER_2ND_BIT_MEDIUM_LIMIT;
name = _attributeNameTable._array[i];
break;
}
case DecoderStateTables.AII_LITERAL:
name = processLiteralQualifiedName(
b & EncodingConstants.LITERAL_QNAME_PREFIX_NAMESPACE_NAME_MASK,
_attributeNameTable.getNext());
name.createAttributeValues(DuplicateAttributeVerifier.MAP_SIZE);
_attributeNameTable.add(name);
break;
case DecoderStateTables.AII_TERMINATOR_DOUBLE:
_doubleTerminate = true;
case DecoderStateTables.AII_TERMINATOR_SINGLE:
_terminate = true;
// AIIs have finished break out of loop
continue;
default:
throw new IOException(CommonResourceBundle.getInstance().getString("message.decodingAIIs"));
}
if (name.prefixIndex > 0 && _prefixTable._currentInScope[name.prefixIndex] != name.namespaceNameIndex) {
throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.AIIqNameNotInScope"));
}
_duplicateAttributeVerifier.checkForDuplicateAttribute(name.attributeHash, name.attributeId);
Attr a = createAttribute(
name.namespaceName,
name.qName,
name.localName);
// [normalized value] of AII
b = read();
switch(DecoderStateTables.NISTRING(b)) {
case DecoderStateTables.NISTRING_UTF8_SMALL_LENGTH:
{
final boolean addToTable = (b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0;
_octetBufferLength = (b & EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_SMALL_MASK) + 1;
value = decodeUtf8StringAsString();
if (addToTable) {
_attributeValueTable.add(value);
}
a.setValue(value);
_currentElement.setAttributeNode(a);
break;
}
case DecoderStateTables.NISTRING_UTF8_MEDIUM_LENGTH:
{
final boolean addToTable = (b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0;
_octetBufferLength = read() + EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_SMALL_LIMIT;
value = decodeUtf8StringAsString();
if (addToTable) {
_attributeValueTable.add(value);
}
a.setValue(value);
_currentElement.setAttributeNode(a);
break;
}
case DecoderStateTables.NISTRING_UTF8_LARGE_LENGTH:
{
final boolean addToTable = (b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0;
final int length = (read() << 24) |
(read() << 16) |
(read() << 8) |
read();
_octetBufferLength = length + EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_MEDIUM_LIMIT;
value = decodeUtf8StringAsString();
if (addToTable) {
_attributeValueTable.add(value);
}
a.setValue(value);
_currentElement.setAttributeNode(a);
break;
}
case DecoderStateTables.NISTRING_UTF16_SMALL_LENGTH:
{
final boolean addToTable = (b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0;
_octetBufferLength = (b & EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_SMALL_MASK) + 1;
value = decodeUtf16StringAsString();
if (addToTable) {
_attributeValueTable.add(value);
}
a.setValue(value);
_currentElement.setAttributeNode(a);
break;
}
case DecoderStateTables.NISTRING_UTF16_MEDIUM_LENGTH:
{
final boolean addToTable = (b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0;
_octetBufferLength = read() + EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_SMALL_LIMIT;
value = decodeUtf16StringAsString();
if (addToTable) {
_attributeValueTable.add(value);
}
a.setValue(value);
_currentElement.setAttributeNode(a);
break;
}
case DecoderStateTables.NISTRING_UTF16_LARGE_LENGTH:
{
final boolean addToTable = (b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0;
final int length = (read() << 24) |
(read() << 16) |
(read() << 8) |
read();
_octetBufferLength = length + EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_MEDIUM_LIMIT;
value = decodeUtf16StringAsString();
if (addToTable) {
_attributeValueTable.add(value);
}
a.setValue(value);
_currentElement.setAttributeNode(a);
break;
}
case DecoderStateTables.NISTRING_RA:
{
final boolean addToTable = (b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0;
// Decode resitricted alphabet integer
_identifier = (b & 0x0F) << 4;
b = read();
_identifier |= (b & 0xF0) >> 4;
decodeOctetsOnFifthBitOfNonIdentifyingStringOnFirstBit(b);
value = decodeRestrictedAlphabetAsString();
if (addToTable) {
_attributeValueTable.add(value);
}
a.setValue(value);
_currentElement.setAttributeNode(a);
break;
}
case DecoderStateTables.NISTRING_EA:
{
final boolean addToTable = (b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0;
_identifier = (b & 0x0F) << 4;
b = read();
_identifier |= (b & 0xF0) >> 4;
decodeOctetsOnFifthBitOfNonIdentifyingStringOnFirstBit(b);
value = convertEncodingAlgorithmDataToCharacters(true);
if (addToTable) {
_attributeValueTable.add(value);
}
a.setValue(value);
_currentElement.setAttributeNode(a);
break;
}
case DecoderStateTables.NISTRING_INDEX_SMALL:
value = _attributeValueTable._array[b & EncodingConstants.INTEGER_2ND_BIT_SMALL_MASK];
a.setValue(value);
_currentElement.setAttributeNode(a);
break;
case DecoderStateTables.NISTRING_INDEX_MEDIUM:
{
final int index = (((b & EncodingConstants.INTEGER_2ND_BIT_MEDIUM_MASK) << 8) | read())
+ EncodingConstants.INTEGER_2ND_BIT_SMALL_LIMIT;
value = _attributeValueTable._array[index];
a.setValue(value);
_currentElement.setAttributeNode(a);
break;
}
case DecoderStateTables.NISTRING_INDEX_LARGE:
{
final int index = (((b & EncodingConstants.INTEGER_2ND_BIT_LARGE_MASK) << 16) | (read() << 8) | read())
+ EncodingConstants.INTEGER_2ND_BIT_MEDIUM_LIMIT;
value = _attributeValueTable._array[index];
a.setValue(value);
_currentElement.setAttributeNode(a);
break;
}
case DecoderStateTables.NISTRING_EMPTY:
a.setValue("");
_currentElement.setAttributeNode(a);
break;
default:
throw new IOException(CommonResourceBundle.getInstance().getString("message.decodingAIIValue"));
}
} while (!_terminate);
// Reset duplication attribute verfifier
_duplicateAttributeVerifier._poolCurrent = _duplicateAttributeVerifier._poolHead;
_terminate = _doubleTerminate;
_doubleTerminate = false;
}
protected final void processCommentII() throws FastInfosetException, IOException {
switch(decodeNonIdentifyingStringOnFirstBit()) {
case NISTRING_STRING:
{
final String s = new String(_charBuffer, 0, _charBufferLength);
if (_addToTable) {
_v.otherString.add(new CharArrayString(s, false));
}
_currentNode.appendChild(_document.createComment(s));
break;
}
case NISTRING_ENCODING_ALGORITHM:
throw new IOException(CommonResourceBundle.getInstance().getString("message.commentIIAlgorithmNotSupported"));
case NISTRING_INDEX:
{
final String s = _v.otherString.get(_integer).toString();
_currentNode.appendChild(_document.createComment(s));
break;
}
case NISTRING_EMPTY_STRING:
_currentNode.appendChild(_document.createComment(""));
break;
}
}
protected final void processProcessingII() throws FastInfosetException, IOException {
final String target = decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherNCName);
switch(decodeNonIdentifyingStringOnFirstBit()) {
case NISTRING_STRING:
{
final String data = new String(_charBuffer, 0, _charBufferLength);
if (_addToTable) {
_v.otherString.add(new CharArrayString(data, false));
}
_currentNode.appendChild(_document.createProcessingInstruction(target, data));
break;
}
case NISTRING_ENCODING_ALGORITHM:
throw new IOException(CommonResourceBundle.getInstance().getString("message.processingIIWithEncodingAlgorithm"));
case NISTRING_INDEX:
{
final String data = _v.otherString.get(_integer).toString();
_currentNode.appendChild(_document.createProcessingInstruction(target, data));
break;
}
case NISTRING_EMPTY_STRING:
_currentNode.appendChild(_document.createProcessingInstruction(target, ""));
break;
}
}
protected Element createElement(String namespaceName, String qName, String localName) {
return _document.createElementNS(namespaceName, qName);
}
protected Attr createAttribute(String namespaceName, String qName, String localName) {
return _document.createAttributeNS(namespaceName, qName);
}
protected String convertEncodingAlgorithmDataToCharacters(boolean isAttributeValue) throws FastInfosetException, IOException {
StringBuffer buffer = new StringBuffer();
if (_identifier < EncodingConstants.ENCODING_ALGORITHM_BUILTIN_END) {
Object array = BuiltInEncodingAlgorithmFactory.getAlgorithm(_identifier).
decodeFromBytes(_octetBuffer, _octetBufferStart, _octetBufferLength);
BuiltInEncodingAlgorithmFactory.getAlgorithm(_identifier).convertToCharacters(array, buffer);
} else if (_identifier == EncodingAlgorithmIndexes.CDATA) {
if (!isAttributeValue) {
// Set back buffer position to start of encoded string
_octetBufferOffset -= _octetBufferLength;
return decodeUtf8StringAsString();
}
throw new EncodingAlgorithmException(CommonResourceBundle.getInstance().getString("message.CDATAAlgorithmNotSupported"));
} else if (_identifier >= EncodingConstants.ENCODING_ALGORITHM_APPLICATION_START) {
final String URI = _v.encodingAlgorithm.get(_identifier - EncodingConstants.ENCODING_ALGORITHM_APPLICATION_START);
final EncodingAlgorithm ea = _registeredEncodingAlgorithms.get(URI);
if (ea != null) {
final Object data = ea.decodeFromBytes(_octetBuffer, _octetBufferStart, _octetBufferLength);
ea.convertToCharacters(data, buffer);
} else {
throw new EncodingAlgorithmException(
CommonResourceBundle.getInstance().getString("message.algorithmDataCannotBeReported"));
}
}
return buffer.toString();
}
}