Repository: camel Updated Branches: refs/heads/master 740a5a73c -> 1044ce5fc
CAMEL-9544. Option to add headers to MIME-Multipart in DataFormat. Thanks to Stephan Siano for the patch. Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/1044ce5f Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/1044ce5f Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/1044ce5f Branch: refs/heads/master Commit: 1044ce5fc39c4cb51d8465f8218bda466f2703a1 Parents: 740a5a7 Author: Claus Ibsen <davscl...@apache.org> Authored: Thu Jan 28 11:37:53 2016 +0100 Committer: Claus Ibsen <davscl...@apache.org> Committed: Thu Jan 28 11:37:53 2016 +0100 ---------------------------------------------------------------------- .../apache/camel/builder/DataFormatClause.java | 24 ++++++++++++++ .../dataformat/MimeMultipartDataFormat.java | 19 +++++++++++ .../mime/multipart/MimeMultipartDataFormat.java | 28 +++++++++++++++++ .../multipart/MimeMultipartDataFormatTest.java | 33 ++++++++++++++++++++ 4 files changed, 104 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/1044ce5f/camel-core/src/main/java/org/apache/camel/builder/DataFormatClause.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/builder/DataFormatClause.java b/camel-core/src/main/java/org/apache/camel/builder/DataFormatClause.java index d9fd05b..de2a7c1 100644 --- a/camel-core/src/main/java/org/apache/camel/builder/DataFormatClause.java +++ b/camel-core/src/main/java/org/apache/camel/builder/DataFormatClause.java @@ -324,6 +324,30 @@ public class DataFormatClause<T extends ProcessorDefinition<?>> { /** * Uses the MIME Multipart data format * + * @param multipartSubType the subtype of the MIME Multipart + * @param multipartWithoutAttachment defines whether a message without attachment is also marshaled + * into a MIME Multipart (with only one body part). + * @param headersInline define the MIME Multipart headers as part of the message body + * or as Camel headers + * @param includeHeadeers if headersInline is set to true all camel headers matching this + * regex are also stored as MIME headers on the Multipart + * @param binaryContent have binary encoding for binary content (true) or use Base-64 + * encoding for binary content (false) + */ + public T mimeMultipart(String multipartSubType, boolean multipartWithoutAttachment, boolean headersInline, + String includeHeaders, boolean binaryContent) { + MimeMultipartDataFormat mm = new MimeMultipartDataFormat(); + mm.setMultipartSubType(multipartSubType); + mm.setMultipartWithoutAttachment(multipartWithoutAttachment); + mm.setHeadersInline(headersInline); + mm.setIncludeHeaders(includeHeaders); + mm.setBinaryContent(binaryContent); + return dataFormat(mm); + } + + /** + * Uses the MIME Multipart data format + * * @param multipartWithoutAttachment defines whether a message without attachment is also marshaled * into a MIME Multipart (with only one body part). * @param headersInline define the MIME Multipart headers as part of the message body http://git-wip-us.apache.org/repos/asf/camel/blob/1044ce5f/camel-core/src/main/java/org/apache/camel/model/dataformat/MimeMultipartDataFormat.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/model/dataformat/MimeMultipartDataFormat.java b/camel-core/src/main/java/org/apache/camel/model/dataformat/MimeMultipartDataFormat.java index 7116f39..535fd91 100644 --- a/camel-core/src/main/java/org/apache/camel/model/dataformat/MimeMultipartDataFormat.java +++ b/camel-core/src/main/java/org/apache/camel/model/dataformat/MimeMultipartDataFormat.java @@ -44,6 +44,8 @@ public class MimeMultipartDataFormat extends DataFormatDefinition { @Metadata(defaultValue = "false") private Boolean headersInline; @XmlAttribute + private String includeHeaders; + @XmlAttribute @Metadata(defaultValue = "false") private Boolean binaryContent; @@ -62,6 +64,9 @@ public class MimeMultipartDataFormat extends DataFormatDefinition { if (getHeadersInline() != null) { setProperty(camelContext, dataFormat, "headersInline", getHeadersInline()); } + if (getIncludeHeaders() != null) { + setProperty(camelContext, dataFormat, "includeHeaders", getIncludeHeaders()); + } if (getBinaryContent() != null) { setProperty(camelContext, dataFormat, "binaryContent", getBinaryContent()); } @@ -113,6 +118,20 @@ public class MimeMultipartDataFormat extends DataFormatDefinition { } /** + * A regex that defines which Camel headers are also included as MIME headers + * into the MIME multipart. This will only work if headersInline is set to true. + * <p> + * Default is to include no headers + */ + public void setIncludeHeaders(String includeHeaders) { + this.includeHeaders = includeHeaders; + } + + public String getIncludeHeaders() { + return includeHeaders; + } + + /** * Defines whether the content of binary parts in the MIME multipart is * binary (true) or Base-64 encoded (false) * <p> http://git-wip-us.apache.org/repos/asf/camel/blob/1044ce5f/components/camel-mail/src/main/java/org/apache/camel/dataformat/mime/multipart/MimeMultipartDataFormat.java ---------------------------------------------------------------------- diff --git a/components/camel-mail/src/main/java/org/apache/camel/dataformat/mime/multipart/MimeMultipartDataFormat.java b/components/camel-mail/src/main/java/org/apache/camel/dataformat/mime/multipart/MimeMultipartDataFormat.java index 7d6cf1c..51fdd2c 100644 --- a/components/camel-mail/src/main/java/org/apache/camel/dataformat/mime/multipart/MimeMultipartDataFormat.java +++ b/components/camel-mail/src/main/java/org/apache/camel/dataformat/mime/multipart/MimeMultipartDataFormat.java @@ -24,6 +24,7 @@ import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import java.util.Map; +import java.util.regex.Pattern; import javax.activation.DataHandler; import javax.activation.DataSource; @@ -57,9 +58,11 @@ public class MimeMultipartDataFormat implements DataFormat { private static final String CONTENT_TYPE = "Content-Type"; private static final String CONTENT_TRANSFER_ENCODING = "Content-Transfer-Encoding"; private static final String DEFAULT_CONTENT_TYPE = "application/octet-stream"; + private static final String[] STANDARD_HEADERS = {"Message-ID", "MIME-Version", "Content-Type"}; private String multipartSubType = "mixed"; private boolean multipartWithoutAttachment; private boolean headersInline; + private Pattern includeHeaders; private boolean binaryContent; public void setBinaryContent(boolean binaryContent) { @@ -70,6 +73,10 @@ public class MimeMultipartDataFormat implements DataFormat { this.headersInline = headersInline; } + public void setIncludeHeaders(String includeHeaders) { + this.includeHeaders = Pattern.compile(includeHeaders, Pattern.CASE_INSENSITIVE); + } + public void setMultipartWithoutAttachment(boolean multipartWithoutAttachment) { this.multipartWithoutAttachment = multipartWithoutAttachment; } @@ -108,6 +115,18 @@ public class MimeMultipartDataFormat implements DataFormat { exchange.getOut().removeAttachment(attachmentFilename); } mm.setContent(mp); + // copy headers if required and if the content can be converted into + // a String + if (headersInline && includeHeaders != null) { + for (Map.Entry<String, Object> entry : exchange.getIn().getHeaders().entrySet()) { + if (includeHeaders.matcher(entry.getKey()).matches()) { + String headerStr = ExchangeHelper.convertToType(exchange, String.class, entry.getValue()); + if (headerStr != null) { + mm.setHeader(entry.getKey(), headerStr); + } + } + } + } mm.saveChanges(); Enumeration<?> hl = mm.getAllHeaders(); List<String> headers = new ArrayList<String>(); @@ -168,6 +187,15 @@ public class MimeMultipartDataFormat implements DataFormat { camelMessage = exchange.getOut(); MessageHelper.copyHeaders(exchange.getIn(), camelMessage, true); contentType = mimeMessage.getHeader(CONTENT_TYPE, null); + // write the MIME headers not generated by javamail as Camel headers + Enumeration<?> headersEnum = mimeMessage.getNonMatchingHeaders(STANDARD_HEADERS); + while (headersEnum.hasMoreElements()) { + Object ho = headersEnum.nextElement(); + if (ho instanceof Header) { + Header header = (Header) ho; + camelMessage.setHeader(header.getName(), header.getValue()); + } + } } else { // check if this a multipart at all. Otherwise do nothing contentType = exchange.getIn().getHeader(CONTENT_TYPE, String.class); http://git-wip-us.apache.org/repos/asf/camel/blob/1044ce5f/components/camel-mail/src/test/java/org/apache/camel/dataformat/mime/multipart/MimeMultipartDataFormatTest.java ---------------------------------------------------------------------- diff --git a/components/camel-mail/src/test/java/org/apache/camel/dataformat/mime/multipart/MimeMultipartDataFormatTest.java b/components/camel-mail/src/test/java/org/apache/camel/dataformat/mime/multipart/MimeMultipartDataFormatTest.java index c839074..dbc7c04 100644 --- a/components/camel-mail/src/test/java/org/apache/camel/dataformat/mime/multipart/MimeMultipartDataFormatTest.java +++ b/components/camel-mail/src/test/java/org/apache/camel/dataformat/mime/multipart/MimeMultipartDataFormatTest.java @@ -34,6 +34,8 @@ import org.junit.Before; import org.junit.Test; import static org.hamcrest.core.IsCollectionContaining.hasItem; +import static org.hamcrest.core.IsNot.not; +import static org.hamcrest.core.StringContains.containsString; import static org.hamcrest.core.StringStartsWith.startsWith; public class MimeMultipartDataFormatTest extends CamelTestSupport { @@ -252,6 +254,35 @@ public class MimeMultipartDataFormatTest extends CamelTestSupport { assertThat(result.getOut().getHeader("Content-Type", String.class), startsWith("multipart/related")); } + @Test + public void marhsalUnmarshalInlineHeaders() throws IOException { + in.setBody("Body text"); + in.setHeader("Content-Type", "text/plain"); + in.setHeader("included", "must be included"); + in.setHeader("excluded", "should not be there"); + in.setHeader("x-foo", "any value"); + in.setHeader("x-bar", "also there"); + in.setHeader("xbar", "should not be there"); + addAttachment("application/octet-stream", "foobar", "attachment.bin"); + Exchange intermediate = template.send("direct:marshalonlyinlineheaders", exchange); + String bodyStr = intermediate.getOut().getBody(String.class); + assertThat(bodyStr, containsString("must be included")); + assertThat(bodyStr, not(containsString("should not be there"))); + assertThat(bodyStr, containsString("x-foo:")); + assertThat(bodyStr, containsString("x-bar:")); + assertThat(bodyStr, not(containsString("xbar"))); + intermediate.setIn(intermediate.getOut()); + intermediate.setOut(null); + intermediate.getIn().removeHeaders(".*"); + intermediate.getIn().setHeader("included", "should be replaced"); + Exchange out = template.send("direct:unmarshalonlyinlineheaders", intermediate); + assertEquals("Body text", out.getOut().getBody(String.class)); + assertEquals("must be included", out.getOut().getHeader("included")); + assertNull(out.getOut().getHeader("excluded")); + assertEquals("any value", out.getOut().getHeader("x-foo")); + assertEquals("also there", out.getOut().getHeader("x-bar")); + } + private void addAttachment(String attContentType, String attText, String attFileName) throws IOException { DataSource ds = new ByteArrayDataSource(attText, attContentType); in.addAttachment(attFileName, new DataHandler(ds)); @@ -268,6 +299,8 @@ public class MimeMultipartDataFormatTest extends CamelTestSupport { from("direct:roundtripbinarycontent").marshal().mimeMultipart(false, false, true).to("log:mime?showHeaders=true").to("dataformat:mime-multipart:unmarshal"); from("direct:marshalonlyrelated").marshal().mimeMultipart("related"); from("direct:marshalonlymixed").marshal().mimeMultipart(); + from("direct:marshalonlyinlineheaders").marshal().mimeMultipart("mixed", false, true, "(included|x-.*)", false); + from("direct:unmarshalonlyinlineheaders").unmarshal().mimeMultipart(false, true, false); } }; }