Fixed SWS-107: Support JAXB's MTOM/XOP/MIME support

This commit is contained in:
Arjen Poutsma
2007-05-13 00:26:02 +00:00
parent 5338aff8d9
commit 0e69ef4e93
49 changed files with 723 additions and 589 deletions

View File

@@ -41,6 +41,11 @@
<groupId>stax</groupId>
<artifactId>stax-api</artifactId>
</dependency>
<!-- JEE dependencies -->
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
</dependency>
<!-- Test dependencies -->
<dependency>
<groupId>org.easymock</groupId>

View File

@@ -0,0 +1,96 @@
/*
* Copyright 2007 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.mime;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import org.springframework.core.io.InputStreamSource;
import org.springframework.core.io.Resource;
import org.springframework.util.Assert;
/**
* Abstract implementation of the {@link MimeMessage} interface. Contains convenient default implementations.
*
* @author Arjen Poutsma
*/
public abstract class AbstractMimeMessage implements MimeMessage {
public final Attachment addAttachment(String contentId, File file) throws AttachmentException {
Assert.hasLength(contentId, "contentId must not be empty");
Assert.notNull(file, "File must not be null");
DataHandler dataHandler = new DataHandler(new FileDataSource(file));
return addAttachment(contentId, dataHandler);
}
public final Attachment addAttachment(String contentId, InputStreamSource inputStreamSource, String contentType) {
Assert.hasLength(contentId, "contentId must not be empty");
Assert.notNull(inputStreamSource, "InputStreamSource must not be null");
if (inputStreamSource instanceof Resource && ((Resource) inputStreamSource).isOpen()) {
throw new IllegalArgumentException("Passed-in Resource contains an open stream: invalid argument. " +
"MIME requires an InputStreamSource that creates a fresh stream for every call.");
}
DataHandler dataHandler = new DataHandler(new InputStreamSourceDataSource(inputStreamSource, contentType));
return addAttachment(contentId, dataHandler);
}
/**
* Activation framework <code>DataSource</code> that wraps a Spring <code>InputStreamSource</code>.
*
* @author Arjen Poutsma
*/
private static class InputStreamSourceDataSource implements DataSource {
private final InputStreamSource inputStreamSource;
private final String contentType;
public InputStreamSourceDataSource(InputStreamSource inputStreamSource, String contentType) {
this.inputStreamSource = inputStreamSource;
this.contentType = contentType;
}
public InputStream getInputStream() throws IOException {
return inputStreamSource.getInputStream();
}
public OutputStream getOutputStream() {
throw new UnsupportedOperationException("Read-only javax.activation.DataSource");
}
public String getContentType() {
return contentType;
}
public String getName() {
if (inputStreamSource instanceof Resource) {
Resource resource = (Resource) inputStreamSource;
return resource.getFilename();
}
else {
throw new UnsupportedOperationException("DataSource name not available");
}
}
}
}

View File

@@ -14,36 +14,27 @@
* limitations under the License.
*/
package org.springframework.ws.soap;
package org.springframework.ws.mime;
import java.io.IOException;
import java.io.InputStream;
import javax.activation.DataHandler;
/**
* Represents an attachment to a <code>SoapMessage</code>.
* Represents an attachment to a {@link org.springframework.ws.mime.MimeMessage}
*
* @author Arjen Poutsma
* @see SoapMessage#getAttachments()
* @see SoapMessage#addAttachment(java.io.File)
* @see SoapMessage#addAttachment(org.springframework.core.io.InputStreamSource, String)
* @see MimeMessage#getAttachments()
* @see MimeMessage#addAttachment
*/
public interface Attachment {
/**
* Returns the identifier of the attachment. Depending on the implementation used, this may be a MIME
* <code>Content-Id</code> header, a DIME ID, etc.
* Returns the content identifier of the attachment.
*
* @return the attachment identifier, or <code>null</code> if empty or not defined
* @return the content id, or <code>null</code> if empty or not defined
*/
String getId();
/**
* Sets the identifier of the attachment. Depending on the implementation used, this may be a MIME
* <code>Content-Id</code> header, a DIME ID, etc.
*
* @param id the new attachment identifier, or <code>null</code> if empty or not defined
*/
void setId(String id);
String getContentId();
/**
* Returns the content type of the attachment.
@@ -62,9 +53,16 @@ public interface Attachment {
InputStream getInputStream() throws IOException;
/**
* Returns the size of the attachment in bytes.
* Returns the size of the attachment in bytes. Returns <code>-1</code> if the size cannot be determined.
*
* @return the size of the attachment, or <code>0</code> if empty
* @return the size of the attachment, <code>0</code> if empty, or <code>-1</code> if the size cannot be determined
*/
long getSize();
/**
* Returns the data handler of the attachment.
*
* @return the data handler of the attachment
*/
DataHandler getDataHandler();
}

View File

@@ -14,15 +14,17 @@
* limitations under the License.
*/
package org.springframework.ws.soap;
package org.springframework.ws.mime;
import org.springframework.ws.WebServiceMessageException;
/**
* Exception thrown when a SOAP attachment could not be accessed.
* Exception thrown when a MIME attachment could not be accessed.
*
* @author Arjen Poutsma
* @see Attachment
*/
public class AttachmentException extends SoapMessageException {
public class AttachmentException extends WebServiceMessageException {
public AttachmentException(String msg) {
super(msg);

View File

@@ -0,0 +1,82 @@
package org.springframework.ws.mime;
import java.io.File;
import java.util.Iterator;
import javax.activation.DataHandler;
import org.springframework.core.io.InputStreamSource;
import org.springframework.ws.WebServiceMessage;
/**
* Represents a Web service message with MIME attachments. Attachments can be added as a file, an {@link
* InputStreamSource}, or a {@link DataHandler}.
*
* @author Arjen Poutsma
* @see Attachment
*/
public interface MimeMessage extends WebServiceMessage {
/**
* Indicates whether this message is a XOP package.
*
* @return <code>true</code> when the constraints specified in <a href="http://www.w3.org/TR/2005/REC-xop10-20050125/#identifying_xop_documents">Identifying
* XOP Documents</a> are met.
* @see <a href="http://www.w3.org/TR/2005/REC-xop10-20050125/#xop_packages">XOP Packages</a>
*/
boolean isXopPackage();
/**
* Returns the <code>Attachment</code> with the specified content Id.
*
* @return the attachment with the specified content id; or <code>null</code> if it cannot be found
* @throws AttachmentException in case of errors
*/
Attachment getAttachment(String contentId) throws AttachmentException;
/**
* Returns an <code>Iterator</code> over all <code>Attachment</code>s that are part of this message.
*
* @return an iterator over all attachments
* @throws AttachmentException in case of errors
* @see Attachment
*/
Iterator getAttachments() throws AttachmentException;
/**
* Add an attachment to the message, taking the content from a {@link File}.
* <p/>
* The content type will be determined by the name of the given content file. Do not use this for temporary files
* with arbitrary filenames (possibly ending in ".tmp" or the like)!
*
* @param contentId the content Id of the attachment
* @param file the file to take the content from
* @return the added attachment
* @throws AttachmentException in case of errors
*/
Attachment addAttachment(String contentId, File file) throws AttachmentException;
/**
* Add an attachment to the message, taking the content from an {@link InputStreamSource}.
* <p/>
* Note that the stream returned by the source needs to be a <em>fresh one on each call</em>, as underlying
* implementations can invoke {@link InputStreamSource#getInputStream()} multiple times.
*
* @param contentId the content Id of the attachment
* @param inputStreamSource the resource to take the content from (all of Spring's Resource implementations can be
* passed in here)
* @param contentType the content type to use for the element
* @return the added attachment
* @throws AttachmentException in case of errors
* @see org.springframework.core.io.Resource
*/
Attachment addAttachment(String contentId, InputStreamSource inputStreamSource, String contentType);
/**
* Add an attachment to the message, taking the content from a {@link DataHandler}.
*
* @param dataHandler the data handler to take the content from
* @return the added attachment
* @throws AttachmentException in case of errors
*/
Attachment addAttachment(String contentId, DataHandler dataHandler);
}

View File

@@ -0,0 +1,6 @@
<html>
<body>
Provides MIME functionality for use the Spring Web Services framework. Contains the Attachment and MimeMessage and
related interfaces.
</body>
</html>

View File

@@ -19,54 +19,44 @@ package org.springframework.ws.soap;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import org.springframework.ws.mime.AbstractMimeMessage;
/**
* Abstract implementation of the <code>SoapMessage</code> interface.
* Abstract implementation of the {@link SoapMessage} interface. Contains convenient default implementations.
*
* @author Arjen Poutsma
*/
public abstract class AbstractSoapMessage implements SoapMessage {
public abstract class AbstractSoapMessage extends AbstractMimeMessage implements SoapMessage {
private SoapVersion version;
/**
* Returns <code>getEnvelope().getBody()</code>.
*/
public SoapBody getSoapBody() {
/** Returns <code>getEnvelope().getBody()</code>. */
public final SoapBody getSoapBody() {
return getEnvelope().getBody();
}
/**
* Returns <code>getEnvelope().getHeader()</code>.
*/
public SoapHeader getSoapHeader() {
/** Returns <code>getEnvelope().getHeader()</code>. */
public final SoapHeader getSoapHeader() {
return getEnvelope().getHeader();
}
/**
* Returns <code>getSoapBody().getPayloadSource()</code>.
*/
public Source getPayloadSource() {
/** Returns <code>getSoapBody().getPayloadSource()</code>. */
public final Source getPayloadSource() {
return getSoapBody().getPayloadSource();
}
/**
* Returns <code>getSoapBody().getPayloadResult()</code>.
*/
public Result getPayloadResult() {
/** Returns <code>getSoapBody().getPayloadResult()</code>. */
public final Result getPayloadResult() {
return getSoapBody().getPayloadResult();
}
/**
* Returns <code>getSoapBody().hasFault()</code>.
*/
public boolean hasFault() {
/** Returns <code>getSoapBody().hasFault()</code>. */
public final boolean hasFault() {
return getSoapBody().hasFault();
}
/**
* Returns <code>getSoapBody().getFault().getFaultStringOrReason()</code>.
*/
public String getFaultReason() {
/** Returns <code>getSoapBody().getFault().getFaultStringOrReason()</code>. */
public final String getFaultReason() {
if (hasFault()) {
return getSoapBody().getFault().getFaultStringOrReason();
}

View File

@@ -16,11 +16,7 @@
package org.springframework.ws.soap;
import java.io.File;
import java.util.Iterator;
import org.springframework.core.io.InputStreamSource;
import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.mime.MimeMessage;
/**
* Represents an abstraction for SOAP messages, providing access to a SOAP Envelope. The contents of the SOAP body can
@@ -32,7 +28,7 @@ import org.springframework.ws.WebServiceMessage;
* @see #getPayloadResult()
* @see #getEnvelope()
*/
public interface SoapMessage extends WebServiceMessage {
public interface SoapMessage extends MimeMessage {
/** Returns the <code>SoapEnvelope</code> associated with this <code>SoapMessage</code>. */
SoapEnvelope getEnvelope() throws SoapEnvelopeException;
@@ -76,51 +72,4 @@ public interface SoapMessage extends WebServiceMessage {
*/
SoapVersion getVersion();
/**
* Returns the <code>Attachment</code> with the specified content Id.
*
* @return the attachment with the specified content id; or <code>null</code> if it cannot be found
* @throws AttachmentException in case of errors
*/
Attachment getAttachment(String contentId) throws AttachmentException;
/**
* Returns an <code>Iterator</code> over all <code>Attachment</code>s that are part of this
* <code>SoapMessage</code>.
*
* @return an iterator over all attachments
* @throws AttachmentException in case of errors
* @see Attachment
*/
Iterator getAttachments() throws AttachmentException;
/**
* Add an attachment to the <code>SoapMessage</code>, taking the content from a <code>java.io.File</code>.
* <p/>
* The content type will be determined by the name of the given content file. Do not use this for temporary files
* with arbitrary filenames (possibly ending in ".tmp" or the like)!
*
* @param file the File resource to take the content from
* @return the added attachment
* @throws AttachmentException in case of errors
* @see #addAttachment(InputStreamSource,String)
*/
Attachment addAttachment(File file) throws AttachmentException;
/**
* Add an attachment to the <code>SoapMessage</code>, taking the content from an
* <code>org.springframework.core.io.InputStreamResource</code>.
* <p/>
* Note that the <code>InputStream</code> returned by the source needs to be a <em>fresh one on each call</em>, as
* underlying implementations can invoke <code>getInputStream()</code> multiple times.
*
* @param inputStreamSource the resource to take the content from (all of Spring's Resource implementations can be
* passed in here)
* @param contentType the content type to use for the element
* @return the added attachment
* @throws AttachmentException in case of errors
* @see #addAttachment(java.io.File)
* @see org.springframework.core.io.Resource
*/
Attachment addAttachment(InputStreamSource inputStreamSource, String contentType);
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright 2007 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;
import org.springframework.ws.WebServiceMessageFactory;
/**
* Sub-interface of {@link WebServiceMessageFactory} which contains SOAP-specific properties and methods.
* <p/>
* The <code>soapVersion</code> property can be used to indicate the SOAP version of the factory. By default, the
* version is {@link SoapVersion#SOAP_11}.
*
* @author Arjen Poutsma
*/
public interface SoapMessageFactory extends WebServiceMessageFactory {
/**
* Sets the SOAP Version used by this factory.
*
* @return the version constant
* @see SoapVersion#SOAP_11
* @see SoapVersion#SOAP_12
*/
void setSoapVersion(SoapVersion version);
}

View File

@@ -0,0 +1,64 @@
/*
* Copyright 2007 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.axiom;
import java.io.IOException;
import java.io.InputStream;
import javax.activation.DataHandler;
import org.springframework.util.Assert;
import org.springframework.ws.mime.Attachment;
/**
* Axiom-specific implementation of {@link org.springframework.ws.mime.Attachment}
*
* @author Arjen Poutsma
*/
class AxiomAttachment implements Attachment {
private final DataHandler dataHandler;
private final String contentId;
public AxiomAttachment(String contentId, DataHandler dataHandler) {
Assert.notNull(contentId, "contentId must not be null");
Assert.notNull(dataHandler, "dataHandler must not be null");
this.contentId = contentId;
this.dataHandler = dataHandler;
}
public String getContentId() {
return contentId;
}
public String getContentType() {
return dataHandler.getContentType();
}
public InputStream getInputStream() throws IOException {
return dataHandler.getInputStream();
}
public long getSize() {
// Axiom does not support getting the size of attachments.
return -1;
}
public DataHandler getDataHandler() {
return dataHandler;
}
}

View File

@@ -16,11 +16,9 @@
package org.springframework.ws.soap.axiom;
import org.springframework.ws.soap.AttachmentException;
import org.springframework.ws.mime.AttachmentException;
/**
* @author Arjen Poutsma
*/
/** @author Arjen Poutsma */
public class AxiomAttachmentException extends AttachmentException {
public AxiomAttachmentException(String msg) {

View File

@@ -16,9 +16,7 @@
package org.springframework.ws.soap.axiom;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Iterator;
import javax.activation.DataHandler;
@@ -27,24 +25,22 @@ import javax.xml.stream.XMLStreamException;
import org.apache.axiom.attachments.Attachments;
import org.apache.axiom.om.OMException;
import org.apache.axiom.om.OMOutputFormat;
import org.apache.axiom.om.impl.MTOMConstants;
import org.apache.axiom.soap.SOAPEnvelope;
import org.apache.axiom.soap.SOAPFactory;
import org.apache.axiom.soap.SOAPMessage;
import org.apache.axiom.soap.SOAPProcessingException;
import org.springframework.core.io.InputStreamSource;
import org.springframework.util.Assert;
import org.springframework.ws.mime.Attachment;
import org.springframework.ws.soap.AbstractSoapMessage;
import org.springframework.ws.soap.Attachment;
import org.springframework.ws.soap.SoapEnvelope;
import org.springframework.ws.soap.SoapMessage;
import org.springframework.ws.soap.SoapVersion;
import org.springframework.ws.transport.TransportOutputStream;
/**
* AXIOM-specific implementation of the {@link SoapMessage} interface. Created via the {@link AxiomSoapMessageFactory}.
* <p/>
* Note that Axiom does support reading SOAP with Attachments (SwA) messages, but does not support creating them
* manually. Hence, the <code>addAttachment</code> methods throw an <code>UnsupportedOperationException</code>.
* AXIOM-specific implementation of the {@link SoapMessage} interface. Created via the {@link AxiomSoapMessageFactory},
* wraps a {@link SOAPMessage}.
*
* @author Arjen Poutsma
* @see SOAPMessage
@@ -72,7 +68,7 @@ public class AxiomSoapMessage extends AbstractSoapMessage {
SOAPEnvelope soapEnvelope = soapFactory.getDefaultEnvelope();
axiomFactory = soapFactory;
axiomMessage = axiomFactory.createSOAPMessage(soapEnvelope, soapEnvelope.getBuilder());
attachments = null;
attachments = new Attachments();
payloadCaching = true;
soapAction = "";
}
@@ -87,7 +83,7 @@ public class AxiomSoapMessage extends AbstractSoapMessage {
public AxiomSoapMessage(SOAPMessage soapMessage, String soapAction, boolean payloadCaching) {
axiomMessage = soapMessage;
axiomFactory = (SOAPFactory) soapMessage.getSOAPEnvelope().getOMFactory();
attachments = null;
this.attachments = new Attachments();
this.soapAction = soapAction;
this.payloadCaching = payloadCaching;
}
@@ -141,6 +137,16 @@ public class AxiomSoapMessage extends AbstractSoapMessage {
}
}
public boolean isXopPackage() {
try {
return MTOMConstants.MTOM_TYPE.equals(attachments.getAttachmentSpecType());
}
catch (NullPointerException ex) {
// gotta love Axis2
return false;
}
}
public Attachment getAttachment(String contentId) {
DataHandler dataHandler = attachments.getDataHandler(contentId);
return dataHandler != null ? new AxiomAttachment(contentId, dataHandler) : null;
@@ -150,23 +156,11 @@ public class AxiomSoapMessage extends AbstractSoapMessage {
return new AxiomAttachmentIterator();
}
/**
* Axiom does not support adding attachments manually.
*
* @throws UnsupportedOperationException always
*/
public Attachment addAttachment(File file) throws UnsupportedOperationException {
throw new UnsupportedOperationException("Axiom does not support adding SwA attachments.");
}
/**
* Axiom does not support adding attachments manually.
*
* @throws UnsupportedOperationException always
*/
public Attachment addAttachment(InputStreamSource inputStreamSource, String contentType)
throws UnsupportedOperationException {
throw new UnsupportedOperationException("Axiom does not support adding SwA attachments.");
public Attachment addAttachment(String contentId, DataHandler dataHandler) {
Assert.hasLength(contentId, "contentId must not be empty");
Assert.notNull(dataHandler, "dataHandler must not be null");
attachments.addDataHandler(contentId, dataHandler);
return new AxiomAttachment(contentId, dataHandler);
}
public void writeTo(OutputStream outputStream) throws IOException {
@@ -176,6 +170,9 @@ public class AxiomSoapMessage extends AbstractSoapMessage {
OMOutputFormat format = new OMOutputFormat();
format.setCharSetEncoding(charsetEncoding);
format.setSOAP11(getVersion() == SoapVersion.SOAP_11);
if (!attachments.getContentIDSet().isEmpty()) {
format.setDoingSWA(true);
}
if (outputStream instanceof TransportOutputStream) {
TransportOutputStream transportOutputStream = (TransportOutputStream) outputStream;
String contentType = format.getContentType();
@@ -194,41 +191,6 @@ public class AxiomSoapMessage extends AbstractSoapMessage {
}
}
/** Axiom-specific implementation of <code>org.springframework.ws.soap.Attachment</code> */
private static class AxiomAttachment implements Attachment {
private final DataHandler dataHandler;
private final String contentId;
public AxiomAttachment(String contentId, DataHandler dataHandler) {
Assert.notNull(contentId, "contentId must not be null");
Assert.notNull(dataHandler, "dataHandler must not be null");
this.contentId = contentId;
this.dataHandler = dataHandler;
}
public String getId() {
return contentId;
}
public void setId(String id) {
throw new UnsupportedOperationException("Axiom does not support setting the Content-ID of attachments.");
}
public String getContentType() {
return dataHandler.getContentType();
}
public InputStream getInputStream() throws IOException {
return dataHandler.getInputStream();
}
public long getSize() {
throw new UnsupportedOperationException("Axiom does not support getting the size of attachments.");
}
}
private class AxiomAttachmentIterator implements Iterator {
private final Iterator iterator;

View File

@@ -39,7 +39,8 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.StringUtils;
import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.WebServiceMessageFactory;
import org.springframework.ws.soap.SoapMessageFactory;
import org.springframework.ws.soap.SoapVersion;
import org.springframework.ws.transport.TransportInputStream;
/**
@@ -62,7 +63,7 @@ import org.springframework.ws.transport.TransportInputStream;
* @see AxiomSoapMessage
* @see #setPayloadCaching(boolean)
*/
public class AxiomSoapMessageFactory implements WebServiceMessageFactory, InitializingBean {
public class AxiomSoapMessageFactory implements SoapMessageFactory, InitializingBean {
private static final String CHAR_SET_ENCODING = "charset";
@@ -80,9 +81,13 @@ public class AxiomSoapMessageFactory implements WebServiceMessageFactory, Initia
private boolean payloadCaching = true;
private SOAP11Factory soap11Factory = new SOAP11Factory();
// use SOAP 1.1 by default
private SOAPFactory soapFactory = new SOAP11Factory();
private SOAP12Factory soap12Factory = new SOAP12Factory();
/** Default constructor. */
public AxiomSoapMessageFactory() {
inputFactory = XMLInputFactory.newInstance();
}
/**
* Indicates whether the SOAP Body payload should be cached or not. Default is <code>true</code>. Setting this to
@@ -93,8 +98,17 @@ public class AxiomSoapMessageFactory implements WebServiceMessageFactory, Initia
this.payloadCaching = payloadCaching;
}
public AxiomSoapMessageFactory() {
inputFactory = XMLInputFactory.newInstance();
public void setSoapVersion(SoapVersion version) {
if (SoapVersion.SOAP_11 == version) {
soapFactory = new SOAP11Factory();
}
else if (SoapVersion.SOAP_12 == version) {
soapFactory = new SOAP12Factory();
}
else {
throw new IllegalArgumentException(
"Invalid version [" + version + "]. " + "Expected the SOAP_11 or SOAP_12 constant");
}
}
public void afterPropertiesSet() throws Exception {
@@ -104,27 +118,19 @@ public class AxiomSoapMessageFactory implements WebServiceMessageFactory, Initia
}
public WebServiceMessage createWebServiceMessage() {
return new AxiomSoapMessage(soap11Factory);
return new AxiomSoapMessage(soapFactory);
}
public WebServiceMessage createWebServiceMessage(InputStream inputStream) throws IOException {
String contentType = null;
String soapAction = "";
if (inputStream instanceof TransportInputStream) {
TransportInputStream transportInputStream = (TransportInputStream) inputStream;
Iterator iterator = transportInputStream.getHeaders(CONTENT_TYPE_HEADER);
if (iterator.hasNext()) {
contentType = (String) iterator.next();
}
iterator = transportInputStream.getHeaders(SOAP_ACTION_HEADER);
if (iterator.hasNext()) {
soapAction = (String) iterator.next();
}
if (!(inputStream instanceof TransportInputStream)) {
throw new IllegalArgumentException("AxiomSoapMessageFactory requires a TransportInputStream");
}
TransportInputStream transportInputStream = (TransportInputStream) inputStream;
String contentType = getHeaderValue(transportInputStream, CONTENT_TYPE_HEADER);
if (!StringUtils.hasLength(contentType)) {
// fall back to SOAP 1.1 as a default
contentType = SOAP11Constants.SOAP_11_CONTENT_TYPE;
throw new IllegalArgumentException("TransportInputStream contains no Content-Type header");
}
String soapAction = getHeaderValue(transportInputStream, SOAP_ACTION_HEADER);
try {
if (isMultiPartRelated(contentType)) {
return createMultiPartAxiomSoapMessage(inputStream, contentType, soapAction);
@@ -141,6 +147,15 @@ public class AxiomSoapMessageFactory implements WebServiceMessageFactory, Initia
}
}
private String getHeaderValue(TransportInputStream transportInputStream, String header) throws IOException {
String contentType = null;
Iterator iterator = transportInputStream.getHeaders(header);
if (iterator.hasNext()) {
contentType = (String) iterator.next();
}
return contentType;
}
private boolean isMultiPartRelated(String contentType) {
return contentType.indexOf(MULTI_PART_RELATED_CONTENT_TYPE) != -1;
}
@@ -149,7 +164,6 @@ public class AxiomSoapMessageFactory implements WebServiceMessageFactory, Initia
private WebServiceMessage createAxiomSoapMessage(InputStream inputStream, String contentType, String soapAction)
throws XMLStreamException {
XMLStreamReader reader = inputFactory.createXMLStreamReader(inputStream, getCharSetEncoding(contentType));
SOAPFactory soapFactory = getSoapFactory(contentType);
String envelopeNamespace = getSoapEnvelopeNamespace(contentType);
StAXSOAPModelBuilder builder = new StAXSOAPModelBuilder(reader, soapFactory, envelopeNamespace);
SOAPMessage soapMessage = builder.getSoapMessage();
@@ -161,35 +175,22 @@ public class AxiomSoapMessageFactory implements WebServiceMessageFactory, Initia
String contentType,
String soapAction) throws XMLStreamException {
Attachments attachments = new Attachments(inputStream, contentType);
if (!(attachments.getAttachmentSpecType().equals(MTOMConstants.SWA_TYPE) ||
attachments.getAttachmentSpecType().equals(MTOMConstants.MTOM_TYPE))) {
throw new AxiomSoapMessageCreationException(
"Unknown attachment type: [" + attachments.getAttachmentSpecType() + "]");
}
XMLStreamReader reader = inputFactory.createXMLStreamReader(attachments.getSOAPPartInputStream(),
getCharSetEncoding(attachments.getSOAPPartContentType()));
StAXSOAPModelBuilder builder = null;
String envelopeNamespace = getSoapEnvelopeNamespace(contentType);
if (attachments.getAttachmentSpecType().equals(MTOMConstants.SWA_TYPE)) {
SOAPFactory soapFactory = getSoapFactory(attachments.getSOAPPartContentType());
if (MTOMConstants.SWA_TYPE.equals(attachments.getAttachmentSpecType()) ||
MTOMConstants.SWA_TYPE_12.equals(attachments.getAttachmentSpecType())) {
builder = new StAXSOAPModelBuilder(reader, soapFactory, envelopeNamespace);
}
else if (attachments.getAttachmentSpecType().equals(MTOMConstants.MTOM_TYPE)) {
else if (MTOMConstants.MTOM_TYPE.equals(attachments.getAttachmentSpecType())) {
builder = new MTOMStAXSOAPModelBuilder(reader, attachments, envelopeNamespace);
}
return new AxiomSoapMessage(builder.getSoapMessage(), attachments, soapAction, payloadCaching);
}
private SOAPFactory getSoapFactory(String contentType) {
if (contentType.indexOf(SOAP11Constants.SOAP_11_CONTENT_TYPE) != -1) {
return soap11Factory;
}
else if (contentType.indexOf(SOAP12Constants.SOAP_12_CONTENT_TYPE) != -1) {
return soap12Factory;
}
else {
throw new AxiomSoapMessageCreationException("Unknown content type '" + contentType + "'");
throw new AxiomSoapMessageCreationException(
"Unknown attachment type: [" + attachments.getAttachmentSpecType() + "]");
}
return new AxiomSoapMessage(builder.getSoapMessage(), attachments, soapAction, payloadCaching);
}
private String getSoapEnvelopeNamespace(String contentType) {

View File

@@ -1,58 +0,0 @@
/*
* Copyright 2006 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.saaj;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.activation.DataSource;
import org.springframework.core.io.InputStreamSource;
/**
* Activation framework <code>DataSource</code> that wraps a Spring <code>InputStreamSource</code>.
*
* @author Arjen Poutsma
*/
class InputStreamSourceDataSource implements DataSource {
private final InputStreamSource inputStreamSource;
private final String contentType;
public InputStreamSourceDataSource(InputStreamSource inputStreamSource, String contentType) {
this.inputStreamSource = inputStreamSource;
this.contentType = contentType;
}
public InputStream getInputStream() throws IOException {
return inputStreamSource.getInputStream();
}
public OutputStream getOutputStream() {
throw new UnsupportedOperationException("Read-only javax.activation.DataSource");
}
public String getContentType() {
return contentType;
}
public String getName() {
throw new UnsupportedOperationException("DataSource name not available");
}
}

View File

@@ -23,7 +23,6 @@ import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.xml.namespace.QName;
import javax.xml.soap.AttachmentPart;
import javax.xml.soap.Detail;
@@ -297,8 +296,8 @@ public class Saaj11Implementation implements SaajImplementation {
return message.getAttachments(mimeHeaders);
}
public AttachmentPart addAttachmentPart(SOAPMessage message, DataSource dataSource) {
AttachmentPart attachmentPart = message.createAttachmentPart(new DataHandler(dataSource));
public AttachmentPart addAttachmentPart(SOAPMessage message, DataHandler dataHandler) {
AttachmentPart attachmentPart = message.createAttachmentPart(dataHandler);
message.addAttachmentPart(attachmentPart);
return attachmentPart;
}

View File

@@ -23,7 +23,6 @@ import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.xml.namespace.QName;
import javax.xml.soap.AttachmentPart;
import javax.xml.soap.Detail;
@@ -249,8 +248,8 @@ public class Saaj12Implementation implements SaajImplementation {
return message.getAttachments(mimeHeaders);
}
public AttachmentPart addAttachmentPart(SOAPMessage message, DataSource dataSource) {
AttachmentPart attachmentPart = message.createAttachmentPart(new DataHandler(dataSource));
public AttachmentPart addAttachmentPart(SOAPMessage message, DataHandler dataHandler) {
AttachmentPart attachmentPart = message.createAttachmentPart(dataHandler);
message.addAttachmentPart(attachmentPart);
return attachmentPart;
}

View File

@@ -21,7 +21,6 @@ import java.io.OutputStream;
import java.util.Iterator;
import java.util.Locale;
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.xml.namespace.QName;
import javax.xml.soap.AttachmentPart;
import javax.xml.soap.Detail;
@@ -284,8 +283,8 @@ public class Saaj13Implementation implements SaajImplementation {
return message.getAttachments(mimeHeaders);
}
public AttachmentPart addAttachmentPart(SOAPMessage message, DataSource dataSource) {
AttachmentPart attachmentPart = message.createAttachmentPart(new DataHandler(dataSource));
public AttachmentPart addAttachmentPart(SOAPMessage message, DataHandler dataHandler) {
AttachmentPart attachmentPart = message.createAttachmentPart(dataHandler);
message.addAttachmentPart(attachmentPart);
return attachmentPart;
}

View File

@@ -16,14 +16,14 @@
package org.springframework.ws.soap.saaj;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.activation.DataHandler;
import javax.xml.soap.AttachmentPart;
import javax.xml.soap.SOAPException;
import org.springframework.util.Assert;
import org.springframework.ws.soap.Attachment;
import org.springframework.ws.mime.Attachment;
/**
* SAAJ-specific implementation of the <code>Attachment</code> interface. Wraps a {@link
@@ -40,14 +40,10 @@ class SaajAttachment implements Attachment {
this.saajAttachment = saajAttachment;
}
public String getId() {
public String getContentId() {
return saajAttachment.getContentId();
}
public void setId(String id) {
saajAttachment.setContentId(id);
}
public String getContentType() {
return saajAttachment.getContentType();
}
@@ -56,20 +52,26 @@ class SaajAttachment implements Attachment {
try {
return saajAttachment.getDataHandler().getInputStream();
}
catch (SOAPException e) {
return new ByteArrayInputStream(new byte[0]);
catch (SOAPException ex) {
throw new SaajAttachmentException(ex);
}
}
public long getSize() {
try {
int result = saajAttachment.getSize();
// SAAJ returns -1 when the size cannot be determined
return result != -1 ? result : 0;
return saajAttachment.getSize();
}
catch (SOAPException ex) {
throw new SaajAttachmentException(ex);
}
}
public DataHandler getDataHandler() {
try {
return saajAttachment.getDataHandler();
}
catch (SOAPException ex) {
throw new SaajAttachmentException(ex);
}
}
}

View File

@@ -16,11 +16,9 @@
package org.springframework.ws.soap.saaj;
import org.springframework.ws.soap.AttachmentException;
import org.springframework.ws.mime.AttachmentException;
/**
* @author Arjen Poutsma
*/
/** @author Arjen Poutsma */
public class SaajAttachmentException extends AttachmentException {
public SaajAttachmentException(String msg) {

View File

@@ -20,7 +20,7 @@ import java.io.IOException;
import java.io.OutputStream;
import java.util.Iterator;
import java.util.Locale;
import javax.activation.DataSource;
import javax.activation.DataHandler;
import javax.xml.namespace.QName;
import javax.xml.soap.AttachmentPart;
import javax.xml.soap.Detail;
@@ -149,7 +149,7 @@ public interface SaajImplementation {
Iterator getAttachment(SOAPMessage message, MimeHeaders mimeHeaders);
/** Adds an attachment to the given message. */
AttachmentPart addAttachmentPart(SOAPMessage message, DataSource dataSource);
AttachmentPart addAttachmentPart(SOAPMessage message, DataHandler dataHandler);
/** Adds a not understood header element to the given header. */
SOAPHeaderElement addNotUnderstoodHeaderElement(SOAPHeader header, QName name) throws SOAPException;

View File

@@ -16,12 +16,10 @@
package org.springframework.ws.soap.saaj;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Iterator;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.activation.DataHandler;
import javax.xml.soap.AttachmentPart;
import javax.xml.soap.MimeHeaders;
import javax.xml.soap.SOAPBody;
@@ -29,23 +27,23 @@ import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.SOAPPart;
import org.springframework.core.io.InputStreamSource;
import org.springframework.core.io.Resource;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.ws.mime.Attachment;
import org.springframework.ws.mime.AttachmentException;
import org.springframework.ws.soap.AbstractSoapMessage;
import org.springframework.ws.soap.Attachment;
import org.springframework.ws.soap.AttachmentException;
import org.springframework.ws.soap.SoapEnvelope;
import org.springframework.ws.soap.SoapMessage;
import org.springframework.ws.soap.saaj.support.SaajUtils;
/**
* SAAJ-specific implementation of the {@link SoapMessage} interface. Created via the {@link SaajSoapMessageFactory}.
* SAAJ-specific implementation of the {@link SoapMessage} interface. Created via the {@link SaajSoapMessageFactory},
* wraps a {@link SOAPMessage}.
*
* @author Arjen Poutsma
* @see javax.xml.soap.SOAPMessage
* @see SOAPMessage
*/
public class SaajSoapMessage extends AbstractSoapMessage {
@@ -53,6 +51,8 @@ public class SaajSoapMessage extends AbstractSoapMessage {
private static final String MIME_HEADER_CONTENT_ID = "Content-Id";
private static final String MIME_HEADER_CONTENT_TYPE = "Content-Type";
private SOAPMessage saajMessage;
private SoapEnvelope envelope;
@@ -112,6 +112,17 @@ public class SaajSoapMessage extends AbstractSoapMessage {
}
}
public boolean isXopPackage() {
SOAPPart saajPart = saajMessage.getSOAPPart();
String[] contentTypes = saajPart.getMimeHeader(MIME_HEADER_CONTENT_TYPE);
for (int i = 0; i < contentTypes.length; i++) {
if (contentTypes[i].indexOf("application/xop+xml") != -1) {
return true;
}
}
return false;
}
public Iterator getAttachments() throws AttachmentException {
Iterator iterator = getImplementation().getAttachments(getSaajMessage());
return new SaajAttachmentIterator(iterator);
@@ -134,21 +145,11 @@ public class SaajSoapMessage extends AbstractSoapMessage {
return new SaajAttachment(saajAttachment);
}
public Attachment addAttachment(File file) throws AttachmentException {
Assert.notNull(file, "File must not be null");
DataSource dataSource = new FileDataSource(file);
AttachmentPart attachmentPart = getImplementation().addAttachmentPart(getSaajMessage(), dataSource);
return new SaajAttachment(attachmentPart);
}
public Attachment addAttachment(InputStreamSource inputStreamSource, String contentType) {
Assert.notNull(inputStreamSource, "InputStreamSource must not be null");
if (inputStreamSource instanceof Resource && ((Resource) inputStreamSource).isOpen()) {
throw new IllegalArgumentException("Passed-in Resource contains an open stream: invalid argument. " +
"SAAJ requires an InputStreamSource that creates a fresh stream for every call.");
}
DataSource dataSource = new InputStreamSourceDataSource(inputStreamSource, contentType);
AttachmentPart saajAttachment = getImplementation().addAttachmentPart(getSaajMessage(), dataSource);
public Attachment addAttachment(String contentId, DataHandler dataHandler) {
Assert.hasLength(contentId, "contentId must not be empty");
Assert.notNull(dataHandler, "dataHandler must not be null");
AttachmentPart saajAttachment = getImplementation().addAttachmentPart(getSaajMessage(), dataHandler);
saajAttachment.setContentId(contentId);
return new SaajAttachment(saajAttachment);
}

View File

@@ -30,19 +30,25 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.StringUtils;
import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.WebServiceMessageFactory;
import org.springframework.ws.soap.SoapMessageCreationException;
import org.springframework.ws.soap.SoapMessageFactory;
import org.springframework.ws.soap.SoapVersion;
import org.springframework.ws.soap.saaj.support.SaajUtils;
import org.springframework.ws.transport.TransportInputStream;
/**
* SAAJ-specific implementation of the {@link org.springframework.ws.WebServiceMessageFactory WebServiceMessageFactory}.
* This factory will use SAAJ 1.3 when found, or fall back to SAAJ 1.2 or 1.1.
* Wraps a SAAJ {@link MessageFactory}. This factory will use SAAJ 1.3 when found, or fall back to SAAJ 1.2 or even
* 1.1.
* <p/>
* A SAAJ {@link MessageFactory} can be injected to the {@link #SaajSoapMessageFactory(javax.xml.soap.MessageFactory)
* constructor}, or by the {@link #setMessageFactory(javax.xml.soap.MessageFactory)} property. When a SAAJ message
* factory is injected, the {@link #setSoapVersion(org.springframework.ws.soap.SoapVersion)} property is ignored.
*
* @author Arjen Poutsma
* @see org.springframework.ws.soap.saaj.SaajSoapMessage
*/
public class SaajSoapMessageFactory implements WebServiceMessageFactory, InitializingBean {
public class SaajSoapMessageFactory implements SoapMessageFactory, InitializingBean {
private static final Log logger = LogFactory.getLog(SaajSoapMessageFactory.class);
@@ -50,39 +56,49 @@ public class SaajSoapMessageFactory implements WebServiceMessageFactory, Initial
private String messageFactoryProtocol;
/**
* Default, empty constructor.
*/
/** Default, empty constructor. */
public SaajSoapMessageFactory() {
}
/**
* Constructor that takes a message factory as an argument.
*/
/** Constructor that takes a message factory as an argument. */
public SaajSoapMessageFactory(MessageFactory messageFactory) {
this.messageFactory = messageFactory;
}
/**
* Sets the SAAJ <code>MessageFactory</code>.
*/
/** Sets the SAAJ <code>MessageFactory</code>. */
public void setMessageFactory(MessageFactory messageFactory) {
this.messageFactory = messageFactory;
}
/**
* Returns the SAAJ <code>MessageFactory</code> used.
*/
public MessageFactory getSaajMessageFactory() {
/** Returns the SAAJ <code>MessageFactory</code> used. */
public MessageFactory getMessageFactory() {
return messageFactory;
}
public void setSoapVersion(SoapVersion version) {
if (SaajUtils.getSaajVersion() >= SaajUtils.SAAJ_13) {
if (SoapVersion.SOAP_11 == version) {
messageFactoryProtocol = SOAPConstants.SOAP_1_1_PROTOCOL;
}
else if (SoapVersion.SOAP_12 == version) {
messageFactoryProtocol = SOAPConstants.SOAP_1_2_PROTOCOL;
}
else {
throw new IllegalArgumentException(
"Invalid version [" + version + "]. " + "Expected the SOAP_11 or SOAP_12 constant");
}
}
else if (SoapVersion.SOAP_11 != version) {
throw new IllegalArgumentException("SAAJ 1.1 and 1.2 only support SOAP 1.1");
}
}
public void afterPropertiesSet() throws Exception {
if (messageFactory == null) {
try {
if (SaajUtils.getSaajVersion() >= SaajUtils.SAAJ_13) {
if (!StringUtils.hasLength(messageFactoryProtocol)) {
messageFactoryProtocol = SOAPConstants.DEFAULT_SOAP_PROTOCOL;
messageFactoryProtocol = SOAPConstants.SOAP_1_1_PROTOCOL;
}
if (logger.isInfoEnabled()) {
logger.info("Creating SAAJ 1.3 MessageFactory with " + messageFactoryProtocol);
@@ -90,20 +106,16 @@ public class SaajSoapMessageFactory implements WebServiceMessageFactory, Initial
messageFactory = MessageFactory.newInstance(messageFactoryProtocol);
}
else if (SaajUtils.getSaajVersion() == SaajUtils.SAAJ_12) {
if (logger.isInfoEnabled()) {
logger.info("Creating SAAJ 1.2 MessageFactory");
}
logger.info("Creating SAAJ 1.2 MessageFactory");
messageFactory = MessageFactory.newInstance();
}
else if (SaajUtils.getSaajVersion() == SaajUtils.SAAJ_11) {
if (logger.isInfoEnabled()) {
logger.info("Creating SAAJ 1.1 MessageFactory");
}
logger.info("Creating SAAJ 1.1 MessageFactory");
messageFactory = MessageFactory.newInstance();
}
else {
throw new IllegalStateException(
"SaajSoapMessageFactory requires SAAJ 1.2, which was not" + "found on the classpath");
"SaajSoapMessageFactory requires SAAJ 1.1, which was not" + "found on the classpath");
}
}
catch (SOAPException ex) {
@@ -146,18 +158,4 @@ public class SaajSoapMessageFactory implements WebServiceMessageFactory, Initial
throw new SoapMessageCreationException("Could not create message from InputStream: " + ex.getMessage(), ex);
}
}
/**
* Sets the protocol for the <code>MessageFactory</code>. Only used for SAAJ 1.3+, defaults to
* <code>SOAPConstants.DEFAULT_SOAP_PROTOCOL</code> (i.e. SOAP 1.1).
*
* @see MessageFactory#newInstance(String)
* @see javax.xml.soap.SOAPConstants#DEFAULT_SOAP_PROTOCOL
* @see javax.xml.soap.SOAPConstants#SOAP_1_1_PROTOCOL
* @see javax.xml.soap.SOAPConstants#SOAP_1_2_PROTOCOL
* @see javax.xml.soap.SOAPConstants#DYNAMIC_SOAP_PROTOCOL
*/
public void setSoapProtocol(String messageFactoryProtocol) {
this.messageFactoryProtocol = messageFactoryProtocol;
}
}

View File

@@ -19,7 +19,6 @@ package org.springframework.ws.client.core;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Collections;
import org.custommonkey.xmlunit.XMLTestCase;
import org.easymock.MockControl;
@@ -97,8 +96,8 @@ public class WebServiceTemplateTest extends XMLTestCase {
connectionControl.expectAndReturn(connectionMock.getTransportOutputStream(),
new MockTransportOutputStream(new ByteArrayOutputStream()));
connectionControl.expectAndReturn(connectionMock.getTransportInputStream(), new MockTransportInputStream(
new ByteArrayInputStream("<response/>".getBytes("UTF-8")), Collections.EMPTY_MAP));
connectionControl.expectAndReturn(connectionMock.getTransportInputStream(),
new MockTransportInputStream(new ByteArrayInputStream("<response/>".getBytes("UTF-8"))));
connectionControl.expectAndReturn(connectionMock.hasFault(), false);
connectionMock.close();
connectionControl.replay();
@@ -156,8 +155,8 @@ public class WebServiceTemplateTest extends XMLTestCase {
connectionControl.expectAndReturn(connectionMock.getTransportOutputStream(),
new MockTransportOutputStream(new ByteArrayOutputStream()));
connectionControl.expectAndReturn(connectionMock.getTransportInputStream(), new MockTransportInputStream(
new ByteArrayInputStream("<response/>".getBytes("UTF-8")), Collections.EMPTY_MAP));
connectionControl.expectAndReturn(connectionMock.getTransportInputStream(),
new MockTransportInputStream(new ByteArrayInputStream("<response/>".getBytes("UTF-8"))));
connectionControl.expectAndReturn(connectionMock.hasFault(), true);
connectionMock.close();
connectionControl.replay();
@@ -181,8 +180,8 @@ public class WebServiceTemplateTest extends XMLTestCase {
connectionControl.expectAndReturn(connectionMock.getTransportOutputStream(),
new MockTransportOutputStream(new ByteArrayOutputStream()));
connectionControl.expectAndReturn(connectionMock.getTransportInputStream(), new MockTransportInputStream(
new ByteArrayInputStream("<response/>".getBytes("UTF-8")), Collections.EMPTY_MAP));
connectionControl.expectAndReturn(connectionMock.getTransportInputStream(),
new MockTransportInputStream(new ByteArrayInputStream("<response/>".getBytes("UTF-8"))));
connectionControl.expectAndReturn(connectionMock.hasFault(), false);
connectionMock.close();
connectionControl.replay();
@@ -215,8 +214,8 @@ public class WebServiceTemplateTest extends XMLTestCase {
public void testSendAndReceiveResultResponse() throws Exception {
connectionControl.expectAndReturn(connectionMock.getTransportOutputStream(),
new MockTransportOutputStream(new ByteArrayOutputStream()));
connectionControl.expectAndReturn(connectionMock.getTransportInputStream(), new MockTransportInputStream(
new ByteArrayInputStream("<response/>".getBytes("UTF-8")), Collections.EMPTY_MAP));
connectionControl.expectAndReturn(connectionMock.getTransportInputStream(),
new MockTransportInputStream(new ByteArrayInputStream("<response/>".getBytes("UTF-8"))));
connectionControl.expectAndReturn(connectionMock.hasFault(), false);
connectionMock.close();
connectionControl.replay();
@@ -246,8 +245,8 @@ public class WebServiceTemplateTest extends XMLTestCase {
connectionControl.expectAndReturn(connectionMock.getTransportOutputStream(),
new MockTransportOutputStream(new ByteArrayOutputStream()));
connectionControl.expectAndReturn(connectionMock.getTransportInputStream(), new MockTransportInputStream(
new ByteArrayInputStream("<response/>".getBytes("UTF-8")), Collections.EMPTY_MAP));
connectionControl.expectAndReturn(connectionMock.getTransportInputStream(),
new MockTransportInputStream(new ByteArrayInputStream("<response/>".getBytes("UTF-8"))));
connectionControl.expectAndReturn(connectionMock.hasFault(), false);
connectionMock.close();
connectionControl.replay();

View File

@@ -0,0 +1,83 @@
/*
* Copyright 2007 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.mime;
import java.io.IOException;
import java.util.Iterator;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.util.FileCopyUtils;
import org.springframework.ws.AbstractWebServiceMessageTestCase;
import org.springframework.ws.WebServiceMessage;
public abstract class AbstractMimeMessageTestCase extends AbstractWebServiceMessageTestCase {
protected MimeMessage mimeMessage;
private Resource picture;
private String contentId;
private String contentType;
protected final WebServiceMessage createWebServiceMessage() throws Exception {
mimeMessage = createMimeMessage();
picture = new ClassPathResource("spring-ws.png", AbstractMimeMessageTestCase.class);
contentId = "spring-ws";
contentType = "image/png";
return mimeMessage;
}
protected abstract MimeMessage createMimeMessage() throws Exception;
public void testEmptyMessage() throws Exception {
Iterator iterator = mimeMessage.getAttachments();
assertFalse("Empty MimeMessage has attachments", iterator.hasNext());
}
public void testAddAttachment() throws Exception {
Attachment attachment = mimeMessage.addAttachment(contentId, picture, contentType);
testAttachment(attachment);
}
public void testGetAttachment() throws Exception {
mimeMessage.addAttachment(contentId, picture, contentType);
Attachment attachment = mimeMessage.getAttachment(contentId);
assertNotNull("Not Attachment found", attachment);
testAttachment(attachment);
}
public void testGetAttachments() throws Exception {
mimeMessage.addAttachment(contentId, picture, contentType);
Iterator iterator = mimeMessage.getAttachments();
assertNotNull("Attachment iterator is null", iterator);
assertTrue("Attachment iterator has no elements", iterator.hasNext());
Attachment attachment = (Attachment) iterator.next();
testAttachment(attachment);
assertFalse("Attachment iterator has too many elements", iterator.hasNext());
}
private void testAttachment(Attachment attachment) throws IOException {
assertEquals("Invalid content id", contentId, attachment.getContentId());
assertEquals("Invalid content type", contentType, attachment.getContentType());
assertTrue("Invalid size", attachment.getSize() != 0);
byte[] contents = FileCopyUtils.copyToByteArray(attachment.getInputStream());
assertTrue("No contents", contents.length > 0);
}
}

View File

@@ -32,10 +32,15 @@ import org.easymock.MockControl;
import org.springframework.oxm.Marshaller;
import org.springframework.oxm.Unmarshaller;
import org.springframework.oxm.XmlMappingException;
import org.springframework.oxm.mime.MimeMarshaller;
import org.springframework.oxm.mime.MimeUnmarshaller;
import org.springframework.ws.MockWebServiceMessage;
import org.springframework.ws.WebServiceMessageFactory;
import org.springframework.ws.context.DefaultMessageContext;
import org.springframework.ws.context.MessageContext;
import org.springframework.ws.mime.MimeMessage;
import org.springframework.xml.transform.StringResult;
import org.springframework.xml.transform.StringSource;
public class MarshallingPayloadEndpointTest extends XMLTestCase {
@@ -54,7 +59,6 @@ public class MarshallingPayloadEndpointTest extends XMLTestCase {
factoryMock = (WebServiceMessageFactory) factoryControl.getMock();
context = new DefaultMessageContext(request, factoryMock);
}
public void testInvoke() throws Exception {
@@ -139,6 +143,50 @@ public class MarshallingPayloadEndpointTest extends XMLTestCase {
factoryControl.verify();
}
public void testInvokeMimeMarshaller() throws Exception {
MockControl unmarshallerControl = MockControl.createControl(MimeUnmarshaller.class);
MimeUnmarshaller unmarshaller = (MimeUnmarshaller) unmarshallerControl.getMock();
MockControl marshallerControl = MockControl.createControl(MimeMarshaller.class);
MimeMarshaller marshaller = (MimeMarshaller) marshallerControl.getMock();
MockControl messageControl = MockControl.createControl(MimeMessage.class);
MimeMessage request = (MimeMessage) messageControl.getMock();
MimeMessage response = (MimeMessage) messageControl.getMock();
Source requestSource = new StringSource("<request/>");
messageControl.expectAndReturn(request.getPayloadSource(), requestSource);
factoryControl.expectAndReturn(factoryMock.createWebServiceMessage(), response);
unmarshaller.unmarshal(requestSource, null);
unmarshallerControl.setMatcher(MockControl.ALWAYS_MATCHER);
unmarshallerControl.setReturnValue(new Long(42));
Result responseResult = new StringResult();
messageControl.expectAndReturn(response.getPayloadResult(), responseResult);
marshaller.marshal("result", responseResult, null);
marshallerControl.setMatcher(MockControl.ALWAYS_MATCHER);
factoryControl.replay();
unmarshallerControl.replay();
marshallerControl.replay();
messageControl.replay();
AbstractMarshallingPayloadEndpoint endpoint = new AbstractMarshallingPayloadEndpoint() {
protected Object invokeInternal(Object requestObject) throws Exception {
assertEquals("Invalid request object", new Long(42), requestObject);
return "result";
}
};
endpoint.setMarshaller(marshaller);
endpoint.setUnmarshaller(unmarshaller);
endpoint.afterPropertiesSet();
context = new DefaultMessageContext(request, factoryMock);
endpoint.invoke(context);
assertNotNull("Invalid result", response);
factoryControl.verify();
unmarshallerControl.verify();
marshallerControl.verify();
messageControl.verify();
}
private abstract static class SimpleMarshaller implements Marshaller, Unmarshaller {
public void marshal(Object graph, Result result) throws XmlMappingException, IOException {

View File

@@ -1,64 +0,0 @@
/*
* Copyright 2006 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;
import java.io.IOException;
import java.io.InputStream;
import javax.xml.soap.SOAPException;
import junit.framework.TestCase;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.util.FileCopyUtils;
public abstract class AbstractAttachmentTestCase extends TestCase {
private Attachment attachment;
private static byte[] CONTENTS;
private static final String CONTENT_TYPE = "text/plain";
protected final void setUp() throws Exception {
CONTENTS = "attachment contents".getBytes("UTF-8");
SoapMessage message = createMessage();
attachment = message.addAttachment(new ByteArrayResource(CONTENTS), CONTENT_TYPE);
}
protected abstract SoapMessage createMessage() throws Exception;
public void testGetSize() throws SOAPException {
assertTrue("Invalid size", attachment.getSize() > 0);
}
public void testContentId() {
String id = "123";
attachment.setId(id);
assertEquals("Invalid content id", id, attachment.getId());
}
public void testGetContentType() {
assertEquals("Invalid content type", CONTENT_TYPE, attachment.getContentType());
}
public void testGetInputStream() throws IOException {
InputStream inputStream = attachment.getInputStream();
assertNotNull("Invalid input stream returned", inputStream);
byte[] bytes = FileCopyUtils.copyToByteArray(inputStream);
assertEquals("Invalid size", CONTENTS.length, bytes.length);
}
}

View File

@@ -26,4 +26,9 @@ public abstract class AbstractSoapMessageFactoryTestCase extends AbstractWebServ
assertTrue("Not a SoapMessage", message instanceof SoapMessage);
}
public abstract void testCreateSoapMessageNoAttachment() throws Exception;
public abstract void testCreateSoapMessageSwA() throws Exception;
public abstract void testCreateSoapMessageMtom() throws Exception;
}

View File

@@ -16,48 +16,25 @@
package org.springframework.ws.soap;
import java.io.ByteArrayOutputStream;
import java.util.Iterator;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.InputStreamSource;
import org.springframework.core.io.Resource;
import org.springframework.util.FileCopyUtils;
import org.springframework.util.StringUtils;
import org.springframework.ws.AbstractWebServiceMessageTestCase;
import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.mime.AbstractMimeMessageTestCase;
import org.springframework.ws.mime.MimeMessage;
import org.springframework.xml.validation.XmlValidator;
import org.springframework.xml.validation.XmlValidatorFactory;
import org.xml.sax.SAXParseException;
public abstract class AbstractSoapMessageTestCase extends AbstractWebServiceMessageTestCase {
public abstract class AbstractSoapMessageTestCase extends AbstractMimeMessageTestCase {
protected SoapMessage soapMessage;
protected final WebServiceMessage createWebServiceMessage() throws Exception {
protected MimeMessage createMimeMessage() throws Exception {
soapMessage = createSoapMessage();
return soapMessage;
}
protected abstract SoapMessage createSoapMessage() throws Exception;
public void testAttachments() throws Exception {
String contents = "contents";
String contentType = "text/plain";
InputStreamSource inputStreamSource = new ByteArrayResource(contents.getBytes("UTF-8"));
soapMessage.addAttachment(inputStreamSource, contentType);
Iterator iterator = soapMessage.getAttachments();
assertNotNull("Attachment iterator is null", iterator);
assertTrue("Attachment iterator has no elements", iterator.hasNext());
Attachment attachment = (Attachment) iterator.next();
assertEquals("Invalid content-id", contentType, attachment.getContentType());
ByteArrayOutputStream os = new ByteArrayOutputStream();
FileCopyUtils.copy(attachment.getInputStream(), os);
String result = new String(os.toByteArray(), "UTF-8");
assertEquals("Invalid contents", contents, result);
assertFalse("Attachment iterator has too many elements", iterator.hasNext());
}
public void testValidate() throws Exception {
XmlValidator validator =
XmlValidatorFactory.createValidator(getSoapSchemas(), XmlValidatorFactory.SCHEMA_W3C_XML);

View File

@@ -53,13 +53,5 @@ public class AxiomSoap11MessageFactoryTest extends AbstractSoap11MessageFactoryT
envelope.serialize(os, format);
} finally {
os.close();
}
}
*/
*/
}

View File

@@ -12,11 +12,4 @@ public class AxiomSoap11MessageTest extends AbstractSoap11MessageTestCase {
return new AxiomSoapMessage(axiomFactory);
}
public void testAttachments() throws Exception {
// Attachment not supported
}
public void testWriteToTransportResponseAttachment() throws Exception {
// Attachment support not supported
}
}

View File

@@ -17,22 +17,15 @@
package org.springframework.ws.soap.axiom;
import org.springframework.ws.WebServiceMessageFactory;
import org.springframework.ws.soap.SoapVersion;
import org.springframework.ws.soap.soap12.AbstractSoap12MessageFactoryTestCase;
public class AxiomSoap12MessageFactoryTest extends AbstractSoap12MessageFactoryTestCase {
protected WebServiceMessageFactory createMessageFactory() throws Exception {
AxiomSoapMessageFactory factory = new AxiomSoapMessageFactory();
factory.afterPropertiesSet();
factory.setSoapVersion(SoapVersion.SOAP_12);
return factory;
}
public void testCreateEmptyMessage() throws Exception {
}
public void testCreateSoapMessageAttachment() throws Exception {
// Axiom does not support SwA with SOAP 1.2
}
}

View File

@@ -28,11 +28,4 @@ public class AxiomSoap12MessageTest extends AbstractSoap12MessageTestCase {
return new AxiomSoapMessage(axiomFactory);
}
public void testAttachments() throws Exception {
// Attachments not supported
}
public void testWriteToTransportResponseAttachment() throws Exception {
// Attachments not supported
}
}

View File

@@ -19,7 +19,7 @@ package org.springframework.ws.soap.saaj;
import java.io.ByteArrayOutputStream;
import java.util.Iterator;
import java.util.Locale;
import javax.activation.DataSource;
import javax.activation.DataHandler;
import javax.mail.util.ByteArrayDataSource;
import javax.xml.namespace.QName;
import javax.xml.soap.AttachmentPart;
@@ -273,8 +273,8 @@ public abstract class AbstractSaajImplementationTestCase extends XMLTestCase {
}
public void testAddAttachmentPart() throws Exception {
DataSource dataSource = new ByteArrayDataSource("data", "text");
AttachmentPart attachmentPart = implementation.addAttachmentPart(message, dataSource);
DataHandler dataHandler = new DataHandler(new ByteArrayDataSource("data", "text"));
AttachmentPart attachmentPart = implementation.addAttachmentPart(message, dataHandler);
assertNotNull("No attachment part", attachmentPart);
}

View File

@@ -1,33 +0,0 @@
/*
* Copyright 2006 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.saaj;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPConstants;
import javax.xml.soap.SOAPMessage;
import org.springframework.ws.soap.AbstractAttachmentTestCase;
import org.springframework.ws.soap.SoapMessage;
public class SaajAttachmentTest extends AbstractAttachmentTestCase {
protected SoapMessage createMessage() throws Exception {
MessageFactory messageFactory = MessageFactory.newInstance(SOAPConstants.SOAP_1_1_PROTOCOL);
SOAPMessage saajMessage = messageFactory.createMessage();
return new SaajSoapMessage(saajMessage);
}
}

View File

@@ -17,6 +17,7 @@
package org.springframework.ws.soap.saaj;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPConstants;
import javax.xml.soap.SOAPMessage;
import org.springframework.ws.soap.SoapBody;
@@ -25,7 +26,7 @@ import org.springframework.ws.soap.soap11.AbstractSoap11BodyTestCase;
public class SaajSoap11BodyTest extends AbstractSoap11BodyTestCase {
protected SoapBody createSoapBody() throws Exception {
MessageFactory messageFactory = MessageFactory.newInstance();
MessageFactory messageFactory = MessageFactory.newInstance(SOAPConstants.SOAP_1_1_PROTOCOL);
SOAPMessage saajMessage = messageFactory.createMessage();
return new SaajSoap11Body(saajMessage.getSOAPPart().getEnvelope().getBody());
}

View File

@@ -17,6 +17,7 @@
package org.springframework.ws.soap.saaj;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPConstants;
import javax.xml.soap.SOAPMessage;
import org.springframework.ws.soap.SoapEnvelope;
@@ -25,7 +26,7 @@ import org.springframework.ws.soap.soap11.AbstractSoap11EnvelopeTestCase;
public class SaajSoap11EnvelopeTest extends AbstractSoap11EnvelopeTestCase {
protected SoapEnvelope createSoapEnvelope() throws Exception {
MessageFactory messageFactory = MessageFactory.newInstance();
MessageFactory messageFactory = MessageFactory.newInstance(SOAPConstants.SOAP_1_1_PROTOCOL);
SOAPMessage saajMessage = messageFactory.createMessage();
return new SaajSoapEnvelope(saajMessage.getSOAPPart().getEnvelope());
}

View File

@@ -17,6 +17,7 @@
package org.springframework.ws.soap.saaj;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPConstants;
import javax.xml.soap.SOAPMessage;
import org.springframework.ws.soap.SoapHeader;
@@ -25,7 +26,7 @@ import org.springframework.ws.soap.soap11.AbstractSoap11HeaderTestCase;
public class SaajSoap11HeaderTest extends AbstractSoap11HeaderTestCase {
protected SoapHeader createSoapHeader() throws Exception {
MessageFactory messageFactory = MessageFactory.newInstance();
MessageFactory messageFactory = MessageFactory.newInstance(SOAPConstants.SOAP_1_1_PROTOCOL);
SOAPMessage saajMessage = messageFactory.createMessage();
return new SaajSoapHeader(saajMessage.getSOAPPart().getEnvelope().getHeader());
}

View File

@@ -17,6 +17,7 @@
package org.springframework.ws.soap.saaj;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPConstants;
import org.springframework.ws.WebServiceMessageFactory;
import org.springframework.ws.soap.soap11.AbstractSoap11MessageFactoryTestCase;
@@ -24,11 +25,8 @@ import org.springframework.ws.soap.soap11.AbstractSoap11MessageFactoryTestCase;
public class SaajSoap11MessageFactoryTest extends AbstractSoap11MessageFactoryTestCase {
protected WebServiceMessageFactory createMessageFactory() throws Exception {
MessageFactory messageFactory = MessageFactory.newInstance();
SaajSoapMessageFactory factory = new SaajSoapMessageFactory();
factory.setMessageFactory(messageFactory);
factory.afterPropertiesSet();
return factory;
MessageFactory messageFactory = MessageFactory.newInstance(SOAPConstants.SOAP_1_1_PROTOCOL);
return new SaajSoapMessageFactory(messageFactory);
}

View File

@@ -20,6 +20,7 @@ import java.util.Iterator;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPBodyElement;
import javax.xml.soap.SOAPConstants;
import javax.xml.soap.SOAPMessage;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
@@ -34,7 +35,7 @@ public class SaajSoap11MessageTest extends AbstractSoap11MessageTestCase {
private SOAPMessage saajMessage;
protected final SoapMessage createSoapMessage() throws Exception {
MessageFactory messageFactory = MessageFactory.newInstance();
MessageFactory messageFactory = MessageFactory.newInstance(SOAPConstants.SOAP_1_1_PROTOCOL);
saajMessage = messageFactory.createMessage();
saajMessage.getSOAPHeader().detachNode();
return new SaajSoapMessage(saajMessage);

View File

@@ -16,6 +16,7 @@
package org.springframework.ws.soap.saaj;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPConstants;
import org.springframework.ws.WebServiceMessageFactory;
@@ -24,9 +25,7 @@ import org.springframework.ws.soap.soap12.AbstractSoap12MessageFactoryTestCase;
public class SaajSoap12MessageFactoryTest extends AbstractSoap12MessageFactoryTestCase {
protected WebServiceMessageFactory createMessageFactory() throws Exception {
SaajSoapMessageFactory factory = new SaajSoapMessageFactory();
factory.setSoapProtocol(SOAPConstants.SOAP_1_2_PROTOCOL);
factory.afterPropertiesSet();
return factory;
MessageFactory messageFactory = MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL);
return new SaajSoapMessageFactory(messageFactory);
}
}

View File

@@ -33,6 +33,7 @@ import org.springframework.ws.soap.SoapEndpointInterceptor;
import org.springframework.ws.soap.SoapHeader;
import org.springframework.ws.soap.SoapHeaderElement;
import org.springframework.ws.soap.SoapMessage;
import org.springframework.ws.soap.SoapMessageFactory;
import org.springframework.ws.soap.saaj.SaajSoapMessage;
import org.springframework.ws.soap.saaj.SaajSoapMessageFactory;
import org.springframework.ws.soap.soap11.Soap11Fault;
@@ -46,13 +47,10 @@ public class SoapMessageDispatcherTest extends TestCase {
private SoapEndpointInterceptor interceptorMock;
private SaajSoapMessageFactory factory;
protected void setUp() throws Exception {
interceptorControl = MockControl.createControl(SoapEndpointInterceptor.class);
interceptorMock = (SoapEndpointInterceptor) interceptorControl.getMock();
dispatcher = new SoapMessageDispatcher();
factory = new SaajSoapMessageFactory();
}
public void testProcessMustUnderstandHeadersUnderstoodSoap11() throws Exception {
@@ -62,8 +60,7 @@ public class SoapMessageDispatcherTest extends TestCase {
request.getSOAPHeader().addHeaderElement(new QName("http://www.springframework.org", "Header"));
header.setActor(SOAPConstants.URI_SOAP_ACTOR_NEXT);
header.setMustUnderstand(true);
factory.setSoapProtocol(SOAPConstants.SOAP_1_1_PROTOCOL);
factory.afterPropertiesSet();
SoapMessageFactory factory = new SaajSoapMessageFactory(messageFactory);
MessageContext context = new DefaultMessageContext(new SaajSoapMessage(request), factory);
interceptorMock.understands(null);
interceptorControl.setMatcher(MockControl.ALWAYS_MATCHER);
@@ -85,8 +82,7 @@ public class SoapMessageDispatcherTest extends TestCase {
request.getSOAPHeader().addHeaderElement(new QName("http://www.springframework.org", "Header"));
header.setMustUnderstand(true);
header.setRole(SOAPConstants.URI_SOAP_1_2_ROLE_NEXT);
factory.setSoapProtocol(SOAPConstants.SOAP_1_2_PROTOCOL);
factory.afterPropertiesSet();
SoapMessageFactory factory = new SaajSoapMessageFactory(messageFactory);
MessageContext context = new DefaultMessageContext(new SaajSoapMessage(request), factory);
interceptorMock.understands(null);
interceptorControl.setMatcher(MockControl.ALWAYS_MATCHER);
@@ -108,8 +104,7 @@ public class SoapMessageDispatcherTest extends TestCase {
.addHeaderElement(new QName("http://www.springframework.org", "Header", "spring-ws"));
header.setActor(SOAPConstants.URI_SOAP_ACTOR_NEXT);
header.setMustUnderstand(true);
factory.setSoapProtocol(SOAPConstants.SOAP_1_1_PROTOCOL);
factory.afterPropertiesSet();
SoapMessageFactory factory = new SaajSoapMessageFactory(messageFactory);
MessageContext context = new DefaultMessageContext(new SaajSoapMessage(request), factory);
interceptorMock.understands(null);
interceptorControl.setMatcher(MockControl.ALWAYS_MATCHER);
@@ -141,8 +136,7 @@ public class SoapMessageDispatcherTest extends TestCase {
.addHeaderElement(new QName("http://www.springframework.org", "Header", "spring-ws"));
header.setMustUnderstand(true);
header.setRole(SOAPConstants.URI_SOAP_1_2_ROLE_NEXT);
factory.setSoapProtocol(SOAPConstants.SOAP_1_2_PROTOCOL);
factory.afterPropertiesSet();
SoapMessageFactory factory = new SaajSoapMessageFactory(messageFactory);
MessageContext context = new DefaultMessageContext(new SaajSoapMessage(request), factory);
interceptorMock.understands(null);
interceptorControl.setMatcher(MockControl.ALWAYS_MATCHER);
@@ -181,8 +175,7 @@ public class SoapMessageDispatcherTest extends TestCase {
String headerActor = "http://www/springframework.org/role";
header.setActor(headerActor);
header.setMustUnderstand(true);
factory.setSoapProtocol(SOAPConstants.SOAP_1_1_PROTOCOL);
factory.afterPropertiesSet();
SoapMessageFactory factory = new SaajSoapMessageFactory(messageFactory);
MessageContext context = new DefaultMessageContext(new SaajSoapMessage(request), factory);
interceptorMock.understands(null);
interceptorControl.setMatcher(MockControl.ALWAYS_MATCHER);
@@ -205,8 +198,7 @@ public class SoapMessageDispatcherTest extends TestCase {
String headerRole = "http://www/springframework.org/role";
header.setRole(headerRole);
header.setMustUnderstand(true);
factory.setSoapProtocol(SOAPConstants.SOAP_1_2_PROTOCOL);
factory.afterPropertiesSet();
SoapMessageFactory factory = new SaajSoapMessageFactory(messageFactory);
MessageContext context = new DefaultMessageContext(new SaajSoapMessage(request), factory);
interceptorMock.understands(null);
interceptorControl.setMatcher(MockControl.ALWAYS_MATCHER);
@@ -225,8 +217,7 @@ public class SoapMessageDispatcherTest extends TestCase {
MessageFactory messageFactory = MessageFactory.newInstance(SOAPConstants.SOAP_1_1_PROTOCOL);
SOAPMessage request = messageFactory.createMessage();
request.getSOAPHeader().detachNode();
factory.setSoapProtocol(SOAPConstants.SOAP_1_1_PROTOCOL);
factory.afterPropertiesSet();
SoapMessageFactory factory = new SaajSoapMessageFactory(messageFactory);
MessageContext context = new DefaultMessageContext(new SaajSoapMessage(request), factory);
interceptorControl.replay();

View File

@@ -27,6 +27,7 @@ import org.springframework.ws.context.DefaultMessageContext;
import org.springframework.ws.context.MessageContext;
import org.springframework.ws.soap.SoapMessage;
import org.springframework.ws.soap.SoapMessageException;
import org.springframework.ws.soap.SoapMessageFactory;
import org.springframework.ws.soap.SoapVersion;
import org.springframework.ws.soap.saaj.SaajSoapMessage;
import org.springframework.ws.soap.saaj.SaajSoapMessageFactory;
@@ -37,12 +38,8 @@ public class SoapFaultMappingExceptionResolverTest extends XMLTestCase {
private SoapFaultMappingExceptionResolver resolver;
private SaajSoapMessageFactory factory;
protected void setUp() throws Exception {
resolver = new SoapFaultMappingExceptionResolver();
factory = new SaajSoapMessageFactory();
}
public void testGetDepth() throws Exception {
@@ -61,8 +58,7 @@ public class SoapFaultMappingExceptionResolverTest extends XMLTestCase {
MessageFactory messageFactory = MessageFactory.newInstance(SOAPConstants.SOAP_1_1_PROTOCOL);
SOAPMessage message = messageFactory.createMessage();
factory.setSoapProtocol(SOAPConstants.SOAP_1_1_PROTOCOL);
factory.afterPropertiesSet();
SoapMessageFactory factory = new SaajSoapMessageFactory(messageFactory);
MessageContext context = new DefaultMessageContext(new SaajSoapMessage(message), factory);
boolean result = resolver.resolveException(context, null, new IllegalArgumentException("bla"));
@@ -85,8 +81,7 @@ public class SoapFaultMappingExceptionResolverTest extends XMLTestCase {
MessageFactory messageFactory = MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL);
SOAPMessage message = messageFactory.createMessage();
factory.setSoapProtocol(SOAPConstants.SOAP_1_2_PROTOCOL);
factory.afterPropertiesSet();
SoapMessageFactory factory = new SaajSoapMessageFactory(messageFactory);
MessageContext context = new DefaultMessageContext(new SaajSoapMessage(message), factory);
boolean result = resolver.resolveException(context, null, new IllegalArgumentException("bla"));
@@ -109,8 +104,7 @@ public class SoapFaultMappingExceptionResolverTest extends XMLTestCase {
MessageFactory messageFactory = MessageFactory.newInstance(SOAPConstants.SOAP_1_1_PROTOCOL);
SOAPMessage message = messageFactory.createMessage();
factory.setSoapProtocol(SOAPConstants.SOAP_1_1_PROTOCOL);
factory.afterPropertiesSet();
SoapMessageFactory factory = new SaajSoapMessageFactory(messageFactory);
MessageContext context = new DefaultMessageContext(new SaajSoapMessage(message), factory);
boolean result = resolver.resolveException(context, null, new IllegalArgumentException("bla"));
@@ -133,8 +127,7 @@ public class SoapFaultMappingExceptionResolverTest extends XMLTestCase {
MessageFactory messageFactory = MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL);
SOAPMessage message = messageFactory.createMessage();
factory.setSoapProtocol(SOAPConstants.SOAP_1_2_PROTOCOL);
factory.afterPropertiesSet();
SoapMessageFactory factory = new SaajSoapMessageFactory(messageFactory);
MessageContext context = new DefaultMessageContext(new SaajSoapMessage(message), factory);
boolean result = resolver.resolveException(context, null, new IllegalArgumentException("bla"));
@@ -159,8 +152,7 @@ public class SoapFaultMappingExceptionResolverTest extends XMLTestCase {
resolver.setDefaultFault(defaultFault);
MessageFactory messageFactory = MessageFactory.newInstance(SOAPConstants.SOAP_1_1_PROTOCOL);
SOAPMessage message = messageFactory.createMessage();
factory.setSoapProtocol(SOAPConstants.SOAP_1_1_PROTOCOL);
factory.afterPropertiesSet();
SoapMessageFactory factory = new SaajSoapMessageFactory(messageFactory);
MessageContext context = new DefaultMessageContext(new SaajSoapMessage(message), factory);
boolean result = resolver.resolveException(context, null, new IllegalArgumentException("bla"));

View File

@@ -21,8 +21,8 @@ import java.util.Iterator;
import java.util.Properties;
import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.mime.Attachment;
import org.springframework.ws.soap.AbstractSoapMessageFactoryTestCase;
import org.springframework.ws.soap.Attachment;
import org.springframework.ws.soap.SoapMessage;
import org.springframework.ws.soap.SoapVersion;
import org.springframework.ws.transport.MockTransportInputStream;
@@ -30,7 +30,7 @@ import org.springframework.ws.transport.TransportInputStream;
public abstract class AbstractSoap11MessageFactoryTestCase extends AbstractSoapMessageFactoryTestCase {
public void testCreateEmptyMessage() throws Exception {
public void testCreateEmptySoap11Message() throws Exception {
WebServiceMessage message = messageFactory.createWebServiceMessage();
assertTrue("Not a SoapMessage", message instanceof SoapMessage);
SoapMessage soapMessage = (SoapMessage) message;
@@ -50,24 +50,26 @@ public abstract class AbstractSoap11MessageFactoryTestCase extends AbstractSoapM
SoapMessage soapMessage = (SoapMessage) message;
assertEquals("Invalid soap version", SoapVersion.SOAP_11, soapMessage.getVersion());
assertEquals("Invalid soap action", soapAction, soapMessage.getSoapAction());
assertFalse("Message a XOP pacakge", soapMessage.isXopPackage());
}
public void testCreateSoapMessageSwA() throws Exception {
InputStream is = AbstractSoap11MessageFactoryTestCase.class.getResourceAsStream("soap11-attachment.bin");
Properties headers = new Properties();
headers.setProperty("Content-Type",
"multipart/related; type=\"text/xml\"; boundary=\"----=_Part_0_11416420.1149699787554\"");
"multipart/related;" + "type=\"text/xml\";" + "boundary=\"----=_Part_0_11416420.1149699787554\"");
TransportInputStream tis = new MockTransportInputStream(is, headers);
WebServiceMessage message = messageFactory.createWebServiceMessage(tis);
assertTrue("Not a SoapMessage", message instanceof SoapMessage);
SoapMessage soapMessage = (SoapMessage) message;
assertEquals("Invalid soap version", SoapVersion.SOAP_11, soapMessage.getVersion());
assertFalse("Message a XOP pacakge", soapMessage.isXopPackage());
Iterator iter = soapMessage.getAttachments();
assertTrue("No attachments read", iter.hasNext());
Attachment attachment = soapMessage.getAttachment("interface21");
assertNotNull("No attachment read", attachment);
assertEquals("Invalid content id", "interface21", attachment.getId());
assertEquals("Invalid content id", "interface21", attachment.getContentId());
}
public void testCreateSoapMessageMtom() throws Exception {
@@ -82,6 +84,7 @@ public abstract class AbstractSoap11MessageFactoryTestCase extends AbstractSoapM
assertTrue("Not a SoapMessage", message instanceof SoapMessage);
SoapMessage soapMessage = (SoapMessage) message;
assertEquals("Invalid soap version", SoapVersion.SOAP_11, soapMessage.getVersion());
assertTrue("Message not a XOP pacakge", soapMessage.isXopPackage());
Iterator iter = soapMessage.getAttachments();
assertTrue("No attachments read", iter.hasNext());

View File

@@ -53,12 +53,15 @@ public abstract class AbstractSoap11MessageTestCase extends AbstractSoapMessageT
public void testWriteToTransportResponseAttachment() throws Exception {
InputStreamSource inputStreamSource = new ByteArrayResource("contents".getBytes("UTF-8"));
soapMessage.addAttachment(inputStreamSource, "text/plain");
soapMessage.addAttachment("contentId", inputStreamSource, "text/plain");
ByteArrayOutputStream bos = new ByteArrayOutputStream();
MockTransportOutputStream tos = new MockTransportOutputStream(bos);
soapMessage.writeTo(tos);
String contentType = (String) tos.getHeaders().get("Content-Type");
assertTrue("Invalid Content-Type set", contentType.indexOf(SoapVersion.SOAP_11.getContentType()) != -1);
assertTrue("Content-Type for attachment message does not contains multipart/related",
contentType.indexOf("multipart/related") != -1);
assertTrue("Content-Type for attachment message does not contains type=\"text/xml\"",
contentType.indexOf("type=\"text/xml\"") != -1);
}

View File

@@ -21,8 +21,8 @@ import java.util.Iterator;
import java.util.Properties;
import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.mime.Attachment;
import org.springframework.ws.soap.AbstractSoapMessageFactoryTestCase;
import org.springframework.ws.soap.Attachment;
import org.springframework.ws.soap.SoapMessage;
import org.springframework.ws.soap.SoapVersion;
import org.springframework.ws.transport.MockTransportInputStream;
@@ -47,19 +47,21 @@ public abstract class AbstractSoap12MessageFactoryTestCase extends AbstractSoapM
assertTrue("Not a SoapMessage", message instanceof SoapMessage);
SoapMessage soapMessage = (SoapMessage) message;
assertEquals("Invalid soap version", SoapVersion.SOAP_12, soapMessage.getVersion());
assertFalse("Message a XOP pacakge", soapMessage.isXopPackage());
}
public void testCreateSoapMessageAttachment() throws Exception {
public void testCreateSoapMessageSwA() throws Exception {
InputStream is = AbstractSoap12MessageFactoryTestCase.class.getResourceAsStream("soap12-attachment.bin");
Properties headers = new Properties();
headers.setProperty("Content-Type",
"multipart/related; type=\"application/soap+xml\"; boundary=\"----=_Part_0_11416420.1149699787554\"");
headers.setProperty("Content-Type", "multipart/related;" + "type=\"application/soap+xml\";" +
"boundary=\"----=_Part_0_11416420.1149699787554\"");
TransportInputStream tis = new MockTransportInputStream(is, headers);
WebServiceMessage message = messageFactory.createWebServiceMessage(tis);
assertTrue("Not a SoapMessage", message instanceof SoapMessage);
SoapMessage soapMessage = (SoapMessage) message;
assertEquals("Invalid soap version", SoapVersion.SOAP_12, soapMessage.getVersion());
assertFalse("Message a XOP pacakge", soapMessage.isXopPackage());
Attachment attachment = soapMessage.getAttachment("interface21");
assertNotNull("No attachment read", attachment);
}
@@ -76,6 +78,7 @@ public abstract class AbstractSoap12MessageFactoryTestCase extends AbstractSoapM
assertTrue("Not a SoapMessage", message instanceof SoapMessage);
SoapMessage soapMessage = (SoapMessage) message;
assertEquals("Invalid soap version", SoapVersion.SOAP_12, soapMessage.getVersion());
assertTrue("Message not a XOP pacakge", soapMessage.isXopPackage());
Iterator iter = soapMessage.getAttachments();
assertTrue("No attachments read", iter.hasNext());

View File

@@ -51,12 +51,15 @@ public abstract class AbstractSoap12MessageTestCase extends AbstractSoapMessageT
public void testWriteToTransportResponseAttachment() throws Exception {
InputStreamSource inputStreamSource = new ByteArrayResource("contents".getBytes("UTF-8"));
soapMessage.addAttachment(inputStreamSource, "text/plain");
soapMessage.addAttachment("contentId", inputStreamSource, "text/plain");
ByteArrayOutputStream bos = new ByteArrayOutputStream();
MockTransportOutputStream tos = new MockTransportOutputStream(bos);
soapMessage.writeTo(tos);
String contentType = (String) tos.getHeaders().get("Content-Type");
assertTrue("Invalid Content-Type set", contentType.indexOf(SoapVersion.SOAP_12.getContentType()) != -1);
assertTrue("Content-Type for attachment message does not contains multipart/related",
contentType.indexOf("multipart/related") != -1);
assertTrue("Content-Type for attachment message does not contains type=\"application/soap+xml\"",
contentType.indexOf("type=\"application/soap+xml\"") != -1);
}

View File

@@ -18,25 +18,32 @@ package org.springframework.ws.transport;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
public class MockTransportInputStream extends TransportInputStream {
private Map headers;
private Properties headers;
private InputStream inputStream;
public MockTransportInputStream(InputStream inputStream, Map headers) {
public MockTransportInputStream(InputStream inputStream, Properties headers) {
Assert.notNull(inputStream, "inputStream must not be null");
Assert.notNull(headers, "headers must not be null");
this.inputStream = inputStream;
this.headers = headers;
}
public MockTransportInputStream(InputStream inputStream) {
Assert.notNull(inputStream, "inputStream must not be null");
this.inputStream = inputStream;
headers = new Properties();
}
protected InputStream createInputStream() throws IOException {
return inputStream;
}
@@ -46,6 +53,7 @@ public class MockTransportInputStream extends TransportInputStream {
}
public Iterator getHeaders(String name) throws IOException {
return Collections.singleton(headers.get(name)).iterator();
String[] values = StringUtils.delimitedListToStringArray(headers.getProperty(name), ", ");
return Arrays.asList(values).iterator();
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View File

@@ -1,14 +1,27 @@
---------
Upgrading
---------
Upgrading from version 1.0-M3 to 1.0-RC1
Some minor changes were made between version 1.0 Milestone 3 and Release Candidate 1 of the project. The following
should help most users the project update their applications:
* Attachments
* The <<<Attachment>>> interface was moved from <<org.springframework.ws.soap>> to <<org.springframework.ws.mime>>.
* The <<<id>>> property on <<<Attachment>> was renamed to <<contentId>>>.
* Methods for getting and adding attachments were taken from <<<SoapMessage>> and extraced into a new interface:
<<<MimeMessage>>>. Adding a method requires a content id now.
Upgrading from version 1.0-M2 to 1.0-M3
Several changes were made between version 1.0 Milestone 2 and Milestone 3 of the project. These changes increased
modularity of the code, enhanced unit testing, made package roles clearer, and added compelling alternatives to
adapters and using web.xml security constraints to protect HTTP resources.
Unfortunately, changes to the API and package locations were required. The following should help most casual users
Unfortunately, changes to the API and package locations were required. The following should help most users
the project update their applications: