package org.jentrata.ebms.messaging;
import org.apache.camel.Exchange;
import org.apache.camel.Message;
import org.apache.camel.support.ExpressionAdapter;
import org.jentrata.ebms.EbmsConstants;
import javax.activation.DataHandler;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* A splitter that takes a list of attachments on a message and splits them out
* into individual messages with attachment being set as the body on the new
* message. The original message body is available as message header called
* CamelOriginalBody
*
* @author aaronwalker
*/
public class SplitAttachmentsToBody extends ExpressionAdapter {
public static final String ORIGINAL_MESSAGE_BODY = "CamelOriginalBody";
private static final String[] DEFAULT_HEADERS = {
EbmsConstants.CONTENT_ID,
EbmsConstants.CONTENT_TYPE,
EbmsConstants.MESSAGE_ID,
EbmsConstants.EBMS_MESSAGE_MEP,
EbmsConstants.MESSAGE_DIRECTION,
EbmsConstants.EBMS_VERSION,
EbmsConstants.MESSAGE_STATUS,
EbmsConstants.MESSAGE_FROM,
EbmsConstants.MESSAGE_TO,
EbmsConstants.MESSAGE_CONVERSATION_ID,
EbmsConstants.MESSAGE_SERVICE,
EbmsConstants.MESSAGE_ACTION,
};
private final boolean copyOriginalMessage;
private final boolean copyHeaders;
private boolean includeOriginalMessage = false;
private final String [] headersToCopy;
public SplitAttachmentsToBody(){
this(true,true,false);
}
public SplitAttachmentsToBody(boolean copyOriginalMessage) {
this(copyOriginalMessage,true,false);
}
public SplitAttachmentsToBody(boolean copyOriginalMessage, boolean copyHeaders) {
this(copyOriginalMessage,copyHeaders,false);
}
public SplitAttachmentsToBody(boolean copyOriginalMessage, boolean copyHeaders, boolean includeOriginalMessage) {
this.copyOriginalMessage = copyOriginalMessage;
this.copyHeaders = copyHeaders;
this.includeOriginalMessage = includeOriginalMessage;
this.headersToCopy = DEFAULT_HEADERS;
}
public SplitAttachmentsToBody(boolean copyOriginalMessage, boolean includeOriginalMessage, String...headersToCopy) {
this.copyOriginalMessage = copyOriginalMessage;
this.copyHeaders = false;
this.includeOriginalMessage = includeOriginalMessage;
this.headersToCopy = headersToCopy;
}
@Override
public Object evaluate(Exchange exchange) {
String originalBody = exchange.getIn().getBody(String.class);
// must use getAttachments to ensure attachments is initial populated
if (!includeOriginalMessage && exchange.getIn().getAttachments().isEmpty()) {
return null;
}
// we want to provide a list of messages with 1 attachment per mail
List<Message> answer = new ArrayList<>();
if(includeOriginalMessage && originalBody != null && originalBody.length() > 0) {
String contentId = exchange.getIn().getHeader(EbmsConstants.CONTENT_ID,EbmsConstants.SOAP_BODY_PAYLOAD_ID,String.class);
String contentType = exchange.getIn().getHeader(EbmsConstants.CONTENT_ID,EbmsConstants.TEXT_XML_CONTENT_TYPE,String.class);
Message soapBodyMessage = createNewMessage(contentId,
contentType,
exchange.getIn().getBody(InputStream.class),
exchange);
copyOriginalMessage(exchange, originalBody, soapBodyMessage);
answer.add(soapBodyMessage);
}
for (Map.Entry<String, DataHandler> entry : exchange.getIn().getAttachments().entrySet()) {
try {
Message copy = createNewMessage(entry.getKey(),
entry.getValue().getContentType(),
entry.getValue().getInputStream(),
exchange);
copyOriginalMessage(exchange, originalBody, copy);
answer.add(copy);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return answer;
}
private void copyOriginalMessage(Exchange exchange, String originalBody, Message copy) {
if(copyOriginalMessage) {
Object body = exchange.getIn().getHeader(ORIGINAL_MESSAGE_BODY);
if(body != null) {
copy.setHeader(ORIGINAL_MESSAGE_BODY,body);
} else {
copy.setHeader(ORIGINAL_MESSAGE_BODY,originalBody);
}
}
}
private Message createNewMessage(String contentId, String contentType, InputStream stream, Exchange exchange) {
final Message copy = exchange.getIn().copy();
copy.getAttachments().clear();
if(!copyHeaders) {
copy.removeHeaders("*");
}
if(!copyHeaders && headersToCopy != null && headersToCopy.length > 0) {
extractHeaders(copy,exchange.getIn().getHeaders(), headersToCopy);
}
// get the content and convert it to byte[]
byte[] data = exchange.getContext().getTypeConverter().convertTo(byte[].class, stream);
copy.setBody(data);
copy.setHeader(EbmsConstants.CONTENT_ID,contentId);
copy.setHeader(EbmsConstants.CONTENT_TYPE,contentType);
return copy;
}
private void extractHeaders(Message copy, Map<String, Object> headers, String[] headersToCopy) {
for(String header : headersToCopy) {
copy.setHeader(header,headers.get(header));
}
}
}