From e254b558f045630138524217982dfe4f576077c7 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Thu, 10 Jul 2014 18:38:07 +0200 Subject: [PATCH] Polishing --- .../messaging/support/MessageBuilder.java | 24 +-- .../support/MessageHeaderAccessor.java | 204 +++++++++--------- 2 files changed, 109 insertions(+), 119 deletions(-) diff --git a/spring-messaging/src/main/java/org/springframework/messaging/support/MessageBuilder.java b/spring-messaging/src/main/java/org/springframework/messaging/support/MessageBuilder.java index 39524581c1a..a7dcbf8b9ed 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/support/MessageBuilder.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/support/MessageBuilder.java @@ -36,26 +36,26 @@ import org.springframework.util.Assert; */ public final class MessageBuilder { - private final Message originalMessage; - private final T payload; + private final Message originalMessage; + private MessageHeaderAccessor headerAccessor; private MessageBuilder(Message originalMessage) { - Assert.notNull(originalMessage, "'originalMessage' must not be null"); + Assert.notNull(originalMessage, "Message must not be null"); this.payload = originalMessage.getPayload(); - this.headerAccessor = new MessageHeaderAccessor(originalMessage); this.originalMessage = originalMessage; + this.headerAccessor = new MessageHeaderAccessor(originalMessage); } private MessageBuilder(T payload, MessageHeaderAccessor accessor) { - Assert.notNull(payload, "'payload' must not be null"); - Assert.notNull(accessor, "'messageHeaderAccessor' must not be null"); + Assert.notNull(payload, "Payload must not be null"); + Assert.notNull(accessor, "MessageHeaderAccessor must not be null"); this.payload = payload; - this.headerAccessor = accessor; this.originalMessage = null; + this.headerAccessor = accessor; } @@ -64,7 +64,7 @@ public final class MessageBuilder { * @param accessor the headers to use */ public MessageBuilder setHeaders(MessageHeaderAccessor accessor) { - Assert.notNull(accessor, "HeaderAccessor must not be null"); + Assert.notNull(accessor, "MessageHeaderAccessor must not be null"); this.headerAccessor = accessor; return this; } @@ -180,15 +180,15 @@ public final class MessageBuilder { * and {@code MessageHeaders}. *

Note: the given {@code MessageHeaders} instance is used * directly in the new message, i.e. it is not copied. - * @param payload the payload to use, never {@code null} - * @param messageHeaders the headers to use, never {@code null} + * @param payload the payload to use (never {@code null}) + * @param messageHeaders the headers to use (never {@code null}) * @return the created message * @since 4.1 */ @SuppressWarnings("unchecked") public static Message createMessage(T payload, MessageHeaders messageHeaders) { - Assert.notNull(payload, "'payload' must not be null"); - Assert.notNull(messageHeaders, "'messageHeaders' must not be null"); + Assert.notNull(payload, "Payload must not be null"); + Assert.notNull(messageHeaders, "MessageHeaders must not be null"); if (payload instanceof Throwable) { return (Message) new ErrorMessage((Throwable) payload, messageHeaders); } diff --git a/spring-messaging/src/main/java/org/springframework/messaging/support/MessageHeaderAccessor.java b/spring-messaging/src/main/java/org/springframework/messaging/support/MessageHeaderAccessor.java index dbb70e2f65e..4aec0b55965 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/support/MessageHeaderAccessor.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/support/MessageHeaderAccessor.java @@ -115,25 +115,26 @@ import org.springframework.util.StringUtils; */ public class MessageHeaderAccessor { - private static final MimeType[] readableMimeTypes = new MimeType[] { + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private static final MimeType[] READABLE_MIME_TYPES = new MimeType[] { MimeTypeUtils.APPLICATION_JSON, MimeTypeUtils.APPLICATION_XML, new MimeType("text", "*"), new MimeType("application", "*+json"), new MimeType("application", "*+xml") }; - public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); - protected Log logger = LogFactory.getLog(getClass()); + protected final Log logger = LogFactory.getLog(getClass()); private final MutableMessageHeaders headers; - private boolean modified; + private boolean leaveMutable = false; + + private boolean enableTimestamp = false; - private boolean leaveMutable; + private boolean modified = false; private IdGenerator idGenerator; - private boolean enableTimestamp = false; - /** * A constructor to create new headers. @@ -154,64 +155,6 @@ public class MessageHeaderAccessor { } } - /** - * Return the original {@code MessageHeaderAccessor} used to create the headers - * of the given {@code Message}, or {@code null} if that's not available or if - * its type does not match the required type. - * - *

This is for cases where the existence of an accessor is strongly expected - * (to be followed up with an assertion) or will created if not provided. - * - * @return an accessor instance of the specified type or {@code null}. - * @since 4.1 - */ - @SuppressWarnings("unchecked") - public static T getAccessor(Message message, Class requiredType) { - return getAccessor(message.getHeaders(), requiredType); - } - - /** - * A variation of {@link #getAccessor(org.springframework.messaging.Message, Class)} - * with a {@code MessageHeaders} instance instead of a {@code Message}. - * - *

This is for cases when a full message may not have been created yet. - * - * @return an accessor instance of the specified type or {@code null}. - * @since 4.1 - */ - @SuppressWarnings("unchecked") - public static T getAccessor(MessageHeaders messageHeaders, Class requiredType) { - if (messageHeaders instanceof MutableMessageHeaders) { - MutableMessageHeaders mutableHeaders = (MutableMessageHeaders) messageHeaders; - MessageHeaderAccessor headerAccessor = mutableHeaders.getMessageHeaderAccessor(); - if (requiredType.isAssignableFrom(headerAccessor.getClass())) { - return (T) headerAccessor; - } - } - return null; - } - - /** - * Return a mutable {@code MessageHeaderAccessor} for the given message attempting - * to match the type of accessor used to create the message headers, or otherwise - * wrapping the message with a {@code MessageHeaderAccessor} instance. - * - *

This is for cases where a header needs to be updated in generic code - * while preserving the accessor type for downstream processing. - * - * @return an accessor of the required type, never {@code null}. - * @since 4.1 - */ - public static MessageHeaderAccessor getMutableAccessor(Message message) { - if (message.getHeaders() instanceof MutableMessageHeaders) { - MutableMessageHeaders mutableHeaders = (MutableMessageHeaders) message.getHeaders(); - MessageHeaderAccessor accessor = mutableHeaders.getMessageHeaderAccessor(); - if (accessor != null) { - return (accessor.isMutable() ? accessor : accessor.createAccessor(message)); - } - } - return new MessageHeaderAccessor(message); - } protected MessageHeaderAccessor createAccessor(Message message) { return new MessageHeaderAccessor(message); @@ -219,11 +162,9 @@ public class MessageHeaderAccessor { /** * Return the underlying {@code MessageHeaders} instance. - * *

Unless {@link #setLeaveMutable(boolean)} was set to {@code true}, after * this call, the headers are immutable and this accessor can no longer * modify them. - * *

This method always returns the same {@code MessageHeaders} instance if * invoked multiples times. To obtain a copy of the underlying headers instead * use {@link #toMap()}. @@ -237,7 +178,6 @@ public class MessageHeaderAccessor { /** * Return a copy of the underlying header values. - * *

This method can be invoked many times, with modifications in between * where each new call returns a fresh copy of the current header values. */ @@ -249,17 +189,14 @@ public class MessageHeaderAccessor { * By default when {@link #getMessageHeaders()} is called, {@code "this"} * {@code MessageHeaderAccessor} instance can no longer be used to modify the * underlying message headers and the returned {@code MessageHeaders} is immutable. - * *

However when this is set to {@code true}, the returned (underlying) * {@code MessageHeaders} instance remains mutable. To make further modifications * continue to use the same accessor instance or re-obtain it via:
- * {@link org.springframework.messaging.support.MessageHeaderAccessor#getAccessor(org.springframework.messaging.Message, Class) + * {@link MessageHeaderAccessor#getAccessor(Message, Class) * MessageHeaderAccessor.getAccessor(Message, Class)} - * *

When modifications are complete use {@link #setImmutable()} to prevent * further changes. The intended use case for this mechanism is initialization * of a Message within a single thread. - * *

By default this is set to {@code false}. * @since 4.1 */ @@ -289,25 +226,11 @@ public class MessageHeaderAccessor { return this.headers.isMutable(); } - /** - * A package private mechanism to configure the IdGenerator strategy to use. - * - *

By default this property is not set in which case the default IdGenerator - * in {@link org.springframework.messaging.MessageHeaders} is used. - * - * @see org.springframework.messaging.support.IdTimestampMessageHeaderInitializer - */ - void setIdGenerator(IdGenerator idGenerator) { - this.idGenerator = idGenerator; - } - /** * A package private mechanism to enables the automatic addition of the * {@link org.springframework.messaging.MessageHeaders#TIMESTAMP} header. - * *

By default this property is set to false. - * - * @see org.springframework.messaging.support.IdTimestampMessageHeaderInitializer + * @see IdTimestampMessageHeaderInitializer */ void setEnableTimestamp(boolean enableTimestamp) { this.enableTimestamp = enableTimestamp; @@ -321,16 +244,28 @@ public class MessageHeaderAccessor { this.modified = modified; } + /** + * A package-private mechanism to configure the IdGenerator strategy to use. + *

By default this property is not set in which case the default IdGenerator + * in {@link org.springframework.messaging.MessageHeaders} is used. + * @see IdTimestampMessageHeaderInitializer + */ + void setIdGenerator(IdGenerator idGenerator) { + this.idGenerator = idGenerator; + } + public Object getHeader(String headerName) { return this.headers.get(headerName); } /** - * Set the value for the given header name. If the provided value is {@code null} the - * header will be removed. + * Set the value for the given header name. + *

If the provided value is {@code null}, the header will be removed. */ public void setHeader(String name, Object value) { - Assert.isTrue(!isReadOnly(name), "The '" + name + "' header is read-only."); + if (isReadOnly(name)) { + throw new IllegalArgumentException("'" + name + "' header is read-only"); + } verifyType(name, value); if (!ObjectUtils.nullSafeEquals(value, getHeader(name))) { this.modified = true; @@ -346,8 +281,10 @@ public class MessageHeaderAccessor { protected void verifyType(String headerName, Object headerValue) { if (headerName != null && headerValue != null) { if (MessageHeaders.ERROR_CHANNEL.equals(headerName) || MessageHeaders.REPLY_CHANNEL.endsWith(headerName)) { - Assert.isTrue(headerValue instanceof MessageChannel || headerValue instanceof String, "The '" - + headerName + "' header value must be a MessageChannel or String."); + if (!(headerValue instanceof MessageChannel || headerValue instanceof String)) { + throw new IllegalArgumentException( + "'" + headerName + "' header value must be a MessageChannel or String"); + } } } } @@ -357,7 +294,8 @@ public class MessageHeaderAccessor { } /** - * Set the value for the given header name only if the header name is not already associated with a value. + * Set the value for the given header name only if the header name is not + * already associated with a value. */ public void setHeaderIfAbsent(String name, Object value) { if (getHeader(name) == null) { @@ -366,9 +304,9 @@ public class MessageHeaderAccessor { } /** - * Removes all headers provided via array of 'headerPatterns'. As the name suggests - * the array may contain simple matching patterns for header names. Supported pattern - * styles are: "xxx*", "*xxx", "*xxx*" and "xxx*yyy". + * Removes all headers provided via array of 'headerPatterns'. + *

As the name suggests, array may contain simple matching patterns for header + * names. Supported pattern styles are: "xxx*", "*xxx", "*xxx*" and "xxx*yyy". */ public void removeHeaders(String... headerPatterns) { List headersToRemove = new ArrayList(); @@ -409,9 +347,9 @@ public class MessageHeaderAccessor { } /** - * Copy the name-value pairs from the provided Map. This operation will overwrite any - * existing values. Use { {@link #copyHeadersIfAbsent(Map)} to avoid overwriting - * values. + * Copy the name-value pairs from the provided Map. + *

This operation will overwrite any existing values. Use + * {@link #copyHeadersIfAbsent(Map)} to avoid overwriting values. */ public void copyHeaders(Map headersToCopy) { if (headersToCopy != null) { @@ -425,8 +363,8 @@ public class MessageHeaderAccessor { } /** - * Copy the name-value pairs from the provided Map. This operation will not - * overwrite any existing values. + * Copy the name-value pairs from the provided Map. + *

This operation will not overwrite any existing values. */ public void copyHeadersIfAbsent(Map headersToCopy) { if (headersToCopy != null) { @@ -547,7 +485,7 @@ public class MessageHeaderAccessor { } protected boolean isReadableContentType() { - for (MimeType mimeType : readableMimeTypes) { + for (MimeType mimeType : READABLE_MIME_TYPES) { if (mimeType.includes(getContentType())) { return true; } @@ -557,7 +495,61 @@ public class MessageHeaderAccessor { @Override public String toString() { - return getClass().getSimpleName() + "[headers=" + this.headers + "]"; + return getClass().getSimpleName() + " [headers=" + this.headers + "]"; + } + + + /** + * Return the original {@code MessageHeaderAccessor} used to create the headers + * of the given {@code Message}, or {@code null} if that's not available or if + * its type does not match the required type. + *

This is for cases where the existence of an accessor is strongly expected + * (to be followed up with an assertion) or will created if not provided. + * @return an accessor instance of the specified type, or {@code null} if none + * @since 4.1 + */ + @SuppressWarnings("unchecked") + public static T getAccessor(Message message, Class requiredType) { + return getAccessor(message.getHeaders(), requiredType); + } + + /** + * A variation of {@link #getAccessor(org.springframework.messaging.Message, Class)} + * with a {@code MessageHeaders} instance instead of a {@code Message}. + *

This is for cases when a full message may not have been created yet. + * @return an accessor instance of the specified typem or {@code null} if none + * @since 4.1 + */ + @SuppressWarnings("unchecked") + public static T getAccessor(MessageHeaders messageHeaders, Class requiredType) { + if (messageHeaders instanceof MutableMessageHeaders) { + MutableMessageHeaders mutableHeaders = (MutableMessageHeaders) messageHeaders; + MessageHeaderAccessor headerAccessor = mutableHeaders.getMessageHeaderAccessor(); + if (requiredType.isAssignableFrom(headerAccessor.getClass())) { + return (T) headerAccessor; + } + } + return null; + } + + /** + * Return a mutable {@code MessageHeaderAccessor} for the given message attempting + * to match the type of accessor used to create the message headers, or otherwise + * wrapping the message with a {@code MessageHeaderAccessor} instance. + *

This is for cases where a header needs to be updated in generic code + * while preserving the accessor type for downstream processing. + * @return an accessor of the required type, never {@code null}. + * @since 4.1 + */ + public static MessageHeaderAccessor getMutableAccessor(Message message) { + if (message.getHeaders() instanceof MutableMessageHeaders) { + MutableMessageHeaders mutableHeaders = (MutableMessageHeaders) message.getHeaders(); + MessageHeaderAccessor accessor = mutableHeaders.getMessageHeaderAccessor(); + if (accessor != null) { + return (accessor.isMutable() ? accessor : accessor.createAccessor(message)); + } + } + return new MessageHeaderAccessor(message); } @@ -566,7 +558,6 @@ public class MessageHeaderAccessor { private boolean immutable; - public MutableMessageHeaders() { this(null); } @@ -598,9 +589,8 @@ public class MessageHeaderAccessor { return; } if (getId() == null) { - IdGenerator idGenerator = (MessageHeaderAccessor.this.idGenerator != null) ? - MessageHeaderAccessor.this.idGenerator : - MessageHeaders.getIdGenerator(); + IdGenerator idGenerator = (MessageHeaderAccessor.this.idGenerator != null ? + MessageHeaderAccessor.this.idGenerator : MessageHeaders.getIdGenerator()); UUID id = idGenerator.generateId(); if (id != null && id != MessageHeaders.ID_VALUE_NONE) {