Polishing
This commit is contained in:
@@ -36,26 +36,26 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public final class MessageBuilder<T> {
|
||||
|
||||
private final Message<T> originalMessage;
|
||||
|
||||
private final T payload;
|
||||
|
||||
private final Message<T> originalMessage;
|
||||
|
||||
private MessageHeaderAccessor headerAccessor;
|
||||
|
||||
|
||||
private MessageBuilder(Message<T> 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<T> {
|
||||
* @param accessor the headers to use
|
||||
*/
|
||||
public MessageBuilder<T> 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<T> {
|
||||
* and {@code MessageHeaders}.
|
||||
* <p><strong>Note:</strong> 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 <T> Message<T> 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<T>) new ErrorMessage((Throwable) payload, messageHeaders);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
private IdGenerator idGenerator;
|
||||
private boolean leaveMutable = false;
|
||||
|
||||
private boolean enableTimestamp = false;
|
||||
|
||||
private boolean modified = false;
|
||||
|
||||
private IdGenerator idGenerator;
|
||||
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* <p>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 extends MessageHeaderAccessor> T getAccessor(Message<?> message, Class<T> 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}.
|
||||
*
|
||||
* <p>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 extends MessageHeaderAccessor> T getAccessor(MessageHeaders messageHeaders, Class<T> 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.
|
||||
*
|
||||
* <p>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.
|
||||
*
|
||||
* <p>Unless {@link #setLeaveMutable(boolean)} was set to {@code true}, after
|
||||
* this call, the headers are immutable and this accessor can no longer
|
||||
* modify them.
|
||||
*
|
||||
* <p>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.
|
||||
*
|
||||
* <p>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.
|
||||
*
|
||||
* <p>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:<br>
|
||||
* {@link org.springframework.messaging.support.MessageHeaderAccessor#getAccessor(org.springframework.messaging.Message, Class)
|
||||
* {@link MessageHeaderAccessor#getAccessor(Message, Class)
|
||||
* MessageHeaderAccessor.getAccessor(Message, Class)}
|
||||
*
|
||||
* <p>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.
|
||||
*
|
||||
* <p>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.
|
||||
*
|
||||
* <p>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.
|
||||
*
|
||||
* <p>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.
|
||||
* <p>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.
|
||||
* <p>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'.
|
||||
* <p>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<String> headersToRemove = new ArrayList<String>();
|
||||
@@ -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.
|
||||
* <p>This operation will overwrite any existing values. Use
|
||||
* {@link #copyHeadersIfAbsent(Map)} to avoid overwriting values.
|
||||
*/
|
||||
public void copyHeaders(Map<String, ?> headersToCopy) {
|
||||
if (headersToCopy != null) {
|
||||
@@ -425,8 +363,8 @@ public class MessageHeaderAccessor {
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the name-value pairs from the provided Map. This operation will <em>not</em>
|
||||
* overwrite any existing values.
|
||||
* Copy the name-value pairs from the provided Map.
|
||||
* <p>This operation will <em>not</em> overwrite any existing values.
|
||||
*/
|
||||
public void copyHeadersIfAbsent(Map<String, ?> 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.
|
||||
* <p>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 extends MessageHeaderAccessor> T getAccessor(Message<?> message, Class<T> 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}.
|
||||
* <p>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 extends MessageHeaderAccessor> T getAccessor(MessageHeaders messageHeaders, Class<T> 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.
|
||||
* <p>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) {
|
||||
|
||||
Reference in New Issue
Block a user