View Javadoc
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       */
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 }