1 /*
   2  * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  *
  25  * THIS FILE WAS MODIFIED BY SUN MICROSYSTEMS, INC.
  26  */
  27 
  28 package com.sun.xml.internal.fastinfoset.sax;
  29 
  30 import com.sun.xml.internal.fastinfoset.Decoder;
  31 import com.sun.xml.internal.fastinfoset.DecoderStateTables;
  32 import com.sun.xml.internal.fastinfoset.EncodingConstants;
  33 import com.sun.xml.internal.fastinfoset.QualifiedName;
  34 import com.sun.xml.internal.fastinfoset.algorithm.BuiltInEncodingAlgorithmFactory;
  35 import com.sun.xml.internal.fastinfoset.algorithm.BuiltInEncodingAlgorithmState;
  36 import com.sun.xml.internal.org.jvnet.fastinfoset.sax.EncodingAlgorithmContentHandler;
  37 import com.sun.xml.internal.org.jvnet.fastinfoset.sax.FastInfosetReader;
  38 import com.sun.xml.internal.org.jvnet.fastinfoset.sax.PrimitiveTypeContentHandler;
  39 import com.sun.xml.internal.fastinfoset.util.CharArray;
  40 import com.sun.xml.internal.fastinfoset.util.CharArrayString;
  41 import java.io.IOException;
  42 import java.io.InputStream;
  43 import java.net.URL;
  44 import java.util.Map;
  45 import com.sun.xml.internal.org.jvnet.fastinfoset.EncodingAlgorithm;
  46 import com.sun.xml.internal.org.jvnet.fastinfoset.EncodingAlgorithmException;
  47 import com.sun.xml.internal.org.jvnet.fastinfoset.EncodingAlgorithmIndexes;
  48 import com.sun.xml.internal.org.jvnet.fastinfoset.FastInfosetException;
  49 import org.xml.sax.ContentHandler;
  50 import org.xml.sax.DTDHandler;
  51 import org.xml.sax.EntityResolver;
  52 import org.xml.sax.ErrorHandler;
  53 import org.xml.sax.InputSource;
  54 import org.xml.sax.SAXException;
  55 import org.xml.sax.SAXNotRecognizedException;
  56 import org.xml.sax.SAXNotSupportedException;
  57 import org.xml.sax.SAXParseException;
  58 import org.xml.sax.ext.LexicalHandler;
  59 import org.xml.sax.helpers.DefaultHandler;
  60 import com.sun.xml.internal.fastinfoset.CommonResourceBundle;
  61 import java.util.logging.Level;
  62 import java.util.logging.Logger;
  63 import org.xml.sax.ext.DeclHandler;
  64 
  65 /**
  66  * The Fast Infoset SAX parser.
  67  * <p>
  68  * Instantiate this parser to parse a fast infoset document in accordance
  69  * with the SAX API.
  70  *
  71  * <p>
  72  * More than one fast infoset document may be decoded from the
  73  * {@link java.io.InputStream}.
  74  */
  75 public class SAXDocumentParser extends Decoder implements FastInfosetReader {
  76     private static final Logger logger = Logger.getLogger(SAXDocumentParser.class.getName());
  77 
  78     /*
  79      * Empty lexical handler used by default to report
  80      * lexical-based events
  81      */
  82     private static final class LexicalHandlerImpl implements LexicalHandler {
  83         public void comment(char[] ch, int start, int end) { }
  84 
  85         public void startDTD(String name, String publicId, String systemId) { }
  86         public void endDTD() { }
  87 
  88         public void startEntity(String name) { }
  89         public void endEntity(String name) { }
  90 
  91         public void startCDATA() { }
  92         public void endCDATA() { }
  93     };
  94 
  95     /*
  96      * Empty DTD declaration handler used by default to report
  97      * DTD declaration-based events
  98      */
  99     private static final class DeclHandlerImpl implements DeclHandler {
 100         public void elementDecl(String name, String model) throws SAXException {
 101         }
 102 
 103         public void attributeDecl(String eName, String aName,
 104                 String type, String mode, String value) throws SAXException {
 105         }
 106 
 107         public void internalEntityDecl(String name,
 108                 String value) throws SAXException {
 109         }
 110 
 111         public void externalEntityDecl(String name,
 112                 String publicId, String systemId) throws SAXException {
 113         }
 114     }
 115 
 116     /**
 117      * SAX Namespace attributes features
 118      */
 119     protected boolean _namespacePrefixesFeature = false;
 120 
 121     /**
 122      * Reference to entity resolver.
 123      */
 124     protected EntityResolver _entityResolver;
 125 
 126     /**
 127      * Reference to dtd handler.
 128      */
 129     protected DTDHandler _dtdHandler;
 130 
 131     /**
 132      * Reference to content handler.
 133      */
 134     protected ContentHandler _contentHandler;
 135 
 136     /**
 137      * Reference to error handler.
 138      */
 139     protected ErrorHandler _errorHandler;
 140 
 141     /**
 142      * Reference to lexical handler.
 143      */
 144     protected LexicalHandler _lexicalHandler;
 145 
 146     /**
 147      * Reference to DTD declaration handler.
 148      */
 149     protected DeclHandler _declHandler;
 150 
 151     protected EncodingAlgorithmContentHandler _algorithmHandler;
 152 
 153     protected PrimitiveTypeContentHandler _primitiveHandler;
 154 
 155     protected BuiltInEncodingAlgorithmState builtInAlgorithmState =
 156             new BuiltInEncodingAlgorithmState();
 157 
 158     protected AttributesHolder _attributes;
 159 
 160     protected int[] _namespacePrefixes = new int[16];
 161 
 162     protected int _namespacePrefixesIndex;
 163 
 164     protected boolean _clearAttributes = false;
 165 
 166     /** Creates a new instance of DocumetParser2 */
 167     public SAXDocumentParser() {
 168         DefaultHandler handler = new DefaultHandler();
 169         _attributes = new AttributesHolder(_registeredEncodingAlgorithms);
 170 
 171         _entityResolver = handler;
 172         _dtdHandler = handler;
 173         _contentHandler = handler;
 174         _errorHandler = handler;
 175         _lexicalHandler = new LexicalHandlerImpl();
 176         _declHandler = new DeclHandlerImpl();
 177     }
 178 
 179     protected void resetOnError() {
 180         _clearAttributes = false;
 181         _attributes.clear();
 182         _namespacePrefixesIndex = 0;
 183 
 184         if (_v != null) {
 185             _v.prefix.clearCompletely();
 186         }
 187         _duplicateAttributeVerifier.clear();
 188     }
 189 
 190     // XMLReader interface
 191 
 192     public boolean getFeature(String name)
 193     throws SAXNotRecognizedException, SAXNotSupportedException {
 194         if (name.equals(Features.NAMESPACES_FEATURE)) {
 195             return true;
 196         } else if (name.equals(Features.NAMESPACE_PREFIXES_FEATURE)) {
 197             return _namespacePrefixesFeature;
 198         } else if (name.equals(Features.STRING_INTERNING_FEATURE) ||
 199                 name.equals(FastInfosetReader.STRING_INTERNING_PROPERTY)) {
 200             return getStringInterning();
 201         } else {
 202             throw new SAXNotRecognizedException(
 203                     CommonResourceBundle.getInstance().getString("message.featureNotSupported") + name);
 204         }
 205     }
 206 
 207     public void setFeature(String name, boolean value)
 208     throws SAXNotRecognizedException, SAXNotSupportedException {
 209         if (name.equals(Features.NAMESPACES_FEATURE)) {
 210             if (value == false) {
 211                 throw new SAXNotSupportedException(name + ":" + value);
 212             }
 213         } else if (name.equals(Features.NAMESPACE_PREFIXES_FEATURE)) {
 214             _namespacePrefixesFeature = value;
 215         } else if (name.equals(Features.STRING_INTERNING_FEATURE) ||
 216                 name.equals(FastInfosetReader.STRING_INTERNING_PROPERTY)) {
 217             setStringInterning(value);
 218         } else {
 219             throw new SAXNotRecognizedException(
 220                     CommonResourceBundle.getInstance().getString("message.featureNotSupported") + name);
 221         }
 222     }
 223 
 224     public Object getProperty(String name)
 225     throws SAXNotRecognizedException, SAXNotSupportedException {
 226         if (name.equals(Properties.LEXICAL_HANDLER_PROPERTY)) {
 227             return getLexicalHandler();
 228         } else if (name.equals(Properties.DTD_DECLARATION_HANDLER_PROPERTY)) {
 229             return getDeclHandler();
 230         } else if (name.equals(FastInfosetReader.EXTERNAL_VOCABULARIES_PROPERTY)) {
 231             return getExternalVocabularies();
 232         } else if (name.equals(FastInfosetReader.REGISTERED_ENCODING_ALGORITHMS_PROPERTY)) {
 233             return getRegisteredEncodingAlgorithms();
 234         } else if (name.equals(FastInfosetReader.ENCODING_ALGORITHM_CONTENT_HANDLER_PROPERTY)) {
 235             return getEncodingAlgorithmContentHandler();
 236         } else if (name.equals(FastInfosetReader.PRIMITIVE_TYPE_CONTENT_HANDLER_PROPERTY)) {
 237             return getPrimitiveTypeContentHandler();
 238         } else {
 239             throw new SAXNotRecognizedException(CommonResourceBundle.getInstance().
 240                     getString("message.propertyNotRecognized", new Object[]{name}));
 241         }
 242     }
 243 
 244     public void setProperty(String name, Object value)
 245     throws SAXNotRecognizedException, SAXNotSupportedException {
 246         if (name.equals(Properties.LEXICAL_HANDLER_PROPERTY)) {
 247             if (value instanceof LexicalHandler) {
 248                 setLexicalHandler((LexicalHandler)value);
 249             } else {
 250                 throw new SAXNotSupportedException(Properties.LEXICAL_HANDLER_PROPERTY);
 251             }
 252         } else if (name.equals(Properties.DTD_DECLARATION_HANDLER_PROPERTY)) {
 253             if (value instanceof DeclHandler) {
 254                 setDeclHandler((DeclHandler)value);
 255             } else {
 256                 throw new SAXNotSupportedException(Properties.LEXICAL_HANDLER_PROPERTY);
 257             }
 258         } else if (name.equals(FastInfosetReader.EXTERNAL_VOCABULARIES_PROPERTY)) {
 259             if (value instanceof Map) {
 260                 setExternalVocabularies((Map)value);
 261             } else {
 262                 throw new SAXNotSupportedException(FastInfosetReader.EXTERNAL_VOCABULARIES_PROPERTY);
 263             }
 264         } else if (name.equals(FastInfosetReader.REGISTERED_ENCODING_ALGORITHMS_PROPERTY)) {
 265             if (value instanceof Map) {
 266                 setRegisteredEncodingAlgorithms((Map)value);
 267             } else {
 268                 throw new SAXNotSupportedException(FastInfosetReader.REGISTERED_ENCODING_ALGORITHMS_PROPERTY);
 269             }
 270         } else if (name.equals(FastInfosetReader.ENCODING_ALGORITHM_CONTENT_HANDLER_PROPERTY)) {
 271             if (value instanceof EncodingAlgorithmContentHandler) {
 272                 setEncodingAlgorithmContentHandler((EncodingAlgorithmContentHandler)value);
 273             } else {
 274                 throw new SAXNotSupportedException(FastInfosetReader.ENCODING_ALGORITHM_CONTENT_HANDLER_PROPERTY);
 275             }
 276         } else if (name.equals(FastInfosetReader.PRIMITIVE_TYPE_CONTENT_HANDLER_PROPERTY)) {
 277             if (value instanceof PrimitiveTypeContentHandler) {
 278                 setPrimitiveTypeContentHandler((PrimitiveTypeContentHandler)value);
 279             } else {
 280                 throw new SAXNotSupportedException(FastInfosetReader.PRIMITIVE_TYPE_CONTENT_HANDLER_PROPERTY);
 281             }
 282         } else if (name.equals(FastInfosetReader.BUFFER_SIZE_PROPERTY)) {
 283             if (value instanceof Integer) {
 284                 setBufferSize(((Integer)value).intValue());
 285             } else {
 286                 throw new SAXNotSupportedException(FastInfosetReader.BUFFER_SIZE_PROPERTY);
 287             }
 288         } else {
 289             throw new SAXNotRecognizedException(CommonResourceBundle.getInstance().
 290                     getString("message.propertyNotRecognized", new Object[]{name}));
 291         }
 292     }
 293 
 294     public void setEntityResolver(EntityResolver resolver) {
 295         _entityResolver = resolver;
 296     }
 297 
 298     public EntityResolver getEntityResolver() {
 299         return _entityResolver;
 300     }
 301 
 302     public void setDTDHandler(DTDHandler handler) {
 303         _dtdHandler = handler;
 304     }
 305 
 306     public DTDHandler getDTDHandler() {
 307         return _dtdHandler;
 308     }
 309     public void setContentHandler(ContentHandler handler) {
 310         _contentHandler = handler;
 311     }
 312 
 313     public ContentHandler getContentHandler() {
 314         return _contentHandler;
 315     }
 316 
 317     public void setErrorHandler(ErrorHandler handler) {
 318         _errorHandler = handler;
 319     }
 320 
 321     public ErrorHandler getErrorHandler() {
 322         return _errorHandler;
 323     }
 324 
 325     public void parse(InputSource input) throws IOException, SAXException {
 326         try {
 327             InputStream s = input.getByteStream();
 328             if (s == null) {
 329                 String systemId = input.getSystemId();
 330                 if (systemId == null) {
 331                     throw new SAXException(CommonResourceBundle.getInstance().getString("message.inputSource"));
 332                 }
 333                 parse(systemId);
 334             } else {
 335                 parse(s);
 336             }
 337         } catch (FastInfosetException e) {
 338             logger.log(Level.FINE, "parsing error", e);
 339             throw new SAXException(e);
 340         }
 341     }
 342 
 343     public void parse(String systemId) throws IOException, SAXException {
 344         try {
 345             systemId = SystemIdResolver.getAbsoluteURI(systemId);
 346             parse(new URL(systemId).openStream());
 347         } catch (FastInfosetException e) {
 348             logger.log(Level.FINE, "parsing error", e);
 349             throw new SAXException(e);
 350         }
 351     }
 352 
 353 
 354 
 355 
 356     // FastInfosetReader
 357 
 358     public final void parse(InputStream s) throws IOException, FastInfosetException, SAXException {
 359         setInputStream(s);
 360         parse();
 361     }
 362 
 363     public void setLexicalHandler(LexicalHandler handler) {
 364         _lexicalHandler = handler;
 365     }
 366 
 367     public LexicalHandler getLexicalHandler() {
 368         return _lexicalHandler;
 369     }
 370 
 371     public void setDeclHandler(DeclHandler handler) {
 372         _declHandler = handler;
 373     }
 374 
 375     public DeclHandler getDeclHandler() {
 376         return _declHandler;
 377     }
 378 
 379     public void setEncodingAlgorithmContentHandler(EncodingAlgorithmContentHandler handler) {
 380         _algorithmHandler = handler;
 381     }
 382 
 383     public EncodingAlgorithmContentHandler getEncodingAlgorithmContentHandler() {
 384         return _algorithmHandler;
 385     }
 386 
 387     public void setPrimitiveTypeContentHandler(PrimitiveTypeContentHandler handler) {
 388         _primitiveHandler = handler;
 389     }
 390 
 391     public PrimitiveTypeContentHandler getPrimitiveTypeContentHandler() {
 392         return _primitiveHandler;
 393     }
 394 
 395 
 396 
 397 
 398     public final void parse() throws FastInfosetException, IOException {
 399         if (_octetBuffer.length < _bufferSize) {
 400             _octetBuffer = new byte[_bufferSize];
 401         }
 402 
 403         try {
 404             reset();
 405             decodeHeader();
 406             if (_parseFragments)
 407                 processDIIFragment();
 408             else
 409                 processDII();
 410         } catch (RuntimeException e) {
 411             try {
 412                 _errorHandler.fatalError(new SAXParseException(e.getClass().getName(), null, e));
 413             } catch (Exception ee) {
 414             }
 415             resetOnError();
 416             // Wrap runtime exception
 417             throw new FastInfosetException(e);
 418         } catch (FastInfosetException e) {
 419             try {
 420                 _errorHandler.fatalError(new SAXParseException(e.getClass().getName(), null, e));
 421             } catch (Exception ee) {
 422             }
 423             resetOnError();
 424             throw e;
 425         } catch (IOException e) {
 426             try {
 427                 _errorHandler.fatalError(new SAXParseException(e.getClass().getName(), null, e));
 428             } catch (Exception ee) {
 429             }
 430             resetOnError();
 431             throw e;
 432         }
 433     }
 434 
 435     protected final void processDII() throws FastInfosetException, IOException {
 436         try {
 437             _contentHandler.startDocument();
 438         } catch (SAXException e) {
 439             throw new FastInfosetException("processDII", e);
 440         }
 441 
 442         _b = read();
 443         if (_b > 0) {
 444             processDIIOptionalProperties();
 445         }
 446 
 447         // Decode one Document Type II, Comment IIs, PI IIs and one EII
 448         boolean firstElementHasOccured = false;
 449         boolean documentTypeDeclarationOccured = false;
 450         while(!_terminate || !firstElementHasOccured) {
 451             _b = read();
 452             switch(DecoderStateTables.DII(_b)) {
 453                 case DecoderStateTables.EII_NO_AIIS_INDEX_SMALL:
 454                     processEII(_elementNameTable._array[_b], false);
 455                     firstElementHasOccured = true;
 456                     break;
 457                 case DecoderStateTables.EII_AIIS_INDEX_SMALL:
 458                     processEII(_elementNameTable._array[_b & EncodingConstants.INTEGER_3RD_BIT_SMALL_MASK], true);
 459                     firstElementHasOccured = true;
 460                     break;
 461                 case DecoderStateTables.EII_INDEX_MEDIUM:
 462                     processEII(decodeEIIIndexMedium(), (_b & EncodingConstants.ELEMENT_ATTRIBUTE_FLAG) > 0);
 463                     firstElementHasOccured = true;
 464                     break;
 465                 case DecoderStateTables.EII_INDEX_LARGE:
 466                     processEII(decodeEIIIndexLarge(), (_b & EncodingConstants.ELEMENT_ATTRIBUTE_FLAG) > 0);
 467                     firstElementHasOccured = true;
 468                     break;
 469                 case DecoderStateTables.EII_LITERAL:
 470                 {
 471                     final QualifiedName qn = decodeLiteralQualifiedName(
 472                             _b & EncodingConstants.LITERAL_QNAME_PREFIX_NAMESPACE_NAME_MASK,
 473                             _elementNameTable.getNext());
 474                     _elementNameTable.add(qn);
 475                     processEII(qn, (_b & EncodingConstants.ELEMENT_ATTRIBUTE_FLAG) > 0);
 476                     firstElementHasOccured = true;
 477                     break;
 478                 }
 479                 case DecoderStateTables.EII_NAMESPACES:
 480                     processEIIWithNamespaces();
 481                     firstElementHasOccured = true;
 482                     break;
 483                 case DecoderStateTables.DOCUMENT_TYPE_DECLARATION_II:
 484                 {
 485                     if (documentTypeDeclarationOccured) {
 486                         throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.secondOccurenceOfDTDII"));
 487                     }
 488                     documentTypeDeclarationOccured = true;
 489 
 490                     String system_identifier = ((_b & EncodingConstants.DOCUMENT_TYPE_SYSTEM_IDENTIFIER_FLAG) > 0)
 491                     ? decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherURI) : "";
 492                     String public_identifier = ((_b & EncodingConstants.DOCUMENT_TYPE_PUBLIC_IDENTIFIER_FLAG) > 0)
 493                     ? decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherURI) : "";
 494 
 495                     _b = read();
 496                     while (_b == EncodingConstants.PROCESSING_INSTRUCTION) {
 497                         switch(decodeNonIdentifyingStringOnFirstBit()) {
 498                             case NISTRING_STRING:
 499                                 if (_addToTable) {
 500                                     _v.otherString.add(new CharArray(_charBuffer, 0, _charBufferLength, true));
 501                                 }
 502                                 break;
 503                             case NISTRING_ENCODING_ALGORITHM:
 504                                 throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.processingIIWithEncodingAlgorithm"));
 505                             case NISTRING_INDEX:
 506                                 break;
 507                             case NISTRING_EMPTY_STRING:
 508                                 break;
 509                         }
 510                         _b = read();
 511                     }
 512                     if ((_b & EncodingConstants.TERMINATOR) != EncodingConstants.TERMINATOR) {
 513                         throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.processingInstructionIIsNotTerminatedCorrectly"));
 514                     }
 515                     if (_b == EncodingConstants.DOUBLE_TERMINATOR) {
 516                         _terminate = true;
 517                     }
 518 
 519                     if (_notations != null) _notations.clear();
 520                     if (_unparsedEntities != null) _unparsedEntities.clear();
 521                     /*
 522                      * TODO
 523                      * Report All events associated with DTD, PIs, notations etc
 524                      */
 525                     break;
 526                 }
 527                 case DecoderStateTables.COMMENT_II:
 528                     processCommentII();
 529                     break;
 530                 case DecoderStateTables.PROCESSING_INSTRUCTION_II:
 531                     processProcessingII();
 532                     break;
 533                 case DecoderStateTables.TERMINATOR_DOUBLE:
 534                     _doubleTerminate = true;
 535                 case DecoderStateTables.TERMINATOR_SINGLE:
 536                     _terminate = true;
 537                     break;
 538                 default:
 539                     throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.IllegalStateDecodingDII"));
 540             }
 541         }
 542 
 543         // Decode any remaining Comment IIs, PI IIs
 544         while(!_terminate) {
 545             _b = read();
 546             switch(DecoderStateTables.DII(_b)) {
 547                 case DecoderStateTables.COMMENT_II:
 548                     processCommentII();
 549                     break;
 550                 case DecoderStateTables.PROCESSING_INSTRUCTION_II:
 551                     processProcessingII();
 552                     break;
 553                 case DecoderStateTables.TERMINATOR_DOUBLE:
 554                     _doubleTerminate = true;
 555                 case DecoderStateTables.TERMINATOR_SINGLE:
 556                     _terminate = true;
 557                     break;
 558                 default:
 559                     throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.IllegalStateDecodingDII"));
 560             }
 561         }
 562 
 563         try {
 564             _contentHandler.endDocument();
 565         } catch (SAXException e) {
 566             throw new FastInfosetException("processDII", e);
 567         }
 568     }
 569 
 570     protected final void processDIIFragment() throws FastInfosetException, IOException {
 571         try {
 572             _contentHandler.startDocument();
 573         } catch (SAXException e) {
 574             throw new FastInfosetException("processDII", e);
 575         }
 576 
 577         _b = read();
 578         if (_b > 0) {
 579             processDIIOptionalProperties();
 580         }
 581 
 582         while(!_terminate) {
 583             _b = read();
 584             switch(DecoderStateTables.EII(_b)) {
 585                 case DecoderStateTables.EII_NO_AIIS_INDEX_SMALL:
 586                     processEII(_elementNameTable._array[_b], false);
 587                     break;
 588                 case DecoderStateTables.EII_AIIS_INDEX_SMALL:
 589                     processEII(_elementNameTable._array[_b & EncodingConstants.INTEGER_3RD_BIT_SMALL_MASK], true);
 590                     break;
 591                 case DecoderStateTables.EII_INDEX_MEDIUM:
 592                     processEII(decodeEIIIndexMedium(), (_b & EncodingConstants.ELEMENT_ATTRIBUTE_FLAG) > 0);
 593                     break;
 594                 case DecoderStateTables.EII_INDEX_LARGE:
 595                     processEII(decodeEIIIndexLarge(), (_b & EncodingConstants.ELEMENT_ATTRIBUTE_FLAG) > 0);
 596                     break;
 597                 case DecoderStateTables.EII_LITERAL:
 598                 {
 599                     final QualifiedName qn = decodeLiteralQualifiedName(
 600                             _b & EncodingConstants.LITERAL_QNAME_PREFIX_NAMESPACE_NAME_MASK,
 601                             _elementNameTable.getNext());
 602                     _elementNameTable.add(qn);
 603                     processEII(qn, (_b & EncodingConstants.ELEMENT_ATTRIBUTE_FLAG) > 0);
 604                     break;
 605                 }
 606                 case DecoderStateTables.EII_NAMESPACES:
 607                     processEIIWithNamespaces();
 608                     break;
 609                 case DecoderStateTables.CII_UTF8_SMALL_LENGTH:
 610                     _octetBufferLength = (_b & EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_SMALL_MASK)
 611                     + 1;
 612                     processUtf8CharacterString();
 613                     break;
 614                 case DecoderStateTables.CII_UTF8_MEDIUM_LENGTH:
 615                     _octetBufferLength = read() + EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_SMALL_LIMIT;
 616                     processUtf8CharacterString();
 617                     break;
 618                 case DecoderStateTables.CII_UTF8_LARGE_LENGTH:
 619                     _octetBufferLength = ((read() << 24) |
 620                             (read() << 16) |
 621                             (read() << 8) |
 622                             read())
 623                             + EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_MEDIUM_LIMIT;
 624                     processUtf8CharacterString();
 625                     break;
 626                 case DecoderStateTables.CII_UTF16_SMALL_LENGTH:
 627                     _octetBufferLength = (_b & EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_SMALL_MASK)
 628                     + 1;
 629                     decodeUtf16StringAsCharBuffer();
 630                     if ((_b & EncodingConstants.CHARACTER_CHUNK_ADD_TO_TABLE_FLAG) > 0) {
 631                         _characterContentChunkTable.add(_charBuffer, _charBufferLength);
 632                     }
 633 
 634                     try {
 635                         _contentHandler.characters(_charBuffer, 0, _charBufferLength);
 636                     } catch (SAXException e) {
 637                         throw new FastInfosetException("processCII", e);
 638                     }
 639                     break;
 640                 case DecoderStateTables.CII_UTF16_MEDIUM_LENGTH:
 641                     _octetBufferLength = read() + EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_SMALL_LIMIT;
 642                     decodeUtf16StringAsCharBuffer();
 643                     if ((_b & EncodingConstants.CHARACTER_CHUNK_ADD_TO_TABLE_FLAG) > 0) {
 644                         _characterContentChunkTable.add(_charBuffer, _charBufferLength);
 645                     }
 646 
 647                     try {
 648                         _contentHandler.characters(_charBuffer, 0, _charBufferLength);
 649                     } catch (SAXException e) {
 650                         throw new FastInfosetException("processCII", e);
 651                     }
 652                     break;
 653                 case DecoderStateTables.CII_UTF16_LARGE_LENGTH:
 654                     _octetBufferLength = ((read() << 24) |
 655                             (read() << 16) |
 656                             (read() << 8) |
 657                             read())
 658                             + EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_MEDIUM_LIMIT;
 659                     decodeUtf16StringAsCharBuffer();
 660                     if ((_b & EncodingConstants.CHARACTER_CHUNK_ADD_TO_TABLE_FLAG) > 0) {
 661                         _characterContentChunkTable.add(_charBuffer, _charBufferLength);
 662                     }
 663 
 664                     try {
 665                         _contentHandler.characters(_charBuffer, 0, _charBufferLength);
 666                     } catch (SAXException e) {
 667                         throw new FastInfosetException("processCII", e);
 668                     }
 669                     break;
 670                 case DecoderStateTables.CII_RA:
 671                 {
 672                     final boolean addToTable = (_b & EncodingConstants.CHARACTER_CHUNK_ADD_TO_TABLE_FLAG) > 0;
 673 
 674                     // Decode resitricted alphabet integer
 675                     _identifier = (_b & 0x02) << 6;
 676                     _b = read();
 677                     _identifier |= (_b & 0xFC) >> 2;
 678 
 679                     decodeOctetsOnSeventhBitOfNonIdentifyingStringOnThirdBit(_b);
 680 
 681                     decodeRestrictedAlphabetAsCharBuffer();
 682 
 683                     if (addToTable) {
 684                         _characterContentChunkTable.add(_charBuffer, _charBufferLength);
 685                     }
 686 
 687                     try {
 688                         _contentHandler.characters(_charBuffer, 0, _charBufferLength);
 689                     } catch (SAXException e) {
 690                         throw new FastInfosetException("processCII", e);
 691                     }
 692                     break;
 693                 }
 694                 case DecoderStateTables.CII_EA:
 695                 {
 696                     final boolean addToTable = (_b & EncodingConstants.CHARACTER_CHUNK_ADD_TO_TABLE_FLAG) > 0;
 697 
 698                     // Decode encoding algorithm integer
 699                     _identifier = (_b & 0x02) << 6;
 700                     _b = read();
 701                     _identifier |= (_b & 0xFC) >> 2;
 702 
 703                     decodeOctetsOnSeventhBitOfNonIdentifyingStringOnThirdBit(_b);
 704 
 705                     processCIIEncodingAlgorithm(addToTable);
 706                     break;
 707                 }
 708                 case DecoderStateTables.CII_INDEX_SMALL:
 709                 {
 710                     final int index = _b & EncodingConstants.INTEGER_4TH_BIT_SMALL_MASK;
 711                     try {
 712                         _contentHandler.characters(_characterContentChunkTable._array,
 713                                 _characterContentChunkTable._offset[index],
 714                                 _characterContentChunkTable._length[index]);
 715                     } catch (SAXException e) {
 716                         throw new FastInfosetException("processCII", e);
 717                     }
 718                     break;
 719                 }
 720                 case DecoderStateTables.CII_INDEX_MEDIUM:
 721                 {
 722                     final int index = (((_b & EncodingConstants.INTEGER_4TH_BIT_MEDIUM_MASK) << 8) | read())
 723                     + EncodingConstants.INTEGER_4TH_BIT_SMALL_LIMIT;
 724                     try {
 725                         _contentHandler.characters(_characterContentChunkTable._array,
 726                                 _characterContentChunkTable._offset[index],
 727                                 _characterContentChunkTable._length[index]);
 728                     } catch (SAXException e) {
 729                         throw new FastInfosetException("processCII", e);
 730                     }
 731                     break;
 732                 }
 733                 case DecoderStateTables.CII_INDEX_LARGE:
 734                 {
 735                     final int index = (((_b & EncodingConstants.INTEGER_4TH_BIT_LARGE_MASK) << 16) |
 736                             (read() << 8) |
 737                             read())
 738                             + EncodingConstants.INTEGER_4TH_BIT_MEDIUM_LIMIT;
 739 
 740                     try {
 741                         _contentHandler.characters(_characterContentChunkTable._array,
 742                                 _characterContentChunkTable._offset[index],
 743                                 _characterContentChunkTable._length[index]);
 744                     } catch (SAXException e) {
 745                         throw new FastInfosetException("processCII", e);
 746                     }
 747                     break;
 748                 }
 749                 case DecoderStateTables.CII_INDEX_LARGE_LARGE:
 750                 {
 751                     final int index = ((read() << 16) |
 752                             (read() << 8) |
 753                             read())
 754                             + EncodingConstants.INTEGER_4TH_BIT_LARGE_LIMIT;
 755 
 756                     try {
 757                         _contentHandler.characters(_characterContentChunkTable._array,
 758                                 _characterContentChunkTable._offset[index],
 759                                 _characterContentChunkTable._length[index]);
 760                     } catch (SAXException e) {
 761                         throw new FastInfosetException("processCII", e);
 762                     }
 763                     break;
 764                 }
 765                 case DecoderStateTables.COMMENT_II:
 766                     processCommentII();
 767                     break;
 768                 case DecoderStateTables.PROCESSING_INSTRUCTION_II:
 769                     processProcessingII();
 770                     break;
 771                 case DecoderStateTables.UNEXPANDED_ENTITY_REFERENCE_II:
 772                 {
 773                     String entity_reference_name = decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherNCName);
 774 
 775                     String system_identifier = ((_b & EncodingConstants.UNEXPANDED_ENTITY_SYSTEM_IDENTIFIER_FLAG) > 0)
 776                     ? decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherURI) : "";
 777                     String public_identifier = ((_b & EncodingConstants.UNEXPANDED_ENTITY_PUBLIC_IDENTIFIER_FLAG) > 0)
 778                     ? decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherURI) : "";
 779 
 780                     try {
 781                         /*
 782                          * TODO
 783                          * Need to verify if the skippedEntity method:
 784                          * http://java.sun.com/j2se/1.4.2/docs/api/org/xml/sax/ContentHandler.html#skippedEntity(java.lang.String)
 785                          * is the correct method to call. It appears so but a more extensive
 786                          * check is necessary.
 787                          */
 788                         _contentHandler.skippedEntity(entity_reference_name);
 789                     } catch (SAXException e) {
 790                         throw new FastInfosetException("processUnexpandedEntityReferenceII", e);
 791                     }
 792                     break;
 793                 }
 794                 case DecoderStateTables.TERMINATOR_DOUBLE:
 795                     _doubleTerminate = true;
 796                 case DecoderStateTables.TERMINATOR_SINGLE:
 797                     _terminate = true;
 798                     break;
 799                 default:
 800                     throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.IllegalStateDecodingEII"));
 801             }
 802         }
 803 
 804         try {
 805             _contentHandler.endDocument();
 806         } catch (SAXException e) {
 807             throw new FastInfosetException("processDII", e);
 808         }
 809     }
 810 
 811     protected final void processDIIOptionalProperties() throws FastInfosetException, IOException {
 812         // Optimize for the most common case
 813         if (_b == EncodingConstants.DOCUMENT_INITIAL_VOCABULARY_FLAG) {
 814             decodeInitialVocabulary();
 815             return;
 816         }
 817 
 818         if ((_b & EncodingConstants.DOCUMENT_ADDITIONAL_DATA_FLAG) > 0) {
 819             decodeAdditionalData();
 820             /*
 821              * TODO
 822              * how to report the additional data?
 823              */
 824         }
 825 
 826         if ((_b & EncodingConstants.DOCUMENT_INITIAL_VOCABULARY_FLAG) > 0) {
 827             decodeInitialVocabulary();
 828         }
 829 
 830         if ((_b & EncodingConstants.DOCUMENT_NOTATIONS_FLAG) > 0) {
 831             decodeNotations();
 832             /*
 833                 try {
 834                     _dtdHandler.notationDecl(name, public_identifier, system_identifier);
 835                 } catch (SAXException e) {
 836                     throw new IOException("NotationsDeclarationII");
 837                 }
 838              */
 839         }
 840 
 841         if ((_b & EncodingConstants.DOCUMENT_UNPARSED_ENTITIES_FLAG) > 0) {
 842             decodeUnparsedEntities();
 843             /*
 844                 try {
 845                     _dtdHandler.unparsedEntityDecl(name, public_identifier, system_identifier, notation_name);
 846                 } catch (SAXException e) {
 847                     throw new IOException("UnparsedEntitiesII");
 848                 }
 849              */
 850         }
 851 
 852         if ((_b & EncodingConstants.DOCUMENT_CHARACTER_ENCODING_SCHEME) > 0) {
 853             String characterEncodingScheme = decodeCharacterEncodingScheme();
 854             /*
 855              * TODO
 856              * how to report the character encoding scheme?
 857              */
 858         }
 859 
 860         if ((_b & EncodingConstants.DOCUMENT_STANDALONE_FLAG) > 0) {
 861             boolean standalone = (read() > 0) ? true : false ;
 862             /*
 863              * TODO
 864              * how to report the standalone flag?
 865              */
 866         }
 867 
 868         if ((_b & EncodingConstants.DOCUMENT_VERSION_FLAG) > 0) {
 869             decodeVersion();
 870             /*
 871              * TODO
 872              * how to report the standalone flag?
 873              */
 874         }
 875     }
 876 
 877     protected final void processEII(QualifiedName name, boolean hasAttributes) throws FastInfosetException, IOException {
 878         if (_prefixTable._currentInScope[name.prefixIndex] != name.namespaceNameIndex) {
 879             throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.qNameOfEIINotInScope"));
 880         }
 881 
 882         if (hasAttributes) {
 883             processAIIs();
 884         }
 885 
 886         try {
 887             _contentHandler.startElement(name.namespaceName, name.localName, name.qName, _attributes);
 888         } catch (SAXException e) {
 889             logger.log(Level.FINE, "processEII error", e);
 890             throw new FastInfosetException("processEII", e);
 891         }
 892 
 893         if (_clearAttributes) {
 894             _attributes.clear();
 895             _clearAttributes = false;
 896         }
 897 
 898         while(!_terminate) {
 899             _b = read();
 900             switch(DecoderStateTables.EII(_b)) {
 901                 case DecoderStateTables.EII_NO_AIIS_INDEX_SMALL:
 902                     processEII(_elementNameTable._array[_b], false);
 903                     break;
 904                 case DecoderStateTables.EII_AIIS_INDEX_SMALL:
 905                     processEII(_elementNameTable._array[_b & EncodingConstants.INTEGER_3RD_BIT_SMALL_MASK], true);
 906                     break;
 907                 case DecoderStateTables.EII_INDEX_MEDIUM:
 908                     processEII(decodeEIIIndexMedium(), (_b & EncodingConstants.ELEMENT_ATTRIBUTE_FLAG) > 0);
 909                     break;
 910                 case DecoderStateTables.EII_INDEX_LARGE:
 911                     processEII(decodeEIIIndexLarge(), (_b & EncodingConstants.ELEMENT_ATTRIBUTE_FLAG) > 0);
 912                     break;
 913                 case DecoderStateTables.EII_LITERAL:
 914                 {
 915                     final QualifiedName qn = decodeLiteralQualifiedName(
 916                             _b & EncodingConstants.LITERAL_QNAME_PREFIX_NAMESPACE_NAME_MASK,
 917                             _elementNameTable.getNext());
 918                     _elementNameTable.add(qn);
 919                     processEII(qn, (_b & EncodingConstants.ELEMENT_ATTRIBUTE_FLAG) > 0);
 920                     break;
 921                 }
 922                 case DecoderStateTables.EII_NAMESPACES:
 923                     processEIIWithNamespaces();
 924                     break;
 925                 case DecoderStateTables.CII_UTF8_SMALL_LENGTH:
 926                     _octetBufferLength = (_b & EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_SMALL_MASK)
 927                     + 1;
 928                     processUtf8CharacterString();
 929                     break;
 930                 case DecoderStateTables.CII_UTF8_MEDIUM_LENGTH:
 931                     _octetBufferLength = read() + EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_SMALL_LIMIT;
 932                     processUtf8CharacterString();
 933                     break;
 934                 case DecoderStateTables.CII_UTF8_LARGE_LENGTH:
 935                     _octetBufferLength = ((read() << 24) |
 936                             (read() << 16) |
 937                             (read() << 8) |
 938                             read())
 939                             + EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_MEDIUM_LIMIT;
 940                     processUtf8CharacterString();
 941                     break;
 942                 case DecoderStateTables.CII_UTF16_SMALL_LENGTH:
 943                     _octetBufferLength = (_b & EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_SMALL_MASK)
 944                     + 1;
 945                     decodeUtf16StringAsCharBuffer();
 946                     if ((_b & EncodingConstants.CHARACTER_CHUNK_ADD_TO_TABLE_FLAG) > 0) {
 947                         _characterContentChunkTable.add(_charBuffer, _charBufferLength);
 948                     }
 949 
 950                     try {
 951                         _contentHandler.characters(_charBuffer, 0, _charBufferLength);
 952                     } catch (SAXException e) {
 953                         throw new FastInfosetException("processCII", e);
 954                     }
 955                     break;
 956                 case DecoderStateTables.CII_UTF16_MEDIUM_LENGTH:
 957                     _octetBufferLength = read() + EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_SMALL_LIMIT;
 958                     decodeUtf16StringAsCharBuffer();
 959                     if ((_b & EncodingConstants.CHARACTER_CHUNK_ADD_TO_TABLE_FLAG) > 0) {
 960                         _characterContentChunkTable.add(_charBuffer, _charBufferLength);
 961                     }
 962 
 963                     try {
 964                         _contentHandler.characters(_charBuffer, 0, _charBufferLength);
 965                     } catch (SAXException e) {
 966                         throw new FastInfosetException("processCII", e);
 967                     }
 968                     break;
 969                 case DecoderStateTables.CII_UTF16_LARGE_LENGTH:
 970                     _octetBufferLength = ((read() << 24) |
 971                             (read() << 16) |
 972                             (read() << 8) |
 973                             read())
 974                             + EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_MEDIUM_LIMIT;
 975                     decodeUtf16StringAsCharBuffer();
 976                     if ((_b & EncodingConstants.CHARACTER_CHUNK_ADD_TO_TABLE_FLAG) > 0) {
 977                         _characterContentChunkTable.add(_charBuffer, _charBufferLength);
 978                     }
 979 
 980                     try {
 981                         _contentHandler.characters(_charBuffer, 0, _charBufferLength);
 982                     } catch (SAXException e) {
 983                         throw new FastInfosetException("processCII", e);
 984                     }
 985                     break;
 986                 case DecoderStateTables.CII_RA:
 987                 {
 988                     final boolean addToTable = (_b & EncodingConstants.CHARACTER_CHUNK_ADD_TO_TABLE_FLAG) > 0;
 989 
 990                     // Decode resitricted alphabet integer
 991                     _identifier = (_b & 0x02) << 6;
 992                     _b = read();
 993                     _identifier |= (_b & 0xFC) >> 2;
 994 
 995                     decodeOctetsOnSeventhBitOfNonIdentifyingStringOnThirdBit(_b);
 996 
 997                     decodeRestrictedAlphabetAsCharBuffer();
 998 
 999                     if (addToTable) {
1000                         _characterContentChunkTable.add(_charBuffer, _charBufferLength);
1001                     }
1002 
1003                     try {
1004                         _contentHandler.characters(_charBuffer, 0, _charBufferLength);
1005                     } catch (SAXException e) {
1006                         throw new FastInfosetException("processCII", e);
1007                     }
1008                     break;
1009                 }
1010                 case DecoderStateTables.CII_EA:
1011                 {
1012                     final boolean addToTable = (_b & EncodingConstants.CHARACTER_CHUNK_ADD_TO_TABLE_FLAG) > 0;
1013                     // Decode encoding algorithm integer
1014                     _identifier = (_b & 0x02) << 6;
1015                     _b = read();
1016                     _identifier |= (_b & 0xFC) >> 2;
1017 
1018                     decodeOctetsOnSeventhBitOfNonIdentifyingStringOnThirdBit(_b);
1019 
1020                     processCIIEncodingAlgorithm(addToTable);
1021                     break;
1022                 }
1023                 case DecoderStateTables.CII_INDEX_SMALL:
1024                 {
1025                     final int index = _b & EncodingConstants.INTEGER_4TH_BIT_SMALL_MASK;
1026                     try {
1027                         _contentHandler.characters(_characterContentChunkTable._array,
1028                                 _characterContentChunkTable._offset[index],
1029                                 _characterContentChunkTable._length[index]);
1030                     } catch (SAXException e) {
1031                         throw new FastInfosetException("processCII", e);
1032                     }
1033                     break;
1034                 }
1035                 case DecoderStateTables.CII_INDEX_MEDIUM:
1036                 {
1037                     final int index = (((_b & EncodingConstants.INTEGER_4TH_BIT_MEDIUM_MASK) << 8) | read())
1038                     + EncodingConstants.INTEGER_4TH_BIT_SMALL_LIMIT;
1039                     try {
1040                         _contentHandler.characters(_characterContentChunkTable._array,
1041                                 _characterContentChunkTable._offset[index],
1042                                 _characterContentChunkTable._length[index]);
1043                     } catch (SAXException e) {
1044                         throw new FastInfosetException("processCII", e);
1045                     }
1046                     break;
1047                 }
1048                 case DecoderStateTables.CII_INDEX_LARGE:
1049                 {
1050                     final int index = (((_b & EncodingConstants.INTEGER_4TH_BIT_LARGE_MASK) << 16) |
1051                             (read() << 8) |
1052                             read())
1053                             + EncodingConstants.INTEGER_4TH_BIT_MEDIUM_LIMIT;
1054 
1055                     try {
1056                         _contentHandler.characters(_characterContentChunkTable._array,
1057                                 _characterContentChunkTable._offset[index],
1058                                 _characterContentChunkTable._length[index]);
1059                     } catch (SAXException e) {
1060                         throw new FastInfosetException("processCII", e);
1061                     }
1062                     break;
1063                 }
1064                 case DecoderStateTables.CII_INDEX_LARGE_LARGE:
1065                 {
1066                     final int index = ((read() << 16) |
1067                             (read() << 8) |
1068                             read())
1069                             + EncodingConstants.INTEGER_4TH_BIT_LARGE_LIMIT;
1070 
1071                     try {
1072                         _contentHandler.characters(_characterContentChunkTable._array,
1073                                 _characterContentChunkTable._offset[index],
1074                                 _characterContentChunkTable._length[index]);
1075                     } catch (SAXException e) {
1076                         throw new FastInfosetException("processCII", e);
1077                     }
1078                     break;
1079                 }
1080                 case DecoderStateTables.COMMENT_II:
1081                     processCommentII();
1082                     break;
1083                 case DecoderStateTables.PROCESSING_INSTRUCTION_II:
1084                     processProcessingII();
1085                     break;
1086                 case DecoderStateTables.UNEXPANDED_ENTITY_REFERENCE_II:
1087                 {
1088                     String entity_reference_name = decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherNCName);
1089 
1090                     String system_identifier = ((_b & EncodingConstants.UNEXPANDED_ENTITY_SYSTEM_IDENTIFIER_FLAG) > 0)
1091                     ? decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherURI) : "";
1092                     String public_identifier = ((_b & EncodingConstants.UNEXPANDED_ENTITY_PUBLIC_IDENTIFIER_FLAG) > 0)
1093                     ? decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherURI) : "";
1094 
1095                     try {
1096                         /*
1097                          * TODO
1098                          * Need to verify if the skippedEntity method:
1099                          * http://java.sun.com/j2se/1.4.2/docs/api/org/xml/sax/ContentHandler.html#skippedEntity(java.lang.String)
1100                          * is the correct method to call. It appears so but a more extensive
1101                          * check is necessary.
1102                          */
1103                         _contentHandler.skippedEntity(entity_reference_name);
1104                     } catch (SAXException e) {
1105                         throw new FastInfosetException("processUnexpandedEntityReferenceII", e);
1106                     }
1107                     break;
1108                 }
1109                 case DecoderStateTables.TERMINATOR_DOUBLE:
1110                     _doubleTerminate = true;
1111                 case DecoderStateTables.TERMINATOR_SINGLE:
1112                     _terminate = true;
1113                     break;
1114                 default:
1115                     throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.IllegalStateDecodingEII"));
1116             }
1117         }
1118 
1119         _terminate = _doubleTerminate;
1120         _doubleTerminate = false;
1121 
1122         try {
1123             _contentHandler.endElement(name.namespaceName, name.localName, name.qName);
1124         } catch (SAXException e) {
1125             throw new FastInfosetException("processEII", e);
1126         }
1127     }
1128 
1129     private final void processUtf8CharacterString() throws FastInfosetException, IOException {
1130         if ((_b & EncodingConstants.CHARACTER_CHUNK_ADD_TO_TABLE_FLAG) > 0) {
1131             _characterContentChunkTable.ensureSize(_octetBufferLength);
1132             final int charactersOffset = _characterContentChunkTable._arrayIndex;
1133             decodeUtf8StringAsCharBuffer(_characterContentChunkTable._array, charactersOffset);
1134             _characterContentChunkTable.add(_charBufferLength);
1135             try {
1136                 _contentHandler.characters(_characterContentChunkTable._array, charactersOffset, _charBufferLength);
1137             } catch (SAXException e) {
1138                 throw new FastInfosetException("processCII", e);
1139             }
1140         } else {
1141             decodeUtf8StringAsCharBuffer();
1142             try {
1143                 _contentHandler.characters(_charBuffer, 0, _charBufferLength);
1144             } catch (SAXException e) {
1145                 throw new FastInfosetException("processCII", e);
1146             }
1147         }
1148     }
1149 
1150     protected final void processEIIWithNamespaces() throws FastInfosetException, IOException {
1151         final boolean hasAttributes = (_b & EncodingConstants.ELEMENT_ATTRIBUTE_FLAG) > 0;
1152 
1153         _clearAttributes = (_namespacePrefixesFeature) ? true : false;
1154 
1155         if (++_prefixTable._declarationId == Integer.MAX_VALUE) {
1156             _prefixTable.clearDeclarationIds();
1157         }
1158 
1159         String prefix = "", namespaceName = "";
1160         final int start = _namespacePrefixesIndex;
1161         int b = read();
1162         while ((b & EncodingConstants.NAMESPACE_ATTRIBUTE_MASK) == EncodingConstants.NAMESPACE_ATTRIBUTE) {
1163             if (_namespacePrefixesIndex == _namespacePrefixes.length) {
1164                 final int[] namespaceAIIs = new int[_namespacePrefixesIndex * 3 / 2 + 1];
1165                 System.arraycopy(_namespacePrefixes, 0, namespaceAIIs, 0, _namespacePrefixesIndex);
1166                 _namespacePrefixes = namespaceAIIs;
1167             }
1168 
1169             switch (b & EncodingConstants.NAMESPACE_ATTRIBUTE_PREFIX_NAME_MASK) {
1170                 // no prefix, no namespace
1171                 // Undeclaration of default namespace
1172                 case 0:
1173                     prefix = namespaceName = "";
1174                     _namespaceNameIndex = _prefixIndex = _namespacePrefixes[_namespacePrefixesIndex++] = -1;
1175                     break;
1176                     // no prefix, namespace
1177                     // Declaration of default namespace
1178                 case 1:
1179                     prefix = "";
1180                     namespaceName = decodeIdentifyingNonEmptyStringOnFirstBitAsNamespaceName(false);
1181 
1182                     _prefixIndex = _namespacePrefixes[_namespacePrefixesIndex++] = -1;
1183                     break;
1184                     // prefix, no namespace
1185                     // Undeclaration of namespace
1186                 case 2:
1187                     prefix = decodeIdentifyingNonEmptyStringOnFirstBitAsPrefix(false);
1188                     namespaceName = "";
1189 
1190                     _namespaceNameIndex = -1;
1191                     _namespacePrefixes[_namespacePrefixesIndex++] = _prefixIndex;
1192                     break;
1193                     // prefix, namespace
1194                     // Declaration of prefixed namespace
1195                 case 3:
1196                     prefix = decodeIdentifyingNonEmptyStringOnFirstBitAsPrefix(true);
1197                     namespaceName = decodeIdentifyingNonEmptyStringOnFirstBitAsNamespaceName(true);
1198 
1199                     _namespacePrefixes[_namespacePrefixesIndex++] = _prefixIndex;
1200                     break;
1201             }
1202 
1203             _prefixTable.pushScope(_prefixIndex, _namespaceNameIndex);
1204 
1205             if (_namespacePrefixesFeature) {
1206                 // Add the namespace delcaration as an attribute
1207                 if (prefix != "") {
1208                     _attributes.addAttribute(new QualifiedName(
1209                             EncodingConstants.XMLNS_NAMESPACE_PREFIX,
1210                             EncodingConstants.XMLNS_NAMESPACE_NAME,
1211                             prefix),
1212                             namespaceName);
1213                 } else {
1214                     _attributes.addAttribute(EncodingConstants.DEFAULT_NAMESPACE_DECLARATION,
1215                             namespaceName);
1216                 }
1217             }
1218 
1219             try {
1220                 _contentHandler.startPrefixMapping(prefix, namespaceName);
1221             } catch (SAXException e) {
1222                 throw new IOException("processStartNamespaceAII");
1223             }
1224 
1225             b = read();
1226         }
1227         if (b != EncodingConstants.TERMINATOR) {
1228             throw new IOException(CommonResourceBundle.getInstance().getString("message.EIInamespaceNameNotTerminatedCorrectly"));
1229         }
1230         final int end = _namespacePrefixesIndex;
1231 
1232         _b = read();
1233         switch(DecoderStateTables.EII(_b)) {
1234             case DecoderStateTables.EII_NO_AIIS_INDEX_SMALL:
1235                 processEII(_elementNameTable._array[_b], hasAttributes);
1236                 break;
1237             case DecoderStateTables.EII_INDEX_MEDIUM:
1238                 processEII(decodeEIIIndexMedium(), hasAttributes);
1239                 break;
1240             case DecoderStateTables.EII_INDEX_LARGE:
1241                 processEII(decodeEIIIndexLarge(), hasAttributes);
1242                 break;
1243             case DecoderStateTables.EII_LITERAL:
1244             {
1245                 final QualifiedName qn = decodeLiteralQualifiedName(
1246                         _b & EncodingConstants.LITERAL_QNAME_PREFIX_NAMESPACE_NAME_MASK,
1247                         _elementNameTable.getNext());
1248                 _elementNameTable.add(qn);
1249                 processEII(qn, hasAttributes);
1250                 break;
1251             }
1252             default:
1253                 throw new IOException(CommonResourceBundle.getInstance().getString("message.IllegalStateDecodingEIIAfterAIIs"));
1254         }
1255 
1256         try {
1257             for (int i = end - 1; i >= start; i--) {
1258                 final int prefixIndex = _namespacePrefixes[i];
1259                 _prefixTable.popScope(prefixIndex);
1260                 prefix = (prefixIndex > 0) ? _prefixTable.get(prefixIndex - 1) :
1261                     (prefixIndex == -1) ? "" : EncodingConstants.XML_NAMESPACE_PREFIX;
1262                 _contentHandler.endPrefixMapping(prefix);
1263             }
1264             _namespacePrefixesIndex = start;
1265         } catch (SAXException e) {
1266             throw new IOException("processStartNamespaceAII");
1267         }
1268     }
1269 
1270     protected final void processAIIs() throws FastInfosetException, IOException {
1271         QualifiedName name;
1272         int b;
1273         String value;
1274 
1275         _clearAttributes = true;
1276 
1277         if (++_duplicateAttributeVerifier._currentIteration == Integer.MAX_VALUE) {
1278             _duplicateAttributeVerifier.clear();
1279         }
1280 
1281         do {
1282             // AII qualified name
1283             b = read();
1284             switch (DecoderStateTables.AII(b)) {
1285                 case DecoderStateTables.AII_INDEX_SMALL:
1286                     name = _attributeNameTable._array[b];
1287                     break;
1288                 case DecoderStateTables.AII_INDEX_MEDIUM:
1289                 {
1290                     final int i = (((b & EncodingConstants.INTEGER_2ND_BIT_MEDIUM_MASK) << 8) | read())
1291                     + EncodingConstants.INTEGER_2ND_BIT_SMALL_LIMIT;
1292                     name = _attributeNameTable._array[i];
1293                     break;
1294                 }
1295                 case DecoderStateTables.AII_INDEX_LARGE:
1296                 {
1297                     final int i = (((b & EncodingConstants.INTEGER_2ND_BIT_LARGE_MASK) << 16) | (read() << 8) | read())
1298                     + EncodingConstants.INTEGER_2ND_BIT_MEDIUM_LIMIT;
1299                     name = _attributeNameTable._array[i];
1300                     break;
1301                 }
1302                 case DecoderStateTables.AII_LITERAL:
1303                     name = decodeLiteralQualifiedName(
1304                             b & EncodingConstants.LITERAL_QNAME_PREFIX_NAMESPACE_NAME_MASK,
1305                             _attributeNameTable.getNext());
1306                     name.createAttributeValues(_duplicateAttributeVerifier.MAP_SIZE);
1307                     _attributeNameTable.add(name);
1308                     break;
1309                 case DecoderStateTables.AII_TERMINATOR_DOUBLE:
1310                     _doubleTerminate = true;
1311                 case DecoderStateTables.AII_TERMINATOR_SINGLE:
1312                     _terminate = true;
1313                     // AIIs have finished break out of loop
1314                     continue;
1315                 default:
1316                     throw new IOException(CommonResourceBundle.getInstance().getString("message.decodingAIIs"));
1317             }
1318 
1319             if (name.prefixIndex > 0 && _prefixTable._currentInScope[name.prefixIndex] != name.namespaceNameIndex) {
1320                 throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.AIIqNameNotInScope"));
1321             }
1322 
1323             _duplicateAttributeVerifier.checkForDuplicateAttribute(name.attributeHash, name.attributeId);
1324 
1325             // [normalized value] of AII
1326 
1327             b = read();
1328             switch(DecoderStateTables.NISTRING(b)) {
1329                 case DecoderStateTables.NISTRING_UTF8_SMALL_LENGTH:
1330                     _octetBufferLength = (b & EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_SMALL_MASK) + 1;
1331                     value = decodeUtf8StringAsString();
1332                     if ((b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0) {
1333                         _attributeValueTable.add(value);
1334                     }
1335 
1336                     _attributes.addAttribute(name, value);
1337                     break;
1338                 case DecoderStateTables.NISTRING_UTF8_MEDIUM_LENGTH:
1339                     _octetBufferLength = read() + EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_SMALL_LIMIT;
1340                     value = decodeUtf8StringAsString();
1341                     if ((b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0) {
1342                         _attributeValueTable.add(value);
1343                     }
1344 
1345                     _attributes.addAttribute(name, value);
1346                     break;
1347                 case DecoderStateTables.NISTRING_UTF8_LARGE_LENGTH:
1348                     _octetBufferLength = ((read() << 24) |
1349                             (read() << 16) |
1350                             (read() << 8) |
1351                             read())
1352                             + EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_MEDIUM_LIMIT;
1353                     value = decodeUtf8StringAsString();
1354                     if ((b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0) {
1355                         _attributeValueTable.add(value);
1356                     }
1357 
1358                     _attributes.addAttribute(name, value);
1359                     break;
1360                 case DecoderStateTables.NISTRING_UTF16_SMALL_LENGTH:
1361                     _octetBufferLength = (b & EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_SMALL_MASK) + 1;
1362                     value = decodeUtf16StringAsString();
1363                     if ((b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0) {
1364                         _attributeValueTable.add(value);
1365                     }
1366 
1367                     _attributes.addAttribute(name, value);
1368                     break;
1369                 case DecoderStateTables.NISTRING_UTF16_MEDIUM_LENGTH:
1370                     _octetBufferLength = read() + EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_SMALL_LIMIT;
1371                     value = decodeUtf16StringAsString();
1372                     if ((b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0) {
1373                         _attributeValueTable.add(value);
1374                     }
1375 
1376                     _attributes.addAttribute(name, value);
1377                     break;
1378                 case DecoderStateTables.NISTRING_UTF16_LARGE_LENGTH:
1379                     _octetBufferLength = ((read() << 24) |
1380                             (read() << 16) |
1381                             (read() << 8) |
1382                             read())
1383                             + EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_MEDIUM_LIMIT;
1384                     value = decodeUtf16StringAsString();
1385                     if ((b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0) {
1386                         _attributeValueTable.add(value);
1387                     }
1388 
1389                     _attributes.addAttribute(name, value);
1390                     break;
1391                 case DecoderStateTables.NISTRING_RA:
1392                 {
1393                     final boolean addToTable = (b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0;
1394                     // Decode resitricted alphabet integer
1395                     _identifier = (b & 0x0F) << 4;
1396                     b = read();
1397                     _identifier |= (b & 0xF0) >> 4;
1398 
1399                     decodeOctetsOnFifthBitOfNonIdentifyingStringOnFirstBit(b);
1400 
1401                     value = decodeRestrictedAlphabetAsString();
1402                     if (addToTable) {
1403                         _attributeValueTable.add(value);
1404                     }
1405 
1406                     _attributes.addAttribute(name, value);
1407                     break;
1408                 }
1409                 case DecoderStateTables.NISTRING_EA:
1410                 {
1411                     final boolean addToTable = (b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0;
1412 
1413                     _identifier = (b & 0x0F) << 4;
1414                     b = read();
1415                     _identifier |= (b & 0xF0) >> 4;
1416 
1417                     decodeOctetsOnFifthBitOfNonIdentifyingStringOnFirstBit(b);
1418 
1419                     processAIIEncodingAlgorithm(name, addToTable);
1420                     break;
1421                 }
1422                 case DecoderStateTables.NISTRING_INDEX_SMALL:
1423                     _attributes.addAttribute(name,
1424                             _attributeValueTable._array[b & EncodingConstants.INTEGER_2ND_BIT_SMALL_MASK]);
1425                     break;
1426                 case DecoderStateTables.NISTRING_INDEX_MEDIUM:
1427                 {
1428                     final int index = (((b & EncodingConstants.INTEGER_2ND_BIT_MEDIUM_MASK) << 8) | read())
1429                     + EncodingConstants.INTEGER_2ND_BIT_SMALL_LIMIT;
1430 
1431                     _attributes.addAttribute(name,
1432                             _attributeValueTable._array[index]);
1433                     break;
1434                 }
1435                 case DecoderStateTables.NISTRING_INDEX_LARGE:
1436                 {
1437                     final int index = (((b & EncodingConstants.INTEGER_2ND_BIT_LARGE_MASK) << 16) | (read() << 8) | read())
1438                     + EncodingConstants.INTEGER_2ND_BIT_MEDIUM_LIMIT;
1439 
1440                     _attributes.addAttribute(name,
1441                             _attributeValueTable._array[index]);
1442                     break;
1443                 }
1444                 case DecoderStateTables.NISTRING_EMPTY:
1445                     _attributes.addAttribute(name, "");
1446                     break;
1447                 default:
1448                     throw new IOException(CommonResourceBundle.getInstance().getString("message.decodingAIIValue"));
1449             }
1450 
1451         } while (!_terminate);
1452 
1453         // Reset duplication attribute verfifier
1454         _duplicateAttributeVerifier._poolCurrent = _duplicateAttributeVerifier._poolHead;
1455 
1456         _terminate = _doubleTerminate;
1457         _doubleTerminate = false;
1458     }
1459 
1460     protected final void processCommentII() throws FastInfosetException, IOException {
1461         switch(decodeNonIdentifyingStringOnFirstBit()) {
1462             case NISTRING_STRING:
1463                 if (_addToTable) {
1464                     _v.otherString.add(new CharArray(_charBuffer, 0, _charBufferLength, true));
1465                 }
1466 
1467                 try {
1468                     _lexicalHandler.comment(_charBuffer, 0, _charBufferLength);
1469                 } catch (SAXException e) {
1470                     throw new FastInfosetException("processCommentII", e);
1471                 }
1472                 break;
1473             case NISTRING_ENCODING_ALGORITHM:
1474                 throw new IOException(CommonResourceBundle.getInstance().getString("message.commentIIAlgorithmNotSupported"));
1475             case NISTRING_INDEX:
1476                 final CharArray ca = _v.otherString.get(_integer);
1477 
1478                 try {
1479                     _lexicalHandler.comment(ca.ch, ca.start, ca.length);
1480                 } catch (SAXException e) {
1481                     throw new FastInfosetException("processCommentII", e);
1482                 }
1483                 break;
1484             case NISTRING_EMPTY_STRING:
1485                 try {
1486                     _lexicalHandler.comment(_charBuffer, 0, 0);
1487                 } catch (SAXException e) {
1488                     throw new FastInfosetException("processCommentII", e);
1489                 }
1490                 break;
1491         }
1492     }
1493 
1494     protected final void processProcessingII() throws FastInfosetException, IOException {
1495         final String target = decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherNCName);
1496 
1497         switch(decodeNonIdentifyingStringOnFirstBit()) {
1498             case NISTRING_STRING:
1499                 final String data = new String(_charBuffer, 0, _charBufferLength);
1500                 if (_addToTable) {
1501                     _v.otherString.add(new CharArrayString(data));
1502                 }
1503                 try {
1504                     _contentHandler.processingInstruction(target, data);
1505                 } catch (SAXException e) {
1506                     throw new FastInfosetException("processProcessingII", e);
1507                 }
1508                 break;
1509             case NISTRING_ENCODING_ALGORITHM:
1510                 throw new IOException(CommonResourceBundle.getInstance().getString("message.processingIIWithEncodingAlgorithm"));
1511             case NISTRING_INDEX:
1512                 try {
1513                     _contentHandler.processingInstruction(target, _v.otherString.get(_integer).toString());
1514                 } catch (SAXException e) {
1515                     throw new FastInfosetException("processProcessingII", e);
1516                 }
1517                 break;
1518             case NISTRING_EMPTY_STRING:
1519                 try {
1520                     _contentHandler.processingInstruction(target, "");
1521                 } catch (SAXException e) {
1522                     throw new FastInfosetException("processProcessingII", e);
1523                 }
1524                 break;
1525         }
1526     }
1527 
1528     protected final void processCIIEncodingAlgorithm(boolean addToTable) throws FastInfosetException, IOException {
1529         if (_identifier < EncodingConstants.ENCODING_ALGORITHM_BUILTIN_END) {
1530             if (_primitiveHandler != null) {
1531                 processCIIBuiltInEncodingAlgorithmAsPrimitive();
1532             } else if (_algorithmHandler != null) {
1533                 Object array = processBuiltInEncodingAlgorithmAsObject();
1534 
1535                 try {
1536                     _algorithmHandler.object(null, _identifier, array);
1537                 } catch (SAXException e) {
1538                     throw new FastInfosetException(e);
1539                 }
1540             } else {
1541                 StringBuffer buffer = new StringBuffer();
1542                 processBuiltInEncodingAlgorithmAsCharacters(buffer);
1543 
1544                 try {
1545                     _contentHandler.characters(buffer.toString().toCharArray(), 0, buffer.length());
1546                 } catch (SAXException e) {
1547                     throw new FastInfosetException(e);
1548                 }
1549             }
1550 
1551             if (addToTable) {
1552                 StringBuffer buffer = new StringBuffer();
1553                 processBuiltInEncodingAlgorithmAsCharacters(buffer);
1554                 _characterContentChunkTable.add(buffer.toString().toCharArray(), buffer.length());
1555             }
1556         } else if (_identifier == EncodingAlgorithmIndexes.CDATA) {
1557             // Set back buffer position to start of encoded string
1558             _octetBufferOffset -= _octetBufferLength;
1559             decodeUtf8StringIntoCharBuffer();
1560 
1561             try {
1562                 _lexicalHandler.startCDATA();
1563                 _contentHandler.characters(_charBuffer, 0, _charBufferLength);
1564                 _lexicalHandler.endCDATA();
1565             } catch (SAXException e) {
1566                 throw new FastInfosetException(e);
1567             }
1568 
1569             if (addToTable) {
1570                 _characterContentChunkTable.add(_charBuffer, _charBufferLength);
1571             }
1572         } else if (_identifier >= EncodingConstants.ENCODING_ALGORITHM_APPLICATION_START && _algorithmHandler != null) {
1573             final String URI = _v.encodingAlgorithm.get(_identifier - EncodingConstants.ENCODING_ALGORITHM_APPLICATION_START);
1574             if (URI == null) {
1575                 throw new EncodingAlgorithmException(CommonResourceBundle.getInstance().
1576                         getString("message.URINotPresent", new Object[]{Integer.valueOf(_identifier)}));
1577             }
1578 
1579             final EncodingAlgorithm ea = (EncodingAlgorithm)_registeredEncodingAlgorithms.get(URI);
1580             if (ea != null) {
1581                 final Object data = ea.decodeFromBytes(_octetBuffer, _octetBufferStart, _octetBufferLength);
1582                 try {
1583                     _algorithmHandler.object(URI, _identifier, data);
1584                 } catch (SAXException e) {
1585                     throw new FastInfosetException(e);
1586                 }
1587             } else {
1588                 try {
1589                     _algorithmHandler.octets(URI, _identifier, _octetBuffer, _octetBufferStart, _octetBufferLength);
1590                 } catch (SAXException e) {
1591                     throw new FastInfosetException(e);
1592                 }
1593             }
1594             if (addToTable) {
1595                 throw new EncodingAlgorithmException(CommonResourceBundle.getInstance().getString("message.addToTableNotSupported"));
1596             }
1597         } else if (_identifier >= EncodingConstants.ENCODING_ALGORITHM_APPLICATION_START) {
1598             // TODO should have property to ignore
1599             throw new EncodingAlgorithmException(
1600                     CommonResourceBundle.getInstance().getString("message.algorithmDataCannotBeReported"));
1601         } else {
1602             // Reserved built-in algorithms for future use
1603             // TODO should use sax property to decide if event will be
1604             // reported, allows for support through handler if required.
1605             throw new EncodingAlgorithmException(CommonResourceBundle.getInstance().getString("message.identifiers10to31Reserved"));
1606         }
1607     }
1608 
1609     protected final void processCIIBuiltInEncodingAlgorithmAsPrimitive() throws FastInfosetException, IOException {
1610         try {
1611             int length;
1612             switch(_identifier) {
1613                 case EncodingAlgorithmIndexes.HEXADECIMAL:
1614                 case EncodingAlgorithmIndexes.BASE64:
1615                     _primitiveHandler.bytes(_octetBuffer, _octetBufferStart, _octetBufferLength);
1616                     break;
1617                 case EncodingAlgorithmIndexes.SHORT:
1618                     length = BuiltInEncodingAlgorithmFactory.shortEncodingAlgorithm.
1619                             getPrimtiveLengthFromOctetLength(_octetBufferLength);
1620                     if (length > builtInAlgorithmState.shortArray.length) {
1621                         final short[] array = new short[length * 3 / 2 + 1];
1622                         System.arraycopy(builtInAlgorithmState.shortArray, 0,
1623                                 array, 0, builtInAlgorithmState.shortArray.length);
1624                         builtInAlgorithmState.shortArray = array;
1625                     }
1626 
1627                     BuiltInEncodingAlgorithmFactory.shortEncodingAlgorithm.
1628                             decodeFromBytesToShortArray(builtInAlgorithmState.shortArray, 0,
1629                             _octetBuffer, _octetBufferStart, _octetBufferLength);
1630                     _primitiveHandler.shorts(builtInAlgorithmState.shortArray, 0, length);
1631                     break;
1632                 case EncodingAlgorithmIndexes.INT:
1633                     length = BuiltInEncodingAlgorithmFactory.intEncodingAlgorithm.
1634                             getPrimtiveLengthFromOctetLength(_octetBufferLength);
1635                     if (length > builtInAlgorithmState.intArray.length) {
1636                         final int[] array = new int[length * 3 / 2 + 1];
1637                         System.arraycopy(builtInAlgorithmState.intArray, 0,
1638                                 array, 0, builtInAlgorithmState.intArray.length);
1639                         builtInAlgorithmState.intArray = array;
1640                     }
1641 
1642                     BuiltInEncodingAlgorithmFactory.intEncodingAlgorithm.
1643                             decodeFromBytesToIntArray(builtInAlgorithmState.intArray, 0,
1644                             _octetBuffer, _octetBufferStart, _octetBufferLength);
1645                     _primitiveHandler.ints(builtInAlgorithmState.intArray, 0, length);
1646                     break;
1647                 case EncodingAlgorithmIndexes.LONG:
1648                     length = BuiltInEncodingAlgorithmFactory.longEncodingAlgorithm.
1649                             getPrimtiveLengthFromOctetLength(_octetBufferLength);
1650                     if (length > builtInAlgorithmState.longArray.length) {
1651                         final long[] array = new long[length * 3 / 2 + 1];
1652                         System.arraycopy(builtInAlgorithmState.longArray, 0,
1653                                 array, 0, builtInAlgorithmState.longArray.length);
1654                         builtInAlgorithmState.longArray = array;
1655                     }
1656 
1657                     BuiltInEncodingAlgorithmFactory.longEncodingAlgorithm.
1658                             decodeFromBytesToLongArray(builtInAlgorithmState.longArray, 0,
1659                             _octetBuffer, _octetBufferStart, _octetBufferLength);
1660                     _primitiveHandler.longs(builtInAlgorithmState.longArray, 0, length);
1661                     break;
1662                 case EncodingAlgorithmIndexes.BOOLEAN:
1663                     length = BuiltInEncodingAlgorithmFactory.booleanEncodingAlgorithm.
1664                             getPrimtiveLengthFromOctetLength(_octetBufferLength, _octetBuffer[_octetBufferStart] & 0xFF);
1665                     if (length > builtInAlgorithmState.booleanArray.length) {
1666                         final boolean[] array = new boolean[length * 3 / 2 + 1];
1667                         System.arraycopy(builtInAlgorithmState.booleanArray, 0,
1668                                 array, 0, builtInAlgorithmState.booleanArray.length);
1669                         builtInAlgorithmState.booleanArray = array;
1670                     }
1671 
1672                     BuiltInEncodingAlgorithmFactory.booleanEncodingAlgorithm.
1673                             decodeFromBytesToBooleanArray(
1674                             builtInAlgorithmState.booleanArray, 0, length,
1675                             _octetBuffer, _octetBufferStart, _octetBufferLength);
1676                     _primitiveHandler.booleans(builtInAlgorithmState.booleanArray, 0, length);
1677                     break;
1678                 case EncodingAlgorithmIndexes.FLOAT:
1679                     length = BuiltInEncodingAlgorithmFactory.floatEncodingAlgorithm.
1680                             getPrimtiveLengthFromOctetLength(_octetBufferLength);
1681                     if (length > builtInAlgorithmState.floatArray.length) {
1682                         final float[] array = new float[length * 3 / 2 + 1];
1683                         System.arraycopy(builtInAlgorithmState.floatArray, 0,
1684                                 array, 0, builtInAlgorithmState.floatArray.length);
1685                         builtInAlgorithmState.floatArray = array;
1686                     }
1687 
1688                     BuiltInEncodingAlgorithmFactory.floatEncodingAlgorithm.
1689                             decodeFromBytesToFloatArray(builtInAlgorithmState.floatArray, 0,
1690                             _octetBuffer, _octetBufferStart, _octetBufferLength);
1691                     _primitiveHandler.floats(builtInAlgorithmState.floatArray, 0, length);
1692                     break;
1693                 case EncodingAlgorithmIndexes.DOUBLE:
1694                     length = BuiltInEncodingAlgorithmFactory.doubleEncodingAlgorithm.
1695                             getPrimtiveLengthFromOctetLength(_octetBufferLength);
1696                     if (length > builtInAlgorithmState.doubleArray.length) {
1697                         final double[] array = new double[length * 3 / 2 + 1];
1698                         System.arraycopy(builtInAlgorithmState.doubleArray, 0,
1699                                 array, 0, builtInAlgorithmState.doubleArray.length);
1700                         builtInAlgorithmState.doubleArray = array;
1701                     }
1702 
1703                     BuiltInEncodingAlgorithmFactory.doubleEncodingAlgorithm.
1704                             decodeFromBytesToDoubleArray(builtInAlgorithmState.doubleArray, 0,
1705                             _octetBuffer, _octetBufferStart, _octetBufferLength);
1706                     _primitiveHandler.doubles(builtInAlgorithmState.doubleArray, 0, length);
1707                     break;
1708                 case EncodingAlgorithmIndexes.UUID:
1709                     length = BuiltInEncodingAlgorithmFactory.uuidEncodingAlgorithm.
1710                             getPrimtiveLengthFromOctetLength(_octetBufferLength);
1711                     if (length > builtInAlgorithmState.longArray.length) {
1712                         final long[] array = new long[length * 3 / 2 + 1];
1713                         System.arraycopy(builtInAlgorithmState.longArray, 0,
1714                                 array, 0, builtInAlgorithmState.longArray.length);
1715                         builtInAlgorithmState.longArray = array;
1716                     }
1717 
1718                     BuiltInEncodingAlgorithmFactory.uuidEncodingAlgorithm.
1719                             decodeFromBytesToLongArray(builtInAlgorithmState.longArray, 0,
1720                             _octetBuffer, _octetBufferStart, _octetBufferLength);
1721                     _primitiveHandler.uuids(builtInAlgorithmState.longArray, 0, length);
1722                     break;
1723                 case EncodingAlgorithmIndexes.CDATA:
1724                     throw new UnsupportedOperationException("CDATA");
1725                 default:
1726                     throw new FastInfosetException(CommonResourceBundle.getInstance().
1727                             getString("message.unsupportedAlgorithm", new Object[]{Integer.valueOf(_identifier)}));
1728             }
1729         } catch (SAXException e) {
1730             throw new FastInfosetException(e);
1731         }
1732     }
1733 
1734 
1735     protected final void processAIIEncodingAlgorithm(QualifiedName name, boolean addToTable) throws FastInfosetException, IOException {
1736         if (_identifier < EncodingConstants.ENCODING_ALGORITHM_BUILTIN_END) {
1737             if (_primitiveHandler != null || _algorithmHandler != null) {
1738                 Object data = processBuiltInEncodingAlgorithmAsObject();
1739                 _attributes.addAttributeWithAlgorithmData(name, null, _identifier, data);
1740             } else {
1741                 StringBuffer buffer = new StringBuffer();
1742                 processBuiltInEncodingAlgorithmAsCharacters(buffer);
1743                 _attributes.addAttribute(name, buffer.toString());
1744             }
1745         } else if (_identifier >= EncodingConstants.ENCODING_ALGORITHM_APPLICATION_START && _algorithmHandler != null) {
1746             final String URI = _v.encodingAlgorithm.get(_identifier - EncodingConstants.ENCODING_ALGORITHM_APPLICATION_START);
1747             if (URI == null) {
1748                 throw new EncodingAlgorithmException(CommonResourceBundle.getInstance().
1749                         getString("message.URINotPresent", new Object[]{Integer.valueOf(_identifier)}));
1750             }
1751 
1752             final EncodingAlgorithm ea = (EncodingAlgorithm)_registeredEncodingAlgorithms.get(URI);
1753             if (ea != null) {
1754                 final Object data = ea.decodeFromBytes(_octetBuffer, _octetBufferStart, _octetBufferLength);
1755                 _attributes.addAttributeWithAlgorithmData(name, URI, _identifier, data);
1756             } else {
1757                 final byte[] data = new byte[_octetBufferLength];
1758                 System.arraycopy(_octetBuffer, _octetBufferStart, data, 0, _octetBufferLength);
1759                 _attributes.addAttributeWithAlgorithmData(name, URI, _identifier, data);
1760             }
1761         } else if (_identifier >= EncodingConstants.ENCODING_ALGORITHM_APPLICATION_START) {
1762             // TODO should have property to ignore
1763             throw new EncodingAlgorithmException(
1764                     CommonResourceBundle.getInstance().getString("message.algorithmDataCannotBeReported"));
1765         } else if (_identifier == EncodingAlgorithmIndexes.CDATA) {
1766             throw new EncodingAlgorithmException(CommonResourceBundle.getInstance().getString("message.CDATAAlgorithmNotSupported"));
1767         } else {
1768             // Reserved built-in algorithms for future use
1769             // TODO should use sax property to decide if event will be
1770             // reported, allows for support through handler if required.
1771             throw new EncodingAlgorithmException(CommonResourceBundle.getInstance().getString("message.identifiers10to31Reserved"));
1772         }
1773 
1774         if (addToTable) {
1775             _attributeValueTable.add(_attributes.getValue(_attributes.getIndex(name.qName)));
1776         }
1777     }
1778 
1779     protected final void processBuiltInEncodingAlgorithmAsCharacters(StringBuffer buffer) throws FastInfosetException, IOException {
1780         // TODO not very efficient, need to reuse buffers
1781         Object array = BuiltInEncodingAlgorithmFactory.getAlgorithm(_identifier).
1782                 decodeFromBytes(_octetBuffer, _octetBufferStart, _octetBufferLength);
1783 
1784         BuiltInEncodingAlgorithmFactory.getAlgorithm(_identifier).convertToCharacters(array,  buffer);
1785     }
1786 
1787     protected final Object processBuiltInEncodingAlgorithmAsObject() throws FastInfosetException, IOException {
1788         return BuiltInEncodingAlgorithmFactory.getAlgorithm(_identifier).
1789                 decodeFromBytes(_octetBuffer, _octetBufferStart, _octetBufferLength);
1790     }
1791 }