Polishing
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
|
||||
/**
|
||||
*
|
||||
* Useful generic {@code java.util.Comparator} implementations,
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
/**
|
||||
*
|
||||
* Useful generic {@code java.util.concurrent.Future} extension.
|
||||
*
|
||||
*/
|
||||
package org.springframework.util.concurrent;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2014 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,7 +27,7 @@ package org.springframework.messaging;
|
||||
public interface Message<T> {
|
||||
|
||||
/**
|
||||
* Return message headers for the message, never {@code null}.
|
||||
* Return message headers for the message (never {@code null}).
|
||||
*/
|
||||
MessageHeaders getHeaders();
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2014 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.
|
||||
@@ -37,17 +37,19 @@ import org.springframework.util.AlternativeJdkIdGenerator;
|
||||
import org.springframework.util.IdGenerator;
|
||||
|
||||
/**
|
||||
* The headers for a {@link Message}
|
||||
* <p>
|
||||
* <b>IMPORTANT</b>: This class is immutable. Any mutating operation such as
|
||||
* The headers for a {@link Message}.
|
||||
*
|
||||
* <p><b>IMPORTANT</b>: This class is immutable. Any mutating operation such as
|
||||
* {@code put(..)}, {@code putAll(..)} and others will throw
|
||||
* {@link UnsupportedOperationException}.
|
||||
* <p>
|
||||
* One way to create message headers is to use the
|
||||
* <p>Subclasses do have access to the raw headers, however, via {@link #getRawHeaders()}.
|
||||
*
|
||||
* <p>One way to create message headers is to use the
|
||||
* {@link org.springframework.messaging.support.MessageBuilder MessageBuilder}:
|
||||
* <pre class="code">
|
||||
* MessageBuilder.withPayload("foo").setHeader("key1", "value1").setHeader("key2", "value2");
|
||||
* </pre>
|
||||
*
|
||||
* A second option is to create {@link org.springframework.messaging.support.GenericMessage}
|
||||
* passing a payload as {@link Object} and headers as a {@link Map java.util.Map}:
|
||||
* <pre class="code">
|
||||
@@ -56,6 +58,7 @@ import org.springframework.util.IdGenerator;
|
||||
* headers.put("key2", "value2");
|
||||
* new GenericMessage("foo", headers);
|
||||
* </pre>
|
||||
*
|
||||
* A third option is to use {@link org.springframework.messaging.support.MessageHeaderAccessor}
|
||||
* or one of its sub-classes to create specific categories of headers.
|
||||
*
|
||||
@@ -98,7 +101,7 @@ public final class MessageHeaders implements Map<String, Object>, Serializable {
|
||||
|
||||
public MessageHeaders(Map<String, Object> headers) {
|
||||
this.headers = (headers != null) ? new HashMap<String, Object>(headers) : new HashMap<String, Object>();
|
||||
this.headers.put(ID, ((idGenerator != null) ? idGenerator : defaultIdGenerator).generateId());
|
||||
this.headers.put(ID, (idGenerator != null ? idGenerator : defaultIdGenerator).generateId());
|
||||
this.headers.put(TIMESTAMP, System.currentTimeMillis());
|
||||
}
|
||||
|
||||
@@ -133,20 +136,14 @@ public final class MessageHeaders implements Map<String, Object>, Serializable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return this.headers.hashCode();
|
||||
public boolean equals(Object other) {
|
||||
return (this == other ||
|
||||
(other instanceof MessageHeaders && this.headers.equals(((MessageHeaders) other).headers)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
if (this == object) {
|
||||
return true;
|
||||
}
|
||||
if (object != null && object instanceof MessageHeaders) {
|
||||
MessageHeaders other = (MessageHeaders) object;
|
||||
return this.headers.equals(other.headers);
|
||||
}
|
||||
return false;
|
||||
public int hashCode() {
|
||||
return this.headers.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -157,9 +154,8 @@ public final class MessageHeaders implements Map<String, Object>, Serializable {
|
||||
return map.toString();
|
||||
}
|
||||
|
||||
/*
|
||||
* Map implementation
|
||||
*/
|
||||
|
||||
// Map implementation
|
||||
|
||||
public boolean containsKey(Object key) {
|
||||
return this.headers.containsKey(key);
|
||||
@@ -193,7 +189,8 @@ public final class MessageHeaders implements Map<String, Object>, Serializable {
|
||||
return Collections.unmodifiableCollection(this.headers.values());
|
||||
}
|
||||
|
||||
// Unsupported operations
|
||||
|
||||
// Unsupported Map operations
|
||||
|
||||
/**
|
||||
* Since MessageHeaders are immutable, the call to this method will result in {@link UnsupportedOperationException}.
|
||||
@@ -223,6 +220,7 @@ public final class MessageHeaders implements Map<String, Object>, Serializable {
|
||||
throw new UnsupportedOperationException("MessageHeaders is immutable");
|
||||
}
|
||||
|
||||
|
||||
// Serialization methods
|
||||
|
||||
private void writeObject(ObjectOutputStream out) throws IOException {
|
||||
@@ -234,7 +232,7 @@ public final class MessageHeaders implements Map<String, Object>, Serializable {
|
||||
}
|
||||
for (String key : keysToRemove) {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("removing non-serializable header: " + key);
|
||||
logger.info("Removing non-serializable header: " + key);
|
||||
}
|
||||
this.headers.remove(key);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2014 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.
|
||||
@@ -38,7 +38,7 @@ public interface MessageConverter {
|
||||
* conversion, it should return {@code null}.
|
||||
* @param message the input message
|
||||
* @param targetClass the target class for the conversion
|
||||
* @return the result of the conversion or {@code null} if the converter cannot
|
||||
* @return the result of the conversion, or {@code null} if the converter cannot
|
||||
* perform the conversion
|
||||
*/
|
||||
Object fromMessage(Message<?> message, Class<?> targetClass);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2014 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.
|
||||
@@ -39,7 +39,7 @@ public class SimpleMessageConverter implements MessageConverter {
|
||||
if (targetClass == null) {
|
||||
return payload;
|
||||
}
|
||||
return ClassUtils.isAssignableValue(targetClass, payload) ? payload : null;
|
||||
return (ClassUtils.isAssignableValue(targetClass, payload) ? payload : null);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2014 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.
|
||||
@@ -23,14 +23,13 @@ import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A builder for creating a {@link GenericMessage} (or {@link ErrorMessage} if
|
||||
* the payload is of type {@link Throwable}).
|
||||
* A builder for creating a {@link GenericMessage}
|
||||
* (or {@link ErrorMessage} if the payload is of type {@link Throwable}).
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @author Mark Fisher
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 4.0
|
||||
*
|
||||
* @see GenericMessage
|
||||
* @see ErrorMessage
|
||||
*/
|
||||
@@ -38,16 +37,13 @@ public final class MessageBuilder<T> {
|
||||
|
||||
private final T payload;
|
||||
|
||||
private MessageHeaderAccessor headerAccessor;
|
||||
|
||||
private final Message<T> originalMessage;
|
||||
|
||||
private MessageHeaderAccessor headerAccessor;
|
||||
|
||||
|
||||
/**
|
||||
* Private constructor to be invoked from the static factory methods only.
|
||||
*/
|
||||
private MessageBuilder(T payload, Message<T> originalMessage) {
|
||||
Assert.notNull(payload, "payload must not be null");
|
||||
Assert.notNull(payload, "Payload must not be null");
|
||||
this.payload = payload;
|
||||
this.originalMessage = originalMessage;
|
||||
this.headerAccessor = new MessageHeaderAccessor(originalMessage);
|
||||
@@ -58,11 +54,10 @@ public final class MessageBuilder<T> {
|
||||
* Create a builder for a new {@link Message} instance pre-populated with all of the
|
||||
* headers copied from the provided message. The payload of the provided Message will
|
||||
* also be used as the payload for the new message.
|
||||
*
|
||||
* @param message the Message from which the payload and all headers will be copied
|
||||
*/
|
||||
public static <T> MessageBuilder<T> fromMessage(Message<T> message) {
|
||||
Assert.notNull(message, "message must not be null");
|
||||
Assert.notNull(message, "Message must not be null");
|
||||
return new MessageBuilder<T>(message.getPayload(), message);
|
||||
}
|
||||
|
||||
@@ -76,12 +71,12 @@ public final class MessageBuilder<T> {
|
||||
|
||||
|
||||
/**
|
||||
* Set the message headers.
|
||||
* @param headerAccessor the headers for the message
|
||||
* Set the message headers to use by providing a {@code MessageHeaderAccessor}.
|
||||
* @param accessor the headers to use
|
||||
*/
|
||||
public MessageBuilder<T> setHeaders(MessageHeaderAccessor headerAccessor) {
|
||||
Assert.notNull(headerAccessor, "HeaderAccessor must not be null");
|
||||
this.headerAccessor = headerAccessor;
|
||||
public MessageBuilder<T> setHeaders(MessageHeaderAccessor accessor) {
|
||||
Assert.notNull(accessor, "MessageHeaderAccessor must not be null");
|
||||
this.headerAccessor = accessor;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -161,13 +156,15 @@ public final class MessageBuilder<T> {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Message<T> build() {
|
||||
if ((this.originalMessage != null) && !this.headerAccessor.isModified()) {
|
||||
if (this.originalMessage != null && !this.headerAccessor.isModified()) {
|
||||
return this.originalMessage;
|
||||
}
|
||||
if (this.payload instanceof Throwable) {
|
||||
return (Message<T>) new ErrorMessage((Throwable) this.payload, this.headerAccessor.toMap());
|
||||
}
|
||||
return new GenericMessage<T>(this.payload, this.headerAccessor.toMap());
|
||||
else {
|
||||
return new GenericMessage<T>(this.payload, this.headerAccessor.toMap());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2014 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.
|
||||
@@ -25,10 +25,10 @@ import java.util.UUID;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.messaging.MessageHeaders;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.MimeType;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.PatternMatchUtils;
|
||||
@@ -48,8 +48,7 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
public class MessageHeaderAccessor {
|
||||
|
||||
protected Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
// wrapped read-only message headers
|
||||
private final MessageHeaders originalHeaders;
|
||||
@@ -69,7 +68,7 @@ public class MessageHeaderAccessor {
|
||||
* A constructor for accessing and modifying existing message headers.
|
||||
*/
|
||||
public MessageHeaderAccessor(Message<?> message) {
|
||||
this.originalHeaders = (message != null) ? message.getHeaders() : null;
|
||||
this.originalHeaders = (message != null ? message.getHeaders() : null);
|
||||
}
|
||||
|
||||
|
||||
@@ -109,23 +108,37 @@ public class MessageHeaderAccessor {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.headers.put(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
protected void verifyType(String headerName, Object headerValue) {
|
||||
if (headerName != null && headerValue != null) {
|
||||
if (MessageHeaders.ERROR_CHANNEL.equals(headerName) || MessageHeaders.REPLY_CHANNEL.endsWith(headerName)) {
|
||||
if (!(headerValue instanceof MessageChannel || headerValue instanceof String)) {
|
||||
throw new IllegalArgumentException(
|
||||
"'" + headerName + "' header value must be a MessageChannel or String");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isReadOnly(String headerName) {
|
||||
return MessageHeaders.ID.equals(headerName) || MessageHeaders.TIMESTAMP.equals(headerName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
@@ -134,9 +147,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>();
|
||||
@@ -178,9 +191,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) {
|
||||
@@ -194,8 +207,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) {
|
||||
@@ -251,17 +264,8 @@ public class MessageHeaderAccessor {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getClass().getSimpleName() + " [originalHeaders=" + this.originalHeaders
|
||||
+ ", updated headers=" + this.headers + "]";
|
||||
return getClass().getSimpleName() + " [originalHeaders=" + this.originalHeaders +
|
||||
", updated headers=" + this.headers + "]";
|
||||
}
|
||||
|
||||
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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user