1 /*
   2  * Copyright (c) 2005, 2012, 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 
  26 package com.sun.xml.internal.stream.buffer;
  27 
  28 /**
  29  * Base class for classes that processes {@link XMLStreamBuffer}
  30  * and produces infoset in API-specific form.
  31  */
  32 public abstract class AbstractProcessor extends AbstractCreatorProcessor {
  33     protected  static final int STATE_ILLEGAL                       = 0;
  34 
  35     protected  static final int STATE_DOCUMENT                      = 1;
  36     protected  static final int STATE_DOCUMENT_FRAGMENT             = 2;
  37     protected  static final int STATE_ELEMENT_U_LN_QN               = 3;
  38     protected  static final int STATE_ELEMENT_P_U_LN                = 4;
  39     protected  static final int STATE_ELEMENT_U_LN                  = 5;
  40     protected  static final int STATE_ELEMENT_LN                    = 6;
  41     protected  static final int STATE_TEXT_AS_CHAR_ARRAY_SMALL      = 7;
  42     protected  static final int STATE_TEXT_AS_CHAR_ARRAY_MEDIUM     = 8;
  43     protected  static final int STATE_TEXT_AS_CHAR_ARRAY_COPY       = 9;
  44     protected  static final int STATE_TEXT_AS_STRING                = 10;
  45     protected  static final int STATE_TEXT_AS_OBJECT                = 11;
  46     protected  static final int STATE_COMMENT_AS_CHAR_ARRAY_SMALL   = 12;
  47     protected  static final int STATE_COMMENT_AS_CHAR_ARRAY_MEDIUM  = 13;
  48     protected  static final int STATE_COMMENT_AS_CHAR_ARRAY_COPY    = 14;
  49     protected  static final int STATE_COMMENT_AS_STRING             = 15;
  50     protected  static final int STATE_PROCESSING_INSTRUCTION        = 16;
  51     protected  static final int STATE_END                           = 17;
  52     private  static final int[] _eiiStateTable = new int[256];
  53 
  54     protected  static final int STATE_NAMESPACE_ATTRIBUTE           = 1;
  55     protected  static final int STATE_NAMESPACE_ATTRIBUTE_P         = 2;
  56     protected  static final int STATE_NAMESPACE_ATTRIBUTE_P_U       = 3;
  57     protected  static final int STATE_NAMESPACE_ATTRIBUTE_U         = 4;
  58     private  static final int[] _niiStateTable = new int[256];
  59 
  60     protected  static final int STATE_ATTRIBUTE_U_LN_QN             = 1;
  61     protected  static final int STATE_ATTRIBUTE_P_U_LN              = 2;
  62     protected  static final int STATE_ATTRIBUTE_U_LN                = 3;
  63     protected  static final int STATE_ATTRIBUTE_LN                  = 4;
  64     protected  static final int STATE_ATTRIBUTE_U_LN_QN_OBJECT      = 5;
  65     protected  static final int STATE_ATTRIBUTE_P_U_LN_OBJECT       = 6;
  66     protected  static final int STATE_ATTRIBUTE_U_LN_OBJECT         = 7;
  67     protected  static final int STATE_ATTRIBUTE_LN_OBJECT           = 8;
  68     private  static final int[] _aiiStateTable = new int[256];
  69 
  70     static {
  71         /*
  72          * Create a state table from information items and options.
  73          * The swtich statement using such states will often generate a more
  74          * efficient byte code representation that can be hotspotted using
  75          * jump tables.
  76          */
  77         _eiiStateTable[T_DOCUMENT] = STATE_DOCUMENT;
  78         _eiiStateTable[T_DOCUMENT_FRAGMENT] = STATE_DOCUMENT_FRAGMENT;
  79         _eiiStateTable[T_ELEMENT_U_LN_QN] = STATE_ELEMENT_U_LN_QN;
  80         _eiiStateTable[T_ELEMENT_P_U_LN] = STATE_ELEMENT_P_U_LN;
  81         _eiiStateTable[T_ELEMENT_U_LN] = STATE_ELEMENT_U_LN;
  82         _eiiStateTable[T_ELEMENT_LN] = STATE_ELEMENT_LN;
  83         _eiiStateTable[T_TEXT_AS_CHAR_ARRAY_SMALL] = STATE_TEXT_AS_CHAR_ARRAY_SMALL;
  84         _eiiStateTable[T_TEXT_AS_CHAR_ARRAY_MEDIUM] = STATE_TEXT_AS_CHAR_ARRAY_MEDIUM;
  85         _eiiStateTable[T_TEXT_AS_CHAR_ARRAY_COPY] = STATE_TEXT_AS_CHAR_ARRAY_COPY;
  86         _eiiStateTable[T_TEXT_AS_STRING] = STATE_TEXT_AS_STRING;
  87         _eiiStateTable[T_TEXT_AS_OBJECT] = STATE_TEXT_AS_OBJECT;
  88         _eiiStateTable[T_COMMENT_AS_CHAR_ARRAY_SMALL] = STATE_COMMENT_AS_CHAR_ARRAY_SMALL;
  89         _eiiStateTable[T_COMMENT_AS_CHAR_ARRAY_MEDIUM] = STATE_COMMENT_AS_CHAR_ARRAY_MEDIUM;
  90         _eiiStateTable[T_COMMENT_AS_CHAR_ARRAY_COPY] = STATE_COMMENT_AS_CHAR_ARRAY_COPY;
  91         _eiiStateTable[T_COMMENT_AS_STRING] = STATE_COMMENT_AS_STRING;
  92         _eiiStateTable[T_PROCESSING_INSTRUCTION] = STATE_PROCESSING_INSTRUCTION;
  93         _eiiStateTable[T_END] = STATE_END;
  94 
  95         _niiStateTable[T_NAMESPACE_ATTRIBUTE] = STATE_NAMESPACE_ATTRIBUTE;
  96         _niiStateTable[T_NAMESPACE_ATTRIBUTE_P] = STATE_NAMESPACE_ATTRIBUTE_P;
  97         _niiStateTable[T_NAMESPACE_ATTRIBUTE_P_U] = STATE_NAMESPACE_ATTRIBUTE_P_U;
  98         _niiStateTable[T_NAMESPACE_ATTRIBUTE_U] = STATE_NAMESPACE_ATTRIBUTE_U;
  99 
 100         _aiiStateTable[T_ATTRIBUTE_U_LN_QN] = STATE_ATTRIBUTE_U_LN_QN;
 101         _aiiStateTable[T_ATTRIBUTE_P_U_LN] = STATE_ATTRIBUTE_P_U_LN;
 102         _aiiStateTable[T_ATTRIBUTE_U_LN] = STATE_ATTRIBUTE_U_LN;
 103         _aiiStateTable[T_ATTRIBUTE_LN] = STATE_ATTRIBUTE_LN;
 104         _aiiStateTable[T_ATTRIBUTE_U_LN_QN_OBJECT] = STATE_ATTRIBUTE_U_LN_QN_OBJECT;
 105         _aiiStateTable[T_ATTRIBUTE_P_U_LN_OBJECT] = STATE_ATTRIBUTE_P_U_LN_OBJECT;
 106         _aiiStateTable[T_ATTRIBUTE_U_LN_OBJECT] = STATE_ATTRIBUTE_U_LN_OBJECT;
 107         _aiiStateTable[T_ATTRIBUTE_LN_OBJECT] = STATE_ATTRIBUTE_LN_OBJECT;
 108     }
 109 
 110     protected XMLStreamBuffer _buffer;
 111 
 112     /**
 113      * True if this processor should create a fragment of XML, without the start/end document markers.
 114      */
 115     protected boolean _fragmentMode;
 116 
 117     protected boolean _stringInterningFeature = false;
 118 
 119     /**
 120      * Number of remaining XML element trees that should be visible
 121      * through this {@link AbstractProcessor}.
 122      */
 123     protected int _treeCount;
 124 
 125     /**
 126      * @deprecated
 127      *      Use {@link #setBuffer(XMLStreamBuffer, boolean)}
 128      */
 129     protected final void setBuffer(XMLStreamBuffer buffer) {
 130         setBuffer(buffer,buffer.isFragment());
 131     }
 132     protected final void setBuffer(XMLStreamBuffer buffer, boolean fragmentMode) {
 133         _buffer = buffer;
 134         _fragmentMode = fragmentMode;
 135 
 136         _currentStructureFragment = _buffer.getStructure();
 137         _structure = _currentStructureFragment.getArray();
 138         _structurePtr = _buffer.getStructurePtr();
 139 
 140         _currentStructureStringFragment = _buffer.getStructureStrings();
 141         _structureStrings = _currentStructureStringFragment.getArray();
 142         _structureStringsPtr = _buffer.getStructureStringsPtr();
 143 
 144         _currentContentCharactersBufferFragment = _buffer.getContentCharactersBuffer();
 145         _contentCharactersBuffer = _currentContentCharactersBufferFragment.getArray();
 146         _contentCharactersBufferPtr = _buffer.getContentCharactersBufferPtr();
 147 
 148         _currentContentObjectFragment = _buffer.getContentObjects();
 149         _contentObjects = _currentContentObjectFragment.getArray();
 150         _contentObjectsPtr = _buffer.getContentObjectsPtr();
 151 
 152         _stringInterningFeature = _buffer.hasInternedStrings();
 153         _treeCount = _buffer.treeCount;
 154     }
 155 
 156     protected final int peekStructure() {
 157         if (_structurePtr < _structure.length) {
 158             return _structure[_structurePtr] & 255;
 159         }
 160 
 161         return readFromNextStructure(0);
 162     }
 163 
 164     protected final int readStructure() {
 165         if (_structurePtr < _structure.length) {
 166             return _structure[_structurePtr++] & 255;
 167         }
 168 
 169         return readFromNextStructure(1);
 170     }
 171 
 172     protected final int readEiiState() {
 173         return _eiiStateTable[readStructure()];
 174     }
 175 
 176     protected static int getEIIState(int item) {
 177         return _eiiStateTable[item];
 178     }
 179 
 180     protected static int getNIIState(int item) {
 181         return _niiStateTable[item];
 182     }
 183 
 184     protected static int getAIIState(int item) {
 185         return _aiiStateTable[item];
 186     }
 187 
 188     protected final int readStructure16() {
 189         return (readStructure() << 8) | readStructure();
 190     }
 191 
 192     private int readFromNextStructure(int v) {
 193         _structurePtr = v;
 194         _currentStructureFragment = _currentStructureFragment.getNext();
 195         _structure = _currentStructureFragment.getArray();
 196         return _structure[0] & 255;
 197     }
 198 
 199     protected final String readStructureString() {
 200         if (_structureStringsPtr < _structureStrings.length) {
 201             return _structureStrings[_structureStringsPtr++];
 202         }
 203 
 204         _structureStringsPtr = 1;
 205         _currentStructureStringFragment = _currentStructureStringFragment.getNext();
 206         _structureStrings = _currentStructureStringFragment.getArray();
 207         return _structureStrings[0];
 208     }
 209 
 210     protected final String readContentString() {
 211         return (String)readContentObject();
 212     }
 213 
 214     protected final char[] readContentCharactersCopy() {
 215         return (char[])readContentObject();
 216     }
 217 
 218     protected final int readContentCharactersBuffer(int length) {
 219         if (_contentCharactersBufferPtr + length < _contentCharactersBuffer.length) {
 220             final int start = _contentCharactersBufferPtr;
 221             _contentCharactersBufferPtr += length;
 222             return start;
 223         }
 224 
 225         _contentCharactersBufferPtr = length;
 226         _currentContentCharactersBufferFragment = _currentContentCharactersBufferFragment.getNext();
 227         _contentCharactersBuffer = _currentContentCharactersBufferFragment.getArray();
 228         return 0;
 229     }
 230 
 231     protected final Object readContentObject() {
 232         if (_contentObjectsPtr < _contentObjects.length) {
 233             return _contentObjects[_contentObjectsPtr++];
 234         }
 235 
 236         _contentObjectsPtr = 1;
 237         _currentContentObjectFragment = _currentContentObjectFragment.getNext();
 238         _contentObjects = _currentContentObjectFragment.getArray();
 239         return _contentObjects[0];
 240     }
 241 
 242     protected final StringBuilder _qNameBuffer = new StringBuilder();
 243 
 244     protected final String getQName(String prefix, String localName) {
 245         _qNameBuffer.append(prefix).append(':').append(localName);
 246         final String qName = _qNameBuffer.toString();
 247         _qNameBuffer.setLength(0);
 248         return (_stringInterningFeature) ? qName.intern() : qName;
 249     }
 250 
 251     protected final String getPrefixFromQName(String qName) {
 252         int pIndex = qName.indexOf(':');
 253         if (_stringInterningFeature) {
 254             return (pIndex != -1) ? qName.substring(0,pIndex).intern() : "";
 255         } else {
 256             return (pIndex != -1) ? qName.substring(0,pIndex) : "";
 257         }
 258     }
 259 }