You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2021/03/23 11:05:26 UTC

[camel] branch master updated: CAMEL-12078: camel-mail - Fix MIME-Mutipart DataFormat reads attachment DataSource twice. Thanks to Tim Dudgeon for test case.

This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/master by this push:
     new ac7ec15  CAMEL-12078: camel-mail - Fix MIME-Mutipart DataFormat reads attachment DataSource twice. Thanks to Tim Dudgeon for test case.
ac7ec15 is described below

commit ac7ec15f8e1908c9527269329cde6811e68a4491
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Tue Mar 23 12:04:29 2021 +0100

    CAMEL-12078: camel-mail - Fix MIME-Mutipart DataFormat reads attachment DataSource twice. Thanks to Tim Dudgeon for test case.
---
 .../mime/multipart/MimeMultipartDataFormat.java    |  7 ++-
 .../multipart/MimeMultipartDataFormatTest.java     | 64 ++++++++++++++++++++++
 2 files changed, 70 insertions(+), 1 deletion(-)

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 94b29de..476a51f 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
@@ -119,6 +119,8 @@ public class MimeMultipartDataFormat extends DefaultDataFormat {
                     part.setHeader(CONTENT_TYPE, ct);
                     if (!contentType.match("text/*") && binaryContent) {
                         part.setHeader(CONTENT_TRANSFER_ENCODING, "binary");
+                    } else {
+                        setContentTransferEncoding(part, contentType);
                     }
                     // Set headers to the attachment
                     for (String headerName : attachment.getHeaderNames()) {
@@ -156,7 +158,6 @@ public class MimeMultipartDataFormat extends DefaultDataFormat {
                         headers.add(h.getName());
                     }
                 }
-                mm.saveChanges();
             }
             mm.writeTo(stream, headers.toArray(new String[0]));
         } else {
@@ -183,6 +184,10 @@ public class MimeMultipartDataFormat extends DefaultDataFormat {
     private void writeBodyPart(byte[] bodyContent, Part part, ContentType contentType) throws MessagingException {
         DataSource ds = new ByteArrayDataSource(bodyContent, contentType.toString());
         part.setDataHandler(new DataHandler(ds));
+        setContentTransferEncoding(part, contentType);
+    }
+
+    private void setContentTransferEncoding(Part part, ContentType contentType) throws MessagingException {
         part.setHeader(CONTENT_TYPE, contentType.toString());
         if (contentType.match("text/*")) {
             part.setHeader(CONTENT_TRANSFER_ENCODING, "8bit");
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 f8846ec..0b8dd3f 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
@@ -41,6 +41,7 @@ import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
 
+import static org.hamcrest.CoreMatchers.startsWith;
 import static org.junit.jupiter.api.Assertions.assertArrayEquals;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
@@ -354,6 +355,42 @@ public class MimeMultipartDataFormatTest extends CamelTestSupport {
         assertEquals("This is not a MIME-Multipart", bodyStr);
     }
 
+    @Test
+    public void attachmentReadOnce() throws IOException {
+        String attContentType = "text/plain";
+        String attText = "Attachment Text";
+        InputStream attInputStream = new ByteArrayInputStream(attText.getBytes());
+        String attFileName = "Attachment File Name";
+        in.setBody("Body text");
+        in.setHeader(Exchange.CONTENT_TYPE, "text/plain;charset=iso8859-1;other-parameter=true");
+        in.setHeader("Content-Transfer-Encoding", "UTF8");
+        in.setHeader(Exchange.CONTENT_ENCODING, "UTF8");
+        Map<String, String> headers = new HashMap<String, String>();
+        headers.put("Content-Description", "Sample Attachment Data");
+        headers.put("X-AdditionalData", "additional data");
+        CountingByteArrayDataSource attachmentDs = new CountingByteArrayDataSource(attInputStream, attContentType);
+        addAttachment(attachmentDs, attFileName, headers);
+        Exchange result = template.send("direct:roundtrip", exchange);
+        AttachmentMessage out = result.getMessage(AttachmentMessage.class);
+        assertEquals("Body text", out.getBody(String.class));
+        assertTrue(out.getHeader(Exchange.CONTENT_TYPE, String.class).startsWith("text/plain"));
+        assertEquals("UTF8", out.getHeader(Exchange.CONTENT_ENCODING));
+        assertTrue(out.hasAttachments());
+        assertEquals(1, out.getAttachmentNames().size());
+        assertTrue(out.getAttachmentNames().contains(attFileName));
+        Attachment att = out.getAttachmentObject(attFileName);
+        DataHandler dh = att.getDataHandler();
+        assertNotNull(dh);
+        assertEquals(attContentType, dh.getContentType());
+        InputStream is = dh.getInputStream();
+        ByteArrayOutputStream os = new ByteArrayOutputStream();
+        IOHelper.copyAndCloseInput(is, os);
+        assertEquals(attText, new String(os.toByteArray()));
+        assertEquals("Sample Attachment Data", att.getHeader("content-description"));
+        assertEquals("additional data", att.getHeader("X-AdditionalData"));
+        assertEquals(1, attachmentDs.readCounts); // Fails - input is read twice
+    }
+
     private Attachment unmarshalAndCheckAttachmentName(String matcher) throws IOException {
         Exchange intermediate = template.send("direct:unmarshalonlyinlineheaders", exchange);
         assertNotNull(intermediate.getMessage());
@@ -373,6 +410,16 @@ public class MimeMultipartDataFormatTest extends CamelTestSupport {
         return att;
     }
 
+    private void addAttachment(DataSource ds, String attFileName, Map<String, String> headers) throws IOException {
+        DefaultAttachment attachment = new DefaultAttachment(ds);
+        if (headers != null) {
+            for (String headerName : headers.keySet()) {
+                attachment.addHeader(headerName, headers.get(headerName));
+            }
+        }
+        in.addAttachmentObject(attFileName, attachment);
+    }
+
     private void addAttachment(String attContentType, String attText, String attFileName) throws IOException {
         addAttachment(attContentType, attText, attFileName, null);
     }
@@ -409,4 +456,21 @@ public class MimeMultipartDataFormatTest extends CamelTestSupport {
             }
         };
     }
+
+    private class CountingByteArrayDataSource extends ByteArrayDataSource {
+
+        volatile int readCounts;
+
+        CountingByteArrayDataSource(InputStream is, String attContentType) throws IOException {
+            super(is, attContentType);
+        }
+
+        @Override
+        public InputStream getInputStream() throws IOException {
+            readCounts++;
+            return super.getInputStream();
+        }
+
+    }
+
 }