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 d6ea869c59..d1b1158b22 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 @@ -73,110 +73,109 @@ import org.springframework.util.StringUtils; */ public class DefaultHttpHeaderMapper implements HeaderMapper, BeanFactoryAware, InitializingBean { - private static final Log logger = LogFactory.getLog(DefaultHttpHeaderMapper.class); + protected final Log logger = LogFactory.getLog(getClass()); + public static final String ACCEPT = "Accept"; - private static final String ACCEPT = "Accept"; + public static final String ACCEPT_CHARSET = "Accept-Charset"; - private static final String ACCEPT_CHARSET = "Accept-Charset"; + public static final String ACCEPT_ENCODING = "Accept-Encoding"; - private static final String ACCEPT_ENCODING = "Accept-Encoding"; + public static final String ACCEPT_LANGUAGE = "Accept-Language"; - private static final String ACCEPT_LANGUAGE = "Accept-Language"; + public static final String ACCEPT_RANGES = "Accept-Ranges"; - private static final String ACCEPT_RANGES = "Accept-Ranges"; + public static final String AGE = "Age"; - private static final String AGE = "Age"; + public static final String ALLOW = "Allow"; - private static final String ALLOW = "Allow"; + public static final String AUTHORIZATION = "Authorization"; - private static final String AUTHORIZATION = "Authorization"; + public static final String CACHE_CONTROL = "Cache-Control"; - private static final String CACHE_CONTROL = "Cache-Control"; + public static final String CONNECTION = "Connection"; - private static final String CONNECTION = "Connection"; + public static final String CONTENT_ENCODING = "Content-Encoding"; - private static final String CONTENT_ENCODING = "Content-Encoding"; + public static final String CONTENT_LANGUAGE = "Content-Language"; - private static final String CONTENT_LANGUAGE = "Content-Language"; + public static final String CONTENT_LENGTH = "Content-Length"; - private static final String CONTENT_LENGTH = "Content-Length"; + public static final String CONTENT_LOCATION = "Content-Location"; - private static final String CONTENT_LOCATION = "Content-Location"; + public static final String CONTENT_MD5 = "Content-MD5"; - private static final String CONTENT_MD5 = "Content-MD5"; + public static final String CONTENT_RANGE = "Content-Range"; - private static final String CONTENT_RANGE = "Content-Range"; + public static final String CONTENT_TYPE = "Content-Type"; - private static final String CONTENT_TYPE = "Content-Type"; - - private static final String CONTENT_DISPOSITION = "Content-Disposition"; + public static final String CONTENT_DISPOSITION = "Content-Disposition"; public static final String COOKIE = "Cookie"; - private static final String DATE = "Date"; + public static final String DATE = "Date"; - private static final String ETAG = "ETag"; + public static final String ETAG = "ETag"; - private static final String EXPECT = "Expect"; + public static final String EXPECT = "Expect"; - private static final String EXPIRES = "Expires"; + public static final String EXPIRES = "Expires"; - private static final String FROM = "From"; + public static final String FROM = "From"; - private static final String HOST = "Host"; + public static final String HOST = "Host"; - private static final String IF_MATCH = "If-Match"; + public static final String IF_MATCH = "If-Match"; - private static final String IF_MODIFIED_SINCE = "If-Modified-Since"; + public static final String IF_MODIFIED_SINCE = "If-Modified-Since"; - private static final String IF_NONE_MATCH = "If-None-Match"; + public static final String IF_NONE_MATCH = "If-None-Match"; - private static final String IF_RANGE = "If-Range"; + public static final String IF_RANGE = "If-Range"; - private static final String IF_UNMODIFIED_SINCE = "If-Unmodified-Since"; + public static final String IF_UNMODIFIED_SINCE = "If-Unmodified-Since"; - private static final String LAST_MODIFIED = "Last-Modified"; + public static final String LAST_MODIFIED = "Last-Modified"; - private static final String LOCATION = "Location"; + public static final String LOCATION = "Location"; - private static final String MAX_FORWARDS = "Max-Forwards"; + public static final String MAX_FORWARDS = "Max-Forwards"; - private static final String PRAGMA = "Pragma"; + public static final String PRAGMA = "Pragma"; - private static final String PROXY_AUTHENTICATE = "Proxy-Authenticate"; + public static final String PROXY_AUTHENTICATE = "Proxy-Authenticate"; - private static final String PROXY_AUTHORIZATION = "Proxy-Authorization"; + public static final String PROXY_AUTHORIZATION = "Proxy-Authorization"; - private static final String RANGE = "Range"; + public static final String RANGE = "Range"; - private static final String REFERER = "Referer"; + public static final String REFERER = "Referer"; - private static final String REFRESH = "Refresh"; + public static final String REFRESH = "Refresh"; - private static final String RETRY_AFTER = "Retry-After"; + public static final String RETRY_AFTER = "Retry-After"; - private static final String SERVER = "Server"; + public static final String SERVER = "Server"; public static final String SET_COOKIE = "Set-Cookie"; - private static final String TE = "TE"; + public static final String TE = "TE"; - private static final String TRAILER = "Trailer"; + public static final String TRAILER = "Trailer"; - private static final String UPGRADE = "Upgrade"; + public static final String UPGRADE = "Upgrade"; - private static final String USER_AGENT = "User-Agent"; + public static final String USER_AGENT = "User-Agent"; - private static final String VARY = "Vary"; + public static final String VARY = "Vary"; - private static final String VIA = "Via"; + public static final String VIA = "Via"; - private static final String WARNING = "Warning"; + public static final String WARNING = "Warning"; - private static final String WWW_AUTHENTICATE = "WWW-Authenticate"; + public static final String WWW_AUTHENTICATE = "WWW-Authenticate"; - private static final String TRANSFER_ENCODING = "Transfer-Encoding"; + public static final String TRANSFER_ENCODING = "Transfer-Encoding"; private static final String[] HTTP_REQUEST_HEADER_NAMES = new String[] { ACCEPT, @@ -259,7 +258,7 @@ public class DefaultHttpHeaderMapper implements HeaderMapper, BeanF public static final String HTTP_RESPONSE_HEADER_NAME_PATTERN = "HTTP_RESPONSE_HEADERS"; // Copy of 'org.springframework.http.HttpHeaders#DATE_FORMATS' - private static final DateTimeFormatter[] DATE_FORMATS = new DateTimeFormatter[] { + protected static final DateTimeFormatter[] DATE_FORMATS = new DateTimeFormatter[] { DateTimeFormatter.ofPattern("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US).withZone(ZoneId.of("GMT")), DateTimeFormatter.ofPattern("EEE, dd-MMM-yy HH:mm:ss zzz", Locale.US).withZone(ZoneId.of("GMT")), DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss yyyy", Locale.US).withZone(ZoneId.of("GMT")) @@ -301,6 +300,10 @@ public class DefaultHttpHeaderMapper implements HeaderMapper, BeanF this.beanFactory = beanFactory; } + protected BeanFactory getBeanFactory() { + return this.beanFactory; + } + /** * 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. @@ -400,8 +403,8 @@ public class DefaultHttpHeaderMapper implements HeaderMapper, BeanF */ @Override public void fromHeaders(MessageHeaders headers, HttpHeaders target) { - if (logger.isDebugEnabled()) { - logger.debug(MessageFormat.format("outboundHeaderNames={0}", + if (this.logger.isDebugEnabled()) { + this.logger.debug(MessageFormat.format("outboundHeaderNames={0}", CollectionUtils.arrayToList(this.outboundHeaderNames))); } for (Entry entry : headers.entrySet()) { @@ -418,8 +421,8 @@ public class DefaultHttpHeaderMapper implements HeaderMapper, BeanF name = StringUtils.startsWithIgnoreCase(name, this.userDefinedHeaderPrefix) ? name : this.userDefinedHeaderPrefix + name; } - if (logger.isDebugEnabled()) { - logger.debug(MessageFormat.format("setting headerName=[{0}], value={1}", name, value)); + if (this.logger.isDebugEnabled()) { + this.logger.debug(MessageFormat.format("setting headerName=[{0}], value={1}", name, value)); } this.setHttpHeader(target, name, value); } @@ -434,8 +437,8 @@ public class DefaultHttpHeaderMapper implements HeaderMapper, BeanF */ @Override public Map toHeaders(HttpHeaders source) { - if (logger.isDebugEnabled()) { - logger.debug(MessageFormat.format("inboundHeaderNames={0}", + if (this.logger.isDebugEnabled()) { + this.logger.debug(MessageFormat.format("inboundHeaderNames={0}", CollectionUtils.arrayToList(this.inboundHeaderNames))); } Map target = new HashMap(); @@ -452,8 +455,8 @@ public class DefaultHttpHeaderMapper implements HeaderMapper, BeanF ? 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)); + if (this.logger.isDebugEnabled()) { + this.logger.debug(MessageFormat.format("setting headerName=[{0}], value={1}", name, value)); } this.setMessageHeader(target, name, value); } @@ -461,8 +464,8 @@ public class DefaultHttpHeaderMapper implements HeaderMapper, BeanF else { Object value = this.getHttpHeader(source, name); if (value != null) { - if (logger.isDebugEnabled()) { - logger.debug(MessageFormat.format("setting headerName=[{0}], value={1}", name, value)); + if (this.logger.isDebugEnabled()) { + this.logger.debug(MessageFormat.format("setting headerName=[{0}], value={1}", name, value)); } if (CONTENT_TYPE.equalsIgnoreCase(name)) { name = MessageHeaders.CONTENT_TYPE; @@ -482,7 +485,7 @@ public class DefaultHttpHeaderMapper implements HeaderMapper, BeanF } } - private boolean containsElementIgnoreCase(String[] headerNames, String name) { + protected final boolean containsElementIgnoreCase(String[] headerNames, String name) { for (String headerName : headerNames) { if (headerName.equalsIgnoreCase(name)) { return true; @@ -500,8 +503,8 @@ public class DefaultHttpHeaderMapper implements HeaderMapper, BeanF * mapping of exclusions for specific headers. */ if (this.containsElementIgnoreCase(this.excludedInboundStandardResponseHeaderNames, headerName)) { - if (logger.isDebugEnabled()) { - logger.debug(MessageFormat.format("headerName=[{0}] WILL NOT be mapped (excluded)", headerName)); + if (this.logger.isDebugEnabled()) { + this.logger.debug(MessageFormat.format("headerName=[{0}] WILL NOT be mapped (excluded)", headerName)); } return false; } @@ -513,8 +516,8 @@ public class DefaultHttpHeaderMapper implements HeaderMapper, BeanF * mapping of exclusions for specific headers. */ if (this.containsElementIgnoreCase(this.excludedOutboundStandardRequestHeaderNames, headerName)) { - if (logger.isDebugEnabled()) { - logger.debug(MessageFormat.format("headerName=[{0}] WILL NOT be mapped (excluded)", headerName)); + if (this.logger.isDebugEnabled()) { + this.logger.debug(MessageFormat.format("headerName=[{0}] WILL NOT be mapped (excluded)", headerName)); } return false; } @@ -522,7 +525,7 @@ public class DefaultHttpHeaderMapper implements HeaderMapper, BeanF return this.shouldMapHeader(headerName, outboundHeaderNamesLower); } - private boolean shouldMapInboundHeader(String headerName) { + protected final boolean shouldMapInboundHeader(String headerName) { return this.shouldMapHeader(headerName, this.inboundHeaderNamesLower); } @@ -535,32 +538,32 @@ public class DefaultHttpHeaderMapper implements HeaderMapper, BeanF if (patterns != null && patterns.length > 0) { for (String pattern : patterns) { if (PatternMatchUtils.simpleMatch(pattern, headerName)) { - if (logger.isDebugEnabled()) { - logger.debug(MessageFormat.format("headerName=[{0}] WILL be mapped, matched pattern={1}", + if (this.logger.isDebugEnabled()) { + this.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) && HTTP_REQUEST_HEADER_NAMES_LOWER.contains(headerName)) { - if (logger.isDebugEnabled()) { - logger.debug(MessageFormat.format("headerName=[{0}] WILL be mapped, matched pattern={1}", + if (this.logger.isDebugEnabled()) { + this.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) && HTTP_RESPONSE_HEADER_NAMES_LOWER.contains(headerName)) { - if (logger.isDebugEnabled()) { - logger.debug(MessageFormat.format("headerName=[{0}] WILL be mapped, matched pattern={1}", + if (this.logger.isDebugEnabled()) { + this.logger.debug(MessageFormat.format("headerName=[{0}] WILL be mapped, matched pattern={1}", headerName, pattern)); } return true; } } } - if (logger.isDebugEnabled()) { - logger.debug(MessageFormat.format("headerName=[{0}] WILL NOT be mapped", headerName)); + if (this.logger.isDebugEnabled()) { + this.logger.debug(MessageFormat.format("headerName=[{0}] WILL NOT be mapped", headerName)); } return false; } @@ -938,7 +941,7 @@ public class DefaultHttpHeaderMapper implements HeaderMapper, BeanF target.add(name, convertedValue); } else { - logger.warn("Element of the header '" + name + "' with value '" + value + + this.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., )"); } @@ -950,14 +953,14 @@ public class DefaultHttpHeaderMapper implements HeaderMapper, BeanF target.set(name, convertedValue); } else { - logger.warn("Header '" + name + "' with value '" + value + + this.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., )"); } } } - private Object getHttpHeader(HttpHeaders source, String name) { + protected Object getHttpHeader(HttpHeaders source, String name) { if (ACCEPT.equalsIgnoreCase(name)) { return source.getAccept(); } @@ -992,9 +995,7 @@ public class DefaultHttpHeaderMapper implements HeaderMapper, BeanF return (expires > -1) ? expires : null; } catch (Exception e) { - if (logger.isDebugEnabled()) { - logger.debug(e.getMessage()); - } + this.logger.debug(e.getMessage()); // According to RFC 2616 return null; } @@ -1052,7 +1053,7 @@ public class DefaultHttpHeaderMapper implements HeaderMapper, BeanF } } - private String convertToString(Object value) { + protected String convertToString(Object value) { if (this.conversionService != null && this.conversionService.canConvert(TypeDescriptor.forObject(value), TypeDescriptor.valueOf(String.class))) { @@ -1063,7 +1064,7 @@ public class DefaultHttpHeaderMapper implements HeaderMapper, BeanF // Utility methods - private long getFirstDate(String headerValue, String headerName) { + protected long getFirstDate(String headerValue, String headerName) { for (DateTimeFormatter dateFormat : DATE_FORMATS) { try { return dateFormat.parse(headerValue, ZonedDateTime::from) @@ -1078,7 +1079,7 @@ public class DefaultHttpHeaderMapper implements HeaderMapper, BeanF + "' header"); } - private String formatDate(long date) { + protected String formatDate(long date) { return DATE_FORMATS[0].format(Instant.ofEpochMilli(date)); } @@ -1090,10 +1091,19 @@ public class DefaultHttpHeaderMapper implements HeaderMapper, BeanF */ public static DefaultHttpHeaderMapper outboundMapper() { DefaultHttpHeaderMapper mapper = new DefaultHttpHeaderMapper(); + setupDefaultOutboundMapper(mapper); + return mapper; + } + + /** + * Subclasses can call this from a static outboundMapper() method to set up + * standard header mappings for an outbound mapper. + * @param mapper the mapper. + */ + protected static void setupDefaultOutboundMapper(DefaultHttpHeaderMapper mapper) { mapper.setOutboundHeaderNames(HTTP_REQUEST_HEADER_NAMES); mapper.setInboundHeaderNames(HTTP_RESPONSE_HEADER_NAMES); mapper.setExcludedOutboundStandardRequestHeaderNames(HTTP_REQUEST_HEADER_NAMES_OUTBOUND_EXCLUSIONS); - return mapper; } /** @@ -1104,10 +1114,19 @@ public class DefaultHttpHeaderMapper implements HeaderMapper, BeanF */ public static DefaultHttpHeaderMapper inboundMapper() { DefaultHttpHeaderMapper mapper = new DefaultHttpHeaderMapper(); - mapper.setInboundHeaderNames(HTTP_REQUEST_HEADER_NAMES); - mapper.setOutboundHeaderNames(HTTP_RESPONSE_HEADER_NAMES); - mapper.setExcludedInboundStandardResponseHeaderNames(HTTP_RESPONSE_HEADER_NAMES_INBOUND_EXCLUSIONS); + setupDefaultInboundMapper(mapper); return mapper; } + /** + * Subclasses can call this from a static inboundMapper() method to set up + * standard header mappings for an inbound mapper. + * @param mapper the mapper. + */ + protected static void setupDefaultInboundMapper(DefaultHttpHeaderMapper mapper) { + mapper.setInboundHeaderNames(HTTP_REQUEST_HEADER_NAMES); + mapper.setOutboundHeaderNames(HTTP_RESPONSE_HEADER_NAMES); + mapper.setExcludedInboundStandardResponseHeaderNames(HTTP_RESPONSE_HEADER_NAMES_INBOUND_EXCLUSIONS); + } + }