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.sax;
27  
28  import com.sun.xml.internal.stream.buffer.AbstractCreator;
29  import org.xml.sax.Attributes;
30  import org.xml.sax.SAXException;
31  import com.sun.xml.internal.stream.buffer.MutableXMLStreamBuffer;
32  import java.io.IOException;
33  import java.io.InputStream;
34  import org.xml.sax.ContentHandler;
35  import org.xml.sax.DTDHandler;
36  import org.xml.sax.EntityResolver;
37  import org.xml.sax.ErrorHandler;
38  import org.xml.sax.InputSource;
39  import org.xml.sax.Locator;
40  import org.xml.sax.SAXParseException;
41  import org.xml.sax.XMLReader;
42  import org.xml.sax.ext.LexicalHandler;
43  
44  /**
45   * Writes into {@link MutableXMLStreamBuffer} from SAX.
46   *
47   * TODO
48   * Implement the marking the stream on the element when an ID
49   * attribute on the element is defined
50   */
51  public class SAXBufferCreator extends AbstractCreator
52          implements EntityResolver, DTDHandler, ContentHandler, ErrorHandler, LexicalHandler {
53      protected String[] _namespaceAttributes;
54  
55      protected int _namespaceAttributesPtr;
56  
57      private int depth = 0;
58  
59      public SAXBufferCreator() {
60          _namespaceAttributes = new String[16 * 2];
61      }
62  
63      public SAXBufferCreator(MutableXMLStreamBuffer buffer) {
64          this();
65          setBuffer(buffer);
66      }
67  
68      public MutableXMLStreamBuffer create(XMLReader reader, InputStream in) throws IOException, SAXException {
69          return create(reader, in, null);
70      }
71  
72      public MutableXMLStreamBuffer create(XMLReader reader, InputStream in, String systemId) throws IOException, SAXException {
73          if (_buffer == null) {
74              createBuffer();
75          }
76          _buffer.setSystemId(systemId);
77          reader.setContentHandler(this);
78          reader.setProperty(Properties.LEXICAL_HANDLER_PROPERTY, this);
79  
80          try {
81              setHasInternedStrings(reader.getFeature(Features.STRING_INTERNING_FEATURE));
82          } catch (SAXException e) {
83          }
84  
85  
86          if (systemId != null) {
87              InputSource s = new InputSource(systemId);
88              s.setByteStream(in);
89              reader.parse(s);
90          } else {
91              reader.parse(new InputSource(in));
92          }
93  
94          return getXMLStreamBuffer();
95      }
96  
97      public void reset() {
98          _buffer = null;
99          _namespaceAttributesPtr = 0;
100         depth=0;
101     }
102 
103     public void startDocument() throws SAXException {
104         storeStructure(T_DOCUMENT);
105     }
106 
107     public void endDocument() throws SAXException {
108         storeStructure(T_END);
109     }
110 
111     public void startPrefixMapping(String prefix, String uri) throws SAXException {
112         cacheNamespaceAttribute(prefix, uri);
113     }
114 
115     public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
116         storeQualifiedName(T_ELEMENT_LN,
117                 uri, localName, qName);
118 
119         // Has namespaces attributes
120         if (_namespaceAttributesPtr > 0) {
121             storeNamespaceAttributes();
122         }
123 
124         // Has attributes
125         if (attributes.getLength() > 0) {
126             storeAttributes(attributes);
127         }
128         depth++;
129     }
130 
131     public void endElement(String uri, String localName, String qName) throws SAXException {
132         storeStructure(T_END);
133         if(--depth==0)
134             increaseTreeCount();    // one tree processed
135     }
136 
137     public void characters(char ch[], int start, int length) throws SAXException {
138         storeContentCharacters(T_TEXT_AS_CHAR_ARRAY, ch, start, length);
139     }
140 
141     public void ignorableWhitespace(char ch[], int start, int length) throws SAXException {
142         characters(ch, start, length);
143     }
144 
145     public void processingInstruction(String target, String data) throws SAXException {
146         storeStructure(T_PROCESSING_INSTRUCTION);
147         storeStructureString(target);
148         storeStructureString(data);
149     }
150 
151     public void comment(char[] ch, int start, int length) throws SAXException {
152         storeContentCharacters(T_COMMENT_AS_CHAR_ARRAY, ch, start, length);
153     }
154 
155     //
156 
157     private void cacheNamespaceAttribute(String prefix, String uri) {
158         _namespaceAttributes[_namespaceAttributesPtr++] = prefix;
159         _namespaceAttributes[_namespaceAttributesPtr++] = uri;
160 
161         if (_namespaceAttributesPtr == _namespaceAttributes.length) {
162             final String[] namespaceAttributes = new String[_namespaceAttributesPtr * 2];
163             System.arraycopy(_namespaceAttributes, 0, namespaceAttributes, 0, _namespaceAttributesPtr);
164             _namespaceAttributes = namespaceAttributes;
165         }
166     }
167 
168     private void storeNamespaceAttributes() {
169         for (int i = 0; i < _namespaceAttributesPtr; i += 2) {
170             int item = T_NAMESPACE_ATTRIBUTE;
171             if (_namespaceAttributes[i].length() > 0) {
172                 item |= FLAG_PREFIX;
173                 storeStructureString(_namespaceAttributes[i]);
174             }
175             if (_namespaceAttributes[i + 1].length() > 0) {
176                 item |= FLAG_URI;
177                 storeStructureString(_namespaceAttributes[i + 1]);
178             }
179             storeStructure(item);
180         }
181         _namespaceAttributesPtr = 0;
182     }
183 
184     private void storeAttributes(Attributes attributes) {
185         for (int i = 0; i < attributes.getLength(); i++) {
186             // Skip NS attributes. Some versions of JDK seem to send wrong local name
187             // Also it is not stored correctly by the following.
188             if (attributes.getQName(i).startsWith("xmlns"))
189                 continue;
190             storeQualifiedName(T_ATTRIBUTE_LN,
191                     attributes.getURI(i),
192                     attributes.getLocalName(i),
193                     attributes.getQName(i));
194 
195             storeStructureString(attributes.getType(i));
196             storeContentString(attributes.getValue(i));
197         }
198     }
199 
200     private void storeQualifiedName(int item, String uri, String localName, String qName) {
201         if (uri.length() > 0) {
202             item |= FLAG_URI;
203             storeStructureString(uri);
204         }
205 
206         storeStructureString(localName);
207 
208         if (qName.indexOf(':') >= 0) {
209             item |= FLAG_QUALIFIED_NAME;
210             storeStructureString(qName);
211         }
212 
213         storeStructure(item);
214     }
215 
216 
217     // Empty methods for SAX handlers
218 
219     // Entity resolver handler
220 
221     public InputSource resolveEntity (String publicId, String systemId)
222         throws IOException, SAXException
223     {
224         return null;
225     }
226 
227     // DTD handler
228 
229     public void notationDecl (String name, String publicId, String systemId)
230         throws SAXException
231     { }
232 
233     public void unparsedEntityDecl (String name, String publicId,
234                                     String systemId, String notationName)
235         throws SAXException
236     { }
237 
238     // Content handler
239 
240     public void setDocumentLocator (Locator locator) { }
241 
242     public void endPrefixMapping (String prefix) throws SAXException { }
243 
244     public void skippedEntity (String name) throws SAXException { }
245 
246     // Lexical handler
247 
248     public void startDTD(String name, String publicId, String systemId) throws SAXException { }
249 
250     public void endDTD() throws SAXException { }
251 
252     public void startEntity(String name) throws SAXException { }
253 
254     public void endEntity(String name) throws SAXException { }
255 
256     public void startCDATA() throws SAXException { }
257 
258     public void endCDATA() throws SAXException { }
259 
260     // Error handler
261 
262     public void warning(SAXParseException e) throws SAXException { }
263 
264     public void error(SAXParseException e) throws SAXException { }
265 
266     public void fatalError(SAXParseException e) throws SAXException
267     {
268         throw e;
269     }
270 }