You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by si...@apache.org on 2016/07/19 10:24:19 UTC

[1/2] camel git commit: CAMEL-9880: Header Support for Attachments in Camel 2.18

Repository: camel
Updated Branches:
  refs/heads/master 00b59137b -> 50d6d4fb9


http://git-wip-us.apache.org/repos/asf/camel/blob/50d6d4fb/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 7759c49..ada79c0 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
@@ -22,14 +22,18 @@ import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.UnsupportedEncodingException;
+import java.util.HashMap;
+import java.util.Map;
 
 import javax.activation.DataHandler;
 import javax.activation.DataSource;
 import javax.mail.util.ByteArrayDataSource;
 
+import org.apache.camel.Attachment;
 import org.apache.camel.Exchange;
 import org.apache.camel.Message;
 import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.impl.DefaultAttachment;
 import org.apache.camel.impl.DefaultExchange;
 import org.apache.camel.test.junit4.CamelTestSupport;
 import org.apache.camel.util.IOHelper;
@@ -61,7 +65,10 @@ public class MimeMultipartDataFormatTest extends CamelTestSupport {
         in.setBody("Body text");
         in.setHeader(Exchange.CONTENT_TYPE, "text/plain;charset=iso8859-1;other-parameter=true");
         in.setHeader(Exchange.CONTENT_ENCODING, "UTF8");
-        addAttachment(attContentType, attText, attFileName);
+        Map<String, String> headers = new HashMap<String, String>();
+        headers.put("Content-Description", "Sample Attachment Data");
+        headers.put("X-AdditionalData", "additional data");
+        addAttachment(attContentType, attText, attFileName, headers);
         Exchange result = template.send("direct:roundtrip", exchange);
         Message out = result.getOut();
         assertEquals("Body text", out.getBody(String.class));
@@ -70,13 +77,16 @@ public class MimeMultipartDataFormatTest extends CamelTestSupport {
         assertTrue(out.hasAttachments());
         assertEquals(1, out.getAttachmentNames().size());
         assertThat(out.getAttachmentNames(), hasItem(attFileName));
-        DataHandler dh = out.getAttachment(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"));
     }
 
     @Test
@@ -245,9 +255,14 @@ public class MimeMultipartDataFormatTest extends CamelTestSupport {
     public void marhsalOnlyMixed() throws IOException {
         in.setBody("Body text");
         in.setHeader("Content-Type", "text/plain");
-        addAttachment("application/octet-stream", "foobar", "attachment.bin");
+        Map<String, String> headers = new HashMap<String, String>();
+        headers.put("Content-Description", "Sample Attachment Data");
+        headers.put("X-AdditionalData", "additional data");
+        addAttachment("application/octet-stream", "foobar", "attachment.bin", headers);
         Exchange result = template.send("direct:marshalonlymixed", exchange);
         assertThat(result.getOut().getHeader("Content-Type", String.class), startsWith("multipart/mixed"));
+        String resultBody = result.getOut().getBody(String.class);
+        assertThat(resultBody, containsString("Content-Description: Sample Attachment Data"));
     }
 
     @Test
@@ -291,7 +306,11 @@ public class MimeMultipartDataFormatTest extends CamelTestSupport {
     @Test
     public void unmarshalRelated() throws IOException {
         in.setBody(new File("src/test/resources/multipart-related.txt"));
-        unmarshalAndCheckAttachmentName("950120.aaCB@XIson.com");
+        Attachment dh = unmarshalAndCheckAttachmentName("950120.aaCB@XIson.com");
+        assertNotNull(dh);
+        assertEquals("The fixed length records", dh.getHeader("Content-Description"));
+        assertEquals("header value1,header value2", dh.getHeader("X-Additional-Header"));
+        assertEquals(2, dh.getHeaderAsList("X-Additional-Header").size());
     }
 
     @Test
@@ -332,7 +351,7 @@ public class MimeMultipartDataFormatTest extends CamelTestSupport {
         assertEquals("This is not a MIME-Multipart", bodyStr);
     }
 
-    private void unmarshalAndCheckAttachmentName(String matcher) throws IOException, UnsupportedEncodingException {
+    private Attachment unmarshalAndCheckAttachmentName(String matcher) throws IOException, UnsupportedEncodingException {
         Exchange intermediate = template.send("direct:unmarshalonlyinlineheaders", exchange);
         assertNotNull(intermediate.getOut());
         String bodyStr = intermediate.getOut().getBody(String.class);
@@ -340,17 +359,29 @@ public class MimeMultipartDataFormatTest extends CamelTestSupport {
         assertThat(bodyStr, startsWith("25"));
         assertEquals(1, intermediate.getOut().getAttachmentNames().size());
         assertThat(intermediate.getOut().getAttachmentNames().iterator().next(), containsString(matcher));
-        DataHandler dh = intermediate.getOut().getAttachment(intermediate.getOut().getAttachmentNames().iterator().next());
+        Attachment att = intermediate.getOut().getAttachmentObject(intermediate.getOut().getAttachmentNames().iterator().next());
+        DataHandler dh = att.getDataHandler();
         assertNotNull(dh);
         ByteArrayOutputStream bos = new ByteArrayOutputStream();
         dh.writeTo(bos);
         String attachmentString = new String(bos.toByteArray(), "UTF-8");
         assertThat(attachmentString, startsWith("Old MacDonald had a farm"));
+        return att;
     }
 
     private void addAttachment(String attContentType, String attText, String attFileName) throws IOException {
+        addAttachment(attContentType, attText, attFileName, null);
+    }
+
+    private void addAttachment(String attContentType, String attText, String attFileName, Map<String, String> headers) throws IOException {
         DataSource ds = new ByteArrayDataSource(attText, attContentType);
-        in.addAttachment(attFileName, new DataHandler(ds));
+        DefaultAttachment attachment = new DefaultAttachment(ds);
+        if (headers != null) {
+            for (String headerName : headers.keySet()) {
+                attachment.addHeader(headerName, headers.get(headerName));
+            }
+        }
+        in.addAttachmentObject(attFileName, attachment);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/camel/blob/50d6d4fb/components/camel-mail/src/test/resources/multipart-related.txt
----------------------------------------------------------------------
diff --git a/components/camel-mail/src/test/resources/multipart-related.txt b/components/camel-mail/src/test/resources/multipart-related.txt
index 71b9e1c..1455c53 100644
--- a/components/camel-mail/src/test/resources/multipart-related.txt
+++ b/components/camel-mail/src/test/resources/multipart-related.txt
@@ -16,6 +16,8 @@ Content-ID: <95...@XIson.com>
 --example-1
 Content-Type: Application/octet-stream
 Content-Description: The fixed length records
+X-Additional-Header: header value1
+X-Additional-Header: header value2
 Content-Transfer-Encoding: base64
 Content-ID: <95...@XIson.com>
 

http://git-wip-us.apache.org/repos/asf/camel/blob/50d6d4fb/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/AnalyticsApiProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/AnalyticsApiProcessor.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/AnalyticsApiProcessor.java
index cb01912..2a35f62 100644
--- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/AnalyticsApiProcessor.java
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/AnalyticsApiProcessor.java
@@ -209,7 +209,7 @@ public class AnalyticsApiProcessor extends AbstractSalesforceProcessor {
 
         // copy headers and attachments
         out.getHeaders().putAll(exchange.getIn().getHeaders());
-        out.getAttachments().putAll(exchange.getIn().getAttachments());
+        out.getAttachmentObjects().putAll(exchange.getIn().getAttachmentObjects());
 
         // signal exchange completion
         callback.done(false);

http://git-wip-us.apache.org/repos/asf/camel/blob/50d6d4fb/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/BulkApiProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/BulkApiProcessor.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/BulkApiProcessor.java
index f83ad9d..b1be0e4 100644
--- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/BulkApiProcessor.java
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/BulkApiProcessor.java
@@ -416,7 +416,7 @@ public class BulkApiProcessor extends AbstractSalesforceProcessor {
 
         // copy headers and attachments
         out.getHeaders().putAll(exchange.getIn().getHeaders());
-        out.getAttachments().putAll(exchange.getIn().getAttachments());
+        out.getAttachmentObjects().putAll(exchange.getIn().getAttachmentObjects());
 
         // signal exchange completion
         callback.done(false);

http://git-wip-us.apache.org/repos/asf/camel/blob/50d6d4fb/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/JsonRestProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/JsonRestProcessor.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/JsonRestProcessor.java
index 1e8f948..4005dc4 100644
--- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/JsonRestProcessor.java
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/JsonRestProcessor.java
@@ -169,7 +169,7 @@ public class JsonRestProcessor extends AbstractRestProcessor {
             }
             // copy headers and attachments
             exchange.getOut().getHeaders().putAll(exchange.getIn().getHeaders());
-            exchange.getOut().getAttachments().putAll(exchange.getIn().getAttachments());
+            exchange.getOut().getAttachmentObjects().putAll(exchange.getIn().getAttachmentObjects());
         } catch (IOException e) {
             String msg = "Error parsing JSON response: " + e.getMessage();
             exchange.setException(new SalesforceException(msg, e));

http://git-wip-us.apache.org/repos/asf/camel/blob/50d6d4fb/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/XmlRestProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/XmlRestProcessor.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/XmlRestProcessor.java
index 3f8756f..4979197 100644
--- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/XmlRestProcessor.java
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/XmlRestProcessor.java
@@ -234,7 +234,7 @@ public class XmlRestProcessor extends AbstractRestProcessor {
             }
             // copy headers and attachments
             exchange.getOut().getHeaders().putAll(exchange.getIn().getHeaders());
-            exchange.getOut().getAttachments().putAll(exchange.getIn().getAttachments());
+            exchange.getOut().getAttachmentObjects().putAll(exchange.getIn().getAttachmentObjects());
         } catch (XStreamException e) {
             String msg = "Error parsing XML response: " + e.getMessage();
             exchange.setException(new SalesforceException(msg, e));

http://git-wip-us.apache.org/repos/asf/camel/blob/50d6d4fb/components/camel-scala/src/main/scala/org/apache/camel/scala/RichMessage.scala
----------------------------------------------------------------------
diff --git a/components/camel-scala/src/main/scala/org/apache/camel/scala/RichMessage.scala b/components/camel-scala/src/main/scala/org/apache/camel/scala/RichMessage.scala
index bc5cec0..627bb7c 100644
--- a/components/camel-scala/src/main/scala/org/apache/camel/scala/RichMessage.scala
+++ b/components/camel-scala/src/main/scala/org/apache/camel/scala/RichMessage.scala
@@ -16,6 +16,7 @@
  */
 package org.apache.camel.scala
 
+import org.apache.camel.Attachment
 import org.apache.camel.Message
 import javax.activation.DataHandler
 import java.util
@@ -27,6 +28,8 @@ class RichMessage(val message: Message) extends Message {
 
   def addAttachment(id: String, content: DataHandler) = message.addAttachment(id, content)
 
+  def addAttachmentObject(id: String, content: Attachment) = message.addAttachmentObject(id, content)
+
   def copy = new RichMessage(message.copy)
 
   def copyAttachments(other: Message) = message.copyAttachments(other)
@@ -38,10 +41,14 @@ class RichMessage(val message: Message) extends Message {
 
   def getAttachment(id: String) = message.getAttachment(id)
 
+  def getAttachmentObject(id: String) = message.getAttachmentObject(id)
+
   def getAttachmentNames = message.getAttachmentNames
 
   def getAttachments = message.getAttachments
 
+  def getAttachmentObjects = message.getAttachmentObjects
+
   def getBody = message.getBody
 
   def getBody[T](bodyType: Class[T]) = message.getBody(bodyType)
@@ -80,6 +87,8 @@ class RichMessage(val message: Message) extends Message {
 
   def setAttachments(attachments: util.Map[String, DataHandler]) = message.setAttachments(attachments)
 
+  def setAttachmentObjects(attachments: util.Map[String, Attachment]) = message.setAttachmentObjects(attachments)
+
   def setBody(body: Any) = message.setBody(body)
 
   def setBody[T](body: Any, bodyType: Class[T]) = message.setBody(body, bodyType)

http://git-wip-us.apache.org/repos/asf/camel/blob/50d6d4fb/components/camel-scala/src/test/scala/org/apache/camel/scala/dsl/PipelineTest.scala
----------------------------------------------------------------------
diff --git a/components/camel-scala/src/test/scala/org/apache/camel/scala/dsl/PipelineTest.scala b/components/camel-scala/src/test/scala/org/apache/camel/scala/dsl/PipelineTest.scala
index c067b92..2597d39 100644
--- a/components/camel-scala/src/test/scala/org/apache/camel/scala/dsl/PipelineTest.scala
+++ b/components/camel-scala/src/test/scala/org/apache/camel/scala/dsl/PipelineTest.scala
@@ -38,6 +38,7 @@ class PipelineTest extends ScalaTestSupport {
 
     out.setHeader("test", "testValue")
     out.addAttachment("test1.xml", new DataHandler(new FileDataSource("pom.xml")))
+    out.getAttachmentObject("test1.xml").addHeader("attachmentHeader", "testvalue")
   }
 
   val removeHeaderAndAttachment = (exchange: Exchange) => {
@@ -45,6 +46,7 @@ class PipelineTest extends ScalaTestSupport {
     out.copyFrom(exchange.getIn)
 
     assertNotNull("The test attachment should not be null", out.getAttachment("test1.xml"))
+    assertNotNull("The test attachement header should not be null", out.getAttachmentObject("test1.xml").getHeader("attachmentHeader"))
     assertNotNull("The test header should not be null", out.getHeader("test"))
     out.removeAttachment("test1.xml")
     out.removeHeader("test") : Unit

http://git-wip-us.apache.org/repos/asf/camel/blob/50d6d4fb/components/camel-servlet/src/main/java/org/apache/camel/component/servlet/AttachmentHttpBinding.java
----------------------------------------------------------------------
diff --git a/components/camel-servlet/src/main/java/org/apache/camel/component/servlet/AttachmentHttpBinding.java b/components/camel-servlet/src/main/java/org/apache/camel/component/servlet/AttachmentHttpBinding.java
index 084e1a3..d84a271 100644
--- a/components/camel-servlet/src/main/java/org/apache/camel/component/servlet/AttachmentHttpBinding.java
+++ b/components/camel-servlet/src/main/java/org/apache/camel/component/servlet/AttachmentHttpBinding.java
@@ -20,14 +20,15 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.util.Collection;
-import javax.activation.DataHandler;
 import javax.activation.DataSource;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.Part;
 
+import org.apache.camel.Attachment;
 import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.http.common.DefaultHttpBinding;
 import org.apache.camel.http.common.HttpMessage;
+import org.apache.camel.impl.DefaultAttachment;
 
 /**
  * To handle attachments with Servlet.
@@ -45,7 +46,13 @@ final class AttachmentHttpBinding extends DefaultHttpBinding {
             Collection<Part> parts = request.getParts();
             for (Part part : parts) {
                 DataSource ds = new PartDataSource(part);
-                message.addAttachment(part.getName(), new DataHandler(ds));
+                Attachment attachment = new DefaultAttachment(ds);
+                for (String headerName : part.getHeaderNames()) {
+                    for (String headerValue : part.getHeaders(headerName)) {
+                        attachment.addHeader(headerName, headerValue);
+                    }
+                }
+                message.addAttachmentObject(part.getName(), attachment);
             }
         } catch (Exception e) {
             throw new RuntimeCamelException("Cannot populate attachments", e);

http://git-wip-us.apache.org/repos/asf/camel/blob/50d6d4fb/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/SjmsMessage.java
----------------------------------------------------------------------
diff --git a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/SjmsMessage.java b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/SjmsMessage.java
index 92f8531..907985e 100644
--- a/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/SjmsMessage.java
+++ b/components/camel-sjms/src/main/java/org/apache/camel/component/sjms/SjmsMessage.java
@@ -99,7 +99,7 @@ public class SjmsMessage extends DefaultMessage {
 
         getAttachments().clear();
         if (that.hasAttachments()) {
-            getAttachments().putAll(that.getAttachments());
+            getAttachmentObjects().putAll(that.getAttachmentObjects());
         }
     }
 


[2/2] camel git commit: CAMEL-9880: Header Support for Attachments in Camel 2.18

Posted by si...@apache.org.
CAMEL-9880: Header Support for Attachments in Camel 2.18


Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/50d6d4fb
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/50d6d4fb
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/50d6d4fb

Branch: refs/heads/master
Commit: 50d6d4fb98660df1351d7779a1fb2f8f13d4e1ac
Parents: 00b5913
Author: Stephan Siano <st...@sap.com>
Authored: Mon Jul 18 14:55:08 2016 +0200
Committer: Stephan Siano <st...@sap.com>
Committed: Tue Jul 19 12:23:44 2016 +0200

----------------------------------------------------------------------
 .../main/java/org/apache/camel/Attachment.java  |  83 +++++++++++
 .../org/apache/camel/AttachmentObjects.java     |  35 +++++
 .../main/java/org/apache/camel/Attachments.java |   5 +-
 .../src/main/java/org/apache/camel/Message.java |  30 ++++
 .../apache/camel/builder/ExpressionBuilder.java |  36 +++++
 .../camel/builder/ExpressionClauseSupport.java  |   2 +-
 .../apache/camel/component/bean/BeanInfo.java   |   5 +-
 .../camel/converter/AttachmentConverter.java    |  43 ++++++
 .../apache/camel/impl/DefaultAttachment.java    | 125 +++++++++++++++++
 .../org/apache/camel/impl/DefaultMessage.java   |  74 +++++++---
 .../org/apache/camel/impl/MessageSupport.java   |   6 +-
 .../converter/CorePackageScanClassResolver.java |   2 +
 .../org/apache/camel/processor/Splitter.java    |   2 +-
 .../org/apache/camel/util/AttachmentMap.java    | 140 +++++++++++++++++++
 .../apache/camel/BodyAndHeaderConvertTest.java  |   5 +-
 .../camel/builder/ExpressionClauseTest.java     |   6 +-
 .../bean/BeanMethodWithExchangeTest.java        |   9 +-
 .../bean/BeanWithAttachmentAnnotationTest.java  |  44 +++++-
 .../apache/camel/impl/DefaultMessageTest.java   |   4 +-
 ...essageWithAttachmentRedeliveryIssueTest.java |   3 +-
 .../apache/camel/processor/PipelineTest.java    |   3 +
 .../camel/component/cxf/DefaultCxfBinding.java  |  34 ++++-
 .../component/cxf/jaxrs/SimpleCxfRsBinding.java |  25 +++-
 .../component/cxf/DefaultCxfBindingTest.java    |  21 ++-
 .../apache/camel/component/jcr/JcrMessage.java  |   2 +-
 .../component/jetty9/AttachmentHttpBinding.java |  11 +-
 .../jetty/MultiPartFormOkHttpTest.java          |   1 +
 .../apache/camel/component/jms/JmsMessage.java  |   2 +-
 .../camel/component/mail/MailBinding.java       |  35 +++--
 .../camel/component/mail/MailMessage.java       |   3 +-
 .../apache/camel/component/mail/MailUtils.java  |   1 +
 .../mail/SplitAttachmentsExpression.java        |   8 +-
 .../mime/multipart/MimeMultipartDataFormat.java |  26 +++-
 .../component/mail/MailAttachmentTest.java      |  13 +-
 .../multipart/MimeMultipartDataFormatTest.java  |  45 +++++-
 .../src/test/resources/multipart-related.txt    |   2 +
 .../processor/AnalyticsApiProcessor.java        |   2 +-
 .../internal/processor/BulkApiProcessor.java    |   2 +-
 .../internal/processor/JsonRestProcessor.java   |   2 +-
 .../internal/processor/XmlRestProcessor.java    |   2 +-
 .../org/apache/camel/scala/RichMessage.scala    |   9 ++
 .../apache/camel/scala/dsl/PipelineTest.scala   |   2 +
 .../servlet/AttachmentHttpBinding.java          |  11 +-
 .../camel/component/sjms/SjmsMessage.java       |   2 +-
 44 files changed, 829 insertions(+), 94 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/50d6d4fb/camel-core/src/main/java/org/apache/camel/Attachment.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/Attachment.java b/camel-core/src/main/java/org/apache/camel/Attachment.java
new file mode 100644
index 0000000..6cdc0e4
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/Attachment.java
@@ -0,0 +1,83 @@
+/**
+ * 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;
+
+import java.util.Collection;
+import java.util.List;
+
+import javax.activation.DataHandler;
+
+/**
+ * Represents an attachment as part of a {@link Message}.
+ */
+public interface Attachment {
+    /**
+     * Return a DataHandler for the content within this attachment.
+     *
+     * @return DataHandler for the content
+     */
+    DataHandler getDataHandler();
+
+    /**
+     * Get all the headers for this header name. Returns null if no headers for
+     * this header name are available.
+     *
+     * @param headerName he name of this header
+     * @return a comma separated list of all header values
+     */
+    String getHeader(String headerName);
+
+    /**
+     * Get all the headers for this header name. Returns null if no headers for
+     * this header name are available.
+     *
+     * @param headerName he name of this header
+     * @return a list of all header values
+     */
+    List<String> getHeaderAsList(String name);
+
+    /**
+     * Get all header names for this attachment.
+     *
+     * @return a collection of all header names
+     */
+    Collection<String> getHeaderNames();
+
+    /**
+     * Set the value for this headerName. Replaces all existing header values
+     * with this new value.
+     * 
+     * @param headerName the name of this header
+     * @param headerValue the value for this header
+     */
+    void setHeader(String headerName, String headerValue);
+
+    /**
+     * Add this value to the existing values for this headerName.
+     * 
+     * @param headerName the name of this header
+     * @param headerValue the value for this header
+     */
+    void addHeader(String headerName, String headerValue);
+
+    /**
+     * Remove all headers with this name.
+     * 
+     * @param headerName the name of this header
+     */
+    void removeHeader(String headerName);
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/50d6d4fb/camel-core/src/main/java/org/apache/camel/AttachmentObjects.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/AttachmentObjects.java b/camel-core/src/main/java/org/apache/camel/AttachmentObjects.java
new file mode 100644
index 0000000..58d376f
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/AttachmentObjects.java
@@ -0,0 +1,35 @@
+/**
+ * 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;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Marks a parameter as being Map of attachments as {@link Attachment} objects
+ * of an inbound {@link Message}
+ * 
+ * @version
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Target({ElementType.PARAMETER })
+public @interface AttachmentObjects {
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/50d6d4fb/camel-core/src/main/java/org/apache/camel/Attachments.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/Attachments.java b/camel-core/src/main/java/org/apache/camel/Attachments.java
index df363ea..d400534 100644
--- a/camel-core/src/main/java/org/apache/camel/Attachments.java
+++ b/camel-core/src/main/java/org/apache/camel/Attachments.java
@@ -23,9 +23,10 @@ import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
 
 /**
- * Marks a parameter as being Map of attachments of an inbound {@link Message}
+ * Marks a parameter as being Map of attachments as
+ * {@link javax.activation.DataHandler} objects of an inbound {@link Message}
  * 
- * @version 
+ * @version
  */
 @Retention(RetentionPolicy.RUNTIME)
 @Documented

http://git-wip-us.apache.org/repos/asf/camel/blob/50d6d4fb/camel-core/src/main/java/org/apache/camel/Message.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/Message.java b/camel-core/src/main/java/org/apache/camel/Message.java
index dd576a8..7efb34c 100644
--- a/camel-core/src/main/java/org/apache/camel/Message.java
+++ b/camel-core/src/main/java/org/apache/camel/Message.java
@@ -256,6 +256,14 @@ public interface Message {
     DataHandler getAttachment(String id);
 
     /**
+     * Returns the attachment specified by the id
+     *
+     * @param id the id under which the attachment is stored
+     * @return the attachment or <tt>null</tt>
+     */
+    Attachment getAttachmentObject(String id);
+
+    /**
      * Returns a set of attachment names of the message
      *
      * @return a set of attachment names
@@ -278,6 +286,14 @@ public interface Message {
     void addAttachment(String id, DataHandler content);
 
     /**
+     * Adds an attachment to the message using the id
+     *
+     * @param id        the id to store the attachment under
+     * @param content   the attachment
+     */
+    void addAttachmentObject(String id, Attachment content);
+
+    /**
      * Returns all attachments of the message
      *
      * @return the attachments in a map or <tt>null</tt>
@@ -285,6 +301,13 @@ public interface Message {
     Map<String, DataHandler> getAttachments();
 
     /**
+     * Returns all attachments of the message
+     *
+     * @return the attachments in a map or <tt>null</tt>
+     */
+    Map<String, Attachment> getAttachmentObjects();
+
+    /**
      * Set all the attachments associated with this message
      *
      * @param attachments the attachments
@@ -292,6 +315,13 @@ public interface Message {
     void setAttachments(Map<String, DataHandler> attachments);
 
     /**
+     * Set all the attachments associated with this message
+     *
+     * @param attachments the attachments
+     */
+    void setAttachmentObjects(Map<String, Attachment> attachments);
+
+    /**
      * Returns whether this message has attachments.
      *
      * @return <tt>true</tt> if this message has any attachments.

http://git-wip-us.apache.org/repos/asf/camel/blob/50d6d4fb/camel-core/src/main/java/org/apache/camel/builder/ExpressionBuilder.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/builder/ExpressionBuilder.java b/camel-core/src/main/java/org/apache/camel/builder/ExpressionBuilder.java
index 3200990..b6069ea 100644
--- a/camel-core/src/main/java/org/apache/camel/builder/ExpressionBuilder.java
+++ b/camel-core/src/main/java/org/apache/camel/builder/ExpressionBuilder.java
@@ -80,6 +80,42 @@ public final class ExpressionBuilder {
     private ExpressionBuilder() {
     }
     
+     /**
+     * Returns an expression for the inbound message attachments
+     *
+     * @return an expression object which will return the inbound message attachments
+     */
+    public static Expression attachmentObjectsExpression() {
+        return new ExpressionAdapter() {
+            public Object evaluate(Exchange exchange) {
+                return exchange.getIn().getAttachmentObjects();
+            }
+
+            @Override
+            public String toString() {
+                return "attachmentObjects";
+            }
+        };
+    }
+
+    /**
+     * Returns an expression for the inbound message attachments
+     *
+     * @return an expression object which will return the inbound message attachments
+     */
+    public static Expression attachmentObjectValuesExpression() {
+        return new ExpressionAdapter() {
+            public Object evaluate(Exchange exchange) {
+                return exchange.getIn().getAttachmentObjects().values();
+            }
+
+            @Override
+            public String toString() {
+                return "attachmentObjects";
+            }
+        };
+    }
+
     /**
      * Returns an expression for the inbound message attachments
      *

http://git-wip-us.apache.org/repos/asf/camel/blob/50d6d4fb/camel-core/src/main/java/org/apache/camel/builder/ExpressionClauseSupport.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/builder/ExpressionClauseSupport.java b/camel-core/src/main/java/org/apache/camel/builder/ExpressionClauseSupport.java
index 0ef21b8..9e1224c 100644
--- a/camel-core/src/main/java/org/apache/camel/builder/ExpressionClauseSupport.java
+++ b/camel-core/src/main/java/org/apache/camel/builder/ExpressionClauseSupport.java
@@ -171,7 +171,7 @@ public class ExpressionClauseSupport<T> {
      * An expression of the inbound message attachments
      */
     public T attachments() {
-        return expression(ExpressionBuilder.attachmentValuesExpression());
+        return expression(ExpressionBuilder.attachmentObjectValuesExpression());
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/camel/blob/50d6d4fb/camel-core/src/main/java/org/apache/camel/component/bean/BeanInfo.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/component/bean/BeanInfo.java b/camel-core/src/main/java/org/apache/camel/component/bean/BeanInfo.java
index 3e23332..5a3a0ef 100644
--- a/camel-core/src/main/java/org/apache/camel/component/bean/BeanInfo.java
+++ b/camel-core/src/main/java/org/apache/camel/component/bean/BeanInfo.java
@@ -32,6 +32,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import org.apache.camel.AttachmentObjects;
 import org.apache.camel.Attachments;
 import org.apache.camel.Body;
 import org.apache.camel.CamelContext;
@@ -946,7 +947,9 @@ public class BeanInfo {
 
     private Expression createParameterUnmarshalExpressionForAnnotation(Class<?> clazz, Method method, 
             Class<?> parameterType, Annotation annotation) {
-        if (annotation instanceof Attachments) {
+        if (annotation instanceof AttachmentObjects) {
+            return ExpressionBuilder.attachmentObjectsExpression();
+        } else if (annotation instanceof Attachments) {
             return ExpressionBuilder.attachmentsExpression();
         } else if (annotation instanceof Property) {
             Property propertyAnnotation = (Property)annotation;

http://git-wip-us.apache.org/repos/asf/camel/blob/50d6d4fb/camel-core/src/main/java/org/apache/camel/converter/AttachmentConverter.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/converter/AttachmentConverter.java b/camel-core/src/main/java/org/apache/camel/converter/AttachmentConverter.java
new file mode 100644
index 0000000..5e032d5
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/converter/AttachmentConverter.java
@@ -0,0 +1,43 @@
+/**
+ * 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.converter;
+
+import javax.activation.DataHandler;
+
+import org.apache.camel.Attachment;
+import org.apache.camel.Converter;
+
+/**
+ * Some useful converters for {@link Attachment}
+ * to a {@link DataHandler}
+ *
+ * @version 
+ */
+@Converter
+public final class AttachmentConverter {
+
+    /**
+     * Utility classes should not have a public constructor.
+     */
+    private AttachmentConverter() {
+    }
+
+    @Converter
+    public static DataHandler toDataHandler(final Attachment attachment) {
+        return attachment.getDataHandler();
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/50d6d4fb/camel-core/src/main/java/org/apache/camel/impl/DefaultAttachment.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/DefaultAttachment.java b/camel-core/src/main/java/org/apache/camel/impl/DefaultAttachment.java
new file mode 100644
index 0000000..dbb87af
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/impl/DefaultAttachment.java
@@ -0,0 +1,125 @@
+/**
+ * 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.impl;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+import javax.activation.DataHandler;
+import javax.activation.DataSource;
+
+import org.apache.camel.Attachment;
+import org.apache.camel.util.CollectionHelper;
+
+public class DefaultAttachment implements Attachment {
+    private Map<String, Object> headers = null;
+    private DataHandler dataHandler;
+
+    public DefaultAttachment(DataHandler dh) {
+        dataHandler = dh;
+    }
+
+    public DefaultAttachment(DataSource ds) {
+        dataHandler = new DataHandler(ds);
+    }
+
+    @Override
+    public DataHandler getDataHandler() {
+        return dataHandler;
+    }
+
+    @Override
+    public String getHeader(String name) {
+        if (headers != null) {
+            Object headerObject = headers.get(name);
+            if (headerObject instanceof String) {
+                return (String)headerObject;
+            } else if (headerObject instanceof Collection<?>) {
+                return CollectionHelper.collectionAsCommaDelimitedString((Collection<?>)headerObject);
+            }
+        }
+        return null;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public List<String> getHeaderAsList(String name) {
+        if (headers != null) {
+            Object headerObject = headers.get(name);
+            if (headerObject instanceof List<?>) {
+                return (List<String>)headerObject;
+            } else if (headerObject instanceof String) {
+                return Collections.singletonList((String)headerObject);
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public void addHeader(String headerName, String headerValue) {
+        if (headers == null) {
+            headers = createHeaders();
+        }
+        CollectionHelper.appendValue(headers, headerName, headerValue);
+    }
+
+    @Override
+    public void setHeader(String headerName, String headerValue) {
+        if (headers == null) {
+            headers = createHeaders();
+        }
+        headers.put(headerName, headerValue);
+    }
+
+    @Override
+    public void removeHeader(String headerName) {
+        if (headers != null) {
+            headers.remove(headerName);
+        }
+    }
+
+    @Override
+    public Collection<String> getHeaderNames() {
+        if (headers == null) {
+            headers = createHeaders();
+        }
+        return headers.keySet();
+    }
+
+    public void clearHeaders() {
+        headers = null;
+    }
+
+    private Map<String, Object> createHeaders() {
+        return new TreeMap<String, Object>(String.CASE_INSENSITIVE_ORDER);
+    }
+
+    public boolean equals(Object other) {
+        if (other instanceof Attachment) {
+            DataHandler otherDh = ((Attachment)other).getDataHandler();
+            return dataHandler.equals(otherDh);
+        }
+        return false;
+    }
+
+    public int hashCode() {
+        return (dataHandler.hashCode());
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/50d6d4fb/camel-core/src/main/java/org/apache/camel/impl/DefaultMessage.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/DefaultMessage.java b/camel-core/src/main/java/org/apache/camel/impl/DefaultMessage.java
index 0ed2841..848586a 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/DefaultMessage.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/DefaultMessage.java
@@ -22,7 +22,9 @@ import java.util.Map;
 import java.util.Set;
 import javax.activation.DataHandler;
 
+import org.apache.camel.Attachment;
 import org.apache.camel.Exchange;
+import org.apache.camel.util.AttachmentMap;
 import org.apache.camel.util.CaseInsensitiveMap;
 import org.apache.camel.util.EndpointHelper;
 
@@ -40,6 +42,7 @@ public class DefaultMessage extends MessageSupport {
     private boolean fault;
     private Map<String, Object> headers;
     private Map<String, DataHandler> attachments;
+    private Map<String, Attachment> attachmentObjects;
 
     public boolean isFault() {
         return fault;
@@ -199,14 +202,14 @@ public class DefaultMessage extends MessageSupport {
     }
 
     /**
-     * A factory method to lazily create the attachments to make it easy to
+     * A factory method to lazily create the attachmentObjects to make it easy to
      * create efficient Message implementations which only construct and
      * populate the Map on demand
      *
      * @return return a newly constructed Map
      */
-    protected Map<String, DataHandler> createAttachments() {
-        Map<String, DataHandler> map = new LinkedHashMap<String, DataHandler>();
+    protected Map<String, Attachment> createAttachments() {
+        Map<String, Attachment> map = new LinkedHashMap<String, Attachment>();
         populateInitialAttachments(map);
         return map;
     }
@@ -222,12 +225,12 @@ public class DefaultMessage extends MessageSupport {
     }
 
     /**
-     * A strategy method populate the initial set of attachments on an inbound
+     * A strategy method populate the initial set of attachmentObjects on an inbound
      * message from an underlying binding
      *
      * @param map is the empty attachment map to populate
      */
-    protected void populateInitialAttachments(Map<String, DataHandler> map) {
+    protected void populateInitialAttachments(Map<String, Attachment> map) {
         // do nothing by default
     }
 
@@ -247,45 +250,82 @@ public class DefaultMessage extends MessageSupport {
     }
 
     public void addAttachment(String id, DataHandler content) {
-        if (attachments == null) {
-            attachments = createAttachments();
+        addAttachmentObject(id, new DefaultAttachment(content));
+    }
+
+    public void addAttachmentObject(String id, Attachment content) {
+        if (attachmentObjects == null) {
+            attachmentObjects = createAttachments();
         }
-        attachments.put(id, content);
+        attachmentObjects.put(id, content);
     }
 
     public DataHandler getAttachment(String id) {
-        return getAttachments().get(id);
+        Attachment att = getAttachmentObject(id);
+        if (att == null) {
+            return null;
+        } else {
+            return att.getDataHandler();
+        }
+    }
+
+    @Override
+    public Attachment getAttachmentObject(String id) {
+        return getAttachmentObjects().get(id);
     }
 
     public Set<String> getAttachmentNames() {
-        if (attachments == null) {
-            attachments = createAttachments();
+        if (attachmentObjects == null) {
+            attachmentObjects = createAttachments();
         }
-        return attachments.keySet();
+        return attachmentObjects.keySet();
     }
 
     public void removeAttachment(String id) {
-        if (attachments != null && attachments.containsKey(id)) {
-            attachments.remove(id);
+        if (attachmentObjects != null && attachmentObjects.containsKey(id)) {
+            attachmentObjects.remove(id);
         }
     }
 
     public Map<String, DataHandler> getAttachments() {
         if (attachments == null) {
-            attachments = createAttachments();
+            attachments = new AttachmentMap(getAttachmentObjects());
         }
         return attachments;
     }
 
+    public Map<String, Attachment> getAttachmentObjects() {
+        if (attachmentObjects == null) {
+            attachmentObjects = createAttachments();
+        }
+        return attachmentObjects;
+    }
+    
     public void setAttachments(Map<String, DataHandler> attachments) {
-        this.attachments = attachments;
+        if (attachments == null) {
+            this.attachmentObjects = null;
+        } else if (attachments instanceof AttachmentMap) {
+            // this way setAttachments(getAttachments()) will tunnel attachment headers
+            this.attachmentObjects = ((AttachmentMap)attachments).getOriginalMap();
+        } else {
+            this.attachmentObjects = new LinkedHashMap<String, Attachment>();
+            for (Map.Entry<String, DataHandler> entry : attachments.entrySet()) {
+                this.attachmentObjects.put(entry.getKey(), new DefaultAttachment(entry.getValue()));
+            }
+        }
+        this.attachments = null;
+    }
+
+    public void setAttachmentObjects(Map<String, Attachment> attachments) {
+        this.attachmentObjects = attachments;
+        this.attachments = null;
     }
 
     public boolean hasAttachments() {
         // optimized to avoid calling createAttachments as that creates a new empty map
         // that we 99% do not need (only camel-mail supports attachments), and we have
         // then ensure camel-mail always creates attachments to remedy for this
-        return this.attachments != null && this.attachments.size() > 0;
+        return this.attachmentObjects != null && this.attachmentObjects.size() > 0;
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/camel/blob/50d6d4fb/camel-core/src/main/java/org/apache/camel/impl/MessageSupport.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/MessageSupport.java b/camel-core/src/main/java/org/apache/camel/impl/MessageSupport.java
index 029c0bf..2d4955e 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/MessageSupport.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/MessageSupport.java
@@ -173,17 +173,17 @@ public abstract class MessageSupport implements Message {
         // the attachments may be the same instance if the end user has made some mistake
         // and set the OUT message with the same attachment instance of the IN message etc
         boolean sameAttachments = false;
-        if (hasAttachments() && that.hasAttachments() && getAttachments() == that.getAttachments()) {
+        if (hasAttachments() && that.hasAttachments() && getAttachmentObjects() == that.getAttachmentObjects()) {
             sameAttachments = true;
         }
 
         if (!sameAttachments) {
             if (hasAttachments()) {
                 // okay its safe to clear the attachments
-                getAttachments().clear();
+                getAttachmentObjects().clear();
             }
             if (that.hasAttachments()) {
-                getAttachments().putAll(that.getAttachments());
+                getAttachmentObjects().putAll(that.getAttachmentObjects());
             }
         }
     }

http://git-wip-us.apache.org/repos/asf/camel/blob/50d6d4fb/camel-core/src/main/java/org/apache/camel/impl/converter/CorePackageScanClassResolver.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/converter/CorePackageScanClassResolver.java b/camel-core/src/main/java/org/apache/camel/impl/converter/CorePackageScanClassResolver.java
index dfa008e..ed11fa9 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/converter/CorePackageScanClassResolver.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/converter/CorePackageScanClassResolver.java
@@ -23,6 +23,7 @@ import java.util.Set;
 
 import org.apache.camel.component.bean.BeanConverter;
 import org.apache.camel.component.file.GenericFileConverter;
+import org.apache.camel.converter.AttachmentConverter;
 import org.apache.camel.converter.CamelConverter;
 import org.apache.camel.converter.CollectionConverter;
 import org.apache.camel.converter.DateTimeConverter;
@@ -75,6 +76,7 @@ public class CorePackageScanClassResolver implements PackageScanClassResolver {
         converters.add(BeanConverter.class);
         converters.add(GenericFileConverter.class);
         converters.add(DurationConverter.class);
+        converters.add(AttachmentConverter.class);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/camel/blob/50d6d4fb/camel-core/src/main/java/org/apache/camel/processor/Splitter.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/processor/Splitter.java b/camel-core/src/main/java/org/apache/camel/processor/Splitter.java
index fba3f71..ba3be2e 100644
--- a/camel-core/src/main/java/org/apache/camel/processor/Splitter.java
+++ b/camel-core/src/main/java/org/apache/camel/processor/Splitter.java
@@ -284,7 +284,7 @@ public class Splitter extends MulticastProcessor implements AsyncProcessor, Trac
     private static Exchange copyExchangeNoAttachments(Exchange exchange, boolean preserveExchangeId) {
         Exchange answer = ExchangeHelper.createCopy(exchange, preserveExchangeId);
         // we do not want attachments for the splitted sub-messages
-        answer.getIn().setAttachments(null);
+        answer.getIn().setAttachmentObjects(null);
         // we do not want to copy the message history for splitted sub-messages
         answer.getProperties().remove(Exchange.MESSAGE_HISTORY);
         return answer;

http://git-wip-us.apache.org/repos/asf/camel/blob/50d6d4fb/camel-core/src/main/java/org/apache/camel/util/AttachmentMap.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/util/AttachmentMap.java b/camel-core/src/main/java/org/apache/camel/util/AttachmentMap.java
new file mode 100644
index 0000000..1f33546
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/util/AttachmentMap.java
@@ -0,0 +1,140 @@
+/**
+ * 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.util;
+
+import java.util.AbstractMap;
+import java.util.AbstractSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import javax.activation.DataHandler;
+
+import org.apache.camel.Attachment;
+import org.apache.camel.impl.DefaultAttachment;
+
+/**
+ * The AttachmentMap class provides a transparent Map<String, DataHandler>
+ * interface for a Map<String, Attachment>
+ */
+public class AttachmentMap extends AbstractMap<String, DataHandler> {
+    private Map<String, Attachment> map;
+
+    public AttachmentMap(Map<String, Attachment> backingMap) {
+        this.map = backingMap;
+    }
+
+    @Override
+    public DataHandler put(String key, DataHandler value) {
+        Attachment old = map.put(key, new DefaultAttachment(value));
+        if (old == null) {
+            return null;
+        } else {
+            return old.getDataHandler();
+        }
+    }
+
+    @Override
+    public Set<Map.Entry<String, DataHandler>> entrySet() {
+        return new AttachmentEntrySet(map.entrySet());
+    }
+
+    public Map<String, Attachment> getOriginalMap() {
+        return map;
+    }
+
+    private static class AttachmentEntrySet extends AbstractSet<Map.Entry<String, DataHandler>> {
+        private Set<Map.Entry<String, Attachment>> set;
+
+        public AttachmentEntrySet(Set<Map.Entry<String, Attachment>> set) {
+            this.set = set;
+        }
+
+        @Override
+        public int size() {
+            return set.size();
+        }
+
+        @Override
+        public Iterator<Map.Entry<String, DataHandler>> iterator() {
+            return new AttachmentEntrySetIterator(set.iterator());
+        }
+    }
+
+    private static class AttachmentEntrySetIterator implements Iterator<Map.Entry<String, DataHandler>> {
+        private Iterator<Map.Entry<String, Attachment>> iter;
+
+        public AttachmentEntrySetIterator(Iterator<Map.Entry<String, Attachment>> origIterator) {
+            iter = origIterator;
+        }
+
+        @Override
+        public boolean hasNext() {
+            return iter.hasNext();
+        }
+
+        @Override
+        public Map.Entry<String, DataHandler> next() {
+            return new AttachmentEntry(iter.next());
+        }
+
+        public void remove() {
+            iter.remove();
+        }
+    }
+
+    private static class AttachmentEntry implements Map.Entry<String, DataHandler> {
+        private Map.Entry<String, Attachment> entry;
+
+        public AttachmentEntry(Map.Entry<String, Attachment> backingEntry) {
+            this.entry = backingEntry;
+        }
+
+        @Override
+        public String getKey() {
+            return entry.getKey();
+        }
+
+        @Override
+        public DataHandler getValue() {
+            Attachment value = entry.getValue();
+            if (value != null)
+                return value.getDataHandler();
+            return null;
+        }
+
+        @Override
+        public DataHandler setValue(DataHandler value) {
+            Attachment oldValue = entry.setValue(new DefaultAttachment(value));
+            if (oldValue != null)
+                return oldValue.getDataHandler();
+            return null;
+        }
+
+        // two AttachmentEntry objects are equal if the backing entries are
+        // equal
+        public boolean equals(Object o) {
+            if (o instanceof AttachmentEntry && entry.equals(((AttachmentEntry)o).entry))
+                return true;
+            return false;
+        }
+
+        public int hashCode() {
+            return entry.hashCode();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/50d6d4fb/camel-core/src/test/java/org/apache/camel/BodyAndHeaderConvertTest.java
----------------------------------------------------------------------
diff --git a/camel-core/src/test/java/org/apache/camel/BodyAndHeaderConvertTest.java b/camel-core/src/test/java/org/apache/camel/BodyAndHeaderConvertTest.java
index 73db6ad..af67e04 100644
--- a/camel-core/src/test/java/org/apache/camel/BodyAndHeaderConvertTest.java
+++ b/camel-core/src/test/java/org/apache/camel/BodyAndHeaderConvertTest.java
@@ -26,6 +26,7 @@ import org.w3c.dom.Element;
 
 import junit.framework.TestCase;
 
+import org.apache.camel.impl.DefaultAttachment;
 import org.apache.camel.impl.DefaultCamelContext;
 import org.apache.camel.impl.DefaultExchange;
 
@@ -55,6 +56,8 @@ public class BodyAndHeaderConvertTest extends TestCase {
     public void testConversionOfMessageAttachments() throws Exception {
         DataHandler handler = exchange.getIn().getAttachment("att");
         assertNotNull("attachment got lost", handler);
+        Attachment attachment = exchange.getIn().getAttachmentObject("att");
+        assertNotNull("attachment got lost", attachment);
     }
 
     @Override
@@ -65,6 +68,6 @@ public class BodyAndHeaderConvertTest extends TestCase {
         Message message = exchange.getIn();
         message.setBody("<hello>world!</hello>");
         message.setHeader("bar", 567);
-        message.addAttachment("att", new DataHandler(new URLDataSource(new URL("http://camel.apache.org/message.html"))));
+        message.addAttachmentObject("att", new DefaultAttachment(new URLDataSource(new URL("http://camel.apache.org/message.html"))));
     }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/50d6d4fb/camel-core/src/test/java/org/apache/camel/builder/ExpressionClauseTest.java
----------------------------------------------------------------------
diff --git a/camel-core/src/test/java/org/apache/camel/builder/ExpressionClauseTest.java b/camel-core/src/test/java/org/apache/camel/builder/ExpressionClauseTest.java
index f45aabe..f053177 100644
--- a/camel-core/src/test/java/org/apache/camel/builder/ExpressionClauseTest.java
+++ b/camel-core/src/test/java/org/apache/camel/builder/ExpressionClauseTest.java
@@ -22,11 +22,13 @@ import javax.activation.DataHandler;
 import javax.activation.DataSource;
 import javax.activation.FileDataSource;
 
+import org.apache.camel.Attachment;
 import org.apache.camel.ContextTestSupport;
 import org.apache.camel.Exchange;
 import org.apache.camel.Message;
 import org.apache.camel.Processor;
 import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.impl.DefaultAttachment;
 
 /**
  * @version 
@@ -53,13 +55,13 @@ public class ExpressionClauseTest extends ContextTestSupport {
             public void process(Exchange exchange) throws Exception {
                 Message m = exchange.getIn();
                 m.setBody("Hello World");
-                m.addAttachment("log4j", new DataHandler(new FileDataSource("src/test/resources/log4j.properties")));
+                m.addAttachmentObject("log4j", new DefaultAttachment(new FileDataSource("src/test/resources/log4j.properties")));
                 m.addAttachment("jndi-example", new DataHandler(new FileDataSource("src/test/resources/jndi-example.properties")));
             }
         });
 
         assertMockEndpointsSatisfied();
-        Map<String, DataHandler> attachments = mock.getExchanges().get(0).getIn().getAttachments();
+        Map<String, Attachment> attachments = mock.getExchanges().get(0).getIn().getAttachmentObjects();
         assertTrue(attachments == null || attachments.size() == 0);
     }
 

http://git-wip-us.apache.org/repos/asf/camel/blob/50d6d4fb/camel-core/src/test/java/org/apache/camel/component/bean/BeanMethodWithExchangeTest.java
----------------------------------------------------------------------
diff --git a/camel-core/src/test/java/org/apache/camel/component/bean/BeanMethodWithExchangeTest.java b/camel-core/src/test/java/org/apache/camel/component/bean/BeanMethodWithExchangeTest.java
index 01e022e..9afe828 100644
--- a/camel-core/src/test/java/org/apache/camel/component/bean/BeanMethodWithExchangeTest.java
+++ b/camel-core/src/test/java/org/apache/camel/component/bean/BeanMethodWithExchangeTest.java
@@ -20,11 +20,13 @@ import javax.activation.DataHandler;
 import javax.activation.FileDataSource;
 import javax.naming.Context;
 
+import org.apache.camel.Attachment;
 import org.apache.camel.ContextTestSupport;
 import org.apache.camel.Exchange;
 import org.apache.camel.Message;
 import org.apache.camel.Processor;
 import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.impl.DefaultAttachment;
 import org.apache.camel.util.jndi.JndiContext;
 
 public class BeanMethodWithExchangeTest extends ContextTestSupport {
@@ -39,7 +41,9 @@ public class BeanMethodWithExchangeTest extends ContextTestSupport {
             
         });
         
-        assertTrue(result.getOut().getAttachments().containsKey("attachment2"));
+        assertTrue(result.getOut().getAttachmentObjects().containsKey("attachment2"));
+        assertTrue(result.getOut().getAttachments().containsKey("attachment1"));
+        assertEquals("attachmentValue1", result.getOut().getAttachmentObjects().get("attachment1").getHeader("attachmentHeader1"));
         assertFalse(result.getOut().getAttachments().containsKey("attachment"));
 
     }
@@ -60,6 +64,9 @@ public class BeanMethodWithExchangeTest extends ContextTestSupport {
 
     public static class AttachmentProcessor {
         public void doSomething(Exchange exchange) {
+            Attachment att = new DefaultAttachment(new FileDataSource("src/test/org/apache/camel/component/bean/BeanMethodWithExchangeTest.java"));
+            att.addHeader("attachmentHeader1", "attachmentValue1");
+            exchange.getOut().addAttachmentObject("attachment1", att);
             exchange.getOut().addAttachment("attachment2", new DataHandler(new FileDataSource("src/test/org/apache/camel/component/bean/BeanMethodWithExchangeTest.java")));
         }
        

http://git-wip-us.apache.org/repos/asf/camel/blob/50d6d4fb/camel-core/src/test/java/org/apache/camel/component/bean/BeanWithAttachmentAnnotationTest.java
----------------------------------------------------------------------
diff --git a/camel-core/src/test/java/org/apache/camel/component/bean/BeanWithAttachmentAnnotationTest.java b/camel-core/src/test/java/org/apache/camel/component/bean/BeanWithAttachmentAnnotationTest.java
index 3eea300..5f43bc4 100644
--- a/camel-core/src/test/java/org/apache/camel/component/bean/BeanWithAttachmentAnnotationTest.java
+++ b/camel-core/src/test/java/org/apache/camel/component/bean/BeanWithAttachmentAnnotationTest.java
@@ -22,6 +22,8 @@ import javax.activation.DataHandler;
 import javax.activation.FileDataSource;
 import javax.naming.Context;
 
+import org.apache.camel.Attachment;
+import org.apache.camel.AttachmentObjects;
 import org.apache.camel.Attachments;
 import org.apache.camel.ContextTestSupport;
 import org.apache.camel.Exchange;
@@ -30,10 +32,28 @@ import org.apache.camel.Message;
 import org.apache.camel.Processor;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.impl.DefaultAttachment;
 import org.apache.camel.util.jndi.JndiContext;
 
 public class BeanWithAttachmentAnnotationTest extends ContextTestSupport {
     
+    public void testBeanWithOldAnnotationAndExchangeTest() throws Exception {
+        MockEndpoint mock = getMockEndpoint("mock:result");
+        mock.expectedBodiesReceived("attachment");
+        
+        template.send("direct:inOld", new Processor() {
+
+            public void process(Exchange exchange) throws Exception {
+                exchange.setPattern(ExchangePattern.InOut);
+                Message m = exchange.getIn();
+                m.addAttachmentObject("attachment", new DefaultAttachment(new FileDataSource("src/test/org/apache/camel/component/bean/BeanWithAttachmentAnnotationTest.java")));
+            }
+            
+        });
+
+        mock.assertIsSatisfied();
+    }
+
     public void testBeanWithAnnotationAndExchangeTest() throws Exception {
         MockEndpoint mock = getMockEndpoint("mock:result");
         mock.expectedBodiesReceived("attachment");
@@ -43,7 +63,7 @@ public class BeanWithAttachmentAnnotationTest extends ContextTestSupport {
             public void process(Exchange exchange) throws Exception {
                 exchange.setPattern(ExchangePattern.InOut);
                 Message m = exchange.getIn();
-                m.addAttachment("attachment", new DataHandler(new FileDataSource("src/test/org/apache/camel/component/bean/BeanWithAttachmentAnnotationTest.java")));
+                m.addAttachmentObject("attachment", new DefaultAttachment(new FileDataSource("src/test/org/apache/camel/component/bean/BeanWithAttachmentAnnotationTest.java")));
             }
             
         });
@@ -53,6 +73,7 @@ public class BeanWithAttachmentAnnotationTest extends ContextTestSupport {
 
     protected Context createJndiContext() throws Exception {
         JndiContext answer = new JndiContext();
+        answer.bind("processorOld", new AttachmentProcessorOld());
         answer.bind("processor", new AttachmentProcessor());
         return answer;
     }
@@ -61,11 +82,12 @@ public class BeanWithAttachmentAnnotationTest extends ContextTestSupport {
         return new RouteBuilder() {
             public void configure() throws Exception {
                 from("direct:in").to("bean:processor").to("mock:result");
+                from("direct:inOld").to("bean:processorOld").to("mock:result");
             }
         };
     }
 
-    public static class AttachmentProcessor {
+    public static class AttachmentProcessorOld {
         // START SNIPPET: e1
         public String doSomething(@Attachments Map<String, DataHandler> attachments) {
             assertNotNull(attachments);
@@ -80,4 +102,22 @@ public class BeanWithAttachmentAnnotationTest extends ContextTestSupport {
         }
         // END SNIPPET: e1
     }
+
+    public static class AttachmentProcessor {
+        // START SNIPPET: e2
+        public String doSomething(@AttachmentObjects Map<String, Attachment> attachments) {
+            assertNotNull(attachments);
+            assertEquals("The attache size is wrong", 1, attachments.size());
+            String key = attachments.keySet().iterator().next();
+            assertNotNull(key);
+            assertNotNull(attachments.get(key));
+            Attachment attachment = attachments.get(key);
+            assertNotNull(attachment);
+            DataHandler handler = attachment.getDataHandler();
+            assertNotNull(handler);
+            assertTrue("The data source should be a instance of FileDataSource", handler.getDataSource() instanceof FileDataSource);     
+            return key;
+        }
+        // END SNIPPET: e2
+    }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/50d6d4fb/camel-core/src/test/java/org/apache/camel/impl/DefaultMessageTest.java
----------------------------------------------------------------------
diff --git a/camel-core/src/test/java/org/apache/camel/impl/DefaultMessageTest.java b/camel-core/src/test/java/org/apache/camel/impl/DefaultMessageTest.java
index 59b4cdc..f8073d2 100644
--- a/camel-core/src/test/java/org/apache/camel/impl/DefaultMessageTest.java
+++ b/camel-core/src/test/java/org/apache/camel/impl/DefaultMessageTest.java
@@ -18,8 +18,8 @@ package org.apache.camel.impl;
 
 import java.util.LinkedHashMap;
 import java.util.Map;
-import javax.activation.DataHandler;
 
+import org.apache.camel.Attachment;
 import org.junit.Test;
 
 import static org.hamcrest.CoreMatchers.instanceOf;
@@ -31,7 +31,7 @@ public class DefaultMessageTest {
     public void testAttachmentsAreSorted() {
         DefaultMessage message = new DefaultMessage();
 
-        Map<String, DataHandler> attachments = message.createAttachments();
+        Map<String, Attachment> attachments = message.createAttachments();
 
         assertThat(attachments, instanceOf(LinkedHashMap.class));
     }

http://git-wip-us.apache.org/repos/asf/camel/blob/50d6d4fb/camel-core/src/test/java/org/apache/camel/issues/MessageWithAttachmentRedeliveryIssueTest.java
----------------------------------------------------------------------
diff --git a/camel-core/src/test/java/org/apache/camel/issues/MessageWithAttachmentRedeliveryIssueTest.java b/camel-core/src/test/java/org/apache/camel/issues/MessageWithAttachmentRedeliveryIssueTest.java
index a264a9c..8156d8e 100644
--- a/camel-core/src/test/java/org/apache/camel/issues/MessageWithAttachmentRedeliveryIssueTest.java
+++ b/camel-core/src/test/java/org/apache/camel/issues/MessageWithAttachmentRedeliveryIssueTest.java
@@ -25,6 +25,7 @@ import org.apache.camel.Exchange;
 import org.apache.camel.Message;
 import org.apache.camel.Processor;
 import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.impl.DefaultAttachment;
 
 /**
  *
@@ -39,7 +40,7 @@ public class MessageWithAttachmentRedeliveryIssueTest extends ContextTestSupport
             public void process(Exchange exchange) throws Exception {
                 exchange.getIn().setBody("Hello World");
                 exchange.getIn().addAttachment("message1.xml", new DataHandler(new FileDataSource(new File("src/test/data/message1.xml"))));
-                exchange.getIn().addAttachment("message2.xml", new DataHandler(new FileDataSource(new File("src/test/data/message2.xml"))));
+                exchange.getIn().addAttachmentObject("message2.xml", new DefaultAttachment(new FileDataSource(new File("src/test/data/message2.xml"))));
             }
         });
 

http://git-wip-us.apache.org/repos/asf/camel/blob/50d6d4fb/camel-core/src/test/java/org/apache/camel/processor/PipelineTest.java
----------------------------------------------------------------------
diff --git a/camel-core/src/test/java/org/apache/camel/processor/PipelineTest.java b/camel-core/src/test/java/org/apache/camel/processor/PipelineTest.java
index db58d81..aa92a5d 100644
--- a/camel-core/src/test/java/org/apache/camel/processor/PipelineTest.java
+++ b/camel-core/src/test/java/org/apache/camel/processor/PipelineTest.java
@@ -132,9 +132,11 @@ public class PipelineTest extends ContextTestSupport {
         });
         // there is always breadcrumb header
         assertEquals("There should have no message header", 1, exchange.getOut().getHeaders().size());
+        assertEquals("There should have no attachments", 0, exchange.getOut().getAttachmentObjects().size());
         assertEquals("There should have no attachments", 0, exchange.getOut().getAttachments().size());
         assertEquals("Get a wrong message body", "test", exchange.getOut().getBody());
         assertNull(exchange.getOut().getHeader("test"));
+        assertNull(exchange.getOut().getAttachmentObject("test1.xml"));
         assertNull(exchange.getOut().getAttachment("test1.xml"));
         
     }
@@ -184,6 +186,7 @@ public class PipelineTest extends ContextTestSupport {
                     .process(new Processor() {
                         public void process(Exchange exchange) throws Exception {
                             exchange.getOut().copyFrom(exchange.getIn());
+                            assertNotNull("The test attachment should not be null", exchange.getOut().getAttachmentObject("test1.xml"));
                             assertNotNull("The test attachment should not be null", exchange.getOut().getAttachment("test1.xml"));
                             assertNotNull("The test header should not be null", exchange.getOut().getHeader("test"));
                             exchange.getOut().removeAttachment("test1.xml");

http://git-wip-us.apache.org/repos/asf/camel/blob/50d6d4fb/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/DefaultCxfBinding.java
----------------------------------------------------------------------
diff --git a/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/DefaultCxfBinding.java b/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/DefaultCxfBinding.java
index aad23d5..bbad18a 100644
--- a/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/DefaultCxfBinding.java
+++ b/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/DefaultCxfBinding.java
@@ -30,7 +30,6 @@ import java.util.Map;
 import java.util.Set;
 import java.util.TreeMap;
 
-import javax.activation.DataHandler;
 import javax.security.auth.Subject;
 import javax.xml.XMLConstants;
 import javax.xml.namespace.QName;
@@ -47,6 +46,7 @@ import org.apache.camel.ExchangePattern;
 import org.apache.camel.component.cxf.common.message.CxfConstants;
 import org.apache.camel.component.cxf.util.CxfUtils;
 import org.apache.camel.component.cxf.util.ReaderInputStream;
+import org.apache.camel.impl.DefaultAttachment;
 import org.apache.camel.spi.HeaderFilterStrategy;
 import org.apache.camel.spi.HeaderFilterStrategyAware;
 import org.apache.camel.util.ExchangeHelper;
@@ -129,11 +129,16 @@ public class DefaultCxfBinding implements CxfBinding, HeaderFilterStrategyAware
         // we should avoid adding the attachments if the data format is CXFMESSAGE, as the message stream 
         // already has the attachment information
         if (!DataFormat.CXF_MESSAGE.equals(dataFormat)) {
-            for (Map.Entry<String, DataHandler> entry : camelExchange.getIn().getAttachments().entrySet()) {
+            for (Map.Entry<String, org.apache.camel.Attachment> entry : camelExchange.getIn().getAttachmentObjects().entrySet()) {
                 if (attachments == null) {
                     attachments = new HashSet<Attachment>();
                 }
-                AttachmentImpl attachment = new AttachmentImpl(entry.getKey(), entry.getValue());
+                AttachmentImpl attachment = new AttachmentImpl(entry.getKey());
+                org.apache.camel.Attachment camelAttachment = entry.getValue();
+                attachment.setDataHandler(camelAttachment.getDataHandler());
+                for (String name : camelAttachment.getHeaderNames()) {
+                    attachment.setHeader(name, camelAttachment.getHeader(name));
+                }
                 attachment.setXOP(isXop);
                 attachments.add(attachment);
             }
@@ -187,10 +192,20 @@ public class DefaultCxfBinding implements CxfBinding, HeaderFilterStrategyAware
         if (cxfMessage.getAttachments() != null) {
             // propagate attachments
             for (Attachment attachment : cxfMessage.getAttachments()) {
-                camelExchange.getOut().addAttachment(attachment.getId(), attachment.getDataHandler());
+                camelExchange.getOut().addAttachmentObject(attachment.getId(), createCamelAttachment(attachment));
             }        
         }
     }
+
+    private DefaultAttachment createCamelAttachment(Attachment attachment) {
+        DefaultAttachment camelAttachment = new DefaultAttachment(attachment.getDataHandler());
+        Iterator<String> headers = attachment.getHeaderNames();
+        while (headers.hasNext()) {
+            String name = headers.next();
+            camelAttachment.addHeader(name, attachment.getHeader(name));
+        }
+        return camelAttachment;
+    }
     
     /**
      * This method is called by {@link CxfConsumer}.
@@ -289,7 +304,7 @@ public class DefaultCxfBinding implements CxfBinding, HeaderFilterStrategyAware
         if (cxfMessage.getAttachments() != null 
             && !camelExchange.getProperty(CxfConstants.DATA_FORMAT_PROPERTY, DataFormat.class).equals(DataFormat.POJO)) {
             for (Attachment attachment : cxfMessage.getAttachments()) {
-                camelExchange.getIn().addAttachment(attachment.getId(), attachment.getDataHandler());
+                camelExchange.getIn().addAttachmentObject(attachment.getId(), createCamelAttachment(attachment));
             }
         }
     }
@@ -387,11 +402,16 @@ public class DefaultCxfBinding implements CxfBinding, HeaderFilterStrategyAware
         
         Set<Attachment> attachments = null;
         boolean isXop = Boolean.valueOf(camelExchange.getProperty(Message.MTOM_ENABLED, String.class));
-        for (Map.Entry<String, DataHandler> entry : camelExchange.getOut().getAttachments().entrySet()) {
+        for (Map.Entry<String, org.apache.camel.Attachment> entry : camelExchange.getOut().getAttachmentObjects().entrySet()) {
             if (attachments == null) {
                 attachments = new HashSet<Attachment>();
             }
-            AttachmentImpl attachment = new AttachmentImpl(entry.getKey(), entry.getValue());
+            AttachmentImpl attachment = new AttachmentImpl(entry.getKey());
+            org.apache.camel.Attachment camelAttachment = entry.getValue();
+            attachment.setDataHandler(camelAttachment.getDataHandler());
+            for (String name : camelAttachment.getHeaderNames()) {
+                attachment.setHeader(name, camelAttachment.getHeader(name));
+            }
             attachment.setXOP(isXop);
             attachments.add(attachment);
         }

http://git-wip-us.apache.org/repos/asf/camel/blob/50d6d4fb/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/SimpleCxfRsBinding.java
----------------------------------------------------------------------
diff --git a/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/SimpleCxfRsBinding.java b/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/SimpleCxfRsBinding.java
index a1a12be..566f9f6 100644
--- a/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/SimpleCxfRsBinding.java
+++ b/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/SimpleCxfRsBinding.java
@@ -43,6 +43,7 @@ import javax.ws.rs.core.Response.ResponseBuilder;
 import javax.ws.rs.core.Response.Status;
 
 import org.apache.camel.Message;
+import org.apache.camel.impl.DefaultAttachment;
 import org.apache.camel.spi.HeaderFilterStrategy;
 import org.apache.cxf.jaxrs.ext.multipart.Attachment;
 import org.apache.cxf.jaxrs.ext.multipart.InputStreamDataSource;
@@ -279,21 +280,31 @@ public class SimpleCxfRsBinding extends DefaultCxfRsBinding {
     }
 
     private void transferBinaryMultipartParameter(Object toMap, String parameterName, String multipartType, Message in) {
-        DataHandler dh = null;
+        org.apache.camel.Attachment dh = null;
         if (toMap instanceof Attachment) {
-            dh = ((Attachment) toMap).getDataHandler();
+            dh = createCamelAttachment((Attachment) toMap);
         } else if (toMap instanceof DataSource) {
-            dh = new DataHandler((DataSource) toMap);
+            dh = new DefaultAttachment((DataSource) toMap);
         } else if (toMap instanceof DataHandler) {
-            dh = (DataHandler) toMap;
+            dh = new DefaultAttachment((DataHandler) toMap);
         } else if (toMap instanceof InputStream) {
-            dh = new DataHandler(new InputStreamDataSource((InputStream) toMap, multipartType == null ? "application/octet-stream" : multipartType));
+            dh = new DefaultAttachment(new InputStreamDataSource((InputStream) toMap, multipartType == null ? "application/octet-stream" : multipartType));
         }
         if (dh != null) {
-            in.addAttachment(parameterName, dh);
+            in.addAttachmentObject(parameterName, dh);
         }
     }
-    
+
+    private DefaultAttachment createCamelAttachment(Attachment attachment) {
+        DefaultAttachment camelAttachment = new DefaultAttachment(attachment.getDataHandler());
+        for (String name : attachment.getHeaders().keySet()) {
+            for(String value : attachment.getHeaderAsList(name)) {
+                camelAttachment.addHeader(name, value);
+            }
+        }
+        return camelAttachment;
+    }
+
     protected static class MethodSpec {
         private boolean multipart;
         private int numberParameters;

http://git-wip-us.apache.org/repos/asf/camel/blob/50d6d4fb/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/DefaultCxfBindingTest.java
----------------------------------------------------------------------
diff --git a/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/DefaultCxfBindingTest.java b/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/DefaultCxfBindingTest.java
index c82050a..a700832 100644
--- a/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/DefaultCxfBindingTest.java
+++ b/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/DefaultCxfBindingTest.java
@@ -159,6 +159,7 @@ public class DefaultCxfBindingTest extends Assert {
         exchange.getIn().setHeader("MyFruitHeader", "peach");
         exchange.getIn().setHeader("MyBrewHeader", Arrays.asList("cappuccino", "espresso"));
         exchange.getIn().addAttachment("att-1", new DataHandler(new FileDataSource("pom.xml")));
+        exchange.getIn().getAttachmentObject("att-1").setHeader("attachment-header", "value 1");
 
         cxfBinding.populateCxfRequestFromExchange(cxfExchange, exchange, requestContext);
         
@@ -181,6 +182,7 @@ public class DefaultCxfBindingTest extends Assert {
         assertNotNull(attachments.size() == 1);
         Attachment att = attachments.iterator().next();
         assertEquals("att-1", att.getId());
+        assertEquals("value 1", att.getHeader("attachment-header"));
     }
     
     @Test
@@ -200,7 +202,9 @@ public class DefaultCxfBindingTest extends Assert {
         cxfExchange.setInMessage(cxfMessage);
         
         Set<Attachment> attachments = new HashSet<Attachment>();
-        attachments.add(new AttachmentImpl("att-1", new DataHandler(new FileDataSource("pom.xml"))));
+        AttachmentImpl attachment = new AttachmentImpl("att-1", new DataHandler(new FileDataSource("pom.xml")));
+        attachment.setHeader("additional-header", "value 1");
+        attachments.add(attachment);
         cxfMessage.setAttachments(attachments);
         
         cxfBinding.populateExchangeFromCxfResponse(exchange, cxfExchange, responseContext);
@@ -209,9 +213,10 @@ public class DefaultCxfBindingTest extends Assert {
         assertNotNull(camelHeaders);
         assertEquals(responseContext, camelHeaders.get(Client.RESPONSE_CONTEXT));
         
-        Map<String, DataHandler> camelAttachments = exchange.getOut().getAttachments();
+        Map<String, org.apache.camel.Attachment> camelAttachments = exchange.getOut().getAttachmentObjects();
         assertNotNull(camelAttachments);
         assertNotNull(camelAttachments.get("att-1"));
+        assertEquals("value 1", camelAttachments.get("att-1").getHeader("additional-header"));
     }
 
     @Test
@@ -249,6 +254,7 @@ public class DefaultCxfBindingTest extends Assert {
         exchange.getOut().setHeader("soapAction", "urn:hello:world");
         exchange.getOut().setHeader("MyFruitHeader", "peach");
         exchange.getOut().addAttachment("att-1", new DataHandler(new FileDataSource("pom.xml")));
+        exchange.getOut().getAttachmentObject("att-1").setHeader("attachment-header", "value 1");
         
         IMocksControl control = EasyMock.createNiceControl();
         
@@ -281,6 +287,7 @@ public class DefaultCxfBindingTest extends Assert {
         assertNotNull(attachments.size() == 1);
         Attachment att = attachments.iterator().next();
         assertEquals("att-1", att.getId());
+        assertEquals("value 1", att.getHeader("attachment-header"));
     }
 
     @Test
@@ -300,7 +307,9 @@ public class DefaultCxfBindingTest extends Assert {
         cxfMessage.put(org.apache.cxf.message.Message.PROTOCOL_HEADERS, headers);
 
         Set<Attachment> attachments = new HashSet<Attachment>();
-        attachments.add(new AttachmentImpl("att-1", new DataHandler(new FileDataSource("pom.xml"))));
+        AttachmentImpl attachment = new AttachmentImpl("att-1", new DataHandler(new FileDataSource("pom.xml")));
+        attachment.setHeader("attachment-header", "value 1");
+        attachments.add(attachment);
         cxfMessage.setAttachments(attachments);
         
         cxfExchange.setInMessage(cxfMessage);
@@ -315,11 +324,11 @@ public class DefaultCxfBindingTest extends Assert {
         assertEquals("241", camelHeaders.get("content-length"));
         assertEquals("peach", camelHeaders.get("MyFruitHeader"));
         assertEquals(Arrays.asList("cappuccino", "espresso"), camelHeaders.get("MyBrewHeader"));
-        
-        Map<String, DataHandler> camelAttachments = exchange.getIn().getAttachments();
+
+        Map<String, org.apache.camel.Attachment> camelAttachments = exchange.getIn().getAttachmentObjects();
         assertNotNull(camelAttachments);
         assertNotNull(camelAttachments.get("att-1"));
-        
+        assertEquals("value 1", camelAttachments.get("att-1").getHeader("attachment-header"));
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/camel/blob/50d6d4fb/components/camel-jcr/src/main/java/org/apache/camel/component/jcr/JcrMessage.java
----------------------------------------------------------------------
diff --git a/components/camel-jcr/src/main/java/org/apache/camel/component/jcr/JcrMessage.java b/components/camel-jcr/src/main/java/org/apache/camel/component/jcr/JcrMessage.java
index 7e2dd44..0cf02ac 100644
--- a/components/camel-jcr/src/main/java/org/apache/camel/component/jcr/JcrMessage.java
+++ b/components/camel-jcr/src/main/java/org/apache/camel/component/jcr/JcrMessage.java
@@ -77,7 +77,7 @@ public class JcrMessage extends DefaultMessage {
         getAttachments().clear();
 
         if (that.hasAttachments()) {
-            getAttachments().putAll(that.getAttachments());
+            getAttachmentObjects().putAll(that.getAttachmentObjects());
         }
     }
 

http://git-wip-us.apache.org/repos/asf/camel/blob/50d6d4fb/components/camel-jetty9/src/main/java/org/apache/camel/component/jetty9/AttachmentHttpBinding.java
----------------------------------------------------------------------
diff --git a/components/camel-jetty9/src/main/java/org/apache/camel/component/jetty9/AttachmentHttpBinding.java b/components/camel-jetty9/src/main/java/org/apache/camel/component/jetty9/AttachmentHttpBinding.java
index 1b7bca1..293dd70 100644
--- a/components/camel-jetty9/src/main/java/org/apache/camel/component/jetty9/AttachmentHttpBinding.java
+++ b/components/camel-jetty9/src/main/java/org/apache/camel/component/jetty9/AttachmentHttpBinding.java
@@ -20,14 +20,15 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.util.Collection;
-import javax.activation.DataHandler;
 import javax.activation.DataSource;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.Part;
 
+import org.apache.camel.Attachment;
 import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.http.common.DefaultHttpBinding;
 import org.apache.camel.http.common.HttpMessage;
+import org.apache.camel.impl.DefaultAttachment;
 import org.eclipse.jetty.util.MultiPartInputStreamParser;
 
 /**
@@ -50,7 +51,13 @@ final class AttachmentHttpBinding extends DefaultHttpBinding {
                 parts = parser.getParts();
                 for (Part part : parts) {
                     DataSource ds = new PartDataSource(part);
-                    message.addAttachment(part.getName(), new DataHandler(ds));
+                    Attachment attachment = new DefaultAttachment(ds);
+                    for (String headerName : part.getHeaderNames()) {
+                        for (String headerValue : part.getHeaders(headerName)) {
+                            attachment.addHeader(headerName, headerValue);
+                        }
+                    }
+                    message.addAttachmentObject(part.getName(), attachment);
                 }
             } catch (Exception e) {
                 throw new RuntimeCamelException("Cannot populate attachments", e);

http://git-wip-us.apache.org/repos/asf/camel/blob/50d6d4fb/components/camel-jetty9/src/test/java/org/apache/camel/component/jetty/MultiPartFormOkHttpTest.java
----------------------------------------------------------------------
diff --git a/components/camel-jetty9/src/test/java/org/apache/camel/component/jetty/MultiPartFormOkHttpTest.java b/components/camel-jetty9/src/test/java/org/apache/camel/component/jetty/MultiPartFormOkHttpTest.java
index 1221cc9..fb02542 100644
--- a/components/camel-jetty9/src/test/java/org/apache/camel/component/jetty/MultiPartFormOkHttpTest.java
+++ b/components/camel-jetty9/src/test/java/org/apache/camel/component/jetty/MultiPartFormOkHttpTest.java
@@ -62,6 +62,7 @@ public class MultiPartFormOkHttpTest extends BaseJettyTest {
 
                         InputStream is = exchange.getIn().getAttachment("test").getInputStream();
                         assertNotNull(is);
+                        assertEquals("form-data; name=\"test\"", exchange.getIn().getAttachmentObject("test").getHeader("content-disposition"));
                         String data = exchange.getContext().getTypeConverter().convertTo(String.class, exchange, is);
                         assertNotNull("Should have data", data);
                         assertEquals("some data here", data);

http://git-wip-us.apache.org/repos/asf/camel/blob/50d6d4fb/components/camel-jms/src/main/java/org/apache/camel/component/jms/JmsMessage.java
----------------------------------------------------------------------
diff --git a/components/camel-jms/src/main/java/org/apache/camel/component/jms/JmsMessage.java b/components/camel-jms/src/main/java/org/apache/camel/component/jms/JmsMessage.java
index fc307fb..0408ff7 100644
--- a/components/camel-jms/src/main/java/org/apache/camel/component/jms/JmsMessage.java
+++ b/components/camel-jms/src/main/java/org/apache/camel/component/jms/JmsMessage.java
@@ -102,7 +102,7 @@ public class JmsMessage extends DefaultMessage {
 
         getAttachments().clear();
         if (that.hasAttachments()) {
-            getAttachments().putAll(that.getAttachments());
+            getAttachmentObjects().putAll(that.getAttachmentObjects());
         }
     }
 

http://git-wip-us.apache.org/repos/asf/camel/blob/50d6d4fb/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailBinding.java
----------------------------------------------------------------------
diff --git a/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailBinding.java b/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailBinding.java
index 79f4066..0596d61 100644
--- a/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailBinding.java
+++ b/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailBinding.java
@@ -42,9 +42,11 @@ import javax.mail.internet.MimeMessage;
 import javax.mail.internet.MimeMultipart;
 import javax.mail.util.ByteArrayDataSource;
 
+import org.apache.camel.Attachment;
 import org.apache.camel.Exchange;
 import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.converter.ObjectConverter;
+import org.apache.camel.impl.DefaultAttachment;
 import org.apache.camel.impl.DefaultHeaderFilterStrategy;
 import org.apache.camel.spi.HeaderFilterStrategy;
 import org.apache.camel.util.CollectionHelper;
@@ -283,7 +285,7 @@ public class MailBinding {
      * @param message the mail message with attachments
      * @param map     the map to add found attachments (attachmentFilename is the key)
      */
-    public void extractAttachmentsFromMail(Message message, Map<String, DataHandler> map)
+    public void extractAttachmentsFromMail(Message message, Map<String, Attachment> map)
         throws MessagingException, IOException {
 
         LOG.trace("Extracting attachments +++ start +++");
@@ -298,7 +300,7 @@ public class MailBinding {
         LOG.trace("Extracting attachments +++ done +++");
     }
 
-    protected void extractAttachmentsFromMultipart(Multipart mp, Map<String, DataHandler> map)
+    protected void extractAttachmentsFromMultipart(Multipart mp, Map<String, Attachment> map)
         throws MessagingException, IOException {
 
         for (int i = 0; i < mp.getCount(); i++) {
@@ -326,7 +328,14 @@ public class MailBinding {
                     LOG.debug("Mail contains file attachment: {}", fileName);
                     if (!map.containsKey(fileName)) {
                         // Parts marked with a disposition of Part.ATTACHMENT are clearly attachments
-                        map.put(fileName, part.getDataHandler());
+                        DefaultAttachment camelAttachment = new DefaultAttachment(part.getDataHandler());
+                        @SuppressWarnings("unchecked")
+                        Enumeration<Header> headers = part.getAllHeaders();
+                        while (headers.hasMoreElements()) {
+                            Header header = headers.nextElement();
+                            camelAttachment.addHeader(header.getName(), header.getValue());
+                        }
+                        map.put(fileName, camelAttachment);
                     } else {
                         LOG.warn("Cannot extract duplicate file attachment: {}.", fileName);
                     }
@@ -457,21 +466,29 @@ public class MailBinding {
                                              AttachmentsContentTransferEncodingResolver encodingResolver, Exchange exchange) throws MessagingException {
         LOG.trace("Adding attachments +++ start +++");
         int i = 0;
-        for (Map.Entry<String, DataHandler> entry : exchange.getIn().getAttachments().entrySet()) {
+        for (Map.Entry<String, Attachment> entry : exchange.getIn().getAttachmentObjects().entrySet()) {
             String attachmentFilename = entry.getKey();
-            DataHandler handler = entry.getValue();
+            Attachment attachment = entry.getValue();
 
             if (LOG.isTraceEnabled()) {
                 LOG.trace("Attachment #{}: Disposition: {}", i, partDisposition);
-                LOG.trace("Attachment #{}: DataHandler: {}", i, handler);
+                LOG.trace("Attachment #{}: DataHandler: {}", i, attachment.getDataHandler());
                 LOG.trace("Attachment #{}: FileName: {}", i, attachmentFilename);
             }
-            if (handler != null) {
-                if (shouldAddAttachment(exchange, attachmentFilename, handler)) {
+            if (attachment != null) {
+                if (shouldAddAttachment(exchange, attachmentFilename, attachment.getDataHandler())) {
                     // Create another body part
                     BodyPart messageBodyPart = new MimeBodyPart();
                     // Set the data handler to the attachment
-                    messageBodyPart.setDataHandler(handler);
+                    messageBodyPart.setDataHandler(attachment.getDataHandler());
+
+                    // Set headers to the attachment
+                    for (String headerName : attachment.getHeaderNames()) {
+                        List<String> values = attachment.getHeaderAsList(headerName);
+                        for (String value : values) {
+                            messageBodyPart.setHeader(headerName, value);
+                        }
+                    }
 
                     if (attachmentFilename.toLowerCase().startsWith("cid:")) {
                         // add a Content-ID header to the attachment

http://git-wip-us.apache.org/repos/asf/camel/blob/50d6d4fb/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailMessage.java
----------------------------------------------------------------------
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 949b0aa..5e0615b 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
@@ -21,6 +21,7 @@ import javax.activation.DataHandler;
 import javax.mail.Message;
 import javax.mail.MessagingException;
 
+import org.apache.camel.Attachment;
 import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.impl.DefaultMessage;
 import org.apache.camel.util.ExchangeHelper;
@@ -120,7 +121,7 @@ public class MailMessage extends DefaultMessage {
     }
 
     @Override
-    protected void populateInitialAttachments(Map<String, DataHandler> map) {
+    protected void populateInitialAttachments(Map<String, Attachment> map) {
         if (mailMessage != null) {
             try {
                 MailBinding binding = ExchangeHelper.getBinding(getExchange(), MailBinding.class);

http://git-wip-us.apache.org/repos/asf/camel/blob/50d6d4fb/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailUtils.java
----------------------------------------------------------------------
diff --git a/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailUtils.java b/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailUtils.java
index 49b7cd0..dc4084e 100644
--- a/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailUtils.java
+++ b/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailUtils.java
@@ -18,6 +18,7 @@ package org.apache.camel.component.mail;
 
 import java.text.DateFormat;
 import java.util.Date;
+
 import javax.mail.Address;
 import javax.mail.Message;
 import javax.mail.MessagingException;

http://git-wip-us.apache.org/repos/asf/camel/blob/50d6d4fb/components/camel-mail/src/main/java/org/apache/camel/component/mail/SplitAttachmentsExpression.java
----------------------------------------------------------------------
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 708428e..ca5aae5 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
@@ -21,8 +21,8 @@ import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
-import javax.activation.DataHandler;
 
+import org.apache.camel.Attachment;
 import org.apache.camel.Exchange;
 import org.apache.camel.Message;
 import org.apache.camel.RuntimeCamelException;
@@ -78,7 +78,7 @@ public class SplitAttachmentsExpression extends ExpressionAdapter {
         try {
             List<Message> answer = new ArrayList<Message>();
             Message inMessage = exchange.getIn();
-            for (Map.Entry<String, DataHandler> entry : inMessage.getAttachments().entrySet()) {
+            for (Map.Entry<String, Attachment> entry : inMessage.getAttachmentObjects().entrySet()) {
                 Message attachmentMessage;
                 if (extractAttachments) {
                     attachmentMessage = extractAttachment(inMessage, entry.getKey());
@@ -97,9 +97,9 @@ public class SplitAttachmentsExpression extends ExpressionAdapter {
         }
     }
 
-    private Message splitAttachment(Message inMessage, String attachmentName, DataHandler attachmentHandler) {
+    private Message splitAttachment(Message inMessage, String attachmentName, Attachment attachmentHandler) {
         final Message copy = inMessage.copy();
-        Map<String, DataHandler> attachments = copy.getAttachments();
+        Map<String, Attachment> attachments = copy.getAttachmentObjects();
         attachments.clear();
         attachments.put(attachmentName, attachmentHandler);
         copy.setHeader(HEADER_NAME, attachmentName);

http://git-wip-us.apache.org/repos/asf/camel/blob/50d6d4fb/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 86e5f35..0af87fb 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
@@ -44,9 +44,11 @@ import javax.mail.internet.MimeUtility;
 import javax.mail.internet.ParseException;
 import javax.mail.util.ByteArrayDataSource;
 
+import org.apache.camel.Attachment;
 import org.apache.camel.Exchange;
 import org.apache.camel.Message;
 import org.apache.camel.NoTypeConversionAvailableException;
+import org.apache.camel.impl.DefaultAttachment;
 import org.apache.camel.spi.DataFormat;
 import org.apache.camel.util.ExchangeHelper;
 import org.apache.camel.util.IOHelper;
@@ -101,18 +103,25 @@ public class MimeMultipartDataFormat implements DataFormat {
             BodyPart part = new MimeBodyPart();
             writeBodyPart(bodyContent, part, contentType);
             mp.addBodyPart(part);
-            for (Map.Entry<String, DataHandler> entry : exchange.getIn().getAttachments().entrySet()) {
+            for (Map.Entry<String, Attachment> entry : exchange.getIn().getAttachmentObjects().entrySet()) {
                 String attachmentFilename = entry.getKey();
-                DataHandler handler = entry.getValue();
+                Attachment attachment = entry.getValue();
                 part = new MimeBodyPart();
-                part.setDataHandler(handler);
+                part.setDataHandler(attachment.getDataHandler());
                 part.setFileName(MimeUtility.encodeText(attachmentFilename, "UTF-8", null));
-                String ct = handler.getContentType();
+                String ct = attachment.getDataHandler().getContentType();
                 contentType = new ContentType(ct);
                 part.setHeader(CONTENT_TYPE, ct);
                 if (!contentType.match("text/*") && binaryContent) {
                     part.setHeader(CONTENT_TRANSFER_ENCODING, "binary");
                 }
+                // Set headers to the attachment
+                for (String headerName : attachment.getHeaderNames()) {
+                    List<String> values = attachment.getHeaderAsList(headerName);
+                    for (String value : values) {
+                        part.setHeader(headerName, value);
+                    }
+                }
                 mp.addBodyPart(part);
                 exchange.getOut().removeAttachment(attachmentFilename);
             }
@@ -238,7 +247,14 @@ public class MimeMultipartDataFormat implements DataFormat {
             content = mp.getBodyPart(0);
             for (int i = 1; i < mp.getCount(); i++) {
                 BodyPart bp = mp.getBodyPart(i);
-                camelMessage.addAttachment(getAttachmentKey(bp), bp.getDataHandler());
+                DefaultAttachment camelAttachment = new DefaultAttachment(bp.getDataHandler());
+                @SuppressWarnings("unchecked")
+                Enumeration<Header> headers = bp.getAllHeaders();
+                while (headers.hasMoreElements()) {
+                    Header header = headers.nextElement();
+                    camelAttachment.addHeader(header.getName(), header.getValue());
+                }
+               camelMessage.addAttachmentObject(getAttachmentKey(bp), camelAttachment);
             }
         }
         if (content instanceof BodyPart) {

http://git-wip-us.apache.org/repos/asf/camel/blob/50d6d4fb/components/camel-mail/src/test/java/org/apache/camel/component/mail/MailAttachmentTest.java
----------------------------------------------------------------------
diff --git a/components/camel-mail/src/test/java/org/apache/camel/component/mail/MailAttachmentTest.java b/components/camel-mail/src/test/java/org/apache/camel/component/mail/MailAttachmentTest.java
index e9ae035..fce729e 100644
--- a/components/camel-mail/src/test/java/org/apache/camel/component/mail/MailAttachmentTest.java
+++ b/components/camel-mail/src/test/java/org/apache/camel/component/mail/MailAttachmentTest.java
@@ -21,12 +21,14 @@ import java.util.Map;
 import javax.activation.DataHandler;
 import javax.activation.FileDataSource;
 
+import org.apache.camel.Attachment;
 import org.apache.camel.Endpoint;
 import org.apache.camel.Exchange;
 import org.apache.camel.Message;
 import org.apache.camel.Producer;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.impl.DefaultAttachment;
 import org.apache.camel.test.junit4.CamelTestSupport;
 import org.junit.Test;
 import org.jvnet.mock_javamail.Mailbox;
@@ -50,7 +52,9 @@ public class MailAttachmentTest extends CamelTestSupport {
         Exchange exchange = endpoint.createExchange();
         Message in = exchange.getIn();
         in.setBody("Hello World");
-        in.addAttachment("logo.jpeg", new DataHandler(new FileDataSource("src/test/data/logo.jpeg")));
+        DefaultAttachment att = new DefaultAttachment(new FileDataSource("src/test/data/logo.jpeg"));
+        att.addHeader("Content-Description", "some sample content");
+        in.addAttachmentObject("logo.jpeg", att);
 
         // create a producer that can produce the exchange (= send the mail)
         Producer producer = endpoint.createProducer();
@@ -73,11 +77,12 @@ public class MailAttachmentTest extends CamelTestSupport {
         assertEquals("Hello World", out.getIn().getBody(String.class));
 
         // attachment
-        Map<String, DataHandler> attachments = out.getIn().getAttachments();
+        Map<String, Attachment> attachments = out.getIn().getAttachmentObjects();
         assertNotNull("Should have attachments", attachments);
         assertEquals(1, attachments.size());
 
-        DataHandler handler = out.getIn().getAttachment("logo.jpeg");
+        Attachment attachment = out.getIn().getAttachmentObject("logo.jpeg");
+        DataHandler handler = attachment.getDataHandler();
         assertNotNull("The logo should be there", handler);
 
         // content type should match
@@ -87,6 +92,8 @@ public class MailAttachmentTest extends CamelTestSupport {
 
         assertEquals("Handler name should be the file name", "logo.jpeg", handler.getName());
 
+        assertEquals("some sample content", attachment.getHeader("content-description"));
+
         producer.stop();
     }