Tue, 09 Apr 2013 14:51:13 +0100
8010393: Update JAX-WS RI to 2.2.9-b12941
Reviewed-by: alanb, erikj
Contributed-by: miroslav.kos@oracle.com, martin.grebac@oracle.com
ohair@286 | 1 | /* |
alanb@368 | 2 | * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. |
ohair@286 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
ohair@286 | 4 | * |
ohair@286 | 5 | * This code is free software; you can redistribute it and/or modify it |
ohair@286 | 6 | * under the terms of the GNU General Public License version 2 only, as |
ohair@286 | 7 | * published by the Free Software Foundation. Oracle designates this |
ohair@286 | 8 | * particular file as subject to the "Classpath" exception as provided |
ohair@286 | 9 | * by Oracle in the LICENSE file that accompanied this code. |
ohair@286 | 10 | * |
ohair@286 | 11 | * This code is distributed in the hope that it will be useful, but WITHOUT |
ohair@286 | 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
ohair@286 | 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
ohair@286 | 14 | * version 2 for more details (a copy is included in the LICENSE file that |
ohair@286 | 15 | * accompanied this code). |
ohair@286 | 16 | * |
ohair@286 | 17 | * You should have received a copy of the GNU General Public License version |
ohair@286 | 18 | * 2 along with this work; if not, write to the Free Software Foundation, |
ohair@286 | 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
ohair@286 | 20 | * |
ohair@286 | 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
ohair@286 | 22 | * or visit www.oracle.com if you need additional information or have any |
ohair@286 | 23 | * questions. |
ohair@286 | 24 | */ |
ohair@286 | 25 | |
ohair@286 | 26 | package com.sun.xml.internal.stream.buffer.sax; |
ohair@286 | 27 | |
ohair@286 | 28 | import com.sun.xml.internal.stream.buffer.AbstractProcessor; |
ohair@286 | 29 | import com.sun.xml.internal.stream.buffer.AttributesHolder; |
ohair@286 | 30 | import com.sun.xml.internal.stream.buffer.XMLStreamBuffer; |
ohair@286 | 31 | import org.xml.sax.ContentHandler; |
ohair@286 | 32 | import org.xml.sax.DTDHandler; |
ohair@286 | 33 | import org.xml.sax.EntityResolver; |
ohair@286 | 34 | import org.xml.sax.ErrorHandler; |
ohair@286 | 35 | import org.xml.sax.InputSource; |
ohair@286 | 36 | import org.xml.sax.SAXException; |
ohair@286 | 37 | import org.xml.sax.SAXNotRecognizedException; |
ohair@286 | 38 | import org.xml.sax.SAXNotSupportedException; |
ohair@286 | 39 | import org.xml.sax.SAXParseException; |
ohair@286 | 40 | import org.xml.sax.XMLReader; |
ohair@286 | 41 | import org.xml.sax.ext.LexicalHandler; |
ohair@286 | 42 | import org.xml.sax.helpers.LocatorImpl; |
ohair@286 | 43 | |
ohair@286 | 44 | import javax.xml.XMLConstants; |
ohair@286 | 45 | import java.io.IOException; |
ohair@286 | 46 | import java.util.Collections; |
ohair@286 | 47 | import java.util.HashSet; |
ohair@286 | 48 | import java.util.Map; |
ohair@286 | 49 | import java.util.Set; |
ohair@286 | 50 | |
ohair@286 | 51 | /** |
ohair@286 | 52 | * A processor of a {@link XMLStreamBuffer} that that reads the XML infoset as |
ohair@286 | 53 | * {@link XMLReader}. |
ohair@286 | 54 | */ |
ohair@286 | 55 | public class SAXBufferProcessor extends AbstractProcessor implements XMLReader { |
ohair@286 | 56 | /** |
ohair@286 | 57 | * Reference to entity resolver. |
ohair@286 | 58 | */ |
ohair@286 | 59 | protected EntityResolver _entityResolver = DEFAULT_LEXICAL_HANDLER; |
ohair@286 | 60 | |
ohair@286 | 61 | /** |
ohair@286 | 62 | * Reference to dtd handler. |
ohair@286 | 63 | */ |
ohair@286 | 64 | protected DTDHandler _dtdHandler = DEFAULT_LEXICAL_HANDLER; |
ohair@286 | 65 | |
ohair@286 | 66 | /** |
ohair@286 | 67 | * Reference to content handler. |
ohair@286 | 68 | */ |
ohair@286 | 69 | protected ContentHandler _contentHandler = DEFAULT_LEXICAL_HANDLER; |
ohair@286 | 70 | |
ohair@286 | 71 | /** |
ohair@286 | 72 | * Reference to error handler. |
ohair@286 | 73 | */ |
ohair@286 | 74 | protected ErrorHandler _errorHandler = DEFAULT_LEXICAL_HANDLER; |
ohair@286 | 75 | |
ohair@286 | 76 | /** |
ohair@286 | 77 | * Reference to lexical handler. |
ohair@286 | 78 | */ |
ohair@286 | 79 | protected LexicalHandler _lexicalHandler = DEFAULT_LEXICAL_HANDLER; |
ohair@286 | 80 | |
ohair@286 | 81 | /** |
ohair@286 | 82 | * SAX Namespace attributes features |
ohair@286 | 83 | */ |
ohair@286 | 84 | protected boolean _namespacePrefixesFeature = false; |
ohair@286 | 85 | |
ohair@286 | 86 | protected AttributesHolder _attributes = new AttributesHolder(); |
ohair@286 | 87 | |
ohair@286 | 88 | protected String[] _namespacePrefixes = new String[16]; |
ohair@286 | 89 | protected int _namespacePrefixesIndex; |
ohair@286 | 90 | |
alanb@368 | 91 | protected int[] _namespaceAttributesStartingStack = new int[16]; |
ohair@286 | 92 | protected int[] _namespaceAttributesStack = new int[16]; |
ohair@286 | 93 | protected int _namespaceAttributesStackIndex; |
ohair@286 | 94 | |
ohair@286 | 95 | public SAXBufferProcessor() { |
ohair@286 | 96 | } |
ohair@286 | 97 | |
ohair@286 | 98 | /** |
ohair@286 | 99 | * @deprecated |
ohair@286 | 100 | * Use {@link #SAXBufferProcessor(XMLStreamBuffer, boolean)} |
ohair@286 | 101 | */ |
ohair@286 | 102 | public SAXBufferProcessor(XMLStreamBuffer buffer) { |
ohair@286 | 103 | setXMLStreamBuffer(buffer); |
ohair@286 | 104 | } |
ohair@286 | 105 | |
ohair@286 | 106 | /** |
ohair@286 | 107 | * @param produceFragmentEvent |
ohair@286 | 108 | * True to generate fragment SAX events without start/endDocument. |
ohair@286 | 109 | * False to generate a full document SAX events. |
ohair@286 | 110 | */ |
ohair@286 | 111 | public SAXBufferProcessor(XMLStreamBuffer buffer, boolean produceFragmentEvent) { |
ohair@286 | 112 | setXMLStreamBuffer(buffer,produceFragmentEvent); |
ohair@286 | 113 | } |
ohair@286 | 114 | |
ohair@286 | 115 | public boolean getFeature(String name) |
ohair@286 | 116 | throws SAXNotRecognizedException, SAXNotSupportedException { |
ohair@286 | 117 | if (name.equals(Features.NAMESPACES_FEATURE)) { |
ohair@286 | 118 | return true; |
ohair@286 | 119 | } else if (name.equals(Features.NAMESPACE_PREFIXES_FEATURE)) { |
ohair@286 | 120 | return _namespacePrefixesFeature; |
ohair@286 | 121 | } else if (name.equals(Features.EXTERNAL_GENERAL_ENTITIES)) { |
ohair@286 | 122 | return true; |
ohair@286 | 123 | } else if (name.equals(Features.EXTERNAL_PARAMETER_ENTITIES)) { |
ohair@286 | 124 | return true; |
ohair@286 | 125 | } else if (name.equals(Features.STRING_INTERNING_FEATURE)) { |
ohair@286 | 126 | return _stringInterningFeature; |
ohair@286 | 127 | } else { |
ohair@286 | 128 | throw new SAXNotRecognizedException( |
ohair@286 | 129 | "Feature not supported: " + name); |
ohair@286 | 130 | } |
ohair@286 | 131 | } |
ohair@286 | 132 | |
ohair@286 | 133 | public void setFeature(String name, boolean value) |
ohair@286 | 134 | throws SAXNotRecognizedException, SAXNotSupportedException { |
ohair@286 | 135 | if (name.equals(Features.NAMESPACES_FEATURE)) { |
ohair@286 | 136 | if (!value) { |
ohair@286 | 137 | throw new SAXNotSupportedException(name + ":" + value); |
ohair@286 | 138 | } |
ohair@286 | 139 | } else if (name.equals(Features.NAMESPACE_PREFIXES_FEATURE)) { |
ohair@286 | 140 | _namespacePrefixesFeature = value; |
ohair@286 | 141 | } else if (name.equals(Features.EXTERNAL_GENERAL_ENTITIES)) { |
ohair@286 | 142 | // ignore |
ohair@286 | 143 | } else if (name.equals(Features.EXTERNAL_PARAMETER_ENTITIES)) { |
ohair@286 | 144 | // ignore |
ohair@286 | 145 | } else if (name.equals(Features.STRING_INTERNING_FEATURE)) { |
ohair@286 | 146 | if (value != _stringInterningFeature) { |
ohair@286 | 147 | throw new SAXNotSupportedException(name + ":" + value); |
ohair@286 | 148 | } |
ohair@286 | 149 | } else { |
ohair@286 | 150 | throw new SAXNotRecognizedException( |
ohair@286 | 151 | "Feature not supported: " + name); |
ohair@286 | 152 | } |
ohair@286 | 153 | } |
ohair@286 | 154 | |
ohair@286 | 155 | public Object getProperty(String name) |
ohair@286 | 156 | throws SAXNotRecognizedException, SAXNotSupportedException { |
ohair@286 | 157 | if (name.equals(Properties.LEXICAL_HANDLER_PROPERTY)) { |
ohair@286 | 158 | return getLexicalHandler(); |
ohair@286 | 159 | } else { |
ohair@286 | 160 | throw new SAXNotRecognizedException("Property not recognized: " + name); |
ohair@286 | 161 | } |
ohair@286 | 162 | } |
ohair@286 | 163 | |
ohair@286 | 164 | public void setProperty(String name, Object value) |
ohair@286 | 165 | throws SAXNotRecognizedException, SAXNotSupportedException { |
ohair@286 | 166 | if (name.equals(Properties.LEXICAL_HANDLER_PROPERTY)) { |
ohair@286 | 167 | if (value instanceof LexicalHandler) { |
ohair@286 | 168 | setLexicalHandler((LexicalHandler)value); |
ohair@286 | 169 | } else { |
ohair@286 | 170 | throw new SAXNotSupportedException(Properties.LEXICAL_HANDLER_PROPERTY); |
ohair@286 | 171 | } |
ohair@286 | 172 | } else { |
ohair@286 | 173 | throw new SAXNotRecognizedException("Property not recognized: " + name); |
ohair@286 | 174 | } |
ohair@286 | 175 | } |
ohair@286 | 176 | |
ohair@286 | 177 | public void setEntityResolver(EntityResolver resolver) { |
ohair@286 | 178 | _entityResolver = resolver; |
ohair@286 | 179 | } |
ohair@286 | 180 | |
ohair@286 | 181 | public EntityResolver getEntityResolver() { |
ohair@286 | 182 | return _entityResolver; |
ohair@286 | 183 | } |
ohair@286 | 184 | |
ohair@286 | 185 | public void setDTDHandler(DTDHandler handler) { |
ohair@286 | 186 | _dtdHandler = handler; |
ohair@286 | 187 | } |
ohair@286 | 188 | |
ohair@286 | 189 | public DTDHandler getDTDHandler() { |
ohair@286 | 190 | return _dtdHandler; |
ohair@286 | 191 | } |
ohair@286 | 192 | |
ohair@286 | 193 | public void setContentHandler(ContentHandler handler) { |
ohair@286 | 194 | _contentHandler = handler; |
ohair@286 | 195 | } |
ohair@286 | 196 | |
ohair@286 | 197 | public ContentHandler getContentHandler() { |
ohair@286 | 198 | return _contentHandler; |
ohair@286 | 199 | } |
ohair@286 | 200 | |
ohair@286 | 201 | public void setErrorHandler(ErrorHandler handler) { |
ohair@286 | 202 | _errorHandler = handler; |
ohair@286 | 203 | } |
ohair@286 | 204 | |
ohair@286 | 205 | public ErrorHandler getErrorHandler() { |
ohair@286 | 206 | return _errorHandler; |
ohair@286 | 207 | } |
ohair@286 | 208 | |
ohair@286 | 209 | public void setLexicalHandler(LexicalHandler handler) { |
ohair@286 | 210 | _lexicalHandler = handler; |
ohair@286 | 211 | } |
ohair@286 | 212 | |
ohair@286 | 213 | public LexicalHandler getLexicalHandler() { |
ohair@286 | 214 | return _lexicalHandler; |
ohair@286 | 215 | } |
ohair@286 | 216 | |
ohair@286 | 217 | public void parse(InputSource input) throws IOException, SAXException { |
ohair@286 | 218 | // InputSource is ignored |
ohair@286 | 219 | process(); |
ohair@286 | 220 | } |
ohair@286 | 221 | |
ohair@286 | 222 | public void parse(String systemId) throws IOException, SAXException { |
ohair@286 | 223 | // systemId is ignored |
ohair@286 | 224 | process(); |
ohair@286 | 225 | } |
ohair@286 | 226 | |
ohair@286 | 227 | /** |
ohair@286 | 228 | * Short-hand for {@link #setXMLStreamBuffer(XMLStreamBuffer)} then {@link #process()}. |
ohair@286 | 229 | * |
ohair@286 | 230 | * @deprecated |
ohair@286 | 231 | * Use {@link #process(XMLStreamBuffer, boolean)} |
ohair@286 | 232 | */ |
ohair@286 | 233 | public final void process(XMLStreamBuffer buffer) throws SAXException { |
ohair@286 | 234 | setXMLStreamBuffer(buffer); |
ohair@286 | 235 | process(); |
ohair@286 | 236 | } |
ohair@286 | 237 | |
ohair@286 | 238 | /** |
ohair@286 | 239 | * Short-hand for {@link #setXMLStreamBuffer(XMLStreamBuffer,boolean)} then {@link #process()}. |
ohair@286 | 240 | * |
ohair@286 | 241 | * @param produceFragmentEvent |
ohair@286 | 242 | * True to generate fragment SAX events without start/endDocument. |
ohair@286 | 243 | * False to generate a full document SAX events. |
ohair@286 | 244 | */ |
ohair@286 | 245 | public final void process(XMLStreamBuffer buffer, boolean produceFragmentEvent) throws SAXException { |
ohair@286 | 246 | setXMLStreamBuffer(buffer); |
ohair@286 | 247 | process(); |
ohair@286 | 248 | } |
ohair@286 | 249 | |
ohair@286 | 250 | /** |
ohair@286 | 251 | * Resets the parser to read from the beginning of the given {@link XMLStreamBuffer}. |
ohair@286 | 252 | * |
ohair@286 | 253 | * @deprecated |
ohair@286 | 254 | * Use {@link #setXMLStreamBuffer(XMLStreamBuffer, boolean)}. |
ohair@286 | 255 | */ |
ohair@286 | 256 | public void setXMLStreamBuffer(XMLStreamBuffer buffer) { |
ohair@286 | 257 | setBuffer(buffer); |
ohair@286 | 258 | } |
ohair@286 | 259 | |
ohair@286 | 260 | /** |
ohair@286 | 261 | * Resets the parser to read from the beginning of the given {@link XMLStreamBuffer}. |
ohair@286 | 262 | * |
ohair@286 | 263 | * @param produceFragmentEvent |
ohair@286 | 264 | * True to generate fragment SAX events without start/endDocument. |
ohair@286 | 265 | * False to generate a full document SAX events. |
ohair@286 | 266 | */ |
ohair@286 | 267 | public void setXMLStreamBuffer(XMLStreamBuffer buffer, boolean produceFragmentEvent) { |
ohair@286 | 268 | if(!produceFragmentEvent && _treeCount>1) |
ohair@286 | 269 | throw new IllegalStateException("Can't write a forest to a full XML infoset"); |
ohair@286 | 270 | setBuffer(buffer,produceFragmentEvent); |
ohair@286 | 271 | } |
ohair@286 | 272 | |
ohair@286 | 273 | /** |
ohair@286 | 274 | * Parse the sub-tree (or a whole document) that {@link XMLStreamBuffer} |
ohair@286 | 275 | * points to, and sends events to handlers. |
ohair@286 | 276 | * |
ohair@286 | 277 | * <p> |
ohair@286 | 278 | * TODO: |
ohair@286 | 279 | * We probably need two modes for a sub-tree event generation. One for |
ohair@286 | 280 | * firing a sub-tree as if it's a whole document (in which case start/endDocument |
ohair@286 | 281 | * and appropriate additional namespace bindings are necessary), and the other |
ohair@286 | 282 | * mode for firing a subtree as a subtree, like it does today. |
ohair@286 | 283 | * A stream buffer SAX feature could be used to specify this. |
ohair@286 | 284 | * |
ohair@286 | 285 | * @throws SAXException |
ohair@286 | 286 | * Follow the same semantics as {@link XMLReader#parse(InputSource)}. |
ohair@286 | 287 | */ |
ohair@286 | 288 | public final void process() throws SAXException { |
ohair@286 | 289 | if(!_fragmentMode) { |
ohair@286 | 290 | LocatorImpl nullLocator = new LocatorImpl(); |
ohair@286 | 291 | nullLocator.setSystemId(_buffer.getSystemId()); |
ohair@286 | 292 | nullLocator.setLineNumber(-1); |
ohair@286 | 293 | nullLocator.setColumnNumber(-1); |
ohair@286 | 294 | _contentHandler.setDocumentLocator(nullLocator); |
ohair@286 | 295 | |
ohair@286 | 296 | _contentHandler.startDocument(); |
ohair@286 | 297 | // TODO: if we are writing a fragment stream buffer as a full XML document, |
ohair@286 | 298 | // we need to declare in-scope namespaces as if they are on the root element. |
ohair@286 | 299 | } |
ohair@286 | 300 | |
ohair@286 | 301 | while (_treeCount>0) { |
ohair@286 | 302 | final int item = readEiiState(); |
ohair@286 | 303 | switch(item) { |
ohair@286 | 304 | case STATE_DOCUMENT: |
ohair@286 | 305 | processDocument(); |
ohair@286 | 306 | _treeCount--; |
ohair@286 | 307 | break; |
ohair@286 | 308 | case STATE_END: |
ohair@286 | 309 | // Empty buffer |
ohair@286 | 310 | return; |
ohair@286 | 311 | case STATE_ELEMENT_U_LN_QN: |
ohair@286 | 312 | processElement(readStructureString(), readStructureString(), readStructureString(), isInscope()); |
ohair@286 | 313 | _treeCount--; |
ohair@286 | 314 | break; |
ohair@286 | 315 | case STATE_ELEMENT_P_U_LN: |
ohair@286 | 316 | { |
ohair@286 | 317 | final String prefix = readStructureString(); |
ohair@286 | 318 | final String uri = readStructureString(); |
ohair@286 | 319 | final String localName = readStructureString(); |
ohair@286 | 320 | processElement(uri, localName, getQName(prefix, localName),isInscope()); |
ohair@286 | 321 | _treeCount--; |
ohair@286 | 322 | break; |
ohair@286 | 323 | } |
ohair@286 | 324 | case STATE_ELEMENT_U_LN: { |
ohair@286 | 325 | final String uri = readStructureString(); |
ohair@286 | 326 | final String localName = readStructureString(); |
ohair@286 | 327 | processElement(uri, localName, localName,isInscope()); |
ohair@286 | 328 | _treeCount--; |
ohair@286 | 329 | break; |
ohair@286 | 330 | } |
ohair@286 | 331 | case STATE_ELEMENT_LN: |
ohair@286 | 332 | { |
ohair@286 | 333 | final String localName = readStructureString(); |
ohair@286 | 334 | processElement("", localName, localName,isInscope()); |
ohair@286 | 335 | _treeCount--; |
ohair@286 | 336 | break; |
ohair@286 | 337 | } |
ohair@286 | 338 | case STATE_COMMENT_AS_CHAR_ARRAY_SMALL: |
ohair@286 | 339 | processCommentAsCharArraySmall(); |
ohair@286 | 340 | break; |
ohair@286 | 341 | case STATE_COMMENT_AS_CHAR_ARRAY_MEDIUM: |
ohair@286 | 342 | processCommentAsCharArrayMedium(); |
ohair@286 | 343 | break; |
ohair@286 | 344 | case STATE_COMMENT_AS_CHAR_ARRAY_COPY: |
ohair@286 | 345 | processCommentAsCharArrayCopy(); |
ohair@286 | 346 | break; |
ohair@286 | 347 | case STATE_COMMENT_AS_STRING: |
ohair@286 | 348 | processComment(readContentString()); |
ohair@286 | 349 | break; |
ohair@286 | 350 | case STATE_PROCESSING_INSTRUCTION: |
ohair@286 | 351 | processProcessingInstruction(readStructureString(), readStructureString()); |
ohair@286 | 352 | break; |
ohair@286 | 353 | default: |
ohair@286 | 354 | throw reportFatalError("Illegal state for DIIs: "+item); |
ohair@286 | 355 | } |
ohair@286 | 356 | } |
ohair@286 | 357 | |
ohair@286 | 358 | if(!_fragmentMode) |
ohair@286 | 359 | _contentHandler.endDocument(); |
ohair@286 | 360 | } |
ohair@286 | 361 | |
ohair@286 | 362 | private void processCommentAsCharArraySmall() throws SAXException { |
ohair@286 | 363 | final int length = readStructure(); |
ohair@286 | 364 | final int start = readContentCharactersBuffer(length); |
ohair@286 | 365 | processComment(_contentCharactersBuffer, start, length); |
ohair@286 | 366 | } |
ohair@286 | 367 | |
ohair@286 | 368 | /** |
ohair@286 | 369 | * Report a fatal error and abort. |
ohair@286 | 370 | * |
ohair@286 | 371 | * This is necessary to follow the SAX semantics of error handling. |
ohair@286 | 372 | */ |
ohair@286 | 373 | private SAXParseException reportFatalError(String msg) throws SAXException { |
ohair@286 | 374 | SAXParseException spe = new SAXParseException(msg, null); |
ohair@286 | 375 | if(_errorHandler!=null) |
ohair@286 | 376 | _errorHandler.fatalError(spe); |
ohair@286 | 377 | return spe; |
ohair@286 | 378 | } |
ohair@286 | 379 | |
ohair@286 | 380 | private boolean isInscope() { |
ohair@286 | 381 | return _buffer.getInscopeNamespaces().size() > 0; |
ohair@286 | 382 | } |
ohair@286 | 383 | |
ohair@286 | 384 | private void processDocument() throws SAXException { |
ohair@286 | 385 | while(true) { |
ohair@286 | 386 | int item = readEiiState(); |
ohair@286 | 387 | switch(item) { |
ohair@286 | 388 | case STATE_ELEMENT_U_LN_QN: |
ohair@286 | 389 | processElement(readStructureString(), readStructureString(), readStructureString(),isInscope()); |
ohair@286 | 390 | break; |
ohair@286 | 391 | case STATE_ELEMENT_P_U_LN: |
ohair@286 | 392 | { |
ohair@286 | 393 | final String prefix = readStructureString(); |
ohair@286 | 394 | final String uri = readStructureString(); |
ohair@286 | 395 | final String localName = readStructureString(); |
ohair@286 | 396 | processElement(uri, localName, getQName(prefix, localName),isInscope()); |
ohair@286 | 397 | break; |
ohair@286 | 398 | } |
ohair@286 | 399 | case STATE_ELEMENT_U_LN: { |
ohair@286 | 400 | final String uri = readStructureString(); |
ohair@286 | 401 | final String localName = readStructureString(); |
ohair@286 | 402 | processElement(uri, localName, localName,isInscope()); |
ohair@286 | 403 | break; |
ohair@286 | 404 | } |
ohair@286 | 405 | case STATE_ELEMENT_LN: |
ohair@286 | 406 | { |
ohair@286 | 407 | final String localName = readStructureString(); |
ohair@286 | 408 | processElement("", localName, localName,isInscope()); |
ohair@286 | 409 | break; |
ohair@286 | 410 | } |
ohair@286 | 411 | case STATE_COMMENT_AS_CHAR_ARRAY_SMALL: |
ohair@286 | 412 | processCommentAsCharArraySmall(); |
ohair@286 | 413 | break; |
ohair@286 | 414 | case STATE_COMMENT_AS_CHAR_ARRAY_MEDIUM: |
ohair@286 | 415 | processCommentAsCharArrayMedium(); |
ohair@286 | 416 | break; |
ohair@286 | 417 | case STATE_COMMENT_AS_CHAR_ARRAY_COPY: |
ohair@286 | 418 | processCommentAsCharArrayCopy(); |
ohair@286 | 419 | break; |
ohair@286 | 420 | case STATE_COMMENT_AS_STRING: |
ohair@286 | 421 | processComment(readContentString()); |
ohair@286 | 422 | break; |
ohair@286 | 423 | case STATE_PROCESSING_INSTRUCTION: |
ohair@286 | 424 | processProcessingInstruction(readStructureString(), readStructureString()); |
ohair@286 | 425 | break; |
ohair@286 | 426 | case STATE_END: |
ohair@286 | 427 | return; |
ohair@286 | 428 | default: |
ohair@286 | 429 | throw reportFatalError("Illegal state for child of DII: "+item); |
ohair@286 | 430 | } |
ohair@286 | 431 | } |
ohair@286 | 432 | } |
ohair@286 | 433 | |
ohair@286 | 434 | protected void processElement(String uri, String localName, String qName, boolean inscope) throws SAXException { |
ohair@286 | 435 | boolean hasAttributes = false; |
ohair@286 | 436 | boolean hasNamespaceAttributes = false; |
ohair@286 | 437 | int item = peekStructure(); |
ohair@286 | 438 | Set<String> prefixSet = inscope ? new HashSet<String>() : Collections.<String>emptySet(); |
ohair@286 | 439 | if ((item & TYPE_MASK) == T_NAMESPACE_ATTRIBUTE) { |
alanb@368 | 440 | cacheNamespacePrefixStartingIndex(); |
ohair@286 | 441 | hasNamespaceAttributes = true; |
ohair@286 | 442 | item = processNamespaceAttributes(item, inscope, prefixSet); |
ohair@286 | 443 | } |
ohair@286 | 444 | if (inscope) { |
ohair@286 | 445 | readInscopeNamespaces(prefixSet); |
ohair@286 | 446 | } |
ohair@286 | 447 | |
ohair@286 | 448 | if ((item & TYPE_MASK) == T_ATTRIBUTE) { |
ohair@286 | 449 | hasAttributes = true; |
ohair@286 | 450 | processAttributes(item); |
ohair@286 | 451 | } |
ohair@286 | 452 | |
ohair@286 | 453 | _contentHandler.startElement(uri, localName, qName, _attributes); |
ohair@286 | 454 | |
ohair@286 | 455 | if (hasAttributes) { |
ohair@286 | 456 | _attributes.clear(); |
ohair@286 | 457 | } |
ohair@286 | 458 | |
ohair@286 | 459 | do { |
ohair@286 | 460 | item = readEiiState(); |
ohair@286 | 461 | switch(item) { |
ohair@286 | 462 | case STATE_ELEMENT_U_LN_QN: |
ohair@286 | 463 | processElement(readStructureString(), readStructureString(), readStructureString(), false); |
ohair@286 | 464 | break; |
ohair@286 | 465 | case STATE_ELEMENT_P_U_LN: |
ohair@286 | 466 | { |
ohair@286 | 467 | final String p = readStructureString(); |
ohair@286 | 468 | final String u = readStructureString(); |
ohair@286 | 469 | final String ln = readStructureString(); |
ohair@286 | 470 | processElement(u, ln, getQName(p, ln),false); |
ohair@286 | 471 | break; |
ohair@286 | 472 | } |
ohair@286 | 473 | case STATE_ELEMENT_U_LN: { |
ohair@286 | 474 | final String u = readStructureString(); |
ohair@286 | 475 | final String ln = readStructureString(); |
ohair@286 | 476 | processElement(u, ln, ln,false); |
ohair@286 | 477 | break; |
ohair@286 | 478 | } |
ohair@286 | 479 | case STATE_ELEMENT_LN: { |
ohair@286 | 480 | final String ln = readStructureString(); |
ohair@286 | 481 | processElement("", ln, ln,false); |
ohair@286 | 482 | break; |
ohair@286 | 483 | } |
ohair@286 | 484 | case STATE_TEXT_AS_CHAR_ARRAY_SMALL: |
ohair@286 | 485 | { |
ohair@286 | 486 | final int length = readStructure(); |
ohair@286 | 487 | int start = readContentCharactersBuffer(length); |
ohair@286 | 488 | _contentHandler.characters(_contentCharactersBuffer, start, length); |
ohair@286 | 489 | break; |
ohair@286 | 490 | } |
ohair@286 | 491 | case STATE_TEXT_AS_CHAR_ARRAY_MEDIUM: |
ohair@286 | 492 | { |
ohair@286 | 493 | final int length = readStructure16(); |
ohair@286 | 494 | int start = readContentCharactersBuffer(length); |
ohair@286 | 495 | _contentHandler.characters(_contentCharactersBuffer, start, length); |
ohair@286 | 496 | break; |
ohair@286 | 497 | } |
ohair@286 | 498 | case STATE_TEXT_AS_CHAR_ARRAY_COPY: |
ohair@286 | 499 | { |
ohair@286 | 500 | final char[] ch = readContentCharactersCopy(); |
ohair@286 | 501 | |
ohair@286 | 502 | _contentHandler.characters(ch, 0, ch.length); |
ohair@286 | 503 | break; |
ohair@286 | 504 | } |
ohair@286 | 505 | case STATE_TEXT_AS_STRING: |
ohair@286 | 506 | { |
ohair@286 | 507 | final String s = readContentString(); |
ohair@286 | 508 | _contentHandler.characters(s.toCharArray(), 0, s.length()); |
ohair@286 | 509 | break; |
ohair@286 | 510 | } |
ohair@286 | 511 | case STATE_TEXT_AS_OBJECT: |
ohair@286 | 512 | { |
ohair@286 | 513 | final CharSequence c = (CharSequence)readContentObject(); |
ohair@286 | 514 | final String s = c.toString(); |
ohair@286 | 515 | _contentHandler.characters(s.toCharArray(), 0, s.length()); |
ohair@286 | 516 | break; |
ohair@286 | 517 | } |
ohair@286 | 518 | case STATE_COMMENT_AS_CHAR_ARRAY_SMALL: |
ohair@286 | 519 | processCommentAsCharArraySmall(); |
ohair@286 | 520 | break; |
ohair@286 | 521 | case STATE_COMMENT_AS_CHAR_ARRAY_MEDIUM: |
ohair@286 | 522 | processCommentAsCharArrayMedium(); |
ohair@286 | 523 | break; |
ohair@286 | 524 | case STATE_COMMENT_AS_CHAR_ARRAY_COPY: |
ohair@286 | 525 | processCommentAsCharArrayCopy(); |
ohair@286 | 526 | break; |
ohair@286 | 527 | case T_COMMENT_AS_STRING: |
ohair@286 | 528 | processComment(readContentString()); |
ohair@286 | 529 | break; |
ohair@286 | 530 | case STATE_PROCESSING_INSTRUCTION: |
ohair@286 | 531 | processProcessingInstruction(readStructureString(), readStructureString()); |
ohair@286 | 532 | break; |
ohair@286 | 533 | case STATE_END: |
ohair@286 | 534 | break; |
ohair@286 | 535 | default: |
ohair@286 | 536 | throw reportFatalError("Illegal state for child of EII: "+item); |
ohair@286 | 537 | } |
ohair@286 | 538 | } while(item != STATE_END); |
ohair@286 | 539 | |
ohair@286 | 540 | _contentHandler.endElement(uri, localName, qName); |
ohair@286 | 541 | |
ohair@286 | 542 | if (hasNamespaceAttributes) { |
ohair@286 | 543 | processEndPrefixMapping(); |
ohair@286 | 544 | } |
ohair@286 | 545 | } |
ohair@286 | 546 | |
ohair@286 | 547 | private void readInscopeNamespaces(Set<String> prefixSet) throws SAXException { |
ohair@286 | 548 | for (Map.Entry<String, String> e : _buffer.getInscopeNamespaces().entrySet()) { |
ohair@286 | 549 | String key = fixNull(e.getKey()); |
ohair@286 | 550 | // If the prefix is already written, do not write the prefix |
ohair@286 | 551 | if (!prefixSet.contains(key)) { |
ohair@286 | 552 | processNamespaceAttribute(key,e.getValue()); |
ohair@286 | 553 | } |
ohair@286 | 554 | } |
ohair@286 | 555 | |
ohair@286 | 556 | } |
ohair@286 | 557 | |
ohair@286 | 558 | private static String fixNull(String s) { |
ohair@286 | 559 | if (s == null) return ""; |
ohair@286 | 560 | else return s; |
ohair@286 | 561 | } |
ohair@286 | 562 | private void processCommentAsCharArrayCopy() throws SAXException { |
ohair@286 | 563 | final char[] ch = readContentCharactersCopy(); |
ohair@286 | 564 | processComment(ch, 0, ch.length); |
ohair@286 | 565 | } |
ohair@286 | 566 | |
ohair@286 | 567 | private void processCommentAsCharArrayMedium() throws SAXException { |
ohair@286 | 568 | final int length = readStructure16(); |
ohair@286 | 569 | final int start = readContentCharactersBuffer(length); |
ohair@286 | 570 | processComment(_contentCharactersBuffer, start, length); |
ohair@286 | 571 | } |
ohair@286 | 572 | |
ohair@286 | 573 | private void processEndPrefixMapping() throws SAXException { |
ohair@286 | 574 | final int end = _namespaceAttributesStack[--_namespaceAttributesStackIndex]; |
alanb@368 | 575 | // final int start = (_namespaceAttributesStackIndex > 0) ? _namespaceAttributesStack[_namespaceAttributesStackIndex] : 0; |
alanb@368 | 576 | final int start = (_namespaceAttributesStackIndex >= 0) ? _namespaceAttributesStartingStack[_namespaceAttributesStackIndex] : 0; |
ohair@286 | 577 | |
ohair@286 | 578 | for (int i = end - 1; i >= start; i--) { |
ohair@286 | 579 | _contentHandler.endPrefixMapping(_namespacePrefixes[i]); |
ohair@286 | 580 | } |
ohair@286 | 581 | _namespacePrefixesIndex = start; |
ohair@286 | 582 | } |
ohair@286 | 583 | |
ohair@286 | 584 | private int processNamespaceAttributes(int item,boolean collectPrefixes, Set<String> prefixSet) throws SAXException { |
ohair@286 | 585 | do { |
ohair@286 | 586 | String prefix; |
ohair@286 | 587 | switch(getNIIState(item)) { |
ohair@286 | 588 | case STATE_NAMESPACE_ATTRIBUTE: |
ohair@286 | 589 | // Undeclaration of default namespace |
ohair@286 | 590 | processNamespaceAttribute("", ""); |
ohair@286 | 591 | if(collectPrefixes) { |
ohair@286 | 592 | prefixSet.add(""); |
ohair@286 | 593 | } |
ohair@286 | 594 | break; |
ohair@286 | 595 | case STATE_NAMESPACE_ATTRIBUTE_P: |
ohair@286 | 596 | // Undeclaration of namespace |
ohair@286 | 597 | prefix = readStructureString(); |
ohair@286 | 598 | processNamespaceAttribute(prefix, ""); |
ohair@286 | 599 | if(collectPrefixes) { |
ohair@286 | 600 | prefixSet.add(prefix); |
ohair@286 | 601 | } |
ohair@286 | 602 | break; |
ohair@286 | 603 | case STATE_NAMESPACE_ATTRIBUTE_P_U: |
ohair@286 | 604 | // Declaration with prefix |
ohair@286 | 605 | prefix = readStructureString(); |
ohair@286 | 606 | processNamespaceAttribute(prefix, readStructureString()); |
ohair@286 | 607 | if(collectPrefixes) { |
ohair@286 | 608 | prefixSet.add(prefix); |
ohair@286 | 609 | } |
ohair@286 | 610 | break; |
ohair@286 | 611 | case STATE_NAMESPACE_ATTRIBUTE_U: |
ohair@286 | 612 | // Default declaration |
ohair@286 | 613 | processNamespaceAttribute("", readStructureString()); |
ohair@286 | 614 | if(collectPrefixes) { |
ohair@286 | 615 | prefixSet.add(""); |
ohair@286 | 616 | } |
ohair@286 | 617 | break; |
ohair@286 | 618 | default: |
ohair@286 | 619 | throw reportFatalError("Illegal state: "+item); |
ohair@286 | 620 | } |
ohair@286 | 621 | readStructure(); |
ohair@286 | 622 | |
ohair@286 | 623 | item = peekStructure(); |
ohair@286 | 624 | } while((item & TYPE_MASK) == T_NAMESPACE_ATTRIBUTE); |
ohair@286 | 625 | |
ohair@286 | 626 | |
ohair@286 | 627 | cacheNamespacePrefixIndex(); |
ohair@286 | 628 | |
ohair@286 | 629 | return item; |
ohair@286 | 630 | } |
ohair@286 | 631 | |
ohair@286 | 632 | private void processAttributes(int item) throws SAXException { |
ohair@286 | 633 | do { |
ohair@286 | 634 | switch(getAIIState(item)) { |
ohair@286 | 635 | case STATE_ATTRIBUTE_U_LN_QN: |
ohair@286 | 636 | _attributes.addAttributeWithQName(readStructureString(), readStructureString(), readStructureString(), readStructureString(), readContentString()); |
ohair@286 | 637 | break; |
ohair@286 | 638 | case STATE_ATTRIBUTE_P_U_LN: |
ohair@286 | 639 | { |
ohair@286 | 640 | final String p = readStructureString(); |
ohair@286 | 641 | final String u = readStructureString(); |
ohair@286 | 642 | final String ln = readStructureString(); |
ohair@286 | 643 | _attributes.addAttributeWithQName(u, ln, getQName(p, ln), readStructureString(), readContentString()); |
ohair@286 | 644 | break; |
ohair@286 | 645 | } |
ohair@286 | 646 | case STATE_ATTRIBUTE_U_LN: { |
ohair@286 | 647 | final String u = readStructureString(); |
ohair@286 | 648 | final String ln = readStructureString(); |
ohair@286 | 649 | _attributes.addAttributeWithQName(u, ln, ln, readStructureString(), readContentString()); |
ohair@286 | 650 | break; |
ohair@286 | 651 | } |
ohair@286 | 652 | case STATE_ATTRIBUTE_LN: { |
ohair@286 | 653 | final String ln = readStructureString(); |
ohair@286 | 654 | _attributes.addAttributeWithQName("", ln, ln, readStructureString(), readContentString()); |
ohair@286 | 655 | break; |
ohair@286 | 656 | } |
ohair@286 | 657 | default: |
ohair@286 | 658 | throw reportFatalError("Illegal state: "+item); |
ohair@286 | 659 | } |
ohair@286 | 660 | readStructure(); |
ohair@286 | 661 | |
ohair@286 | 662 | item = peekStructure(); |
ohair@286 | 663 | } while((item & TYPE_MASK) == T_ATTRIBUTE); |
ohair@286 | 664 | } |
ohair@286 | 665 | |
ohair@286 | 666 | private void processNamespaceAttribute(String prefix, String uri) throws SAXException { |
ohair@286 | 667 | _contentHandler.startPrefixMapping(prefix, uri); |
ohair@286 | 668 | |
ohair@286 | 669 | if (_namespacePrefixesFeature) { |
ohair@286 | 670 | // Add the namespace delcaration as an attribute |
ohair@286 | 671 | if (prefix != "") { |
ohair@286 | 672 | _attributes.addAttributeWithQName(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, prefix, |
ohair@286 | 673 | getQName(XMLConstants.XMLNS_ATTRIBUTE, prefix), |
ohair@286 | 674 | "CDATA", uri); |
ohair@286 | 675 | } else { |
ohair@286 | 676 | _attributes.addAttributeWithQName(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, XMLConstants.XMLNS_ATTRIBUTE, |
ohair@286 | 677 | XMLConstants.XMLNS_ATTRIBUTE, |
ohair@286 | 678 | "CDATA", uri); |
ohair@286 | 679 | } |
ohair@286 | 680 | } |
ohair@286 | 681 | |
ohair@286 | 682 | cacheNamespacePrefix(prefix); |
ohair@286 | 683 | } |
ohair@286 | 684 | |
ohair@286 | 685 | private void cacheNamespacePrefix(String prefix) { |
ohair@286 | 686 | if (_namespacePrefixesIndex == _namespacePrefixes.length) { |
ohair@286 | 687 | final String[] namespaceAttributes = new String[_namespacePrefixesIndex * 3 / 2 + 1]; |
ohair@286 | 688 | System.arraycopy(_namespacePrefixes, 0, namespaceAttributes, 0, _namespacePrefixesIndex); |
ohair@286 | 689 | _namespacePrefixes = namespaceAttributes; |
ohair@286 | 690 | } |
ohair@286 | 691 | |
ohair@286 | 692 | _namespacePrefixes[_namespacePrefixesIndex++] = prefix; |
ohair@286 | 693 | } |
ohair@286 | 694 | |
ohair@286 | 695 | private void cacheNamespacePrefixIndex() { |
ohair@286 | 696 | if (_namespaceAttributesStackIndex == _namespaceAttributesStack.length) { |
ohair@286 | 697 | final int[] namespaceAttributesStack = new int[_namespaceAttributesStackIndex * 3 /2 + 1]; |
ohair@286 | 698 | System.arraycopy(_namespaceAttributesStack, 0, namespaceAttributesStack, 0, _namespaceAttributesStackIndex); |
ohair@286 | 699 | _namespaceAttributesStack = namespaceAttributesStack; |
ohair@286 | 700 | } |
ohair@286 | 701 | |
ohair@286 | 702 | _namespaceAttributesStack[_namespaceAttributesStackIndex++] = _namespacePrefixesIndex; |
ohair@286 | 703 | } |
ohair@286 | 704 | |
alanb@368 | 705 | private void cacheNamespacePrefixStartingIndex() { |
alanb@368 | 706 | if (_namespaceAttributesStackIndex == _namespaceAttributesStartingStack.length) { |
alanb@368 | 707 | final int[] namespaceAttributesStart = new int[_namespaceAttributesStackIndex * 3 /2 + 1]; |
alanb@368 | 708 | System.arraycopy(_namespaceAttributesStartingStack, 0, namespaceAttributesStart, 0, _namespaceAttributesStackIndex); |
alanb@368 | 709 | _namespaceAttributesStartingStack = namespaceAttributesStart; |
alanb@368 | 710 | } |
alanb@368 | 711 | _namespaceAttributesStartingStack[_namespaceAttributesStackIndex] = _namespacePrefixesIndex; |
alanb@368 | 712 | } |
alanb@368 | 713 | |
ohair@286 | 714 | private void processComment(String s) throws SAXException { |
ohair@286 | 715 | processComment(s.toCharArray(), 0, s.length()); |
ohair@286 | 716 | } |
ohair@286 | 717 | |
ohair@286 | 718 | private void processComment(char[] ch, int start, int length) throws SAXException { |
ohair@286 | 719 | _lexicalHandler.comment(ch, start, length); |
ohair@286 | 720 | } |
ohair@286 | 721 | |
ohair@286 | 722 | private void processProcessingInstruction(String target, String data) throws SAXException { |
ohair@286 | 723 | _contentHandler.processingInstruction(target, data); |
ohair@286 | 724 | } |
ohair@286 | 725 | |
ohair@286 | 726 | private static final DefaultWithLexicalHandler DEFAULT_LEXICAL_HANDLER = new DefaultWithLexicalHandler(); |
ohair@286 | 727 | } |