Stroap tweaks

This commit is contained in:
Arjen Poutsma
2010-09-10 11:35:40 +00:00
parent abff5a68b4
commit 8f0f0185ac
12 changed files with 264 additions and 203 deletions

View File

@@ -39,7 +39,7 @@ class FaultStroapPayload extends StroapPayload {
@Override
public XMLEventReader getEventReader() {
return fault.getEventReader();
return fault.getEventReader(false);
}
}

View File

@@ -32,13 +32,13 @@ class Stroap11Body extends StroapBody implements Soap11Body {
private static final String ENVELOPE_NAMESPACE_URI = "http://schemas.xmlsoap.org/soap/envelope/";
private QName CLIENT_FAULT_NAME = new QName(ENVELOPE_NAMESPACE_URI, "Client", PREFIX);
private QName CLIENT_FAULT_NAME = new QName(ENVELOPE_NAMESPACE_URI, "Client", DEFAULT_PREFIX);
private QName SERVER_FAULT_NAME = new QName(ENVELOPE_NAMESPACE_URI, "Server", PREFIX);
private QName SERVER_FAULT_NAME = new QName(ENVELOPE_NAMESPACE_URI, "Server", DEFAULT_PREFIX);
private QName MUST_UNDERSTAND_FAULT_NAME = new QName(ENVELOPE_NAMESPACE_URI, "MustUnderstand", PREFIX);
private QName MUST_UNDERSTAND_FAULT_NAME = new QName(ENVELOPE_NAMESPACE_URI, "MustUnderstand", DEFAULT_PREFIX);
private QName VERSION_MISMATCH_FAULT_NAME = new QName(ENVELOPE_NAMESPACE_URI, "VersionMismatch", PREFIX);
private QName VERSION_MISMATCH_FAULT_NAME = new QName(ENVELOPE_NAMESPACE_URI, "VersionMismatch", DEFAULT_PREFIX);
Stroap11Body(StroapMessageFactory messageFactory) {
super(messageFactory);

View File

@@ -26,6 +26,7 @@ import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.ws.soap.SoapFaultDetail;
import org.springframework.ws.soap.soap11.Soap11Fault;
import org.springframework.xml.stream.CompositeXMLEventReader;
import org.springframework.xml.stream.ListBasedXMLEventReader;
/**
@@ -99,17 +100,17 @@ class Stroap11Fault extends StroapFault implements Soap11Fault {
}
@Override
protected XMLEventReader[] getChildEventReaders() {
XMLEventReader[] eventReaders = (faultActor != null) ? new XMLEventReader[2] : new XMLEventReader[3];
eventReaders[0] = faultCode.getEventReader();
eventReaders[1] = faultString.getEventReader();
protected XMLEventReader getChildEventReader() {
XMLEventReader[] eventReaders = (faultActor == null) ? new XMLEventReader[2] : new XMLEventReader[3];
eventReaders[0] = faultCode.getEventReader(false);
eventReaders[1] = faultString.getEventReader(false);
if (faultActor != null) {
eventReaders[2] = faultActor.getEventReader();
eventReaders[2] = faultActor.getEventReader(false);
}
return eventReaders;
return new CompositeXMLEventReader(eventReaders);
}
private static class FaultElement extends StroapContainer {
private static class FaultElement extends StroapElement {
private final Characters characters;
@@ -149,8 +150,8 @@ class Stroap11Fault extends StroapFault implements Soap11Fault {
}
@Override
protected XMLEventReader[] getChildEventReaders() {
return new XMLEventReader[]{new ListBasedXMLEventReader(characters)};
protected XMLEventReader getChildEventReader() {
return new ListBasedXMLEventReader(characters);
}
}
}

View File

@@ -33,7 +33,7 @@ import org.springframework.ws.stream.StreamingPayload;
/**
* @author Arjen Poutsma
*/
abstract class StroapBody extends StroapContainer implements SoapBody {
abstract class StroapBody extends StroapElement implements SoapBody {
private StroapPayload payload;
@@ -105,8 +105,8 @@ abstract class StroapBody extends StroapContainer implements SoapBody {
}
@Override
protected final XMLEventReader[] getChildEventReaders() {
return new XMLEventReader[]{payload.getEventReader()};
protected final XMLEventReader getChildEventReader() {
return payload.getEventReader();
}
@Override

View File

@@ -1,151 +0,0 @@
/*
* Copyright 2005-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.soap.stroap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.events.Attribute;
import javax.xml.stream.events.EndElement;
import javax.xml.stream.events.Namespace;
import javax.xml.stream.events.StartElement;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.xml.stream.CompositeXMLEventReader;
import org.springframework.xml.stream.ListBasedXMLEventReader;
/**
* @author Arjen Poutsma
*/
abstract class StroapContainer extends StroapElement {
static final String PREFIX = "SOAP-ENV";
private StartElement startElement;
private EndElement endElement;
protected StroapContainer(QName name, StroapMessageFactory messageFactory) {
super(messageFactory);
Assert.notNull(name, "'name' must not be null");
if (!StringUtils.hasLength(name.getPrefix())) {
name = new QName(name.getNamespaceURI(), name.getLocalPart(), PREFIX);
}
this.startElement = getEventFactory().createStartElement(name, null, null);
this.endElement = getEventFactory().createEndElement(name, null);
}
protected StroapContainer(StartElement startElement, StroapMessageFactory messageFactory) {
super(messageFactory);
Assert.notNull(startElement, "'startElement' must not be null");
this.startElement = startElement;
this.endElement = getEventFactory().createEndElement(startElement.getName(), startElement.getNamespaces());
}
public final QName getName() {
return getStartElement().getName();
}
@Override
protected XMLEventReader getEventReader() {
XMLEventReader[] childEventReaders = getChildEventReaders();
XMLEventReader[] eventReaders = new XMLEventReader[childEventReaders.length + 2];
eventReaders[0] = new ListBasedXMLEventReader(startElement);
System.arraycopy(childEventReaders, 0, eventReaders, 1, childEventReaders.length);
eventReaders[eventReaders.length - 1] = new ListBasedXMLEventReader(endElement);
return new CompositeXMLEventReader(eventReaders);
}
protected abstract XMLEventReader[] getChildEventReaders();
// Attributes
public final Iterator<QName> getAllAttributes() {
List<QName> result = new LinkedList<QName>();
for (Iterator iterator = getStartElement().getAttributes(); iterator.hasNext();) {
Attribute attribute = (Attribute) iterator.next();
result.add(attribute.getName());
}
return result.iterator();
}
public final String getAttributeValue(QName name) {
Attribute attribute = getStartElement().getAttributeByName(name);
return attribute != null ? attribute.getValue() : null;
}
public final void removeAttribute(QName name) {
List<Attribute> newAttributes = new LinkedList<Attribute>();
for (Iterator iterator = getStartElement().getAttributes(); iterator.hasNext();) {
Attribute attribute = (Attribute) iterator.next();
if (!name.equals(attribute.getName())) {
newAttributes.add(attribute);
}
}
StartElement oldStartElement = getStartElement();
this.startElement = getEventFactory().createStartElement(oldStartElement.getName(), newAttributes.iterator(),
oldStartElement.getNamespaces());
}
public final void addAttribute(QName name, String value) {
List<Attribute> newAttributes = new LinkedList<Attribute>();
for (Iterator iterator = getStartElement().getAttributes(); iterator.hasNext();) {
Attribute attribute = (Attribute) iterator.next();
newAttributes.add(attribute);
}
Attribute newAttribute = getEventFactory().createAttribute(name, value);
newAttributes.add(newAttribute);
StartElement oldStartElement = getStartElement();
this.startElement = getEventFactory().createStartElement(oldStartElement.getName(), newAttributes.iterator(),
oldStartElement.getNamespaces());
}
// Namespaces
public final void addNamespaceDeclaration(String prefix, String namespaceUri) {
List<Namespace> newNamespaces = new LinkedList<Namespace>();
for (Iterator iterator = getStartElement().getNamespaces(); iterator.hasNext();) {
Namespace namespace = (Namespace) iterator.next();
newNamespaces.add(namespace);
}
Namespace newNamespace;
if (StringUtils.hasLength(prefix)) {
newNamespace = getEventFactory().createNamespace(prefix, namespaceUri);
}
else {
newNamespace = getEventFactory().createNamespace(namespaceUri);
}
newNamespaces.add(newNamespace);
StartElement oldStartElement = getStartElement();
this.startElement = getEventFactory()
.createStartElement(oldStartElement.getName(), oldStartElement.getAttributes(),
newNamespaces.iterator());
}
protected final StartElement getStartElement() {
return startElement;
}
protected final EndElement getEndElement() {
return endElement;
}
}

View File

@@ -16,37 +16,71 @@
package org.springframework.ws.soap.stroap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.NoSuchElementException;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLEventFactory;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.Attribute;
import javax.xml.stream.events.EndElement;
import javax.xml.stream.events.Namespace;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;
import javax.xml.transform.Source;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.StaxUtils;
import org.springframework.ws.soap.SoapElement;
import org.springframework.ws.soap.SoapVersion;
import org.springframework.xml.stream.AbstractXMLEventReader;
/**
* @author Arjen Poutsma
*/
abstract class StroapElement implements SoapElement {
protected static final String DEFAULT_PREFIX = "SOAP-ENV";
private final StroapMessageFactory messageFactory;
public StroapElement(StroapMessageFactory messageFactory) {
private StartElement startElement;
private EndElement endElement;
protected StroapElement(QName name, StroapMessageFactory messageFactory) {
this(createStartElement(name, messageFactory), messageFactory);
}
private static StartElement createStartElement(QName name, StroapMessageFactory messageFactory) {
if (!StringUtils.hasLength(name.getPrefix())) {
name = new QName(name.getNamespaceURI(), name.getLocalPart(), DEFAULT_PREFIX);
}
return messageFactory.getEventFactory().createStartElement(name, null, null);
}
protected StroapElement(StartElement startElement, StroapMessageFactory messageFactory) {
Assert.notNull(startElement, "'startElement' must not be null");
Assert.notNull(messageFactory, "'messageFactory' must not be null");
this.messageFactory = messageFactory;
this.startElement = startElement;
this.endElement = getEventFactory().createEndElement(startElement.getName(), startElement.getNamespaces());
}
public final Source getSource() {
return StaxUtils.createCustomStaxSource(getEventReader());
return StaxUtils.createCustomStaxSource(getEventReader(true));
}
protected abstract XMLEventReader getEventReader();
protected XMLEventReader getEventReader(boolean documentEvents) {
return new StroapElementEventReader(documentEvents);
}
public void writeTo(XMLEventWriter eventWriter) throws XMLStreamException {
eventWriter.add(getEventReader());
eventWriter.add(getEventReader(false));
}
protected StroapMessageFactory getMessageFactory() {
@@ -60,4 +94,167 @@ abstract class StroapElement implements SoapElement {
protected SoapVersion getSoapVersion() {
return getMessageFactory().getSoapVersion();
}
public final QName getName() {
return getStartElement().getName();
}
protected abstract XMLEventReader getChildEventReader();
public final Iterator<QName> getAllAttributes() {
List<QName> result = new LinkedList<QName>();
for (Iterator iterator = getStartElement().getAttributes(); iterator.hasNext();) {
Attribute attribute = (Attribute) iterator.next();
result.add(attribute.getName());
}
return result.iterator();
}
public final String getAttributeValue(QName name) {
Attribute attribute = getStartElement().getAttributeByName(name);
return attribute != null ? attribute.getValue() : null;
}
public final void removeAttribute(QName name) {
List<Attribute> newAttributes = new LinkedList<Attribute>();
for (Iterator iterator = getStartElement().getAttributes(); iterator.hasNext();) {
Attribute attribute = (Attribute) iterator.next();
if (!name.equals(attribute.getName())) {
newAttributes.add(attribute);
}
}
StartElement oldStartElement = getStartElement();
this.startElement = getEventFactory().createStartElement(oldStartElement.getName(), newAttributes.iterator(),
oldStartElement.getNamespaces());
}
public final void addAttribute(QName name, String value) {
List<Attribute> newAttributes = new LinkedList<Attribute>();
for (Iterator iterator = getStartElement().getAttributes(); iterator.hasNext();) {
Attribute attribute = (Attribute) iterator.next();
newAttributes.add(attribute);
}
Attribute newAttribute = getEventFactory().createAttribute(name, value);
newAttributes.add(newAttribute);
StartElement oldStartElement = getStartElement();
this.startElement = getEventFactory().createStartElement(oldStartElement.getName(), newAttributes.iterator(),
oldStartElement.getNamespaces());
}
public final void addNamespaceDeclaration(String prefix, String namespaceUri) {
List<Namespace> newNamespaces = new LinkedList<Namespace>();
for (Iterator iterator = getStartElement().getNamespaces(); iterator.hasNext();) {
Namespace namespace = (Namespace) iterator.next();
newNamespaces.add(namespace);
}
Namespace newNamespace;
if (StringUtils.hasLength(prefix)) {
newNamespace = getEventFactory().createNamespace(prefix, namespaceUri);
}
else {
newNamespace = getEventFactory().createNamespace(namespaceUri);
}
newNamespaces.add(newNamespace);
StartElement oldStartElement = getStartElement();
this.startElement = getEventFactory()
.createStartElement(oldStartElement.getName(), oldStartElement.getAttributes(),
newNamespaces.iterator());
}
protected final StartElement getStartElement() {
return startElement;
}
protected final EndElement getEndElement() {
return endElement;
}
private enum EVENT_READER_STATE {
START_DOCUMENT,
START_ELEMENT,
CHILDREN,
END_ELEMENT,
END_DOCUMENT,
DONE
}
private class StroapElementEventReader extends AbstractXMLEventReader {
private EVENT_READER_STATE state;
private boolean documentEvents;
private final XMLEventReader childEventReader;
private StroapElementEventReader(boolean documentEvents) {
this.documentEvents = documentEvents;
state = documentEvents ? EVENT_READER_STATE.START_DOCUMENT : EVENT_READER_STATE.START_ELEMENT;
this.childEventReader = getChildEventReader();
}
public boolean hasNext() {
if (documentEvents && state == EVENT_READER_STATE.DONE) {
return false;
}
else if (!documentEvents && state == EVENT_READER_STATE.END_DOCUMENT) {
return false;
}
else {
return true;
}
}
public XMLEvent nextEvent() throws XMLStreamException {
switch (state) {
case START_DOCUMENT:
state = EVENT_READER_STATE.START_ELEMENT;
return getEventFactory().createStartDocument();
case START_ELEMENT:
state = EVENT_READER_STATE.CHILDREN;
return getStartElement();
case CHILDREN:
if (!childEventReader.hasNext()) {
state = EVENT_READER_STATE.END_ELEMENT;
return nextEvent();
}
return childEventReader.nextEvent();
case END_ELEMENT:
state = EVENT_READER_STATE.END_DOCUMENT;
return getEndElement();
case END_DOCUMENT:
state = EVENT_READER_STATE.DONE;
return getEventFactory().createEndDocument();
case DONE:
throw new NoSuchElementException();
default:
throw new IllegalStateException();
}
}
public XMLEvent peek() throws XMLStreamException {
switch (state) {
case START_DOCUMENT:
return getEventFactory().createStartDocument();
case START_ELEMENT:
return getStartElement();
case CHILDREN:
XMLEvent event = childEventReader.peek();
if (event == null) {
state = EVENT_READER_STATE.END_ELEMENT;
event = getEndElement();
}
return event;
case END_ELEMENT:
return getEndElement();
case END_DOCUMENT:
return getEventFactory().createEndDocument();
case DONE:
return null;
default:
throw new IllegalStateException();
}
}
}
}

View File

@@ -28,11 +28,12 @@ import org.springframework.ws.soap.SoapEnvelope;
import org.springframework.ws.soap.SoapHeader;
import org.springframework.ws.soap.SoapHeaderException;
import org.springframework.ws.soap.SoapVersion;
import org.springframework.xml.stream.CompositeXMLEventReader;
/**
* @author Arjen Poutsma
*/
class StroapEnvelope extends StroapContainer implements SoapEnvelope {
class StroapEnvelope extends StroapElement implements SoapEnvelope {
private static final String LOCAL_NAME = "Envelope";
@@ -112,12 +113,12 @@ class StroapEnvelope extends StroapContainer implements SoapEnvelope {
}
@Override
protected XMLEventReader[] getChildEventReaders() {
protected XMLEventReader getChildEventReader() {
if (header != null) {
return new XMLEventReader[]{header.getEventReader(), body.getEventReader()};
return new CompositeXMLEventReader(header.getEventReader(false), body.getEventReader(false));
}
else {
return new XMLEventReader[]{body.getEventReader()};
return body.getEventReader(false);
}
}

View File

@@ -21,7 +21,7 @@ import org.springframework.ws.soap.SoapFault;
/**
* @author Arjen Poutsma
*/
abstract class StroapFault extends StroapContainer implements SoapFault {
abstract class StroapFault extends StroapElement implements SoapFault {
protected StroapFault(StroapMessageFactory messageFactory) {
super(messageFactory.getSoapVersion().getFaultName(), messageFactory);

View File

@@ -34,11 +34,12 @@ import org.springframework.ws.soap.SoapHeaderElement;
import org.springframework.ws.soap.SoapHeaderException;
import org.springframework.ws.soap.SoapVersion;
import org.springframework.xml.stream.AbstractXMLEventWriter;
import org.springframework.xml.stream.CompositeXMLEventReader;
/**
* @author Arjen Poutsma
*/
abstract class StroapHeader extends StroapContainer implements SoapHeader {
abstract class StroapHeader extends StroapElement implements SoapHeader {
private List<StroapHeaderElement> headerElements = new LinkedList<StroapHeaderElement>();
@@ -107,13 +108,13 @@ abstract class StroapHeader extends StroapContainer implements SoapHeader {
}
@Override
protected XMLEventReader[] getChildEventReaders() {
protected XMLEventReader getChildEventReader() {
XMLEventReader[] eventReaders = new XMLEventReader[headerElements.size()];
for (int i = 0; i < headerElements.size(); i++) {
StroapHeaderElement headerElement = headerElements.get(i);
eventReaders[i] = headerElement.getEventReader();
eventReaders[i] = headerElement.getEventReader(false);
}
return eventReaders;
return new CompositeXMLEventReader(eventReaders);
}
public Result getResult() {

View File

@@ -34,7 +34,7 @@ import org.springframework.xml.stream.ListBasedXMLEventReader;
/**
* @author Arjen Poutsma
*/
class StroapHeaderElement extends StroapContainer implements SoapHeaderElement {
class StroapHeaderElement extends StroapElement implements SoapHeaderElement {
private final List<XMLEvent> events = new LinkedList<XMLEvent>();
@@ -104,8 +104,8 @@ class StroapHeaderElement extends StroapContainer implements SoapHeaderElement {
}
@Override
protected XMLEventReader[] getChildEventReaders() {
return new XMLEventReader[]{new ListBasedXMLEventReader(events)};
protected XMLEventReader getChildEventReader() {
return new ListBasedXMLEventReader(events);
}

View File

@@ -23,6 +23,8 @@ import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.Characters;
import javax.xml.stream.events.XMLEvent;
import org.springframework.util.ClassUtils;
/**
* Abstract base class for <code>XMLEventReader</code>s.
*
@@ -36,7 +38,7 @@ public abstract class AbstractXMLEventReader implements XMLEventReader {
try {
return nextEvent();
}
catch (XMLStreamException e) {
catch (XMLStreamException ex) {
throw new NoSuchElementException();
}
}
@@ -47,7 +49,7 @@ public abstract class AbstractXMLEventReader implements XMLEventReader {
* @throws UnsupportedOperationException when called
*/
public void remove() {
throw new UnsupportedOperationException("remove not supported on AbstractXmlEventReader");
throw new UnsupportedOperationException("remove not supported on " + ClassUtils.getShortName(getClass()));
}
public String getElementText() throws XMLStreamException {

View File

@@ -24,6 +24,8 @@ import javax.xml.stream.events.XMLEvent;
import org.springframework.util.Assert;
/**
* Implementation of {@link XMLEventReader} that combines multiple other {@code XMLEventReader}s.
*
* @author Arjen Poutsma
*/
public class CompositeXMLEventReader extends AbstractXMLEventReader {
@@ -47,11 +49,24 @@ public class CompositeXMLEventReader extends AbstractXMLEventReader {
this.eventReaders = eventReaders.toArray(new XMLEventReader[eventReaders.size()]);
}
public boolean hasNext() {
while (cursor < eventReaders.length) {
if (!atLastEventReader()) {
if (!currentEventReader().hasNext()) {
cursor++;
continue;
}
}
return currentEventReader().hasNext();
}
return false;
}
public XMLEvent nextEvent() throws XMLStreamException {
XMLEvent event = null;
while (cursor < eventReaders.length) {
event = eventReaders[cursor].nextEvent();
if (cursor != eventReaders.length - 1 && event.isEndDocument()) {
event = currentEventReader().nextEvent();
if (!atLastEventReader() && event.isEndDocument()) {
cursor++;
}
else {
@@ -61,24 +76,11 @@ public class CompositeXMLEventReader extends AbstractXMLEventReader {
return event;
}
public boolean hasNext() {
while (cursor < eventReaders.length) {
if (cursor != eventReaders.length - 1) {
if (!eventReaders[cursor].hasNext()) {
cursor++;
continue;
}
}
return eventReaders[cursor].hasNext();
}
return false;
}
public XMLEvent peek() throws XMLStreamException {
XMLEvent event = null;
while (cursor < eventReaders.length) {
event = eventReaders[cursor].peek();
if (cursor != eventReaders.length - 1 && (event == null || event.isEndDocument())) {
event = currentEventReader().peek();
if (!atLastEventReader() && (event == null || event.isEndDocument())) {
cursor++;
}
else {
@@ -88,4 +90,12 @@ public class CompositeXMLEventReader extends AbstractXMLEventReader {
return event;
}
private XMLEventReader currentEventReader() {
return eventReaders[cursor];
}
private boolean atLastEventReader() {
return cursor == eventReaders.length - 1;
}
}