Author: veithen
Date: Wed Jun 15 20:25:14 2011
New Revision: 1136177
URL: http://svn.apache.org/viewvc?rev=1136177&view=rev
Log:
AXIS2-5067: Committed patch provided by Ivan (xuhaihong), with minor changes.
This implements the saveChanges method and calculates the correct content type
for a SOAPMessage.
Modified:
axis/axis2/java/core/trunk/modules/saaj/src/org/apache/axis2/saaj/SOAPMessageImpl.java
axis/axis2/java/core/trunk/modules/saaj/src/org/apache/axis2/saaj/SOAPPartImpl.java
axis/axis2/java/core/trunk/modules/saaj/test/org/apache/axis2/saaj/SOAPMessageTest.java
Modified:
axis/axis2/java/core/trunk/modules/saaj/src/org/apache/axis2/saaj/SOAPMessageImpl.java
URL:
http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/saaj/src/org/apache/axis2/saaj/SOAPMessageImpl.java?rev=1136177&r1=1136176&r2=1136177&view=diff
==============================================================================
---
axis/axis2/java/core/trunk/modules/saaj/src/org/apache/axis2/saaj/SOAPMessageImpl.java
(original)
+++
axis/axis2/java/core/trunk/modules/saaj/src/org/apache/axis2/saaj/SOAPMessageImpl.java
Wed Jun 15 20:25:14 2011
@@ -26,9 +26,12 @@ import org.apache.axiom.om.impl.OMMultip
import org.apache.axiom.soap.SOAPEnvelope;
import org.apache.axiom.soap.impl.dom.soap11.SOAP11Factory;
import org.apache.axiom.soap.impl.dom.soap12.SOAP12Factory;
+import org.apache.axiom.util.UIDGenerator;
import org.apache.axis2.saaj.util.SAAJUtil;
import org.apache.axis2.transport.http.HTTPConstants;
+import javax.mail.internet.ContentType;
+import javax.mail.internet.ParseException;
import javax.xml.soap.AttachmentPart;
import javax.xml.soap.MimeHeader;
import javax.xml.soap.MimeHeaders;
@@ -73,13 +76,13 @@ public class SOAPMessageImpl extends SOA
String contentType = null;
String tmpContentType = "";
if (mimeHeaders != null) {
- String contentTypes[] =
mimeHeaders.getHeader(HTTPConstants.CONTENT_TYPE);
+ String contentTypes[] =
mimeHeaders.getHeader(HTTPConstants.HEADER_CONTENT_TYPE);
if (contentTypes != null && contentTypes.length > 0) {
tmpContentType = contentTypes[0];
contentType = SAAJUtil.normalizeContentType(tmpContentType);
}
}
- if ("multipart/related".equals(contentType)) {
+ if (HTTPConstants.MEDIA_TYPE_MULTIPART_RELATED.equals(contentType)) {
try {
Attachments attachments =
new Attachments(inputstream, tmpContentType, false,
"", "");
@@ -88,7 +91,7 @@ public class SOAPMessageImpl extends SOA
// parts of the SOAP message package. We need to reconstruct
them from
// the available information.
MimeHeaders soapPartHeaders = new MimeHeaders();
- soapPartHeaders.addHeader(HTTPConstants.CONTENT_TYPE,
+ soapPartHeaders.addHeader(HTTPConstants.HEADER_CONTENT_TYPE,
attachments.getSOAPPartContentType());
String soapPartContentId = attachments.getSOAPPartContentID();
soapPartHeaders.addHeader("Content-ID", "<" +
soapPartContentId + ">");
@@ -164,6 +167,7 @@ public class SOAPMessageImpl extends SOA
*/
public void removeAllAttachments() {
attachmentParts.clear();
+ saveRequired = true;
}
/**
@@ -223,7 +227,8 @@ public class SOAPMessageImpl extends SOA
public void addAttachmentPart(AttachmentPart attachmentPart) {
if (attachmentPart != null) {
attachmentParts.add(attachmentPart);
- mimeHeaders.setHeader(HTTPConstants.CONTENT_TYPE,
"multipart/related");
+ mimeHeaders.setHeader(HTTPConstants.HEADER_CONTENT_TYPE,
"multipart/related");
+ saveRequired = true;
}
}
@@ -267,8 +272,70 @@ public class SOAPMessageImpl extends SOA
* @throws SOAPException if there was a problem saving changes to this
message.
*/
public void saveChanges() throws SOAPException {
+ try {
+ String contentTypeValue =
getSingleHeaderValue(HTTPConstants.HEADER_CONTENT_TYPE);
+ ContentType contentType = null;
+ if (isEmptyString(contentTypeValue)) {
+ if (attachmentParts.size() > 0) {
+ contentTypeValue =
HTTPConstants.MEDIA_TYPE_MULTIPART_RELATED;
+ } else {
+ contentTypeValue = getBaseType();
+ }
+ }
+ contentType = new ContentType(contentTypeValue);
+
+ //Use configures the baseType with multipart/related while no
attachment exists or all the attachments are removed
+
if(contentType.getBaseType().equals(HTTPConstants.MEDIA_TYPE_MULTIPART_RELATED)
&& attachmentParts.size() == 0) {
+ contentType = new ContentType(getBaseType());
+ }
+
+ //If it is of multipart/related, initialize those required values
in the content-type, including boundary etc.
+ if
(contentType.getBaseType().equals(HTTPConstants.MEDIA_TYPE_MULTIPART_RELATED)) {
+
+ //Configure boundary
+ String boundaryParam = contentType.getParameter("boundary");
+ if (isEmptyString(boundaryParam)) {
+ contentType.setParameter("boundary",
UIDGenerator.generateMimeBoundary());
+ }
+
+ //Configure start content id, always get it from soapPart in
case it is changed
+ String soapPartContentId = soapPart.getContentId();
+ if (isEmptyString(soapPartContentId)) {
+ soapPartContentId = "<" + UIDGenerator.generateContentId()
+ ">";
+ soapPart.setContentId(soapPartContentId);
+ }
+ contentType.setParameter("start", soapPartContentId);
+
+ //Configure contentId for each attachments
+ for(AttachmentPart attachmentPart : attachmentParts) {
+ if(isEmptyString(attachmentPart.getContentId())) {
+ attachmentPart.setContentId("<" +
UIDGenerator.generateContentId() + ">");
+ }
+ }
+
+ //Configure type
+ contentType.setParameter("type", getBaseType());
+
+ //Configure charset
+ String soapPartContentTypeValue =
getSingleHeaderValue(soapPart.getMimeHeader(HTTPConstants.HEADER_CONTENT_TYPE));
+ ContentType soapPartContentType = null;
+ if (isEmptyString(soapPartContentTypeValue)) {
+ soapPartContentType = new
ContentType(soapPartContentTypeValue);
+ } else {
+ soapPartContentType = new ContentType(getBaseType());
+ }
+ setCharsetParameter(soapPartContentType);
+ } else {
+ //Configure charset
+ setCharsetParameter(contentType);
+ }
+
+ mimeHeaders.setHeader(HTTPConstants.HEADER_CONTENT_TYPE,
contentType.toString());
+ } catch (ParseException e) {
+ throw new SOAPException("Invalid Content Type Field in the Mime
Message", e);
+ }
+
saveRequired = false;
- // TODO not sure of the implementation
}
public void setSaveRequired() {
@@ -299,23 +366,45 @@ public class SOAPMessageImpl extends SOA
* @throws IOException if an I/O error occurs
*/
public void writeTo(OutputStream out) throws SOAPException, IOException {
- try {
+ try {
+ saveChanges();
OMOutputFormat format = new OMOutputFormat();
String enc = (String)getProperty(CHARACTER_SET_ENCODING);
format.setCharSetEncoding(enc != null ? enc :
OMOutputFormat.DEFAULT_CHAR_SET_ENCODING);
String writeXmlDecl = (String)getProperty(WRITE_XML_DECLARATION);
if (writeXmlDecl == null || writeXmlDecl.equals("false")) {
-
//SAAJ default case doesn't send XML decl
format.setIgnoreXMLDeclaration(true);
}
-
- SOAPEnvelope envelope =
((SOAPEnvelopeImpl)soapPart.getEnvelope()).getOMEnvelope();
+
+ SOAPEnvelope envelope = ((SOAPEnvelopeImpl)
soapPart.getEnvelope()).getOMEnvelope();
if (attachmentParts.isEmpty()) {
envelope.serialize(out, format);
} else {
-
format.setSOAP11(((SOAPEnvelopeImpl)soapPart.getEnvelope()).getOMFactory()
- instanceof SOAP11Factory);
+ ContentType contentType = new
ContentType(getSingleHeaderValue(HTTPConstants.HEADER_CONTENT_TYPE));
+ String boundary = contentType.getParameter("boundary");
+ if(isEmptyString(boundary)) {
+ boundary = UIDGenerator.generateMimeBoundary();
+ contentType.setParameter("boundary", boundary);
+ }
+ format.setMimeBoundary(boundary);
+
+ String rootContentId = soapPart.getContentId();
+ if(isEmptyString(rootContentId)) {
+ rootContentId = "<" + UIDGenerator.generateContentId() +
">";
+ soapPart.setContentId(rootContentId);
+ }
+ contentType.setParameter("start", rootContentId);
+ if ((rootContentId.indexOf("<") > -1) &
(rootContentId.indexOf(">") > -1)) {
+ rootContentId = rootContentId.substring(1,
(rootContentId.length() - 1));
+ }
+ format.setRootContentId(rootContentId);
+
+ format.setSOAP11(((SOAPEnvelopeImpl)
soapPart.getEnvelope()).getOMFactory() instanceof SOAP11Factory);
+
+ //Double save the content-type in case anything is updated
+ mimeHeaders.setHeader(HTTPConstants.HEADER_CONTENT_TYPE,
contentType.toString());
+
OMMultipartWriter mpw = new OMMultipartWriter(out, format);
OutputStream rootPartOutputStream = mpw.writeRootPart();
envelope.serialize(rootPartOutputStream);
@@ -325,7 +414,8 @@ public class SOAPMessageImpl extends SOA
}
mpw.complete();
}
- saveChanges();
+
+ saveRequired = true;
} catch (Exception e) {
throw new SOAPException(e);
}
@@ -453,6 +543,7 @@ public class SOAPMessageImpl extends SOA
}
attachmentParts.clear();
this.attachmentParts = newAttachmentParts;
+ saveRequired = true;
}
/**
@@ -502,4 +593,45 @@ public class SOAPMessageImpl extends SOA
}
}
}
+
+ private boolean isEmptyString(String value) {
+ return value == null || value.length() == 0;
+ }
+
+ private String getSingleHeaderValue(String[] values) {
+ return values != null && values.length > 0 ? values[0] : null;
+ }
+
+ private String getSingleHeaderValue(String name) {
+ String[] values = mimeHeaders.getHeader(name);
+ if (values == null || values.length == 0) {
+ return null;
+ } else {
+ return values[0];
+ }
+ }
+
+ private String getBaseType() throws SOAPException {
+ boolean isSOAP12 = ((SOAPEnvelopeImpl)
soapPart.getEnvelope()).getOMFactory() instanceof SOAP12Factory;
+ return isSOAP12 ? HTTPConstants.MEDIA_TYPE_APPLICATION_SOAP_XML :
HTTPConstants.MEDIA_TYPE_TEXT_XML;
+ }
+
+ /**
+ * If the charset is configured by CHARACTER_SET_ENCODING, set it in the
contentPart always.
+ * If it has already been configured in the contentType, leave it there.
+ * UTF-8 is used as the default value.
+ * @param contentType
+ * @throws SOAPException
+ */
+ private void setCharsetParameter(ContentType contentType) throws
SOAPException{
+ String charset = (String)getProperty(CHARACTER_SET_ENCODING);
+ if (!isEmptyString(charset)) {
+ contentType.setParameter("charset", charset);
+ } else {
+ charset = contentType.getParameter("charset");
+ if(isEmptyString(charset)) {
+ contentType.setParameter("charset", "UTF-8");
+ }
+ }
+ }
}
Modified:
axis/axis2/java/core/trunk/modules/saaj/src/org/apache/axis2/saaj/SOAPPartImpl.java
URL:
http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/saaj/src/org/apache/axis2/saaj/SOAPPartImpl.java?rev=1136177&r1=1136176&r2=1136177&view=diff
==============================================================================
---
axis/axis2/java/core/trunk/modules/saaj/src/org/apache/axis2/saaj/SOAPPartImpl.java
(original)
+++
axis/axis2/java/core/trunk/modules/saaj/src/org/apache/axis2/saaj/SOAPPartImpl.java
Wed Jun 15 20:25:14 2011
@@ -89,7 +89,7 @@ public class SOAPPartImpl extends SOAPPa
SOAPEnvelopeImpl soapEnvelope) {
//setMimeHeader(HTTPConstants.HEADER_CONTENT_ID,
IDGenerator.generateID());
//setMimeHeader(HTTPConstants.HEADER_CONTENT_TYPE, "text/xml");
- this.mimeHeaders = parentSoapMsg.getMimeHeaders();
+ this.mimeHeaders =
SAAJUtil.copyMimeHeaders(parentSoapMsg.getMimeHeaders());
soapMessage = parentSoapMsg;
envelope = soapEnvelope;
document = soapEnvelope.getOwnerDocument();
@@ -122,7 +122,7 @@ public class SOAPPartImpl extends SOAPPa
this.mimeHeaders.addHeader("Content-ID", IDGenerator.generateID());
this.mimeHeaders.addHeader("content-type",
HTTPConstants.MEDIA_TYPE_APPLICATION_SOAP_XML);
} else {
- String contentTypes[] =
mimeHeaders.getHeader(HTTPConstants.CONTENT_TYPE);
+ String contentTypes[] =
mimeHeaders.getHeader(HTTPConstants.HEADER_CONTENT_TYPE);
if (contentTypes != null && contentTypes.length > 0) {
try {
contentType = new ContentType(contentTypes[0]);
Modified:
axis/axis2/java/core/trunk/modules/saaj/test/org/apache/axis2/saaj/SOAPMessageTest.java
URL:
http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/saaj/test/org/apache/axis2/saaj/SOAPMessageTest.java?rev=1136177&r1=1136176&r2=1136177&view=diff
==============================================================================
---
axis/axis2/java/core/trunk/modules/saaj/test/org/apache/axis2/saaj/SOAPMessageTest.java
(original)
+++
axis/axis2/java/core/trunk/modules/saaj/test/org/apache/axis2/saaj/SOAPMessageTest.java
Wed Jun 15 20:25:14 2011
@@ -21,11 +21,13 @@ package org.apache.axis2.saaj;
import junit.framework.Assert;
import org.apache.axis2.saaj.util.SAAJDataSource;
+import org.apache.axis2.transport.http.HTTPConstants;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import javax.activation.DataHandler;
+import javax.mail.internet.ContentType;
import javax.xml.namespace.QName;
import javax.xml.soap.AttachmentPart;
import javax.xml.soap.MessageFactory;
@@ -45,6 +47,8 @@ import javax.xml.soap.SOAPMessage;
import javax.xml.soap.SOAPPart;
import javax.xml.transform.stream.StreamSource;
import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
@@ -187,8 +191,7 @@ public class SOAPMessageTest extends Ass
}
}
- // TODO: check why this fails with Sun's SAAJ implementation
- @Test
+ @Validated @Test
public void testGetContent() {
try {
MessageFactory fac =
MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL);
@@ -201,7 +204,7 @@ public class SOAPMessageTest extends Ass
AttachmentPart ap;
InputStream inputStream = TestUtils.getTestFile("attach.xml");
- ap = msg.createAttachmentPart(inputStream, "text/xml");
+ ap = msg.createAttachmentPart(new StreamSource(inputStream),
"text/xml");
DataHandler dh =
new DataHandler(new SAAJDataSource(inputStream, 1000,
"text/xml", true));
@@ -229,6 +232,67 @@ public class SOAPMessageTest extends Ass
}
}
+ @Validated @Test
+ public void testContentTypeGeneration() throws Exception{
+ MessageFactory fac = MessageFactory.newInstance();
+ SOAPMessage msg = fac.createMessage();
+ InputStream inputStream = TestUtils.getTestFile("attach.xml");
+ AttachmentPart ap = msg.createAttachmentPart(new
StreamSource(inputStream), "text/xml");
+ msg.addAttachmentPart(ap);
+ msg.saveChanges();
+
assertNotNull(msg.getMimeHeaders().getHeader(HTTPConstants.HEADER_CONTENT_TYPE));
+ String contentTypeValue =
msg.getMimeHeaders().getHeader(HTTPConstants.HEADER_CONTENT_TYPE)[0];
+ ContentType contentType = new ContentType(contentTypeValue);
+ assertNotNull("boundary parameter should exist in the content-type
header", contentType.getParameter("boundary"));
+ //start parameter is not checked, due to it is optional parameter, and
seems RI will not add this value
+ //assertNotNull("start parameter should exist in the content-type
header", contentType.getParameter("start"));
+ assertNotNull("type parameter should exist in the content-type
header", contentType.getParameter("type"));
+ assertEquals(HTTPConstants.MEDIA_TYPE_MULTIPART_RELATED,
contentType.getBaseType());
+ }
+
+ @Validated @Test
+ public void testCreateMessageWithMimeHeaders() throws Exception{
+ MessageFactory fac = MessageFactory.newInstance();
+ SOAPMessage msg = fac.createMessage();
+ InputStream inputStream = TestUtils.getTestFile("attach.xml");
+ AttachmentPart ap = msg.createAttachmentPart(new
StreamSource(inputStream), "text/xml");
+ msg.addAttachmentPart(ap);
+ msg.saveChanges();
+ ContentType contentType = new
ContentType(msg.getMimeHeaders().getHeader(HTTPConstants.HEADER_CONTENT_TYPE)[0]);
+
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ msg.writeTo(out);
+ SOAPMessage msg2 = fac.createMessage(msg.getMimeHeaders(), new
ByteArrayInputStream(out.toByteArray()));
+ msg2.saveChanges();
+ ContentType contentType2 = new
ContentType(msg2.getMimeHeaders().getHeader(HTTPConstants.HEADER_CONTENT_TYPE)[0]);
+
+ assertEquals(contentType.getBaseType(), contentType2.getBaseType());
+ assertEquals(contentType.getParameter("boundary"),
contentType2.getParameter("boundary"));
+ assertEquals(contentType.getParameter("type"),
contentType2.getParameter("type"));
+ //start parameter is not checked, due to it is an optional parameter,
and seems RI will not add this value
+ //assertEquals(contentType.getParameter("start"),
contentType2.getParameter("start"));
+ }
+
+ @Validated @Test
+ public void testContentTypeUpdateWithAttachmentChanges() throws Exception{
+ MessageFactory fac = MessageFactory.newInstance();
+ SOAPMessage msg = fac.createMessage();
+ InputStream inputStream = TestUtils.getTestFile("attach.xml");
+ AttachmentPart ap = msg.createAttachmentPart(new
StreamSource(inputStream), "text/xml");
+ msg.addAttachmentPart(ap);
+ msg.saveChanges();
+
+
assertNotNull(msg.getMimeHeaders().getHeader(HTTPConstants.HEADER_CONTENT_TYPE));
+ ContentType contentType = new
ContentType(msg.getMimeHeaders().getHeader(HTTPConstants.HEADER_CONTENT_TYPE)[0]);
+ assertEquals(HTTPConstants.MEDIA_TYPE_MULTIPART_RELATED,
contentType.getBaseType());
+
+ msg.removeAllAttachments();
+ msg.saveChanges();
+
+
assertNotNull(msg.getMimeHeaders().getHeader(HTTPConstants.HEADER_CONTENT_TYPE));
+ contentType = new
ContentType(msg.getMimeHeaders().getHeader(HTTPConstants.HEADER_CONTENT_TYPE)[0]);
+ assertEquals("text/xml", contentType.getBaseType());
+ }
private StringBuffer copyToBuffer(InputStream inputStream) {
if (inputStream == null) {