From 054f473287d6338dc4a5a96598c5300e2f2e1e16 Mon Sep 17 00:00:00 2001 From: Artem Bilan Date: Mon, 1 Sep 2014 11:24:50 +0300 Subject: [PATCH] INT-3508: HTTP: Map `MessageHeaders.CONTENT_TYPE` JIRA: https://jira.spring.io/browse/INT-3508 Before SI 4.0 and moving `MessageHeaders` to the Spring Messaging the `MessageHeaders.CONTENT_TYPE` had a value as `content-type`, which was mapped to the HTTP Header `Content-Type` well. Starting with SF 4.0 `MessageHeaders.CONTENT_TYPE` has a value `contentType`. It doesn't allow to map HTTP headers properly. * Add `contentType` mapping logic to the `DefaultHttpHeaderMapper`, to map to the `Content-Type` HTTP header and vice versa. * Fix bug in the `DefaultHttpHeaderMapper#toHeaders`: `ObjectUtils.containsElement` -> `containsElementIgnoreCase`. Some HTTP servers can return `Content-Type` as `Content-type` or even `content-type`, although it is `Content-Type` anyway. * Add test-case with ``, when the `application/json` value from `MessageHeaders.CONTENT_TYPE` is properly mapped to the HTTP `Content-Type`. Prior to this fix we had to remap `MessageHeaders.CONTENT_TYPE` to the `Content-Type` manually using `` Reformat code Use only `MessageHeaders.CONTENT_TYPE` for mapping to/from SI Move `MessageHeaders.CONTENT_TYPE` logic to the `fromHeaders` Performance Improvements Remove toLowerCase() calls within loop of `shouldMapHeader()`. Pre-build lower case versions of arrays. --- .../http/support/DefaultHttpHeaderMapper.java | 186 ++++++---- .../OutboundResponseTypeTests-context.xml | 31 +- .../config/OutboundResponseTypeTests.java | 37 +- ...pHeaderMapperFromMessageOutboundTests.java | 323 ++++++++++-------- 4 files changed, 351 insertions(+), 226 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 cd8349cdd0..c92d2ad9ac 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 @@ -24,6 +24,7 @@ import java.text.MessageFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Date; @@ -111,7 +112,7 @@ public class DefaultHttpHeaderMapper implements HeaderMapper, BeanF private static final String CONTENT_DISPOSITION = "Content-Disposition"; - public static final String COOKIE = "Cookie"; + public static final String COOKIE = "Cookie"; private static final String DATE = "Date"; @@ -157,7 +158,7 @@ public class DefaultHttpHeaderMapper implements HeaderMapper, BeanF private static final String SERVER = "Server"; - public static final String SET_COOKIE = "Set-Cookie"; + public static final String SET_COOKIE = "Set-Cookie"; private static final String TE = "TE"; @@ -210,7 +211,9 @@ public class DefaultHttpHeaderMapper implements HeaderMapper, BeanF WARNING }; - private static String[] HTTP_RESPONSE_HEADER_NAMES = new String[] { + private static final Set HTTP_REQUEST_HEADER_NAMES_LOWER = new HashSet(); + + private static final String[] HTTP_RESPONSE_HEADER_NAMES = new String[] { ACCEPT_RANGES, AGE, ALLOW, @@ -243,9 +246,11 @@ public class DefaultHttpHeaderMapper implements HeaderMapper, BeanF WWW_AUTHENTICATE }; - private static String[] HTTP_REQUEST_HEADER_NAMES_OUTBOUND_EXCLUSIONS = new String[0]; + private static final Set HTTP_RESPONSE_HEADER_NAMES_LOWER = new HashSet(); - private static String[] HTTP_RESPONSE_HEADER_NAMES_INBOUND_EXCLUSIONS = new String[] { + private static final String[] HTTP_REQUEST_HEADER_NAMES_OUTBOUND_EXCLUSIONS = new String[0]; + + private static final String[] HTTP_RESPONSE_HEADER_NAMES_INBOUND_EXCLUSIONS = new String[] { CONTENT_LENGTH, TRANSFER_ENCODING }; @@ -262,10 +267,25 @@ public class DefaultHttpHeaderMapper implements HeaderMapper, BeanF private static TimeZone GMT = TimeZone.getTimeZone("GMT"); + static { + for (String header : HTTP_REQUEST_HEADER_NAMES) { + HTTP_REQUEST_HEADER_NAMES_LOWER.add(header.toLowerCase()); + } + for (String header : HTTP_RESPONSE_HEADER_NAMES) { + HTTP_RESPONSE_HEADER_NAMES_LOWER.add(header.toLowerCase()); + } + } + private volatile String[] outboundHeaderNames = new String[0]; + private volatile String[] outboundHeaderNamesLower = new String[0]; + + private volatile String[] outboundHeaderNamesLowerWithContentType = new String[0]; + private volatile String[] inboundHeaderNames = new String[0]; + private volatile String[] inboundHeaderNamesLower = new String[0]; + private volatile String[] excludedOutboundStandardRequestHeaderNames = new String[0]; private volatile String[] excludedInboundStandardResponseHeaderNames = new String[0]; @@ -281,29 +301,49 @@ public class DefaultHttpHeaderMapper implements HeaderMapper, BeanF * 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 with the value specified by + *

Any non-standard headers will be prefixed with the value specified by * {@link DefaultHttpHeaderMapper#setUserDefinedHeaderPrefix(String)}. The default is 'X-'. - * * @param outboundHeaderNames The outbound header names. */ public void setOutboundHeaderNames(String[] outboundHeaderNames) { this.outboundHeaderNames = (outboundHeaderNames != null) ? outboundHeaderNames : new String[0]; + this.outboundHeaderNamesLower = new String[this.outboundHeaderNames.length]; + for (int i = 0; i < outboundHeaderNames.length; i++) { + if (HTTP_REQUEST_HEADER_NAME_PATTERN.equals(this.outboundHeaderNames[i]) + || HTTP_RESPONSE_HEADER_NAME_PATTERN.equals(this.outboundHeaderNames[i])) { + this.outboundHeaderNamesLower[i] = this.outboundHeaderNames[i]; + } + else { + this.outboundHeaderNamesLower[i] = this.outboundHeaderNames[i].toLowerCase(); + } + } + this.outboundHeaderNamesLowerWithContentType = + Arrays.copyOf(this.outboundHeaderNamesLower, this.outboundHeaderNames.length + 1); + this.outboundHeaderNamesLowerWithContentType[this.outboundHeaderNamesLowerWithContentType.length - 1] + = MessageHeaders.CONTENT_TYPE.toLowerCase(); } /** * 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 + *

This will match the header name directly or, for non-standard HTTP headers, it will match * the header name prefixed with the value specified by * {@link DefaultHttpHeaderMapper#setUserDefinedHeaderPrefix(String)}. The default is 'X-'. - * * @param inboundHeaderNames The inbound header names. */ public void setInboundHeaderNames(String[] inboundHeaderNames) { this.inboundHeaderNames = (inboundHeaderNames != null) ? inboundHeaderNames : new String[0]; + this.inboundHeaderNamesLower = new String[this.inboundHeaderNames.length]; + for (int i = 0; i < inboundHeaderNames.length; i++) { + if (HTTP_REQUEST_HEADER_NAME_PATTERN.equals(this.inboundHeaderNames[i]) + || HTTP_RESPONSE_HEADER_NAME_PATTERN.equals(this.inboundHeaderNames[i])) { + this.inboundHeaderNamesLower[i] = this.inboundHeaderNames[i]; + } + else { + this.inboundHeaderNamesLower[i] = this.inboundHeaderNames[i].toLowerCase(); + } + } } /** @@ -312,23 +352,24 @@ public class DefaultHttpHeaderMapper implements HeaderMapper, BeanF * @param excludedOutboundStandardRequestHeaderNames the excludedStandardRequestHeaderNames to set */ public void setExcludedOutboundStandardRequestHeaderNames(String[] excludedOutboundStandardRequestHeaderNames) { - Assert.notNull(excludedOutboundStandardRequestHeaderNames, "'excludedOutboundStandardRequestHeaderNames' must not be null"); + Assert.notNull(excludedOutboundStandardRequestHeaderNames, + "'excludedOutboundStandardRequestHeaderNames' must not be null"); this.excludedOutboundStandardRequestHeaderNames = excludedOutboundStandardRequestHeaderNames; } /** * Provide header names from the list of standard headers that should be suppressed when - * mapping inbound endopoint response headers. + * mapping inbound endpoint response headers. * @param excludedInboundStandardResponseHeaderNames the excludedStandardResponseHeaderNames to set */ public void setExcludedInboundStandardResponseHeaderNames(String[] excludedInboundStandardResponseHeaderNames) { - Assert.notNull(excludedInboundStandardResponseHeaderNames, "'excludedInboundStandardResponseHeaderNames' must not be null"); + Assert.notNull(excludedInboundStandardResponseHeaderNames, + "'excludedInboundStandardResponseHeaderNames' must not be null"); this.excludedInboundStandardResponseHeaderNames = excludedInboundStandardResponseHeaderNames; } /** * Sets the prefix to use with user-defined (non-standard) headers. Default is 'X-'. - * * @param userDefinedHeaderPrefix The user defined header prefix. */ public void setUserDefinedHeaderPrefix(String userDefinedHeaderPrefix) { @@ -342,16 +383,19 @@ public class DefaultHttpHeaderMapper implements HeaderMapper, BeanF */ @Override public void fromHeaders(MessageHeaders headers, HttpHeaders target) { - if (logger.isDebugEnabled()){ - logger.debug(MessageFormat.format("outboundHeaderNames={0}", CollectionUtils.arrayToList(outboundHeaderNames))); + if (logger.isDebugEnabled()) { + logger.debug(MessageFormat.format("outboundHeaderNames={0}", + CollectionUtils.arrayToList(outboundHeaderNames))); } Set headerNames = headers.keySet(); for (String name : headerNames) { - if (this.shouldMapOutboundHeader(name)) { + String lowerName = name.toLowerCase(); + if (this.shouldMapOutboundHeader(lowerName)) { Object value = headers.get(name); if (value != null) { - if (!this.containsElementIgnoreCase(HTTP_REQUEST_HEADER_NAMES, name) && - !this.containsElementIgnoreCase(HTTP_RESPONSE_HEADER_NAMES, name)) { + if (!HTTP_REQUEST_HEADER_NAMES_LOWER.contains(lowerName) && + !HTTP_RESPONSE_HEADER_NAMES_LOWER.contains(lowerName) && + !MessageHeaders.CONTENT_TYPE.equalsIgnoreCase(name)) { // prefix the user-defined header names if not already prefixed name = StringUtils.startsWithIgnoreCase(name, this.userDefinedHeaderPrefix) ? name : @@ -374,16 +418,22 @@ public class DefaultHttpHeaderMapper implements HeaderMapper, BeanF @Override public Map toHeaders(HttpHeaders source) { if (logger.isDebugEnabled()) { - logger.debug(MessageFormat.format("inboundHeaderNames={0}", CollectionUtils.arrayToList(inboundHeaderNames))); + logger.debug(MessageFormat.format("inboundHeaderNames={0}", + CollectionUtils.arrayToList(inboundHeaderNames))); } Map target = new HashMap(); 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 = StringUtils.startsWithIgnoreCase(name, this.userDefinedHeaderPrefix) ? name : - this.userDefinedHeaderPrefix + name; - Object value = source.containsKey(prefixedName) ? this.getHttpHeader(source, prefixedName) : this.getHttpHeader(source, name); + String lowerName = name.toLowerCase(); + if (this.shouldMapInboundHeader(lowerName)) { + if (!HTTP_REQUEST_HEADER_NAMES_LOWER.contains(lowerName) + && !HTTP_RESPONSE_HEADER_NAMES_LOWER.contains(lowerName)) { + String prefixedName = StringUtils.startsWithIgnoreCase(name, this.userDefinedHeaderPrefix) + ? name + : this.userDefinedHeaderPrefix + name; + Object value = source.containsKey(prefixedName) + ? this.getHttpHeader(source, prefixedName) + : this.getHttpHeader(source, name); if (value != null) { if (logger.isDebugEnabled()) { logger.debug(MessageFormat.format("setting headerName=[{0}], value={1}", name, value)); @@ -397,6 +447,9 @@ public class DefaultHttpHeaderMapper implements HeaderMapper, BeanF if (logger.isDebugEnabled()) { logger.debug(MessageFormat.format("setting headerName=[{0}], value={1}", name, value)); } + if (CONTENT_TYPE.equals(name)) { + name = MessageHeaders.CONTENT_TYPE; + } this.setMessageHeader(target, name, value); } } @@ -407,14 +460,14 @@ public class DefaultHttpHeaderMapper implements HeaderMapper, BeanF @Override public void afterPropertiesSet() throws Exception { - if (this.beanFactory != null){ + if (this.beanFactory != null) { this.conversionService = IntegrationUtils.getConversionService(this.beanFactory); } } - private boolean containsElementIgnoreCase(String[] headerNames, String name){ + private boolean containsElementIgnoreCase(String[] headerNames, String name) { for (String headerName : headerNames) { - if (headerName.equalsIgnoreCase(name)){ + if (headerName.equalsIgnoreCase(name)) { return true; } } @@ -422,6 +475,8 @@ public class DefaultHttpHeaderMapper implements HeaderMapper, BeanF } private boolean shouldMapOutboundHeader(String headerName) { + String[] outboundHeaderNames = this.outboundHeaderNamesLower; + if (this.outboundHeaderNames == HTTP_RESPONSE_HEADER_NAMES) { // a default inbound mapper /* * When using the default response header name list, suppress the @@ -435,6 +490,7 @@ public class DefaultHttpHeaderMapper implements HeaderMapper, BeanF } } else if (this.outboundHeaderNames == HTTP_REQUEST_HEADER_NAMES) { // a default outbound mapper + outboundHeaderNames = this.outboundHeaderNamesLowerWithContentType; /* * When using the default request header name list, suppress the * mapping of exclusions for specific headers. @@ -446,33 +502,41 @@ public class DefaultHttpHeaderMapper implements HeaderMapper, BeanF return false; } } - return this.shouldMapHeader(headerName, this.outboundHeaderNames); + return this.shouldMapHeader(headerName, outboundHeaderNames); } private boolean shouldMapInboundHeader(String headerName) { - return this.shouldMapHeader(headerName, this.inboundHeaderNames); + return this.shouldMapHeader(headerName, this.inboundHeaderNamesLower); } + /** + * @param headerName the header name (lower cased). + * @param patterns the patterns (lower cased). + * @return true if should be mapped. + */ private boolean shouldMapHeader(String headerName, String[] patterns) { if (patterns != null && patterns.length > 0) { for (String pattern : patterns) { - if (PatternMatchUtils.simpleMatch(pattern.toLowerCase(), headerName.toLowerCase())) { + if (PatternMatchUtils.simpleMatch(pattern, headerName)) { if (logger.isDebugEnabled()) { - logger.debug(MessageFormat.format("headerName=[{0}] WILL be mapped, matched pattern={1}", headerName, pattern)); + logger.debug(MessageFormat.format("headerName=[{0}] WILL be mapped, matched pattern={1}", + headerName, pattern)); } return true; } else if (HTTP_REQUEST_HEADER_NAME_PATTERN.equals(pattern) - && this.containsElementIgnoreCase(HTTP_REQUEST_HEADER_NAMES, headerName)) { + && HTTP_REQUEST_HEADER_NAMES_LOWER.contains(headerName)) { if (logger.isDebugEnabled()) { - logger.debug(MessageFormat.format("headerName=[{0}] WILL be mapped, matched pattern={1}", headerName, pattern)); + logger.debug(MessageFormat.format("headerName=[{0}] WILL be mapped, matched pattern={1}", + headerName, pattern)); } return true; } else if (HTTP_RESPONSE_HEADER_NAME_PATTERN.equals(pattern) - && this.containsElementIgnoreCase(HTTP_RESPONSE_HEADER_NAMES, headerName)) { + && HTTP_RESPONSE_HEADER_NAMES_LOWER.contains(headerName)) { if (logger.isDebugEnabled()) { - logger.debug(MessageFormat.format("headerName=[{0}] WILL be mapped, matched pattern={1}", headerName, pattern)); + logger.debug(MessageFormat.format("headerName=[{0}] WILL be mapped, matched pattern={1}", + headerName, pattern)); } return true; } @@ -500,7 +564,8 @@ public class DefaultHttpHeaderMapper implements HeaderMapper, BeanF else { Class clazz = (type != null) ? type.getClass() : null; throw new IllegalArgumentException( - "Expected MediaType or String value for 'Accept' header value, but received: " + clazz); + "Expected MediaType or String value for 'Accept' header value, but received: " + + clazz); } } target.setAccept(acceptableMediaTypes); @@ -540,7 +605,8 @@ public class DefaultHttpHeaderMapper implements HeaderMapper, BeanF else { Class clazz = (charset != null) ? charset.getClass() : null; throw new IllegalArgumentException( - "Expected Charset or String value for 'Accept-Charset' header value, but received: " + clazz); + "Expected Charset or String value for 'Accept-Charset' header value, but received: " + + clazz); } } target.setAcceptCharset(acceptableCharsets); @@ -591,7 +657,8 @@ public class DefaultHttpHeaderMapper implements HeaderMapper, BeanF else { Class clazz = (method != null) ? method.getClass() : null; throw new IllegalArgumentException( - "Expected HttpMethod or String value for 'Allow' header value, but received: " + clazz); + "Expected HttpMethod or String value for 'Allow' header value, but received: " + + clazz); } } target.setAllow(allowedMethods); @@ -603,9 +670,7 @@ public class DefaultHttpHeaderMapper implements HeaderMapper, BeanF } else if (value instanceof HttpMethod[]) { Set allowedMethods = new HashSet(); - for (HttpMethod next : (HttpMethod[]) value) { - allowedMethods.add(next); - } + Collections.addAll(allowedMethods, (HttpMethod[]) value); target.setAllow(allowedMethods); } else if (value instanceof String || value instanceof String[]) { @@ -647,7 +712,7 @@ public class DefaultHttpHeaderMapper implements HeaderMapper, BeanF "Expected Number or String value for 'Content-Length' header value, but received: " + clazz); } } - else if (CONTENT_TYPE.equalsIgnoreCase(name)) { + else if (MessageHeaders.CONTENT_TYPE.equalsIgnoreCase(name)) { if (value instanceof MediaType) { target.setContentType((MediaType) value); } @@ -730,7 +795,8 @@ public class DefaultHttpHeaderMapper implements HeaderMapper, BeanF else { Class clazz = (value != null) ? value.getClass() : null; throw new IllegalArgumentException( - "Expected Date, Number, or String value for 'If-Modified-Since' header value, but received: " + clazz); + "Expected Date, Number, or String value for 'If-Modified-Since' header value, but received: " + + clazz); } } else if (IF_UNMODIFIED_SINCE.equalsIgnoreCase(name)) { @@ -753,7 +819,8 @@ public class DefaultHttpHeaderMapper implements HeaderMapper, BeanF else { Class clazz = (value != null) ? value.getClass() : null; throw new IllegalArgumentException( - "Expected Date, Number, or String value for 'If-Unmodified-Since' header value, but received: " + clazz); + "Expected Date, Number, or String value for 'If-Unmodified-Since' header value, but received: " + + clazz); } target.set(IF_UNMODIFIED_SINCE, ifUnmodifiedSinceValue); } @@ -801,7 +868,8 @@ public class DefaultHttpHeaderMapper implements HeaderMapper, BeanF else { Class clazz = (value != null) ? value.getClass() : null; throw new IllegalArgumentException( - "Expected Date, Number, or String value for 'Last-Modified' header value, but received: " + clazz); + "Expected Date, Number, or String value for 'Last-Modified' header value, but received: " + + clazz); } } else if (LOCATION.equalsIgnoreCase(name)) { @@ -849,13 +917,13 @@ public class DefaultHttpHeaderMapper implements HeaderMapper, BeanF else { convertedValue = this.convertToString(value); } - if (StringUtils.hasText(convertedValue)){ - target.add(name, (String) next); + if (StringUtils.hasText(convertedValue)) { + target.add(name, convertedValue); } else { logger.warn("Element of the header '" + name + "' with value '" + value + - "' will not be set since it is not a String and no Converter " + - "is available. Consider registering a Converter with ConversionService (e.g., )"); + "' will not be set since it is not a String and no Converter is available. " + + "Consider registering a Converter with ConversionService (e.g., )"); } } } @@ -866,8 +934,8 @@ public class DefaultHttpHeaderMapper implements HeaderMapper, BeanF } else { logger.warn("Header '" + name + "' with value '" + value + - "' will not be set since it is not a String and no Converter " + - "is available. Consider registering a Converter with ConversionService (e.g., )"); + "' will not be set since it is not a String and no Converter is available. " + + "Consider registering a Converter with ConversionService (e.g., )"); } } } @@ -907,7 +975,7 @@ public class DefaultHttpHeaderMapper implements HeaderMapper, BeanF return (expires > -1) ? expires : null; } catch (Exception e) { - if(logger.isDebugEnabled()) { + if (logger.isDebugEnabled()) { logger.debug(e.getMessage()); } // According to RFC 2616 @@ -967,9 +1035,10 @@ public class DefaultHttpHeaderMapper implements HeaderMapper, BeanF } } - private String convertToString(Object value){ + private String convertToString(Object value) { if (this.conversionService != null && - this.conversionService.canConvert(TypeDescriptor.forObject(value), TypeDescriptor.valueOf(String.class))){ + this.conversionService.canConvert(TypeDescriptor.forObject(value), + TypeDescriptor.valueOf(String.class))) { return this.conversionService.convert(value, String.class); } return null; @@ -988,7 +1057,8 @@ public class DefaultHttpHeaderMapper implements HeaderMapper, BeanF // ignore } } - throw new IllegalArgumentException("Cannot parse date value '" + headerValue +"' for '" + headerName + "' header"); + throw new IllegalArgumentException("Cannot parse date value '" + headerValue + "' for '" + headerName + + "' header"); } private String formatDate(long date) { @@ -1001,7 +1071,6 @@ public class DefaultHttpHeaderMapper implements HeaderMapper, BeanF * Factory method for creating a basic outbound mapper instance. * This will map all standard HTTP request headers when sending an HTTP request, * and it will map all standard HTTP response headers when receiving an HTTP response. - * * @return The default outbound mapper. */ public static DefaultHttpHeaderMapper outboundMapper() { @@ -1016,7 +1085,6 @@ public class DefaultHttpHeaderMapper implements HeaderMapper, BeanF * Factory method for creating a basic inbound mapper instance. * This will map all standard HTTP request headers when receiving an HTTP request, * and it will map all standard HTTP response headers when sending an HTTP response. - * * @return The default inbound mapper. */ public static DefaultHttpHeaderMapper inboundMapper() { diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/config/OutboundResponseTypeTests-context.xml b/spring-integration-http/src/test/java/org/springframework/integration/http/config/OutboundResponseTypeTests-context.xml index 18890c47e0..a850228635 100644 --- a/spring-integration-http/src/test/java/org/springframework/integration/http/config/OutboundResponseTypeTests-context.xml +++ b/spring-integration-http/src/test/java/org/springframework/integration/http/config/OutboundResponseTypeTests-context.xml @@ -1,15 +1,19 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:int="http://www.springframework.org/schema/integration" + xmlns:int-http="http://www.springframework.org/schema/integration/http" + xmlns:util="http://www.springframework.org/schema/util" + xsi:schemaLocation="http://www.springframework.org/schema/integration/http + http://www.springframework.org/schema/integration/http/spring-integration-http.xsd + http://www.springframework.org/schema/integration + http://www.springframework.org/schema/integration/spring-integration.xsd + http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/util + http://www.springframework.org/schema/util/spring-util.xsd"> - + + + + + + - - + + diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/config/OutboundResponseTypeTests.java b/spring-integration-http/src/test/java/org/springframework/integration/http/config/OutboundResponseTypeTests.java index 6a4969bd27..16c2285e56 100644 --- a/spring-integration-http/src/test/java/org/springframework/integration/http/config/OutboundResponseTypeTests.java +++ b/spring-integration-http/src/test/java/org/springframework/integration/http/config/OutboundResponseTypeTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,6 +15,7 @@ */ package org.springframework.integration.http.config; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; @@ -23,6 +24,8 @@ import static org.junit.Assert.fail; import java.io.IOException; import java.io.OutputStream; import java.net.InetSocketAddress; +import java.util.Collections; +import java.util.Map; import org.hamcrest.Matchers; import org.junit.AfterClass; @@ -30,25 +33,26 @@ import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; +import com.sun.net.httpserver.Headers; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; + import org.springframework.beans.BeansException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.parsing.BeanDefinitionParsingException; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; -import org.springframework.messaging.MessageHandlingException; import org.springframework.integration.channel.QueueChannel; import org.springframework.integration.test.util.SocketUtils; import org.springframework.messaging.Message; import org.springframework.messaging.MessageChannel; +import org.springframework.messaging.MessageHandlingException; import org.springframework.messaging.support.GenericMessage; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import com.sun.net.httpserver.HttpExchange; -import com.sun.net.httpserver.HttpHandler; -import com.sun.net.httpserver.HttpServer; - /** * @author Oleg Zhurakousky * @author Artem Bilan @@ -87,6 +91,9 @@ public class OutboundResponseTypeTests { @Autowired private MessageChannel invalidResponseTypeChannel; + @Autowired + private MessageChannel contentTypePropagationChannel; + private static int port = SocketUtils.findAvailableServerSocket(); @BeforeClass @@ -160,8 +167,8 @@ public class OutboundResponseTypeTests { assertThat(e, Matchers.instanceOf(MessageHandlingException.class)); Throwable t = e.getCause(); assertThat(t, Matchers.instanceOf(IllegalArgumentException.class)); - assertThat(t.getMessage(), - Matchers.containsString("'expectedResponseType' can be an instance of 'Class', 'String' or 'ParameterizedTypeReference'")); + assertThat(t.getMessage(), Matchers.containsString("'expectedResponseType' can be an instance of " + + "'Class', 'String' or 'ParameterizedTypeReference'")); } } @@ -173,20 +180,31 @@ public class OutboundResponseTypeTests { } catch (BeansException e) { assertTrue(e instanceof BeanDefinitionParsingException); - assertTrue(e.getMessage().contains("The 'expected-response-type' and 'expected-response-type-expression' are mutually exclusive")); + assertTrue(e.getMessage().contains("The 'expected-response-type' " + + "and 'expected-response-type-expression' are mutually exclusive")); } } + @Test + public void testContentTypePropagation() throws Exception { + this.contentTypePropagationChannel + .send(new GenericMessage>(Collections.singletonMap("foo", "bar"))); + assertEquals(MediaType.APPLICATION_JSON.toString(), httpHandler.requestHeaders.getFirst("Content-Type")); + } + static class MyHandler implements HttpHandler { private String httpMethod = "POST"; + private volatile Headers requestHeaders; + public void setHttpMethod(String httpMethod) { this.httpMethod = httpMethod; } public void handle(HttpExchange t) throws IOException { String requestMethod = t.getRequestMethod(); + requestHeaders = t.getRequestHeaders(); String response = null; if (requestMethod.equalsIgnoreCase(this.httpMethod)) { response = httpMethod; @@ -202,6 +220,7 @@ public class OutboundResponseTypeTests { os.write(response.getBytes()); os.close(); } + } public static class Port { 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 b696a5d40e..1d7dd4dce6 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 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,6 +25,7 @@ import java.nio.charset.Charset; import java.nio.charset.UnsupportedCharsetException; import java.text.ParseException; import java.text.SimpleDateFormat; +import java.util.Arrays; import java.util.Calendar; import java.util.Collections; import java.util.Date; @@ -33,15 +34,16 @@ import java.util.Locale; import java.util.Map; import java.util.TimeZone; +import org.junit.Ignore; import org.junit.Test; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageHeaders; import org.springframework.integration.mapping.HeaderMapper; import org.springframework.integration.support.MessageBuilder; -import org.springframework.util.CollectionUtils; +import org.springframework.messaging.Message; +import org.springframework.messaging.MessageHeaders; +import org.springframework.util.StopWatch; /** * @author Oleg Zhurakousky @@ -53,9 +55,9 @@ import org.springframework.util.CollectionUtils; public class DefaultHttpHeaderMapperFromMessageOutboundTests { // ACCEPT tests - @Test(expected=IllegalArgumentException.class) - public void validateAcceptHeaderWithNoSlash(){ - HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); + @Test(expected = IllegalArgumentException.class) + public void validateAcceptHeaderWithNoSlash() { + HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); Map messageHeaders = new HashMap(); messageHeaders.put("Accept", "bar"); HttpHeaders headers = new HttpHeaders(); @@ -64,8 +66,8 @@ public class DefaultHttpHeaderMapperFromMessageOutboundTests { } @Test - public void validateAcceptHeaderSingleString(){ - HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); + public void validateAcceptHeaderSingleString() { + HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); Map messageHeaders = new HashMap(); messageHeaders.put("Accept", "bar/foo"); @@ -77,8 +79,8 @@ public class DefaultHttpHeaderMapperFromMessageOutboundTests { } @Test - public void validateAcceptHeaderSingleMediaType(){ - HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); + public void validateAcceptHeaderSingleMediaType() { + HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); Map messageHeaders = new HashMap(); messageHeaders.put("Accept", new MediaType("bar", "foo")); @@ -90,8 +92,8 @@ public class DefaultHttpHeaderMapperFromMessageOutboundTests { } @Test - public void validateAcceptHeaderMultipleAsDelimitedString(){ - HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); + public void validateAcceptHeaderMultipleAsDelimitedString() { + HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); Map messageHeaders = new HashMap(); messageHeaders.put("Accept", "bar/foo, text/xml"); HttpHeaders headers = new HttpHeaders(); @@ -103,10 +105,10 @@ public class DefaultHttpHeaderMapperFromMessageOutboundTests { } @Test - public void validateAcceptHeaderMultipleAsStringArray(){ - HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); + public void validateAcceptHeaderMultipleAsStringArray() { + HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); Map messageHeaders = new HashMap(); - messageHeaders.put("Accept", new String[]{"bar/foo", "text/xml"}); + messageHeaders.put("Accept", new String[] {"bar/foo", "text/xml"}); HttpHeaders headers = new HttpHeaders(); mapper.fromHeaders(new MessageHeaders(messageHeaders), headers); @@ -116,10 +118,10 @@ public class DefaultHttpHeaderMapperFromMessageOutboundTests { } @Test - public void validateAcceptHeaderMultipleAsStringCollection(){ - HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); + public void validateAcceptHeaderMultipleAsStringCollection() { + HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); Map messageHeaders = new HashMap(); - messageHeaders.put("Accept", CollectionUtils.arrayToList(new String[]{"bar/foo", "text/xml"})); + messageHeaders.put("Accept", Arrays.asList("bar/foo", "text/xml")); HttpHeaders headers = new HttpHeaders(); mapper.fromHeaders(new MessageHeaders(messageHeaders), headers); @@ -129,10 +131,10 @@ public class DefaultHttpHeaderMapperFromMessageOutboundTests { } @Test - public void validateAcceptHeaderMultipleAsStringCollectionCaseInsensitive(){ - HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); + public void validateAcceptHeaderMultipleAsStringCollectionCaseInsensitive() { + HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); Map messageHeaders = new HashMap(); - messageHeaders.put("acCePt", CollectionUtils.arrayToList(new String[]{"bar/foo", "text/xml"})); + messageHeaders.put("acCePt", Arrays.asList("bar/foo", "text/xml")); HttpHeaders headers = new HttpHeaders(); mapper.fromHeaders(new MessageHeaders(messageHeaders), headers); @@ -142,11 +144,10 @@ public class DefaultHttpHeaderMapperFromMessageOutboundTests { } @Test - public void validateAcceptHeaderMultipleAsMediatypeCollection(){ - HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); + public void validateAcceptHeaderMultipleAsMediatypeCollection() { + HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); Map messageHeaders = new HashMap(); - messageHeaders.put("Accept", - CollectionUtils.arrayToList(new MediaType[]{new MediaType("bar", "foo"), new MediaType("text", "xml")})); + messageHeaders.put("Accept", Arrays.asList(new MediaType("bar", "foo"), new MediaType("text", "xml"))); HttpHeaders headers = new HttpHeaders(); mapper.fromHeaders(new MessageHeaders(messageHeaders), headers); @@ -157,9 +158,9 @@ public class DefaultHttpHeaderMapperFromMessageOutboundTests { // ACCEPT_CHARSET tests - @Test(expected=UnsupportedCharsetException.class) - public void validateAcceptCharsetHeaderWithWrongCharset(){ - HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); + @Test(expected = UnsupportedCharsetException.class) + public void validateAcceptCharsetHeaderWithWrongCharset() { + HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); Map messageHeaders = new HashMap(); messageHeaders.put("Accept-Charset", "foo"); HttpHeaders headers = new HttpHeaders(); @@ -167,8 +168,8 @@ public class DefaultHttpHeaderMapperFromMessageOutboundTests { } @Test - public void validateAcceptCharsetHeaderSingleString(){ - HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); + public void validateAcceptCharsetHeaderSingleString() { + HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); Map messageHeaders = new HashMap(); messageHeaders.put("Accept-Charset", "UTF-8"); HttpHeaders headers = new HttpHeaders(); @@ -179,8 +180,8 @@ public class DefaultHttpHeaderMapperFromMessageOutboundTests { } @Test - public void validateAcceptCharsetHeaderSingleCharset(){ - HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); + public void validateAcceptCharsetHeaderSingleCharset() { + HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); Map messageHeaders = new HashMap(); messageHeaders.put("Accept-Charset", Charset.forName("UTF-8")); HttpHeaders headers = new HttpHeaders(); @@ -191,8 +192,8 @@ public class DefaultHttpHeaderMapperFromMessageOutboundTests { } @Test - public void validateAcceptCharsetHeaderMultipleAsDelimitedString(){ - HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); + public void validateAcceptCharsetHeaderMultipleAsDelimitedString() { + HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); Map messageHeaders = new HashMap(); messageHeaders.put("Accept-Charset", "UTF-8, ISO-8859-1"); HttpHeaders headers = new HttpHeaders(); @@ -205,10 +206,10 @@ public class DefaultHttpHeaderMapperFromMessageOutboundTests { } @Test - public void validateAcceptCharsetHeaderMultipleAsStringArray(){ - HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); + public void validateAcceptCharsetHeaderMultipleAsStringArray() { + HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); Map messageHeaders = new HashMap(); - messageHeaders.put("Accept-Charset", new String[]{"UTF-8", "ISO-8859-1"}); + messageHeaders.put("Accept-Charset", new String[] {"UTF-8", "ISO-8859-1"}); HttpHeaders headers = new HttpHeaders(); mapper.fromHeaders(new MessageHeaders(messageHeaders), headers); @@ -219,10 +220,10 @@ public class DefaultHttpHeaderMapperFromMessageOutboundTests { } @Test - public void validateAcceptCharsetHeaderMultipleAsCharsetArray(){ - HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); + public void validateAcceptCharsetHeaderMultipleAsCharsetArray() { + HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); Map messageHeaders = new HashMap(); - messageHeaders.put("Accept-Charset", new Charset[]{ Charset.forName("UTF-8"), Charset.forName("ISO-8859-1") }); + messageHeaders.put("Accept-Charset", new Charset[] {Charset.forName("UTF-8"), Charset.forName("ISO-8859-1")}); HttpHeaders headers = new HttpHeaders(); mapper.fromHeaders(new MessageHeaders(messageHeaders), headers); @@ -233,10 +234,10 @@ public class DefaultHttpHeaderMapperFromMessageOutboundTests { } @Test - public void validateAcceptCharsetHeaderMultipleAsCollectionOfStrings(){ - HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); + public void validateAcceptCharsetHeaderMultipleAsCollectionOfStrings() { + HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); Map messageHeaders = new HashMap(); - messageHeaders.put("Accept-Charset", CollectionUtils.arrayToList(new String[]{"UTF-8", "ISO-8859-1"})); + messageHeaders.put("Accept-Charset", Arrays.asList("UTF-8", "ISO-8859-1")); HttpHeaders headers = new HttpHeaders(); mapper.fromHeaders(new MessageHeaders(messageHeaders), headers); @@ -247,11 +248,10 @@ public class DefaultHttpHeaderMapperFromMessageOutboundTests { } @Test - public void validateAcceptCharsetHeaderMultipleAsCollectionOfCharsets(){ - HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); + public void validateAcceptCharsetHeaderMultipleAsCollectionOfCharsets() { + HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); Map messageHeaders = new HashMap(); - messageHeaders.put("Accept-Charset", - CollectionUtils.arrayToList(new Charset[]{Charset.forName("UTF-8"), Charset.forName("ISO-8859-1")})); + messageHeaders.put("Accept-Charset", Arrays.asList(Charset.forName("UTF-8"), Charset.forName("ISO-8859-1"))); HttpHeaders headers = new HttpHeaders(); mapper.fromHeaders(new MessageHeaders(messageHeaders), headers); @@ -264,8 +264,8 @@ public class DefaultHttpHeaderMapperFromMessageOutboundTests { // Cache-Control tests @Test - public void validateCacheControl(){ - HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); + public void validateCacheControl() { + HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); Map messageHeaders = new HashMap(); messageHeaders.put("Cache-Control", "foo"); HttpHeaders headers = new HttpHeaders(); @@ -277,8 +277,8 @@ public class DefaultHttpHeaderMapperFromMessageOutboundTests { // Content-Length tests @Test - public void validateContentLengthAsString(){ - HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); + public void validateContentLengthAsString() { + HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); Map messageHeaders = new HashMap(); messageHeaders.put("Content-Length", "1"); HttpHeaders headers = new HttpHeaders(); @@ -288,8 +288,8 @@ public class DefaultHttpHeaderMapperFromMessageOutboundTests { } @Test - public void validateContentLengthAsNumber(){ - HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); + public void validateContentLengthAsNumber() { + HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); Map messageHeaders = new HashMap(); messageHeaders.put("Content-Length", 1); HttpHeaders headers = new HttpHeaders(); @@ -298,9 +298,9 @@ public class DefaultHttpHeaderMapperFromMessageOutboundTests { assertEquals(1, headers.getContentLength()); } - @Test(expected=NumberFormatException.class) - public void validateContentLengthAsNonNumericString(){ - HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); + @Test(expected = NumberFormatException.class) + public void validateContentLengthAsNonNumericString() { + HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); Map messageHeaders = new HashMap(); messageHeaders.put("Content-Length", "foo"); HttpHeaders headers = new HttpHeaders(); @@ -310,19 +310,19 @@ public class DefaultHttpHeaderMapperFromMessageOutboundTests { // Content-Type test - @Test(expected=IllegalArgumentException.class) - public void validateContentTypeWrongValue(){ - HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); + @Test(expected = IllegalArgumentException.class) + public void validateContentTypeWrongValue() { + HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); Map messageHeaders = new HashMap(); - messageHeaders.put("Content-Type", "foo"); + messageHeaders.put(MessageHeaders.CONTENT_TYPE, "foo"); HttpHeaders headers = new HttpHeaders(); mapper.fromHeaders(new MessageHeaders(messageHeaders), headers); } @Test - public void validateContentTypeAsString(){ - HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); + public void validateContentTypeAsString() { + HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); Map messageHeaders = new HashMap(); messageHeaders.put("Content-Type", "text/html"); HttpHeaders headers = new HttpHeaders(); @@ -333,10 +333,10 @@ public class DefaultHttpHeaderMapperFromMessageOutboundTests { } @Test - public void validateContentTypeAsMediaType(){ - HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); + public void validateContentTypeAsMediaType() { + HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); Map messageHeaders = new HashMap(); - messageHeaders.put("Content-Type", new MediaType("text", "html")); + messageHeaders.put(MessageHeaders.CONTENT_TYPE, new MediaType("text", "html")); HttpHeaders headers = new HttpHeaders(); mapper.fromHeaders(new MessageHeaders(messageHeaders), headers); @@ -347,8 +347,8 @@ public class DefaultHttpHeaderMapperFromMessageOutboundTests { // Date test @Test - public void validateDateAsNumber() throws ParseException{ - HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); + public void validateDateAsNumber() throws ParseException { + HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); Map messageHeaders = new HashMap(); messageHeaders.put("Date", 12345678); HttpHeaders headers = new HttpHeaders(); @@ -360,8 +360,8 @@ public class DefaultHttpHeaderMapperFromMessageOutboundTests { } @Test - public void validateDateAsString() throws ParseException{ - HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); + public void validateDateAsString() throws ParseException { + HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); Map messageHeaders = new HashMap(); messageHeaders.put("Date", "12345678"); HttpHeaders headers = new HttpHeaders(); @@ -371,9 +371,10 @@ public class DefaultHttpHeaderMapperFromMessageOutboundTests { assertEquals(simpleDateFormat.parse("Thu, 01 Jan 1970 03:25:45 GMT").getTime(), headers.getDate()); } + @Test - public void validateDateAsDate() throws ParseException{ - HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); + public void validateDateAsDate() throws ParseException { + HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); Map messageHeaders = new HashMap(); messageHeaders.put("Date", new Date(12345678)); HttpHeaders headers = new HttpHeaders(); @@ -387,8 +388,8 @@ public class DefaultHttpHeaderMapperFromMessageOutboundTests { // If-Modified-Since tests @Test - public void validateIfModifiedSinceAsNumber() throws ParseException{ - HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); + public void validateIfModifiedSinceAsNumber() throws ParseException { + HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); Map messageHeaders = new HashMap(); messageHeaders.put("If-Modified-Since", 12345678); HttpHeaders headers = new HttpHeaders(); @@ -400,8 +401,8 @@ public class DefaultHttpHeaderMapperFromMessageOutboundTests { } @Test - public void validateIfModifiedSinceAsString() throws ParseException{ - HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); + public void validateIfModifiedSinceAsString() throws ParseException { + HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); Map messageHeaders = new HashMap(); messageHeaders.put("If-Modified-Since", "12345678"); HttpHeaders headers = new HttpHeaders(); @@ -411,9 +412,10 @@ public class DefaultHttpHeaderMapperFromMessageOutboundTests { assertEquals(simpleDateFormat.parse("Thu, 01 Jan 1970 03:25:45 GMT").getTime(), headers.getIfModifiedSince()); } + @Test - public void validateIfModifiedSinceAsDate() throws ParseException{ - HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); + public void validateIfModifiedSinceAsDate() throws ParseException { + HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); Map messageHeaders = new HashMap(); messageHeaders.put("If-Modified-Since", new Date(12345678)); HttpHeaders headers = new HttpHeaders(); @@ -427,8 +429,8 @@ public class DefaultHttpHeaderMapperFromMessageOutboundTests { // If-None-Match @Test - public void validateIfNoneMatch() throws ParseException{ - HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); + public void validateIfNoneMatch() throws ParseException { + HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); Map messageHeaders = new HashMap(); messageHeaders.put("If-None-Match", "1234567"); HttpHeaders headers = new HttpHeaders(); @@ -439,8 +441,8 @@ public class DefaultHttpHeaderMapperFromMessageOutboundTests { } @Test - public void validateIfNoneMatchAsDelimitedString() throws ParseException{ - HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); + public void validateIfNoneMatchAsDelimitedString() throws ParseException { + HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); Map messageHeaders = new HashMap(); messageHeaders.put("If-None-Match", "1234567, 123"); HttpHeaders headers = new HttpHeaders(); @@ -452,10 +454,10 @@ public class DefaultHttpHeaderMapperFromMessageOutboundTests { } @Test - public void validateIfNoneMatchAsStringArray() throws ParseException{ - HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); + public void validateIfNoneMatchAsStringArray() throws ParseException { + HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); Map messageHeaders = new HashMap(); - messageHeaders.put("If-None-Match", new String[]{"1234567", "123"}); + messageHeaders.put("If-None-Match", new String[] {"1234567", "123"}); HttpHeaders headers = new HttpHeaders(); mapper.fromHeaders(new MessageHeaders(messageHeaders), headers); @@ -465,8 +467,8 @@ public class DefaultHttpHeaderMapperFromMessageOutboundTests { } @Test - public void validateIfNoneMatchAsCommaDelimitedString() throws ParseException{ - HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); + public void validateIfNoneMatchAsCommaDelimitedString() throws ParseException { + HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); Map messageHeaders = new HashMap(); messageHeaders.put("If-None-Match", "1234567, 123"); HttpHeaders headers = new HttpHeaders(); @@ -478,10 +480,10 @@ public class DefaultHttpHeaderMapperFromMessageOutboundTests { } @Test - public void validateIfNoneMatchAsStringCollection() throws ParseException{ - HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); + public void validateIfNoneMatchAsStringCollection() throws ParseException { + HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); Map messageHeaders = new HashMap(); - messageHeaders.put("If-None-Match", CollectionUtils.arrayToList(new String[]{"1234567", "123"})); + messageHeaders.put("If-None-Match", Arrays.asList("1234567", "123")); HttpHeaders headers = new HttpHeaders(); mapper.fromHeaders(new MessageHeaders(messageHeaders), headers); @@ -492,8 +494,8 @@ public class DefaultHttpHeaderMapperFromMessageOutboundTests { // Pragma tests @Test - public void validatePragma() throws ParseException{ - HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); + public void validatePragma() throws ParseException { + HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); Map messageHeaders = new HashMap(); messageHeaders.put("Pragma", "foo"); HttpHeaders headers = new HttpHeaders(); @@ -503,8 +505,8 @@ public class DefaultHttpHeaderMapperFromMessageOutboundTests { // Transfer-Encoding tests @Test - public void validateTransferEncoding() throws ParseException{ - HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); + public void validateTransferEncoding() throws ParseException { + HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); Map messageHeaders = new HashMap(); messageHeaders.put("Transfer-Encoding", "chunked"); HttpHeaders headers = new HttpHeaders(); @@ -513,8 +515,8 @@ public class DefaultHttpHeaderMapperFromMessageOutboundTests { } @Test - public void validateTransferEncodingToHeaders() throws ParseException{ - HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); + public void validateTransferEncodingToHeaders() throws ParseException { + HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); HttpHeaders httpHeaders = new HttpHeaders(); httpHeaders.set("Transfer-Encoding", "chunked"); @@ -524,11 +526,36 @@ public class DefaultHttpHeaderMapperFromMessageOutboundTests { } + @Test + @Ignore + public void perf() throws ParseException { + HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); + + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.set("Transfer-Encoding", "chunked"); + httpHeaders.set("X-Transfer-Encoding1", "chunked"); + httpHeaders.set("X-Transfer-Encoding2", "chunked"); + httpHeaders.set("X-Transfer-Encoding3", "chunked"); + httpHeaders.set("X-Transfer-Encoding4", "chunked"); + httpHeaders.set("X-Transfer-Encoding5", "chunked"); + httpHeaders.set("X-Transfer-Encoding6", "chunked"); + httpHeaders.set("X-Transfer-Encoding7", "chunked"); + + StopWatch watch = new StopWatch(); + watch.start(); + for (int i = 0; i < 100000; i++) { + mapper.toHeaders(httpHeaders); + } + watch.stop(); + System.out.println(watch.getTotalTimeMillis()); + + } + // Custom headers @Test - public void validateCustomHeaderWithNoHeaderNames() throws ParseException{ - DefaultHttpHeaderMapper mapper = new DefaultHttpHeaderMapper(); + public void validateCustomHeaderWithNoHeaderNames() throws ParseException { + DefaultHttpHeaderMapper mapper = new DefaultHttpHeaderMapper(); Map messageHeaders = new HashMap(); messageHeaders.put("foo", "foo"); HttpHeaders headers = new HttpHeaders(); @@ -538,9 +565,9 @@ public class DefaultHttpHeaderMapperFromMessageOutboundTests { } @Test - public void validateCustomHeaderWithHeaderNames() throws ParseException{ - DefaultHttpHeaderMapper mapper = new DefaultHttpHeaderMapper(); - mapper.setOutboundHeaderNames(new String[]{"foo"}); + public void validateCustomHeaderWithHeaderNames() throws ParseException { + DefaultHttpHeaderMapper mapper = new DefaultHttpHeaderMapper(); + mapper.setOutboundHeaderNames(new String[] {"foo"}); Map messageHeaders = new HashMap(); messageHeaders.put("foo", "foo"); HttpHeaders headers = new HttpHeaders(); @@ -552,9 +579,9 @@ public class DefaultHttpHeaderMapperFromMessageOutboundTests { } @Test - public void validateCustomHeaderWithHeaderNamePatterns() throws ParseException{ - DefaultHttpHeaderMapper mapper = new DefaultHttpHeaderMapper(); - mapper.setOutboundHeaderNames(new String[]{"x*", "*z", "a*f"}); + 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"); @@ -579,9 +606,9 @@ public class DefaultHttpHeaderMapperFromMessageOutboundTests { } @Test - public void validateCustomHeaderWithHeaderNamePatternsAndStandardRequestHeaders() throws ParseException{ - DefaultHttpHeaderMapper mapper = new DefaultHttpHeaderMapper(); - mapper.setOutboundHeaderNames(new String[]{"foo*", "HTTP_REQUEST_HEADERS"}); + public void validateCustomHeaderWithHeaderNamePatternsAndStandardRequestHeaders() throws ParseException { + DefaultHttpHeaderMapper mapper = new DefaultHttpHeaderMapper(); + mapper.setOutboundHeaderNames(new String[] {"foo*", "HTTP_REQUEST_HEADERS"}); Map messageHeaders = new HashMap(); messageHeaders.put("foobar", "abc"); messageHeaders.put("Content-Type", "text/html"); @@ -597,9 +624,9 @@ public class DefaultHttpHeaderMapperFromMessageOutboundTests { } @Test - public void validateCustomHeaderWithHeaderNamePatternsAndStandardResponseHeaders() throws ParseException{ - DefaultHttpHeaderMapper mapper = new DefaultHttpHeaderMapper(); - mapper.setInboundHeaderNames(new String[]{"foo*", "HTTP_RESPONSE_HEADERS"}); + public void validateCustomHeaderWithHeaderNamePatternsAndStandardResponseHeaders() throws ParseException { + DefaultHttpHeaderMapper mapper = new DefaultHttpHeaderMapper(); + mapper.setInboundHeaderNames(new String[] {"foo*", "HTTP_RESPONSE_HEADERS"}); HttpHeaders httpHeaders = new HttpHeaders(); httpHeaders.set("foobar", "abc"); httpHeaders.setContentType(MediaType.TEXT_HTML); @@ -608,11 +635,11 @@ public class DefaultHttpHeaderMapperFromMessageOutboundTests { assertEquals(2, messageHeaders.size()); assertNull(messageHeaders.get("Accept")); assertEquals("abc", messageHeaders.get("foobar")); - assertEquals("text/html", messageHeaders.get("Content-Type").toString()); + assertEquals("text/html", messageHeaders.get(MessageHeaders.CONTENT_TYPE).toString()); } @Test - public void validateCustomHeaderWithStandardPrefix() throws Exception{ + public void validateCustomHeaderWithStandardPrefix() throws Exception { DefaultHttpHeaderMapper mapper = new DefaultHttpHeaderMapper(); mapper.setInboundHeaderNames(new String[] {"X-Foo"}); HttpHeaders headers = new HttpHeaders(); @@ -623,7 +650,7 @@ public class DefaultHttpHeaderMapperFromMessageOutboundTests { } @Test - public void validateCustomHeaderWithStandardPrefixSameCase() throws Exception{ + public void validateCustomHeaderWithStandardPrefixSameCase() throws Exception { DefaultHttpHeaderMapper mapper = new DefaultHttpHeaderMapper(); mapper.setInboundHeaderNames(new String[] {"X-Foo"}); HttpHeaders headers = new HttpHeaders(); @@ -632,38 +659,40 @@ public class DefaultHttpHeaderMapperFromMessageOutboundTests { assertEquals(1, result.size()); assertEquals("x-foo-value", result.get("X-Foo")); } - @Test - public void validateCustomHeaderCaseInsensitivity() throws ParseException{ - DefaultHttpHeaderMapper mapper = new DefaultHttpHeaderMapper(); - mapper.setOutboundHeaderNames(new String[]{"*", "HTTP_REQUEST_HEADERS"}); - Map messageHeaders = new HashMap(); - messageHeaders.put("foobar", "abc"); - messageHeaders.put("X-bar", "xbar"); - messageHeaders.put("x-baz", "xbaz"); - messageHeaders.put("Content-Type", "text/html"); - messageHeaders.put("Accept", "text/xml"); - HttpHeaders headers = new HttpHeaders(); - mapper.fromHeaders(new MessageHeaders(messageHeaders), headers); - assertEquals(5, headers.size()); - assertEquals(1, headers.get("X-foobar").size()); - assertEquals(1, headers.get("x-foobar").size()); - assertEquals(1, headers.get("X-bar").size()); - assertEquals(1, headers.get("x-bar").size()); - assertEquals(1, headers.get("X-baz").size()); - assertEquals(1, headers.get("x-baz").size()); - } - @Test - public void dontPropagateContentLength() { - DefaultHttpHeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); - // not suppressed on outbound request, by default - mapper.setExcludedOutboundStandardRequestHeaderNames(new String[] {"Content-Length"}); - Map messageHeaders = new HashMap(); - messageHeaders.put("Content-Length", 4); - HttpHeaders headers = new HttpHeaders(); - mapper.fromHeaders(new MessageHeaders(messageHeaders), headers); - assertNull(headers.get("Content-Length")); - } + @Test + public void validateCustomHeaderCaseInsensitivity() throws ParseException { + DefaultHttpHeaderMapper mapper = new DefaultHttpHeaderMapper(); + mapper.setOutboundHeaderNames(new String[] {"*", "HTTP_REQUEST_HEADERS"}); + Map messageHeaders = new HashMap(); + messageHeaders.put("foobar", "abc"); + messageHeaders.put("X-bar", "xbar"); + messageHeaders.put("x-baz", "xbaz"); + messageHeaders.put("Content-Type", "text/html"); + messageHeaders.put("Accept", "text/xml"); + HttpHeaders headers = new HttpHeaders(); + mapper.fromHeaders(new MessageHeaders(messageHeaders), headers); + assertEquals(5, headers.size()); + assertEquals(1, headers.get("X-foobar").size()); + assertEquals(1, headers.get("x-foobar").size()); + assertEquals(1, headers.get("X-bar").size()); + assertEquals(1, headers.get("x-bar").size()); + assertEquals(1, headers.get("X-baz").size()); + assertEquals(1, headers.get("x-baz").size()); + } + + @Test + public void dontPropagateContentLength() { + DefaultHttpHeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); + // not suppressed on outbound request, by default + mapper.setExcludedOutboundStandardRequestHeaderNames(new String[] {"Content-Length"}); + Map messageHeaders = new HashMap(); + messageHeaders.put("Content-Length", 4); + + HttpHeaders headers = new HttpHeaders(); + mapper.fromHeaders(new MessageHeaders(messageHeaders), headers); + assertNull(headers.get("Content-Length")); + } @Test public void testInt3063InvalidExpiresHeader() { @@ -674,13 +703,13 @@ public class DefaultHttpHeaderMapperFromMessageOutboundTests { } @Test - public void testInt2995IfModifiedSince() throws Exception{ + public void testInt2995IfModifiedSince() throws Exception { Date ifModifiedSince = new Date(); SimpleDateFormat dateFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy", Locale.US); dateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); String value = dateFormat.format(ifModifiedSince); Message testMessage = MessageBuilder.withPayload("foo").setHeader("If-Modified-Since", value).build(); - HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); + HeaderMapper mapper = DefaultHttpHeaderMapper.outboundMapper(); HttpHeaders headers = new HttpHeaders(); mapper.fromHeaders(testMessage.getHeaders(), headers); Calendar c = Calendar.getInstance(); @@ -690,7 +719,7 @@ public class DefaultHttpHeaderMapperFromMessageOutboundTests { } @Test - public void testContentDispositionHeader() throws Exception{ + public void testContentDispositionHeader() throws Exception { HttpHeaders headers = new HttpHeaders(); String headerValue = "attachment; filename=\"test.txt\""; headers.set("Content-Disposition", headerValue);