You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commons-dev@ws.apache.org by sc...@apache.org on 2008/09/27 01:10:12 UTC
svn commit: r699528 - in /webservices/commons/trunk/modules/axiom/modules:
axiom-api/src/main/java/org/apache/axiom/attachments/impl/
axiom-api/src/main/java/org/apache/axiom/om/
axiom-api/src/main/java/org/apache/axiom/om/impl/ axiom-api/src/main/java...
Author: scheu
Date: Fri Sep 26 16:10:11 2008
New Revision: 699528
URL: http://svn.apache.org/viewvc?rev=699528&view=rev
Log:
WSCOMMONS-390
Contributor:Rich Scheuerle
Add an OMOutputFormat option that will write out "non-textual" attachments as base64.
A "textual" attachment is an attachment part that has one of the following:
* a content-type of "text/" "attachment/xml" or "attachment/soap"
* a content-type with a "charset" parameter.
A "non-textual" type is anything else (example: image/gif)
The new property is defined in OMOutputFormat:
public static final String USE_CTE_BASE64_FOR_NON_TEXTUAL_ATTACHMENTS =
"org.apache.axiom.om.OMFormat.use.cteBase64.forNonTextualAttachments";
I also included a representative test that writes and reads attachments with the property enabled and
disabled.
Modified:
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/PartOnMemoryEnhanced.java
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/OMOutputFormat.java
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/MIMEOutputUtils.java
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/MTOMXMLStreamWriter.java
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/util/CommonUtils.java
webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/attachments/AttachmentsTest.java
Modified: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/PartOnMemoryEnhanced.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/PartOnMemoryEnhanced.java?rev=699528&r1=699527&r2=699528&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/PartOnMemoryEnhanced.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/PartOnMemoryEnhanced.java Fri Sep 26 16:10:11 2008
@@ -95,6 +95,8 @@
InputStream is = ds.getInputStream();
if (is instanceof BAAInputStream) {
((BAAInputStream)is).writeTo(os);
+ } else {
+ BufferUtils.inputStream2OutputStream(is, os);
}
}
}
Modified: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/OMOutputFormat.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/OMOutputFormat.java?rev=699528&r1=699527&r2=699528&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/OMOutputFormat.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/OMOutputFormat.java Fri Sep 26 16:10:11 2008
@@ -59,6 +59,19 @@
public static final String ACTION_PROPERTY = "action";
+ // The value of this property is a Boolean.
+ // A missing value indicates the default action, which is Boolean.FALSE
+ // If Boolean.TRUE, attachments that are "non textual" are written out with
+ // a content-transfer-encoding type of base64.
+ // @See CommonUtils.isTextualPart for the textual part definition.
+ //
+ // Example:
+ // An attachment with a content-type of "image/gif" is a non-textual attachment.
+ // An attachment with a content-type of "application/soap+xml" is an textual attachment
+ //
+ public static final String USE_CTE_BASE64_FOR_NON_TEXTUAL_ATTACHMENTS =
+ "org.apache.axiom.om.OMFormat.use.cteBase64.forNonTextualAttachments";
+
HashMap map = null; // Map of generic properties
Modified: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/MIMEOutputUtils.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/MIMEOutputUtils.java?rev=699528&r1=699527&r2=699528&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/MIMEOutputUtils.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/MIMEOutputUtils.java Fri Sep 26 16:10:11 2008
@@ -36,6 +36,7 @@
import org.apache.axiom.om.OMException;
import org.apache.axiom.om.OMOutputFormat;
import org.apache.axiom.om.OMText;
+import org.apache.axiom.om.util.CommonUtils;
import org.apache.axiom.soap.SOAP11Constants;
import org.apache.axiom.soap.SOAP12Constants;
import org.apache.commons.logging.Log;
@@ -114,6 +115,7 @@
}
}
+
/**
* Invoked by MTOMXMLStreamWriter to write the SOAP Part and the attachements.
*
@@ -132,6 +134,29 @@
String contentId,
String charSetEncoding,
String SOAPContentType) {
+ complete(outStream, xmlData, binaryNodeList, boundary,
+ contentId, charSetEncoding, SOAPContentType, null);
+ }
+ /**
+ * Invoked by MTOMXMLStreamWriter to write the SOAP Part and the attachements.
+ *
+ * @param outStream OutputStream target
+ * @param bufferedXML String containing XML of SOAPPart
+ * @param binaryNodeList Text nodes with the attachment Data Handlers
+ * @param boundary Boundary String
+ * @param contentId Content-ID of SOAPPart
+ * @param charSetEncoding Character Encoding of SOAPPart
+ * @param SOAPContentType Content-Type of SOAPPart
+ * @param OMOutputFormat
+ */
+ public static void complete(OutputStream outStream,
+ byte[] xmlData,
+ LinkedList binaryNodeList,
+ String boundary,
+ String contentId,
+ String charSetEncoding,
+ String SOAPContentType,
+ OMOutputFormat omOutputFormat) {
try {
if (isDebugEnabled) {
log.debug("Start: write the SOAPPart and the attachments");
@@ -166,7 +191,7 @@
OMText binaryNode = (OMText) binaryNodeIterator.next();
writeBodyPart(outStream, createMimeBodyPart(binaryNode
.getContentID(), (DataHandler) binaryNode
- .getDataHandler()), boundary);
+ .getDataHandler(), omOutputFormat), boundary);
}
finishWritingMime(outStream);
outStream.flush();
@@ -205,24 +230,53 @@
}
public static MimeBodyPart createMimeBodyPart(String contentID,
- DataHandler dataHandler)
+ DataHandler dataHandler)
throws MessagingException {
+ return createMimeBodyPart(contentID, dataHandler, null);
+ }
+
+ public static MimeBodyPart createMimeBodyPart(String contentID,
+ DataHandler dataHandler,
+ OMOutputFormat omOutputFormat)
+ throws MessagingException {
+ String contentType = dataHandler.getContentType();
+
+ // Get the content-transfer-encoding
+ String contentTransferEncoding = "binary";
+ if (dataHandler instanceof ConfigurableDataHandler) {
+ ConfigurableDataHandler configurableDataHandler = (ConfigurableDataHandler) dataHandler;
+ contentTransferEncoding = configurableDataHandler.getTransferEncoding();
+ }
+
if (isDebugEnabled) {
- log.debug("Create MimeBodyPart for " + contentID);
+ log.debug("Create MimeBodyPart");
+ log.debug(" Content-ID = " + contentID);
+ log.debug(" Content-Type = " + contentType);
+ log.debug(" Content-Transfer-Encoding = " + contentTransferEncoding);
+ }
+
+ boolean useCTEBase64 = omOutputFormat != null &&
+ Boolean.TRUE.equals(
+ omOutputFormat.getProperty(
+ OMOutputFormat.USE_CTE_BASE64_FOR_NON_TEXTUAL_ATTACHMENTS));
+ if (useCTEBase64) {
+ if (!CommonUtils.isTextualPart(contentType) &&
+ "binary".equals(contentTransferEncoding)) {
+ if (isDebugEnabled) {
+ log.debug(" changing Content-Transfer-Encoding from " +
+ contentTransferEncoding + " to base-64");
+ }
+ contentTransferEncoding = "base64";
+ }
+
}
- String encoding = null;
+
+ // Now create the mimeBodyPart for the datahandler and add the appropriate content headers
MimeBodyPart mimeBodyPart = new MimeBodyPart();
mimeBodyPart.setDataHandler(dataHandler);
mimeBodyPart.addHeader("Content-ID", "<" + contentID + ">");
- mimeBodyPart.addHeader("Content-Type", dataHandler.getContentType());
- if (dataHandler instanceof ConfigurableDataHandler) {
- ConfigurableDataHandler configurableDataHandler = (ConfigurableDataHandler) dataHandler;
- encoding = configurableDataHandler.getTransferEncoding();
- }
- if (encoding == null) {
- encoding = "binary";
- }
- mimeBodyPart.addHeader("Content-Transfer-Encoding", encoding);
+ mimeBodyPart.addHeader("Content-Type", contentType);
+ mimeBodyPart.addHeader("Content-Transfer-Encoding", contentTransferEncoding);
return mimeBodyPart;
}
Modified: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/MTOMXMLStreamWriter.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/MTOMXMLStreamWriter.java?rev=699528&r1=699527&r2=699528&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/MTOMXMLStreamWriter.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/MTOMXMLStreamWriter.java Fri Sep 26 16:10:11 2008
@@ -184,7 +184,8 @@
format.getMimeBoundary(),
format.getRootContentId(),
format.getCharSetEncoding(),
- SOAPContentType);
+ SOAPContentType,
+ format);
bufferedXML.close();
bufferedXML = null;
} catch (UnsupportedEncodingException e) {
Modified: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/util/CommonUtils.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/util/CommonUtils.java?rev=699528&r1=699527&r2=699528&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/util/CommonUtils.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/util/CommonUtils.java Fri Sep 26 16:10:11 2008
@@ -156,4 +156,32 @@
return logStream.getLength();
}
+ /**
+ * A "textual part" has one or more of the following criteria
+ * 1) a content-type that start with "text"
+ * "application/xml" or "application/soap"
+ * 2) has a charset parameter on the content-type.
+ *
+ * Example:
+ * An part with a content-type of "image/gif" is a non-textual attachment.
+ * An part with a content-type of "application/soap+xml" is an textual attachment
+ *
+ * @param contentType
+ * @return true if text, false otherwise
+ */
+ public static boolean isTextualPart(String contentType) {
+ String ct = contentType.trim();
+ if (ct.startsWith("text/") ||
+ ct.startsWith("application/soap") ||
+ ct.startsWith("application/xml")) {
+ // REVIEW: What about content-type with a type of "message"
+ return true;
+ }
+
+ if (ct.contains("charset")) {
+ return true;
+ }
+ return false;
+
+ }
}
Modified: webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/attachments/AttachmentsTest.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/attachments/AttachmentsTest.java?rev=699528&r1=699527&r2=699528&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/attachments/AttachmentsTest.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/attachments/AttachmentsTest.java Fri Sep 26 16:10:11 2008
@@ -20,9 +20,16 @@
package org.apache.axiom.attachments;
import org.apache.axiom.om.AbstractTestCase;
+import org.apache.axiom.om.OMElement;
+import org.apache.axiom.om.OMOutputFormat;
+import org.apache.axiom.om.impl.MTOMXMLStreamWriter;
+import org.apache.axiom.om.impl.builder.XOPAwareStAXOMBuilder;
+import org.apache.axiom.om.util.CommonUtils;
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
+
+import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
@@ -41,8 +48,16 @@
String img1FileName = "mtom/img/test.jpg";
String img2FileName = "mtom/img/test2.jpg";
+ String boundary = "MIMEBoundaryurn:uuid:A3ADBAEE51A1A87B2A11443668160701";
+ String start= "0.urn:uuid:A3ADBAEE51A1A87B2A11443668160702@apache.org";
String contentTypeString =
- "multipart/related; boundary=\"MIMEBoundaryurn:uuid:A3ADBAEE51A1A87B2A11443668160701\"; type=\"application/xop+xml\"; start=\"<0....@apache.org>\"; start-info=\"application/soap+xml\"; charset=UTF-8;action=\"mtomSample\"";
+ "multipart/related; " +
+ "boundary=\"" + boundary + "\"; " +
+ "type=\"application/xop+xml\"; " +
+ "start=\"<" + start +">\"; " +
+ "start-info=\"application/soap+xml\"; " +
+ "charset=UTF-8;" +
+ "action=\"mtomSample\"";
public void testMIMEHelper() {
}
@@ -154,6 +169,100 @@
is = attachments.getSOAPPartInputStream();
while (is.read() != -1) ;
}
+
+ public void testWritingBinaryAttachments() throws Exception {
+
+ // Read in message: SOAPPart and 2 image attachments
+ File f = getTestResourceFile(inMimeFileName);
+ InputStream inStream = new FileInputStream(f);
+ Attachments attachments = new Attachments(inStream, contentTypeString);
+
+ attachments.getSOAPPartInputStream();
+
+ String[] contentIDs = attachments.getAllContentIDs();
+
+ OMOutputFormat oof = new OMOutputFormat();
+ oof.setDoOptimize(true);
+ oof.setMimeBoundary(boundary);
+ oof.setRootContentId(start);
+
+ // Write out the message
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ MTOMXMLStreamWriter writer = new MTOMXMLStreamWriter(baos, oof);
+
+ XOPAwareStAXOMBuilder builder =
+ new XOPAwareStAXOMBuilder(attachments.getSOAPPartInputStream(),
+ attachments);
+ OMElement om = builder.getDocumentElement();
+ om.serialize(writer);
+ String outNormal = baos.toString();
+
+ assertTrue(!outNormal.contains("base64"));
+
+ // Now do it again but use base64 content-type-encoding for
+ // binary attachments
+ baos = new ByteArrayOutputStream();
+ oof.setProperty(OMOutputFormat.USE_CTE_BASE64_FOR_NON_TEXTUAL_ATTACHMENTS,
+ Boolean.TRUE);
+ writer = new MTOMXMLStreamWriter(baos, oof);
+ builder =
+ new XOPAwareStAXOMBuilder(attachments.getSOAPPartInputStream(),
+ attachments);
+ om = builder.getDocumentElement();
+ om.serialize(writer);
+ String outBase64 = baos.toString();
+
+
+ // Do a quick check to see if the data is base64 and is
+ // writing base64 compliant code.
+ assertTrue(outBase64.contains("base64"));
+ assertTrue(outBase64.contains("GBgcGBQgHBwcJCQgKDBQNDAsL"));
+
+ // Now read the data back in
+ InputStream is = new ByteArrayInputStream(outBase64.getBytes());
+ Attachments attachments2 = new Attachments(is, contentTypeString);
+
+ // Now write it back out with binary...
+ baos = new ByteArrayOutputStream();
+ oof.setProperty(OMOutputFormat.USE_CTE_BASE64_FOR_NON_TEXTUAL_ATTACHMENTS,
+ Boolean.FALSE);
+ writer = new MTOMXMLStreamWriter(baos, oof);
+ builder =
+ new XOPAwareStAXOMBuilder(attachments2.getSOAPPartInputStream(),
+ attachments2);
+ om = builder.getDocumentElement();
+ om.serialize(writer);
+ String outBase64ToNormal = baos.toString();
+
+ assertTrue(!outBase64ToNormal.contains("base64"));
+
+ // Now do it again but use base64 content-type-encoding for
+ // binary attachments
+ baos = new ByteArrayOutputStream();
+ oof.setProperty(OMOutputFormat.USE_CTE_BASE64_FOR_NON_TEXTUAL_ATTACHMENTS,
+ Boolean.TRUE);
+ writer = new MTOMXMLStreamWriter(baos, oof);
+ builder =
+ new XOPAwareStAXOMBuilder(attachments2.getSOAPPartInputStream(),
+ attachments2);
+ om = builder.getDocumentElement();
+ om.serialize(writer);
+ String outBase64ToBase64 = baos.toString();
+
+ // Do a quick check to see if the data is base64 and is
+ // writing base64 compliant code.
+ assertTrue(outBase64ToBase64.contains("base64"));
+ assertTrue(outBase64ToBase64.contains("GBgcGBQgHBwcJCQgKDBQNDAsL"));
+
+ // Some quick verifications of the isTextualPart logic
+ assertTrue(CommonUtils.isTextualPart("text/xml"));
+ assertTrue(CommonUtils.isTextualPart("application/xml"));
+ assertTrue(CommonUtils.isTextualPart("application/soap+xml"));
+ assertTrue(CommonUtils.isTextualPart("foo/bar; charset=UTF-8"));
+ assertTrue(!CommonUtils.isTextualPart("image/gif"));
+
+ }
+
private void compareStreams(InputStream data, InputStream expected) throws Exception {
byte[] dataArray = this.getStreamAsByteArray(data, -1);