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 2009/05/14 08:46:08 UTC

svn commit: r774657 - in /camel/trunk/components/camel-mail/src: main/java/org/apache/camel/component/mail/ test/java/org/apache/camel/component/mail/ test/resources/

Author: davsclaus
Date: Thu May 14 06:46:07 2009
New Revision: 774657

URL: http://svn.apache.org/viewvc?rev=774657&view=rev
Log:
MR-173: Added TRACE logging to camel-mail and option for ContentTypeResolver to work around bugs in geronimo mail jar.

Added:
    camel/trunk/components/camel-mail/src/main/java/org/apache/camel/component/mail/ContentTypeResolver.java   (with props)
    camel/trunk/components/camel-mail/src/test/java/org/apache/camel/component/mail/MailContentTypeResolverTest.java
      - copied, changed from r774627, camel/trunk/components/camel-mail/src/test/java/org/apache/camel/component/mail/MailAttachmentTest.java
Modified:
    camel/trunk/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailBinding.java
    camel/trunk/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailComponent.java
    camel/trunk/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailEndpoint.java
    camel/trunk/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailMessage.java
    camel/trunk/components/camel-mail/src/test/java/org/apache/camel/component/mail/MailSubjectTest.java
    camel/trunk/components/camel-mail/src/test/resources/log4j.properties

Added: camel/trunk/components/camel-mail/src/main/java/org/apache/camel/component/mail/ContentTypeResolver.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-mail/src/main/java/org/apache/camel/component/mail/ContentTypeResolver.java?rev=774657&view=auto
==============================================================================
--- camel/trunk/components/camel-mail/src/main/java/org/apache/camel/component/mail/ContentTypeResolver.java (added)
+++ camel/trunk/components/camel-mail/src/main/java/org/apache/camel/component/mail/ContentTypeResolver.java Thu May 14 06:46:07 2009
@@ -0,0 +1,45 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.camel.component.mail;
+
+/**
+ * Resolver to determine Content-Type for file attachments.
+ * <p/>
+ * Strategy introduced to work around mail providers having problems with this such as geronimo mail jars.
+ * <p/>
+ * Note using SUN mail jar have no problem with resolving Content-Type based on file attachments. This resolver
+ * is thus only needed to work around mail providers having bugs or when you a new mime type is unknown by the
+ * mail provider allowing you to deterime it.
+ *
+ * @version $Revision$
+ */
+public interface ContentTypeResolver {
+
+    /**
+     * Resolves the mime content-type based on the attachment file name.
+     * <p/>
+     * Return <tt>null</tt> if you cannot resolve a content type or want to rely on the mail provider
+     * to resolve it for you.
+     * <p/>
+     * The returned value should only be the mime part of the ContentType header, for example:
+     * <tt>image/jpeg</tt> should be returned. Camel will add the remaining <tt>; name=FILENAME</tt>.
+     *
+     * @param fileName  the attachment file nane
+     * @return the Content-Type or <tt>null</tt> to rely on the mail provider
+     */
+    public String resolveContentType(String fileName);
+}

Propchange: camel/trunk/components/camel-mail/src/main/java/org/apache/camel/component/mail/ContentTypeResolver.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: camel/trunk/components/camel-mail/src/main/java/org/apache/camel/component/mail/ContentTypeResolver.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Modified: camel/trunk/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailBinding.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailBinding.java?rev=774657&r1=774656&r2=774657&view=diff
==============================================================================
--- camel/trunk/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailBinding.java (original)
+++ camel/trunk/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailBinding.java Thu May 14 06:46:07 2009
@@ -43,6 +43,8 @@
 import org.apache.camel.spi.HeaderFilterStrategy;
 import org.apache.camel.util.CollectionHelper;
 import org.apache.camel.util.ObjectHelper;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 
 /**
  * A Strategy used to convert between a Camel {@link Exchange} and {@link Message} to and
@@ -52,14 +54,17 @@
  */
 public class MailBinding {
 
+    private static final transient Log LOG = LogFactory.getLog(MailBinding.class);
     private HeaderFilterStrategy headerFilterStrategy;
+    private ContentTypeResolver contentTypeResolver;
 
     public MailBinding() {
         headerFilterStrategy = new DefaultHeaderFilterStrategy();
     }
 
-    public MailBinding(HeaderFilterStrategy headerFilterStrategy) {
+    public MailBinding(HeaderFilterStrategy headerFilterStrategy, ContentTypeResolver contentTypeResolver) {
         this.headerFilterStrategy = headerFilterStrategy;
+        this.contentTypeResolver = contentTypeResolver;
     }
 
     public void populateMailMessage(MailEndpoint endpoint, MimeMessage mimeMessage, Exchange exchange)
@@ -152,7 +157,7 @@
     }
 
     private void setRecipientFromCamelMessage(MimeMessage mimeMessage, Exchange exchange,
-                                                org.apache.camel.Message camelMessage)
+                                              org.apache.camel.Message camelMessage)
         throws MessagingException {
 
         for (Map.Entry<String, Object> entry : camelMessage.getHeaders().entrySet()) {
@@ -208,34 +213,63 @@
         multipart.setSubType("mixed");
         addBodyToMultipart(camelMessage, configuration, multipart);
         String partDisposition = configuration.isUseInlineAttachments() ?  Part.INLINE : Part.ATTACHMENT;
-        addAttachmentsToMultipart(camelMessage, multipart, partDisposition);
+        if (camelMessage.hasAttachments()) {
+            addAttachmentsToMultipart(camelMessage, multipart, partDisposition);
+        }
         return multipart;
     }
 
     protected void addAttachmentsToMultipart(org.apache.camel.Message camelMessage, MimeMultipart multipart, String partDisposition) throws MessagingException {
+        LOG.trace("Adding attachments +++ start +++");
+        int i = 0;
         for (Map.Entry<String, DataHandler> entry : camelMessage.getAttachments().entrySet()) {
             String attachmentFilename = entry.getKey();
             DataHandler handler = entry.getValue();
+
+            if (LOG.isTraceEnabled()) {
+                LOG.trace("Attachment #" + i + ": Disposition: " + partDisposition);
+                LOG.trace("Attachment #" + i + ": DataHandler: " + handler);
+                LOG.trace("Attachment #" + i + ": FileName: " + attachmentFilename);
+            }
             if (handler != null) {
-                if (shouldOutputAttachment(camelMessage, attachmentFilename, handler)) {
+                if (shouldAddAttachment(camelMessage, attachmentFilename, handler)) {
                     // Create another body part
                     BodyPart messageBodyPart = new MimeBodyPart();
                     // Set the data handler to the attachment
                     messageBodyPart.setDataHandler(handler);
                     
                     if (attachmentFilename.toLowerCase().startsWith("cid:")) {
-                    // add a Content-ID header to the attachment
+                        // add a Content-ID header to the attachment
                         messageBodyPart.addHeader("Content-ID", attachmentFilename.substring(4));
                     }
+
                     // Set the filename
                     messageBodyPart.setFileName(attachmentFilename);
+                    LOG.trace("Attachment #" + i + ": ContentType: " + messageBodyPart.getContentType());
+
+                    if (contentTypeResolver != null) {
+                        String contentType = contentTypeResolver.resolveContentType(attachmentFilename);
+                        LOG.trace("Attachment #" + i + ": Using content type resolver: " + contentTypeResolver + " resolved content type as: " + contentType);
+                        if (contentType != null) {
+                            String value = contentType + "; name=" + attachmentFilename;
+                            messageBodyPart.setHeader("Content-Type", value);
+                            LOG.trace("Attachment #" + i + ": ContentType: " + messageBodyPart.getContentType());
+                        }
+                    }
+
                     // Set Disposition
                     messageBodyPart.setDisposition(partDisposition);
                     // Add part to multipart
                     multipart.addBodyPart(messageBodyPart);
+                } else {
+                    LOG.trace("shouldAddAttachment: false");
                 }
+            } else {
+                LOG.warn("Cannot add attachment: " + attachmentFilename + " as DataHandler is null");
             }
+            i++;
         }
+        LOG.trace("Adding attachments +++ done +++");
     }
 
     protected void createMultipartAlternativeMessage(MimeMessage mimeMessage, org.apache.camel.Message camelMessage, MailConfiguration configuration)
@@ -281,11 +315,10 @@
         activeMultipart.addBodyPart(bodyMessage);
     }
 
-
     /**
-     * Strategy to allow filtering of attachments which are put on the Mail message
+     * Strategy to allow filtering of attachments which are added on the Mail message
      */
-    protected boolean shouldOutputAttachment(org.apache.camel.Message camelMessage, String attachmentFilename, DataHandler handler) {
+    protected boolean shouldAddAttachment(org.apache.camel.Message camelMessage, String attachmentFilename, DataHandler handler) {
         return true;
     }
 

Modified: camel/trunk/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailComponent.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailComponent.java?rev=774657&r1=774656&r2=774657&view=diff
==============================================================================
--- camel/trunk/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailComponent.java (original)
+++ camel/trunk/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailComponent.java Thu May 14 06:46:07 2009
@@ -33,6 +33,7 @@
  */
 public class MailComponent extends DefaultComponent {
     private MailConfiguration configuration;
+    private ContentTypeResolver contentTypeResolver;
 
     public MailComponent() {
         this.configuration = new MailConfiguration();
@@ -63,6 +64,7 @@
         configureAdditionalJavaMailProperties(config, parameters);
 
         MailEndpoint endpoint = new MailEndpoint(uri, this, config);
+        endpoint.setContentTypeResolver(contentTypeResolver);
         setProperties(endpoint.getConfiguration(), parameters);
 
         // sanity check that we know the mail server
@@ -112,4 +114,11 @@
         return path;
     }
 
+    public ContentTypeResolver getContentTypeResolver() {
+        return contentTypeResolver;
+    }
+
+    public void setContentTypeResolver(ContentTypeResolver contentTypeResolver) {
+        this.contentTypeResolver = contentTypeResolver;
+    }
 }

Modified: camel/trunk/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailEndpoint.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailEndpoint.java?rev=774657&r1=774656&r2=774657&view=diff
==============================================================================
--- camel/trunk/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailEndpoint.java (original)
+++ camel/trunk/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailEndpoint.java Thu May 14 06:46:07 2009
@@ -38,6 +38,7 @@
     private MailBinding binding;
     private MailConfiguration configuration;
     private HeaderFilterStrategy headerFilterStrategy = new DefaultHeaderFilterStrategy();
+    private ContentTypeResolver contentTypeResolver;
 
     public MailEndpoint() {
     }
@@ -111,7 +112,7 @@
 
     public MailBinding getBinding() {
         if (binding == null) {
-            binding = new MailBinding(headerFilterStrategy);
+            binding = new MailBinding(headerFilterStrategy, contentTypeResolver);
         }
         return binding;
     }
@@ -139,4 +140,11 @@
         this.headerFilterStrategy = headerFilterStrategy;
     }
 
+    public ContentTypeResolver getContentTypeResolver() {
+        return contentTypeResolver;
+    }
+
+    public void setContentTypeResolver(ContentTypeResolver contentTypeResolver) {
+        this.contentTypeResolver = contentTypeResolver;
+    }
 }

Modified: camel/trunk/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailMessage.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailMessage.java?rev=774657&r1=774656&r2=774657&view=diff
==============================================================================
--- camel/trunk/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailMessage.java (original)
+++ camel/trunk/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailMessage.java Thu May 14 06:46:07 2009
@@ -28,6 +28,8 @@
 import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.impl.DefaultMessage;
 import org.apache.camel.util.CollectionHelper;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 
 /**
  * Represents a {@link org.apache.camel.Message} for working with Mail
@@ -35,6 +37,7 @@
  * @version $Revision:520964 $
  */
 public class MailMessage extends DefaultMessage {
+    private static final transient Log LOG = LogFactory.getLog(MailMessage.class);
     private Message mailMessage;
 
     public MailMessage() {
@@ -138,29 +141,46 @@
     protected static void extractAttachments(Message message, Map<String, DataHandler> map)
         throws javax.mail.MessagingException, IOException {
 
+        LOG.trace("Extracting attachments +++ start +++");
+
         Object content = message.getContent();
         if (content instanceof Multipart) {
             extractFromMultipart((Multipart)content, map);
+        } else if (content != null) {
+            LOG.trace("No attachments to extract as content is not Multipart: " + content.getClass().getName());
         }
+
+        LOG.trace("Extracting attachments +++ done +++");
     }
     
     protected static void extractFromMultipart(Multipart mp, Map<String, DataHandler> map) 
         throws javax.mail.MessagingException, IOException {
 
         for (int i = 0; i < mp.getCount(); i++) {
-            Part part = mp.getBodyPart(i);           
+            Part part = mp.getBodyPart(i);
+            LOG.trace("Part #" + i + ": " + part);
+
             if (part.isMimeType("multipart/*")) {
+                LOG.trace("Part #" + i + ": is mimetype: multipart/*");
                 extractFromMultipart((Multipart)part.getContent(), map);
             } else {
                 String disposition = part.getDisposition();
-                if (disposition != null) {
-                    if (disposition.equalsIgnoreCase(Part.ATTACHMENT) || disposition.equalsIgnoreCase(Part.INLINE)) {
-                        // only add named attachments
-                        if (part.getFileName() != null) {
-                            // Parts marked with a disposition of Part.ATTACHMENT
-                            // are clearly attachments
-                            CollectionHelper.appendValue(map, part.getFileName(), part.getDataHandler());
-                        }
+                if (LOG.isTraceEnabled()) {
+                    LOG.trace("Part #" + i + ": Disposition: " + part.getDisposition());
+                    LOG.trace("Part #" + i + ": Description: " + part.getDescription());
+                    LOG.trace("Part #" + i + ": ContentType: " + part.getContentType());
+                    LOG.trace("Part #" + i + ": FileName: " + part.getFileName());
+                    LOG.trace("Part #" + i + ": Size: " + part.getSize());
+                    LOG.trace("Part #" + i + ": LineCount: " + part.getLineCount());
+                }
+
+                if (disposition != null && (disposition.equalsIgnoreCase(Part.ATTACHMENT) || disposition.equalsIgnoreCase(Part.INLINE))) {
+                    // only add named attachments
+                    String fileName = part.getFileName();
+                    if (fileName != null) {
+                        LOG.debug("Mail contains file attachment: " + fileName);
+                        // Parts marked with a disposition of Part.ATTACHMENT are clearly attachments
+                        CollectionHelper.appendValue(map, fileName, part.getDataHandler());
                     }
                 }
             }

Copied: camel/trunk/components/camel-mail/src/test/java/org/apache/camel/component/mail/MailContentTypeResolverTest.java (from r774627, camel/trunk/components/camel-mail/src/test/java/org/apache/camel/component/mail/MailAttachmentTest.java)
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-mail/src/test/java/org/apache/camel/component/mail/MailContentTypeResolverTest.java?p2=camel/trunk/components/camel-mail/src/test/java/org/apache/camel/component/mail/MailContentTypeResolverTest.java&p1=camel/trunk/components/camel-mail/src/test/java/org/apache/camel/component/mail/MailAttachmentTest.java&r1=774627&r2=774657&rev=774657&view=diff
==============================================================================
--- camel/trunk/components/camel-mail/src/test/java/org/apache/camel/component/mail/MailAttachmentTest.java (original)
+++ camel/trunk/components/camel-mail/src/test/java/org/apache/camel/component/mail/MailContentTypeResolverTest.java Thu May 14 06:46:07 2009
@@ -17,7 +17,6 @@
 package org.apache.camel.component.mail;
 
 import java.util.Map;
-
 import javax.activation.DataHandler;
 import javax.activation.FileDataSource;
 
@@ -32,11 +31,9 @@
 /**
  * Unit test for Camel attachments and Mail attachments.
  */
-public class MailAttachmentTest extends ContextTestSupport {
-
-    public void testSendAndRecieveMailWithAttachments() throws Exception {
-        // START SNIPPET: e1
+public class MailContentTypeResolverTest extends ContextTestSupport {
 
+    public void testCustomContentTypeResolver() throws Exception {
         // create an exchange with a normal body and attachment to be produced as email
         Endpoint endpoint = context.getEndpoint("smtp://james@mymailserver.com?password=secret");
 
@@ -53,8 +50,6 @@
         // and let it go (processes the exchange by sending the email)
         producer.process(exchange);
 
-        // END SNIPPET: e1
-
         // need some time for the mail to arrive on the inbox (consumed and sent to the mock)
         Thread.sleep(1000);
 
@@ -74,8 +69,8 @@
         DataHandler handler = out.getIn().getAttachment("logo.jpeg");
         assertNotNull("The logo should be there", handler);
 
-        // TODO: content type does not work with geronomi mail jar (its a buggy jar, use SUN mail jar instead)
-        // assertEquals("image/jpeg; name=logo.jpeg", handler.getContentType());
+        // as we use a custom content type resolver the content type should then be fixed and correct
+        assertEquals("image/jpeg; name=logo.jpeg", handler.getContentType());
 
         producer.stop();
     }
@@ -83,8 +78,15 @@
     protected RouteBuilder createRouteBuilder() throws Exception {
         return new RouteBuilder() {
             public void configure() throws Exception {
+                MailComponent mail = getContext().getComponent("smtp", MailComponent.class);
+                mail.setContentTypeResolver(new ContentTypeResolver() {
+                    public String resolveContentType(String fileName) {
+                        return "image/jpeg";
+                    }
+                });
+
                 from("pop3://james@mymailserver.com?password=secret&consumer.delay=1000").to("mock:result");
             }
         };
     }
-}
+}
\ No newline at end of file

Modified: camel/trunk/components/camel-mail/src/test/java/org/apache/camel/component/mail/MailSubjectTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-mail/src/test/java/org/apache/camel/component/mail/MailSubjectTest.java?rev=774657&r1=774656&r2=774657&view=diff
==============================================================================
--- camel/trunk/components/camel-mail/src/test/java/org/apache/camel/component/mail/MailSubjectTest.java (original)
+++ camel/trunk/components/camel-mail/src/test/java/org/apache/camel/component/mail/MailSubjectTest.java Thu May 14 06:46:07 2009
@@ -40,6 +40,8 @@
         template.sendBody("direct:a", body);
 
         mock.assertIsSatisfied();
+
+        assertFalse("Should not have attachements", mock.getExchanges().get(0).getIn().hasAttachments());
     }
 
     protected RouteBuilder createRouteBuilder() throws Exception {

Modified: camel/trunk/components/camel-mail/src/test/resources/log4j.properties
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-mail/src/test/resources/log4j.properties?rev=774657&r1=774656&r2=774657&view=diff
==============================================================================
--- camel/trunk/components/camel-mail/src/test/resources/log4j.properties (original)
+++ camel/trunk/components/camel-mail/src/test/resources/log4j.properties Thu May 14 06:46:07 2009
@@ -32,4 +32,4 @@
 log4j.appender.file.file=target/camel-mail-test.log
 
 # debug logging for Camel
-log4j.logger.org.apache.camel.component.mail=DEBUG
\ No newline at end of file
+log4j.logger.org.apache.camel.component.mail=TRACE
\ No newline at end of file