Browse Source

Polishing

pull/554/head
Juergen Hoeller 12 years ago
parent
commit
e254b558f0
  1. 24
      spring-messaging/src/main/java/org/springframework/messaging/support/MessageBuilder.java
  2. 204
      spring-messaging/src/main/java/org/springframework/messaging/support/MessageHeaderAccessor.java

24
spring-messaging/src/main/java/org/springframework/messaging/support/MessageBuilder.java

@ -36,26 +36,26 @@ import org.springframework.util.Assert; @@ -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> { @@ -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> { @@ -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);
}

204
spring-messaging/src/main/java/org/springframework/messaging/support/MessageHeaderAccessor.java

@ -115,25 +115,26 @@ import org.springframework.util.StringUtils; @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -566,7 +558,6 @@ public class MessageHeaderAccessor {
private boolean immutable;
public MutableMessageHeaders() {
this(null);
}
@ -598,9 +589,8 @@ public class MessageHeaderAccessor { @@ -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) {

Loading…
Cancel
Save