aoqi@0: /* aoqi@0: * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@0: * aoqi@0: * This code is free software; you can redistribute it and/or modify it aoqi@0: * under the terms of the GNU General Public License version 2 only, as aoqi@0: * published by the Free Software Foundation. Oracle designates this aoqi@0: * particular file as subject to the "Classpath" exception as provided aoqi@0: * by Oracle in the LICENSE file that accompanied this code. aoqi@0: * aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that aoqi@0: * accompanied this code). aoqi@0: * aoqi@0: * You should have received a copy of the GNU General Public License version aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@0: * aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@0: * or visit www.oracle.com if you need additional information or have any aoqi@0: * questions. aoqi@0: */ aoqi@0: aoqi@0: package com.sun.xml.internal.stream.buffer.sax; aoqi@0: aoqi@0: import com.sun.xml.internal.stream.buffer.AbstractProcessor; aoqi@0: import com.sun.xml.internal.stream.buffer.AttributesHolder; aoqi@0: import com.sun.xml.internal.stream.buffer.XMLStreamBuffer; aoqi@0: import org.xml.sax.ContentHandler; aoqi@0: import org.xml.sax.DTDHandler; aoqi@0: import org.xml.sax.EntityResolver; aoqi@0: import org.xml.sax.ErrorHandler; aoqi@0: import org.xml.sax.InputSource; aoqi@0: import org.xml.sax.SAXException; aoqi@0: import org.xml.sax.SAXNotRecognizedException; aoqi@0: import org.xml.sax.SAXNotSupportedException; aoqi@0: import org.xml.sax.SAXParseException; aoqi@0: import org.xml.sax.XMLReader; aoqi@0: import org.xml.sax.ext.LexicalHandler; aoqi@0: import org.xml.sax.helpers.LocatorImpl; aoqi@0: aoqi@0: import javax.xml.XMLConstants; aoqi@0: import java.io.IOException; aoqi@0: import java.util.Collections; aoqi@0: import java.util.HashSet; aoqi@0: import java.util.Map; aoqi@0: import java.util.Set; aoqi@0: aoqi@0: /** aoqi@0: * A processor of a {@link XMLStreamBuffer} that that reads the XML infoset as aoqi@0: * {@link XMLReader}. aoqi@0: */ aoqi@0: public class SAXBufferProcessor extends AbstractProcessor implements XMLReader { aoqi@0: /** aoqi@0: * Reference to entity resolver. aoqi@0: */ aoqi@0: protected EntityResolver _entityResolver = DEFAULT_LEXICAL_HANDLER; aoqi@0: aoqi@0: /** aoqi@0: * Reference to dtd handler. aoqi@0: */ aoqi@0: protected DTDHandler _dtdHandler = DEFAULT_LEXICAL_HANDLER; aoqi@0: aoqi@0: /** aoqi@0: * Reference to content handler. aoqi@0: */ aoqi@0: protected ContentHandler _contentHandler = DEFAULT_LEXICAL_HANDLER; aoqi@0: aoqi@0: /** aoqi@0: * Reference to error handler. aoqi@0: */ aoqi@0: protected ErrorHandler _errorHandler = DEFAULT_LEXICAL_HANDLER; aoqi@0: aoqi@0: /** aoqi@0: * Reference to lexical handler. aoqi@0: */ aoqi@0: protected LexicalHandler _lexicalHandler = DEFAULT_LEXICAL_HANDLER; aoqi@0: aoqi@0: /** aoqi@0: * SAX Namespace attributes features aoqi@0: */ aoqi@0: protected boolean _namespacePrefixesFeature = false; aoqi@0: aoqi@0: protected AttributesHolder _attributes = new AttributesHolder(); aoqi@0: aoqi@0: protected String[] _namespacePrefixes = new String[16]; aoqi@0: protected int _namespacePrefixesIndex; aoqi@0: aoqi@0: protected int[] _namespaceAttributesStartingStack = new int[16]; aoqi@0: protected int[] _namespaceAttributesStack = new int[16]; aoqi@0: protected int _namespaceAttributesStackIndex; aoqi@0: aoqi@0: public SAXBufferProcessor() { aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * @deprecated aoqi@0: * Use {@link #SAXBufferProcessor(XMLStreamBuffer, boolean)} aoqi@0: */ aoqi@0: public SAXBufferProcessor(XMLStreamBuffer buffer) { aoqi@0: setXMLStreamBuffer(buffer); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * @param produceFragmentEvent aoqi@0: * True to generate fragment SAX events without start/endDocument. aoqi@0: * False to generate a full document SAX events. aoqi@0: */ aoqi@0: public SAXBufferProcessor(XMLStreamBuffer buffer, boolean produceFragmentEvent) { aoqi@0: setXMLStreamBuffer(buffer,produceFragmentEvent); aoqi@0: } aoqi@0: aoqi@0: public boolean getFeature(String name) aoqi@0: throws SAXNotRecognizedException, SAXNotSupportedException { aoqi@0: if (name.equals(Features.NAMESPACES_FEATURE)) { aoqi@0: return true; aoqi@0: } else if (name.equals(Features.NAMESPACE_PREFIXES_FEATURE)) { aoqi@0: return _namespacePrefixesFeature; aoqi@0: } else if (name.equals(Features.EXTERNAL_GENERAL_ENTITIES)) { aoqi@0: return true; aoqi@0: } else if (name.equals(Features.EXTERNAL_PARAMETER_ENTITIES)) { aoqi@0: return true; aoqi@0: } else if (name.equals(Features.STRING_INTERNING_FEATURE)) { aoqi@0: return _stringInterningFeature; aoqi@0: } else { aoqi@0: throw new SAXNotRecognizedException( aoqi@0: "Feature not supported: " + name); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: public void setFeature(String name, boolean value) aoqi@0: throws SAXNotRecognizedException, SAXNotSupportedException { aoqi@0: if (name.equals(Features.NAMESPACES_FEATURE)) { aoqi@0: if (!value) { aoqi@0: throw new SAXNotSupportedException(name + ":" + value); aoqi@0: } aoqi@0: } else if (name.equals(Features.NAMESPACE_PREFIXES_FEATURE)) { aoqi@0: _namespacePrefixesFeature = value; aoqi@0: } else if (name.equals(Features.EXTERNAL_GENERAL_ENTITIES)) { aoqi@0: // ignore aoqi@0: } else if (name.equals(Features.EXTERNAL_PARAMETER_ENTITIES)) { aoqi@0: // ignore aoqi@0: } else if (name.equals(Features.STRING_INTERNING_FEATURE)) { aoqi@0: if (value != _stringInterningFeature) { aoqi@0: throw new SAXNotSupportedException(name + ":" + value); aoqi@0: } aoqi@0: } else { aoqi@0: throw new SAXNotRecognizedException( aoqi@0: "Feature not supported: " + name); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: public Object getProperty(String name) aoqi@0: throws SAXNotRecognizedException, SAXNotSupportedException { aoqi@0: if (name.equals(Properties.LEXICAL_HANDLER_PROPERTY)) { aoqi@0: return getLexicalHandler(); aoqi@0: } else { aoqi@0: throw new SAXNotRecognizedException("Property not recognized: " + name); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: public void setProperty(String name, Object value) aoqi@0: throws SAXNotRecognizedException, SAXNotSupportedException { aoqi@0: if (name.equals(Properties.LEXICAL_HANDLER_PROPERTY)) { aoqi@0: if (value instanceof LexicalHandler) { aoqi@0: setLexicalHandler((LexicalHandler)value); aoqi@0: } else { aoqi@0: throw new SAXNotSupportedException(Properties.LEXICAL_HANDLER_PROPERTY); aoqi@0: } aoqi@0: } else { aoqi@0: throw new SAXNotRecognizedException("Property not recognized: " + name); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: public void setEntityResolver(EntityResolver resolver) { aoqi@0: _entityResolver = resolver; aoqi@0: } aoqi@0: aoqi@0: public EntityResolver getEntityResolver() { aoqi@0: return _entityResolver; aoqi@0: } aoqi@0: aoqi@0: public void setDTDHandler(DTDHandler handler) { aoqi@0: _dtdHandler = handler; aoqi@0: } aoqi@0: aoqi@0: public DTDHandler getDTDHandler() { aoqi@0: return _dtdHandler; aoqi@0: } aoqi@0: aoqi@0: public void setContentHandler(ContentHandler handler) { aoqi@0: _contentHandler = handler; aoqi@0: } aoqi@0: aoqi@0: public ContentHandler getContentHandler() { aoqi@0: return _contentHandler; aoqi@0: } aoqi@0: aoqi@0: public void setErrorHandler(ErrorHandler handler) { aoqi@0: _errorHandler = handler; aoqi@0: } aoqi@0: aoqi@0: public ErrorHandler getErrorHandler() { aoqi@0: return _errorHandler; aoqi@0: } aoqi@0: aoqi@0: public void setLexicalHandler(LexicalHandler handler) { aoqi@0: _lexicalHandler = handler; aoqi@0: } aoqi@0: aoqi@0: public LexicalHandler getLexicalHandler() { aoqi@0: return _lexicalHandler; aoqi@0: } aoqi@0: aoqi@0: public void parse(InputSource input) throws IOException, SAXException { aoqi@0: // InputSource is ignored aoqi@0: process(); aoqi@0: } aoqi@0: aoqi@0: public void parse(String systemId) throws IOException, SAXException { aoqi@0: // systemId is ignored aoqi@0: process(); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Short-hand for {@link #setXMLStreamBuffer(XMLStreamBuffer)} then {@link #process()}. aoqi@0: * aoqi@0: * @deprecated aoqi@0: * Use {@link #process(XMLStreamBuffer, boolean)} aoqi@0: */ aoqi@0: public final void process(XMLStreamBuffer buffer) throws SAXException { aoqi@0: setXMLStreamBuffer(buffer); aoqi@0: process(); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Short-hand for {@link #setXMLStreamBuffer(XMLStreamBuffer,boolean)} then {@link #process()}. aoqi@0: * aoqi@0: * @param produceFragmentEvent aoqi@0: * True to generate fragment SAX events without start/endDocument. aoqi@0: * False to generate a full document SAX events. aoqi@0: */ aoqi@0: public final void process(XMLStreamBuffer buffer, boolean produceFragmentEvent) throws SAXException { aoqi@0: setXMLStreamBuffer(buffer); aoqi@0: process(); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Resets the parser to read from the beginning of the given {@link XMLStreamBuffer}. aoqi@0: * aoqi@0: * @deprecated aoqi@0: * Use {@link #setXMLStreamBuffer(XMLStreamBuffer, boolean)}. aoqi@0: */ aoqi@0: public void setXMLStreamBuffer(XMLStreamBuffer buffer) { aoqi@0: setBuffer(buffer); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Resets the parser to read from the beginning of the given {@link XMLStreamBuffer}. aoqi@0: * aoqi@0: * @param produceFragmentEvent aoqi@0: * True to generate fragment SAX events without start/endDocument. aoqi@0: * False to generate a full document SAX events. aoqi@0: */ aoqi@0: public void setXMLStreamBuffer(XMLStreamBuffer buffer, boolean produceFragmentEvent) { aoqi@0: if(!produceFragmentEvent && _treeCount>1) aoqi@0: throw new IllegalStateException("Can't write a forest to a full XML infoset"); aoqi@0: setBuffer(buffer,produceFragmentEvent); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Parse the sub-tree (or a whole document) that {@link XMLStreamBuffer} aoqi@0: * points to, and sends events to handlers. aoqi@0: * aoqi@0: *

aoqi@0: * TODO: aoqi@0: * We probably need two modes for a sub-tree event generation. One for aoqi@0: * firing a sub-tree as if it's a whole document (in which case start/endDocument aoqi@0: * and appropriate additional namespace bindings are necessary), and the other aoqi@0: * mode for firing a subtree as a subtree, like it does today. aoqi@0: * A stream buffer SAX feature could be used to specify this. aoqi@0: * aoqi@0: * @throws SAXException aoqi@0: * Follow the same semantics as {@link XMLReader#parse(InputSource)}. aoqi@0: */ aoqi@0: public final void process() throws SAXException { aoqi@0: if(!_fragmentMode) { aoqi@0: LocatorImpl nullLocator = new LocatorImpl(); aoqi@0: nullLocator.setSystemId(_buffer.getSystemId()); aoqi@0: nullLocator.setLineNumber(-1); aoqi@0: nullLocator.setColumnNumber(-1); aoqi@0: _contentHandler.setDocumentLocator(nullLocator); aoqi@0: aoqi@0: _contentHandler.startDocument(); aoqi@0: // TODO: if we are writing a fragment stream buffer as a full XML document, aoqi@0: // we need to declare in-scope namespaces as if they are on the root element. aoqi@0: } aoqi@0: aoqi@0: while (_treeCount>0) { aoqi@0: final int item = readEiiState(); aoqi@0: switch(item) { aoqi@0: case STATE_DOCUMENT: aoqi@0: processDocument(); aoqi@0: _treeCount--; aoqi@0: break; aoqi@0: case STATE_END: aoqi@0: // Empty buffer aoqi@0: return; aoqi@0: case STATE_ELEMENT_U_LN_QN: aoqi@0: processElement(readStructureString(), readStructureString(), readStructureString(), isInscope()); aoqi@0: _treeCount--; aoqi@0: break; aoqi@0: case STATE_ELEMENT_P_U_LN: aoqi@0: { aoqi@0: final String prefix = readStructureString(); aoqi@0: final String uri = readStructureString(); aoqi@0: final String localName = readStructureString(); aoqi@0: processElement(uri, localName, getQName(prefix, localName),isInscope()); aoqi@0: _treeCount--; aoqi@0: break; aoqi@0: } aoqi@0: case STATE_ELEMENT_U_LN: { aoqi@0: final String uri = readStructureString(); aoqi@0: final String localName = readStructureString(); aoqi@0: processElement(uri, localName, localName,isInscope()); aoqi@0: _treeCount--; aoqi@0: break; aoqi@0: } aoqi@0: case STATE_ELEMENT_LN: aoqi@0: { aoqi@0: final String localName = readStructureString(); aoqi@0: processElement("", localName, localName,isInscope()); aoqi@0: _treeCount--; aoqi@0: break; aoqi@0: } aoqi@0: case STATE_COMMENT_AS_CHAR_ARRAY_SMALL: aoqi@0: processCommentAsCharArraySmall(); aoqi@0: break; aoqi@0: case STATE_COMMENT_AS_CHAR_ARRAY_MEDIUM: aoqi@0: processCommentAsCharArrayMedium(); aoqi@0: break; aoqi@0: case STATE_COMMENT_AS_CHAR_ARRAY_COPY: aoqi@0: processCommentAsCharArrayCopy(); aoqi@0: break; aoqi@0: case STATE_COMMENT_AS_STRING: aoqi@0: processComment(readContentString()); aoqi@0: break; aoqi@0: case STATE_PROCESSING_INSTRUCTION: aoqi@0: processProcessingInstruction(readStructureString(), readStructureString()); aoqi@0: break; aoqi@0: default: aoqi@0: throw reportFatalError("Illegal state for DIIs: "+item); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: if(!_fragmentMode) aoqi@0: _contentHandler.endDocument(); aoqi@0: } aoqi@0: aoqi@0: private void processCommentAsCharArraySmall() throws SAXException { aoqi@0: final int length = readStructure(); aoqi@0: final int start = readContentCharactersBuffer(length); aoqi@0: processComment(_contentCharactersBuffer, start, length); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Report a fatal error and abort. aoqi@0: * aoqi@0: * This is necessary to follow the SAX semantics of error handling. aoqi@0: */ aoqi@0: private SAXParseException reportFatalError(String msg) throws SAXException { aoqi@0: SAXParseException spe = new SAXParseException(msg, null); aoqi@0: if(_errorHandler!=null) aoqi@0: _errorHandler.fatalError(spe); aoqi@0: return spe; aoqi@0: } aoqi@0: aoqi@0: private boolean isInscope() { aoqi@0: return _buffer.getInscopeNamespaces().size() > 0; aoqi@0: } aoqi@0: aoqi@0: private void processDocument() throws SAXException { aoqi@0: while(true) { aoqi@0: int item = readEiiState(); aoqi@0: switch(item) { aoqi@0: case STATE_ELEMENT_U_LN_QN: aoqi@0: processElement(readStructureString(), readStructureString(), readStructureString(),isInscope()); aoqi@0: break; aoqi@0: case STATE_ELEMENT_P_U_LN: aoqi@0: { aoqi@0: final String prefix = readStructureString(); aoqi@0: final String uri = readStructureString(); aoqi@0: final String localName = readStructureString(); aoqi@0: processElement(uri, localName, getQName(prefix, localName),isInscope()); aoqi@0: break; aoqi@0: } aoqi@0: case STATE_ELEMENT_U_LN: { aoqi@0: final String uri = readStructureString(); aoqi@0: final String localName = readStructureString(); aoqi@0: processElement(uri, localName, localName,isInscope()); aoqi@0: break; aoqi@0: } aoqi@0: case STATE_ELEMENT_LN: aoqi@0: { aoqi@0: final String localName = readStructureString(); aoqi@0: processElement("", localName, localName,isInscope()); aoqi@0: break; aoqi@0: } aoqi@0: case STATE_COMMENT_AS_CHAR_ARRAY_SMALL: aoqi@0: processCommentAsCharArraySmall(); aoqi@0: break; aoqi@0: case STATE_COMMENT_AS_CHAR_ARRAY_MEDIUM: aoqi@0: processCommentAsCharArrayMedium(); aoqi@0: break; aoqi@0: case STATE_COMMENT_AS_CHAR_ARRAY_COPY: aoqi@0: processCommentAsCharArrayCopy(); aoqi@0: break; aoqi@0: case STATE_COMMENT_AS_STRING: aoqi@0: processComment(readContentString()); aoqi@0: break; aoqi@0: case STATE_PROCESSING_INSTRUCTION: aoqi@0: processProcessingInstruction(readStructureString(), readStructureString()); aoqi@0: break; aoqi@0: case STATE_END: aoqi@0: return; aoqi@0: default: aoqi@0: throw reportFatalError("Illegal state for child of DII: "+item); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: protected void processElement(String uri, String localName, String qName, boolean inscope) throws SAXException { aoqi@0: boolean hasAttributes = false; aoqi@0: boolean hasNamespaceAttributes = false; aoqi@0: int item = peekStructure(); aoqi@0: Set prefixSet = inscope ? new HashSet() : Collections.emptySet(); aoqi@0: if ((item & TYPE_MASK) == T_NAMESPACE_ATTRIBUTE) { aoqi@0: cacheNamespacePrefixStartingIndex(); aoqi@0: hasNamespaceAttributes = true; aoqi@0: item = processNamespaceAttributes(item, inscope, prefixSet); aoqi@0: } aoqi@0: if (inscope) { aoqi@0: readInscopeNamespaces(prefixSet); aoqi@0: } aoqi@0: aoqi@0: if ((item & TYPE_MASK) == T_ATTRIBUTE) { aoqi@0: hasAttributes = true; aoqi@0: processAttributes(item); aoqi@0: } aoqi@0: aoqi@0: _contentHandler.startElement(uri, localName, qName, _attributes); aoqi@0: aoqi@0: if (hasAttributes) { aoqi@0: _attributes.clear(); aoqi@0: } aoqi@0: aoqi@0: do { aoqi@0: item = readEiiState(); aoqi@0: switch(item) { aoqi@0: case STATE_ELEMENT_U_LN_QN: aoqi@0: processElement(readStructureString(), readStructureString(), readStructureString(), false); aoqi@0: break; aoqi@0: case STATE_ELEMENT_P_U_LN: aoqi@0: { aoqi@0: final String p = readStructureString(); aoqi@0: final String u = readStructureString(); aoqi@0: final String ln = readStructureString(); aoqi@0: processElement(u, ln, getQName(p, ln),false); aoqi@0: break; aoqi@0: } aoqi@0: case STATE_ELEMENT_U_LN: { aoqi@0: final String u = readStructureString(); aoqi@0: final String ln = readStructureString(); aoqi@0: processElement(u, ln, ln,false); aoqi@0: break; aoqi@0: } aoqi@0: case STATE_ELEMENT_LN: { aoqi@0: final String ln = readStructureString(); aoqi@0: processElement("", ln, ln,false); aoqi@0: break; aoqi@0: } aoqi@0: case STATE_TEXT_AS_CHAR_ARRAY_SMALL: aoqi@0: { aoqi@0: final int length = readStructure(); aoqi@0: int start = readContentCharactersBuffer(length); aoqi@0: _contentHandler.characters(_contentCharactersBuffer, start, length); aoqi@0: break; aoqi@0: } aoqi@0: case STATE_TEXT_AS_CHAR_ARRAY_MEDIUM: aoqi@0: { aoqi@0: final int length = readStructure16(); aoqi@0: int start = readContentCharactersBuffer(length); aoqi@0: _contentHandler.characters(_contentCharactersBuffer, start, length); aoqi@0: break; aoqi@0: } aoqi@0: case STATE_TEXT_AS_CHAR_ARRAY_COPY: aoqi@0: { aoqi@0: final char[] ch = readContentCharactersCopy(); aoqi@0: aoqi@0: _contentHandler.characters(ch, 0, ch.length); aoqi@0: break; aoqi@0: } aoqi@0: case STATE_TEXT_AS_STRING: aoqi@0: { aoqi@0: final String s = readContentString(); aoqi@0: _contentHandler.characters(s.toCharArray(), 0, s.length()); aoqi@0: break; aoqi@0: } aoqi@0: case STATE_TEXT_AS_OBJECT: aoqi@0: { aoqi@0: final CharSequence c = (CharSequence)readContentObject(); aoqi@0: final String s = c.toString(); aoqi@0: _contentHandler.characters(s.toCharArray(), 0, s.length()); aoqi@0: break; aoqi@0: } aoqi@0: case STATE_COMMENT_AS_CHAR_ARRAY_SMALL: aoqi@0: processCommentAsCharArraySmall(); aoqi@0: break; aoqi@0: case STATE_COMMENT_AS_CHAR_ARRAY_MEDIUM: aoqi@0: processCommentAsCharArrayMedium(); aoqi@0: break; aoqi@0: case STATE_COMMENT_AS_CHAR_ARRAY_COPY: aoqi@0: processCommentAsCharArrayCopy(); aoqi@0: break; aoqi@0: case T_COMMENT_AS_STRING: aoqi@0: processComment(readContentString()); aoqi@0: break; aoqi@0: case STATE_PROCESSING_INSTRUCTION: aoqi@0: processProcessingInstruction(readStructureString(), readStructureString()); aoqi@0: break; aoqi@0: case STATE_END: aoqi@0: break; aoqi@0: default: aoqi@0: throw reportFatalError("Illegal state for child of EII: "+item); aoqi@0: } aoqi@0: } while(item != STATE_END); aoqi@0: aoqi@0: _contentHandler.endElement(uri, localName, qName); aoqi@0: aoqi@0: if (hasNamespaceAttributes) { aoqi@0: processEndPrefixMapping(); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: private void readInscopeNamespaces(Set prefixSet) throws SAXException { aoqi@0: for (Map.Entry e : _buffer.getInscopeNamespaces().entrySet()) { aoqi@0: String key = fixNull(e.getKey()); aoqi@0: // If the prefix is already written, do not write the prefix aoqi@0: if (!prefixSet.contains(key)) { aoqi@0: processNamespaceAttribute(key,e.getValue()); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: } aoqi@0: aoqi@0: private static String fixNull(String s) { aoqi@0: if (s == null) return ""; aoqi@0: else return s; aoqi@0: } aoqi@0: private void processCommentAsCharArrayCopy() throws SAXException { aoqi@0: final char[] ch = readContentCharactersCopy(); aoqi@0: processComment(ch, 0, ch.length); aoqi@0: } aoqi@0: aoqi@0: private void processCommentAsCharArrayMedium() throws SAXException { aoqi@0: final int length = readStructure16(); aoqi@0: final int start = readContentCharactersBuffer(length); aoqi@0: processComment(_contentCharactersBuffer, start, length); aoqi@0: } aoqi@0: aoqi@0: private void processEndPrefixMapping() throws SAXException { aoqi@0: final int end = _namespaceAttributesStack[--_namespaceAttributesStackIndex]; aoqi@0: // final int start = (_namespaceAttributesStackIndex > 0) ? _namespaceAttributesStack[_namespaceAttributesStackIndex] : 0; aoqi@0: final int start = (_namespaceAttributesStackIndex >= 0) ? _namespaceAttributesStartingStack[_namespaceAttributesStackIndex] : 0; aoqi@0: aoqi@0: for (int i = end - 1; i >= start; i--) { aoqi@0: _contentHandler.endPrefixMapping(_namespacePrefixes[i]); aoqi@0: } aoqi@0: _namespacePrefixesIndex = start; aoqi@0: } aoqi@0: aoqi@0: private int processNamespaceAttributes(int item,boolean collectPrefixes, Set prefixSet) throws SAXException { aoqi@0: do { aoqi@0: String prefix; aoqi@0: switch(getNIIState(item)) { aoqi@0: case STATE_NAMESPACE_ATTRIBUTE: aoqi@0: // Undeclaration of default namespace aoqi@0: processNamespaceAttribute("", ""); aoqi@0: if(collectPrefixes) { aoqi@0: prefixSet.add(""); aoqi@0: } aoqi@0: break; aoqi@0: case STATE_NAMESPACE_ATTRIBUTE_P: aoqi@0: // Undeclaration of namespace aoqi@0: prefix = readStructureString(); aoqi@0: processNamespaceAttribute(prefix, ""); aoqi@0: if(collectPrefixes) { aoqi@0: prefixSet.add(prefix); aoqi@0: } aoqi@0: break; aoqi@0: case STATE_NAMESPACE_ATTRIBUTE_P_U: aoqi@0: // Declaration with prefix aoqi@0: prefix = readStructureString(); aoqi@0: processNamespaceAttribute(prefix, readStructureString()); aoqi@0: if(collectPrefixes) { aoqi@0: prefixSet.add(prefix); aoqi@0: } aoqi@0: break; aoqi@0: case STATE_NAMESPACE_ATTRIBUTE_U: aoqi@0: // Default declaration aoqi@0: processNamespaceAttribute("", readStructureString()); aoqi@0: if(collectPrefixes) { aoqi@0: prefixSet.add(""); aoqi@0: } aoqi@0: break; aoqi@0: default: aoqi@0: throw reportFatalError("Illegal state: "+item); aoqi@0: } aoqi@0: readStructure(); aoqi@0: aoqi@0: item = peekStructure(); aoqi@0: } while((item & TYPE_MASK) == T_NAMESPACE_ATTRIBUTE); aoqi@0: aoqi@0: aoqi@0: cacheNamespacePrefixIndex(); aoqi@0: aoqi@0: return item; aoqi@0: } aoqi@0: aoqi@0: private void processAttributes(int item) throws SAXException { aoqi@0: do { aoqi@0: switch(getAIIState(item)) { aoqi@0: case STATE_ATTRIBUTE_U_LN_QN: aoqi@0: _attributes.addAttributeWithQName(readStructureString(), readStructureString(), readStructureString(), readStructureString(), readContentString()); aoqi@0: break; aoqi@0: case STATE_ATTRIBUTE_P_U_LN: aoqi@0: { aoqi@0: final String p = readStructureString(); aoqi@0: final String u = readStructureString(); aoqi@0: final String ln = readStructureString(); aoqi@0: _attributes.addAttributeWithQName(u, ln, getQName(p, ln), readStructureString(), readContentString()); aoqi@0: break; aoqi@0: } aoqi@0: case STATE_ATTRIBUTE_U_LN: { aoqi@0: final String u = readStructureString(); aoqi@0: final String ln = readStructureString(); aoqi@0: _attributes.addAttributeWithQName(u, ln, ln, readStructureString(), readContentString()); aoqi@0: break; aoqi@0: } aoqi@0: case STATE_ATTRIBUTE_LN: { aoqi@0: final String ln = readStructureString(); aoqi@0: _attributes.addAttributeWithQName("", ln, ln, readStructureString(), readContentString()); aoqi@0: break; aoqi@0: } aoqi@0: default: aoqi@0: throw reportFatalError("Illegal state: "+item); aoqi@0: } aoqi@0: readStructure(); aoqi@0: aoqi@0: item = peekStructure(); aoqi@0: } while((item & TYPE_MASK) == T_ATTRIBUTE); aoqi@0: } aoqi@0: aoqi@0: private void processNamespaceAttribute(String prefix, String uri) throws SAXException { aoqi@0: _contentHandler.startPrefixMapping(prefix, uri); aoqi@0: aoqi@0: if (_namespacePrefixesFeature) { aoqi@0: // Add the namespace delcaration as an attribute aoqi@0: if (prefix != "") { aoqi@0: _attributes.addAttributeWithQName(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, prefix, aoqi@0: getQName(XMLConstants.XMLNS_ATTRIBUTE, prefix), aoqi@0: "CDATA", uri); aoqi@0: } else { aoqi@0: _attributes.addAttributeWithQName(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, XMLConstants.XMLNS_ATTRIBUTE, aoqi@0: XMLConstants.XMLNS_ATTRIBUTE, aoqi@0: "CDATA", uri); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: cacheNamespacePrefix(prefix); aoqi@0: } aoqi@0: aoqi@0: private void cacheNamespacePrefix(String prefix) { aoqi@0: if (_namespacePrefixesIndex == _namespacePrefixes.length) { aoqi@0: final String[] namespaceAttributes = new String[_namespacePrefixesIndex * 3 / 2 + 1]; aoqi@0: System.arraycopy(_namespacePrefixes, 0, namespaceAttributes, 0, _namespacePrefixesIndex); aoqi@0: _namespacePrefixes = namespaceAttributes; aoqi@0: } aoqi@0: aoqi@0: _namespacePrefixes[_namespacePrefixesIndex++] = prefix; aoqi@0: } aoqi@0: aoqi@0: private void cacheNamespacePrefixIndex() { aoqi@0: if (_namespaceAttributesStackIndex == _namespaceAttributesStack.length) { aoqi@0: final int[] namespaceAttributesStack = new int[_namespaceAttributesStackIndex * 3 /2 + 1]; aoqi@0: System.arraycopy(_namespaceAttributesStack, 0, namespaceAttributesStack, 0, _namespaceAttributesStackIndex); aoqi@0: _namespaceAttributesStack = namespaceAttributesStack; aoqi@0: } aoqi@0: aoqi@0: _namespaceAttributesStack[_namespaceAttributesStackIndex++] = _namespacePrefixesIndex; aoqi@0: } aoqi@0: aoqi@0: private void cacheNamespacePrefixStartingIndex() { aoqi@0: if (_namespaceAttributesStackIndex == _namespaceAttributesStartingStack.length) { aoqi@0: final int[] namespaceAttributesStart = new int[_namespaceAttributesStackIndex * 3 /2 + 1]; aoqi@0: System.arraycopy(_namespaceAttributesStartingStack, 0, namespaceAttributesStart, 0, _namespaceAttributesStackIndex); aoqi@0: _namespaceAttributesStartingStack = namespaceAttributesStart; aoqi@0: } aoqi@0: _namespaceAttributesStartingStack[_namespaceAttributesStackIndex] = _namespacePrefixesIndex; aoqi@0: } aoqi@0: aoqi@0: private void processComment(String s) throws SAXException { aoqi@0: processComment(s.toCharArray(), 0, s.length()); aoqi@0: } aoqi@0: aoqi@0: private void processComment(char[] ch, int start, int length) throws SAXException { aoqi@0: _lexicalHandler.comment(ch, start, length); aoqi@0: } aoqi@0: aoqi@0: private void processProcessingInstruction(String target, String data) throws SAXException { aoqi@0: _contentHandler.processingInstruction(target, data); aoqi@0: } aoqi@0: aoqi@0: private static final DefaultWithLexicalHandler DEFAULT_LEXICAL_HANDLER = new DefaultWithLexicalHandler(); aoqi@0: }