0001: /*
0002: * Fast Infoset ver. 0.1 software ("Software")
0003: *
0004: * Copyright, 2004-2005 Sun Microsystems, Inc. All Rights Reserved.
0005: *
0006: * Software is licensed under the Apache License, Version 2.0 (the "License");
0007: * you may not use this file except in compliance with the License. You may
0008: * obtain a copy of the License at:
0009: *
0010: * http://www.apache.org/licenses/LICENSE-2.0
0011: *
0012: * Unless required by applicable law or agreed to in writing, software
0013: * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
0014: * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
0015: * License for the specific language governing permissions and limitations.
0016: *
0017: * Sun supports and benefits from the global community of open source
0018: * developers, and thanks the community for its important contributions and
0019: * open standards-based technology, which Sun has adopted into many of its
0020: * products.
0021: *
0022: * Please note that portions of Software may be provided with notices and
0023: * open source licenses from such communities and third parties that govern the
0024: * use of those portions, and any licenses granted hereunder do not alter any
0025: * rights and obligations you may have under such open source licenses,
0026: * however, the disclaimer of warranty and limitation of liability provisions
0027: * in this License will apply to all Software in this distribution.
0028: *
0029: * You acknowledge that the Software is not designed, licensed or intended
0030: * for use in the design, construction, operation or maintenance of any nuclear
0031: * facility.
0032: *
0033: * Apache License
0034: * Version 2.0, January 2004
0035: * http://www.apache.org/licenses/
0036: *
0037: */
0038:
0039: package com.sun.xml.fastinfoset.dom;
0040:
0041: import com.sun.xml.fastinfoset.Decoder;
0042: import com.sun.xml.fastinfoset.DecoderStateTables;
0043: import com.sun.xml.fastinfoset.EncodingConstants;
0044: import com.sun.xml.fastinfoset.QualifiedName;
0045: import com.sun.xml.fastinfoset.algorithm.BuiltInEncodingAlgorithmFactory;
0046: import com.sun.xml.fastinfoset.util.CharArray;
0047: import com.sun.xml.fastinfoset.util.CharArrayString;
0048: import java.io.IOException;
0049: import java.io.InputStream;
0050: import org.jvnet.fastinfoset.EncodingAlgorithm;
0051: import org.jvnet.fastinfoset.EncodingAlgorithmException;
0052: import org.jvnet.fastinfoset.EncodingAlgorithmIndexes;
0053: import org.jvnet.fastinfoset.FastInfosetException;
0054: import org.w3c.dom.Attr;
0055: import org.w3c.dom.Document;
0056: import org.w3c.dom.Element;
0057: import org.w3c.dom.Node;
0058: import com.sun.xml.fastinfoset.CommonResourceBundle;
0059:
0060: /**
0061: * The Fast Infoset DOM parser.
0062: * <p>
0063: * Instantiate this parser to parse a fast infoset document in accordance
0064: * with the DOM API.
0065: *
0066: */
0067: public class DOMDocumentParser extends Decoder {
0068: protected Document _document;
0069:
0070: protected Node _currentNode;
0071:
0072: protected Element _currentElement;
0073:
0074: protected Attr[] _namespaceAttributes = new Attr[16];
0075:
0076: protected int _namespaceAttributesIndex;
0077:
0078: protected int[] _namespacePrefixes = new int[16];
0079:
0080: protected int _namespacePrefixesIndex;
0081:
0082: /**
0083: * Parse a fast infoset document into a {@link Document} instance.
0084: * <p>
0085: * {@link Node}s will be created and appended to the {@link Document}
0086: * instance.
0087: *
0088: * @param d the {@link Document} instance.
0089: * @param s the input stream containing the fast infoset document.
0090: */
0091: public void parse(Document d, InputStream s)
0092: throws FastInfosetException, IOException {
0093: _currentNode = _document = d;
0094: _namespaceAttributesIndex = 0;
0095:
0096: parse(s);
0097: }
0098:
0099: protected final void parse(InputStream s)
0100: throws FastInfosetException, IOException {
0101: setInputStream(s);
0102: parse();
0103: }
0104:
0105: protected void resetOnError() {
0106: _namespacePrefixesIndex = 0;
0107:
0108: if (_v == null) {
0109: _prefixTable.clearCompletely();
0110: }
0111: _duplicateAttributeVerifier.clear();
0112: }
0113:
0114: protected final void parse() throws FastInfosetException,
0115: IOException {
0116: try {
0117: reset();
0118: decodeHeader();
0119: processDII();
0120: } catch (RuntimeException e) {
0121: resetOnError();
0122: // Wrap runtime exception
0123: throw new FastInfosetException(e);
0124: } catch (FastInfosetException e) {
0125: resetOnError();
0126: throw e;
0127: } catch (IOException e) {
0128: resetOnError();
0129: throw e;
0130: }
0131: }
0132:
0133: protected final void processDII() throws FastInfosetException,
0134: IOException {
0135: _b = read();
0136: if (_b > 0) {
0137: processDIIOptionalProperties();
0138: }
0139:
0140: // Decode one Document Type II, Comment IIs, PI IIs and one EII
0141: boolean firstElementHasOccured = false;
0142: boolean documentTypeDeclarationOccured = false;
0143: while (!_terminate || !firstElementHasOccured) {
0144: _b = read();
0145: switch (DecoderStateTables.DII[_b]) {
0146: case DecoderStateTables.EII_NO_AIIS_INDEX_SMALL:
0147: processEII(_elementNameTable._array[_b], false);
0148: firstElementHasOccured = true;
0149: break;
0150: case DecoderStateTables.EII_AIIS_INDEX_SMALL:
0151: processEII(
0152: _elementNameTable._array[_b
0153: & EncodingConstants.INTEGER_3RD_BIT_SMALL_MASK],
0154: true);
0155: firstElementHasOccured = true;
0156: break;
0157: case DecoderStateTables.EII_INDEX_MEDIUM:
0158: processEII(
0159: decodeEIIIndexMedium(),
0160: (_b & EncodingConstants.ELEMENT_ATTRIBUTE_FLAG) > 0);
0161: firstElementHasOccured = true;
0162: break;
0163: case DecoderStateTables.EII_INDEX_LARGE:
0164: processEII(
0165: decodeEIIIndexLarge(),
0166: (_b & EncodingConstants.ELEMENT_ATTRIBUTE_FLAG) > 0);
0167: firstElementHasOccured = true;
0168: break;
0169: case DecoderStateTables.EII_LITERAL: {
0170: final QualifiedName qn = processLiteralQualifiedName(
0171: _b
0172: & EncodingConstants.LITERAL_QNAME_PREFIX_NAMESPACE_NAME_MASK,
0173: _elementNameTable.getNext());
0174: _elementNameTable.add(qn);
0175: processEII(
0176: qn,
0177: (_b & EncodingConstants.ELEMENT_ATTRIBUTE_FLAG) > 0);
0178: firstElementHasOccured = true;
0179: break;
0180: }
0181: case DecoderStateTables.EII_NAMESPACES:
0182: processEIIWithNamespaces();
0183: firstElementHasOccured = true;
0184: break;
0185: case DecoderStateTables.DOCUMENT_TYPE_DECLARATION_II: {
0186: if (documentTypeDeclarationOccured) {
0187: throw new FastInfosetException(CommonResourceBundle
0188: .getInstance().getString(
0189: "message.secondOccurenceOfDTDII"));
0190: }
0191: documentTypeDeclarationOccured = true;
0192:
0193: String system_identifier = ((_b & EncodingConstants.DOCUMENT_TYPE_SYSTEM_IDENTIFIER_FLAG) > 0) ? decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherURI)
0194: : null;
0195: String public_identifier = ((_b & EncodingConstants.DOCUMENT_TYPE_PUBLIC_IDENTIFIER_FLAG) > 0) ? decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherURI)
0196: : null;
0197:
0198: _b = read();
0199: while (_b == EncodingConstants.PROCESSING_INSTRUCTION) {
0200: switch (decodeNonIdentifyingStringOnFirstBit()) {
0201: case NISTRING_STRING:
0202: if (_addToTable) {
0203: _v.otherString.add(new CharArray(
0204: _charBuffer, 0, _charBufferLength,
0205: true));
0206: }
0207: break;
0208: case NISTRING_ENCODING_ALGORITHM:
0209: throw new FastInfosetException(
0210: CommonResourceBundle
0211: .getInstance()
0212: .getString(
0213: "message.processingIIWithEncodingAlgorithm"));
0214: case NISTRING_INDEX:
0215: break;
0216: case NISTRING_EMPTY_STRING:
0217: break;
0218: }
0219: _b = read();
0220: }
0221: if ((_b & EncodingConstants.TERMINATOR) != EncodingConstants.TERMINATOR) {
0222: throw new FastInfosetException(
0223: CommonResourceBundle
0224: .getInstance()
0225: .getString(
0226: "message.processingInstructionIIsNotTerminatedCorrectly"));
0227: }
0228: if (_b == EncodingConstants.DOUBLE_TERMINATOR) {
0229: _terminate = true;
0230: }
0231:
0232: _notations.clear();
0233: _unparsedEntities.clear();
0234: /*
0235: * TODO
0236: * Report All events associated with DTD, PIs, notations etc
0237: */
0238: break;
0239: }
0240: case DecoderStateTables.COMMENT_II:
0241: processCommentII();
0242: break;
0243: case DecoderStateTables.PROCESSING_INSTRUCTION_II:
0244: processProcessingII();
0245: break;
0246: case DecoderStateTables.TERMINATOR_DOUBLE:
0247: _doubleTerminate = true;
0248: case DecoderStateTables.TERMINATOR_SINGLE:
0249: _terminate = true;
0250: break;
0251: default:
0252: throw new FastInfosetException(CommonResourceBundle
0253: .getInstance().getString(
0254: "message.IllegalStateDecodingDII"));
0255: }
0256: }
0257:
0258: // Decode any remaining Comment IIs, PI IIs
0259: while (!_terminate) {
0260: _b = read();
0261: switch (DecoderStateTables.DII[_b]) {
0262: case DecoderStateTables.COMMENT_II:
0263: processCommentII();
0264: break;
0265: case DecoderStateTables.PROCESSING_INSTRUCTION_II:
0266: processProcessingII();
0267: break;
0268: case DecoderStateTables.TERMINATOR_DOUBLE:
0269: _doubleTerminate = true;
0270: case DecoderStateTables.TERMINATOR_SINGLE:
0271: _terminate = true;
0272: break;
0273: default:
0274: throw new FastInfosetException(CommonResourceBundle
0275: .getInstance().getString(
0276: "message.IllegalStateDecodingDII"));
0277: }
0278: }
0279:
0280: }
0281:
0282: protected final void processDIIOptionalProperties()
0283: throws FastInfosetException, IOException {
0284: // Optimize for the most common case
0285: if (_b == EncodingConstants.DOCUMENT_INITIAL_VOCABULARY_FLAG) {
0286: decodeInitialVocabulary();
0287: return;
0288: }
0289:
0290: if ((_b & EncodingConstants.DOCUMENT_ADDITIONAL_DATA_FLAG) > 0) {
0291: decodeAdditionalData();
0292: /*
0293: * TODO
0294: * how to report the additional data?
0295: */
0296: }
0297:
0298: if ((_b & EncodingConstants.DOCUMENT_INITIAL_VOCABULARY_FLAG) > 0) {
0299: decodeInitialVocabulary();
0300: }
0301:
0302: if ((_b & EncodingConstants.DOCUMENT_NOTATIONS_FLAG) > 0) {
0303: decodeNotations();
0304: // TODO Report notations
0305: }
0306:
0307: if ((_b & EncodingConstants.DOCUMENT_UNPARSED_ENTITIES_FLAG) > 0) {
0308: decodeUnparsedEntities();
0309: // TODO Report unparsed entities
0310: }
0311:
0312: if ((_b & EncodingConstants.DOCUMENT_CHARACTER_ENCODING_SCHEME) > 0) {
0313: String version = decodeCharacterEncodingScheme();
0314: /*
0315: * TODO
0316: * how to report the character encoding scheme?
0317: */
0318: }
0319:
0320: if ((_b & EncodingConstants.DOCUMENT_STANDALONE_FLAG) > 0) {
0321: boolean standalone = (read() > 0) ? true : false;
0322: /*
0323: * TODO
0324: * how to report the standalone flag?
0325: */
0326: }
0327:
0328: if ((_b & EncodingConstants.DOCUMENT_VERSION_FLAG) > 0) {
0329: decodeVersion();
0330: /*
0331: * TODO
0332: * how to report the document version?
0333: */
0334: }
0335: }
0336:
0337: protected final void processEII(QualifiedName name,
0338: boolean hasAttributes) throws FastInfosetException,
0339: IOException {
0340: if (_prefixTable._currentInScope[name.prefixIndex] != name.namespaceNameIndex) {
0341: throw new FastInfosetException(CommonResourceBundle
0342: .getInstance().getString(
0343: "message.qnameOfEIINotInScope"));
0344: }
0345:
0346: final Node parentCurrentNode = _currentNode;
0347:
0348: _currentNode = _currentElement = createElement(
0349: name.namespaceName, name.qName, name.localName);
0350:
0351: if (_namespaceAttributesIndex > 0) {
0352: for (int i = 0; i < _namespaceAttributesIndex; i++) {
0353: _currentElement
0354: .setAttributeNode(_namespaceAttributes[i]);
0355: _namespaceAttributes[i] = null;
0356: }
0357: _namespaceAttributesIndex = 0;
0358: }
0359:
0360: if (hasAttributes) {
0361: processAIIs();
0362: }
0363:
0364: parentCurrentNode.appendChild(_currentElement);
0365:
0366: while (!_terminate) {
0367: _b = read();
0368: switch (DecoderStateTables.EII[_b]) {
0369: case DecoderStateTables.EII_NO_AIIS_INDEX_SMALL:
0370: processEII(_elementNameTable._array[_b], false);
0371: break;
0372: case DecoderStateTables.EII_AIIS_INDEX_SMALL:
0373: processEII(
0374: _elementNameTable._array[_b
0375: & EncodingConstants.INTEGER_3RD_BIT_SMALL_MASK],
0376: true);
0377: break;
0378: case DecoderStateTables.EII_INDEX_MEDIUM:
0379: processEII(
0380: decodeEIIIndexMedium(),
0381: (_b & EncodingConstants.ELEMENT_ATTRIBUTE_FLAG) > 0);
0382: break;
0383: case DecoderStateTables.EII_INDEX_LARGE:
0384: processEII(
0385: decodeEIIIndexLarge(),
0386: (_b & EncodingConstants.ELEMENT_ATTRIBUTE_FLAG) > 0);
0387: break;
0388: case DecoderStateTables.EII_LITERAL: {
0389: final QualifiedName qn = processLiteralQualifiedName(
0390: _b
0391: & EncodingConstants.LITERAL_QNAME_PREFIX_NAMESPACE_NAME_MASK,
0392: _elementNameTable.getNext());
0393: _elementNameTable.add(qn);
0394: processEII(
0395: qn,
0396: (_b & EncodingConstants.ELEMENT_ATTRIBUTE_FLAG) > 0);
0397: break;
0398: }
0399: case DecoderStateTables.EII_NAMESPACES:
0400: processEIIWithNamespaces();
0401: break;
0402: case DecoderStateTables.CII_UTF8_SMALL_LENGTH: {
0403: _octetBufferLength = (_b & EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_SMALL_MASK) + 1;
0404: processUtf8CharacterString();
0405: break;
0406: }
0407: case DecoderStateTables.CII_UTF8_MEDIUM_LENGTH: {
0408: _octetBufferLength = read()
0409: + EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_SMALL_LIMIT;
0410: processUtf8CharacterString();
0411: break;
0412: }
0413: case DecoderStateTables.CII_UTF8_LARGE_LENGTH: {
0414: _octetBufferLength = (read() << 24) | (read() << 16)
0415: | (read() << 8) | read();
0416: _octetBufferLength += EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_MEDIUM_LIMIT;
0417: processUtf8CharacterString();
0418: break;
0419: }
0420: case DecoderStateTables.CII_UTF16_SMALL_LENGTH: {
0421: _octetBufferLength = (_b & EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_SMALL_MASK) + 1;
0422: String v = decodeUtf16StringAsString();
0423: if ((_b & EncodingConstants.CHARACTER_CHUNK_ADD_TO_TABLE_FLAG) > 0) {
0424: _characterContentChunkTable.add(_charBuffer,
0425: _charBufferLength);
0426: }
0427:
0428: _currentNode.appendChild(_document.createTextNode(v));
0429: break;
0430: }
0431: case DecoderStateTables.CII_UTF16_MEDIUM_LENGTH: {
0432: _octetBufferLength = read()
0433: + EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_SMALL_LIMIT;
0434: String v = decodeUtf16StringAsString();
0435: if ((_b & EncodingConstants.CHARACTER_CHUNK_ADD_TO_TABLE_FLAG) > 0) {
0436: _characterContentChunkTable.add(_charBuffer,
0437: _charBufferLength);
0438: }
0439:
0440: _currentNode.appendChild(_document.createTextNode(v));
0441: break;
0442: }
0443: case DecoderStateTables.CII_UTF16_LARGE_LENGTH: {
0444: _octetBufferLength = (read() << 24) | (read() << 16)
0445: | (read() << 8) | read();
0446: _octetBufferLength += EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_MEDIUM_LIMIT;
0447: String v = decodeUtf16StringAsString();
0448: if ((_b & EncodingConstants.CHARACTER_CHUNK_ADD_TO_TABLE_FLAG) > 0) {
0449: _characterContentChunkTable.add(_charBuffer,
0450: _charBufferLength);
0451: }
0452:
0453: _currentNode.appendChild(_document.createTextNode(v));
0454: break;
0455: }
0456: case DecoderStateTables.CII_RA: {
0457: final boolean addToTable = (_b & EncodingConstants.CHARACTER_CHUNK_ADD_TO_TABLE_FLAG) > 0;
0458:
0459: // Decode resitricted alphabet integer
0460: _identifier = (_b & 0x02) << 6;
0461: _b = read();
0462: _identifier |= (_b & 0xFC) >> 2;
0463:
0464: decodeOctetsOnSeventhBitOfNonIdentifyingStringOnThirdBit(_b);
0465:
0466: String v = decodeRestrictedAlphabetAsString();
0467: if (addToTable) {
0468: _characterContentChunkTable.add(_charBuffer,
0469: _charBufferLength);
0470: }
0471:
0472: _currentNode.appendChild(_document.createTextNode(v));
0473: break;
0474: }
0475: case DecoderStateTables.CII_EA: {
0476: if ((_b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0) {
0477: throw new EncodingAlgorithmException(
0478: CommonResourceBundle
0479: .getInstance()
0480: .getString(
0481: "message.addToTableNotSupported"));
0482: }
0483:
0484: // Decode encoding algorithm integer
0485: _identifier = (_b & 0x02) << 6;
0486: _b = read();
0487: _identifier |= (_b & 0xFC) >> 2;
0488:
0489: decodeOctetsOnSeventhBitOfNonIdentifyingStringOnThirdBit(_b);
0490: final String s = convertEncodingAlgorithmDataToCharacters(false);
0491: _currentNode.appendChild(_document.createTextNode(s));
0492: break;
0493: }
0494: case DecoderStateTables.CII_INDEX_SMALL: {
0495: final String s = _characterContentChunkTable
0496: .getString(_b
0497: & EncodingConstants.INTEGER_4TH_BIT_SMALL_MASK);
0498:
0499: _currentNode.appendChild(_document.createTextNode(s));
0500: break;
0501: }
0502: case DecoderStateTables.CII_INDEX_MEDIUM: {
0503: final int index = (((_b & EncodingConstants.INTEGER_4TH_BIT_MEDIUM_MASK) << 8) | read())
0504: + EncodingConstants.INTEGER_4TH_BIT_SMALL_LIMIT;
0505: final String s = _characterContentChunkTable
0506: .getString(index);
0507:
0508: _currentNode.appendChild(_document.createTextNode(s));
0509: break;
0510: }
0511: case DecoderStateTables.CII_INDEX_LARGE: {
0512: int index = ((_b & EncodingConstants.INTEGER_4TH_BIT_LARGE_MASK) << 16)
0513: | (read() << 8) | read();
0514: index += EncodingConstants.INTEGER_4TH_BIT_MEDIUM_LIMIT;
0515: final String s = _characterContentChunkTable
0516: .getString(index);
0517:
0518: _currentNode.appendChild(_document.createTextNode(s));
0519: break;
0520: }
0521: case DecoderStateTables.CII_INDEX_LARGE_LARGE: {
0522: int index = (read() << 16) | (read() << 8) | read();
0523: index += EncodingConstants.INTEGER_4TH_BIT_LARGE_LIMIT;
0524: final String s = _characterContentChunkTable
0525: .getString(index);
0526:
0527: _currentNode.appendChild(_document.createTextNode(s));
0528: break;
0529: }
0530: case DecoderStateTables.COMMENT_II:
0531: processCommentII();
0532: break;
0533: case DecoderStateTables.PROCESSING_INSTRUCTION_II:
0534: processProcessingII();
0535: break;
0536: case DecoderStateTables.UNEXPANDED_ENTITY_REFERENCE_II: {
0537: String entity_reference_name = decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherNCName);
0538:
0539: String system_identifier = ((_b & EncodingConstants.UNEXPANDED_ENTITY_SYSTEM_IDENTIFIER_FLAG) > 0) ? decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherURI)
0540: : null;
0541: String public_identifier = ((_b & EncodingConstants.UNEXPANDED_ENTITY_PUBLIC_IDENTIFIER_FLAG) > 0) ? decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherURI)
0542: : null;
0543:
0544: // TODO create Node
0545: break;
0546: }
0547: case DecoderStateTables.TERMINATOR_DOUBLE:
0548: _doubleTerminate = true;
0549: case DecoderStateTables.TERMINATOR_SINGLE:
0550: _terminate = true;
0551: break;
0552: default:
0553: throw new FastInfosetException(CommonResourceBundle
0554: .getInstance().getString(
0555: "message.IllegalStateDecodingEII"));
0556: }
0557: }
0558:
0559: _terminate = _doubleTerminate;
0560: _doubleTerminate = false;
0561:
0562: _currentNode = parentCurrentNode;
0563: }
0564:
0565: private final void processUtf8CharacterString()
0566: throws FastInfosetException, IOException {
0567: if ((_b & EncodingConstants.CHARACTER_CHUNK_ADD_TO_TABLE_FLAG) > 0) {
0568: _characterContentChunkTable.ensureSize(_octetBufferLength);
0569: final int charactersOffset = _characterContentChunkTable._arrayIndex;
0570: decodeUtf8StringAsCharBuffer(
0571: _characterContentChunkTable._array,
0572: charactersOffset);
0573: _characterContentChunkTable.add(_charBufferLength);
0574: _currentNode
0575: .appendChild(_document
0576: .createTextNode(_characterContentChunkTable
0577: .getString(_characterContentChunkTable._cachedIndex)));
0578: } else {
0579: decodeUtf8StringAsCharBuffer();
0580: _currentNode.appendChild(_document
0581: .createTextNode(new String(_charBuffer, 0,
0582: _charBufferLength)));
0583: }
0584: }
0585:
0586: protected final void processEIIWithNamespaces()
0587: throws FastInfosetException, IOException {
0588: final boolean hasAttributes = (_b & EncodingConstants.ELEMENT_ATTRIBUTE_FLAG) > 0;
0589:
0590: if (++_prefixTable._declarationId == Integer.MAX_VALUE) {
0591: _prefixTable.clearDeclarationIds();
0592: }
0593:
0594: String prefix;
0595: Attr a = null;
0596: final int start = _namespacePrefixesIndex;
0597: int b = read();
0598: while ((b & EncodingConstants.NAMESPACE_ATTRIBUTE_MASK) == EncodingConstants.NAMESPACE_ATTRIBUTE) {
0599: if (_namespaceAttributesIndex == _namespaceAttributes.length) {
0600: final Attr[] newNamespaceAttributes = new Attr[_namespaceAttributesIndex * 3 / 2 + 1];
0601: System.arraycopy(_namespaceAttributes, 0,
0602: newNamespaceAttributes, 0,
0603: _namespaceAttributesIndex);
0604: _namespaceAttributes = newNamespaceAttributes;
0605: }
0606:
0607: if (_namespacePrefixesIndex == _namespacePrefixes.length) {
0608: final int[] namespaceAIIs = new int[_namespacePrefixesIndex * 3 / 2 + 1];
0609: System.arraycopy(_namespacePrefixes, 0, namespaceAIIs,
0610: 0, _namespacePrefixesIndex);
0611: _namespacePrefixes = namespaceAIIs;
0612: }
0613:
0614: switch (b
0615: & EncodingConstants.NAMESPACE_ATTRIBUTE_PREFIX_NAME_MASK) {
0616: // no prefix, no namespace
0617: // Undeclaration of default namespace
0618: case 0:
0619: a = createAttribute(
0620: EncodingConstants.XMLNS_NAMESPACE_NAME,
0621: EncodingConstants.XMLNS_NAMESPACE_PREFIX,
0622: EncodingConstants.XMLNS_NAMESPACE_PREFIX);
0623: a.setValue("");
0624:
0625: _prefixIndex = _namespaceNameIndex = _namespacePrefixes[_namespacePrefixesIndex++] = -1;
0626: break;
0627: // no prefix, namespace
0628: // Declaration of default namespace
0629: case 1:
0630: a = createAttribute(
0631: EncodingConstants.XMLNS_NAMESPACE_NAME,
0632: EncodingConstants.XMLNS_NAMESPACE_PREFIX,
0633: EncodingConstants.XMLNS_NAMESPACE_PREFIX);
0634: a
0635: .setValue(decodeIdentifyingNonEmptyStringOnFirstBitAsNamespaceName(false));
0636:
0637: _prefixIndex = _namespacePrefixes[_namespacePrefixesIndex++] = -1;
0638: break;
0639: // prefix, no namespace
0640: // Undeclaration of namespace
0641: case 2:
0642: prefix = decodeIdentifyingNonEmptyStringOnFirstBitAsPrefix(false);
0643: a = createAttribute(
0644: EncodingConstants.XMLNS_NAMESPACE_NAME,
0645: createQualifiedNameString(
0646: XMLNS_NAMESPACE_PREFIX_CHARS, prefix),
0647: prefix);
0648: a.setValue("");
0649:
0650: _namespaceNameIndex = -1;
0651: _namespacePrefixes[_namespacePrefixesIndex++] = _prefixIndex;
0652: break;
0653: // prefix, namespace
0654: // Declaration of prefixed namespace
0655: case 3:
0656: prefix = decodeIdentifyingNonEmptyStringOnFirstBitAsPrefix(true);
0657: a = createAttribute(
0658: EncodingConstants.XMLNS_NAMESPACE_NAME,
0659: createQualifiedNameString(
0660: XMLNS_NAMESPACE_PREFIX_CHARS, prefix),
0661: prefix);
0662: a
0663: .setValue(decodeIdentifyingNonEmptyStringOnFirstBitAsNamespaceName(true));
0664:
0665: _namespacePrefixes[_namespacePrefixesIndex++] = _prefixIndex;
0666: break;
0667: }
0668:
0669: _prefixTable.pushScope(_prefixIndex, _namespaceNameIndex);
0670:
0671: _namespaceAttributes[_namespaceAttributesIndex++] = a;
0672:
0673: b = read();
0674: }
0675: if (b != EncodingConstants.TERMINATOR) {
0676: throw new IOException(
0677: CommonResourceBundle
0678: .getInstance()
0679: .getString(
0680: "message.EIInamespaceNameNotTerminatedCorrectly"));
0681: }
0682: final int end = _namespacePrefixesIndex;
0683:
0684: _b = read();
0685: switch (DecoderStateTables.EII[_b]) {
0686: case DecoderStateTables.EII_NO_AIIS_INDEX_SMALL:
0687: processEII(_elementNameTable._array[_b], hasAttributes);
0688: break;
0689: case DecoderStateTables.EII_INDEX_MEDIUM:
0690: processEII(decodeEIIIndexMedium(), hasAttributes);
0691: break;
0692: case DecoderStateTables.EII_INDEX_LARGE:
0693: processEII(decodeEIIIndexLarge(), hasAttributes);
0694: break;
0695: case DecoderStateTables.EII_LITERAL: {
0696: final QualifiedName qn = processLiteralQualifiedName(
0697: _b
0698: & EncodingConstants.LITERAL_QNAME_PREFIX_NAMESPACE_NAME_MASK,
0699: _elementNameTable.getNext());
0700: _elementNameTable.add(qn);
0701: processEII(qn, hasAttributes);
0702: break;
0703: }
0704: default:
0705: throw new IOException(CommonResourceBundle.getInstance()
0706: .getString(
0707: "message.IllegalStateDecodingEIIAfterAIIs"));
0708: }
0709:
0710: for (int i = start; i < end; i++) {
0711: _prefixTable.popScope(_namespacePrefixes[i]);
0712: }
0713: _namespacePrefixesIndex = start;
0714:
0715: }
0716:
0717: protected final QualifiedName processLiteralQualifiedName(
0718: int state, QualifiedName q) throws FastInfosetException,
0719: IOException {
0720: if (q == null)
0721: q = new QualifiedName();
0722:
0723: switch (state) {
0724: // no prefix, no namespace
0725: case 0:
0726: return q
0727: .set(
0728: null,
0729: null,
0730: decodeIdentifyingNonEmptyStringOnFirstBit(_v.localName),
0731: -1, -1, _identifier, null);
0732: // no prefix, namespace
0733: case 1:
0734: return q
0735: .set(
0736: null,
0737: decodeIdentifyingNonEmptyStringIndexOnFirstBitAsNamespaceName(false),
0738: decodeIdentifyingNonEmptyStringOnFirstBit(_v.localName),
0739: -1, _namespaceNameIndex, _identifier, null);
0740: // prefix, no namespace
0741: case 2:
0742: throw new FastInfosetException(CommonResourceBundle
0743: .getInstance().getString(
0744: "message.qNameMissingNamespaceName"));
0745: // prefix, namespace
0746: case 3:
0747: return q
0748: .set(
0749: decodeIdentifyingNonEmptyStringIndexOnFirstBitAsPrefix(true),
0750: decodeIdentifyingNonEmptyStringIndexOnFirstBitAsNamespaceName(true),
0751: decodeIdentifyingNonEmptyStringOnFirstBit(_v.localName),
0752: _prefixIndex, _namespaceNameIndex,
0753: _identifier, _charBuffer);
0754: default:
0755: throw new FastInfosetException(CommonResourceBundle
0756: .getInstance().getString("message.decodingEII"));
0757: }
0758: }
0759:
0760: protected final QualifiedName processLiteralQualifiedName(int state)
0761: throws FastInfosetException, IOException {
0762: switch (state) {
0763: // no prefix, no namespace
0764: case 0:
0765: return new QualifiedName(
0766: null,
0767: null,
0768: decodeIdentifyingNonEmptyStringOnFirstBit(_v.localName),
0769: -1, -1, _identifier, null);
0770: // no prefix, namespace
0771: case 1:
0772: return new QualifiedName(
0773: null,
0774: decodeIdentifyingNonEmptyStringIndexOnFirstBitAsNamespaceName(false),
0775: decodeIdentifyingNonEmptyStringOnFirstBit(_v.localName),
0776: -1, _namespaceNameIndex, _identifier, null);
0777: // prefix, no namespace
0778: case 2:
0779: throw new FastInfosetException(CommonResourceBundle
0780: .getInstance().getString(
0781: "message.qNameMissingNamespaceName"));
0782: // prefix, namespace
0783: case 3:
0784: return new QualifiedName(
0785: decodeIdentifyingNonEmptyStringIndexOnFirstBitAsPrefix(true),
0786: decodeIdentifyingNonEmptyStringIndexOnFirstBitAsNamespaceName(true),
0787: decodeIdentifyingNonEmptyStringOnFirstBit(_v.localName),
0788: _prefixIndex, _namespaceNameIndex, _identifier,
0789: _charBuffer);
0790: default:
0791: throw new FastInfosetException(CommonResourceBundle
0792: .getInstance().getString("message.decodingEII"));
0793: }
0794: }
0795:
0796: protected final void processAIIs() throws FastInfosetException,
0797: IOException {
0798: QualifiedName name;
0799: int b;
0800: String value;
0801:
0802: if (++_duplicateAttributeVerifier._currentIteration == Integer.MAX_VALUE) {
0803: _duplicateAttributeVerifier.clear();
0804: }
0805:
0806: do {
0807: // AII qualified name
0808: b = read();
0809: switch (DecoderStateTables.AII[b]) {
0810: case DecoderStateTables.AII_INDEX_SMALL:
0811: name = _attributeNameTable._array[b];
0812: break;
0813: case DecoderStateTables.AII_INDEX_MEDIUM: {
0814: final int i = (((b & EncodingConstants.INTEGER_2ND_BIT_MEDIUM_MASK) << 8) | read())
0815: + EncodingConstants.INTEGER_2ND_BIT_SMALL_LIMIT;
0816: name = _attributeNameTable._array[i];
0817: break;
0818: }
0819: case DecoderStateTables.AII_INDEX_LARGE: {
0820: final int i = (((b & EncodingConstants.INTEGER_2ND_BIT_LARGE_MASK) << 16)
0821: | (read() << 8) | read())
0822: + EncodingConstants.INTEGER_2ND_BIT_MEDIUM_LIMIT;
0823: name = _attributeNameTable._array[i];
0824: break;
0825: }
0826: case DecoderStateTables.AII_LITERAL:
0827: name = processLiteralQualifiedName(
0828: b
0829: & EncodingConstants.LITERAL_QNAME_PREFIX_NAMESPACE_NAME_MASK,
0830: _attributeNameTable.getNext());
0831: name
0832: .createAttributeValues(_duplicateAttributeVerifier.MAP_SIZE);
0833: _attributeNameTable.add(name);
0834: break;
0835: case DecoderStateTables.AII_TERMINATOR_DOUBLE:
0836: _doubleTerminate = true;
0837: case DecoderStateTables.AII_TERMINATOR_SINGLE:
0838: _terminate = true;
0839: // AIIs have finished break out of loop
0840: continue;
0841: default:
0842: throw new IOException(CommonResourceBundle
0843: .getInstance()
0844: .getString("message.decodingAIIs"));
0845: }
0846:
0847: if (name.prefixIndex > 0
0848: && _prefixTable._currentInScope[name.prefixIndex] != name.namespaceNameIndex) {
0849: throw new FastInfosetException(CommonResourceBundle
0850: .getInstance().getString(
0851: "message.AIIqNameNotInScope"));
0852: }
0853:
0854: _duplicateAttributeVerifier.checkForDuplicateAttribute(
0855: name.attributeHash, name.attributeId);
0856:
0857: Attr a = createAttribute(name.namespaceName, name.qName,
0858: name.localName);
0859:
0860: // [normalized value] of AII
0861:
0862: b = read();
0863: switch (DecoderStateTables.NISTRING[b]) {
0864: case DecoderStateTables.NISTRING_UTF8_SMALL_LENGTH: {
0865: final boolean addToTable = (b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0;
0866: _octetBufferLength = (b & EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_SMALL_MASK) + 1;
0867: value = decodeUtf8StringAsString();
0868: if (addToTable) {
0869: _attributeValueTable.add(value);
0870: }
0871:
0872: a.setValue(value);
0873: _currentElement.setAttributeNode(a);
0874: break;
0875: }
0876: case DecoderStateTables.NISTRING_UTF8_MEDIUM_LENGTH: {
0877: final boolean addToTable = (b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0;
0878: _octetBufferLength = read()
0879: + EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_SMALL_LIMIT;
0880: value = decodeUtf8StringAsString();
0881: if (addToTable) {
0882: _attributeValueTable.add(value);
0883: }
0884:
0885: a.setValue(value);
0886: _currentElement.setAttributeNode(a);
0887: break;
0888: }
0889: case DecoderStateTables.NISTRING_UTF8_LARGE_LENGTH: {
0890: final boolean addToTable = (b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0;
0891: final int length = (read() << 24) | (read() << 16)
0892: | (read() << 8) | read();
0893: _octetBufferLength = length
0894: + EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_MEDIUM_LIMIT;
0895: value = decodeUtf8StringAsString();
0896: if (addToTable) {
0897: _attributeValueTable.add(value);
0898: }
0899:
0900: a.setValue(value);
0901: _currentElement.setAttributeNode(a);
0902: break;
0903: }
0904: case DecoderStateTables.NISTRING_UTF16_SMALL_LENGTH: {
0905: final boolean addToTable = (b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0;
0906: _octetBufferLength = (b & EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_SMALL_MASK) + 1;
0907: value = decodeUtf16StringAsString();
0908: if (addToTable) {
0909: _attributeValueTable.add(value);
0910: }
0911:
0912: a.setValue(value);
0913: _currentElement.setAttributeNode(a);
0914: break;
0915: }
0916: case DecoderStateTables.NISTRING_UTF16_MEDIUM_LENGTH: {
0917: final boolean addToTable = (b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0;
0918: _octetBufferLength = read()
0919: + EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_SMALL_LIMIT;
0920: value = decodeUtf16StringAsString();
0921: if (addToTable) {
0922: _attributeValueTable.add(value);
0923: }
0924:
0925: a.setValue(value);
0926: _currentElement.setAttributeNode(a);
0927: break;
0928: }
0929: case DecoderStateTables.NISTRING_UTF16_LARGE_LENGTH: {
0930: final boolean addToTable = (b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0;
0931: final int length = (read() << 24) | (read() << 16)
0932: | (read() << 8) | read();
0933: _octetBufferLength = length
0934: + EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_MEDIUM_LIMIT;
0935: value = decodeUtf16StringAsString();
0936: if (addToTable) {
0937: _attributeValueTable.add(value);
0938: }
0939:
0940: a.setValue(value);
0941: _currentElement.setAttributeNode(a);
0942: break;
0943: }
0944: case DecoderStateTables.NISTRING_RA: {
0945: final boolean addToTable = (b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0;
0946: // Decode resitricted alphabet integer
0947: _identifier = (b & 0x0F) << 4;
0948: b = read();
0949: _identifier |= (b & 0xF0) >> 4;
0950:
0951: decodeOctetsOnFifthBitOfNonIdentifyingStringOnFirstBit(b);
0952:
0953: value = decodeRestrictedAlphabetAsString();
0954: if (addToTable) {
0955: _attributeValueTable.add(value);
0956: }
0957:
0958: a.setValue(value);
0959: _currentElement.setAttributeNode(a);
0960: break;
0961: }
0962: case DecoderStateTables.NISTRING_EA: {
0963: if ((b & EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG) > 0) {
0964: throw new EncodingAlgorithmException(
0965: CommonResourceBundle
0966: .getInstance()
0967: .getString(
0968: "message.addToTableNotSupported"));
0969: }
0970:
0971: _identifier = (b & 0x0F) << 4;
0972: b = read();
0973: _identifier |= (b & 0xF0) >> 4;
0974:
0975: decodeOctetsOnFifthBitOfNonIdentifyingStringOnFirstBit(b);
0976: value = convertEncodingAlgorithmDataToCharacters(true);
0977: a.setValue(value);
0978: _currentElement.setAttributeNode(a);
0979: break;
0980: }
0981: case DecoderStateTables.NISTRING_INDEX_SMALL:
0982: value = _attributeValueTable._array[b
0983: & EncodingConstants.INTEGER_2ND_BIT_SMALL_MASK];
0984:
0985: a.setValue(value);
0986: _currentElement.setAttributeNode(a);
0987: break;
0988: case DecoderStateTables.NISTRING_INDEX_MEDIUM: {
0989: final int index = (((b & EncodingConstants.INTEGER_2ND_BIT_MEDIUM_MASK) << 8) | read())
0990: + EncodingConstants.INTEGER_2ND_BIT_SMALL_LIMIT;
0991: value = _attributeValueTable._array[index];
0992:
0993: a.setValue(value);
0994: _currentElement.setAttributeNode(a);
0995: break;
0996: }
0997: case DecoderStateTables.NISTRING_INDEX_LARGE: {
0998: final int index = (((b & EncodingConstants.INTEGER_2ND_BIT_LARGE_MASK) << 16)
0999: | (read() << 8) | read())
1000: + EncodingConstants.INTEGER_2ND_BIT_MEDIUM_LIMIT;
1001: value = _attributeValueTable._array[index];
1002:
1003: a.setValue(value);
1004: _currentElement.setAttributeNode(a);
1005: break;
1006: }
1007: case DecoderStateTables.NISTRING_EMPTY:
1008: a.setValue("");
1009: _currentElement.setAttributeNode(a);
1010: break;
1011: default:
1012: throw new IOException(CommonResourceBundle
1013: .getInstance().getString(
1014: "message.decodingAIIValue"));
1015: }
1016:
1017: } while (!_terminate);
1018:
1019: // Reset duplication attribute verfifier
1020: _duplicateAttributeVerifier._poolCurrent = _duplicateAttributeVerifier._poolHead;
1021:
1022: _terminate = _doubleTerminate;
1023: _doubleTerminate = false;
1024: }
1025:
1026: protected final void processCommentII()
1027: throws FastInfosetException, IOException {
1028: switch (decodeNonIdentifyingStringOnFirstBit()) {
1029: case NISTRING_STRING: {
1030: final String s = new String(_charBuffer, 0,
1031: _charBufferLength);
1032: if (_addToTable) {
1033: _v.otherString.add(new CharArrayString(s, false));
1034: }
1035:
1036: _currentNode.appendChild(_document.createComment(s));
1037: break;
1038: }
1039: case NISTRING_ENCODING_ALGORITHM:
1040: throw new IOException(
1041: CommonResourceBundle.getInstance().getString(
1042: "message.commentIIAlgorithmNotSupported"));
1043: case NISTRING_INDEX: {
1044: final String s = _v.otherString.get(_integer).toString();
1045:
1046: _currentNode.appendChild(_document.createComment(s));
1047: break;
1048: }
1049: case NISTRING_EMPTY_STRING:
1050: _currentNode.appendChild(_document.createComment(""));
1051: break;
1052: }
1053: }
1054:
1055: protected final void processProcessingII()
1056: throws FastInfosetException, IOException {
1057: final String target = decodeIdentifyingNonEmptyStringOnFirstBit(_v.otherNCName);
1058:
1059: switch (decodeNonIdentifyingStringOnFirstBit()) {
1060: case NISTRING_STRING: {
1061: final String data = new String(_charBuffer, 0,
1062: _charBufferLength);
1063: if (_addToTable) {
1064: _v.otherString.add(new CharArrayString(data, false));
1065: }
1066:
1067: _currentNode.appendChild(_document
1068: .createProcessingInstruction(target, data));
1069: break;
1070: }
1071: case NISTRING_ENCODING_ALGORITHM:
1072: throw new IOException(
1073: CommonResourceBundle
1074: .getInstance()
1075: .getString(
1076: "message.processingIIWithEncodingAlgorithm"));
1077: case NISTRING_INDEX: {
1078: final String data = _v.otherString.get(_integer).toString();
1079:
1080: _currentNode.appendChild(_document
1081: .createProcessingInstruction(target, data));
1082: break;
1083: }
1084: case NISTRING_EMPTY_STRING:
1085: _currentNode.appendChild(_document
1086: .createProcessingInstruction(target, ""));
1087: break;
1088: }
1089: }
1090:
1091: protected Element createElement(String namespaceName, String qName,
1092: String localName) {
1093: return _document.createElementNS(namespaceName, qName);
1094: }
1095:
1096: protected Attr createAttribute(String namespaceName, String qName,
1097: String localName) {
1098: return _document.createAttributeNS(namespaceName, qName);
1099: }
1100:
1101: protected String convertEncodingAlgorithmDataToCharacters(
1102: boolean isAttributeValue) throws FastInfosetException,
1103: IOException {
1104: StringBuffer buffer = new StringBuffer();
1105: if (_identifier < EncodingConstants.ENCODING_ALGORITHM_BUILTIN_END) {
1106: Object array = BuiltInEncodingAlgorithmFactory.table[_identifier]
1107: .decodeFromBytes(_octetBuffer, _octetBufferStart,
1108: _octetBufferLength);
1109: BuiltInEncodingAlgorithmFactory.table[_identifier]
1110: .convertToCharacters(array, buffer);
1111: } else if (_identifier == EncodingAlgorithmIndexes.CDATA) {
1112: if (!isAttributeValue) {
1113: // Set back buffer position to start of encoded string
1114: _octetBufferOffset -= _octetBufferLength;
1115: return decodeUtf8StringAsString();
1116: }
1117: throw new EncodingAlgorithmException(CommonResourceBundle
1118: .getInstance().getString(
1119: "message.CDATAAlgorithmNotSupported"));
1120: } else if (_identifier >= EncodingConstants.ENCODING_ALGORITHM_APPLICATION_START) {
1121: final String URI = _v.encodingAlgorithm
1122: .get(_identifier
1123: - EncodingConstants.ENCODING_ALGORITHM_APPLICATION_START);
1124: final EncodingAlgorithm ea = (EncodingAlgorithm) _registeredEncodingAlgorithms
1125: .get(URI);
1126: if (ea != null) {
1127: final Object data = ea.decodeFromBytes(_octetBuffer,
1128: _octetBufferStart, _octetBufferLength);
1129: ea.convertToCharacters(data, buffer);
1130: } else {
1131: throw new EncodingAlgorithmException(
1132: CommonResourceBundle
1133: .getInstance()
1134: .getString(
1135: "message.algorithmDataCannotBeReported"));
1136: }
1137: }
1138: return buffer.toString();
1139: }
1140:
1141: }
|