1 /* 2 * Copyright (c) 2005, 2010, 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 import com.sun.xml.internal.stream.buffer.sax.Properties; 29 import com.sun.xml.internal.stream.buffer.sax.SAXBufferCreator; 30 import com.sun.xml.internal.stream.buffer.stax.StreamReaderBufferCreator; 31 import com.sun.xml.internal.stream.buffer.stax.StreamWriterBufferCreator; 32 import org.xml.sax.ContentHandler; 33 import org.xml.sax.SAXException; 34 import org.xml.sax.XMLReader; 35 36 import javax.xml.stream.XMLStreamException; 37 import javax.xml.stream.XMLStreamReader; 38 import javax.xml.stream.XMLStreamWriter; 39 import java.io.IOException; 40 import java.io.InputStream; 41 42 /** 43 * 44 * A mutable stream-based buffer of an XML infoset. 45 * 46 * <p> 47 * A MutableXMLStreamBuffer is created using specific SAX and StAX-based 48 * creators. Utility methods on MutableXMLStreamBuffer are provided for 49 * such functionality that utilize SAX and StAX-based creators. 50 * 51 * <p> 52 * Once instantiated the same instance of a MutableXMLStreamBuffer may be reused for 53 * creation to reduce the amount of Objects instantiated and garbage 54 * collected that are required for internally representing an XML infoset. 55 * 56 * <p> 57 * A MutableXMLStreamBuffer is not designed to be created and processed 58 * concurrently. If done so unspecified behaviour may occur. 59 */ 60 public class MutableXMLStreamBuffer extends XMLStreamBuffer { 61 /** 62 * The default array size for the arrays used in internal representation 63 * of the XML infoset. 64 */ 65 public static final int DEFAULT_ARRAY_SIZE = 512; 66 67 /** 68 * Create a new MutableXMLStreamBuffer using the 69 * {@link MutableXMLStreamBuffer#DEFAULT_ARRAY_SIZE}. 70 */ 71 public MutableXMLStreamBuffer() { 72 this(DEFAULT_ARRAY_SIZE); 73 } 74 75 /** 76 * Set the system identifier for this buffer. 77 * @param systemId The system identifier. 78 */ 79 public void setSystemId(String systemId) { 80 this.systemId = systemId; 81 } 82 83 /** 84 * Create a new MutableXMLStreamBuffer. 85 * 86 * @param size 87 * The size of the arrays used in the internal representation 88 * of the XML infoset. 89 * @throws NegativeArraySizeException 90 * If the <code>size</code> argument is less than <code>0</code>. 91 */ 92 public MutableXMLStreamBuffer(int size) { 93 _structure = new FragmentedArray<byte[]>(new byte[size]); 94 _structureStrings = new FragmentedArray<String[]>(new String[size]); 95 _contentCharactersBuffer = new FragmentedArray<char[]>(new char[4096]); 96 _contentObjects = new FragmentedArray<Object[]>(new Object[size]); 97 98 // Set the first element of structure array to indicate an empty buffer 99 // that has not been created 100 _structure.getArray()[0] = (byte) AbstractCreatorProcessor.T_END; 101 } 102 103 /** 104 * Create contents of a buffer from a XMLStreamReader. 105 * 106 * <p> 107 * The MutableXMLStreamBuffer is reset (see {@link #reset}) before creation. 108 * 109 * <p> 110 * The MutableXMLStreamBuffer is created by consuming the events on the XMLStreamReader using 111 * an instance of {@link StreamReaderBufferCreator}. 112 * 113 * @param reader 114 * A XMLStreamReader to read from to create. 115 */ 116 public void createFromXMLStreamReader(XMLStreamReader reader) throws XMLStreamException { 117 reset(); 118 StreamReaderBufferCreator c = new StreamReaderBufferCreator(this); 119 c.create(reader); 120 } 121 122 /** 123 * Create contents of a buffer from a XMLStreamWriter. 124 * 125 * <p> 126 * The MutableXMLStreamBuffer is reset (see {@link #reset}) before creation. 127 * 128 * <p> 129 * The MutableXMLStreamBuffer is created by consuming events on a XMLStreamWriter using 130 * an instance of {@link StreamWriterBufferCreator}. 131 */ 132 public XMLStreamWriter createFromXMLStreamWriter() { 133 reset(); 134 return new StreamWriterBufferCreator(this); 135 } 136 137 /** 138 * Create contents of a buffer from a {@link SAXBufferCreator}. 139 * 140 * <p> 141 * The MutableXMLStreamBuffer is reset (see {@link #reset}) before creation. 142 * 143 * <p> 144 * The MutableXMLStreamBuffer is created by consuming events from a {@link ContentHandler} using 145 * an instance of {@link SAXBufferCreator}. 146 * 147 * @return The {@link SAXBufferCreator} to create from. 148 */ 149 public SAXBufferCreator createFromSAXBufferCreator() { 150 reset(); 151 SAXBufferCreator c = new SAXBufferCreator(); 152 c.setBuffer(this); 153 return c; 154 } 155 156 /** 157 * Create contents of a buffer from a {@link XMLReader} and {@link InputStream}. 158 * 159 * <p> 160 * The MutableXMLStreamBuffer is reset (see {@link #reset}) before creation. 161 * 162 * <p> 163 * The MutableXMLStreamBuffer is created by using an instance of {@link SAXBufferCreator} 164 * and registering associated handlers on the {@link XMLReader}. 165 * 166 * @param reader 167 * The {@link XMLReader} to use for parsing. 168 * @param in 169 * The {@link InputStream} to be parsed. 170 */ 171 public void createFromXMLReader(XMLReader reader, InputStream in) throws SAXException, IOException { 172 createFromXMLReader(reader, in, null); 173 } 174 175 /** 176 * Create contents of a buffer from a {@link XMLReader} and {@link InputStream}. 177 * 178 * <p> 179 * The MutableXMLStreamBuffer is reset (see {@link #reset}) before creation. 180 * 181 * <p> 182 * The MutableXMLStreamBuffer is created by using an instance of {@link SAXBufferCreator} 183 * and registering associated handlers on the {@link XMLReader}. 184 * 185 * @param reader 186 * The {@link XMLReader} to use for parsing. 187 * @param in 188 * The {@link InputStream} to be parsed. 189 * @param systemId 190 * The system ID of the input stream. 191 */ 192 public void createFromXMLReader(XMLReader reader, InputStream in, String systemId) throws SAXException, IOException { 193 reset(); 194 SAXBufferCreator c = new SAXBufferCreator(this); 195 196 reader.setContentHandler(c); 197 reader.setDTDHandler(c); 198 reader.setProperty(Properties.LEXICAL_HANDLER_PROPERTY, c); 199 200 c.create(reader, in, systemId); 201 } 202 203 /** 204 * Reset the MutableXMLStreamBuffer. 205 * 206 * <p> 207 * This method will reset the MutableXMLStreamBuffer to a state of being "uncreated" 208 * similar to the state of a newly instantiated MutableXMLStreamBuffer. 209 * 210 * <p> 211 * As many Objects as possible will be retained for reuse in future creation. 212 */ 213 public void reset() { 214 // Reset the ptrs in arrays to 0 215 _structurePtr = 216 _structureStringsPtr = 217 _contentCharactersBufferPtr = 218 _contentObjectsPtr = 0; 219 220 // Set the first element of structure array to indicate an empty buffer 221 // that has not been created 222 _structure.getArray()[0] = (byte)AbstractCreatorProcessor.T_END; 223 224 // Clean up content objects 225 _contentObjects.setNext(null); 226 final Object[] o = _contentObjects.getArray(); 227 for (int i = 0; i < o.length; i++) { 228 if (o[i] != null) { 229 o[i] = null; 230 } else { 231 break; 232 } 233 } 234 235 treeCount = 0; 236 237 /* 238 * TODO consider truncating the size of _structureStrings and 239 * _contentCharactersBuffer to limit the memory used by the buffer 240 */ 241 } 242 243 244 protected void setHasInternedStrings(boolean hasInternedStrings) { 245 _hasInternedStrings = hasInternedStrings; 246 } 247 }