com.sun.xml.stream.buffer.stax.StreamReaderBufferCreator Maven / Gradle / Ivy
Show all versions of webservices-rt Show documentation
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2005-2013 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can
* obtain a copy of the License at
* http://glassfish.java.net/public/CDDL+GPL_1_1.html
* or packager/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package com.sun.xml.stream.buffer.stax;
import com.sun.xml.stream.buffer.MutableXMLStreamBuffer;
import org.jvnet.staxex.Base64Data;
import org.jvnet.staxex.XMLStreamReaderEx;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import java.util.HashMap;
import java.util.Map;
/**
* Create a buffer using an {@link XMLStreamReader}.
*
* TODO: Implement the marking the stream on the element when an ID
* attribute on the element is defined
*/
public class StreamReaderBufferCreator extends StreamBufferCreator {
private int _eventType;
private boolean _storeInScopeNamespacesOnElementFragment;
private Map _inScopePrefixes;
/**
* Create a stream reader buffer creator.
*
* A stream buffer will be created for storing the infoset
* from a stream reader.
*/
public StreamReaderBufferCreator() {
}
/**
* Create a stream reader buffer creator using a mutable stream buffer.
*
* @param buffer the mutable stream buffer.
*/
public StreamReaderBufferCreator(MutableXMLStreamBuffer buffer) {
setBuffer(buffer);
}
/**
* Create the buffer from a stream reader.
*
* The stream reader must be positioned at the start of the document
* or the start of an element.
*
* If the stream is positioned at the start of the document then the
* whole document is stored and after storing the stream will be positioned
* at the end of the document.
*
* If the stream is positioned at the start of an element then the
* element and all its children will be stored and after storing the stream
* will be positioned at the next event after the end of the element.
*
* @return the mutable stream buffer.
* @throws XMLStreamException if the stream reader is not positioned at
* the start of the document or at an element.
*/
public MutableXMLStreamBuffer create(XMLStreamReader reader) throws XMLStreamException {
if (_buffer == null) {
createBuffer();
}
store(reader);
return getXMLStreamBuffer();
}
/**
* Creates the buffer from a stream reader that is an element fragment.
*
* The stream reader will be moved to the position of the next start of
* an element if the stream reader is not already positioned at the start
* of an element.
*
* The element and all its children will be stored and after storing the stream
* will be positioned at the next event after the end of the element.
*
* @param storeInScopeNamespaces true if in-scope namespaces of the element
* fragment should be stored.
* @return the mutable stream buffer.
* @throws XMLStreamException if the stream reader cannot be positioned at
* the start of an element.
*/
public MutableXMLStreamBuffer createElementFragment(XMLStreamReader reader,
boolean storeInScopeNamespaces) throws XMLStreamException {
if (_buffer == null) {
createBuffer();
}
if (!reader.hasNext()) {
return _buffer;
}
_storeInScopeNamespacesOnElementFragment = storeInScopeNamespaces;
_eventType = reader.getEventType();
if (_eventType != XMLStreamReader.START_ELEMENT) {
do {
_eventType = reader.next();
} while(_eventType != XMLStreamReader.START_ELEMENT && _eventType != XMLStreamReader.END_DOCUMENT);
}
if (storeInScopeNamespaces) {
_inScopePrefixes = new HashMap();
}
storeElementAndChildren(reader);
return getXMLStreamBuffer();
}
private void store(XMLStreamReader reader) throws XMLStreamException {
if (!reader.hasNext()) {
return;
}
_eventType = reader.getEventType();
switch (_eventType) {
case XMLStreamReader.START_DOCUMENT:
storeDocumentAndChildren(reader);
break;
case XMLStreamReader.START_ELEMENT:
storeElementAndChildren(reader);
break;
default:
throw new XMLStreamException("XMLStreamReader not positioned at a document or element");
}
increaseTreeCount();
}
private void storeDocumentAndChildren(XMLStreamReader reader) throws XMLStreamException {
storeStructure(T_DOCUMENT);
_eventType = reader.next();
while (_eventType != XMLStreamReader.END_DOCUMENT) {
switch (_eventType) {
case XMLStreamReader.START_ELEMENT:
storeElementAndChildren(reader);
continue;
case XMLStreamReader.COMMENT:
storeComment(reader);
break;
case XMLStreamReader.PROCESSING_INSTRUCTION:
storeProcessingInstruction(reader);
break;
}
_eventType = reader.next();
}
storeStructure(T_END);
}
private void storeElementAndChildren(XMLStreamReader reader) throws XMLStreamException {
if (reader instanceof XMLStreamReaderEx) {
storeElementAndChildrenEx((XMLStreamReaderEx)reader);
} else {
storeElementAndChildrenNoEx(reader);
}
}
private void storeElementAndChildrenEx(XMLStreamReaderEx reader) throws XMLStreamException {
int depth = 1;
if (_storeInScopeNamespacesOnElementFragment) {
storeElementWithInScopeNamespaces(reader);
} else {
storeElement(reader);
}
while(depth > 0) {
_eventType = reader.next();
switch (_eventType) {
case XMLStreamReader.START_ELEMENT:
depth++;
storeElement(reader);
break;
case XMLStreamReader.END_ELEMENT:
depth--;
storeStructure(T_END);
break;
case XMLStreamReader.NAMESPACE:
storeNamespaceAttributes(reader);
break;
case XMLStreamReader.ATTRIBUTE:
storeAttributes(reader);
break;
case XMLStreamReader.SPACE:
case XMLStreamReader.CHARACTERS:
case XMLStreamReader.CDATA: {
CharSequence c = reader.getPCDATA();
if (c instanceof Base64Data) {
storeStructure(T_TEXT_AS_OBJECT);
//Instead of clone the Base64Data, the original Base64Data instance is used here to preserve the DataHandler
storeContentObject(c);
} else {
storeContentCharacters(T_TEXT_AS_CHAR_ARRAY,
reader.getTextCharacters(), reader.getTextStart(),
reader.getTextLength());
}
break;
}
case XMLStreamReader.COMMENT:
storeComment(reader);
break;
case XMLStreamReader.PROCESSING_INSTRUCTION:
storeProcessingInstruction(reader);
break;
}
}
/*
* Move to next item after the end of the element
* that has been stored
*/
_eventType = reader.next();
}
private void storeElementAndChildrenNoEx(XMLStreamReader reader) throws XMLStreamException {
int depth = 1;
if (_storeInScopeNamespacesOnElementFragment) {
storeElementWithInScopeNamespaces(reader);
} else {
storeElement(reader);
}
while(depth > 0) {
_eventType = reader.next();
switch (_eventType) {
case XMLStreamReader.START_ELEMENT:
depth++;
storeElement(reader);
break;
case XMLStreamReader.END_ELEMENT:
depth--;
storeStructure(T_END);
break;
case XMLStreamReader.NAMESPACE:
storeNamespaceAttributes(reader);
break;
case XMLStreamReader.ATTRIBUTE:
storeAttributes(reader);
break;
case XMLStreamReader.SPACE:
case XMLStreamReader.CHARACTERS:
case XMLStreamReader.CDATA: {
storeContentCharacters(T_TEXT_AS_CHAR_ARRAY,
reader.getTextCharacters(), reader.getTextStart(),
reader.getTextLength());
break;
}
case XMLStreamReader.COMMENT:
storeComment(reader);
break;
case XMLStreamReader.PROCESSING_INSTRUCTION:
storeProcessingInstruction(reader);
break;
}
}
/*
* Move to next item after the end of the element
* that has been stored
*/
_eventType = reader.next();
}
private void storeElementWithInScopeNamespaces(XMLStreamReader reader) {
storeQualifiedName(T_ELEMENT_LN,
reader.getPrefix(), reader.getNamespaceURI(), reader.getLocalName());
if (reader.getNamespaceCount() > 0) {
storeNamespaceAttributes(reader);
}
if (reader.getAttributeCount() > 0) {
storeAttributes(reader);
}
}
private void storeElement(XMLStreamReader reader) {
storeQualifiedName(T_ELEMENT_LN,
reader.getPrefix(), reader.getNamespaceURI(), reader.getLocalName());
if (reader.getNamespaceCount() > 0) {
storeNamespaceAttributes(reader);
}
if (reader.getAttributeCount() > 0) {
storeAttributes(reader);
}
}
/**
* A low level method a create a structure element explicitly. This is useful when xsb is
* created from a fragment's XMLStreamReader and inscope namespaces can be passed using
* this method. Note that there is no way to enumerate namespaces from XMLStreamReader.
*
* For e.g: Say the SOAP message is as follows
*
* ...
*
* when xsb is to be created using a reader that is at tag, the inscope
* namespace like 'n1' can be passed using this method.
*
* WARNING: Instead of using this, try other methods(if you don't know what you are
* doing).
*
* @param ns an array of the even length of the form { prefix0, uri0, prefix1, uri1, ... }.
*/
public void storeElement(String nsURI, String localName, String prefix, String[] ns) {
storeQualifiedName(T_ELEMENT_LN, prefix, nsURI, localName);
storeNamespaceAttributes(ns);
}
/**
* A low level method a create a structure element explicitly. This is
* required to support {@link #storeElement} method.
*
* WARNING: Instead of using this, try other methods(if you don't know what
* you are doing).
*/
public void storeEndElement() {
storeStructure(T_END);
}
private void storeNamespaceAttributes(XMLStreamReader reader) {
int count = reader.getNamespaceCount();
for (int i = 0; i < count; i++) {
storeNamespaceAttribute(reader.getNamespacePrefix(i), reader.getNamespaceURI(i));
}
}
/**
* @param ns an array of the even length of the form { prefix0, uri0, prefix1, uri1, ... }.
*/
private void storeNamespaceAttributes(String[] ns) {
for (int i = 0; i < ns.length; i=i+2) {
storeNamespaceAttribute(ns[i], ns[i+1]);
}
}
private void storeAttributes(XMLStreamReader reader) {
int count = reader.getAttributeCount();
for (int i = 0; i < count; i++) {
storeAttribute(reader.getAttributePrefix(i), reader.getAttributeNamespace(i), reader.getAttributeLocalName(i),
reader.getAttributeType(i), reader.getAttributeValue(i));
}
}
private void storeComment(XMLStreamReader reader) {
storeContentCharacters(T_COMMENT_AS_CHAR_ARRAY,
reader.getTextCharacters(), reader.getTextStart(), reader.getTextLength());
}
private void storeProcessingInstruction(XMLStreamReader reader) {
storeProcessingInstruction(reader.getPITarget(), reader.getPIData());
}
}