| /* |
| * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Oracle designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Oracle in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| package com.sun.xml.internal.stream.buffer.sax; |
| |
| import com.sun.xml.internal.stream.buffer.AbstractProcessor; |
| import com.sun.xml.internal.stream.buffer.AttributesHolder; |
| import com.sun.xml.internal.stream.buffer.XMLStreamBuffer; |
| import org.xml.sax.ContentHandler; |
| import org.xml.sax.DTDHandler; |
| import org.xml.sax.EntityResolver; |
| import org.xml.sax.ErrorHandler; |
| import org.xml.sax.InputSource; |
| import org.xml.sax.SAXException; |
| import org.xml.sax.SAXNotRecognizedException; |
| import org.xml.sax.SAXNotSupportedException; |
| import org.xml.sax.SAXParseException; |
| import org.xml.sax.XMLReader; |
| import org.xml.sax.ext.LexicalHandler; |
| import org.xml.sax.helpers.LocatorImpl; |
| |
| import javax.xml.XMLConstants; |
| import java.io.IOException; |
| import java.util.Collections; |
| import java.util.HashSet; |
| import java.util.Map; |
| import java.util.Set; |
| |
| /** |
| * A processor of a {@link XMLStreamBuffer} that that reads the XML infoset as |
| * {@link XMLReader}. |
| */ |
| public class SAXBufferProcessor extends AbstractProcessor implements XMLReader { |
| /** |
| * Reference to entity resolver. |
| */ |
| protected EntityResolver _entityResolver = DEFAULT_LEXICAL_HANDLER; |
| |
| /** |
| * Reference to dtd handler. |
| */ |
| protected DTDHandler _dtdHandler = DEFAULT_LEXICAL_HANDLER; |
| |
| /** |
| * Reference to content handler. |
| */ |
| protected ContentHandler _contentHandler = DEFAULT_LEXICAL_HANDLER; |
| |
| /** |
| * Reference to error handler. |
| */ |
| protected ErrorHandler _errorHandler = DEFAULT_LEXICAL_HANDLER; |
| |
| /** |
| * Reference to lexical handler. |
| */ |
| protected LexicalHandler _lexicalHandler = DEFAULT_LEXICAL_HANDLER; |
| |
| /** |
| * SAX Namespace attributes features |
| */ |
| protected boolean _namespacePrefixesFeature = false; |
| |
| protected AttributesHolder _attributes = new AttributesHolder(); |
| |
| protected String[] _namespacePrefixes = new String[16]; |
| protected int _namespacePrefixesIndex; |
| |
| protected int[] _namespaceAttributesStartingStack = new int[16]; |
| protected int[] _namespaceAttributesStack = new int[16]; |
| protected int _namespaceAttributesStackIndex; |
| |
| public SAXBufferProcessor() { |
| } |
| |
| /** |
| * @deprecated |
| * Use {@link #SAXBufferProcessor(XMLStreamBuffer, boolean)} |
| */ |
| public SAXBufferProcessor(XMLStreamBuffer buffer) { |
| setXMLStreamBuffer(buffer); |
| } |
| |
| /** |
| * @param produceFragmentEvent |
| * True to generate fragment SAX events without start/endDocument. |
| * False to generate a full document SAX events. |
| */ |
| public SAXBufferProcessor(XMLStreamBuffer buffer, boolean produceFragmentEvent) { |
| setXMLStreamBuffer(buffer,produceFragmentEvent); |
| } |
| |
| public boolean getFeature(String name) |
| throws SAXNotRecognizedException, SAXNotSupportedException { |
| if (name.equals(Features.NAMESPACES_FEATURE)) { |
| return true; |
| } else if (name.equals(Features.NAMESPACE_PREFIXES_FEATURE)) { |
| return _namespacePrefixesFeature; |
| } else if (name.equals(Features.EXTERNAL_GENERAL_ENTITIES)) { |
| return true; |
| } else if (name.equals(Features.EXTERNAL_PARAMETER_ENTITIES)) { |
| return true; |
| } else if (name.equals(Features.STRING_INTERNING_FEATURE)) { |
| return _stringInterningFeature; |
| } else { |
| throw new SAXNotRecognizedException( |
| "Feature not supported: " + name); |
| } |
| } |
| |
| public void setFeature(String name, boolean value) |
| throws SAXNotRecognizedException, SAXNotSupportedException { |
| if (name.equals(Features.NAMESPACES_FEATURE)) { |
| if (!value) { |
| throw new SAXNotSupportedException(name + ":" + value); |
| } |
| } else if (name.equals(Features.NAMESPACE_PREFIXES_FEATURE)) { |
| _namespacePrefixesFeature = value; |
| } else if (name.equals(Features.EXTERNAL_GENERAL_ENTITIES)) { |
| // ignore |
| } else if (name.equals(Features.EXTERNAL_PARAMETER_ENTITIES)) { |
| // ignore |
| } else if (name.equals(Features.STRING_INTERNING_FEATURE)) { |
| if (value != _stringInterningFeature) { |
| throw new SAXNotSupportedException(name + ":" + value); |
| } |
| } else { |
| throw new SAXNotRecognizedException( |
| "Feature not supported: " + name); |
| } |
| } |
| |
| public Object getProperty(String name) |
| throws SAXNotRecognizedException, SAXNotSupportedException { |
| if (name.equals(Properties.LEXICAL_HANDLER_PROPERTY)) { |
| return getLexicalHandler(); |
| } else { |
| throw new SAXNotRecognizedException("Property not recognized: " + name); |
| } |
| } |
| |
| public void setProperty(String name, Object value) |
| throws SAXNotRecognizedException, SAXNotSupportedException { |
| if (name.equals(Properties.LEXICAL_HANDLER_PROPERTY)) { |
| if (value instanceof LexicalHandler) { |
| setLexicalHandler((LexicalHandler)value); |
| } else { |
| throw new SAXNotSupportedException(Properties.LEXICAL_HANDLER_PROPERTY); |
| } |
| } else { |
| throw new SAXNotRecognizedException("Property not recognized: " + name); |
| } |
| } |
| |
| public void setEntityResolver(EntityResolver resolver) { |
| _entityResolver = resolver; |
| } |
| |
| public EntityResolver getEntityResolver() { |
| return _entityResolver; |
| } |
| |
| public void setDTDHandler(DTDHandler handler) { |
| _dtdHandler = handler; |
| } |
| |
| public DTDHandler getDTDHandler() { |
| return _dtdHandler; |
| } |
| |
| public void setContentHandler(ContentHandler handler) { |
| _contentHandler = handler; |
| } |
| |
| public ContentHandler getContentHandler() { |
| return _contentHandler; |
| } |
| |
| public void setErrorHandler(ErrorHandler handler) { |
| _errorHandler = handler; |
| } |
| |
| public ErrorHandler getErrorHandler() { |
| return _errorHandler; |
| } |
| |
| public void setLexicalHandler(LexicalHandler handler) { |
| _lexicalHandler = handler; |
| } |
| |
| public LexicalHandler getLexicalHandler() { |
| return _lexicalHandler; |
| } |
| |
| public void parse(InputSource input) throws IOException, SAXException { |
| // InputSource is ignored |
| process(); |
| } |
| |
| public void parse(String systemId) throws IOException, SAXException { |
| // systemId is ignored |
| process(); |
| } |
| |
| /** |
| * Short-hand for {@link #setXMLStreamBuffer(XMLStreamBuffer)} then {@link #process()}. |
| * |
| * @deprecated |
| * Use {@link #process(XMLStreamBuffer, boolean)} |
| */ |
| public final void process(XMLStreamBuffer buffer) throws SAXException { |
| setXMLStreamBuffer(buffer); |
| process(); |
| } |
| |
| /** |
| * Short-hand for {@link #setXMLStreamBuffer(XMLStreamBuffer,boolean)} then {@link #process()}. |
| * |
| * @param produceFragmentEvent |
| * True to generate fragment SAX events without start/endDocument. |
| * False to generate a full document SAX events. |
| */ |
| public final void process(XMLStreamBuffer buffer, boolean produceFragmentEvent) throws SAXException { |
| setXMLStreamBuffer(buffer); |
| process(); |
| } |
| |
| /** |
| * Resets the parser to read from the beginning of the given {@link XMLStreamBuffer}. |
| * |
| * @deprecated |
| * Use {@link #setXMLStreamBuffer(XMLStreamBuffer, boolean)}. |
| */ |
| public void setXMLStreamBuffer(XMLStreamBuffer buffer) { |
| setBuffer(buffer); |
| } |
| |
| /** |
| * Resets the parser to read from the beginning of the given {@link XMLStreamBuffer}. |
| * |
| * @param produceFragmentEvent |
| * True to generate fragment SAX events without start/endDocument. |
| * False to generate a full document SAX events. |
| */ |
| public void setXMLStreamBuffer(XMLStreamBuffer buffer, boolean produceFragmentEvent) { |
| if(!produceFragmentEvent && _treeCount>1) |
| throw new IllegalStateException("Can't write a forest to a full XML infoset"); |
| setBuffer(buffer,produceFragmentEvent); |
| } |
| |
| /** |
| * Parse the sub-tree (or a whole document) that {@link XMLStreamBuffer} |
| * points to, and sends events to handlers. |
| * |
| * <p> |
| * TODO: |
| * We probably need two modes for a sub-tree event generation. One for |
| * firing a sub-tree as if it's a whole document (in which case start/endDocument |
| * and appropriate additional namespace bindings are necessary), and the other |
| * mode for firing a subtree as a subtree, like it does today. |
| * A stream buffer SAX feature could be used to specify this. |
| * |
| * @throws SAXException |
| * Follow the same semantics as {@link XMLReader#parse(InputSource)}. |
| */ |
| public final void process() throws SAXException { |
| if(!_fragmentMode) { |
| LocatorImpl nullLocator = new LocatorImpl(); |
| nullLocator.setSystemId(_buffer.getSystemId()); |
| nullLocator.setLineNumber(-1); |
| nullLocator.setColumnNumber(-1); |
| _contentHandler.setDocumentLocator(nullLocator); |
| |
| _contentHandler.startDocument(); |
| // TODO: if we are writing a fragment stream buffer as a full XML document, |
| // we need to declare in-scope namespaces as if they are on the root element. |
| } |
| |
| while (_treeCount>0) { |
| final int item = readEiiState(); |
| switch(item) { |
| case STATE_DOCUMENT: |
| processDocument(); |
| _treeCount--; |
| break; |
| case STATE_END: |
| // Empty buffer |
| return; |
| case STATE_ELEMENT_U_LN_QN: |
| processElement(readStructureString(), readStructureString(), readStructureString(), isInscope()); |
| _treeCount--; |
| break; |
| case STATE_ELEMENT_P_U_LN: |
| { |
| final String prefix = readStructureString(); |
| final String uri = readStructureString(); |
| final String localName = readStructureString(); |
| processElement(uri, localName, getQName(prefix, localName),isInscope()); |
| _treeCount--; |
| break; |
| } |
| case STATE_ELEMENT_U_LN: { |
| final String uri = readStructureString(); |
| final String localName = readStructureString(); |
| processElement(uri, localName, localName,isInscope()); |
| _treeCount--; |
| break; |
| } |
| case STATE_ELEMENT_LN: |
| { |
| final String localName = readStructureString(); |
| processElement("", localName, localName,isInscope()); |
| _treeCount--; |
| break; |
| } |
| case STATE_COMMENT_AS_CHAR_ARRAY_SMALL: |
| processCommentAsCharArraySmall(); |
| break; |
| case STATE_COMMENT_AS_CHAR_ARRAY_MEDIUM: |
| processCommentAsCharArrayMedium(); |
| break; |
| case STATE_COMMENT_AS_CHAR_ARRAY_COPY: |
| processCommentAsCharArrayCopy(); |
| break; |
| case STATE_COMMENT_AS_STRING: |
| processComment(readContentString()); |
| break; |
| case STATE_PROCESSING_INSTRUCTION: |
| processProcessingInstruction(readStructureString(), readStructureString()); |
| break; |
| default: |
| throw reportFatalError("Illegal state for DIIs: "+item); |
| } |
| } |
| |
| if(!_fragmentMode) |
| _contentHandler.endDocument(); |
| } |
| |
| private void processCommentAsCharArraySmall() throws SAXException { |
| final int length = readStructure(); |
| final int start = readContentCharactersBuffer(length); |
| processComment(_contentCharactersBuffer, start, length); |
| } |
| |
| /** |
| * Report a fatal error and abort. |
| * |
| * This is necessary to follow the SAX semantics of error handling. |
| */ |
| private SAXParseException reportFatalError(String msg) throws SAXException { |
| SAXParseException spe = new SAXParseException(msg, null); |
| if(_errorHandler!=null) |
| _errorHandler.fatalError(spe); |
| return spe; |
| } |
| |
| private boolean isInscope() { |
| return _buffer.getInscopeNamespaces().size() > 0; |
| } |
| |
| private void processDocument() throws SAXException { |
| while(true) { |
| int item = readEiiState(); |
| switch(item) { |
| case STATE_ELEMENT_U_LN_QN: |
| processElement(readStructureString(), readStructureString(), readStructureString(),isInscope()); |
| break; |
| case STATE_ELEMENT_P_U_LN: |
| { |
| final String prefix = readStructureString(); |
| final String uri = readStructureString(); |
| final String localName = readStructureString(); |
| processElement(uri, localName, getQName(prefix, localName),isInscope()); |
| break; |
| } |
| case STATE_ELEMENT_U_LN: { |
| final String uri = readStructureString(); |
| final String localName = readStructureString(); |
| processElement(uri, localName, localName,isInscope()); |
| break; |
| } |
| case STATE_ELEMENT_LN: |
| { |
| final String localName = readStructureString(); |
| processElement("", localName, localName,isInscope()); |
| break; |
| } |
| case STATE_COMMENT_AS_CHAR_ARRAY_SMALL: |
| processCommentAsCharArraySmall(); |
| break; |
| case STATE_COMMENT_AS_CHAR_ARRAY_MEDIUM: |
| processCommentAsCharArrayMedium(); |
| break; |
| case STATE_COMMENT_AS_CHAR_ARRAY_COPY: |
| processCommentAsCharArrayCopy(); |
| break; |
| case STATE_COMMENT_AS_STRING: |
| processComment(readContentString()); |
| break; |
| case STATE_PROCESSING_INSTRUCTION: |
| processProcessingInstruction(readStructureString(), readStructureString()); |
| break; |
| case STATE_END: |
| return; |
| default: |
| throw reportFatalError("Illegal state for child of DII: "+item); |
| } |
| } |
| } |
| |
| protected void processElement(String uri, String localName, String qName, boolean inscope) throws SAXException { |
| boolean hasAttributes = false; |
| boolean hasNamespaceAttributes = false; |
| int item = peekStructure(); |
| Set<String> prefixSet = inscope ? new HashSet<String>() : Collections.<String>emptySet(); |
| if ((item & TYPE_MASK) == T_NAMESPACE_ATTRIBUTE) { |
| cacheNamespacePrefixStartingIndex(); |
| hasNamespaceAttributes = true; |
| item = processNamespaceAttributes(item, inscope, prefixSet); |
| } |
| if (inscope) { |
| readInscopeNamespaces(prefixSet); |
| } |
| |
| if ((item & TYPE_MASK) == T_ATTRIBUTE) { |
| hasAttributes = true; |
| processAttributes(item); |
| } |
| |
| _contentHandler.startElement(uri, localName, qName, _attributes); |
| |
| if (hasAttributes) { |
| _attributes.clear(); |
| } |
| |
| do { |
| item = readEiiState(); |
| switch(item) { |
| case STATE_ELEMENT_U_LN_QN: |
| processElement(readStructureString(), readStructureString(), readStructureString(), false); |
| break; |
| case STATE_ELEMENT_P_U_LN: |
| { |
| final String p = readStructureString(); |
| final String u = readStructureString(); |
| final String ln = readStructureString(); |
| processElement(u, ln, getQName(p, ln),false); |
| break; |
| } |
| case STATE_ELEMENT_U_LN: { |
| final String u = readStructureString(); |
| final String ln = readStructureString(); |
| processElement(u, ln, ln,false); |
| break; |
| } |
| case STATE_ELEMENT_LN: { |
| final String ln = readStructureString(); |
| processElement("", ln, ln,false); |
| break; |
| } |
| case STATE_TEXT_AS_CHAR_ARRAY_SMALL: |
| { |
| final int length = readStructure(); |
| int start = readContentCharactersBuffer(length); |
| _contentHandler.characters(_contentCharactersBuffer, start, length); |
| break; |
| } |
| case STATE_TEXT_AS_CHAR_ARRAY_MEDIUM: |
| { |
| final int length = readStructure16(); |
| int start = readContentCharactersBuffer(length); |
| _contentHandler.characters(_contentCharactersBuffer, start, length); |
| break; |
| } |
| case STATE_TEXT_AS_CHAR_ARRAY_COPY: |
| { |
| final char[] ch = readContentCharactersCopy(); |
| |
| _contentHandler.characters(ch, 0, ch.length); |
| break; |
| } |
| case STATE_TEXT_AS_STRING: |
| { |
| final String s = readContentString(); |
| _contentHandler.characters(s.toCharArray(), 0, s.length()); |
| break; |
| } |
| case STATE_TEXT_AS_OBJECT: |
| { |
| final CharSequence c = (CharSequence)readContentObject(); |
| final String s = c.toString(); |
| _contentHandler.characters(s.toCharArray(), 0, s.length()); |
| break; |
| } |
| case STATE_COMMENT_AS_CHAR_ARRAY_SMALL: |
| processCommentAsCharArraySmall(); |
| break; |
| case STATE_COMMENT_AS_CHAR_ARRAY_MEDIUM: |
| processCommentAsCharArrayMedium(); |
| break; |
| case STATE_COMMENT_AS_CHAR_ARRAY_COPY: |
| processCommentAsCharArrayCopy(); |
| break; |
| case T_COMMENT_AS_STRING: |
| processComment(readContentString()); |
| break; |
| case STATE_PROCESSING_INSTRUCTION: |
| processProcessingInstruction(readStructureString(), readStructureString()); |
| break; |
| case STATE_END: |
| break; |
| default: |
| throw reportFatalError("Illegal state for child of EII: "+item); |
| } |
| } while(item != STATE_END); |
| |
| _contentHandler.endElement(uri, localName, qName); |
| |
| if (hasNamespaceAttributes) { |
| processEndPrefixMapping(); |
| } |
| } |
| |
| private void readInscopeNamespaces(Set<String> prefixSet) throws SAXException { |
| for (Map.Entry<String, String> e : _buffer.getInscopeNamespaces().entrySet()) { |
| String key = fixNull(e.getKey()); |
| // If the prefix is already written, do not write the prefix |
| if (!prefixSet.contains(key)) { |
| processNamespaceAttribute(key,e.getValue()); |
| } |
| } |
| |
| } |
| |
| private static String fixNull(String s) { |
| if (s == null) return ""; |
| else return s; |
| } |
| private void processCommentAsCharArrayCopy() throws SAXException { |
| final char[] ch = readContentCharactersCopy(); |
| processComment(ch, 0, ch.length); |
| } |
| |
| private void processCommentAsCharArrayMedium() throws SAXException { |
| final int length = readStructure16(); |
| final int start = readContentCharactersBuffer(length); |
| processComment(_contentCharactersBuffer, start, length); |
| } |
| |
| private void processEndPrefixMapping() throws SAXException { |
| final int end = _namespaceAttributesStack[--_namespaceAttributesStackIndex]; |
| // final int start = (_namespaceAttributesStackIndex > 0) ? _namespaceAttributesStack[_namespaceAttributesStackIndex] : 0; |
| final int start = (_namespaceAttributesStackIndex >= 0) ? _namespaceAttributesStartingStack[_namespaceAttributesStackIndex] : 0; |
| |
| for (int i = end - 1; i >= start; i--) { |
| _contentHandler.endPrefixMapping(_namespacePrefixes[i]); |
| } |
| _namespacePrefixesIndex = start; |
| } |
| |
| private int processNamespaceAttributes(int item,boolean collectPrefixes, Set<String> prefixSet) throws SAXException { |
| do { |
| String prefix; |
| switch(getNIIState(item)) { |
| case STATE_NAMESPACE_ATTRIBUTE: |
| // Undeclaration of default namespace |
| processNamespaceAttribute("", ""); |
| if(collectPrefixes) { |
| prefixSet.add(""); |
| } |
| break; |
| case STATE_NAMESPACE_ATTRIBUTE_P: |
| // Undeclaration of namespace |
| prefix = readStructureString(); |
| processNamespaceAttribute(prefix, ""); |
| if(collectPrefixes) { |
| prefixSet.add(prefix); |
| } |
| break; |
| case STATE_NAMESPACE_ATTRIBUTE_P_U: |
| // Declaration with prefix |
| prefix = readStructureString(); |
| processNamespaceAttribute(prefix, readStructureString()); |
| if(collectPrefixes) { |
| prefixSet.add(prefix); |
| } |
| break; |
| case STATE_NAMESPACE_ATTRIBUTE_U: |
| // Default declaration |
| processNamespaceAttribute("", readStructureString()); |
| if(collectPrefixes) { |
| prefixSet.add(""); |
| } |
| break; |
| default: |
| throw reportFatalError("Illegal state: "+item); |
| } |
| readStructure(); |
| |
| item = peekStructure(); |
| } while((item & TYPE_MASK) == T_NAMESPACE_ATTRIBUTE); |
| |
| |
| cacheNamespacePrefixIndex(); |
| |
| return item; |
| } |
| |
| private void processAttributes(int item) throws SAXException { |
| do { |
| switch(getAIIState(item)) { |
| case STATE_ATTRIBUTE_U_LN_QN: |
| _attributes.addAttributeWithQName(readStructureString(), readStructureString(), readStructureString(), readStructureString(), readContentString()); |
| break; |
| case STATE_ATTRIBUTE_P_U_LN: |
| { |
| final String p = readStructureString(); |
| final String u = readStructureString(); |
| final String ln = readStructureString(); |
| _attributes.addAttributeWithQName(u, ln, getQName(p, ln), readStructureString(), readContentString()); |
| break; |
| } |
| case STATE_ATTRIBUTE_U_LN: { |
| final String u = readStructureString(); |
| final String ln = readStructureString(); |
| _attributes.addAttributeWithQName(u, ln, ln, readStructureString(), readContentString()); |
| break; |
| } |
| case STATE_ATTRIBUTE_LN: { |
| final String ln = readStructureString(); |
| _attributes.addAttributeWithQName("", ln, ln, readStructureString(), readContentString()); |
| break; |
| } |
| default: |
| throw reportFatalError("Illegal state: "+item); |
| } |
| readStructure(); |
| |
| item = peekStructure(); |
| } while((item & TYPE_MASK) == T_ATTRIBUTE); |
| } |
| |
| private void processNamespaceAttribute(String prefix, String uri) throws SAXException { |
| _contentHandler.startPrefixMapping(prefix, uri); |
| |
| if (_namespacePrefixesFeature) { |
| // Add the namespace delcaration as an attribute |
| if (prefix != "") { |
| _attributes.addAttributeWithQName(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, prefix, |
| getQName(XMLConstants.XMLNS_ATTRIBUTE, prefix), |
| "CDATA", uri); |
| } else { |
| _attributes.addAttributeWithQName(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, XMLConstants.XMLNS_ATTRIBUTE, |
| XMLConstants.XMLNS_ATTRIBUTE, |
| "CDATA", uri); |
| } |
| } |
| |
| cacheNamespacePrefix(prefix); |
| } |
| |
| private void cacheNamespacePrefix(String prefix) { |
| if (_namespacePrefixesIndex == _namespacePrefixes.length) { |
| final String[] namespaceAttributes = new String[_namespacePrefixesIndex * 3 / 2 + 1]; |
| System.arraycopy(_namespacePrefixes, 0, namespaceAttributes, 0, _namespacePrefixesIndex); |
| _namespacePrefixes = namespaceAttributes; |
| } |
| |
| _namespacePrefixes[_namespacePrefixesIndex++] = prefix; |
| } |
| |
| private void cacheNamespacePrefixIndex() { |
| if (_namespaceAttributesStackIndex == _namespaceAttributesStack.length) { |
| final int[] namespaceAttributesStack = new int[_namespaceAttributesStackIndex * 3 /2 + 1]; |
| System.arraycopy(_namespaceAttributesStack, 0, namespaceAttributesStack, 0, _namespaceAttributesStackIndex); |
| _namespaceAttributesStack = namespaceAttributesStack; |
| } |
| |
| _namespaceAttributesStack[_namespaceAttributesStackIndex++] = _namespacePrefixesIndex; |
| } |
| |
| private void cacheNamespacePrefixStartingIndex() { |
| if (_namespaceAttributesStackIndex == _namespaceAttributesStartingStack.length) { |
| final int[] namespaceAttributesStart = new int[_namespaceAttributesStackIndex * 3 /2 + 1]; |
| System.arraycopy(_namespaceAttributesStartingStack, 0, namespaceAttributesStart, 0, _namespaceAttributesStackIndex); |
| _namespaceAttributesStartingStack = namespaceAttributesStart; |
| } |
| _namespaceAttributesStartingStack[_namespaceAttributesStackIndex] = _namespacePrefixesIndex; |
| } |
| |
| private void processComment(String s) throws SAXException { |
| processComment(s.toCharArray(), 0, s.length()); |
| } |
| |
| private void processComment(char[] ch, int start, int length) throws SAXException { |
| _lexicalHandler.comment(ch, start, length); |
| } |
| |
| private void processProcessingInstruction(String target, String data) throws SAXException { |
| _contentHandler.processingInstruction(target, data); |
| } |
| |
| private static final DefaultWithLexicalHandler DEFAULT_LEXICAL_HANDLER = new DefaultWithLexicalHandler(); |
| } |