blob: 2d44b5f319d861a423995dfa34f108912d6ad5a6 [file] [log] [blame]
/*
* Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
* THIS FILE WAS MODIFIED BY SUN MICROSYSTEMS, INC.
*/
package com.sun.xml.internal.fastinfoset.sax;
import com.sun.xml.internal.fastinfoset.Decoder;
import com.sun.xml.internal.fastinfoset.DecoderStateTables;
import com.sun.xml.internal.fastinfoset.EncodingConstants;
import com.sun.xml.internal.fastinfoset.QualifiedName;
import com.sun.xml.internal.fastinfoset.algorithm.BuiltInEncodingAlgorithmFactory;
import com.sun.xml.internal.fastinfoset.algorithm.BuiltInEncodingAlgorithmState;
import com.sun.xml.internal.org.jvnet.fastinfoset.sax.EncodingAlgorithmContentHandler;
import com.sun.xml.internal.org.jvnet.fastinfoset.sax.FastInfosetReader;
import com.sun.xml.internal.org.jvnet.fastinfoset.sax.PrimitiveTypeContentHandler;
import com.sun.xml.internal.fastinfoset.util.CharArray;
import com.sun.xml.internal.fastinfoset.util.CharArrayString;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Map;
import com.sun.xml.internal.org.jvnet.fastinfoset.EncodingAlgorithm;
import com.sun.xml.internal.org.jvnet.fastinfoset.EncodingAlgorithmException;
import com.sun.xml.internal.org.jvnet.fastinfoset.EncodingAlgorithmIndexes;
import com.sun.xml.internal.org.jvnet.fastinfoset.FastInfosetException;
import org.xml.sax.ContentHandler;
import org.xml.sax.DTDHandler;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXNotSupportedException;
import org.xml.sax.SAXParseException;
import org.xml.sax.ext.LexicalHandler;
import org.xml.sax.helpers.DefaultHandler;
import com.sun.xml.internal.fastinfoset.CommonResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.xml.sax.ext.DeclHandler;
/**
* The Fast Infoset SAX parser.
* <p>
* Instantiate this parser to parse a fast infoset document in accordance
* with the SAX API.
*
* <p>
* More than one fast infoset document may be decoded from the
* {@link java.io.InputStream}.
*/
public class SAXDocumentParser extends Decoder implements FastInfosetReader {
private static final Logger logger = Logger.getLogger(SAXDocumentParser.class.getName());
/*
* Empty lexical handler used by default to report
* lexical-based events
*/
private static final class LexicalHandlerImpl implements LexicalHandler {
public void comment(char[] ch, int start, int end) { }
public void startDTD(String name, String publicId, String systemId) { }
public void endDTD() { }
public void startEntity(String name) { }
public void endEntity(String name) { }
public void startCDATA() { }
public void endCDATA() { }
};
/*
* Empty DTD declaration handler used by default to report
* DTD declaration-based events
*/
private static final class DeclHandlerImpl implements DeclHandler {
public void elementDecl(String name, String model) throws SAXException {
}
public void attributeDecl(String eName, String aName,
String type, String mode, String value) throws SAXException {
}
public void internalEntityDecl(String name,
String value) throws SAXException {
}
public void externalEntityDecl(String name,
String publicId, String systemId) throws SAXException {
}
}
/**
* SAX Namespace attributes features
*/
protected boolean _namespacePrefixesFeature = false;
/**
* Reference to entity resolver.
*/
protected EntityResolver _entityResolver;
/**
* Reference to dtd handler.
*/
protected DTDHandler _dtdHandler;
/**
* Reference to content handler.
*/
protected ContentHandler _contentHandler;
/**
* Reference to error handler.
*/
protected ErrorHandler _errorHandler;
/**
* Reference to lexical handler.
*/
protected LexicalHandler _lexicalHandler;
/**
* Reference to DTD declaration handler.
*/
protected DeclHandler _declHandler;
protected EncodingAlgorithmContentHandler _algorithmHandler;
protected PrimitiveTypeContentHandler _primitiveHandler;
protected BuiltInEncodingAlgorithmState builtInAlgorithmState =
new BuiltInEncodingAlgorithmState();
protected AttributesHolder _attributes;
protected int[] _namespacePrefixes = new int[16];
protected int _namespacePrefixesIndex;
protected boolean _clearAttributes = false;
/** Creates a new instance of DocumetParser2 */
public SAXDocumentParser() {
DefaultHandler handler = new DefaultHandler();
_attributes = new AttributesHolder(_registeredEncodingAlgorithms);
_entityResolver = handler;
_dtdHandler = handler;
_contentHandler = handler;
_errorHandler = handler;
_lexicalHandler = new LexicalHandlerImpl();
_declHandler = new DeclHandlerImpl();
}
protected void resetOnError() {
_clearAttributes = false;
_attributes.clear();
_namespacePrefixesIndex = 0;
if (_v != null) {
_v.prefix.clearCompletely();
}
_duplicateAttributeVerifier.clear();
}
// XMLReader interface
public boolean getFeature(String name)
throws SAXNotRecognizedException, SAXNotSupportedException {
if (name.equals(Features.NAMESPACES_FEATURE)) {
return true;
} else if (name.equals(Features.NAMESPACE_PREFIXES_FEATURE)) {
return _namespacePrefixesFeature;
} else if (name.equals(Features.STRING_INTERNING_FEATURE) ||
name.equals(FastInfosetReader.STRING_INTERNING_PROPERTY)) {
return getStringInterning();
} else {
throw new SAXNotRecognizedException(
CommonResourceBundle.getInstance().getString("message.featureNotSupported") + name);
}
}
public void setFeature(String name, boolean value)
throws SAXNotRecognizedException, SAXNotSupportedException {
if (name.equals(Features.NAMESPACES_FEATURE)) {
if (value == false) {
throw new SAXNotSupportedException(name + ":" + value);
}
} else if (name.equals(Features.NAMESPACE_PREFIXES_FEATURE)) {
_namespacePrefixesFeature = value;
} else if (name.equals(Features.STRING_INTERNING_FEATURE) ||
name.equals(FastInfosetReader.STRING_INTERNING_PROPERTY)) {
setStringInterning(value);
} else {
throw new SAXNotRecognizedException(
CommonResourceBundle.getInstance().getString("message.featureNotSupported") + name);
}
}
public Object getProperty(String name)
throws SAXNotRecognizedException, SAXNotSupportedException {
if (name.equals(Properties.LEXICAL_HANDLER_PROPERTY)) {
return getLexicalHandler();
} else if (name.equals(Properties.DTD_DECLARATION_HANDLER_PROPERTY)) {
return getDeclHandler();
} else if (name.equals(FastInfosetReader.EXTERNAL_VOCABULARIES_PROPERTY)) {
return getExternalVocabularies();
} else if (name.equals(FastInfosetReader.REGISTERED_ENCODING_ALGORITHMS_PROPERTY)) {
return getRegisteredEncodingAlgorithms();
} else if (name.equals(FastInfosetReader.ENCODING_ALGORITHM_CONTENT_HANDLER_PROPERTY)) {
return getEncodingAlgorithmContentHandler();
} else if (name.equals(FastInfosetReader.PRIMITIVE_TYPE_CONTENT_HANDLER_PROPERTY)) {
return getPrimitiveTypeContentHandler();
} else {
throw new SAXNotRecognizedException(CommonResourceBundle.getInstance().
getString("message.propertyNotRecognized", new Object[]{name}));
}
}
public void setProperty(String name, Object value)
throws SAXNotRecognizedException, SAXNotSupportedException {
if (name.equals(Properties.LEXICAL_HANDLER_PROPERTY)) {
if (value instanceof LexicalHandler) {
setLexicalHandler((LexicalHandler)value);
} else {
throw new SAXNotSupportedException(Properties.LEXICAL_HANDLER_PROPERTY);
}
} else if (name.equals(Properties.DTD_DECLARATION_HANDLER_PROPERTY)) {
if (value instanceof DeclHandler) {
setDeclHandler((DeclHandler)value);
} else {
throw new SAXNotSupportedException(Properties.LEXICAL_HANDLER_PROPERTY);
}
} else if (name.equals(FastInfosetReader.EXTERNAL_VOCABULARIES_PROPERTY)) {
if (value instanceof Map) {
setExternalVocabularies((Map)value);
} else {
throw new SAXNotSupportedException(FastInfosetReader.EXTERNAL_VOCABULARIES_PROPERTY);
}
} else if (name.equals(FastInfosetReader.REGISTERED_ENCODING_ALGORITHMS_PROPERTY)) {
if (value instanceof Map) {
setRegisteredEncodingAlgorithms((Map)value);
} else {
throw new SAXNotSupportedException(FastInfosetReader.REGISTERED_ENCODING_ALGORITHMS_PROPERTY);
}
} else if (name.equals(FastInfosetReader.ENCODING_ALGORITHM_CONTENT_HANDLER_PROPERTY)) {
if (value instanceof EncodingAlgorithmContentHandler) {
setEncodingAlgorithmContentHandler((EncodingAlgorithmContentHandler)value);
} else {
throw new SAXNotSupportedException(FastInfosetReader.ENCODING_ALGORITHM_CONTENT_HANDLER_PROPERTY);
}
} else if (name.equals(FastInfosetReader.PRIMITIVE_TYPE_CONTENT_HANDLER_PROPERTY)) {
if (value instanceof PrimitiveTypeContentHandler) {
setPrimitiveTypeContentHandler((PrimitiveTypeContentHandler)value);
} else {
throw new SAXNotSupportedException(FastInfosetReader.PRIMITIVE_TYPE_CONTENT_HANDLER_PROPERTY);
}
} else if (name.equals(FastInfosetReader.BUFFER_SIZE_PROPERTY)) {
if (value instanceof Integer) {
setBufferSize(((Integer)value).intValue());
} else {
throw new SAXNotSupportedException(FastInfosetReader.BUFFER_SIZE_PROPERTY);
}
} else {
throw new SAXNotRecognizedException(CommonResourceBundle.getInstance().
getString("message.propertyNotRecognized", new Object[]{name}));
}
}
public void setEntityResolver(EntityResolver resolver) {
_entityResolver = resolver;
}
public EntityResolver getEntityResolver() {
return _entityResolver;
}
public void setDTDHandler(DTDHandler handler) {
_dtdHandler = handler;
}
public DTDHandler getDTDHandler() {
return _dtdHandler;
}
public void setContentHandler(ContentHandler handler) {
_contentHandler = handler;
}
public ContentHandler getContentHandler() {
return _contentHandler;
}
public void setErrorHandler(ErrorHandler handler) {
_errorHandler = handler;
}
public ErrorHandler getErrorHandler() {
return _errorHandler;
}
public void parse(InputSource input) throws IOException, SAXException {
try {
InputStream s = input.getByteStream();
if (s == null) {
String systemId = input.getSystemId();
if (systemId == null) {
throw new SAXException(CommonResourceBundle.getInstance().getString("message.inputSource"));
}
parse(systemId);
} else {
parse(s);
}
} catch (FastInfosetException e) {
logger.log(Level.FINE, "parsing error", e);
throw new SAXException(e);
}
}
public void parse(String systemId) throws IOException, SAXException {
try {
systemId = SystemIdResolver.getAbsoluteURI(systemId);
parse(new URL(systemId).openStream());
} catch (FastInfosetException e) {
logger.log(Level.FINE, "parsing error", e);
throw new SAXException(e);
}
}
// FastInfosetReader
public final void parse(InputStream s) throws IOException, FastInfosetException, SAXException {
setInputStream(s);
parse();
}
public void setLexicalHandler(LexicalHandler handler) {
_lexicalHandler = handler;
}
public LexicalHandler getLexicalHandler() {
return _lexicalHandler;
}
public void setDeclHandler(DeclHandler handler) {
_declHandler = handler;
}
public DeclHandler getDeclHandler() {
return _declHandler;
}
public void setEncodingAlgorithmContentHandler(EncodingAlgorithmContentHandler handler) {
_algorithmHandler = handler;
}
public EncodingAlgorithmContentHandler getEncodingAlgorithmContentHandler() {
return _algorithmHandler;
}
public void setPrimitiveTypeContentHandler(PrimitiveTypeContentHandler handler) {
_primitiveHandler = handler;
}
public PrimitiveTypeContentHandler getPrimitiveTypeContentHandler() {
return _primitiveHandler;
}
public final void parse() throws FastInfosetException, IOException {
if (_octetBuffer.length < _bufferSize) {
_octetBuffer = new byte[_bufferSize];
}
try {
reset();
decodeHeader();
if (_parseFragments)
processDIIFragment();
else
processDII();
} catch (RuntimeException e) {
try {
_errorHandler.fatalError(new SAXParseException(e.getClass().getName(), null, e));
} catch (Exception ee) {
}
resetOnError();
// Wrap runtime exception
throw new FastInfosetException(e);
} catch (FastInfosetException e) {
try {
_errorHandler.fatalError(new SAXParseException(e.getClass().getName(), null, e));
} catch (Exception ee) {
}
resetOnError();
throw e;
} catch (IOException e) {
try {
_errorHandler.fatalError(new SAXParseException(e.getClass().getName(), null, e));
} catch (Exception ee) {
}
resetOnError();
throw e;
}
}
protected final void processDII() throws FastInfosetException, IOException {
try {
_contentHandler.startDocument();
} catch (SAXException e) {
throw new FastInfosetException("processDII", e);
}
_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 = decodeLiteralQualifiedName(
_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) : "";
String public_identifier = ((_b & EncodingConstants.DOCUMENT_TYPE_PUBLIC_IDENTIFIER_FLAG) > 0)
? decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherURI) : "";
_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;
}
if (_notations != null) _notations.clear();
if (_unparsedEntities != null) _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"));
}
}
try {
_contentHandler.endDocument();
} catch (SAXException e) {
throw new FastInfosetException("processDII", e);
}
}
protected final void processDIIFragment() throws FastInfosetException, IOException {
try {
_contentHandler.startDocument();
} catch (SAXException e) {
throw new FastInfosetException("processDII", e);
}
_b = read();
if (_b > 0) {
processDIIOptionalProperties();
}
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 = decodeLiteralQualifiedName(
_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;
processUtf8CharacterString();
break;
case DecoderStateTables.CII_UTF8_MEDIUM_LENGTH:
_octetBufferLength = read() + EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_SMALL_LIMIT;
processUtf8CharacterString();
break;
case DecoderStateTables.CII_UTF8_LARGE_LENGTH:
_octetBufferLength = ((read() << 24) |
(read() << 16) |
(read() << 8) |
read())
+ EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_MEDIUM_LIMIT;
processUtf8CharacterString();
break;
case DecoderStateTables.CII_UTF16_SMALL_LENGTH:
_octetBufferLength = (_b & EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_SMALL_MASK)
+ 1;
decodeUtf16StringAsCharBuffer();
if ((_b & EncodingConstants.CHARACTER_CHUNK_ADD_TO_TABLE_FLAG) > 0) {
_characterContentChunkTable.add(_charBuffer, _charBufferLength);
}
try {
_contentHandler.characters(_charBuffer, 0, _charBufferLength);
} catch (SAXException e) {
throw new FastInfosetException("processCII", e);
}
break;
case DecoderStateTables.CII_UTF16_MEDIUM_LENGTH:
_octetBufferLength = read() + EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_SMALL_LIMIT;
decodeUtf16StringAsCharBuffer();
if ((_b & EncodingConstants.CHARACTER_CHUNK_ADD_TO_TABLE_FLAG) > 0) {
_characterContentChunkTable.add(_charBuffer, _charBufferLength);
}
try {
_contentHandler.characters(_charBuffer, 0, _charBufferLength);
} catch (SAXException e) {
throw new FastInfosetException("processCII", e);
}
break;
case DecoderStateTables.CII_UTF16_LARGE_LENGTH:
_octetBufferLength = ((read() << 24) |
(read() << 16) |
(read() << 8) |
read())
+ EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_MEDIUM_LIMIT;
decodeUtf16StringAsCharBuffer();
if ((_b & EncodingConstants.CHARACTER_CHUNK_ADD_TO_TABLE_FLAG) > 0) {
_characterContentChunkTable.add(_charBuffer, _charBufferLength);
}
try {
_contentHandler.characters(_charBuffer, 0, _charBufferLength);
} catch (SAXException e) {
throw new FastInfosetException("processCII", e);
}
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);
decodeRestrictedAlphabetAsCharBuffer();
if (addToTable) {
_characterContentChunkTable.add(_charBuffer, _charBufferLength);
}
try {
_contentHandler.characters(_charBuffer, 0, _charBufferLength);
} catch (SAXException e) {
throw new FastInfosetException("processCII", e);
}
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);
processCIIEncodingAlgorithm(addToTable);
break;
}
case DecoderStateTables.CII_INDEX_SMALL:
{
final int index = _b & EncodingConstants.INTEGER_4TH_BIT_SMALL_MASK;
try {
_contentHandler.characters(_characterContentChunkTable._array,
_characterContentChunkTable._offset[index],
_characterContentChunkTable._length[index]);
} catch (SAXException e) {
throw new FastInfosetException("processCII", e);
}
break;
}
case DecoderStateTables.CII_INDEX_MEDIUM:
{
final int index = (((_b & EncodingConstants.INTEGER_4TH_BIT_MEDIUM_MASK) << 8) | read())
+ EncodingConstants.INTEGER_4TH_BIT_SMALL_LIMIT;
try {
_contentHandler.characters(_characterContentChunkTable._array,
_characterContentChunkTable._offset[index],
_characterContentChunkTable._length[index]);
} catch (SAXException e) {
throw new FastInfosetException("processCII", e);
}
break;
}
case DecoderStateTables.CII_INDEX_LARGE:
{
final int index = (((_b & EncodingConstants.INTEGER_4TH_BIT_LARGE_MASK) << 16) |
(read() << 8) |
read())
+ EncodingConstants.INTEGER_4TH_BIT_MEDIUM_LIMIT;
try {
_contentHandler.characters(_characterContentChunkTable._array,
_characterContentChunkTable._offset[index],
_characterContentChunkTable._length[index]);
} catch (SAXException e) {
throw new FastInfosetException("processCII", e);
}
break;
}
case DecoderStateTables.CII_INDEX_LARGE_LARGE:
{
final int index = ((read() << 16) |
(read() << 8) |
read())
+ EncodingConstants.INTEGER_4TH_BIT_LARGE_LIMIT;
try {
_contentHandler.characters(_characterContentChunkTable._array,
_characterContentChunkTable._offset[index],
_characterContentChunkTable._length[index]);
} catch (SAXException e) {
throw new FastInfosetException("processCII", e);
}
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) : "";
String public_identifier = ((_b & EncodingConstants.UNEXPANDED_ENTITY_PUBLIC_IDENTIFIER_FLAG) > 0)
? decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherURI) : "";
try {
/*
* TODO
* Need to verify if the skippedEntity method:
* http://java.sun.com/j2se/1.4.2/docs/api/org/xml/sax/ContentHandler.html#skippedEntity(java.lang.String)
* is the correct method to call. It appears so but a more extensive
* check is necessary.
*/
_contentHandler.skippedEntity(entity_reference_name);
} catch (SAXException e) {
throw new FastInfosetException("processUnexpandedEntityReferenceII", e);
}
break;
}
case DecoderStateTables.TERMINATOR_DOUBLE:
_doubleTerminate = true;
case DecoderStateTables.TERMINATOR_SINGLE:
_terminate = true;
break;
default:
throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.IllegalStateDecodingEII"));
}
}
try {
_contentHandler.endDocument();
} catch (SAXException e) {
throw new FastInfosetException("processDII", e);
}
}
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();
/*
try {
_dtdHandler.notationDecl(name, public_identifier, system_identifier);
} catch (SAXException e) {
throw new IOException("NotationsDeclarationII");
}
*/
}
if ((_b & EncodingConstants.DOCUMENT_UNPARSED_ENTITIES_FLAG) > 0) {
decodeUnparsedEntities();
/*
try {
_dtdHandler.unparsedEntityDecl(name, public_identifier, system_identifier, notation_name);
} catch (SAXException e) {
throw new IOException("UnparsedEntitiesII");
}
*/
}
if ((_b & EncodingConstants.DOCUMENT_CHARACTER_ENCODING_SCHEME) > 0) {
/*String characterEncodingScheme = */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 standalone flag?
*/
}
}
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"));
}
if (hasAttributes) {
processAIIs();
}
try {
_contentHandler.startElement(name.namespaceName, name.localName, name.qName, _attributes);
} catch (SAXException e) {
logger.log(Level.FINE, "processEII error", e);
throw new FastInfosetException("processEII", e);
}
if (_clearAttributes) {
_attributes.clear();
_clearAttributes = false;
}
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 = decodeLiteralQualifiedName(
_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;
processUtf8CharacterString();
break;
case DecoderStateTables.CII_UTF8_MEDIUM_LENGTH:
_octetBufferLength = read() + EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_SMALL_LIMIT;
processUtf8CharacterString();
break;
case DecoderStateTables.CII_UTF8_LARGE_LENGTH:
_octetBufferLength = ((read() << 24) |
(read() << 16) |
(read() << 8) |
read())
+ EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_MEDIUM_LIMIT;
processUtf8CharacterString();
break;
case DecoderStateTables.CII_UTF16_SMALL_LENGTH:
_octetBufferLength = (_b & EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_SMALL_MASK)
+ 1;
decodeUtf16StringAsCharBuffer();
if ((_b & EncodingConstants.CHARACTER_CHUNK_ADD_TO_TABLE_FLAG) > 0) {
_characterContentChunkTable.add(_charBuffer, _charBufferLength);
}
try {
_contentHandler.characters(_charBuffer, 0, _charBufferLength);
} catch (SAXException e) {
throw new FastInfosetException("processCII", e);
}
break;
case DecoderStateTables.CII_UTF16_MEDIUM_LENGTH:
_octetBufferLength = read() + EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_SMALL_LIMIT;
decodeUtf16StringAsCharBuffer();
if ((_b & EncodingConstants.CHARACTER_CHUNK_ADD_TO_TABLE_FLAG) > 0) {
_characterContentChunkTable.add(_charBuffer, _charBufferLength);
}
try {
_contentHandler.characters(_charBuffer, 0, _charBufferLength);
} catch (SAXException e) {
throw new FastInfosetException("processCII", e);
}
break;
case DecoderStateTables.CII_UTF16_LARGE_LENGTH:
_octetBufferLength = ((read() << 24) |
(read() << 16) |
(read() << 8) |
read())
+ EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_MEDIUM_LIMIT;
decodeUtf16StringAsCharBuffer();
if ((_b & EncodingConstants.CHARACTER_CHUNK_ADD_TO_TABLE_FLAG) > 0) {
_characterContentChunkTable.add(_charBuffer, _charBufferLength);
}
try {
_contentHandler.characters(_charBuffer, 0, _charBufferLength);
} catch (SAXException e) {
throw new FastInfosetException("processCII", e);
}
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);
decodeRestrictedAlphabetAsCharBuffer();
if (addToTable) {
_characterContentChunkTable.add(_charBuffer, _charBufferLength);
}
try {
_contentHandler.characters(_charBuffer, 0, _charBufferLength);
} catch (SAXException e) {
throw new FastInfosetException("processCII", e);
}
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);
processCIIEncodingAlgorithm(addToTable);
break;
}
case DecoderStateTables.CII_INDEX_SMALL:
{
final int index = _b & EncodingConstants.INTEGER_4TH_BIT_SMALL_MASK;
try {
_contentHandler.characters(_characterContentChunkTable._array,
_characterContentChunkTable._offset[index],
_characterContentChunkTable._length[index]);
} catch (SAXException e) {
throw new FastInfosetException("processCII", e);
}
break;
}
case DecoderStateTables.CII_INDEX_MEDIUM:
{
final int index = (((_b & EncodingConstants.INTEGER_4TH_BIT_MEDIUM_MASK) << 8) | read())
+ EncodingConstants.INTEGER_4TH_BIT_SMALL_LIMIT;
try {
_contentHandler.characters(_characterContentChunkTable._array,
_characterContentChunkTable._offset[index],
_characterContentChunkTable._length[index]);
} catch (SAXException e) {
throw new FastInfosetException("processCII", e);
}
break;
}
case DecoderStateTables.CII_INDEX_LARGE:
{
final int index = (((_b & EncodingConstants.INTEGER_4TH_BIT_LARGE_MASK) << 16) |
(read() << 8) |
read())
+ EncodingConstants.INTEGER_4TH_BIT_MEDIUM_LIMIT;
try {
_contentHandler.characters(_characterContentChunkTable._array,
_characterContentChunkTable._offset[index],
_characterContentChunkTable._length[index]);
} catch (SAXException e) {
throw new FastInfosetException("processCII", e);
}
break;
}
case DecoderStateTables.CII_INDEX_LARGE_LARGE:
{
final int index = ((read() << 16) |
(read() << 8) |
read())
+ EncodingConstants.INTEGER_4TH_BIT_LARGE_LIMIT;
try {
_contentHandler.characters(_characterContentChunkTable._array,
_characterContentChunkTable._offset[index],
_characterContentChunkTable._length[index]);
} catch (SAXException e) {
throw new FastInfosetException("processCII", e);
}
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) : "";
String public_identifier = ((_b & EncodingConstants.UNEXPANDED_ENTITY_PUBLIC_IDENTIFIER_FLAG) > 0)
? decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherURI) : "";
try {
/*
* TODO
* Need to verify if the skippedEntity method:
* http://java.sun.com/j2se/1.4.2/docs/api/org/xml/sax/ContentHandler.html#skippedEntity(java.lang.String)
* is the correct method to call. It appears so but a more extensive
* check is necessary.
*/
_contentHandler.skippedEntity(entity_reference_name);
} catch (SAXException e) {
throw new FastInfosetException("processUnexpandedEntityReferenceII", e);
}
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;
try {
_contentHandler.endElement(name.namespaceName, name.localName, name.qName);
} catch (SAXException e) {
throw new FastInfosetException("processEII", e);
}
}
private final void 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);
try {
_contentHandler.characters(_characterContentChunkTable._array, charactersOffset, _charBufferLength);
} catch (SAXException e) {
throw new FastInfosetException("processCII", e);
}
} else {
decodeUtf8StringAsCharBuffer();
try {
_contentHandler.characters(_charBuffer, 0, _charBufferLength);
} catch (SAXException e) {
throw new FastInfosetException("processCII", e);
}
}
}
protected final void processEIIWithNamespaces() throws FastInfosetException, IOException {
final boolean hasAttributes = (_b & EncodingConstants.ELEMENT_ATTRIBUTE_FLAG) > 0;
_clearAttributes = (_namespacePrefixesFeature) ? true : false;
if (++_prefixTable._declarationId == Integer.MAX_VALUE) {
_prefixTable.clearDeclarationIds();
}
String prefix = "", namespaceName = "";
final int start = _namespacePrefixesIndex;
int b = read();
while ((b & EncodingConstants.NAMESPACE_ATTRIBUTE_MASK) == EncodingConstants.NAMESPACE_ATTRIBUTE) {
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:
prefix = namespaceName = "";
_namespaceNameIndex = _prefixIndex = _namespacePrefixes[_namespacePrefixesIndex++] = -1;
break;
// no prefix, namespace
// Declaration of default namespace
case 1:
prefix = "";
namespaceName = decodeIdentifyingNonEmptyStringOnFirstBitAsNamespaceName(false);
_prefixIndex = _namespacePrefixes[_namespacePrefixesIndex++] = -1;
break;
// prefix, no namespace
// Undeclaration of namespace
case 2:
prefix = decodeIdentifyingNonEmptyStringOnFirstBitAsPrefix(false);
namespaceName = "";
_namespaceNameIndex = -1;
_namespacePrefixes[_namespacePrefixesIndex++] = _prefixIndex;
break;
// prefix, namespace
// Declaration of prefixed namespace
case 3:
prefix = decodeIdentifyingNonEmptyStringOnFirstBitAsPrefix(true);
namespaceName = decodeIdentifyingNonEmptyStringOnFirstBitAsNamespaceName(true);
_namespacePrefixes[_namespacePrefixesIndex++] = _prefixIndex;
break;
}
_prefixTable.pushScope(_prefixIndex, _namespaceNameIndex);
if (_namespacePrefixesFeature) {
// Add the namespace delcaration as an attribute
if (prefix != "") {
_attributes.addAttribute(new QualifiedName(
EncodingConstants.XMLNS_NAMESPACE_PREFIX,
EncodingConstants.XMLNS_NAMESPACE_NAME,
prefix),
namespaceName);
} else {
_attributes.addAttribute(EncodingConstants.DEFAULT_NAMESPACE_DECLARATION,
namespaceName);
}
}
try {
_contentHandler.startPrefixMapping(prefix, namespaceName);
} catch (SAXException e) {
throw new IOException("processStartNamespaceAII");
}
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 = decodeLiteralQualifiedName(
_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"));
}
try {
for (int i = end - 1; i >= start; i--) {
final int prefixIndex = _namespacePrefixes[i];
_prefixTable.popScope(prefixIndex);
prefix = (prefixIndex > 0) ? _prefixTable.get(prefixIndex - 1) :
(prefixIndex == -1) ? "" : EncodingConstants.XML_NAMESPACE_PREFIX;
_contentHandler.endPrefixMapping(prefix);
}
_namespacePrefixesIndex = start;
} catch (SAXException e) {
throw new IOException("processStartNamespaceAII");
}
}
protected final void processAIIs() throws FastInfosetException, IOException {
QualifiedName name;
int b;
String value;
_clearAttributes = true;
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 = decodeLiteralQualifiedName(
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);
// [normalized value] of AII
b = read();
switch(DecoderStateTables.NISTRING(b)) {
case DecoderStateTables.NISTRING_UTF8_SMALL_LENGTH:
_octetBufferLength = (b & EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_SMALL_MASK) + 1;
value = decodeUtf8StringAsString();
if ((b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0) {
_attributeValueTable.add(value);
}
_attributes.addAttribute(name, value);
break;
case DecoderStateTables.NISTRING_UTF8_MEDIUM_LENGTH:
_octetBufferLength = read() + EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_SMALL_LIMIT;
value = decodeUtf8StringAsString();
if ((b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0) {
_attributeValueTable.add(value);
}
_attributes.addAttribute(name, value);
break;
case DecoderStateTables.NISTRING_UTF8_LARGE_LENGTH:
_octetBufferLength = ((read() << 24) |
(read() << 16) |
(read() << 8) |
read())
+ EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_MEDIUM_LIMIT;
value = decodeUtf8StringAsString();
if ((b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0) {
_attributeValueTable.add(value);
}
_attributes.addAttribute(name, value);
break;
case DecoderStateTables.NISTRING_UTF16_SMALL_LENGTH:
_octetBufferLength = (b & EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_SMALL_MASK) + 1;
value = decodeUtf16StringAsString();
if ((b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0) {
_attributeValueTable.add(value);
}
_attributes.addAttribute(name, value);
break;
case DecoderStateTables.NISTRING_UTF16_MEDIUM_LENGTH:
_octetBufferLength = read() + EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_SMALL_LIMIT;
value = decodeUtf16StringAsString();
if ((b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0) {
_attributeValueTable.add(value);
}
_attributes.addAttribute(name, value);
break;
case DecoderStateTables.NISTRING_UTF16_LARGE_LENGTH:
_octetBufferLength = ((read() << 24) |
(read() << 16) |
(read() << 8) |
read())
+ EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_MEDIUM_LIMIT;
value = decodeUtf16StringAsString();
if ((b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0) {
_attributeValueTable.add(value);
}
_attributes.addAttribute(name, value);
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);
}
_attributes.addAttribute(name, value);
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);
processAIIEncodingAlgorithm(name, addToTable);
break;
}
case DecoderStateTables.NISTRING_INDEX_SMALL:
_attributes.addAttribute(name,
_attributeValueTable._array[b & EncodingConstants.INTEGER_2ND_BIT_SMALL_MASK]);
break;
case DecoderStateTables.NISTRING_INDEX_MEDIUM:
{
final int index = (((b & EncodingConstants.INTEGER_2ND_BIT_MEDIUM_MASK) << 8) | read())
+ EncodingConstants.INTEGER_2ND_BIT_SMALL_LIMIT;
_attributes.addAttribute(name,
_attributeValueTable._array[index]);
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;
_attributes.addAttribute(name,
_attributeValueTable._array[index]);
break;
}
case DecoderStateTables.NISTRING_EMPTY:
_attributes.addAttribute(name, "");
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:
if (_addToTable) {
_v.otherString.add(new CharArray(_charBuffer, 0, _charBufferLength, true));
}
try {
_lexicalHandler.comment(_charBuffer, 0, _charBufferLength);
} catch (SAXException e) {
throw new FastInfosetException("processCommentII", e);
}
break;
case NISTRING_ENCODING_ALGORITHM:
throw new IOException(CommonResourceBundle.getInstance().getString("message.commentIIAlgorithmNotSupported"));
case NISTRING_INDEX:
final CharArray ca = _v.otherString.get(_integer);
try {
_lexicalHandler.comment(ca.ch, ca.start, ca.length);
} catch (SAXException e) {
throw new FastInfosetException("processCommentII", e);
}
break;
case NISTRING_EMPTY_STRING:
try {
_lexicalHandler.comment(_charBuffer, 0, 0);
} catch (SAXException e) {
throw new FastInfosetException("processCommentII", e);
}
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));
}
try {
_contentHandler.processingInstruction(target, data);
} catch (SAXException e) {
throw new FastInfosetException("processProcessingII", e);
}
break;
case NISTRING_ENCODING_ALGORITHM:
throw new IOException(CommonResourceBundle.getInstance().getString("message.processingIIWithEncodingAlgorithm"));
case NISTRING_INDEX:
try {
_contentHandler.processingInstruction(target, _v.otherString.get(_integer).toString());
} catch (SAXException e) {
throw new FastInfosetException("processProcessingII", e);
}
break;
case NISTRING_EMPTY_STRING:
try {
_contentHandler.processingInstruction(target, "");
} catch (SAXException e) {
throw new FastInfosetException("processProcessingII", e);
}
break;
}
}
protected final void processCIIEncodingAlgorithm(boolean addToTable) throws FastInfosetException, IOException {
if (_identifier < EncodingConstants.ENCODING_ALGORITHM_BUILTIN_END) {
if (_primitiveHandler != null) {
processCIIBuiltInEncodingAlgorithmAsPrimitive();
} else if (_algorithmHandler != null) {
Object array = processBuiltInEncodingAlgorithmAsObject();
try {
_algorithmHandler.object(null, _identifier, array);
} catch (SAXException e) {
throw new FastInfosetException(e);
}
} else {
StringBuffer buffer = new StringBuffer();
processBuiltInEncodingAlgorithmAsCharacters(buffer);
try {
_contentHandler.characters(buffer.toString().toCharArray(), 0, buffer.length());
} catch (SAXException e) {
throw new FastInfosetException(e);
}
}
if (addToTable) {
StringBuffer buffer = new StringBuffer();
processBuiltInEncodingAlgorithmAsCharacters(buffer);
_characterContentChunkTable.add(buffer.toString().toCharArray(), buffer.length());
}
} else if (_identifier == EncodingAlgorithmIndexes.CDATA) {
// Set back buffer position to start of encoded string
_octetBufferOffset -= _octetBufferLength;
decodeUtf8StringIntoCharBuffer();
try {
_lexicalHandler.startCDATA();
_contentHandler.characters(_charBuffer, 0, _charBufferLength);
_lexicalHandler.endCDATA();
} catch (SAXException e) {
throw new FastInfosetException(e);
}
if (addToTable) {
_characterContentChunkTable.add(_charBuffer, _charBufferLength);
}
} else if (_identifier >= EncodingConstants.ENCODING_ALGORITHM_APPLICATION_START && _algorithmHandler != null) {
final String URI = _v.encodingAlgorithm.get(_identifier - EncodingConstants.ENCODING_ALGORITHM_APPLICATION_START);
if (URI == null) {
throw new EncodingAlgorithmException(CommonResourceBundle.getInstance().
getString("message.URINotPresent", new Object[]{Integer.valueOf(_identifier)}));
}
final EncodingAlgorithm ea = (EncodingAlgorithm)_registeredEncodingAlgorithms.get(URI);
if (ea != null) {
final Object data = ea.decodeFromBytes(_octetBuffer, _octetBufferStart, _octetBufferLength);
try {
_algorithmHandler.object(URI, _identifier, data);
} catch (SAXException e) {
throw new FastInfosetException(e);
}
} else {
try {
_algorithmHandler.octets(URI, _identifier, _octetBuffer, _octetBufferStart, _octetBufferLength);
} catch (SAXException e) {
throw new FastInfosetException(e);
}
}
if (addToTable) {
throw new EncodingAlgorithmException(CommonResourceBundle.getInstance().getString("message.addToTableNotSupported"));
}
} else if (_identifier >= EncodingConstants.ENCODING_ALGORITHM_APPLICATION_START) {
// TODO should have property to ignore
throw new EncodingAlgorithmException(
CommonResourceBundle.getInstance().getString("message.algorithmDataCannotBeReported"));
} else {
// Reserved built-in algorithms for future use
// TODO should use sax property to decide if event will be
// reported, allows for support through handler if required.
throw new EncodingAlgorithmException(CommonResourceBundle.getInstance().getString("message.identifiers10to31Reserved"));
}
}
protected final void processCIIBuiltInEncodingAlgorithmAsPrimitive() throws FastInfosetException, IOException {
try {
int length;
switch(_identifier) {
case EncodingAlgorithmIndexes.HEXADECIMAL:
case EncodingAlgorithmIndexes.BASE64:
_primitiveHandler.bytes(_octetBuffer, _octetBufferStart, _octetBufferLength);
break;
case EncodingAlgorithmIndexes.SHORT:
length = BuiltInEncodingAlgorithmFactory.shortEncodingAlgorithm.
getPrimtiveLengthFromOctetLength(_octetBufferLength);
if (length > builtInAlgorithmState.shortArray.length) {
final short[] array = new short[length * 3 / 2 + 1];
System.arraycopy(builtInAlgorithmState.shortArray, 0,
array, 0, builtInAlgorithmState.shortArray.length);
builtInAlgorithmState.shortArray = array;
}
BuiltInEncodingAlgorithmFactory.shortEncodingAlgorithm.
decodeFromBytesToShortArray(builtInAlgorithmState.shortArray, 0,
_octetBuffer, _octetBufferStart, _octetBufferLength);
_primitiveHandler.shorts(builtInAlgorithmState.shortArray, 0, length);
break;
case EncodingAlgorithmIndexes.INT:
length = BuiltInEncodingAlgorithmFactory.intEncodingAlgorithm.
getPrimtiveLengthFromOctetLength(_octetBufferLength);
if (length > builtInAlgorithmState.intArray.length) {
final int[] array = new int[length * 3 / 2 + 1];
System.arraycopy(builtInAlgorithmState.intArray, 0,
array, 0, builtInAlgorithmState.intArray.length);
builtInAlgorithmState.intArray = array;
}
BuiltInEncodingAlgorithmFactory.intEncodingAlgorithm.
decodeFromBytesToIntArray(builtInAlgorithmState.intArray, 0,
_octetBuffer, _octetBufferStart, _octetBufferLength);
_primitiveHandler.ints(builtInAlgorithmState.intArray, 0, length);
break;
case EncodingAlgorithmIndexes.LONG:
length = BuiltInEncodingAlgorithmFactory.longEncodingAlgorithm.
getPrimtiveLengthFromOctetLength(_octetBufferLength);
if (length > builtInAlgorithmState.longArray.length) {
final long[] array = new long[length * 3 / 2 + 1];
System.arraycopy(builtInAlgorithmState.longArray, 0,
array, 0, builtInAlgorithmState.longArray.length);
builtInAlgorithmState.longArray = array;
}
BuiltInEncodingAlgorithmFactory.longEncodingAlgorithm.
decodeFromBytesToLongArray(builtInAlgorithmState.longArray, 0,
_octetBuffer, _octetBufferStart, _octetBufferLength);
_primitiveHandler.longs(builtInAlgorithmState.longArray, 0, length);
break;
case EncodingAlgorithmIndexes.BOOLEAN:
length = BuiltInEncodingAlgorithmFactory.booleanEncodingAlgorithm.
getPrimtiveLengthFromOctetLength(_octetBufferLength, _octetBuffer[_octetBufferStart] & 0xFF);
if (length > builtInAlgorithmState.booleanArray.length) {
final boolean[] array = new boolean[length * 3 / 2 + 1];
System.arraycopy(builtInAlgorithmState.booleanArray, 0,
array, 0, builtInAlgorithmState.booleanArray.length);
builtInAlgorithmState.booleanArray = array;
}
BuiltInEncodingAlgorithmFactory.booleanEncodingAlgorithm.
decodeFromBytesToBooleanArray(
builtInAlgorithmState.booleanArray, 0, length,
_octetBuffer, _octetBufferStart, _octetBufferLength);
_primitiveHandler.booleans(builtInAlgorithmState.booleanArray, 0, length);
break;
case EncodingAlgorithmIndexes.FLOAT:
length = BuiltInEncodingAlgorithmFactory.floatEncodingAlgorithm.
getPrimtiveLengthFromOctetLength(_octetBufferLength);
if (length > builtInAlgorithmState.floatArray.length) {
final float[] array = new float[length * 3 / 2 + 1];
System.arraycopy(builtInAlgorithmState.floatArray, 0,
array, 0, builtInAlgorithmState.floatArray.length);
builtInAlgorithmState.floatArray = array;
}
BuiltInEncodingAlgorithmFactory.floatEncodingAlgorithm.
decodeFromBytesToFloatArray(builtInAlgorithmState.floatArray, 0,
_octetBuffer, _octetBufferStart, _octetBufferLength);
_primitiveHandler.floats(builtInAlgorithmState.floatArray, 0, length);
break;
case EncodingAlgorithmIndexes.DOUBLE:
length = BuiltInEncodingAlgorithmFactory.doubleEncodingAlgorithm.
getPrimtiveLengthFromOctetLength(_octetBufferLength);
if (length > builtInAlgorithmState.doubleArray.length) {
final double[] array = new double[length * 3 / 2 + 1];
System.arraycopy(builtInAlgorithmState.doubleArray, 0,
array, 0, builtInAlgorithmState.doubleArray.length);
builtInAlgorithmState.doubleArray = array;
}
BuiltInEncodingAlgorithmFactory.doubleEncodingAlgorithm.
decodeFromBytesToDoubleArray(builtInAlgorithmState.doubleArray, 0,
_octetBuffer, _octetBufferStart, _octetBufferLength);
_primitiveHandler.doubles(builtInAlgorithmState.doubleArray, 0, length);
break;
case EncodingAlgorithmIndexes.UUID:
length = BuiltInEncodingAlgorithmFactory.uuidEncodingAlgorithm.
getPrimtiveLengthFromOctetLength(_octetBufferLength);
if (length > builtInAlgorithmState.longArray.length) {
final long[] array = new long[length * 3 / 2 + 1];
System.arraycopy(builtInAlgorithmState.longArray, 0,
array, 0, builtInAlgorithmState.longArray.length);
builtInAlgorithmState.longArray = array;
}
BuiltInEncodingAlgorithmFactory.uuidEncodingAlgorithm.
decodeFromBytesToLongArray(builtInAlgorithmState.longArray, 0,
_octetBuffer, _octetBufferStart, _octetBufferLength);
_primitiveHandler.uuids(builtInAlgorithmState.longArray, 0, length);
break;
case EncodingAlgorithmIndexes.CDATA:
throw new UnsupportedOperationException("CDATA");
default:
throw new FastInfosetException(CommonResourceBundle.getInstance().
getString("message.unsupportedAlgorithm", new Object[]{Integer.valueOf(_identifier)}));
}
} catch (SAXException e) {
throw new FastInfosetException(e);
}
}
protected final void processAIIEncodingAlgorithm(QualifiedName name, boolean addToTable) throws FastInfosetException, IOException {
if (_identifier < EncodingConstants.ENCODING_ALGORITHM_BUILTIN_END) {
if (_primitiveHandler != null || _algorithmHandler != null) {
Object data = processBuiltInEncodingAlgorithmAsObject();
_attributes.addAttributeWithAlgorithmData(name, null, _identifier, data);
} else {
StringBuffer buffer = new StringBuffer();
processBuiltInEncodingAlgorithmAsCharacters(buffer);
_attributes.addAttribute(name, buffer.toString());
}
} else if (_identifier >= EncodingConstants.ENCODING_ALGORITHM_APPLICATION_START && _algorithmHandler != null) {
final String URI = _v.encodingAlgorithm.get(_identifier - EncodingConstants.ENCODING_ALGORITHM_APPLICATION_START);
if (URI == null) {
throw new EncodingAlgorithmException(CommonResourceBundle.getInstance().
getString("message.URINotPresent", new Object[]{Integer.valueOf(_identifier)}));
}
final EncodingAlgorithm ea = (EncodingAlgorithm)_registeredEncodingAlgorithms.get(URI);
if (ea != null) {
final Object data = ea.decodeFromBytes(_octetBuffer, _octetBufferStart, _octetBufferLength);
_attributes.addAttributeWithAlgorithmData(name, URI, _identifier, data);
} else {
final byte[] data = new byte[_octetBufferLength];
System.arraycopy(_octetBuffer, _octetBufferStart, data, 0, _octetBufferLength);
_attributes.addAttributeWithAlgorithmData(name, URI, _identifier, data);
}
} else if (_identifier >= EncodingConstants.ENCODING_ALGORITHM_APPLICATION_START) {
// TODO should have property to ignore
throw new EncodingAlgorithmException(
CommonResourceBundle.getInstance().getString("message.algorithmDataCannotBeReported"));
} else if (_identifier == EncodingAlgorithmIndexes.CDATA) {
throw new EncodingAlgorithmException(CommonResourceBundle.getInstance().getString("message.CDATAAlgorithmNotSupported"));
} else {
// Reserved built-in algorithms for future use
// TODO should use sax property to decide if event will be
// reported, allows for support through handler if required.
throw new EncodingAlgorithmException(CommonResourceBundle.getInstance().getString("message.identifiers10to31Reserved"));
}
if (addToTable) {
_attributeValueTable.add(_attributes.getValue(_attributes.getIndex(name.qName)));
}
}
protected final void processBuiltInEncodingAlgorithmAsCharacters(StringBuffer buffer) throws FastInfosetException, IOException {
// TODO not very efficient, need to reuse buffers
Object array = BuiltInEncodingAlgorithmFactory.getAlgorithm(_identifier).
decodeFromBytes(_octetBuffer, _octetBufferStart, _octetBufferLength);
BuiltInEncodingAlgorithmFactory.getAlgorithm(_identifier).convertToCharacters(array, buffer);
}
protected final Object processBuiltInEncodingAlgorithmAsObject() throws FastInfosetException, IOException {
return BuiltInEncodingAlgorithmFactory.getAlgorithm(_identifier).
decodeFromBytes(_octetBuffer, _octetBufferStart, _octetBufferLength);
}
}