Repository: camel Updated Branches: refs/heads/master 42b908741 -> 583bec8fb
CAMEL-10446 - Need to consolidate header mapping logic between Camel and CXF messages Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/583bec8f Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/583bec8f Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/583bec8f Branch: refs/heads/master Commit: 583bec8fb6d5595170d6ab36981d4acdcb9de4c2 Parents: 42b9087 Author: Tadayoshi Sato <sato.tadayo...@gmail.com> Authored: Mon Nov 7 22:15:20 2016 +0900 Committer: Claus Ibsen <davscl...@apache.org> Committed: Mon Nov 7 20:12:06 2016 +0100 ---------------------------------------------------------------------- .../cxf/common/header/CxfHeaderHelper.java | 274 +++++++++++++------ .../cxf/common/header/CxfHeaderHelperTest.java | 92 ++++--- .../cxf/jaxrs/DefaultCxfRsBinding.java | 97 +------ 3 files changed, 253 insertions(+), 210 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/583bec8f/components/camel-cxf-transport/src/main/java/org/apache/camel/component/cxf/common/header/CxfHeaderHelper.java ---------------------------------------------------------------------- diff --git a/components/camel-cxf-transport/src/main/java/org/apache/camel/component/cxf/common/header/CxfHeaderHelper.java b/components/camel-cxf-transport/src/main/java/org/apache/camel/component/cxf/common/header/CxfHeaderHelper.java index a72e2a8..2c8ba59 100644 --- a/components/camel-cxf-transport/src/main/java/org/apache/camel/component/cxf/common/header/CxfHeaderHelper.java +++ b/components/camel-cxf-transport/src/main/java/org/apache/camel/component/cxf/common/header/CxfHeaderHelper.java @@ -17,7 +17,9 @@ package org.apache.camel.component.cxf.common.header; import java.util.ArrayList; -import java.util.Iterator; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.TreeMap; @@ -28,6 +30,8 @@ import org.apache.camel.spi.HeaderFilterStrategy; import org.apache.cxf.endpoint.Client; import org.apache.cxf.helpers.CastUtils; import org.apache.cxf.message.Message; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Utility class to propagate headers to and from CXF message. @@ -35,6 +39,22 @@ import org.apache.cxf.message.Message; * @version */ public final class CxfHeaderHelper { + private static final Logger LOG = LoggerFactory.getLogger(CxfHeaderHelper.class); + + private static final Map<String, String> CAMEL_TO_CXF_HEADERS = new HashMap<>(); + private static final Map<String, String> CXF_TO_CAMEL_HEADERS = new HashMap<>(); + + static { + // initialize mappings between Camel and CXF header names + defineMapping(Exchange.HTTP_URI, Message.REQUEST_URI); + defineMapping(Exchange.HTTP_METHOD, Message.HTTP_REQUEST_METHOD); + defineMapping(Exchange.HTTP_PATH, Message.PATH_INFO); + defineMapping(Exchange.CONTENT_TYPE, Message.CONTENT_TYPE); + defineMapping(Exchange.HTTP_CHARACTER_ENCODING, Message.ENCODING); + defineMapping(Exchange.HTTP_QUERY, Message.QUERY_STRING); + defineMapping(Exchange.ACCEPT_CONTENT_TYPE, Message.ACCEPT_CONTENT_TYPE); + defineMapping(Exchange.HTTP_RESPONSE_CODE, Message.RESPONSE_CODE); + } /** * Utility class does not have public constructor @@ -42,50 +62,130 @@ public final class CxfHeaderHelper { private CxfHeaderHelper() { } + private static void defineMapping(String camelHeader, String cxfHeader) { + CAMEL_TO_CXF_HEADERS.put(camelHeader, cxfHeader); + CXF_TO_CAMEL_HEADERS.put(cxfHeader, camelHeader); + } + + /** + * Propagates Camel headers to CXF headers. + * + * @param strategy header filter strategy + * @param camelHeaders Camel headers + * @param requestHeaders CXF request headers + * @param camelExchange provides context for filtering + */ + public static void propagateCamelHeadersToCxfHeaders(HeaderFilterStrategy strategy, + Map<String, Object> camelHeaders, Map<String, List<String>> requestHeaders, + Exchange camelExchange) throws Exception { + if (strategy == null) { + return; + } + camelHeaders.entrySet().forEach(entry -> { + // Need to make sure the cxf needed header will not be filtered + if (strategy.applyFilterToCamelHeaders(entry.getKey(), entry.getValue(), camelExchange) + && CAMEL_TO_CXF_HEADERS.get(entry.getKey()) == null) { + LOG.trace("Drop Camel header: {}={}", entry.getKey(), entry.getValue()); + return; + } + + // we need to make sure the entry value is not null + if (entry.getValue() == null) { + LOG.trace("Drop Camel header: {}={}", entry.getKey(), entry.getValue()); + return; + } + + String cxfHeaderName = CAMEL_TO_CXF_HEADERS.getOrDefault(entry.getKey(), entry.getKey()); + + LOG.trace("Propagate Camel header: {}={} as {}", entry.getKey(), entry.getValue(), cxfHeaderName); + + requestHeaders.put(cxfHeaderName, Arrays.asList(entry.getValue().toString())); + }); + } + /** * Propagates Camel headers to CXF message. * * @param strategy header filter strategy - * @param headers Camel header - * @param message CXF message + * @param camelHeaders Camel header + * @param cxfMessage CXF message * @param exchange provides context for filtering */ public static void propagateCamelToCxf(HeaderFilterStrategy strategy, - Map<String, Object> headers, Message message, Exchange exchange) { + Map<String, Object> camelHeaders, Message cxfMessage, Exchange exchange) { - Map<String, List<String>> cxfHeaders = - CastUtils.cast((Map<?, ?>)message.get(Message.PROTOCOL_HEADERS)); + // use copyProtocolHeadersFromCxfToCamel treemap to keep ordering and ignore key case + cxfMessage.putIfAbsent(Message.PROTOCOL_HEADERS, new TreeMap<>(String.CASE_INSENSITIVE_ORDER)); + final Map<String, List<String>> cxfHeaders = + CastUtils.cast((Map<?, ?>) cxfMessage.get(Message.PROTOCOL_HEADERS)); - if (cxfHeaders == null) { - // use a treemap to keep ordering and ignore key case - cxfHeaders = new TreeMap<String, List<String>>(String.CASE_INSENSITIVE_ORDER); - message.put(Message.PROTOCOL_HEADERS, cxfHeaders); + if (strategy == null) { + return; } - for (Map.Entry<String, Object> entry : headers.entrySet()) { - if (strategy != null - && !strategy.applyFilterToCamelHeaders(entry.getKey(), entry.getValue(), exchange)) { + camelHeaders.entrySet().forEach(entry -> { + // Need to make sure the cxf needed header will not be filtered + if (strategy.applyFilterToCamelHeaders(entry.getKey(), entry.getValue(), exchange)) { + LOG.trace("Drop external header: {}={}", entry.getKey(), entry.getValue()); + return; + } - if (Exchange.CONTENT_TYPE.equals(entry.getKey())) { - message.put(Message.CONTENT_TYPE, entry.getValue()); - } - if (Client.REQUEST_CONTEXT.equals(entry.getKey()) - || Client.RESPONSE_CONTEXT.equals(entry.getKey())) { - message.put(entry.getKey(), entry.getValue()); - } else if (Exchange.HTTP_RESPONSE_CODE.equals(entry.getKey())) { - message.put(Message.RESPONSE_CODE, entry.getValue()); + // we need to make sure the entry value is not null + if (entry.getValue() == null) { + LOG.trace("Drop Camel header: {}={}", entry.getKey(), entry.getValue()); + return; + } + + String cxfHeaderName = CAMEL_TO_CXF_HEADERS.getOrDefault(entry.getKey(), entry.getKey()); + + LOG.trace("Propagate Camel header: {}={} as {}", entry.getKey(), entry.getValue(), cxfHeaderName); + + if (Exchange.CONTENT_TYPE.equals(entry.getKey())) { + cxfMessage.put(cxfHeaderName, entry.getValue()); + } + if (Exchange.HTTP_RESPONSE_CODE.equals(entry.getKey()) + || Client.REQUEST_CONTEXT.equals(entry.getKey()) + || Client.RESPONSE_CONTEXT.equals(entry.getKey())) { + cxfMessage.put(cxfHeaderName, entry.getValue()); + } else { + Object values = entry.getValue(); + if (values instanceof List<?>) { + cxfHeaders.put(cxfHeaderName, CastUtils.cast((List<?>) values, String.class)); } else { - Object values = entry.getValue(); - if (values instanceof List<?>) { - cxfHeaders.put(entry.getKey(), CastUtils.cast((List<?>)values, String.class)); - } else { - List<String> listValue = new ArrayList<String>(); - listValue.add(entry.getValue().toString()); - cxfHeaders.put(entry.getKey(), listValue); - } + List<String> listValue = new ArrayList<>(); + listValue.add(entry.getValue().toString()); + cxfHeaders.put(cxfHeaderName, listValue); } } + }); + } + + /** + * Propagates CXF headers to Camel headers. + * + * @param strategy header filter strategy + * @param responseHeaders CXF response headers + * @param camelHeaders Camel headers + * @param camelExchange provides context for filtering + */ + public static void propagateCxfHeadersToCamelHeaders(HeaderFilterStrategy strategy, + Map<String, List<Object>> responseHeaders, Map<String, Object> camelHeaders, + Exchange camelExchange) throws Exception { + if (strategy == null) { + return; } + responseHeaders.entrySet().forEach(entry -> { + if (strategy.applyFilterToExternalHeaders(entry.getKey(), entry.getValue(), camelExchange)) { + LOG.trace("Drop external header: {}={}", entry.getKey(), entry.getValue()); + return; + } + + String camelHeaderName = CXF_TO_CAMEL_HEADERS.getOrDefault(entry.getKey(), entry.getKey()); + + LOG.trace("Populate external header: {}={} as {}", entry.getKey(), entry.getValue(), camelHeaderName); + + camelHeaders.put(camelHeaderName, entry.getValue().get(0)); + }); } /** @@ -103,79 +203,64 @@ public final class CxfHeaderHelper { return; } + // Copy the CXF protocol headers to the camel headers + copyProtocolHeadersFromCxfToCamel(strategy, exchange, cxfMessage, camelMessage); + // Copy the CXF HTTP headers to the camel headers copyHttpHeadersFromCxfToCamel(strategy, cxfMessage, camelMessage, exchange); - // Copy the CXF protocol headers to the camel headers - Map<String, List<String>> cxfHeaders = - CastUtils.cast((Map<?, ?>) cxfMessage.get(Message.PROTOCOL_HEADERS)); - if (cxfHeaders != null) { - for (Map.Entry<String, List<String>> entry : cxfHeaders.entrySet()) { - if (!strategy.applyFilterToExternalHeaders(entry.getKey(), entry.getValue(), exchange)) { - List<String> values = entry.getValue(); - camelMessage.setHeader(entry.getKey(), protocolHeaderValuesToSingleValue(values, exchange)); - } - } - } - // propagate request context - copyMessageHeader(strategy, exchange, cxfMessage, camelMessage, Client.REQUEST_CONTEXT); + copyCxfHeaderToCamel(strategy, exchange, cxfMessage, camelMessage, Client.REQUEST_CONTEXT); // propagate response context - copyMessageHeader(strategy, exchange, cxfMessage, camelMessage, Client.RESPONSE_CONTEXT); - - // propagate response code - copyMessageHeader(strategy, exchange, cxfMessage, camelMessage, Message.RESPONSE_CODE, Exchange.HTTP_RESPONSE_CODE); + copyCxfHeaderToCamel(strategy, exchange, cxfMessage, camelMessage, Client.RESPONSE_CONTEXT); + } + + private static void copyProtocolHeadersFromCxfToCamel(HeaderFilterStrategy strategy, Exchange exchange, + Message cxfMessage, org.apache.camel.Message camelMessage) { + Map<String, List<String>> cxfHeaders = + CastUtils.cast((Map<?, ?>) cxfMessage.getOrDefault(Message.PROTOCOL_HEADERS, Collections.emptyMap())); + cxfHeaders.entrySet().forEach(cxfHeader -> { + String camelHeaderName = CXF_TO_CAMEL_HEADERS.getOrDefault(cxfHeader.getKey(), cxfHeader.getKey()); + Object value = convertCxfProtocolHeaderValues(cxfHeader.getValue(), exchange); + copyCxfHeaderToCamel(strategy, exchange, cxfMessage, camelMessage, cxfHeader.getKey(), camelHeaderName, value); + }); } - private static Object protocolHeaderValuesToSingleValue(List<String> values, Exchange exchange) { - if (values.size() < 2) { + private static Object convertCxfProtocolHeaderValues(List<String> values, Exchange exchange) { + if (values.size() == 1) { return values.get(0); } - if (!exchange.getProperty(CxfConstants.CAMEL_CXF_PROTOCOL_HEADERS_MERGED, Boolean.FALSE, Boolean.class)) { - return values; - } - StringBuilder sb = new StringBuilder(); - Iterator<String> it = values.iterator(); - while (it.hasNext()) { - sb.append(it.next()); - if (it.hasNext()) { - sb.append(',').append(' '); - } + if (exchange.getProperty(CxfConstants.CAMEL_CXF_PROTOCOL_HEADERS_MERGED, Boolean.FALSE, Boolean.class)) { + return String.join(", ", values); } - return sb.toString(); + return values; } public static void copyHttpHeadersFromCxfToCamel(HeaderFilterStrategy strategy, Message cxfMessage, org.apache.camel.Message camelMessage, Exchange exchange) { - copyMessageHeader(strategy, exchange, cxfMessage, camelMessage, Message.REQUEST_URI, Exchange.HTTP_URI); - copyMessageHeader(strategy, exchange, cxfMessage, camelMessage, Message.HTTP_REQUEST_METHOD, Exchange.HTTP_METHOD); - - // We need remove the BASE_PATH from the PATH_INFO - String pathInfo = (String) cxfMessage.get(Message.PATH_INFO); - String basePath = (String) cxfMessage.get(Message.BASE_PATH); - if (pathInfo != null && basePath != null && pathInfo.startsWith(basePath)) { - pathInfo = pathInfo.substring(basePath.length()); - } - if (pathInfo != null) { - camelMessage.setHeader(Exchange.HTTP_PATH, pathInfo); - } - - copyMessageHeader(strategy, exchange, cxfMessage, camelMessage, Message.CONTENT_TYPE, Exchange.CONTENT_TYPE); - copyMessageHeader(strategy, exchange, cxfMessage, camelMessage, Message.ENCODING, Exchange.HTTP_CHARACTER_ENCODING); - copyMessageHeader(strategy, exchange, cxfMessage, camelMessage, Message.QUERY_STRING, Exchange.HTTP_QUERY); - copyMessageHeader(strategy, exchange, cxfMessage, camelMessage, Message.ACCEPT_CONTENT_TYPE, Exchange.ACCEPT_CONTENT_TYPE); + CXF_TO_CAMEL_HEADERS.entrySet().forEach(entry -> + copyCxfHeaderToCamel(strategy, exchange, cxfMessage, camelMessage, entry.getKey(), entry.getValue())); } - private static void copyMessageHeader(HeaderFilterStrategy strategy, Exchange exchange, + private static void copyCxfHeaderToCamel(HeaderFilterStrategy strategy, Exchange exchange, Message cxfMessage, org.apache.camel.Message camelMessage, String key) { - copyMessageHeader(strategy, exchange, cxfMessage, camelMessage, key, key); + copyCxfHeaderToCamel(strategy, exchange, cxfMessage, camelMessage, key, key); } - private static void copyMessageHeader(HeaderFilterStrategy strategy, Exchange exchange, + private static void copyCxfHeaderToCamel(HeaderFilterStrategy strategy, Exchange exchange, Message cxfMessage, org.apache.camel.Message camelMessage, String cxfKey, String camelKey) { - Object value = cxfMessage.get(cxfKey); - if (Message.CONTENT_TYPE.equals(cxfKey)) { + copyCxfHeaderToCamel(strategy, exchange, cxfMessage, camelMessage, cxfKey, camelKey, cxfMessage.get(cxfKey)); + } + + private static void copyCxfHeaderToCamel(HeaderFilterStrategy strategy, Exchange exchange, + Message cxfMessage, org.apache.camel.Message camelMessage, String cxfKey, String camelKey, + Object initialValue) { + Object value = initialValue; + if (Message.PATH_INFO.equals(cxfKey)) { + // We need remove the BASE_PATH from the PATH_INFO + value = convertPathInfo(cxfMessage); + } else if (Message.CONTENT_TYPE.equals(cxfKey)) { // propagate content type with the encoding information // We need to do it as the CXF does this kind of thing in transport level value = determineContentType(cxfMessage); @@ -184,14 +269,23 @@ public final class CxfHeaderHelper { camelMessage.setHeader(camelKey, value); } } - + + private static String convertPathInfo(Message message) { + String pathInfo = findHeaderValue(message, Message.PATH_INFO); + String basePath = findHeaderValue(message, Message.BASE_PATH); + if (pathInfo != null && basePath != null && pathInfo.startsWith(basePath)) { + return pathInfo.substring(basePath.length()); + } + return pathInfo; + } + private static String determineContentType(Message message) { - String ct = (String)message.get(Message.CONTENT_TYPE); - String enc = (String)message.get(Message.ENCODING); + String ct = findHeaderValue(message, Message.CONTENT_TYPE); + String enc = findHeaderValue(message, Message.ENCODING); if (null != ct) { if (enc != null - && ct.indexOf("charset=") == -1 + && !ct.contains("charset=") && !ct.toLowerCase().contains("multipart/related")) { ct = ct + "; charset=" + enc; } @@ -205,4 +299,14 @@ public final class CxfHeaderHelper { return ct; } + private static String findHeaderValue(Message message, String key) { + String value = (String) message.get(key); + if (value != null) { + return value; + } + Map<String, List<String>> protocolHeaders = + CastUtils.cast((Map<?, ?>) message.getOrDefault(Message.PROTOCOL_HEADERS, Collections.emptyMap())); + return protocolHeaders.getOrDefault(key, Collections.singletonList(null)).get(0); + } + } http://git-wip-us.apache.org/repos/asf/camel/blob/583bec8f/components/camel-cxf-transport/src/test/java/org/apache/camel/component/cxf/common/header/CxfHeaderHelperTest.java ---------------------------------------------------------------------- diff --git a/components/camel-cxf-transport/src/test/java/org/apache/camel/component/cxf/common/header/CxfHeaderHelperTest.java b/components/camel-cxf-transport/src/test/java/org/apache/camel/component/cxf/common/header/CxfHeaderHelperTest.java index 9d80955..81f4d6d 100755 --- a/components/camel-cxf-transport/src/test/java/org/apache/camel/component/cxf/common/header/CxfHeaderHelperTest.java +++ b/components/camel-cxf-transport/src/test/java/org/apache/camel/component/cxf/common/header/CxfHeaderHelperTest.java @@ -27,18 +27,12 @@ import org.apache.camel.component.cxf.common.message.CxfConstants; import org.apache.camel.impl.DefaultCamelContext; import org.apache.camel.impl.DefaultExchange; import org.apache.camel.impl.DefaultHeaderFilterStrategy; -import org.apache.camel.spi.HeaderFilterStrategy; +import org.apache.cxf.endpoint.Client; import org.apache.cxf.helpers.CastUtils; import org.apache.cxf.message.Message; -import org.apache.cxf.message.MessageImpl; -import org.easymock.EasyMock; import org.junit.Assert; import org.junit.Test; - -/** - * - */ public class CxfHeaderHelperTest extends Assert { private DefaultCamelContext context = new DefaultCamelContext(); @@ -49,17 +43,32 @@ public class CxfHeaderHelperTest extends Assert { exchange.getIn().setHeader("soapAction", "urn:hello:world"); exchange.getIn().setHeader("MyFruitHeader", "peach"); exchange.getIn().setHeader("MyBrewHeader", Arrays.asList("cappuccino", "espresso")); + exchange.getIn().setHeader(Exchange.CONTENT_TYPE, "text/xml"); exchange.getIn().setHeader(Exchange.HTTP_RESPONSE_CODE, "200"); + exchange.getIn().setHeader(Exchange.HTTP_URI, "/hello/cxf"); + exchange.getIn().setHeader(Exchange.HTTP_METHOD, "GET"); + exchange.getIn().setHeader(Exchange.HTTP_PATH, "/hello/cxf"); + Map<String, Object> requestContext = Collections.singletonMap("request", "true"); + Map<String, Object> responseContext = Collections.singletonMap("response", "true"); + exchange.getIn().setHeader(Client.REQUEST_CONTEXT, requestContext); + exchange.getIn().setHeader(Client.RESPONSE_CONTEXT, responseContext); org.apache.cxf.message.Message cxfMessage = new org.apache.cxf.message.MessageImpl(); CxfHeaderHelper.propagateCamelToCxf(new DefaultHeaderFilterStrategy(), exchange.getIn().getHeaders(), cxfMessage, exchange); + + assertEquals("text/xml", cxfMessage.get(Message.CONTENT_TYPE)); + assertEquals("200", cxfMessage.get(Message.RESPONSE_CODE)); + assertEquals(requestContext, cxfMessage.get(Client.REQUEST_CONTEXT)); + assertEquals(responseContext, cxfMessage.get(Client.RESPONSE_CONTEXT)); + + assertNull(cxfMessage.get(Exchange.HTTP_RESPONSE_CODE)); // check the protocol headers Map<String, List<String>> cxfHeaders = CastUtils.cast((Map<?, ?>)cxfMessage.get(org.apache.cxf.message.Message.PROTOCOL_HEADERS)); assertNotNull(cxfHeaders); - assertTrue(cxfHeaders.size() == 3); + assertTrue(cxfHeaders.size() == 7); verifyHeader(cxfHeaders, "soapaction", "urn:hello:world"); verifyHeader(cxfHeaders, "SoapAction", "urn:hello:world"); @@ -68,20 +77,40 @@ public class CxfHeaderHelperTest extends Assert { verifyHeader(cxfHeaders, "myFruitHeader", "peach"); verifyHeader(cxfHeaders, "MYFRUITHEADER", "peach"); verifyHeader(cxfHeaders, "MyBrewHeader", Arrays.asList("cappuccino", "espresso")); - assertEquals("200", cxfMessage.get(Message.RESPONSE_CODE)); - } + verifyHeader(cxfHeaders, Message.CONTENT_TYPE, "text/xml"); + verifyHeader(cxfHeaders, Message.REQUEST_URI, "/hello/cxf"); + verifyHeader(cxfHeaders, Message.HTTP_REQUEST_METHOD, "GET"); + verifyHeader(cxfHeaders, Message.PATH_INFO, "/hello/cxf"); + + assertNull(cxfHeaders.get(Exchange.HTTP_RESPONSE_CODE)); + assertNull(cxfHeaders.get(Exchange.HTTP_URI)); + assertNull(cxfHeaders.get(Exchange.HTTP_METHOD)); + assertNull(cxfHeaders.get(Exchange.HTTP_PATH)); + } @Test public void testPropagateCxfToCamel() { Exchange exchange = new DefaultExchange(context); org.apache.cxf.message.Message cxfMessage = new org.apache.cxf.message.MessageImpl(); - Map<String, List<String>> cxfHeaders = new TreeMap<String, List<String>>(String.CASE_INSENSITIVE_ORDER); + Map<String, List<String>> cxfHeaders = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); cxfHeaders.put("Content-Length", Arrays.asList("241")); cxfHeaders.put("soapAction", Arrays.asList("urn:hello:world")); cxfHeaders.put("myfruitheader", Arrays.asList("peach")); cxfHeaders.put("mybrewheader", Arrays.asList("cappuccino", "espresso")); + cxfHeaders.put(Message.CONTENT_TYPE, Arrays.asList("text/xml")); + cxfHeaders.put(Message.ENCODING, Arrays.asList("UTF-8")); + cxfHeaders.put(Message.RESPONSE_CODE, Arrays.asList("201")); // Ignored + cxfHeaders.put(Message.REQUEST_URI, Arrays.asList("/base/hello/cxf")); + cxfHeaders.put(Message.HTTP_REQUEST_METHOD, Arrays.asList("GET")); + cxfHeaders.put(Message.PATH_INFO, Arrays.asList("/base/hello/cxf")); + cxfHeaders.put(Message.BASE_PATH, Arrays.asList("/base")); cxfMessage.put(org.apache.cxf.message.Message.PROTOCOL_HEADERS, cxfHeaders); + cxfMessage.put(Message.RESPONSE_CODE, "200"); + Map<String, Object> requestContext = Collections.singletonMap("request", "true"); + Map<String, Object> responseContext = Collections.singletonMap("response", "true"); + cxfMessage.put(Client.REQUEST_CONTEXT, requestContext); + cxfMessage.put(Client.RESPONSE_CONTEXT, responseContext); CxfHeaderHelper.propagateCxfToCamel(new DefaultHeaderFilterStrategy(), cxfMessage, exchange.getIn(), exchange); @@ -92,7 +121,20 @@ public class CxfHeaderHelperTest extends Assert { assertEquals("241", camelHeaders.get("content-length")); assertEquals("peach", camelHeaders.get("MyFruitHeader")); assertEquals(Arrays.asList("cappuccino", "espresso"), camelHeaders.get("MyBrewHeader")); + assertEquals("text/xml; charset=UTF-8", camelHeaders.get(Exchange.CONTENT_TYPE)); + assertEquals("/base/hello/cxf", camelHeaders.get(Exchange.HTTP_URI)); + assertEquals("GET", camelHeaders.get(Exchange.HTTP_METHOD)); + assertEquals("/hello/cxf", camelHeaders.get(Exchange.HTTP_PATH)); + assertEquals("200", camelHeaders.get(Exchange.HTTP_RESPONSE_CODE)); + assertEquals(requestContext, camelHeaders.get(Client.REQUEST_CONTEXT)); + assertEquals(responseContext, camelHeaders.get(Client.RESPONSE_CONTEXT)); + + assertNull(camelHeaders.get(Message.RESPONSE_CODE)); + assertNull(camelHeaders.get(Message.REQUEST_URI)); + assertNull(camelHeaders.get(Message.HTTP_REQUEST_METHOD)); + assertNull(camelHeaders.get(Message.PATH_INFO)); + assertNull(camelHeaders.get(Message.RESPONSE_CODE)); } @Test @@ -101,7 +143,7 @@ public class CxfHeaderHelperTest extends Assert { exchange.setProperty(CxfConstants.CAMEL_CXF_PROTOCOL_HEADERS_MERGED, Boolean.TRUE); org.apache.cxf.message.Message cxfMessage = new org.apache.cxf.message.MessageImpl(); - Map<String, List<String>> cxfHeaders = new TreeMap<String, List<String>>(String.CASE_INSENSITIVE_ORDER); + Map<String, List<String>> cxfHeaders = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); cxfHeaders.put("myfruitheader", Arrays.asList("peach")); cxfHeaders.put("mybrewheader", Arrays.asList("cappuccino", "espresso")); cxfMessage.put(org.apache.cxf.message.Message.PROTOCOL_HEADERS, cxfHeaders); @@ -112,23 +154,6 @@ public class CxfHeaderHelperTest extends Assert { Map<String, Object> camelHeaders = exchange.getIn().getHeaders(); assertEquals("peach", camelHeaders.get("MyFruitHeader")); assertEquals("cappuccino, espresso", camelHeaders.get("MyBrewHeader")); - } - - @Test - public void testContentType() { - - Exchange camelExchange = EasyMock.createMock(Exchange.class); - HeaderFilterStrategy strategy = setupHeaderStrategy(camelExchange); - Message cxfMessage = new MessageImpl(); - CxfHeaderHelper.propagateCamelToCxf(strategy, - Collections.<String, Object>singletonMap("Content-Type", "text/xml"), cxfMessage, camelExchange); - - Map<String, List<String>> cxfHeaders = CastUtils.cast((Map<?, ?>)cxfMessage.get(Message.PROTOCOL_HEADERS)); - assertEquals(1, cxfHeaders.size()); - assertEquals(1, cxfHeaders.get("Content-Type").size()); - assertEquals("text/xml", cxfHeaders.get("Content-Type").get(0)); - - assertEquals("text/xml", cxfMessage.get(Message.CONTENT_TYPE)); } private void verifyHeader(Map<String, List<String>> headers, String name, List<String> value) { @@ -143,13 +168,4 @@ public class CxfHeaderHelperTest extends Assert { assertEquals("The value must match", value, values.get(0)); } - private HeaderFilterStrategy setupHeaderStrategy(Exchange exchange) { - - HeaderFilterStrategy strategy = EasyMock.createMock(HeaderFilterStrategy.class); - strategy.applyFilterToCamelHeaders("Content-Type", "text/xml", exchange); - EasyMock.expectLastCall().andReturn(false); - EasyMock.replay(strategy); - return strategy; - } - } http://git-wip-us.apache.org/repos/asf/camel/blob/583bec8f/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/DefaultCxfRsBinding.java ---------------------------------------------------------------------- diff --git a/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/DefaultCxfRsBinding.java b/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/DefaultCxfRsBinding.java index eb936ff..673ec6a 100644 --- a/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/DefaultCxfRsBinding.java +++ b/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/DefaultCxfRsBinding.java @@ -51,32 +51,12 @@ import org.slf4j.LoggerFactory; */ public class DefaultCxfRsBinding implements CxfRsBinding, HeaderFilterStrategyAware { private static final Logger LOG = LoggerFactory.getLogger(DefaultCxfRsBinding.class); - - protected Map<String, String> camelToCxfHeaderMap = new HashMap<String, String>(); - protected Map<String, String> cxfToCamelHeaderMap = new HashMap<String, String>(); private HeaderFilterStrategy headerFilterStrategy; public DefaultCxfRsBinding() { - // initialize mappings between Camel and CXF header names - - camelToCxfHeaderMap.put(Exchange.HTTP_URI, org.apache.cxf.message.Message.REQUEST_URI); - camelToCxfHeaderMap.put(Exchange.HTTP_METHOD, org.apache.cxf.message.Message.HTTP_REQUEST_METHOD); - camelToCxfHeaderMap.put(Exchange.HTTP_PATH, org.apache.cxf.message.Message.PATH_INFO); - camelToCxfHeaderMap.put(Exchange.CONTENT_TYPE, org.apache.cxf.message.Message.CONTENT_TYPE); - camelToCxfHeaderMap.put(Exchange.HTTP_CHARACTER_ENCODING, org.apache.cxf.message.Message.ENCODING); - camelToCxfHeaderMap.put(Exchange.HTTP_QUERY, org.apache.cxf.message.Message.QUERY_STRING); - camelToCxfHeaderMap.put(Exchange.ACCEPT_CONTENT_TYPE, org.apache.cxf.message.Message.ACCEPT_CONTENT_TYPE); - - cxfToCamelHeaderMap.put(org.apache.cxf.message.Message.REQUEST_URI, Exchange.HTTP_URI); - cxfToCamelHeaderMap.put(org.apache.cxf.message.Message.HTTP_REQUEST_METHOD, Exchange.HTTP_METHOD); - cxfToCamelHeaderMap.put(org.apache.cxf.message.Message.PATH_INFO, Exchange.HTTP_PATH); - cxfToCamelHeaderMap.put(org.apache.cxf.message.Message.CONTENT_TYPE, Exchange.CONTENT_TYPE); - cxfToCamelHeaderMap.put(org.apache.cxf.message.Message.ENCODING, Exchange.HTTP_CHARACTER_ENCODING); - cxfToCamelHeaderMap.put(org.apache.cxf.message.Message.QUERY_STRING, Exchange.HTTP_QUERY); - cxfToCamelHeaderMap.put(org.apache.cxf.message.Message.ACCEPT_CONTENT_TYPE, Exchange.ACCEPT_CONTENT_TYPE); } - + public Object populateCxfRsResponseFromExchange(Exchange camelExchange, org.apache.cxf.message.Exchange cxfExchange) throws Exception { // Need to check if the exchange has the exception @@ -106,10 +86,10 @@ public class DefaultCxfRsBinding implements CxfRsBinding, HeaderFilterStrategyAw Message camelMessage = camelExchange.getIn(); //Copy the CXF message header into the Camel inMessage org.apache.cxf.message.Message cxfMessage = cxfExchange.getInMessage(); - - // TODO use header filter strategy and cxfToCamelHeaderMap + CxfHeaderHelper.copyHttpHeadersFromCxfToCamel(headerFilterStrategy, cxfMessage, camelMessage, camelExchange); - + + // TODO move to CxfHeaderHelper and use header filter strategy and CXF_TO_CAMEL_HEADERS // setup the charset from content-type header setCharsetWithContentType(camelExchange); @@ -158,31 +138,8 @@ public class DefaultCxfRsBinding implements CxfRsBinding, HeaderFilterStrategyAw Exchange camelExchange) throws Exception { - MultivaluedMap<String, String> answer = new MetadataMap<String, String>(); - for (Map.Entry<String, Object> entry : camelHeaders.entrySet()) { - // Need to make sure the cxf needed header will not be filtered - if (headerFilterStrategy.applyFilterToCamelHeaders(entry.getKey(), entry.getValue(), camelExchange) - && camelToCxfHeaderMap.get(entry.getKey()) == null) { - LOG.trace("Drop Camel header: {}={}", entry.getKey(), entry.getValue()); - continue; - } - - // we need to make sure the entry value is not null - if (entry.getValue() == null) { - LOG.trace("Drop Camel header: {}={}", entry.getKey(), entry.getValue()); - continue; - } - - String mappedHeaderName = camelToCxfHeaderMap.get(entry.getKey()); - if (mappedHeaderName == null) { - mappedHeaderName = entry.getKey(); - } - - LOG.trace("Propagate Camel header: {}={} as {}", - new Object[]{entry.getKey(), entry.getValue(), mappedHeaderName}); - - answer.putSingle(mappedHeaderName, entry.getValue().toString()); - } + MultivaluedMap<String, String> answer = new MetadataMap<>(); + CxfHeaderHelper.propagateCamelHeadersToCxfHeaders(headerFilterStrategy, camelHeaders, answer, camelExchange); return answer; } @@ -217,30 +174,12 @@ public class DefaultCxfRsBinding implements CxfRsBinding, HeaderFilterStrategyAw public Map<String, Object> bindResponseHeadersToCamelHeaders(Object response, Exchange camelExchange) throws Exception { - Map<String, Object> answer = new HashMap<String, Object>(); + Map<String, Object> answer = new HashMap<>(); if (response instanceof Response) { - - for (Map.Entry<String, List<Object>> entry : ((Response)response).getMetadata().entrySet()) { - if (!headerFilterStrategy.applyFilterToExternalHeaders(entry.getKey(), - entry.getValue(), camelExchange)) { - - String mappedHeaderName = cxfToCamelHeaderMap.get(entry.getKey()); - if (mappedHeaderName == null) { - mappedHeaderName = entry.getKey(); - } - - LOG.trace("Populate external header {}={} as {}", - new Object[]{entry.getKey(), entry.getValue(), mappedHeaderName}); - - answer.put(mappedHeaderName, entry.getValue().get(0)); - - } else { - LOG.trace("Drop external header {}={}", entry.getKey(), entry.getValue()); - } - } - + Map<String, List<Object>> responseHeaders = ((Response) response).getMetadata(); + CxfHeaderHelper.propagateCxfHeadersToCamelHeaders(headerFilterStrategy, responseHeaders, answer, camelExchange); } - + return answer; } @@ -259,22 +198,6 @@ public class DefaultCxfRsBinding implements CxfRsBinding, HeaderFilterStrategyAw headerFilterStrategy = strategy; } - public Map<String, String> getCamelToCxfHeaderMap() { - return camelToCxfHeaderMap; - } - - public void setCamelToCxfHeaderMap(Map<String, String> camelToCxfHeaderMap) { - this.camelToCxfHeaderMap = camelToCxfHeaderMap; - } - - public Map<String, String> getCxfToCamelHeaderMap() { - return cxfToCamelHeaderMap; - } - - public void setCxfToCamelHeaderMap(Map<String, String> cxfToCamelHeaderMap) { - this.cxfToCamelHeaderMap = cxfToCamelHeaderMap; - } - @SuppressWarnings("unchecked") protected void copyProtocolHeader(org.apache.cxf.message.Message cxfMessage, Message camelMessage, Exchange camelExchange) { Map<String, List<String>> headers = (Map<String, List<String>>)cxfMessage.get(org.apache.cxf.message.Message.PROTOCOL_HEADERS);