This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch CAMEL-13678 in repository https://gitbox.apache.org/repos/asf/camel.git
commit 58b384151f06785f8c5a21073807a6a41402d490 Author: Claus Ibsen <claus.ib...@gmail.com> AuthorDate: Mon Jul 8 11:20:10 2019 +0200 CAMEL-13678: Move attachments out of camel-core into camel-attachments. --- .../camel-mail/src/main/docs/mail-component.adoc | 2 +- .../camel/component/mail/MailConfiguration.java | 5 +- .../apache/camel/component/mail/MailConsumer.java | 16 ++++++ .../apache/camel/component/mail/MailMessage.java | 3 ++ .../component/mail/SplitAttachmentsExpression.java | 62 +++++----------------- .../component/mail/MailSplitAttachmentsTest.java | 33 +----------- .../mail/SpringMailSplitAttachmentsTest.java | 31 ----------- .../mail/SpringMailSplitAttachmentsTest.xml | 4 +- .../endpoint/dsl/MailEndpointBuilderFactory.java | 24 +++++---- .../springboot/MailComponentConfiguration.java | 12 +++-- 10 files changed, 60 insertions(+), 132 deletions(-) diff --git a/components/camel-mail/src/main/docs/mail-component.adoc b/components/camel-mail/src/main/docs/mail-component.adoc index 792df33..664a379 100644 --- a/components/camel-mail/src/main/docs/mail-component.adoc +++ b/components/camel-mail/src/main/docs/mail-component.adoc @@ -153,7 +153,7 @@ with the following path and query parameters: | *fetchSize* (consumer) | Sets the maximum number of messages to consume during a poll. This can be used to avoid overloading a mail server, if a mailbox folder contains a lot of messages. Default value of -1 means no fetch size and all messages will be consumed. Setting the value to 0 is a special corner case, where Camel will not consume any messages at all. | -1 | int | *folderName* (consumer) | The folder to poll. | INBOX | String | *mailUidGenerator* (consumer) | A pluggable MailUidGenerator that allows to use custom logic to generate UUID of the mail message. | | MailUidGenerator -| *mapMailMessage* (consumer) | Specifies whether Camel should map the received mail message to Camel body/headers. If set to true, the body of the mail message is mapped to the body of the Camel IN message and the mail headers are mapped to IN headers. If this option is set to false then the IN message contains a raw javax.mail.Message. You can retrieve this raw message by calling exchange.getIn().getBody(javax.mail.Message.class). | true | boolean +| *mapMailMessage* (consumer) | Specifies whether Camel should map the received mail message to Camel body/headers/attachments. If set to true, the body of the mail message is mapped to the body of the Camel IN message, the mail headers are mapped to IN headers, and the attachments to Camel IN attachment message. If this option is set to false then the IN message contains a raw javax.mail.Message. You can retrieve this raw message by calling exchange.getIn().getBody(javax.mail.Message.cl [...] | *pollStrategy* (consumer) | A pluggable org.apache.camel.PollingConsumerPollingStrategy allowing you to provide your custom implementation to control error handling usually occurred during the poll operation before an Exchange have been created and being routed in Camel. | | PollingConsumerPoll Strategy | *postProcessAction* (consumer) | Refers to an MailBoxPostProcessAction for doing post processing tasks on the mailbox once the normal processing ended. | | MailBoxPostProcess Action | *bcc* (producer) | Sets the BCC email address. Separate multiple email addresses with comma. | | String diff --git a/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailConfiguration.java b/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailConfiguration.java index b365abf..d1abdd8 100644 --- a/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailConfiguration.java +++ b/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailConfiguration.java @@ -449,8 +449,9 @@ public class MailConfiguration implements Cloneable { } /** - * Specifies whether Camel should map the received mail message to Camel body/headers. - * If set to true, the body of the mail message is mapped to the body of the Camel IN message and the mail headers are mapped to IN headers. + * Specifies whether Camel should map the received mail message to Camel body/headers/attachments. + * If set to true, the body of the mail message is mapped to the body of the Camel IN message, the mail headers are mapped to IN headers, + * and the attachments to Camel IN attachment message. * If this option is set to false then the IN message contains a raw javax.mail.Message. * You can retrieve this raw message by calling exchange.getIn().getBody(javax.mail.Message.class). */ diff --git a/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailConsumer.java b/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailConsumer.java index 6acb9f5..f228287 100644 --- a/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailConsumer.java +++ b/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailConsumer.java @@ -16,9 +16,12 @@ */ package org.apache.camel.component.mail; +import java.io.IOException; import java.util.ArrayList; +import java.util.HashMap; import java.util.LinkedList; import java.util.List; +import java.util.Map; import java.util.Queue; import javax.mail.Flags; @@ -34,6 +37,9 @@ import com.sun.mail.imap.IMAPStore; import com.sun.mail.imap.SortTerm; import org.apache.camel.Exchange; import org.apache.camel.Processor; +import org.apache.camel.RuntimeCamelException; +import org.apache.camel.attachment.Attachment; +import org.apache.camel.attachment.AttachmentMessage; import org.apache.camel.support.IntrospectionSupport; import org.apache.camel.support.ScheduledBatchPollingConsumer; import org.apache.camel.support.SynchronizationAdapter; @@ -351,6 +357,16 @@ public class MailConsumer extends ScheduledBatchPollingConsumer { log.trace("Mapping #{} from javax.mail.Message to Camel MailMessage", i); exchange.getIn().getBody(); exchange.getIn().getHeaders(); + // must also map attachments + try { + Map<String, Attachment> att = new HashMap<>(); + getEndpoint().getBinding().extractAttachmentsFromMail(message, att); + if (!att.isEmpty()) { + exchange.getIn(AttachmentMessage.class).setAttachmentObjects(att); + } + } catch (MessagingException | IOException e) { + throw new RuntimeCamelException("Error accessing attachments due to: " + e.getMessage(), e); + } } // If the protocol is POP3 we need to remember the uid on the exchange diff --git a/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailMessage.java b/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailMessage.java index 836c9ee..79b7c2f 100644 --- a/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailMessage.java +++ b/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailMessage.java @@ -17,12 +17,15 @@ package org.apache.camel.component.mail; import java.io.IOException; +import java.util.HashMap; import java.util.Map; import javax.mail.Message; import javax.mail.MessagingException; import org.apache.camel.Exchange; import org.apache.camel.RuntimeCamelException; +import org.apache.camel.attachment.Attachment; +import org.apache.camel.attachment.AttachmentMap; import org.apache.camel.support.DefaultMessage; import org.apache.camel.support.ExchangeHelper; import org.apache.camel.util.ObjectHelper; diff --git a/components/camel-mail/src/main/java/org/apache/camel/component/mail/SplitAttachmentsExpression.java b/components/camel-mail/src/main/java/org/apache/camel/component/mail/SplitAttachmentsExpression.java index 66feaf7..b1a5459 100644 --- a/components/camel-mail/src/main/java/org/apache/camel/component/mail/SplitAttachmentsExpression.java +++ b/components/camel-mail/src/main/java/org/apache/camel/component/mail/SplitAttachmentsExpression.java @@ -22,11 +22,12 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import org.apache.camel.CamelContext; import org.apache.camel.Exchange; import org.apache.camel.Message; import org.apache.camel.RuntimeCamelException; -import org.apache.camel.attachment.AttachmentMessage; import org.apache.camel.attachment.Attachment; +import org.apache.camel.attachment.AttachmentMessage; import org.apache.camel.support.DefaultMessage; import org.apache.camel.support.ExpressionAdapter; import org.apache.camel.util.IOHelper; @@ -35,16 +36,9 @@ import org.apache.camel.util.IOHelper; * A {@link org.apache.camel.Expression} which can be used to split a {@link MailMessage} * per attachment. For example if a mail message has 5 attachments, then this * expression will return a <tt>List<Message></tt> that contains 5 {@link Message}. - * The message can be split 2 ways: + * The message is split: * <table> * <tr> - * <td>As an attachment</td> - * <td> - * The message is split into cloned messages, each has only one attachment. The mail attachment in each message - * remains unprocessed. - * </td> - * </tr> - * <tr> * <td>As a byte[] or String</td> * <td> * The attachments are split into new messages as the body. This allows the split messages to be easily used by @@ -60,15 +54,9 @@ public class SplitAttachmentsExpression extends ExpressionAdapter { public static final String HEADER_NAME = "CamelSplitAttachmentId"; - private boolean extractAttachments; - public SplitAttachmentsExpression() { } - public SplitAttachmentsExpression(boolean extractAttachments) { - this.extractAttachments = extractAttachments; - } - @Override public Object evaluate(Exchange exchange) { // must use getAttachments to ensure attachments is initial populated @@ -80,50 +68,36 @@ public class SplitAttachmentsExpression extends ExpressionAdapter { List<Message> answer = new ArrayList<>(); AttachmentMessage inMessage = exchange.getIn(AttachmentMessage.class); for (Map.Entry<String, Attachment> entry : inMessage.getAttachmentObjects().entrySet()) { - Message attachmentMessage; - if (extractAttachments) { - attachmentMessage = extractAttachment(inMessage, entry.getKey()); - } else { - attachmentMessage = splitAttachment(inMessage, entry.getKey(), entry.getValue()); - } - + Message attachmentMessage = extractAttachment(entry.getValue(), entry.getKey(), exchange.getContext()); if (attachmentMessage != null) { answer.add(attachmentMessage); } } + // clear attachments on original message after we have split them + inMessage.getAttachmentObjects().clear(); + return answer; } catch (Exception e) { throw new RuntimeCamelException("Unable to split attachments from MimeMultipart message", e); } } - private Message splitAttachment(Message inMessage, String attachmentName, Attachment attachmentHandler) { - final Message copy = inMessage.copy(); - final AttachmentMessage am = copy.getExchange().getMessage(AttachmentMessage.class); - Map<String, Attachment> attachments = am.getAttachmentObjects(); - attachments.clear(); - attachments.put(attachmentName, attachmentHandler); - copy.setHeader(HEADER_NAME, attachmentName); - return copy; - } - - private Message extractAttachment(AttachmentMessage inMessage, String attachmentName) throws Exception { - final Message outMessage = new DefaultMessage(inMessage.getExchange().getContext()); + private Message extractAttachment(Attachment attachment, String attachmentName, CamelContext camelContext) throws Exception { + final Message outMessage = new DefaultMessage(camelContext); outMessage.setHeader(HEADER_NAME, attachmentName); - Object attachment = inMessage.getAttachment(attachmentName).getContent(); - if (attachment instanceof InputStream) { - outMessage.setBody(readMimePart((InputStream) attachment)); + Object obj = attachment.getDataHandler().getContent(); + if (obj instanceof InputStream) { + outMessage.setBody(readMimePart((InputStream) obj)); return outMessage; - } else if (attachment instanceof String || attachment instanceof byte[]) { - outMessage.setBody(attachment); + } else if (obj instanceof String || obj instanceof byte[]) { + outMessage.setBody(obj); return outMessage; } else { return null; } } - private byte[] readMimePart(InputStream mimePartStream) throws Exception { // mimePartStream could be base64 encoded, or not, but we don't need to worry about it as // Camel is smart enough to wrap it in a decoder stream (eg Base64DecoderStream) when required @@ -132,12 +106,4 @@ public class SplitAttachmentsExpression extends ExpressionAdapter { return bos.toByteArray(); } - - public boolean isExtractAttachments() { - return extractAttachments; - } - - public void setExtractAttachments(boolean extractAttachments) { - this.extractAttachments = extractAttachments; - } } diff --git a/components/camel-mail/src/test/java/org/apache/camel/component/mail/MailSplitAttachmentsTest.java b/components/camel-mail/src/test/java/org/apache/camel/component/mail/MailSplitAttachmentsTest.java index 21f6728..d824bcc 100644 --- a/components/camel-mail/src/test/java/org/apache/camel/component/mail/MailSplitAttachmentsTest.java +++ b/components/camel-mail/src/test/java/org/apache/camel/component/mail/MailSplitAttachmentsTest.java @@ -21,7 +21,6 @@ import javax.activation.FileDataSource; import org.apache.camel.Endpoint; import org.apache.camel.Exchange; -import org.apache.camel.Message; import org.apache.camel.Producer; import org.apache.camel.attachment.AttachmentMessage; import org.apache.camel.builder.RouteBuilder; @@ -58,40 +57,10 @@ public class MailSplitAttachmentsTest extends CamelTestSupport { } @Test - public void testSplitAttachments() throws Exception { - MockEndpoint mock = getMockEndpoint("mock:split"); - mock.expectedMessageCount(2); - - Producer producer = endpoint.createProducer(); - producer.start(); - producer.process(exchange); - - mock.assertIsSatisfied(); - - AttachmentMessage first = mock.getReceivedExchanges().get(0).getIn(AttachmentMessage.class); - AttachmentMessage second = mock.getReceivedExchanges().get(1).getIn(AttachmentMessage.class); - - assertEquals(1, first.getAttachments().size()); - assertEquals(1, second.getAttachments().size()); - - String file1 = first.getAttachments().keySet().iterator().next(); - String file2 = second.getAttachments().keySet().iterator().next(); - - boolean logo = file1.equals("logo.jpeg") || file2.equals("logo.jpeg"); - boolean license = file1.equals("log4j2.properties") || file2.equals("log4j2.properties"); - - assertTrue("Should have logo.jpeg file attachment", logo); - assertTrue("Should have log4j2.properties file attachment", license); - } - - @Test public void testExtractAttachments() throws Exception { MockEndpoint mock = getMockEndpoint("mock:split"); mock.expectedMessageCount(2); - // set the expression to extract the attachments as byte[]s - splitAttachmentsExpression.setExtractAttachments(true); - Producer producer = endpoint.createProducer(); producer.start(); producer.process(exchange); @@ -118,7 +87,7 @@ public class MailSplitAttachmentsTest extends CamelTestSupport { @Override protected RouteBuilder createRouteBuilder() throws Exception { - splitAttachmentsExpression = new SplitAttachmentsExpression(false); + splitAttachmentsExpression = new SplitAttachmentsExpression(); return new RouteBuilder() { @Override diff --git a/components/camel-mail/src/test/java/org/apache/camel/component/mail/SpringMailSplitAttachmentsTest.java b/components/camel-mail/src/test/java/org/apache/camel/component/mail/SpringMailSplitAttachmentsTest.java index c12f7f9..18bb761 100644 --- a/components/camel-mail/src/test/java/org/apache/camel/component/mail/SpringMailSplitAttachmentsTest.java +++ b/components/camel-mail/src/test/java/org/apache/camel/component/mail/SpringMailSplitAttachmentsTest.java @@ -63,41 +63,10 @@ public class SpringMailSplitAttachmentsTest extends CamelSpringTestSupport { } @Test - public void testSplitAttachments() throws Exception { - MockEndpoint mock = getMockEndpoint("mock:split"); - mock.expectedMessageCount(2); - - Producer producer = endpoint.createProducer(); - producer.start(); - producer.process(exchange); - - mock.assertIsSatisfied(); - - AttachmentMessage first = mock.getReceivedExchanges().get(0).getIn(AttachmentMessage.class); - AttachmentMessage second = mock.getReceivedExchanges().get(1).getIn(AttachmentMessage.class); - - assertEquals(1, first.getAttachments().size()); - assertEquals(1, second.getAttachments().size()); - - String file1 = first.getAttachments().keySet().iterator().next(); - String file2 = second.getAttachments().keySet().iterator().next(); - - boolean logo = file1.equals("logo.jpeg") || file2.equals("logo.jpeg"); - boolean license = file1.equals("log4j2.properties") || file2.equals("log4j2.properties"); - - assertTrue("Should have logo.jpeg file attachment", logo); - assertTrue("Should have log4j2.properties file attachment", license); - } - - @Test public void testExtractAttachments() throws Exception { MockEndpoint mock = getMockEndpoint("mock:split"); mock.expectedMessageCount(2); - // set the expression to extract the attachments as byte[]s - SplitAttachmentsExpression splitAttachmentsExpression = context.getRegistry().findByType(SplitAttachmentsExpression.class).iterator().next(); - splitAttachmentsExpression.setExtractAttachments(true); - Producer producer = endpoint.createProducer(); producer.start(); producer.process(exchange); diff --git a/components/camel-mail/src/test/resources/org/apache/camel/component/mail/SpringMailSplitAttachmentsTest.xml b/components/camel-mail/src/test/resources/org/apache/camel/component/mail/SpringMailSplitAttachmentsTest.xml index a3d1276..06eb1b5 100644 --- a/components/camel-mail/src/test/resources/org/apache/camel/component/mail/SpringMailSplitAttachmentsTest.xml +++ b/components/camel-mail/src/test/resources/org/apache/camel/component/mail/SpringMailSplitAttachmentsTest.xml @@ -24,9 +24,7 @@ http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd "> - <bean id="splitAttachments" class="org.apache.camel.component.mail.SplitAttachmentsExpression"> - <constructor-arg index="0" value="false"/> - </bean> + <bean id="splitAttachments" class="org.apache.camel.component.mail.SplitAttachmentsExpression"/> <camelContext xmlns="http://camel.apache.org/schema/spring"> <route> diff --git a/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/dsl/MailEndpointBuilderFactory.java b/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/dsl/MailEndpointBuilderFactory.java index 22abb5f..1ed6891 100644 --- a/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/dsl/MailEndpointBuilderFactory.java +++ b/core/camel-endpointdsl/src/main/java/org/apache/camel/builder/endpoint/dsl/MailEndpointBuilderFactory.java @@ -1038,11 +1038,13 @@ public interface MailEndpointBuilderFactory { } /** * Specifies whether Camel should map the received mail message to Camel - * body/headers. If set to true, the body of the mail message is mapped - * to the body of the Camel IN message and the mail headers are mapped - * to IN headers. If this option is set to false then the IN message - * contains a raw javax.mail.Message. You can retrieve this raw message - * by calling exchange.getIn().getBody(javax.mail.Message.class). + * body/headers/attachments. If set to true, the body of the mail + * message is mapped to the body of the Camel IN message, the mail + * headers are mapped to IN headers, and the attachments to Camel IN + * attachment message. If this option is set to false then the IN + * message contains a raw javax.mail.Message. You can retrieve this raw + * message by calling + * exchange.getIn().getBody(javax.mail.Message.class). * * The option is a: <code>boolean</code> type. * @@ -1055,11 +1057,13 @@ public interface MailEndpointBuilderFactory { } /** * Specifies whether Camel should map the received mail message to Camel - * body/headers. If set to true, the body of the mail message is mapped - * to the body of the Camel IN message and the mail headers are mapped - * to IN headers. If this option is set to false then the IN message - * contains a raw javax.mail.Message. You can retrieve this raw message - * by calling exchange.getIn().getBody(javax.mail.Message.class). + * body/headers/attachments. If set to true, the body of the mail + * message is mapped to the body of the Camel IN message, the mail + * headers are mapped to IN headers, and the attachments to Camel IN + * attachment message. If this option is set to false then the IN + * message contains a raw javax.mail.Message. You can retrieve this raw + * message by calling + * exchange.getIn().getBody(javax.mail.Message.class). * * The option will be converted to a <code>boolean</code> type. * diff --git a/platforms/spring-boot/components-starter/camel-mail-starter/src/main/java/org/apache/camel/component/mail/springboot/MailComponentConfiguration.java b/platforms/spring-boot/components-starter/camel-mail-starter/src/main/java/org/apache/camel/component/mail/springboot/MailComponentConfiguration.java index 4443dc7..5e975b8 100644 --- a/platforms/spring-boot/components-starter/camel-mail-starter/src/main/java/org/apache/camel/component/mail/springboot/MailComponentConfiguration.java +++ b/platforms/spring-boot/components-starter/camel-mail-starter/src/main/java/org/apache/camel/component/mail/springboot/MailComponentConfiguration.java @@ -189,11 +189,13 @@ public class MailComponentConfiguration private Boolean delete = false; /** * Specifies whether Camel should map the received mail message to Camel - * body/headers. If set to true, the body of the mail message is mapped - * to the body of the Camel IN message and the mail headers are mapped - * to IN headers. If this option is set to false then the IN message - * contains a raw javax.mail.Message. You can retrieve this raw message - * by calling exchange.getIn().getBody(javax.mail.Message.class). + * body/headers/attachments. If set to true, the body of the mail + * message is mapped to the body of the Camel IN message, the mail + * headers are mapped to IN headers, and the attachments to Camel IN + * attachment message. If this option is set to false then the IN + * message contains a raw javax.mail.Message. You can retrieve this raw + * message by calling + * exchange.getIn().getBody(javax.mail.Message.class). */ private Boolean mapMailMessage = true; /**