You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2015/11/13 17:32:37 UTC
[1/4] camel git commit: Fixed CS
Repository: camel
Updated Branches:
refs/heads/camel-2.16.x 59b54c679 -> b2ce0f990
refs/heads/master 74eda663a -> 7fb7b5641
Fixed CS
Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/7fb7b564
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/7fb7b564
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/7fb7b564
Branch: refs/heads/master
Commit: 7fb7b56413a625ea80830b3a930a7182d13a1565
Parents: 86d08e2
Author: Claus Ibsen <da...@apache.org>
Authored: Fri Nov 13 17:34:54 2015 +0100
Committer: Claus Ibsen <da...@apache.org>
Committed: Fri Nov 13 17:35:02 2015 +0100
----------------------------------------------------------------------
.../src/main/java/org/apache/camel/builder/DataFormatClause.java | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/camel/blob/7fb7b564/camel-core/src/main/java/org/apache/camel/builder/DataFormatClause.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/builder/DataFormatClause.java b/camel-core/src/main/java/org/apache/camel/builder/DataFormatClause.java
index 689ef1f..c80f45d 100644
--- a/camel-core/src/main/java/org/apache/camel/builder/DataFormatClause.java
+++ b/camel-core/src/main/java/org/apache/camel/builder/DataFormatClause.java
@@ -20,6 +20,8 @@ import java.nio.charset.Charset;
import java.util.Map;
import java.util.zip.Deflater;
+import org.w3c.dom.Node;
+
import org.apache.camel.model.DataFormatDefinition;
import org.apache.camel.model.ProcessorDefinition;
import org.apache.camel.model.dataformat.AvroDataFormat;
@@ -56,7 +58,6 @@ import org.apache.camel.model.dataformat.ZipDataFormat;
import org.apache.camel.model.dataformat.ZipFileDataFormat;
import org.apache.camel.util.CollectionStringBuffer;
import org.apache.camel.util.jsse.KeyStoreParameters;
-import org.w3c.dom.Node;
/**
* An expression for constructing the different possible {@link org.apache.camel.spi.DataFormat}
[2/4] camel git commit: Fixed CS
Posted by da...@apache.org.
Fixed CS
Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/86d08e2b
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/86d08e2b
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/86d08e2b
Branch: refs/heads/master
Commit: 86d08e2b4c762fb4e2753807abf2603d0a09bbe0
Parents: 08aa98f
Author: Claus Ibsen <da...@apache.org>
Authored: Fri Nov 13 17:33:46 2015 +0100
Committer: Claus Ibsen <da...@apache.org>
Committed: Fri Nov 13 17:35:02 2015 +0100
----------------------------------------------------------------------
.../dynamicrouter/DynamicRouterConcurrentPOJOTest.java | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/camel/blob/86d08e2b/camel-core/src/test/java/org/apache/camel/processor/dynamicrouter/DynamicRouterConcurrentPOJOTest.java
----------------------------------------------------------------------
diff --git a/camel-core/src/test/java/org/apache/camel/processor/dynamicrouter/DynamicRouterConcurrentPOJOTest.java b/camel-core/src/test/java/org/apache/camel/processor/dynamicrouter/DynamicRouterConcurrentPOJOTest.java
index eb6db04..776c801 100644
--- a/camel-core/src/test/java/org/apache/camel/processor/dynamicrouter/DynamicRouterConcurrentPOJOTest.java
+++ b/camel-core/src/test/java/org/apache/camel/processor/dynamicrouter/DynamicRouterConcurrentPOJOTest.java
@@ -16,7 +16,10 @@
*/
package org.apache.camel.processor.dynamicrouter;
-import org.apache.camel.*;
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.DynamicRouter;
+import org.apache.camel.Exchange;
+import org.apache.camel.Header;
import org.apache.camel.builder.RouteBuilder;
public class DynamicRouterConcurrentPOJOTest extends ContextTestSupport {
[4/4] camel git commit: Fixed CS
Posted by da...@apache.org.
Fixed CS
Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/b2ce0f99
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/b2ce0f99
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/b2ce0f99
Branch: refs/heads/camel-2.16.x
Commit: b2ce0f99032fc8b9f26c97370ce8a794006e2135
Parents: 59b54c6
Author: Claus Ibsen <da...@apache.org>
Authored: Fri Nov 13 17:33:46 2015 +0100
Committer: Claus Ibsen <da...@apache.org>
Committed: Fri Nov 13 17:35:51 2015 +0100
----------------------------------------------------------------------
.../dynamicrouter/DynamicRouterConcurrentPOJOTest.java | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/camel/blob/b2ce0f99/camel-core/src/test/java/org/apache/camel/processor/dynamicrouter/DynamicRouterConcurrentPOJOTest.java
----------------------------------------------------------------------
diff --git a/camel-core/src/test/java/org/apache/camel/processor/dynamicrouter/DynamicRouterConcurrentPOJOTest.java b/camel-core/src/test/java/org/apache/camel/processor/dynamicrouter/DynamicRouterConcurrentPOJOTest.java
index eb6db04..776c801 100644
--- a/camel-core/src/test/java/org/apache/camel/processor/dynamicrouter/DynamicRouterConcurrentPOJOTest.java
+++ b/camel-core/src/test/java/org/apache/camel/processor/dynamicrouter/DynamicRouterConcurrentPOJOTest.java
@@ -16,7 +16,10 @@
*/
package org.apache.camel.processor.dynamicrouter;
-import org.apache.camel.*;
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.DynamicRouter;
+import org.apache.camel.Exchange;
+import org.apache.camel.Header;
import org.apache.camel.builder.RouteBuilder;
public class DynamicRouterConcurrentPOJOTest extends ContextTestSupport {
[3/4] camel git commit: CAMEL-9283: Data Format for MIME-Multipart.
Thanks to Stephan Siano for the patch.
Posted by da...@apache.org.
CAMEL-9283: Data Format for MIME-Multipart. Thanks to Stephan Siano for the patch.
Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/08aa98f8
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/08aa98f8
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/08aa98f8
Branch: refs/heads/master
Commit: 08aa98f8bc771b7edf2a51978c94835d0cd3624c
Parents: 74eda66
Author: Claus Ibsen <da...@apache.org>
Authored: Fri Nov 13 16:39:58 2015 +0100
Committer: Claus Ibsen <da...@apache.org>
Committed: Fri Nov 13 17:35:02 2015 +0100
----------------------------------------------------------------------
.../apache/camel/builder/DataFormatClause.java | 63 ++++-
.../model/dataformat/DataFormatsDefinition.java | 1 +
.../dataformat/MimeMultipartDataFormat.java | 124 +++++++++
.../apache/camel/model/dataformat/jaxb.index | 1 +
components/camel-mail/pom.xml | 5 +-
.../mime/multipart/MimeMultipartDataFormat.java | 241 ++++++++++++++++
.../org/apache/camel/dataformat/mime-multipart | 18 ++
.../multipart/MimeMultipartDataFormatTest.java | 275 +++++++++++++++++++
8 files changed, 724 insertions(+), 4 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/camel/blob/08aa98f8/camel-core/src/main/java/org/apache/camel/builder/DataFormatClause.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/builder/DataFormatClause.java b/camel-core/src/main/java/org/apache/camel/builder/DataFormatClause.java
index 9495f4c..689ef1f 100644
--- a/camel-core/src/main/java/org/apache/camel/builder/DataFormatClause.java
+++ b/camel-core/src/main/java/org/apache/camel/builder/DataFormatClause.java
@@ -20,8 +20,6 @@ import java.nio.charset.Charset;
import java.util.Map;
import java.util.zip.Deflater;
-import org.w3c.dom.Node;
-
import org.apache.camel.model.DataFormatDefinition;
import org.apache.camel.model.ProcessorDefinition;
import org.apache.camel.model.dataformat.AvroDataFormat;
@@ -41,6 +39,7 @@ import org.apache.camel.model.dataformat.JaxbDataFormat;
import org.apache.camel.model.dataformat.JibxDataFormat;
import org.apache.camel.model.dataformat.JsonDataFormat;
import org.apache.camel.model.dataformat.JsonLibrary;
+import org.apache.camel.model.dataformat.MimeMultipartDataFormat;
import org.apache.camel.model.dataformat.PGPDataFormat;
import org.apache.camel.model.dataformat.ProtobufDataFormat;
import org.apache.camel.model.dataformat.RssDataFormat;
@@ -57,6 +56,7 @@ import org.apache.camel.model.dataformat.ZipDataFormat;
import org.apache.camel.model.dataformat.ZipFileDataFormat;
import org.apache.camel.util.CollectionStringBuffer;
import org.apache.camel.util.jsse.KeyStoreParameters;
+import org.w3c.dom.Node;
/**
* An expression for constructing the different possible {@link org.apache.camel.spi.DataFormat}
@@ -272,6 +272,65 @@ public class DataFormatClause<T extends ProcessorDefinition<?>> {
}
/**
+ * Uses the MIME Multipart data format
+ */
+ public T mimeMultipart() {
+ MimeMultipartDataFormat mm = new MimeMultipartDataFormat();
+ return dataFormat(mm);
+ }
+
+ /**
+ * Uses the MIME Multipart data format
+ *
+ * @param multipartSubType Specifies the subtype of the MIME Multipart
+ */
+ public T mimeMultipart(String multipartSubType) {
+ MimeMultipartDataFormat mm = new MimeMultipartDataFormat();
+ mm.setMultipartSubType(multipartSubType);
+ return dataFormat(mm);
+ }
+
+ /**
+ * Uses the MIME Multipart data format
+ *
+ * @param multipartSubType the subtype of the MIME Multipart
+ * @param multipartWithoutAttachment defines whether a message without attachment is also marshaled
+ * into a MIME Multipart (with only one body part).
+ * @param headersInline define the MIME Multipart headers as part of the message body
+ * or as Camel headers
+ * @param binaryContent have binary encoding for binary content (true) or use Base-64
+ * encoding for binary content (false)
+ */
+ public T mimeMultipart(String multipartSubType, boolean multipartWithoutAttachment, boolean headersInline,
+ boolean binaryContent) {
+ MimeMultipartDataFormat mm = new MimeMultipartDataFormat();
+ mm.setMultipartSubType(multipartSubType);
+ mm.setMultipartWithoutAttachment(multipartWithoutAttachment);
+ mm.setHeadersInline(headersInline);
+ mm.setBinaryContent(binaryContent);
+ return dataFormat(mm);
+ }
+
+ /**
+ * Uses the MIME Multipart data format
+ *
+ * @param multipartWithoutAttachment defines whether a message without attachment is also marshaled
+ * into a MIME Multipart (with only one body part).
+ * @param headersInline define the MIME Multipart headers as part of the message body
+ * or as Camel headers
+ * @param binaryContent have binary encoding for binary content (true) or use Base-64
+ * encoding for binary content (false)
+ */
+ public T mimeMultipart(boolean multipartWithoutAttachment, boolean headersInline,
+ boolean binaryContent) {
+ MimeMultipartDataFormat mm = new MimeMultipartDataFormat();
+ mm.setMultipartWithoutAttachment(multipartWithoutAttachment);
+ mm.setHeadersInline(headersInline);
+ mm.setBinaryContent(binaryContent);
+ return dataFormat(mm);
+ }
+
+ /**
* Uses the PGP data format
*/
public T pgp(String keyFileName, String keyUserid) {
http://git-wip-us.apache.org/repos/asf/camel/blob/08aa98f8/camel-core/src/main/java/org/apache/camel/model/dataformat/DataFormatsDefinition.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/model/dataformat/DataFormatsDefinition.java b/camel-core/src/main/java/org/apache/camel/model/dataformat/DataFormatsDefinition.java
index d0ea53b..bdb8caf 100644
--- a/camel-core/src/main/java/org/apache/camel/model/dataformat/DataFormatsDefinition.java
+++ b/camel-core/src/main/java/org/apache/camel/model/dataformat/DataFormatsDefinition.java
@@ -57,6 +57,7 @@ public class DataFormatsDefinition {
@XmlElement(required = false, name = "jaxb", type = JaxbDataFormat.class),
@XmlElement(required = false, name = "jibx", type = JibxDataFormat.class),
@XmlElement(required = false, name = "json", type = JsonDataFormat.class),
+ @XmlElement(required = false, name = "mimeMultipart", type = MimeMultipartDataFormat.class),
@XmlElement(required = false, name = "protobuf", type = ProtobufDataFormat.class),
@XmlElement(required = false, name = "rss", type = RssDataFormat.class),
@XmlElement(required = false, name = "secureXML", type = XMLSecurityDataFormat.class),
http://git-wip-us.apache.org/repos/asf/camel/blob/08aa98f8/camel-core/src/main/java/org/apache/camel/model/dataformat/MimeMultipartDataFormat.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/model/dataformat/MimeMultipartDataFormat.java b/camel-core/src/main/java/org/apache/camel/model/dataformat/MimeMultipartDataFormat.java
new file mode 100644
index 0000000..7116f39
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/model/dataformat/MimeMultipartDataFormat.java
@@ -0,0 +1,124 @@
+/**
+ * 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.model.dataformat;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.model.DataFormatDefinition;
+import org.apache.camel.spi.DataFormat;
+import org.apache.camel.spi.Metadata;
+
+/**
+ * MIME Multipart data format
+ */
+@Metadata(label = "dataformat,transformation", title = "MIME Multipart")
+@XmlRootElement(name = "mime-multipart")
+@XmlAccessorType(XmlAccessType.FIELD)
+public class MimeMultipartDataFormat extends DataFormatDefinition {
+
+ @XmlAttribute
+ @Metadata(defaultValue = "mixed")
+ private String multipartSubType = "mixed";
+ @XmlAttribute
+ @Metadata(defaultValue = "false")
+ private Boolean multipartWithoutAttachment;
+ @XmlAttribute
+ @Metadata(defaultValue = "false")
+ private Boolean headersInline;
+ @XmlAttribute
+ @Metadata(defaultValue = "false")
+ private Boolean binaryContent;
+
+ public MimeMultipartDataFormat() {
+ super("mime-multipart");
+ }
+
+ @Override
+ protected void configureDataFormat(DataFormat dataFormat, CamelContext camelContext) {
+ if (getMultipartSubType() != null) {
+ setProperty(camelContext, dataFormat, "multipartSubType", getMultipartSubType());
+ }
+ if (getMultipartWithoutAttachment() != null) {
+ setProperty(camelContext, dataFormat, "multipartWithoutAttachment", getMultipartWithoutAttachment());
+ }
+ if (getHeadersInline() != null) {
+ setProperty(camelContext, dataFormat, "headersInline", getHeadersInline());
+ }
+ if (getBinaryContent() != null) {
+ setProperty(camelContext, dataFormat, "binaryContent", getBinaryContent());
+ }
+ }
+
+ public String getMultipartSubType() {
+ return multipartSubType;
+ }
+
+ /**
+ * Specify the subtype of the MIME Multipart.
+ * <p>
+ * Default is "mixed".
+ */
+ public void setMultipartSubType(String multipartSubType) {
+ this.multipartSubType = multipartSubType;
+ }
+
+ public Boolean getMultipartWithoutAttachment() {
+ return multipartWithoutAttachment;
+ }
+
+ /**
+ * Defines whether a message without attachment is also marshaled into a
+ * MIME Multipart (with only one body part).
+ * <p>
+ * Default is "false".
+ */
+ public void setMultipartWithoutAttachment(Boolean multipartWithoutAttachment) {
+ this.multipartWithoutAttachment = multipartWithoutAttachment;
+ }
+
+ public Boolean getHeadersInline() {
+ return headersInline;
+ }
+
+ /**
+ * Defines whether the MIME-Multipart headers are part of the message body
+ * (true) or are set as Camel headers (false).
+ * <p>
+ * Default is "false".
+ */
+ public void setHeadersInline(Boolean headersInline) {
+ this.headersInline = headersInline;
+ }
+
+ public Boolean getBinaryContent() {
+ return binaryContent;
+ }
+
+ /**
+ * Defines whether the content of binary parts in the MIME multipart is
+ * binary (true) or Base-64 encoded (false)
+ * <p>
+ * Default is "false".
+ */
+ public void setBinaryContent(Boolean binaryContent) {
+ this.binaryContent = binaryContent;
+ }
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/08aa98f8/camel-core/src/main/resources/org/apache/camel/model/dataformat/jaxb.index
----------------------------------------------------------------------
diff --git a/camel-core/src/main/resources/org/apache/camel/model/dataformat/jaxb.index b/camel-core/src/main/resources/org/apache/camel/model/dataformat/jaxb.index
index 17a947c..07253ec 100644
--- a/camel-core/src/main/resources/org/apache/camel/model/dataformat/jaxb.index
+++ b/camel-core/src/main/resources/org/apache/camel/model/dataformat/jaxb.index
@@ -32,6 +32,7 @@ JaxbDataFormat
JibxDataFormat
JsonDataFormat
JsonLibrary
+MimeMultipartDataFormat
ProtobufDataFormat
RssDataFormat
SerializationDataFormat
http://git-wip-us.apache.org/repos/asf/camel/blob/08aa98f8/components/camel-mail/pom.xml
----------------------------------------------------------------------
diff --git a/components/camel-mail/pom.xml b/components/camel-mail/pom.xml
index 5069c05..d5123ce 100644
--- a/components/camel-mail/pom.xml
+++ b/components/camel-mail/pom.xml
@@ -30,7 +30,7 @@
<description>Camel Mail support</description>
<properties>
- <camel.osgi.export.pkg>org.apache.camel.component.mail.*</camel.osgi.export.pkg>
+ <camel.osgi.export.pkg>org.apache.camel.component.mail.*,org.apache.camel.dataformat.mime.multipart.*</camel.osgi.export.pkg>
<camel.osgi.export.service>
org.apache.camel.spi.ComponentResolver;component=imap,
org.apache.camel.spi.ComponentResolver;component=imaps,
@@ -38,7 +38,8 @@
org.apache.camel.spi.ComponentResolver;component=pop3,
org.apache.camel.spi.ComponentResolver;component=pop3s,
org.apache.camel.spi.ComponentResolver;component=smtp,
- org.apache.camel.spi.ComponentResolver;component=smtps
+ org.apache.camel.spi.ComponentResolver;component=smtps,
+ org.apache.camel.spi.DataFormatResolver;dataformat=mime-multipart
</camel.osgi.export.service>
</properties>
http://git-wip-us.apache.org/repos/asf/camel/blob/08aa98f8/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
new file mode 100644
index 0000000..7d6cf1c
--- /dev/null
+++ b/components/camel-mail/src/main/java/org/apache/camel/dataformat/mime/multipart/MimeMultipartDataFormat.java
@@ -0,0 +1,241 @@
+/**
+ * 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.dataformat.mime.multipart;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Map;
+
+import javax.activation.DataHandler;
+import javax.activation.DataSource;
+import javax.mail.BodyPart;
+import javax.mail.Header;
+import javax.mail.MessagingException;
+import javax.mail.Part;
+import javax.mail.Session;
+import javax.mail.internet.ContentType;
+import javax.mail.internet.InternetHeaders;
+import javax.mail.internet.MimeBodyPart;
+import javax.mail.internet.MimeMessage;
+import javax.mail.internet.MimeMultipart;
+import javax.mail.internet.MimeUtility;
+import javax.mail.internet.ParseException;
+import javax.mail.util.ByteArrayDataSource;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.NoTypeConversionAvailableException;
+import org.apache.camel.spi.DataFormat;
+import org.apache.camel.util.ExchangeHelper;
+import org.apache.camel.util.IOHelper;
+import org.apache.camel.util.MessageHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MimeMultipartDataFormat implements DataFormat {
+ private static final Logger LOG = LoggerFactory.getLogger(MimeMultipartDataFormat.class);
+ private static final String MIME_VERSION = "MIME-Version";
+ private static final String CONTENT_TYPE = "Content-Type";
+ private static final String CONTENT_TRANSFER_ENCODING = "Content-Transfer-Encoding";
+ private static final String DEFAULT_CONTENT_TYPE = "application/octet-stream";
+ private String multipartSubType = "mixed";
+ private boolean multipartWithoutAttachment;
+ private boolean headersInline;
+ private boolean binaryContent;
+
+ public void setBinaryContent(boolean binaryContent) {
+ this.binaryContent = binaryContent;
+ }
+
+ public void setHeadersInline(boolean headersInline) {
+ this.headersInline = headersInline;
+ }
+
+ public void setMultipartWithoutAttachment(boolean multipartWithoutAttachment) {
+ this.multipartWithoutAttachment = multipartWithoutAttachment;
+ }
+
+ public void setMultipartSubType(String multipartSubType) {
+ this.multipartSubType = multipartSubType;
+ }
+
+ @Override
+ public void marshal(Exchange exchange, Object graph, OutputStream stream)
+ throws NoTypeConversionAvailableException, MessagingException, IOException {
+ if (multipartWithoutAttachment || headersInline || exchange.getIn().hasAttachments()) {
+ ContentType contentType = getContentType(exchange);
+ // remove the Content-Type header. This will be wrong afterwards...
+ exchange.getOut().removeHeader(Exchange.CONTENT_TYPE);
+ byte[] bodyContent = ExchangeHelper.convertToMandatoryType(exchange, byte[].class, graph);
+ Session session = Session.getInstance(System.getProperties());
+ MimeMessage mm = new MimeMessage(session);
+ MimeMultipart mp = new MimeMultipart(multipartSubType);
+ BodyPart part = new MimeBodyPart();
+ writeBodyPart(bodyContent, part, contentType);
+ mp.addBodyPart(part);
+ for (Map.Entry<String, DataHandler> entry : exchange.getIn().getAttachments().entrySet()) {
+ String attachmentFilename = entry.getKey();
+ DataHandler handler = entry.getValue();
+ part = new MimeBodyPart();
+ part.setDataHandler(handler);
+ part.setFileName(MimeUtility.encodeText(attachmentFilename, "UTF-8", null));
+ String ct = handler.getContentType();
+ contentType = new ContentType(ct);
+ part.setHeader(CONTENT_TYPE, ct);
+ if (!contentType.match("text/*") && binaryContent) {
+ part.setHeader(CONTENT_TRANSFER_ENCODING, "binary");
+ }
+ mp.addBodyPart(part);
+ exchange.getOut().removeAttachment(attachmentFilename);
+ }
+ mm.setContent(mp);
+ mm.saveChanges();
+ Enumeration<?> hl = mm.getAllHeaders();
+ List<String> headers = new ArrayList<String>();
+ if (!headersInline) {
+ while (hl.hasMoreElements()) {
+ Object ho = hl.nextElement();
+ if (ho instanceof Header) {
+ Header h = (Header) ho;
+ exchange.getOut().setHeader(h.getName(), h.getValue());
+ headers.add(h.getName());
+ }
+ }
+ mm.saveChanges();
+ }
+ mm.writeTo(stream, headers.toArray(new String[0]));
+ } else {
+ // keep the original data
+ InputStream is = ExchangeHelper.convertToMandatoryType(exchange, InputStream.class, graph);
+ IOHelper.copyAndCloseInput(is, stream);
+ }
+ }
+
+ private ContentType getContentType(Exchange exchange) throws ParseException {
+ String contentTypeStr = ExchangeHelper.getContentType(exchange);
+ if (contentTypeStr == null) {
+ contentTypeStr = DEFAULT_CONTENT_TYPE;
+ }
+ ContentType contentType = new ContentType(contentTypeStr);
+ String contentEncoding = ExchangeHelper.getContentEncoding(exchange);
+ // add a charset parameter for text subtypes
+ if (contentEncoding != null && contentType.match("text/*")) {
+ contentType.setParameter("charset", MimeUtility.mimeCharset(contentEncoding));
+ }
+ return contentType;
+ }
+
+ private void writeBodyPart(byte[] bodyContent, Part part, ContentType contentType) throws MessagingException {
+ DataSource ds = new ByteArrayDataSource(bodyContent, contentType.toString());
+ part.setDataHandler(new DataHandler(ds));
+ part.setHeader(CONTENT_TYPE, contentType.toString());
+ if (contentType.match("text/*")) {
+ part.setHeader(CONTENT_TRANSFER_ENCODING, "8bit");
+ } else if (binaryContent) {
+ part.setHeader(CONTENT_TRANSFER_ENCODING, "binary");
+ } else {
+ part.setHeader(CONTENT_TRANSFER_ENCODING, "base64");
+ }
+ }
+
+ @Override
+ public Object unmarshal(Exchange exchange, InputStream stream) throws IOException, MessagingException {
+ MimeBodyPart mimeMessage;
+ String contentType;
+ Message camelMessage;
+ Object content = null;
+ if (headersInline) {
+ mimeMessage = new MimeBodyPart(stream);
+ camelMessage = exchange.getOut();
+ MessageHelper.copyHeaders(exchange.getIn(), camelMessage, true);
+ contentType = mimeMessage.getHeader(CONTENT_TYPE, null);
+ } else {
+ // check if this a multipart at all. Otherwise do nothing
+ contentType = exchange.getIn().getHeader(CONTENT_TYPE, String.class);
+ if (contentType == null) {
+ return stream;
+ }
+ try {
+ ContentType ct = new ContentType(contentType);
+ if (!ct.match("multipart/*")) {
+ return stream;
+ }
+ } catch (ParseException e) {
+ LOG.warn("Invalid Content-Type " + contentType + " ignored");
+ return stream;
+ }
+ camelMessage = exchange.getOut();
+ MessageHelper.copyHeaders(exchange.getIn(), camelMessage, true);
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ IOHelper.copyAndCloseInput(stream, bos);
+ InternetHeaders headers = new InternetHeaders();
+ extractHeader(CONTENT_TYPE, camelMessage, headers);
+ extractHeader(MIME_VERSION, camelMessage, headers);
+ mimeMessage = new MimeBodyPart(headers, bos.toByteArray());
+ bos.close();
+ }
+ DataHandler dh;
+ try {
+ dh = mimeMessage.getDataHandler();
+ if (dh != null) {
+ content = dh.getContent();
+ contentType = dh.getContentType();
+ }
+ } catch (MessagingException e) {
+ LOG.warn("cannot parse message, no unmarshalling done");
+ }
+ if (content instanceof MimeMultipart) {
+ MimeMultipart mp = (MimeMultipart) content;
+ content = mp.getBodyPart(0);
+ for (int i = 1; i < mp.getCount(); i++) {
+ BodyPart bp = mp.getBodyPart(i);
+ camelMessage.addAttachment(MimeUtility.decodeText(bp.getFileName()), bp.getDataHandler());
+ }
+ }
+ if (content instanceof BodyPart) {
+ BodyPart bp = (BodyPart) content;
+ camelMessage.setBody(bp.getInputStream());
+ contentType = bp.getContentType();
+ } else {
+ // Last fallback: I don't see how this can happen, but we do this
+ // just to be safe
+ camelMessage.setBody(content);
+ }
+ if (contentType != null && !DEFAULT_CONTENT_TYPE.equals(contentType)) {
+ camelMessage.setHeader(CONTENT_TYPE, contentType);
+ ContentType ct = new ContentType(contentType);
+ String charset = ct.getParameter("charset");
+ if (charset != null) {
+ camelMessage.setHeader(Exchange.CONTENT_ENCODING, MimeUtility.javaCharset(charset));
+ }
+ }
+ return camelMessage;
+ }
+
+ private void extractHeader(String headerMame, Message camelMessage, InternetHeaders headers) {
+ String h = camelMessage.getHeader(headerMame, String.class);
+ if (h != null) {
+ headers.addHeader(headerMame, h);
+ camelMessage.removeHeader(headerMame);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/08aa98f8/components/camel-mail/src/main/resources/META-INF/services/org/apache/camel/dataformat/mime-multipart
----------------------------------------------------------------------
diff --git a/components/camel-mail/src/main/resources/META-INF/services/org/apache/camel/dataformat/mime-multipart b/components/camel-mail/src/main/resources/META-INF/services/org/apache/camel/dataformat/mime-multipart
new file mode 100644
index 0000000..b8483d2
--- /dev/null
+++ b/components/camel-mail/src/main/resources/META-INF/services/org/apache/camel/dataformat/mime-multipart
@@ -0,0 +1,18 @@
+#
+# 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.
+#
+
+class=org.apache.camel.dataformat.mime.multipart.MimeMultipartDataFormat
http://git-wip-us.apache.org/repos/asf/camel/blob/08aa98f8/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
new file mode 100644
index 0000000..7dbfe42
--- /dev/null
+++ b/components/camel-mail/src/test/java/org/apache/camel/dataformat/mime/multipart/MimeMultipartDataFormatTest.java
@@ -0,0 +1,275 @@
+/**
+ * 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.dataformat.mime.multipart;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.activation.DataHandler;
+import javax.activation.DataSource;
+import javax.mail.util.ByteArrayDataSource;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.impl.DefaultExchange;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.apache.camel.util.IOHelper;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.hamcrest.core.IsCollectionContaining.hasItem;
+import static org.hamcrest.core.StringStartsWith.startsWith;
+
+public class MimeMultipartDataFormatTest extends CamelTestSupport {
+ private Exchange exchange;
+ private Message in;
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ exchange = new DefaultExchange(context);
+ in = exchange.getIn();
+ }
+
+ @Test
+ public void roundtripWithTextAttachments() throws IOException {
+ String attContentType = "text/plain";
+ String attText = "Attachment Text";
+ String attFileName = "Attachment File Name";
+ 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);
+ Exchange result = template.send("direct:roundtrip", exchange);
+ Message out = result.getOut();
+ assertEquals("Body text", out.getBody(String.class));
+ assertThat(out.getHeader(Exchange.CONTENT_TYPE, String.class), startsWith("text/plain"));
+ assertEquals("UTF8", out.getHeader(Exchange.CONTENT_ENCODING));
+ assertTrue(out.hasAttachments());
+ assertEquals(1, out.getAttachmentNames().size());
+ assertThat(out.getAttachmentNames(), hasItem(attFileName));
+ DataHandler dh = out.getAttachment(attFileName);
+ assertNotNull(dh);
+ assertEquals(attContentType, dh.getContentType());
+ InputStream is = dh.getInputStream();
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ IOHelper.copyAndCloseInput(is, os);
+ assertEquals(attText, new String(os.toByteArray()));
+ }
+
+ @Test
+ public void roundtripWithTextAttachmentsHeadersInline() throws IOException {
+ String attContentType = "text/plain";
+ String attText = "Attachment Text";
+ String attFileName = "Attachment File Name";
+ 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);
+ Exchange result = template.send("direct:roundtripinlineheaders", exchange);
+ Message out = result.getOut();
+ assertEquals("Body text", out.getBody(String.class));
+ assertThat(out.getHeader(Exchange.CONTENT_TYPE, String.class), startsWith("text/plain"));
+ assertEquals("UTF8", out.getHeader(Exchange.CONTENT_ENCODING));
+ assertTrue(out.hasAttachments());
+ assertEquals(1, out.getAttachmentNames().size());
+ assertThat(out.getAttachmentNames(), hasItem(attFileName));
+ DataHandler dh = out.getAttachment(attFileName);
+ assertNotNull(dh);
+ assertEquals(attContentType, dh.getContentType());
+ InputStream is = dh.getInputStream();
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ IOHelper.copyAndCloseInput(is, os);
+ assertEquals(attText, new String(os.toByteArray()));
+ }
+
+ @Test
+ public void roundtripWithTextAttachmentsAndSpecialCharacters() throws IOException {
+ String attContentType = "text/plain";
+ String attText = "Attachment Text with special characters: \u00A9";
+ String attFileName = "Attachment File Name with special characters: \u00A9";
+ in.setBody("Body text with special characters: \u00A9");
+ in.setHeader(Exchange.CONTENT_TYPE, "text/plain");
+ in.setHeader(Exchange.CONTENT_ENCODING, "UTF8");
+ addAttachment(attContentType, attText, attFileName);
+ Exchange result = template.send("direct:roundtrip", exchange);
+ Message out = result.getOut();
+ assertEquals("Body text with special characters: \u00A9", out.getBody(String.class));
+ assertThat(out.getHeader(Exchange.CONTENT_TYPE, String.class), startsWith("text/plain"));
+ assertEquals("UTF8", out.getHeader(Exchange.CONTENT_ENCODING));
+ assertTrue(out.hasAttachments());
+ assertEquals(1, out.getAttachmentNames().size());
+ assertThat(out.getAttachmentNames(), hasItem(attFileName));
+ DataHandler dh = out.getAttachment(attFileName);
+ assertNotNull(dh);
+ assertEquals(attContentType, dh.getContentType());
+ InputStream is = dh.getInputStream();
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ IOHelper.copyAndCloseInput(is, os);
+ assertEquals(attText, new String(os.toByteArray()));
+ }
+
+ @Test
+ public void roundtripWithTextAttachmentsAndBinaryContent() throws IOException {
+ String attContentType = "text/plain";
+ String attText = "Attachment Text";
+ String attFileName = "Attachment File Name";
+ 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);
+ Exchange result = template.send("direct:roundtripbinarycontent", exchange);
+ Message out = result.getOut();
+ assertEquals("Body text", out.getBody(String.class));
+ assertThat(out.getHeader(Exchange.CONTENT_TYPE, String.class), startsWith("text/plain"));
+ assertEquals("UTF8", out.getHeader(Exchange.CONTENT_ENCODING));
+ assertTrue(out.hasAttachments());
+ assertEquals(1, out.getAttachmentNames().size());
+ assertThat(out.getAttachmentNames(), hasItem(attFileName));
+ DataHandler dh = out.getAttachment(attFileName);
+ assertNotNull(dh);
+ assertEquals(attContentType, dh.getContentType());
+ InputStream is = dh.getInputStream();
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ IOHelper.copyAndCloseInput(is, os);
+ assertEquals(attText, new String(os.toByteArray()));
+ }
+
+ @Test
+ public void roundtripWithBinaryAttachments() throws IOException {
+ String attContentType = "application/binary";
+ byte[] attText = {0, 1, 2, 3, 4, 5, 6, 7};
+ String attFileName = "Attachment File Name";
+ in.setBody("Body text");
+ DataSource ds = new ByteArrayDataSource(attText, attContentType);
+ in.addAttachment(attFileName, new DataHandler(ds));
+ Exchange result = template.send("direct:roundtrip", exchange);
+ Message out = result.getOut();
+ assertEquals("Body text", out.getBody(String.class));
+ assertTrue(out.hasAttachments());
+ assertEquals(1, out.getAttachmentNames().size());
+ assertThat(out.getAttachmentNames(), hasItem(attFileName));
+ DataHandler dh = out.getAttachment(attFileName);
+ assertNotNull(dh);
+ assertEquals(attContentType, dh.getContentType());
+ InputStream is = dh.getInputStream();
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ IOHelper.copyAndCloseInput(is, os);
+ assertArrayEquals(attText, os.toByteArray());
+ }
+
+ @Test
+ public void roundtripWithBinaryAttachmentsAndBinaryContent() throws IOException {
+ String attContentType = "application/binary";
+ byte[] attText = {0, 1, 2, 3, 4, 5, 6, 7};
+ String attFileName = "Attachment File Name";
+ in.setBody("Body text");
+ DataSource ds = new ByteArrayDataSource(attText, attContentType);
+ in.addAttachment(attFileName, new DataHandler(ds));
+ Exchange result = template.send("direct:roundtripbinarycontent", exchange);
+ Message out = result.getOut();
+ assertEquals("Body text", out.getBody(String.class));
+ assertTrue(out.hasAttachments());
+ assertEquals(1, out.getAttachmentNames().size());
+ assertThat(out.getAttachmentNames(), hasItem(attFileName));
+ DataHandler dh = out.getAttachment(attFileName);
+ assertNotNull(dh);
+ assertEquals(attContentType, dh.getContentType());
+ InputStream is = dh.getInputStream();
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ IOHelper.copyAndCloseInput(is, os);
+ assertArrayEquals(attText, os.toByteArray());
+ }
+
+ @Test
+ public void roundtripWithoutAttachments() throws IOException {
+ in.setBody("Body text");
+ Exchange result = template.send("direct:roundtrip", exchange);
+ Message out = result.getOut();
+ assertEquals("Body text", out.getBody(String.class));
+ assertFalse(out.hasAttachments());
+ }
+
+ @Test
+ public void roundtripWithoutAttachmentsToMultipart() throws IOException {
+ in.setBody("Body text");
+ Exchange result = template.send("direct:roundtripmultipart", exchange);
+ Message out = result.getOut();
+ assertEquals("Body text", out.getBody(String.class));
+ assertFalse(out.hasAttachments());
+ }
+
+ @Test
+ public void roundtripWithoutAttachmentsAndContentType() throws IOException {
+ in.setBody("Body text");
+ in.setHeader("Content-Type", "text/plain");
+ Exchange result = template.send("direct:roundtrip", exchange);
+ Message out = result.getOut();
+ assertEquals("Body text", out.getBody(String.class));
+ assertFalse(out.hasAttachments());
+ }
+
+ @Test
+ public void roundtripWithoutAttachmentsAndInvalidContentType() throws IOException {
+ in.setBody("Body text");
+ in.setHeader("Content-Type", "text?plain");
+ Exchange result = template.send("direct:roundtrip", exchange);
+ Message out = result.getOut();
+ assertEquals("Body text", out.getBody(String.class));
+ assertFalse(out.hasAttachments());
+ }
+
+ @Test
+ public void marhsalOnlyMixed() throws IOException {
+ in.setBody("Body text");
+ in.setHeader("Content-Type", "text/plain");
+ addAttachment("application/octet-stream", "foobar", "attachment.bin");
+ Exchange result = template.send("direct:marshalonlymixed", exchange);
+ assertThat(result.getOut().getHeader("Content-Type", String.class), startsWith("multipart/mixed"));
+ }
+
+ @Test
+ public void marhsalOnlyRelated() throws IOException {
+ in.setBody("Body text");
+ in.setHeader("Content-Type", "text/plain");
+ addAttachment("application/octet-stream", "foobar", "attachment.bin");
+ Exchange result = template.send("direct:marshalonlyrelated", exchange);
+ assertThat(result.getOut().getHeader("Content-Type", String.class), startsWith("multipart/related"));
+ }
+
+ private void addAttachment(String attContentType, String attText, String attFileName) throws IOException {
+ DataSource ds = new ByteArrayDataSource(attText, attContentType);
+ in.addAttachment(attFileName, new DataHandler(ds));
+ }
+
+ @Override
+ protected RouteBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ from("direct:roundtrip").marshal().mimeMultipart().to("log:mime?showHeaders=true").unmarshal().mimeMultipart();
+ from("direct:roundtripmultipart").marshal().mimeMultipart(true, false, false).to("log:mime?showHeaders=true").unmarshal().mimeMultipart();
+ from("direct:roundtripinlineheaders").marshal().mimeMultipart(false, true, false).to("log:mime?showHeaders=true").unmarshal().mimeMultipart(false, true, false);
+ from("direct:roundtripbinarycontent").marshal().mimeMultipart(false, false, true).to("log:mime?showHeaders=true").to("dataformat:mime-multipart:unmarshal");
+ from("direct:marshalonlyrelated").marshal().mimeMultipart("related");
+ from("direct:marshalonlymixed").marshal().mimeMultipart();
+ }
+ };
+ }
+}