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 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      */
MutableXMLStreamBuffer()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      */
setSystemId(String systemId)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      */
MutableXMLStreamBuffer(int size)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      */
createFromXMLStreamReader(XMLStreamReader reader)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      */
createFromXMLStreamWriter()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      */
createFromSAXBufferCreator()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      */
createFromXMLReader(XMLReader reader, InputStream in)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      */
createFromXMLReader(XMLReader reader, InputStream in, String systemId)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      */
reset()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 
setHasInternedStrings(boolean hasInternedStrings)244     protected void setHasInternedStrings(boolean hasInternedStrings) {
245         _hasInternedStrings = hasInternedStrings;
246     }
247 }
248