1/* 2 * Copyright (c) 2005, 2013, 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 26package com.sun.xml.internal.stream.buffer.sax; 27 28import com.sun.xml.internal.stream.buffer.AbstractCreator; 29import org.xml.sax.Attributes; 30import org.xml.sax.SAXException; 31import com.sun.xml.internal.stream.buffer.MutableXMLStreamBuffer; 32import java.io.IOException; 33import java.io.InputStream; 34import org.xml.sax.ContentHandler; 35import org.xml.sax.DTDHandler; 36import org.xml.sax.EntityResolver; 37import org.xml.sax.ErrorHandler; 38import org.xml.sax.InputSource; 39import org.xml.sax.Locator; 40import org.xml.sax.SAXParseException; 41import org.xml.sax.XMLReader; 42import 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 */ 51public 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} 271