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 0000000000000..6cdc0e474c012 --- /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 getHeaderAsList(String name); + + /** + * Get all header names for this attachment. + * + * @return a collection of all header names + */ + Collection 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); +} 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 0000000000000..58d376f868da0 --- /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 { +} 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 df363ea806268..d400534f9f522 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.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 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 dd576a80a3185..7efb34c233f71 100644 --- a/camel-core/src/main/java/org/apache/camel/Message.java +++ b/camel-core/src/main/java/org/apache/camel/Message.java @@ -255,6 +255,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 null + */ + Attachment getAttachmentObject(String id); + /** * Returns a set of attachment names of the message * @@ -277,6 +285,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 * @@ -284,6 +300,13 @@ public interface Message { */ Map getAttachments(); + /** + * Returns all attachments of the message + * + * @return the attachments in a map or null + */ + Map getAttachmentObjects(); + /** * Set all the attachments associated with this message * @@ -291,6 +314,13 @@ public interface Message { */ void setAttachments(Map attachments); + /** + * Set all the attachments associated with this message + * + * @param attachments the attachments + */ + void setAttachmentObjects(Map attachments); + /** * Returns whether this message has attachments. * 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 3200990c3d488..b6069ead66f10 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 * 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 0ef21b8c61f66..9e1224c47372d 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 T outHeaders() { * An expression of the inbound message attachments */ public T attachments() { - return expression(ExpressionBuilder.attachmentValuesExpression()); + return expression(ExpressionBuilder.attachmentObjectValuesExpression()); } /** 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 3e23332ba2e72..5a3a0ef6300c4 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.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 @@ private Expression createParameterUnmarshalExpression(Class clazz, Method met 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; 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 0000000000000..5e032d515d228 --- /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(); + } +} 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 0000000000000..dbb87af0180a6 --- /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 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 getHeaderAsList(String name) { + if (headers != null) { + Object headerObject = headers.get(name); + if (headerObject instanceof List) { + return (List)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 getHeaderNames() { + if (headers == null) { + headers = createHeaders(); + } + return headers.keySet(); + } + + public void clearHeaders() { + headers = null; + } + + private Map createHeaders() { + return new TreeMap(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()); + } +} 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 0ed28417e6b69..848586ac02754 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.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 headers; private Map attachments; + private Map attachmentObjects; public boolean isFault() { return fault; @@ -199,14 +202,14 @@ protected Map createHeaders() { } /** - * 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 createAttachments() { - Map map = new LinkedHashMap(); + protected Map createAttachments() { + Map map = new LinkedHashMap(); populateInitialAttachments(map); return map; } @@ -222,12 +225,12 @@ protected void populateInitialHeaders(Map map) { } /** - * 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 map) { + protected void populateInitialAttachments(Map map) { // do nothing by default } @@ -247,45 +250,82 @@ protected Boolean isTransactedRedelivered() { } 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 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 getAttachments() { if (attachments == null) { - attachments = createAttachments(); + attachments = new AttachmentMap(getAttachmentObjects()); } return attachments; } + public Map getAttachmentObjects() { + if (attachmentObjects == null) { + attachmentObjects = createAttachments(); + } + return attachmentObjects; + } + public void setAttachments(Map 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(); + for (Map.Entry entry : attachments.entrySet()) { + this.attachmentObjects.put(entry.getKey(), new DefaultAttachment(entry.getValue())); + } + } + this.attachments = null; + } + + public void setAttachmentObjects(Map 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; } /** 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 029c0bfea14cf..2d4955e074421 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 void copyAttachments(Message that) { // 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()); } } } 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 dfa008e59c6a1..ed11fa927dd8f 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 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 CorePackageScanClassResolver() { converters.add(BeanConverter.class); converters.add(GenericFileConverter.class); converters.add(DurationConverter.class); + converters.add(AttachmentConverter.class); } @Override 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 fba3f71a0140b..ba3be2e7e3c75 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 Expression getExpression() { 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; 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 0000000000000..1f3354646e46b --- /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 + * interface for a Map + */ +public class AttachmentMap extends AbstractMap { + private Map map; + + public AttachmentMap(Map 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> entrySet() { + return new AttachmentEntrySet(map.entrySet()); + } + + public Map getOriginalMap() { + return map; + } + + private static class AttachmentEntrySet extends AbstractSet> { + private Set> set; + + public AttachmentEntrySet(Set> set) { + this.set = set; + } + + @Override + public int size() { + return set.size(); + } + + @Override + public Iterator> iterator() { + return new AttachmentEntrySetIterator(set.iterator()); + } + } + + private static class AttachmentEntrySetIterator implements Iterator> { + private Iterator> iter; + + public AttachmentEntrySetIterator(Iterator> origIterator) { + iter = origIterator; + } + + @Override + public boolean hasNext() { + return iter.hasNext(); + } + + @Override + public Map.Entry next() { + return new AttachmentEntry(iter.next()); + } + + public void remove() { + iter.remove(); + } + } + + private static class AttachmentEntry implements Map.Entry { + private Map.Entry entry; + + public AttachmentEntry(Map.Entry 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(); + } + } +} 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 73db6ad3d091f..af67e04724277 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 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 void testConversionOfMessageHeaders() throws Exception { 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 @@ protected void setUp() throws Exception { Message message = exchange.getIn(); message.setBody("world!"); 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")))); } } 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 f45aabe631f4c..f053177ecf608 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.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 void testAttachments() throws Exception { 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 attachments = mock.getExchanges().get(0).getIn().getAttachments(); + Map attachments = mock.getExchanges().get(0).getIn().getAttachmentObjects(); assertTrue(attachments == null || attachments.size() == 0); } 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 01e022eff7da3..9afe828216e47 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.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 void process(Exchange exchange) throws Exception { }); - 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 void configure() throws Exception { 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"))); } 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 3eea3005ab5bf..5f43bc4cb169d 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.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.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 void testBeanWithAnnotationAndExchangeTest() throws Exception { 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 void process(Exchange exchange) throws Exception { 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 @@ protected RouteBuilder createRouteBuilder() throws Exception { 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 attachments) { assertNotNull(attachments); @@ -80,4 +102,22 @@ public String doSomething(@Attachments Map attachments) { } // END SNIPPET: e1 } + + public static class AttachmentProcessor { + // START SNIPPET: e2 + public String doSomething(@AttachmentObjects Map 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 + } } 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 59b4cdc0cc0d7..f8073d2fd8e41 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 @@ 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 attachments = message.createAttachments(); + Map attachments = message.createAttachments(); assertThat(attachments, instanceOf(LinkedHashMap.class)); } 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 a264a9c3889ac..8156d8eb9a4e3 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.Message; import org.apache.camel.Processor; import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.impl.DefaultAttachment; /** * @@ -39,7 +40,7 @@ public void testMessageWithAttachmentRedeliveryIssue() throws Exception { 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")))); } }); 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 db58d81bc89b9..aa92a5d1f9092 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 void process(Exchange exchange) { }); // 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 void process(Exchange exchange) throws Exception { .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"); 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 aad23d54cd37a..bbad18a45ba6b 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.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.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 void populateCxfRequestFromExchange( // 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 entry : camelExchange.getIn().getAttachments().entrySet()) { + for (Map.Entry entry : camelExchange.getIn().getAttachmentObjects().entrySet()) { if (attachments == null) { attachments = new HashSet(); } - 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 void populateExchangeFromCxfResponse(Exchange camelExchange, 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 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 void populateExchangeFromCxfRequest(org.apache.cxf.message.Exchange cxfEx 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 void populateCxfResponseFromExchange(Exchange camelExchange, Set attachments = null; boolean isXop = Boolean.valueOf(camelExchange.getProperty(Message.MTOM_ENABLED, String.class)); - for (Map.Entry entry : camelExchange.getOut().getAttachments().entrySet()) { + for (Map.Entry entry : camelExchange.getOut().getAttachmentObjects().entrySet()) { if (attachments == null) { attachments = new HashSet(); } - 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); } 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 a1a12bef394a8..566f9f6b2e7d1 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.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 @@ private void transferMultipartParameters(Object[] paramArray, String[] multipart } 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; 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 c82050abf7b4d..a700832983007 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 void testPopulateCxfRequestFromExchange() { 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 void testPopulateCxfRequestFromExchange() { 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 void testPopupalteExchangeFromCxfResponse() { cxfExchange.setInMessage(cxfMessage); Set attachments = new HashSet(); - 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 void testPopupalteExchangeFromCxfResponse() { assertNotNull(camelHeaders); assertEquals(responseContext, camelHeaders.get(Client.RESPONSE_CONTEXT)); - Map camelAttachments = exchange.getOut().getAttachments(); + Map 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 void testPopupalteCxfResponseFromExchange() { 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 void testPopupalteCxfResponseFromExchange() { 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 void testPopupalteExchangeFromCxfRequest() { cxfMessage.put(org.apache.cxf.message.Message.PROTOCOL_HEADERS, headers); Set attachments = new HashSet(); - 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 void testPopupalteExchangeFromCxfRequest() { assertEquals("241", camelHeaders.get("content-length")); assertEquals("peach", camelHeaders.get("MyFruitHeader")); assertEquals(Arrays.asList("cappuccino", "espresso"), camelHeaders.get("MyBrewHeader")); - - Map camelAttachments = exchange.getIn().getAttachments(); + + Map camelAttachments = exchange.getIn().getAttachmentObjects(); assertNotNull(camelAttachments); assertNotNull(camelAttachments.get("att-1")); - + assertEquals("value 1", camelAttachments.get("att-1").getHeader("attachment-header")); } @Test 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 7e2dd441faa74..0cf02ac8961b7 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 void copyFrom(org.apache.camel.Message that) { getAttachments().clear(); if (that.hasAttachments()) { - getAttachments().putAll(that.getAttachments()); + getAttachmentObjects().putAll(that.getAttachmentObjects()); } } 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 1b7bca1bb6239..293dd70937f24 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.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 @@ protected void populateAttachments(HttpServletRequest request, HttpMessage messa 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); 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 1221cc9de17cb..fb02542b8c2e5 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 void process(Exchange exchange) throws Exception { 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); 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 fc307fb098ed4..0408ff74195dc 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 void copyFrom(org.apache.camel.Message that) { getAttachments().clear(); if (that.hasAttachments()) { - getAttachments().putAll(that.getAttachments()); + getAttachmentObjects().putAll(that.getAttachmentObjects()); } } 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 79f4066ed459d..0596d61895528 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.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 Object extractBodyFromMail(Exchange exchange, MailMessage mailMessage) { * @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 map) + public void extractAttachmentsFromMail(Message message, Map map) throws MessagingException, IOException { LOG.trace("Extracting attachments +++ start +++"); @@ -298,7 +300,7 @@ public void extractAttachmentsFromMail(Message message, Map LOG.trace("Extracting attachments +++ done +++"); } - protected void extractAttachmentsFromMultipart(Multipart mp, Map map) + protected void extractAttachmentsFromMultipart(Multipart mp, Map map) throws MessagingException, IOException { for (int i = 0; i < mp.getCount(); i++) { @@ -326,7 +328,14 @@ protected void extractAttachmentsFromMultipart(Multipart mp, Map 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 @@ protected void addAttachmentsToMultipart(MimeMultipart multipart, String partDis AttachmentsContentTransferEncodingResolver encodingResolver, Exchange exchange) throws MessagingException { LOG.trace("Adding attachments +++ start +++"); int i = 0; - for (Map.Entry entry : exchange.getIn().getAttachments().entrySet()) { + for (Map.Entry 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 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 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 949b0aadc6bf2..5e0615bdd534d 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.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 @@ protected void populateInitialHeaders(Map map) { } @Override - protected void populateInitialAttachments(Map map) { + protected void populateInitialAttachments(Map map) { if (mailMessage != null) { try { MailBinding binding = ExchangeHelper.getBinding(getExchange(), MailBinding.class); 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 49b7cd098b852..dc4084e56e360 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 @@ import java.text.DateFormat; import java.util.Date; + import javax.mail.Address; import javax.mail.Message; import javax.mail.MessagingException; 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 708428ea3c673..ca5aae54b055b 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.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 Object evaluate(Exchange exchange) { try { List answer = new ArrayList(); Message inMessage = exchange.getIn(); - for (Map.Entry entry : inMessage.getAttachments().entrySet()) { + for (Map.Entry entry : inMessage.getAttachmentObjects().entrySet()) { Message attachmentMessage; if (extractAttachments) { attachmentMessage = extractAttachment(inMessage, entry.getKey()); @@ -97,9 +97,9 @@ public Object evaluate(Exchange exchange) { } } - private Message splitAttachment(Message inMessage, String attachmentName, DataHandler attachmentHandler) { + private Message splitAttachment(Message inMessage, String attachmentName, Attachment attachmentHandler) { final Message copy = inMessage.copy(); - Map attachments = copy.getAttachments(); + Map attachments = copy.getAttachmentObjects(); attachments.clear(); attachments.put(attachmentName, attachmentHandler); copy.setHeader(HEADER_NAME, attachmentName); 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 86e5f3534bf23..0af87fbb140ff 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.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 void marshal(Exchange exchange, Object graph, OutputStream stream) BodyPart part = new MimeBodyPart(); writeBodyPart(bodyContent, part, contentType); mp.addBodyPart(part); - for (Map.Entry entry : exchange.getIn().getAttachments().entrySet()) { + for (Map.Entry 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 values = attachment.getHeaderAsList(headerName); + for (String value : values) { + part.setHeader(headerName, value); + } + } mp.addBodyPart(part); exchange.getOut().removeAttachment(attachmentFilename); } @@ -238,7 +247,14 @@ public Object unmarshal(Exchange exchange, InputStream stream) throws IOExceptio 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
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) { 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 e9ae03577969f..fce729ee11059 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 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 void testSendAndReceiveMailWithAttachments() throws Exception { 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 void testSendAndReceiveMailWithAttachments() throws Exception { assertEquals("Hello World", out.getIn().getBody(String.class)); // attachment - Map attachments = out.getIn().getAttachments(); + Map 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 void testSendAndReceiveMailWithAttachments() throws Exception { assertEquals("Handler name should be the file name", "logo.jpeg", handler.getName()); + assertEquals("some sample content", attachment.getHeader("content-description")); + producer.stop(); } 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 7759c490367ae..ada79c017fcbe 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.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 void roundtripWithTextAttachments() throws IOException { 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 headers = new HashMap(); + 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 void roundtripWithTextAttachments() throws IOException { 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 void roundtripWithoutAttachmentsAndInvalidContentType() throws IOExceptio public void marhsalOnlyMixed() throws IOException { in.setBody("Body text"); in.setHeader("Content-Type", "text/plain"); - addAttachment("application/octet-stream", "foobar", "attachment.bin"); + Map headers = new HashMap(); + 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 void marhsalUnmarshalInlineHeaders() throws IOException { @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 void unmarshalInlineHeadersNonMimeBodyStream() throws UnsupportedEncoding 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 @@ private void unmarshalAndCheckAttachmentName(String matcher) throws IOException, 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 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 diff --git a/components/camel-mail/src/test/resources/multipart-related.txt b/components/camel-mail/src/test/resources/multipart-related.txt index 71b9e1c2b0383..1455c533b367f 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: <950120.aaCC@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: <950120.aaCB@XIson.com> 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 cb0191200dc36..2a35f6210ec36 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 @@ private void processResponse(Exchange exchange, Object body, SalesforceException // 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); 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 f83ad9d843bb3..b1be0e4f35259 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 @@ private void processResponse(Exchange exchange, Object body, SalesforceException // 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); 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 1e8f948593028..4005dc43d7441 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 @@ protected void processResponse(Exchange exchange, InputStream responseEntity, Sa } // 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)); 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 3f8756f57b343..4979197a2767e 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 @@ protected void processResponse(Exchange exchange, InputStream responseEntity, } // 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)); 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 bc5cec03e8de6..627bb7ca55285 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) 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 c067b92621f1d..2597d39780e47 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 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 084e1a33b2539..d84a27181fe22 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.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 @@ protected void populateAttachments(HttpServletRequest request, HttpMessage messa Collection 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); 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 92f853196b57a..907985eb00bc1 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 void copyFrom(org.apache.camel.Message that) { getAttachments().clear(); if (that.hasAttachments()) { - getAttachments().putAll(that.getAttachments()); + getAttachmentObjects().putAll(that.getAttachmentObjects()); } }