From 37553b6e5fc97d5b6ab7ce3162fe0c0412fb99b8 Mon Sep 17 00:00:00 2001 From: Mark Fisher Date: Sun, 12 Dec 2010 16:42:50 -0500 Subject: [PATCH] INT-1680 DefaultHttpHeaderMapper now supports simple pattern matching for the inboundHeaderNames and outboundHeaderNames --- .../http/support/DefaultHttpHeaderMapper.java | 66 ++++++++++----- ...tpHeaderMapperFromMessageInboundTests.java | 81 +++++++++++++++++++ ...pHeaderMapperFromMessageOutboundTests.java | 27 +++++++ 3 files changed, 155 insertions(+), 19 deletions(-) diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/support/DefaultHttpHeaderMapper.java b/spring-integration-http/src/main/java/org/springframework/integration/http/support/DefaultHttpHeaderMapper.java index 0245a5e4aa..6d1ea8ef43 100644 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/support/DefaultHttpHeaderMapper.java +++ b/spring-integration-http/src/main/java/org/springframework/integration/http/support/DefaultHttpHeaderMapper.java @@ -36,6 +36,7 @@ import org.springframework.integration.MessageHeaders; import org.springframework.integration.mapping.HeaderMapper; import org.springframework.util.CollectionUtils; import org.springframework.util.ObjectUtils; +import org.springframework.util.PatternMatchUtils; import org.springframework.util.StringUtils; /** @@ -222,6 +223,7 @@ public class DefaultHttpHeaderMapper implements HeaderMapper { /** * Provide the header names that should be mapped to an HTTP request (for outbound adapters) * or HTTP response (for inbound adapters) from a Spring Integration Message's headers. + * The values can also contain simple wildcard patterns (e.g. "foo*" or "*foo") to be matched. *

* Any non-standard headers will be prefixed by {@value #USER_DEFINED_HEADER_PREFIX} if not already. */ @@ -232,6 +234,7 @@ public class DefaultHttpHeaderMapper implements HeaderMapper { /** * Provide the header names that should be mapped from an HTTP request (for inbound adapters) * or HTTP response (for outbound adapters) to a Spring Integration Message's headers. + * The values can also contain simple wildcard patterns (e.g. "foo*" or "*foo") to be matched. *

* This will match the header name directly or, for non-standard HTTP headers, it will match * the header name prefixed by {@value #USER_DEFINED_HEADER_PREFIX}. @@ -246,14 +249,17 @@ public class DefaultHttpHeaderMapper implements HeaderMapper { * for an HTTP request (outbound adapter) or for an HTTP response (inbound adapter). */ public void fromHeaders(MessageHeaders headers, HttpHeaders target) { - for (String name : this.outboundHeaderNames) { - Object value = headers.get(name); - if (value != null) { - if (!ObjectUtils.containsElement(HTTP_REQUEST_HEADER_NAMES, name) && !ObjectUtils.containsElement(HTTP_RESPONSE_HEADER_NAMES, name)) { - // prefix the user-defined header names if not already prefixed - name = name.startsWith(USER_DEFINED_HEADER_PREFIX) ? name : USER_DEFINED_HEADER_PREFIX + name; + Set headerNames = headers.keySet(); + for (String name : headerNames) { + if (this.shouldMapOutboundHeader(name)) { + Object value = headers.get(name); + if (value != null) { + if (!ObjectUtils.containsElement(HTTP_REQUEST_HEADER_NAMES, name) && !ObjectUtils.containsElement(HTTP_RESPONSE_HEADER_NAMES, name)) { + // prefix the user-defined header names if not already prefixed + name = name.startsWith(USER_DEFINED_HEADER_PREFIX) ? name : USER_DEFINED_HEADER_PREFIX + name; + } + this.setHttpHeader(target, name, value); } - this.setHttpHeader(target, name, value); } } } @@ -265,25 +271,47 @@ public class DefaultHttpHeaderMapper implements HeaderMapper { */ public Map toHeaders(HttpHeaders source) { Map target = new HashMap(); - for (String name : this.inboundHeaderNames) { - if (!ObjectUtils.containsElement(HTTP_REQUEST_HEADER_NAMES, name) && !ObjectUtils.containsElement(HTTP_RESPONSE_HEADER_NAMES, name)) { - String prefixedName = name.startsWith(USER_DEFINED_HEADER_PREFIX) ? name - : USER_DEFINED_HEADER_PREFIX + name; - Object value = source.containsKey(prefixedName) ? this.getHttpHeader(source, prefixedName) : this.getHttpHeader(source, name); - if (value != null) { - this.setMessageHeader(target, name, value); + Set headerNames = source.keySet(); + for (String name : headerNames) { + if (this.shouldMapInboundHeader(name)) { + if (!ObjectUtils.containsElement(HTTP_REQUEST_HEADER_NAMES, name) && !ObjectUtils.containsElement(HTTP_RESPONSE_HEADER_NAMES, name)) { + String prefixedName = name.startsWith(USER_DEFINED_HEADER_PREFIX) ? name + : USER_DEFINED_HEADER_PREFIX + name; + Object value = source.containsKey(prefixedName) ? this.getHttpHeader(source, prefixedName) : this.getHttpHeader(source, name); + if (value != null) { + this.setMessageHeader(target, name, value); + } } - } - else { - Object value = this.getHttpHeader(source, name); - if (value != null) { - this.setMessageHeader(target, name, value); + else { + Object value = this.getHttpHeader(source, name); + if (value != null) { + this.setMessageHeader(target, name, value); + } } } } return target; } + private boolean shouldMapOutboundHeader(String headerName) { + return this.shouldMapHeader(headerName, this.outboundHeaderNames); + } + + private boolean shouldMapInboundHeader(String headerName) { + return this.shouldMapHeader(headerName, this.inboundHeaderNames); + } + + private boolean shouldMapHeader(String headerName, String[] patterns) { + if (patterns != null && patterns.length > 0) { + for (String pattern : patterns) { + if (PatternMatchUtils.simpleMatch(pattern, headerName)) { + return true; + } + } + } + return false; + } + private void setHttpHeader(HttpHeaders target, String name, Object value) { if (ACCEPT.equals(name)) { if (value instanceof Collection) { diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/support/DefaultHttpHeaderMapperFromMessageInboundTests.java b/spring-integration-http/src/test/java/org/springframework/integration/http/support/DefaultHttpHeaderMapperFromMessageInboundTests.java index 1590ce094b..160a5fc492 100644 --- a/spring-integration-http/src/test/java/org/springframework/integration/http/support/DefaultHttpHeaderMapperFromMessageInboundTests.java +++ b/spring-integration-http/src/test/java/org/springframework/integration/http/support/DefaultHttpHeaderMapperFromMessageInboundTests.java @@ -18,6 +18,7 @@ package org.springframework.integration.http.support; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertTrue; +import static org.junit.Assert.assertNull; import java.net.URI; import java.text.ParseException; @@ -254,4 +255,84 @@ public class DefaultHttpHeaderMapperFromMessageInboundTests { } // Pragma tested as part of DefaultHttpHeaderMapperFromMessageOutboundTests + + @Test + public void validateCustomHeaderNamesMappedToHttpHeaders() throws Exception{ + DefaultHttpHeaderMapper mapper = new DefaultHttpHeaderMapper(); + mapper.setOutboundHeaderNames(new String[] {"foo", "bar"}); + Map messageHeaders = new HashMap(); + messageHeaders.put("foo", "abc"); + messageHeaders.put("bar", "123"); + HttpHeaders headers = new HttpHeaders(); + mapper.fromHeaders(new MessageHeaders(messageHeaders), headers); + assertEquals(2, headers.size()); + assertEquals(1, headers.get("X-foo").size()); + assertEquals("abc", headers.getFirst("X-foo")); + assertEquals(1, headers.get("X-bar").size()); + assertEquals("123", headers.getFirst("X-bar")); + } + + @Test + public void validateCustomHeaderNamePatternsMappedToHttpHeaders() throws Exception{ + DefaultHttpHeaderMapper mapper = new DefaultHttpHeaderMapper(); + mapper.setOutboundHeaderNames(new String[] {"x*", "*z", "a*f"}); + Map messageHeaders = new HashMap(); + messageHeaders.put("x1", "x1-value"); + messageHeaders.put("1x", "1x-value"); + messageHeaders.put("z1", "z1-value"); + messageHeaders.put("1z", "1z-value"); + messageHeaders.put("abc", "abc-value"); + messageHeaders.put("def", "def-value"); + messageHeaders.put("abcdef", "abcdef-value"); + HttpHeaders headers = new HttpHeaders(); + mapper.fromHeaders(new MessageHeaders(messageHeaders), headers); + assertEquals(3, headers.size()); + assertNull(headers.get("1x")); + assertNull(headers.get("z1")); + assertNull(headers.get("abc")); + assertNull(headers.get("def")); + assertEquals(1, headers.get("X-x1").size()); + assertEquals("x1-value", headers.getFirst("X-x1")); + assertEquals(1, headers.get("X-1z").size()); + assertEquals("1z-value", headers.getFirst("X-1z")); + assertEquals(1, headers.get("X-abcdef").size()); + assertEquals("abcdef-value", headers.getFirst("X-abcdef")); + } + + @Test + public void validateCustomHeaderNamesMappedFromHttpHeaders() throws Exception{ + DefaultHttpHeaderMapper mapper = new DefaultHttpHeaderMapper(); + mapper.setInboundHeaderNames(new String[] {"foo", "bar"}); + HttpHeaders headers = new HttpHeaders(); + headers.set("foo", "abc"); + headers.set("bar", "123"); + Map result = mapper.toHeaders(headers); + assertEquals(2, result.size()); + assertEquals("abc", result.get("foo")); + assertEquals("123", result.get("bar")); + } + + @Test + public void validateCustomHeaderNamePatternsMappedFromHttpHeaders() throws Exception{ + DefaultHttpHeaderMapper mapper = new DefaultHttpHeaderMapper(); + mapper.setInboundHeaderNames(new String[] {"x*", "*z", "a*f"}); + HttpHeaders headers = new HttpHeaders(); + headers.set("x1", "x1-value"); + headers.set("1x", "1x-value"); + headers.set("z1", "z1-value"); + headers.set("1z", "1z-value"); + headers.set("abc", "abc-value"); + headers.set("def", "def-value"); + headers.set("abcdef", "abcdef-value"); + Map result = mapper.toHeaders(headers); + assertEquals(3, result.size()); + assertNull(result.get("1x")); + assertNull(result.get("z1")); + assertNull(result.get("abc")); + assertNull(result.get("def")); + assertEquals("x1-value", result.get("x1")); + assertEquals("1z-value", result.get("1z")); + assertEquals("abcdef-value", result.get("abcdef")); + } + } diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/support/DefaultHttpHeaderMapperFromMessageOutboundTests.java b/spring-integration-http/src/test/java/org/springframework/integration/http/support/DefaultHttpHeaderMapperFromMessageOutboundTests.java index 71266bec78..c12a0b42f5 100644 --- a/spring-integration-http/src/test/java/org/springframework/integration/http/support/DefaultHttpHeaderMapperFromMessageOutboundTests.java +++ b/spring-integration-http/src/test/java/org/springframework/integration/http/support/DefaultHttpHeaderMapperFromMessageOutboundTests.java @@ -508,4 +508,31 @@ public class DefaultHttpHeaderMapperFromMessageOutboundTests { assertEquals("foo", headers.get("X-foo").get(0)); } + @Test + public void validateCustomHeaderWithHeaderNamePatterns() throws ParseException{ + DefaultHttpHeaderMapper mapper = new DefaultHttpHeaderMapper(); + mapper.setOutboundHeaderNames(new String[]{"x*", "*z", "a*f"}); + Map messageHeaders = new HashMap(); + messageHeaders.put("x1", "x1-value"); + messageHeaders.put("1x", "1x-value"); + messageHeaders.put("z1", "z1-value"); + messageHeaders.put("1z", "1z-value"); + messageHeaders.put("abc", "abc-value"); + messageHeaders.put("def", "def-value"); + messageHeaders.put("abcdef", "abcdef-value"); + HttpHeaders headers = new HttpHeaders(); + mapper.fromHeaders(new MessageHeaders(messageHeaders), headers); + assertEquals(3, headers.size()); + assertNull(headers.get("1x")); + assertNull(headers.get("z1")); + assertNull(headers.get("abc")); + assertNull(headers.get("def")); + assertEquals(1, headers.get("X-x1").size()); + assertEquals("x1-value", headers.getFirst("X-x1")); + assertEquals(1, headers.get("X-1z").size()); + assertEquals("1z-value", headers.getFirst("X-1z")); + assertEquals(1, headers.get("X-abcdef").size()); + assertEquals("abcdef-value", headers.getFirst("X-abcdef")); + } + }