/*******************************************************************************
* Copyright (c) 2006-2010 eBay Inc. All Rights Reserved.
* 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
*******************************************************************************/
package org.ebayopensource.turmeric.runtime.common.impl.attachment;
/*
* Copyright 2004,2005 The Apache Software Foundation.
*
* 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.
*/
import java.io.IOException;
import java.io.OutputStream;
import java.io.StringWriter;
import java.util.Iterator;
import javax.activation.DataHandler;
import javax.mail.MessagingException;
import javax.mail.internet.MimeBodyPart;
import org.apache.axiom.attachments.Attachments;
import org.apache.axiom.attachments.ConfigurableDataHandler;
import org.apache.axiom.om.OMException;
import org.apache.axiom.om.OMOutputFormat;
import org.apache.axiom.soap.SOAP11Constants;
import org.apache.axiom.soap.SOAP12Constants;
public class MIMEOutputUtils {
private static byte[] CRLF = { 13, 10 };
public static void complete(OutputStream outStream, String payload,
OutboundMessageAttachments attachments) {
try {
OutputFormat format = attachments.getOutputFormat();
String boundary = format.getMimeBoundary();
String charSetEncoding = format.getCharSetEncoding();
String payloadContentType = format.getPayloadContentType();
String contentId = format.getRootContentId();
if(payloadContentType.indexOf(";")!=-1)
payloadContentType = payloadContentType.substring(0, payloadContentType.indexOf(";"));
startWritingMime(outStream, boundary);
javax.activation.DataHandler dh = new javax.activation.DataHandler(
payload, "text/xml; charset=" + charSetEncoding);
MimeBodyPart rootMimeBodyPart = new MimeBodyPart();
rootMimeBodyPart.setDataHandler(dh);
String content_type = "application/xop+xml; charset="
+ charSetEncoding
+ "; type=\""
+ payloadContentType + "\"";
rootMimeBodyPart.addHeader("Content-Type", content_type);
rootMimeBodyPart.addHeader("Content-Transfer-Encoding", "binary");
rootMimeBodyPart.addHeader("Content-ID", "<" + contentId + ">");
writeBodyPart(outStream, rootMimeBodyPart, boundary);
String[] cids = attachments.getAllContentIds();
for (int i=0; i< cids.length; i++) {
String cid = cids[i];
dh = attachments.getDataHandler(cid);
writeBodyPart(outStream, createMimeBodyPart(cid, dh), boundary);
}
finishWritingMime(outStream);
outStream.flush();
} catch (IOException e) {
throw new OMException("Error while writing to the OutputStream.", e);
} catch (MessagingException e) {
throw new OMException("Problem writing Mime Parts.", e);
}
}
public static MimeBodyPart createMimeBodyPart(String contentID,
DataHandler dataHandler) throws MessagingException {
String encoding = null;
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);
return mimeBodyPart;
}
/**
* @throws IOException
* This will write the boundary to output Stream
*/
public static void writeMimeBoundary(OutputStream outStream, String boundary)
throws IOException {
// REVIEW: This conversion is hard-coded to UTF-8.
// The complete solution is to respect the charset setting of the
// message.
// However this may cause problems in BoundaryDelimittedStream and other
// lower level classes.
outStream.write(new byte[] { 45, 45 });
outStream.write(boundary.getBytes("UTF-8"));
}
/**
* @throws IOException
* This will write the boundary with CRLF
*/
public static void startWritingMime(OutputStream outStream, String boundary)
throws IOException {
writeMimeBoundary(outStream, boundary);
//outStream.write(CRLF);
}
/**
* Writes a CRLF for the earlier boundary then the BodyPart data with
* headers followed by boundary. Writes only the boundary. No more CRLF's
* are written after that.
*
* @throws IOException
* @throws MessagingException
*/
public static void writeBodyPart(OutputStream outStream, MimeBodyPart part,
String boundary) throws IOException, MessagingException {
outStream.write(CRLF);
part.writeTo(outStream);
outStream.write(CRLF);
writeMimeBoundary(outStream, boundary);
outStream.flush();
}
/**
* @throws IOException
* This will write "--" to the end of last boundary
*/
public static void finishWritingMime(OutputStream outStream)
throws IOException {
outStream.write(new byte[] { 45, 45 });
}
public static void writeSOAPWithAttachmentsMessage(StringWriter writer,
OutputStream outputStream, Attachments attachments,
OMOutputFormat format) {
String SOAPContentType;
try {
if (format.isSOAP11()) {
SOAPContentType = SOAP11Constants.SOAP_11_CONTENT_TYPE;
} else {
SOAPContentType = SOAP12Constants.SOAP_12_CONTENT_TYPE;
}
startWritingMime(outputStream, format.getMimeBoundary());
javax.activation.DataHandler dh = new javax.activation.DataHandler(
writer.toString(), "text/xml; charset="
+ format.getCharSetEncoding());
MimeBodyPart rootMimeBodyPart = new MimeBodyPart();
rootMimeBodyPart.setDataHandler(dh);
rootMimeBodyPart.addHeader("Content-Type", SOAPContentType
+ "; charset=" + format.getCharSetEncoding());
rootMimeBodyPart.addHeader("Content-Transfer-Encoding", "8bit");
rootMimeBodyPart.addHeader("Content-ID", "<"
+ format.getRootContentId() + ">");
writeBodyPart(outputStream, rootMimeBodyPart, format
.getMimeBoundary());
Iterator attachmentIDIterator = attachments.getContentIDSet()
.iterator();
while (attachmentIDIterator.hasNext()) {
String contentID = (String) attachmentIDIterator.next();
DataHandler dataHandler = attachments.getDataHandler(contentID);
writeBodyPart(outputStream, createMimeBodyPart(contentID,
dataHandler), format.getMimeBoundary());
}
finishWritingMime(outputStream);
outputStream.flush();
} catch (IOException e) {
throw new OMException("Error while writing to the OutputStream.", e);
} catch (MessagingException e) {
throw new OMException("Problem writing Mime Parts.", e);
}
}
/**
* Pack all the attachments in to a multipart/related MIME part and attachs
* it as the second MIME Part of MIME message
*
* @param writer
* @param outputStream
* @param attachments
* @param format
* @param innerBoundary
*/
public static void writeMM7Message(StringWriter writer,
OutputStream outputStream, Attachments attachments,
OMOutputFormat format, String innerPartCID, String innerBoundary) {
String SOAPContentType;
try {
if (format.isSOAP11()) {
SOAPContentType = SOAP11Constants.SOAP_11_CONTENT_TYPE;
} else {
SOAPContentType = SOAP12Constants.SOAP_12_CONTENT_TYPE;
}
startWritingMime(outputStream, format.getMimeBoundary());
javax.activation.DataHandler dh = new javax.activation.DataHandler(
writer.toString(), "text/xml; charset="
+ format.getCharSetEncoding());
MimeBodyPart rootMimeBodyPart = new MimeBodyPart();
rootMimeBodyPart.setDataHandler(dh);
rootMimeBodyPart.addHeader("Content-Type", SOAPContentType
+ "; charset=" + format.getCharSetEncoding());
rootMimeBodyPart.addHeader("Content-ID", "<"
+ format.getRootContentId() + ">");
writeBodyPart(outputStream, rootMimeBodyPart, format
.getMimeBoundary());
if (attachments.getContentIDSet().size() != 0) {
outputStream.write(CRLF);
StringBuffer sb = new StringBuffer();
sb.append("Content-Type: multipart/related");
sb.append("; ");
sb.append("boundary=");
sb.append("\"" + innerBoundary + "\"");
// REVIEW Should this be getBytes("UTF-8") or getBytes(charset)
outputStream.write(sb.toString().getBytes());
outputStream.write(CRLF);
StringBuffer sb1 = new StringBuffer();
sb1.append("Content-ID: ");
sb1.append("<");
sb1.append(innerPartCID);
sb1.append(">");
// REVIEW Should this be getBytes("UTF-8") or getBytes(charset)
outputStream.write(sb1.toString().getBytes());
outputStream.write(CRLF);
outputStream.write(CRLF);
startWritingMime(outputStream, innerBoundary);
Iterator attachmentIDIterator = attachments.getContentIDSet()
.iterator();
while (attachmentIDIterator.hasNext()) {
String contentID = (String) attachmentIDIterator.next();
DataHandler dataHandler = attachments
.getDataHandler(contentID);
writeBodyPart(outputStream, createMimeBodyPart(contentID,
dataHandler), innerBoundary);
}
finishWritingMime(outputStream);
outputStream.write(CRLF);
writeMimeBoundary(outputStream, format.getMimeBoundary());
}
finishWritingMime(outputStream);
outputStream.flush();
} catch (IOException e) {
throw new OMException("Error while writing to the OutputStream.", e);
} catch (MessagingException e) {
throw new OMException("Problem writing Mime Parts.", e);
}
}
public static String getContentTypeForMime(String boundary,
String contentId, String charSetEncoding, String soapContentType) {
StringBuffer sb = new StringBuffer();
sb.append("multipart/related");
sb.append(";");
sb.append("boundary=");
sb.append(boundary);
sb.append(";");
sb.append("type=\"application/xop+xml\"");
sb.append(";");
sb.append("start=\"<" + contentId + ">\"");
sb.append(";");
int index = soapContentType.indexOf(";");
// Removes the encoding part as a workaround of the problem that servlet
// rewrite content
// type with encoding into unbalanced quoted string.
if (index > 0) {
soapContentType = soapContentType.substring(0, index);
}
sb.append("start-info=\""+soapContentType + "\"");
return sb.toString();
}
}