INT-3811: Support Negative Matches on Header Map
JIRA: https://jira.spring.io/browse/INT-3811 Polishing - PR Comments
This commit is contained in:
committed by
Artem Bilan
parent
583371007a
commit
edb30efcd5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -20,8 +20,8 @@ import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
@@ -139,7 +139,7 @@ public abstract class AbstractHeaderMapper<T> implements RequestReplyHeaderMappe
|
||||
* @return a header mapper that match if any of the specified patters match
|
||||
*/
|
||||
protected HeaderMatcher createHeaderMatcher(Collection<String> patterns) {
|
||||
Collection<HeaderMatcher> matchers = new ArrayList<HeaderMatcher>();
|
||||
List<HeaderMatcher> matchers = new ArrayList<HeaderMatcher>();
|
||||
for (String pattern : patterns) {
|
||||
if (STANDARD_REQUEST_HEADER_NAME_PATTERN.equals(pattern)) {
|
||||
matchers.add(new ContentBasedHeaderMatcher(true, this.requestHeaderNames));
|
||||
@@ -151,7 +151,22 @@ public abstract class AbstractHeaderMapper<T> implements RequestReplyHeaderMappe
|
||||
matchers.add(new PrefixBasedMatcher(false, this.standardHeaderPrefix));
|
||||
}
|
||||
else {
|
||||
matchers.add(new PatternBasedHeaderMatcher(Collections.singleton(pattern)));
|
||||
String thePattern = pattern;
|
||||
boolean negate = false;
|
||||
if (pattern.startsWith("!")) {
|
||||
thePattern = pattern.substring(1);
|
||||
negate = true;
|
||||
}
|
||||
else if (pattern.startsWith("\\!")) {
|
||||
thePattern = pattern.substring(1);
|
||||
}
|
||||
if (negate) {
|
||||
// negative matchers get priority
|
||||
matchers.add(0, new SinglePatternBasedHeaderMatcher(thePattern, negate));
|
||||
}
|
||||
else {
|
||||
matchers.add(new SinglePatternBasedHeaderMatcher(thePattern, negate));
|
||||
}
|
||||
}
|
||||
}
|
||||
return new CompositeHeaderMatcher(matchers);
|
||||
@@ -343,6 +358,12 @@ public abstract class AbstractHeaderMapper<T> implements RequestReplyHeaderMappe
|
||||
*/
|
||||
boolean matchHeader(String headerName);
|
||||
|
||||
/**
|
||||
* Return true if this match should be explicitly excluded from the mapping.
|
||||
* @return true if negated.
|
||||
*/
|
||||
boolean isNegated();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -388,11 +409,16 @@ public abstract class AbstractHeaderMapper<T> implements RequestReplyHeaderMappe
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNegated() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* A pattern-based {@link HeaderMatcher} that matches if the specified
|
||||
* header match one of the specified simple patterns.
|
||||
* header matches one of the specified simple patterns.
|
||||
* @see org.springframework.util.PatternMatchUtils#simpleMatch(String, String)
|
||||
* @since 4.1
|
||||
*/
|
||||
@@ -400,19 +426,21 @@ public abstract class AbstractHeaderMapper<T> implements RequestReplyHeaderMappe
|
||||
|
||||
private static final Log logger = LogFactory.getLog(HeaderMatcher.class);
|
||||
|
||||
private final Collection<String> patterns;
|
||||
private final Collection<String> patterns = new ArrayList<String>();
|
||||
|
||||
public PatternBasedHeaderMatcher(Collection<String> patterns) {
|
||||
Assert.notNull(patterns, "Patters must no be null");
|
||||
Assert.notNull(patterns, "Patterns must no be null");
|
||||
Assert.notEmpty(patterns, "At least one pattern must be specified");
|
||||
this.patterns = patterns;
|
||||
for (String pattern : patterns) {
|
||||
this.patterns.add(pattern.toLowerCase());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matchHeader(String headerName) {
|
||||
String header = headerName.toLowerCase();
|
||||
for (String pattern : this.patterns) {
|
||||
if (PatternMatchUtils.simpleMatch(pattern.toLowerCase(), header)) {
|
||||
if (PatternMatchUtils.simpleMatch(pattern, header)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(MessageFormat.format(
|
||||
"headerName=[{0}] WILL be mapped, matched pattern={1}", headerName, pattern));
|
||||
@@ -423,6 +451,56 @@ public abstract class AbstractHeaderMapper<T> implements RequestReplyHeaderMappe
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNegated() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* A pattern-based {@link HeaderMatcher} that matches if the specified
|
||||
* header matches the specified simple pattern.
|
||||
* <p> The {@code negate == true} state indicates if the matching should be treated as "not matched".
|
||||
* @see org.springframework.util.PatternMatchUtils#simpleMatch(String, String)
|
||||
* @since 4.3
|
||||
*/
|
||||
protected static class SinglePatternBasedHeaderMatcher implements HeaderMatcher {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(HeaderMatcher.class);
|
||||
|
||||
private final String pattern;
|
||||
|
||||
private final boolean negate;
|
||||
|
||||
public SinglePatternBasedHeaderMatcher(String pattern) {
|
||||
this(pattern, false);
|
||||
}
|
||||
|
||||
public SinglePatternBasedHeaderMatcher(String pattern, boolean negate) {
|
||||
Assert.notNull(pattern, "Pattern must no be null");
|
||||
this.pattern = pattern.toLowerCase();
|
||||
this.negate = negate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matchHeader(String headerName) {
|
||||
String header = headerName.toLowerCase();
|
||||
if (PatternMatchUtils.simpleMatch(this.pattern, header)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(MessageFormat.format(
|
||||
"headerName=[{0}] WILL be mapped, matched pattern={1}", headerName, pattern));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNegated() {
|
||||
return this.negate;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -457,6 +535,11 @@ public abstract class AbstractHeaderMapper<T> implements RequestReplyHeaderMappe
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNegated() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -464,14 +547,14 @@ public abstract class AbstractHeaderMapper<T> implements RequestReplyHeaderMappe
|
||||
* {@link HeaderMatcher}s matches to the {@code headerName}.
|
||||
* @since 4.1
|
||||
*/
|
||||
protected static class CompositeHeaderMatcher implements HeaderMatcher {
|
||||
protected static class CompositeHeaderMatcher implements HeaderMatcher{
|
||||
|
||||
private static final Log logger = LogFactory.getLog(HeaderMatcher.class);
|
||||
|
||||
private final Collection<HeaderMatcher> strategies;
|
||||
private final Collection<HeaderMatcher> matchers;
|
||||
|
||||
CompositeHeaderMatcher(Collection<HeaderMatcher> strategies) {
|
||||
this.strategies = strategies;
|
||||
this.matchers = strategies;
|
||||
}
|
||||
|
||||
CompositeHeaderMatcher(HeaderMatcher... strategies) {
|
||||
@@ -480,8 +563,11 @@ public abstract class AbstractHeaderMapper<T> implements RequestReplyHeaderMappe
|
||||
|
||||
@Override
|
||||
public boolean matchHeader(String headerName) {
|
||||
for (HeaderMatcher strategy : this.strategies) {
|
||||
for (HeaderMatcher strategy : this.matchers) {
|
||||
if (strategy.matchHeader(headerName)) {
|
||||
if (strategy.isNegated()) {
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -491,6 +577,11 @@ public abstract class AbstractHeaderMapper<T> implements RequestReplyHeaderMappe
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNegated() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -19,11 +19,6 @@ package org.springframework.integration.mapping;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.springframework.integration.mapping.AbstractHeaderMapper.CompositeHeaderMatcher;
|
||||
import static org.springframework.integration.mapping.AbstractHeaderMapper.ContentBasedHeaderMatcher;
|
||||
import static org.springframework.integration.mapping.AbstractHeaderMapper.HeaderMatcher;
|
||||
import static org.springframework.integration.mapping.AbstractHeaderMapper.PatternBasedHeaderMatcher;
|
||||
import static org.springframework.integration.mapping.AbstractHeaderMapper.PrefixBasedMatcher;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
@@ -33,6 +28,12 @@ import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.integration.mapping.AbstractHeaderMapper.CompositeHeaderMatcher;
|
||||
import org.springframework.integration.mapping.AbstractHeaderMapper.ContentBasedHeaderMatcher;
|
||||
import org.springframework.integration.mapping.AbstractHeaderMapper.HeaderMatcher;
|
||||
import org.springframework.integration.mapping.AbstractHeaderMapper.PatternBasedHeaderMatcher;
|
||||
import org.springframework.integration.mapping.AbstractHeaderMapper.PrefixBasedMatcher;
|
||||
import org.springframework.integration.mapping.AbstractHeaderMapper.SinglePatternBasedHeaderMatcher;
|
||||
import org.springframework.messaging.MessageHeaders;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@@ -237,6 +238,33 @@ public class HeaderMapperTests {
|
||||
assertEquals(1, properties.getUserDefinedHeaders().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fromHeadersToRequestWithStandardRequestPatternAndNegatives() {
|
||||
this.mapper.setRequestHeaderNames("foo", "!foo", "bar", "!baz", "\\!qux", "!fiz*",
|
||||
GenericTestHeaderMapper.STANDARD_REQUEST_HEADER_NAME_PATTERN);
|
||||
Map<String, Object> headers = new HashMap<String, Object>();
|
||||
headers.put(GenericTestHeaders.APP_ID, "myAppId");
|
||||
headers.put(GenericTestHeaders.REDELIVERED, true);
|
||||
headers.put(GenericTestHeaders.REQUEST_ONLY, "request-456");
|
||||
headers.put(GenericTestHeaders.REPLY_ONLY, "reply-456");
|
||||
headers.put("foo", "foo");
|
||||
headers.put("bar", "bar");
|
||||
headers.put("baz", "baz");
|
||||
headers.put("!qux", "qux");
|
||||
headers.put("fizbuz", "fizbuz");
|
||||
MessageHeaders messageHeaders = new MessageHeaders(headers);
|
||||
GenericTestProperties properties = new GenericTestProperties();
|
||||
this.mapper.fromHeadersToRequest(messageHeaders, properties);
|
||||
assertEquals("myAppId", properties.getAppId());
|
||||
assertNull(properties.getTransactionSize());
|
||||
assertEquals(true, properties.getRedelivered());
|
||||
assertEquals("request-456", properties.getRequestOnly());
|
||||
assertNull(properties.getReplyOnly());
|
||||
assertEquals("bar", properties.getUserDefinedHeaders().get("bar"));
|
||||
assertEquals("qux", properties.getUserDefinedHeaders().get("!qux"));
|
||||
assertEquals(2, properties.getUserDefinedHeaders().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fromHeadersToReply() {
|
||||
MessageHeaders messageHeaders = createSimpleMessageHeaders();
|
||||
@@ -296,8 +324,9 @@ public class HeaderMapperTests {
|
||||
|
||||
@Test
|
||||
public void prefixHeaderPatternMatching() {
|
||||
@SuppressWarnings("deprecation")
|
||||
PatternBasedHeaderMatcher strategy =
|
||||
new PatternBasedHeaderMatcher(Collections.singleton("foo*"));
|
||||
new PatternBasedHeaderMatcher(Collections.singleton("fOo*"));
|
||||
|
||||
assertMapping(strategy, "foo", true);
|
||||
assertMapping(strategy, "foo123", true);
|
||||
@@ -309,8 +338,35 @@ public class HeaderMapperTests {
|
||||
|
||||
@Test
|
||||
public void suffixHeaderPatternMatching() {
|
||||
@SuppressWarnings("deprecation")
|
||||
PatternBasedHeaderMatcher strategy =
|
||||
new PatternBasedHeaderMatcher(Collections.singleton("*foo"));
|
||||
new PatternBasedHeaderMatcher(Collections.singleton("*fOo"));
|
||||
|
||||
assertMapping(strategy, "foo", true);
|
||||
assertMapping(strategy, "123foo", true);
|
||||
assertMapping(strategy, "FoO", true);
|
||||
|
||||
assertMapping(strategy, "foo123", false);
|
||||
assertMapping(strategy, "foo_", false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void prefixSingleHeaderPatternMatching() {
|
||||
SinglePatternBasedHeaderMatcher strategy =
|
||||
new SinglePatternBasedHeaderMatcher("Foo*");
|
||||
|
||||
assertMapping(strategy, "foo", true);
|
||||
assertMapping(strategy, "foo123", true);
|
||||
assertMapping(strategy, "FoO", true);
|
||||
|
||||
assertMapping(strategy, "123foo", false);
|
||||
assertMapping(strategy, "_foo", false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void suffixSingleHeaderPatternMatching() {
|
||||
SinglePatternBasedHeaderMatcher strategy =
|
||||
new SinglePatternBasedHeaderMatcher("*fOo");
|
||||
|
||||
assertMapping(strategy, "foo", true);
|
||||
assertMapping(strategy, "123foo", true);
|
||||
@@ -322,7 +378,7 @@ public class HeaderMapperTests {
|
||||
|
||||
@Test
|
||||
public void contentHeaderMatching() {
|
||||
AbstractHeaderMapper.ContentBasedHeaderMatcher strategy =
|
||||
ContentBasedHeaderMatcher strategy =
|
||||
new ContentBasedHeaderMatcher(true, Arrays.asList("foo", "bar"));
|
||||
|
||||
assertMapping(strategy, "foo", true);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -36,12 +36,12 @@ import org.springframework.xml.namespace.QNameUtils;
|
||||
/**
|
||||
* A {@link HeaderMapper} implementation for mapping to and from a SoapHeader.
|
||||
* The {@link #setRequestHeaderNames(String[])} and {@link #setReplyHeaderNames(String[])}
|
||||
* accept exact name Strings or simple patterns (e.g. "start*", "*end", or "*").
|
||||
* accept exact name Strings or simple patterns (e.g. "start*", "*end", or "*").
|
||||
* By default all inbound headers will be accepted, but any outbound header that should
|
||||
* be mapped must be configured explicitly. Note that the outbound mapping only writes
|
||||
* String header values into attributes on the SoapHeader. For anything more advanced,
|
||||
* one should implement the HeaderMapper interface directly.
|
||||
*
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @author Oleg Zhurakousky
|
||||
* @author Stephane Nicoll
|
||||
@@ -49,7 +49,7 @@ import org.springframework.xml.namespace.QNameUtils;
|
||||
* @since 2.0
|
||||
*/
|
||||
public class DefaultSoapHeaderMapper extends AbstractHeaderMapper<SoapMessage> implements SoapHeaderMapper {
|
||||
|
||||
|
||||
private static final List<String> STANDARD_HEADER_NAMES = new ArrayList<String>();
|
||||
|
||||
static {
|
||||
@@ -67,8 +67,10 @@ public class DefaultSoapHeaderMapper extends AbstractHeaderMapper<SoapMessage> i
|
||||
Map<String, Object> headers = new HashMap<String, Object>(1);
|
||||
headers.put(WebServiceHeaders.SOAP_ACTION, soapAction);
|
||||
return headers;
|
||||
} else
|
||||
}
|
||||
else {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1059,11 +1059,14 @@ public IntegrationFlow pubSubInFlow(ConnectionFactory connectionFactory) {
|
||||
=== AMQP Message Headers
|
||||
|
||||
The Spring Integration AMQP Adapters will map standard AMQP properties automatically.
|
||||
These properties will be copied by default to and from Spring Integration `MessageHeaders` using the http://static.springsource.org/spring-integration/api/org/springframework/integration/amqp/support/DefaultAmqpHeaderMapper.html[DefaultAmqpHeaderMapper].
|
||||
These properties will be copied by default to and from Spring Integration `MessageHeaders` using the
|
||||
http://docs.spring.io/spring-integration/api/org/springframework/integration/amqp/support/DefaultAmqpHeaderMapper.html[DefaultAmqpHeaderMapper].
|
||||
|
||||
Of course, you can pass in your own implementation of AMQP specific header mappers, as the adapters have respective properties to support that.
|
||||
|
||||
Any user-defined headers within the AMQP http://static.springsource.org/spring-amqp/api/org/springframework/amqp/core/MessageProperties.html[MessageProperties] will NOT be copied to or from an AMQP Message, unless explicitly specified by the _requestHeaderNames_ and/or _replyHeaderNames_ properties of the `DefaultAmqpHeaderMapper`.
|
||||
Any user-defined headers within the AMQP http://docs.spring.io/spring-amqp/api/org/springframework/amqp/core/MessageProperties.html[MessageProperties] will NOT
|
||||
be copied to or from an AMQP Message, unless explicitly specified by the _requestHeaderNames_ and/or
|
||||
_replyHeaderNames_ properties of the `DefaultAmqpHeaderMapper`.
|
||||
|
||||
TIP: When mapping user-defined headers, the values can also contain simple wildcard patterns (e.g. "foo*" or "*foo") to be matched.
|
||||
For example, if you need to copy all user-defined headers simply use the wildcard character `*`, but see the CAUTION below.
|
||||
@@ -1142,6 +1145,14 @@ before sending the reply to the AMQP Inbound Gateway.
|
||||
Alternatively, you could explicitly list those properties that you actually want mapped instead of using
|
||||
wildcards.
|
||||
|
||||
Starting with _version 4.3_, patterns in the header mappings can be negated by preceding the pattern with `!`.
|
||||
Negated patterns get priority, so a list such as
|
||||
`STANDARD_REQUEST_HEADERS,foo,ba*,!bar,!baz,qux,!foo` will *NOT* map `foo`
|
||||
(nor `bar` nor `baz`); the standard headers plus `bad`, `qux` will be mapped.
|
||||
|
||||
IMPORTANT: If you have a user defined header that begins with `!` that you *do* wish to map, you need to escape it with
|
||||
`\` thus: `STANDARD_REQUEST_HEADERS,\!myBangHeader` and it *WILL* be mapped.
|
||||
|
||||
=== AMQP Samples
|
||||
|
||||
To experiment with the AMQP adapters, check out the samples available in the Spring Integration Samples Git repository at:
|
||||
|
||||
@@ -114,7 +114,7 @@ See <<http-inbound>> for more information.
|
||||
A new factory bean is provided to simplify the configuration of Jsch proxies for SFTP.
|
||||
See <<sftp-proxy-factory-bean>> for more information.
|
||||
|
||||
==== Routers Changes
|
||||
==== Router Changes
|
||||
|
||||
The `ErrorMessageExceptionTypeRouter` supports now the `Exception` superclass mappings to avoid duplication
|
||||
for the same channel in case of several inheritors.
|
||||
@@ -122,3 +122,9 @@ For this purpose the `ErrorMessageExceptionTypeRouter` loads mapping classes dur
|
||||
for a `ClassNotFoundException`.
|
||||
|
||||
See <<router>> for more information.
|
||||
|
||||
==== Header Mapping
|
||||
|
||||
AMQP, WS and XMPP header mappings (e.g. `request-header-mapping`, `reply-header-mapping`) now support negated
|
||||
patterns.
|
||||
See <<amqp-message-headers>>, <<ws-message-headers>>, and <<xmpp-message-headers>> for more information.
|
||||
|
||||
@@ -165,3 +165,34 @@ If you wish to partially encode some of the URL, this can be achieved using an `
|
||||
----
|
||||
|
||||
Note, `encode-uri` is ignored, if `DestinationProvider` is supplied.
|
||||
|
||||
[[ws-message-headers]]
|
||||
=== WS Message Headers
|
||||
|
||||
The Spring Integration WebService Gateways will map the SOAP Action header automatically.
|
||||
It will be copied by default to and from Spring Integration `MessageHeaders` using the
|
||||
http://docs.spring.io/spring-integration/api/org/springframework/integration/ws/DefaultSoapHeaderMapper.html[DefaultSoapHeaderMapper].
|
||||
|
||||
Of course, you can pass in your own implementation of SOAP specific header mappers, as the gateways have respective properties to support that.
|
||||
|
||||
Any user-defined headers will NOT
|
||||
be copied to or from an SOAP Message, unless explicitly specified by the _requestHeaderNames_ and/or
|
||||
_replyHeaderNames_ properties of the `DefaultSoapHeaderMapper`.
|
||||
|
||||
TIP: When mapping user-defined headers, the values can also contain simple wildcard patterns (e.g. "foo*" or "*foo") to be matched.
|
||||
For example, if you need to copy all user-defined headers simply use the wildcard character `*`.
|
||||
|
||||
Starting with _version 4.1_, the `AbstractHeaderMapper` (a `DefaultSoapHeaderMapper` superclass) allows the
|
||||
`NON_STANDARD_HEADERS` token to be configured for the _requestHeaderNames_ and/or _replyHeaderNames_
|
||||
properties (in addition to existing `STANDARD_REQUEST_HEADERS` and `STANDARD_REPLY_HEADERS`) to map all
|
||||
user-defined headers.
|
||||
Note, it is recommended to use the combination like this `STANDARD_REPLY_HEADERS, NON_STANDARD_HEADERS` instead of a
|
||||
`*`, to avoid mapping of _request_ headers to the reply.
|
||||
|
||||
Starting with _version 4.3_, patterns in the header mappings can be negated by preceding the pattern with `!`.
|
||||
Negated patterns get priority, so a list such as
|
||||
`STANDARD_REQUEST_HEADERS,foo,ba*,!bar,!baz,qux,!foo` will *NOT* map `foo`
|
||||
(nor `bar` nor `baz`); the standard headers plus `bad`, `qux` will be mapped.
|
||||
|
||||
IMPORTANT: If you have a user defined header that begins with `!` that you *do* wish to map, you need to escape it with
|
||||
`\` thus: `STANDARD_REQUEST_HEADERS,\!myBangHeader` and it *WILL* be mapped.
|
||||
|
||||
@@ -219,3 +219,40 @@ public class CustomConnectionConfiguration {
|
||||
----
|
||||
|
||||
For more information on the JavaConfig style of Application Context configuration, refer to the following section in the Spring Reference Manual: http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/beans.html#beans-java
|
||||
|
||||
[[xmpp-message-headers]]
|
||||
=== XMPP Message Headers
|
||||
|
||||
The Spring Integration XMPP Adapters will map standard XMPP properties automatically.
|
||||
These properties will be copied by default to and from Spring Integration `MessageHeaders` using the
|
||||
http://docs.spring.io/spring-integration/api/org/springframework/integration/xmpp/support/DefaultXmppHeaderMapper.html[DefaultXmppHeaderMapper].
|
||||
|
||||
Any user-defined headers will NOT be copied to or from an XMPP Message, unless explicitly specified by the
|
||||
_requestHeaderNames_ and/or _replyHeaderNames_ properties of the `DefaultXmppHeaderMapper`.
|
||||
|
||||
TIP: When mapping user-defined headers, the values can also contain simple wildcard patterns (e.g. "foo*" or "*foo") to
|
||||
be matched.
|
||||
|
||||
Starting with _version 4.1_, the `AbstractHeaderMapper` (a `DefaultXmppHeaderMapper` superclass) allows the
|
||||
`NON_STANDARD_HEADERS` token to be configured for the _requestHeaderNames_ property (in addition to existing
|
||||
`STANDARD_REQUEST_HEADERS`) to map all user-defined headers.
|
||||
|
||||
Class `org.springframework.xmpp.XmppHeaders` identifies the default headers that will be used by the `DefaultXmppHeaderMapper`:
|
||||
|
||||
* xmpp_from
|
||||
|
||||
* xmpp_subject
|
||||
|
||||
* xmpp_thread
|
||||
|
||||
* xmpp_to
|
||||
|
||||
* xmpp_type
|
||||
|
||||
Starting with _version 4.3_, patterns in the header mappings can be negated by preceding the pattern with `!`.
|
||||
Negated patterns get priority, so a list such as
|
||||
`STANDARD_REQUEST_HEADERS,foo,ba*,!bar,!baz,qux,!foo` will *NOT* map `foo`
|
||||
(nor `bar` nor `baz`); the standard headers plus `bad`, `qux` will be mapped.
|
||||
|
||||
IMPORTANT: If you have a user defined header that begins with `!` that you *do* wish to map, you need to escape it with
|
||||
`\` thus: `STANDARD_REQUEST_HEADERS,\!myBangHeader` and it *WILL* be mapped.
|
||||
|
||||
Reference in New Issue
Block a user