Repository: camel Updated Branches: refs/heads/master a302c732e -> 41277fbdd
CAMEL-8415: DefaultExchangeHolder - Only transfer primitive headers/properties Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/41277fbd Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/41277fbd Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/41277fbd Branch: refs/heads/master Commit: 41277fbdd08644c2c2282741bc12389f30548c33 Parents: a302c73 Author: Claus Ibsen <[email protected]> Authored: Mon Sep 7 13:10:21 2015 +0200 Committer: Claus Ibsen <[email protected]> Committed: Mon Sep 7 13:59:49 2015 +0200 ---------------------------------------------------------------------- .../camel/impl/DefaultExchangeHolder.java | 109 +++++++++++-------- 1 file changed, 64 insertions(+), 45 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/41277fbd/camel-core/src/main/java/org/apache/camel/impl/DefaultExchangeHolder.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/impl/DefaultExchangeHolder.java b/camel-core/src/main/java/org/apache/camel/impl/DefaultExchangeHolder.java index e6a277b..0605649 100644 --- a/camel-core/src/main/java/org/apache/camel/impl/DefaultExchangeHolder.java +++ b/camel-core/src/main/java/org/apache/camel/impl/DefaultExchangeHolder.java @@ -18,7 +18,9 @@ package org.apache.camel.impl; import java.io.File; import java.io.Serializable; -import java.util.Collection; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.Date; import java.util.LinkedHashMap; import java.util.Map; @@ -49,6 +51,9 @@ import org.slf4j.LoggerFactory; * <li>exchange properties</li> * <li>exception</li> * </ul> + * The body is serialized and stored as serialized bytes. The header and exchange properties only include + * primitive, and String types. Any other type is skipped. + * <p/> * Any object that is not serializable will be skipped and Camel will log this at WARN level. * * @version @@ -179,7 +184,7 @@ public class DefaultExchangeHolder implements Serializable { private Map<String, Object> safeSetInHeaders(Exchange exchange) { if (exchange.getIn().hasHeaders()) { - Map<String, Object> map = checkMapSerializableObjects("in headers", exchange, exchange.getIn().getHeaders()); + Map<String, Object> map = checkValidMapObjects("in headers", exchange, exchange.getIn().getHeaders()); if (map != null && !map.isEmpty()) { inHeaders = new LinkedHashMap<String, Object>(map); } @@ -189,7 +194,7 @@ public class DefaultExchangeHolder implements Serializable { private Map<String, Object> safeSetOutHeaders(Exchange exchange) { if (exchange.hasOut() && exchange.getOut().hasHeaders()) { - Map<String, Object> map = checkMapSerializableObjects("out headers", exchange, exchange.getOut().getHeaders()); + Map<String, Object> map = checkValidMapObjects("out headers", exchange, exchange.getOut().getHeaders()); if (map != null && !map.isEmpty()) { outHeaders = new LinkedHashMap<String, Object>(map); } @@ -199,7 +204,7 @@ public class DefaultExchangeHolder implements Serializable { private Map<String, Object> safeSetProperties(Exchange exchange) { if (exchange.hasProperties()) { - Map<String, Object> map = checkMapSerializableObjects("properties", exchange, exchange.getProperties()); + Map<String, Object> map = checkValidMapObjects("properties", exchange, exchange.getProperties()); if (map != null && !map.isEmpty()) { properties = new LinkedHashMap<String, Object>(map); } @@ -221,7 +226,7 @@ public class DefaultExchangeHolder implements Serializable { } } - private static Map<String, Object> checkMapSerializableObjects(String type, Exchange exchange, Map<String, Object> map) { + private static Map<String, Object> checkValidMapObjects(String type, Exchange exchange, Map<String, Object> map) { if (map == null) { return null; } @@ -230,71 +235,85 @@ public class DefaultExchangeHolder implements Serializable { for (Map.Entry<String, Object> entry : map.entrySet()) { // silently skip any values which is null - if (entry.getValue() != null) { - Serializable converted = exchange.getContext().getTypeConverter().convertTo(Serializable.class, exchange, entry.getValue()); - - // if the converter is a map/collection we need to check its content as well - if (converted instanceof Collection) { - Collection<?> valueCol = (Collection<?>) converted; - if (!collectionContainsAllSerializableObjects(valueCol, exchange)) { - logCannotSerializeObject(type, entry.getKey(), entry.getValue()); - continue; - } - } else if (converted instanceof Map) { - Map<?, ?> valueMap = (Map<?, ?>) converted; - if (!mapContainsAllSerializableObjects(valueMap, exchange)) { - logCannotSerializeObject(type, entry.getKey(), entry.getValue()); - continue; - } - } - + Object value = getValidHeaderValue(entry.getKey(), entry.getValue()); + if (value != null) { + Serializable converted = exchange.getContext().getTypeConverter().convertTo(Serializable.class, exchange, value); if (converted != null) { result.put(entry.getKey(), converted); } else { logCannotSerializeObject(type, entry.getKey(), entry.getValue()); } + } else { + logInvalidHeaderValue(type, entry.getKey(), entry.getValue()); } } return result; } + /** + * We only want to store header values of primitive and String related types. + * <p/> + * This default implementation will allow: + * <ul> + * <li>any primitives and their counter Objects (Integer, Double etc.)</li> + * <li>String and any other literals, Character, CharSequence</li> + * <li>Boolean</li> + * <li>Number</li> + * <li>java.util.Date</li> + * </ul> + * + * @param headerName the header name + * @param headerValue the header value + * @return the value to use, <tt>null</tt> to ignore this header + */ + protected static Object getValidHeaderValue(String headerName, Object headerValue) { + if (headerValue instanceof String) { + return headerValue; + } else if (headerValue instanceof BigInteger) { + return headerValue; + } else if (headerValue instanceof BigDecimal) { + return headerValue; + } else if (headerValue instanceof Number) { + return headerValue; + } else if (headerValue instanceof Character) { + return headerValue; + } else if (headerValue instanceof CharSequence) { + return headerValue.toString(); + } else if (headerValue instanceof Boolean) { + return headerValue; + } else if (headerValue instanceof Date) { + return headerValue; + } + return null; + } + private static void logCannotSerializeObject(String type, String key, Object value) { if (key.startsWith("Camel")) { // log Camel at DEBUG level if (LOG.isDebugEnabled()) { LOG.debug("Exchange {} containing key: {} with object: {} of type: {} cannot be serialized, it will be excluded by the holder." - , new Object[]{type, key, value, ObjectHelper.classCanonicalName(value)}); + , new Object[]{type, key, value, ObjectHelper.classCanonicalName(value)}); } } else { // log regular at WARN level LOG.warn("Exchange {} containing key: {} with object: {} of type: {} cannot be serialized, it will be excluded by the holder." - , new Object[]{type, key, value, ObjectHelper.classCanonicalName(value)}); + , new Object[]{type, key, value, ObjectHelper.classCanonicalName(value)}); } } - private static boolean collectionContainsAllSerializableObjects(Collection<?> col, Exchange exchange) { - for (Object value : col) { - if (value != null) { - Serializable converted = exchange.getContext().getTypeConverter().convertTo(Serializable.class, exchange, value); - if (converted == null) { - return false; - } - } - } - return true; - } - - private static boolean mapContainsAllSerializableObjects(Map<?, ?> map, Exchange exchange) { - for (Object value : map.values()) { - if (value != null) { - Serializable converted = exchange.getContext().getTypeConverter().convertTo(Serializable.class, exchange, value); - if (converted == null) { - return false; - } + private static void logInvalidHeaderValue(String type, String key, Object value) { + if (key.startsWith("Camel")) { + // log Camel at DEBUG level + if (LOG.isDebugEnabled()) { + LOG.debug("Exchange {} containing key: {} with object: {} of type: {} is not valid header type, it will be excluded by the holder." + , new Object[]{type, key, value, ObjectHelper.classCanonicalName(value)}); } + } else { + // log regular at WARN level + LOG.warn("Exchange {} containing key: {} with object: {} of type: {} is not valid header type, it will be excluded by the holder." + , new Object[]{type, key, value, ObjectHelper.classCanonicalName(value)}); } - return true; } }
