diff --git a/spring-integration-core/src/main/java/org/springframework/integration/IntegrationMessageHeaderAccessor.java b/spring-integration-core/src/main/java/org/springframework/integration/IntegrationMessageHeaderAccessor.java index 1f2a91abeb..e11459eac4 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/IntegrationMessageHeaderAccessor.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/IntegrationMessageHeaderAccessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2016 the original author or authors. + * Copyright 2013-2017 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. @@ -35,6 +35,8 @@ import org.springframework.util.ObjectUtils; * * @author Andy Wilkinson * @author Artem Bilan + * @author Gary Russel + * * @since 4.0 * */ @@ -157,4 +159,18 @@ public class IntegrationMessageHeaderAccessor extends MessageHeaderAccessor { return super.isReadOnly(headerName) || this.readOnlyHeaders.contains(headerName); } + @Override + public Map toMap() { + if (ObjectUtils.isEmpty(this.readOnlyHeaders)) { + return super.toMap(); + } + else { + Map headers = super.toMap(); + for (String header : this.readOnlyHeaders) { + headers.remove(header); + } + return headers; + } + } + } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/support/DefaultMessageBuilderFactory.java b/spring-integration-core/src/main/java/org/springframework/integration/support/DefaultMessageBuilderFactory.java index 854841cfab..87a4558d4a 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/support/DefaultMessageBuilderFactory.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/support/DefaultMessageBuilderFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2016 the original author or authors. + * Copyright 2014-2017 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. @@ -16,6 +16,8 @@ package org.springframework.integration.support; +import java.util.Arrays; + import org.springframework.messaging.Message; import org.springframework.messaging.MessageHeaders; @@ -37,7 +39,24 @@ public class DefaultMessageBuilderFactory implements MessageBuilderFactory { * @since 4.3.2 */ public void setReadOnlyHeaders(String... readOnlyHeaders) { - this.readOnlyHeaders = readOnlyHeaders; + this.readOnlyHeaders = Arrays.copyOf(readOnlyHeaders, readOnlyHeaders.length); + } + + /** + * Add headers to the configured list of read only headers. + * @param readOnlyHeaders the additional headers. + * @since 4.3.10 + */ + public void addReadOnlyHeaders(String... readOnlyHeaders) { + String[] headers = this.readOnlyHeaders; + if (headers == null || headers.length == 0) { + headers = Arrays.copyOf(readOnlyHeaders, readOnlyHeaders.length); + } + else { + headers = Arrays.copyOf(headers, headers.length + readOnlyHeaders.length); + System.arraycopy(readOnlyHeaders, 0, headers, this.readOnlyHeaders.length, readOnlyHeaders.length); + } + this.readOnlyHeaders = headers; } @Override diff --git a/spring-integration-core/src/main/java/org/springframework/integration/support/MessageBuilder.java b/spring-integration-core/src/main/java/org/springframework/integration/support/MessageBuilder.java index 00f9e9a918..cc72bb9d71 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/support/MessageBuilder.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/support/MessageBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2016 the original author or authors. + * Copyright 2002-2017 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. @@ -27,6 +27,7 @@ import org.springframework.messaging.MessageHeaders; import org.springframework.messaging.support.ErrorMessage; import org.springframework.messaging.support.GenericMessage; import org.springframework.util.Assert; +import org.springframework.util.ObjectUtils; /** * The default message builder; creates immutable {@link GenericMessage}s. @@ -50,6 +51,8 @@ public final class MessageBuilder extends AbstractIntegrationMessageBuilder extends AbstractIntegrationMessageBuilder setHeader(String headerName, Object headerValue) { - this.headerAccessor.setHeader(headerName, headerValue); + this.headerAccessor.setHeader(headerName, headerValue); return this; } @@ -136,6 +139,7 @@ public final class MessageBuilder extends AbstractIntegrationMessageBuilder extends AbstractIntegrationMessageBuilder readOnlyHeaders(String... readOnlyHeaders) { + this.readOnlyHeaders = readOnlyHeaders; this.headerAccessor.setReadOnlyHeaders(readOnlyHeaders); return this; } - - @Override @SuppressWarnings("unchecked") public Message build() { - if (!this.modified && !this.headerAccessor.isModified() && this.originalMessage != null) { + if (!this.modified && !this.headerAccessor.isModified() && this.originalMessage != null + && !containsReadOnly(this.originalMessage.getHeaders())) { return this.originalMessage; } if (this.payload instanceof Throwable) { @@ -302,4 +306,16 @@ public final class MessageBuilder extends AbstractIntegrationMessageBuilder(this.payload, this.headerAccessor.toMap()); } + private boolean containsReadOnly(MessageHeaders headers) { + if (!ObjectUtils.isEmpty(this.readOnlyHeaders)) { + for (String readOnly : this.readOnlyHeaders) { + if (headers.containsKey(readOnly)) { + return true; + } + } + } + return false; + } + + } diff --git a/spring-integration-core/src/test/java/org/springframework/integration/support/MessageBuilderTests.java b/spring-integration-core/src/test/java/org/springframework/integration/support/MessageBuilderTests.java new file mode 100644 index 0000000000..11650bb44a --- /dev/null +++ b/spring-integration-core/src/test/java/org/springframework/integration/support/MessageBuilderTests.java @@ -0,0 +1,50 @@ +/* + * Copyright 2017 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.integration.support; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertThat; + +import org.junit.Test; + +import org.springframework.messaging.Message; + +/** + * @author Gary Russell + * @since 4.3.10 + * + */ +public class MessageBuilderTests { + + @Test + public void testReadOnlyHeaders() { + DefaultMessageBuilderFactory factory = new DefaultMessageBuilderFactory(); + Message message = factory.withPayload("bar").setHeader("foo", "baz").setHeader("qux", "fiz").build(); + assertThat(message.getHeaders().get("foo"), equalTo("baz")); + assertThat(message.getHeaders().get("qux"), equalTo("fiz")); + factory.setReadOnlyHeaders("foo"); + message = factory.fromMessage(message).build(); + assertNull(message.getHeaders().get("foo")); + assertThat(message.getHeaders().get("qux"), equalTo("fiz")); + factory.addReadOnlyHeaders("qux"); + message = factory.fromMessage(message).build(); + assertNull(message.getHeaders().get("foo")); + assertNull(message.getHeaders().get("qux")); + } + +}