diff options
author | Emmanuel Bourg <ebourg@apache.org> | 2016-11-11 22:59:07 +0100 |
---|---|---|
committer | Emmanuel Bourg <ebourg@apache.org> | 2016-11-11 22:59:07 +0100 |
commit | 0591d269b8b2b33af090ace1ecbd408490618428 (patch) | |
tree | 2b9b277dd7cb0cd3bc6f66fb0a4c79a85293a04b /spring-messaging/src/main/java/org | |
parent | c3df6b7858afaef71fbe0b42cd62f7f12e595bf0 (diff) |
New upstream version 4.3.4
Diffstat (limited to 'spring-messaging/src/main/java/org')
12 files changed, 134 insertions, 164 deletions
diff --git a/spring-messaging/src/main/java/org/springframework/messaging/MessageChannel.java b/spring-messaging/src/main/java/org/springframework/messaging/MessageChannel.java index f64ff0bf..d8712900 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/MessageChannel.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/MessageChannel.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2016 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 @@ public interface MessageChannel { /** * Constant for sending a message without a prescribed timeout. */ - public static final long INDEFINITE_TIMEOUT = -1; + long INDEFINITE_TIMEOUT = -1; /** diff --git a/spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/support/MessageMethodArgumentResolver.java b/spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/support/MessageMethodArgumentResolver.java index a388946f..e247cd9b 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/support/MessageMethodArgumentResolver.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/support/MessageMethodArgumentResolver.java @@ -73,10 +73,9 @@ public class MessageMethodArgumentResolver implements HandlerMethodArgumentResol Class<?> targetPayloadType = getPayloadType(parameter); if (!targetMessageType.isAssignableFrom(message.getClass())) { - String actual = ClassUtils.getQualifiedName(message.getClass()); - String expected = ClassUtils.getQualifiedName(targetMessageType); - throw new MethodArgumentTypeMismatchException(message, parameter, "The actual message type " + - "[" + actual + "] does not match the expected type [" + expected + "]"); + throw new MethodArgumentTypeMismatchException(message, parameter, "Actual message type '" + + ClassUtils.getDescriptiveType(message) + "' does not match expected type '" + + ClassUtils.getQualifiedName(targetMessageType) + "'"); } Object payload = message.getPayload(); @@ -85,11 +84,9 @@ public class MessageMethodArgumentResolver implements HandlerMethodArgumentResol } if (isEmptyPayload(payload)) { - String actual = ClassUtils.getQualifiedName(payload.getClass()); - String expected = ClassUtils.getQualifiedName(targetPayloadType); - throw new MessageConversionException(message, "Cannot convert from the " + - "expected payload type [" + expected + "] to the " + - "actual payload type [" + actual + "] when the payload is empty."); + throw new MessageConversionException(message, "Cannot convert from actual payload type '" + + ClassUtils.getDescriptiveType(payload) + "' to expected payload type '" + + ClassUtils.getQualifiedName(targetPayloadType) + "' when payload is empty"); } payload = convertPayload(message, parameter, targetPayloadType); @@ -132,10 +129,9 @@ public class MessageMethodArgumentResolver implements HandlerMethodArgumentResol } if (result == null) { - String actual = ClassUtils.getQualifiedName(targetPayloadType); - String expected = ClassUtils.getQualifiedName(message.getPayload().getClass()); - throw new MessageConversionException(message, "No converter found to convert payload type [" + - actual + "] to expected payload type [" + expected + "]"); + throw new MessageConversionException(message, "No converter found from actual payload type '" + + ClassUtils.getDescriptiveType(message.getPayload()) + "' to expected payload type '" + + ClassUtils.getQualifiedName(targetPayloadType) + "'"); } return result; } diff --git a/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/InvocableHandlerMethod.java b/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/InvocableHandlerMethod.java index 82932ca8..584fa91a 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/InvocableHandlerMethod.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/InvocableHandlerMethod.java @@ -28,6 +28,7 @@ import org.springframework.core.ParameterNameDiscoverer; import org.springframework.core.ResolvableType; import org.springframework.messaging.Message; import org.springframework.messaging.handler.HandlerMethod; +import org.springframework.util.ClassUtils; import org.springframework.util.ReflectionUtils; /** @@ -106,15 +107,13 @@ public class InvocableHandlerMethod extends HandlerMethod { public Object invoke(Message<?> message, Object... providedArgs) throws Exception { Object[] args = getMethodArgumentValues(message, providedArgs); if (logger.isTraceEnabled()) { - StringBuilder sb = new StringBuilder("Invoking ["); - sb.append(getBeanType().getSimpleName()).append("."); - sb.append(getMethod().getName()).append("] method with arguments "); - sb.append(Arrays.asList(args)); - logger.trace(sb.toString()); + logger.trace("Invoking '" + ClassUtils.getQualifiedMethodName(getMethod(), getBeanType()) + + "' with arguments " + Arrays.toString(args)); } Object returnValue = doInvoke(args); if (logger.isTraceEnabled()) { - logger.trace("Method [" + getMethod().getName() + "] returned [" + returnValue + "]"); + logger.trace("Method [" + ClassUtils.getQualifiedMethodName(getMethod(), getBeanType()) + + "] returned [" + returnValue + "]"); } return returnValue; } diff --git a/spring-messaging/src/main/java/org/springframework/messaging/simp/annotation/support/SendToMethodReturnValueHandler.java b/spring-messaging/src/main/java/org/springframework/messaging/simp/annotation/support/SendToMethodReturnValueHandler.java index dd473a26..5268d925 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/simp/annotation/support/SendToMethodReturnValueHandler.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/simp/annotation/support/SendToMethodReturnValueHandler.java @@ -133,13 +133,11 @@ public class SendToMethodReturnValueHandler implements HandlerMethodReturnValueH @Override public boolean supportsReturnType(MethodParameter returnType) { - if (returnType.hasMethodAnnotation(SendTo.class) || + return (returnType.hasMethodAnnotation(SendTo.class) || AnnotatedElementUtils.hasAnnotation(returnType.getDeclaringClass(), SendTo.class) || returnType.hasMethodAnnotation(SendToUser.class) || - AnnotatedElementUtils.hasAnnotation(returnType.getDeclaringClass(), SendToUser.class)) { - return true; - } - return !this.annotationRequired; + AnnotatedElementUtils.hasAnnotation(returnType.getDeclaringClass(), SendToUser.class) || + !this.annotationRequired); } @Override @@ -188,56 +186,34 @@ public class SendToMethodReturnValueHandler implements HandlerMethodReturnValueH } private Object findAnnotation(MethodParameter returnType) { - Annotation[] annot = new Annotation[4]; - annot[0] = AnnotatedElementUtils.findMergedAnnotation(returnType.getMethod(), SendToUser.class); - annot[1] = AnnotatedElementUtils.findMergedAnnotation(returnType.getMethod(), SendTo.class); - annot[2] = AnnotatedElementUtils.findMergedAnnotation(returnType.getDeclaringClass(), SendToUser.class); - annot[3] = AnnotatedElementUtils.findMergedAnnotation(returnType.getDeclaringClass(), SendTo.class); - - if (annot[0] != null && !ObjectUtils.isEmpty(((SendToUser) annot[0]).value())) { - return annot[0]; + Annotation[] anns = new Annotation[4]; + anns[0] = AnnotatedElementUtils.findMergedAnnotation(returnType.getMethod(), SendToUser.class); + anns[1] = AnnotatedElementUtils.findMergedAnnotation(returnType.getMethod(), SendTo.class); + anns[2] = AnnotatedElementUtils.findMergedAnnotation(returnType.getDeclaringClass(), SendToUser.class); + anns[3] = AnnotatedElementUtils.findMergedAnnotation(returnType.getDeclaringClass(), SendTo.class); + + if (anns[0] != null && !ObjectUtils.isEmpty(((SendToUser) anns[0]).value())) { + return anns[0]; } - if (annot[1] != null && !ObjectUtils.isEmpty(((SendTo) annot[1]).value())) { - return annot[1]; + if (anns[1] != null && !ObjectUtils.isEmpty(((SendTo) anns[1]).value())) { + return anns[1]; } - if (annot[2] != null && !ObjectUtils.isEmpty(((SendToUser) annot[2]).value())) { - return annot[2]; + if (anns[2] != null && !ObjectUtils.isEmpty(((SendToUser) anns[2]).value())) { + return anns[2]; } - if (annot[3] != null && !ObjectUtils.isEmpty(((SendTo) annot[3]).value())) { - return annot[3]; + if (anns[3] != null && !ObjectUtils.isEmpty(((SendTo) anns[3]).value())) { + return anns[3]; } for (int i=0; i < 4; i++) { - if (annot[i] != null) { - return annot[i]; + if (anns[i] != null) { + return anns[i]; } } return null; } - private SendToUser getSendToUser(MethodParameter returnType) { - SendToUser annot = AnnotatedElementUtils.findMergedAnnotation(returnType.getMethod(), SendToUser.class); - if (annot != null && !ObjectUtils.isEmpty(annot.value())) { - return annot; - } - SendToUser typeAnnot = AnnotatedElementUtils.findMergedAnnotation(returnType.getDeclaringClass(), SendToUser.class); - if (typeAnnot != null && !ObjectUtils.isEmpty(typeAnnot.value())) { - return typeAnnot; - } - return (annot != null ? annot : typeAnnot); - } - - private SendTo getSendTo(MethodParameter returnType) { - SendTo sendTo = AnnotatedElementUtils.findMergedAnnotation(returnType.getMethod(), SendTo.class); - if (sendTo != null && !ObjectUtils.isEmpty(sendTo.value())) { - return sendTo; - } - else { - return AnnotatedElementUtils.findMergedAnnotation(returnType.getDeclaringClass(), SendTo.class); - } - } - @SuppressWarnings("unchecked") private PlaceholderResolver initVarResolver(MessageHeaders headers) { String name = DestinationVariableMethodArgumentResolver.DESTINATION_TEMPLATE_VARIABLES_HEADER; @@ -268,7 +244,7 @@ public class SendToMethodReturnValueHandler implements HandlerMethodReturnValueH } return (destination.startsWith("/") ? - new String[] {defaultPrefix + destination} : new String[] {defaultPrefix + "/" + destination}); + new String[] {defaultPrefix + destination} : new String[] {defaultPrefix + '/' + destination}); } private MessageHeaders createHeaders(String sessionId, MethodParameter returnType) { diff --git a/spring-messaging/src/main/java/org/springframework/messaging/simp/config/AbstractBrokerRegistration.java b/spring-messaging/src/main/java/org/springframework/messaging/simp/config/AbstractBrokerRegistration.java index 93a25239..21f225eb 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/simp/config/AbstractBrokerRegistration.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/simp/config/AbstractBrokerRegistration.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2016 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. @@ -50,8 +50,8 @@ public abstract class AbstractBrokerRegistration { this.clientInboundChannel = clientInboundChannel; this.clientOutboundChannel = clientOutboundChannel; - this.destinationPrefixes = (destinationPrefixes != null) - ? Arrays.<String>asList(destinationPrefixes) : Collections.<String>emptyList(); + this.destinationPrefixes = (destinationPrefixes != null ? + Arrays.asList(destinationPrefixes) : Collections.<String>emptyList()); } @@ -67,6 +67,7 @@ public abstract class AbstractBrokerRegistration { return this.destinationPrefixes; } + protected abstract AbstractBrokerMessageHandler getMessageHandler(SubscribableChannel brokerChannel); } diff --git a/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/BufferingStompDecoder.java b/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/BufferingStompDecoder.java index bf521874..e31957e3 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/BufferingStompDecoder.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/BufferingStompDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2016 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,7 +16,6 @@ package org.springframework.messaging.simp.stomp; - import java.nio.ByteBuffer; import java.util.Collections; import java.util.List; @@ -28,7 +27,6 @@ import org.springframework.util.Assert; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; - /** * An extension of {@link org.springframework.messaging.simp.stomp.StompDecoder} * that buffers content remaining in the input ByteBuffer after the parent @@ -45,6 +43,7 @@ import org.springframework.util.MultiValueMap; * * @author Rossen Stoyanchev * @since 4.0.3 + * @see StompDecoder */ public class BufferingStompDecoder { @@ -57,78 +56,57 @@ public class BufferingStompDecoder { private volatile Integer expectedContentLength; + /** + * Create a new {@code BufferingStompDecoder} wrapping the given {@code StompDecoder}. + * @param stompDecoder the target decoder to wrap + * @param bufferSizeLimit the buffer size limit + */ public BufferingStompDecoder(StompDecoder stompDecoder, int bufferSizeLimit) { - Assert.notNull(stompDecoder, "'stompDecoder' is required"); - Assert.isTrue(bufferSizeLimit > 0, "Buffer size must be greater than 0"); + Assert.notNull(stompDecoder, "StompDecoder is required"); + Assert.isTrue(bufferSizeLimit > 0, "Buffer size limit must be greater than 0"); this.stompDecoder = stompDecoder; this.bufferSizeLimit = bufferSizeLimit; } /** - * Return the wrapped - * {@link org.springframework.messaging.simp.stomp.StompDecoder}. + * Return the wrapped {@link StompDecoder}. */ - public StompDecoder getStompDecoder() { + public final StompDecoder getStompDecoder() { return this.stompDecoder; } /** * Return the configured buffer size limit. */ - public int getBufferSizeLimit() { + public final int getBufferSizeLimit() { return this.bufferSizeLimit; } - /** - * Calculate the current buffer size. - */ - public int getBufferSize() { - int size = 0; - for (ByteBuffer buffer : this.chunks) { - size = size + buffer.remaining(); - } - return size; - } - - /** - * Get the expected content length of the currently buffered, incomplete STOMP frame. - */ - public Integer getExpectedContentLength() { - return this.expectedContentLength; - } - /** * Decodes one or more STOMP frames from the given {@code ByteBuffer} into a * list of {@link Message}s. - * * <p>If there was enough data to parse a "content-length" header, then the * value is used to determine how much more data is needed before a new * attempt to decode is made. - * * <p>If there was not enough data to parse the "content-length", or if there * is "content-length" header, every subsequent call to decode attempts to * parse again with all available data. Therefore the presence of a "content-length" * header helps to optimize the decoding of large messages. - * * @param newBuffer a buffer containing new data to decode - * * @return decoded messages or an empty list * @throws StompConversionException raised in case of decoding issues */ public List<Message<byte[]>> decode(ByteBuffer newBuffer) { - this.chunks.add(newBuffer); - checkBufferLimits(); - if (getExpectedContentLength() != null && getBufferSize() < this.expectedContentLength) { + if (this.expectedContentLength != null && getBufferSize() < this.expectedContentLength) { return Collections.<Message<byte[]>>emptyList(); } ByteBuffer bufferToDecode = assembleChunksAndReset(); - MultiValueMap<String, String> headers = new LinkedMultiValueMap<String, String>(); List<Message<byte[]>> messages = this.stompDecoder.decode(bufferToDecode, headers); @@ -140,21 +118,6 @@ public class BufferingStompDecoder { return messages; } - private void checkBufferLimits() { - if (getExpectedContentLength() != null) { - if (getExpectedContentLength() > getBufferSizeLimit()) { - throw new StompConversionException( - "The 'content-length' header " + getExpectedContentLength() + - " exceeds the configured message buffer size limit " + getBufferSizeLimit()); - } - } - if (getBufferSize() > getBufferSizeLimit()) { - throw new StompConversionException("The configured stomp frame buffer size limit of " + - getBufferSizeLimit() + " bytes has been exceeded"); - - } - } - private ByteBuffer assembleChunksAndReset() { ByteBuffer result; if (this.chunks.size() == 1) { @@ -172,4 +135,36 @@ public class BufferingStompDecoder { return result; } + private void checkBufferLimits() { + if (this.expectedContentLength != null) { + if (this.expectedContentLength > this.bufferSizeLimit) { + throw new StompConversionException( + "STOMP 'content-length' header value " + this.expectedContentLength + + " exceeds configured buffer size limit " + this.bufferSizeLimit); + } + } + if (getBufferSize() > this.bufferSizeLimit) { + throw new StompConversionException("The configured STOMP buffer size limit of " + + this.bufferSizeLimit + " bytes has been exceeded"); + } + } + + /** + * Calculate the current buffer size. + */ + public int getBufferSize() { + int size = 0; + for (ByteBuffer buffer : this.chunks) { + size = size + buffer.remaining(); + } + return size; + } + + /** + * Get the expected content length of the currently buffered, incomplete STOMP frame. + */ + public Integer getExpectedContentLength() { + return this.expectedContentLength; + } + } diff --git a/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompClientSupport.java b/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompClientSupport.java index e56b2a37..708f277b 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompClientSupport.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompClientSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 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. @@ -26,15 +26,14 @@ import org.springframework.util.Assert; /** * Base class for STOMP client implementations. * - * <p>Subclasses can connect over WebSocket or TCP using any library. - * When creating a new connection a sub-class can create an instance of - * {@link DefaultStompSession} which extends - * {@link org.springframework.messaging.tcp.TcpConnectionHandler - * TcpConnectionHandler} whose lifecycle methods the sub-class must then invoke. + * <p>Subclasses can connect over WebSocket or TCP using any library. When creating + * a new connection, a subclass can create an instance of @link DefaultStompSession} + * which extends {@link org.springframework.messaging.tcp.TcpConnectionHandler} + * whose lifecycle methods the subclass must then invoke. * - * <p>In effect {@code TcpConnectionHandler} and {@code TcpConnection} are the - * contracts any sub-class must adapt to while using {@link StompEncoder} and - * {@link StompDecoder} to encode and decode STOMP messages. + * <p>In effect, {@code TcpConnectionHandler} and {@code TcpConnection} are the + * contracts that any subclass must adapt to while using {@link StompEncoder} + * and {@link StompDecoder} to encode and decode STOMP messages. * * @author Rossen Stoyanchev * @since 4.2 @@ -58,7 +57,7 @@ public abstract class StompClientSupport { * @param messageConverter the message converter to use */ public void setMessageConverter(MessageConverter messageConverter) { - Assert.notNull(messageConverter, "'messageConverter' must not be null"); + Assert.notNull(messageConverter, "MessageConverter must not be null"); this.messageConverter = messageConverter; } @@ -92,7 +91,7 @@ public abstract class StompClientSupport { * CONNECT frame. The first number represents how often the client will write * or send a heart-beat. The second is how often the server should write. * A value of 0 means no heart-beats. - * <p>By default this is set to "10000,10000" but sub-classes may override + * <p>By default this is set to "10000,10000" but subclasses may override * that default and for example set it to "0,0" if they require a * TaskScheduler to be configured first. * @param heartbeat the value for the CONNECT "heart-beat" header @@ -100,22 +99,23 @@ public abstract class StompClientSupport { * http://stomp.github.io/stomp-specification-1.2.html#Heart-beating</a> */ public void setDefaultHeartbeat(long[] heartbeat) { - Assert.notNull(heartbeat); - Assert.isTrue(heartbeat[0] >= 0 && heartbeat[1] >=0 , "Invalid heart-beat: " + Arrays.toString(heartbeat)); + if (heartbeat == null || heartbeat.length != 2 || heartbeat[0] < 0 || heartbeat[1] < 0) { + throw new IllegalArgumentException("Invalid heart-beat: " + Arrays.toString(heartbeat)); + } this.defaultHeartbeat = heartbeat; } /** - * Return the configured default heart-beat value, never {@code null}. + * Return the configured default heart-beat value (never {@code null}). */ public long[] getDefaultHeartbeat() { return this.defaultHeartbeat; } /** - * Whether heartbeats are enabled. Returns {@code false} if - * {@link #setDefaultHeartbeat defaultHeartbeat} is set to "0,0", and - * {@code true} otherwise. + * Determine whether heartbeats are enabled. + * <p>Returns {@code false} if {@link #setDefaultHeartbeat defaultHeartbeat} + * is set to "0,0", and {@code true} otherwise. */ public boolean isDefaultHeartbeatEnabled() { return (getDefaultHeartbeat() != null && getDefaultHeartbeat()[0] != 0 && getDefaultHeartbeat()[1] != 0); diff --git a/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompDecoder.java b/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompDecoder.java index 28a636a9..3bd92ebe 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompDecoder.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompDecoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 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. @@ -53,7 +53,6 @@ public class StompDecoder { private static final Log logger = LogFactory.getLog(StompDecoder.class); - private MessageHeaderInitializer headerInitializer; diff --git a/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompEncoder.java b/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompEncoder.java index 228fbcdb..86d7a7bf 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompEncoder.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompEncoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2016 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. @@ -19,7 +19,7 @@ package org.springframework.messaging.simp.stomp; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.IOException; -import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -39,14 +39,15 @@ import org.springframework.util.Assert; * @author Andy Wilkinson * @author Rossen Stoyanchev * @since 4.0 + * @see StompDecoder */ -public final class StompEncoder { +public class StompEncoder { private static final byte LF = '\n'; private static final byte COLON = ':'; - private final Log logger = LogFactory.getLog(StompEncoder.class); + private static final Log logger = LogFactory.getLog(StompEncoder.class); /** @@ -78,9 +79,13 @@ public final class StompEncoder { } output.write(StompDecoder.HEARTBEAT_PAYLOAD); } + else { StompCommand command = StompHeaderAccessor.getCommand(headers); - Assert.notNull(command, "Missing STOMP command: " + headers); + if (command == null) { + throw new IllegalStateException("Missing STOMP command: " + headers); + } + output.write(command.toString().getBytes(StompDecoder.UTF8_CHARSET)); output.write(LF); writeHeaders(command, headers, payload, output); @@ -96,8 +101,8 @@ public final class StompEncoder { } } - private void writeHeaders(StompCommand command, Map<String, Object> headers, byte[] payload, DataOutputStream output) - throws IOException { + private void writeHeaders(StompCommand command, Map<String, Object> headers, byte[] payload, + DataOutputStream output) throws IOException { @SuppressWarnings("unchecked") Map<String,List<String>> nativeHeaders = @@ -114,22 +119,25 @@ public final class StompEncoder { boolean shouldEscape = (command != StompCommand.CONNECT && command != StompCommand.CONNECTED); for (Entry<String, List<String>> entry : nativeHeaders.entrySet()) { - byte[] key = encodeHeaderString(entry.getKey(), shouldEscape); if (command.requiresContentLength() && "content-length".equals(entry.getKey())) { continue; } + List<String> values = entry.getValue(); if (StompCommand.CONNECT.equals(command) && StompHeaderAccessor.STOMP_PASSCODE_HEADER.equals(entry.getKey())) { - values = Arrays.asList(StompHeaderAccessor.getPasscode(headers)); + values = Collections.singletonList(StompHeaderAccessor.getPasscode(headers)); } + + byte[] encodedKey = encodeHeaderString(entry.getKey(), shouldEscape); for (String value : values) { - output.write(key); + output.write(encodedKey); output.write(COLON); output.write(encodeHeaderString(value, shouldEscape)); output.write(LF); } } + if (command.requiresContentLength()) { int contentLength = payload.length; output.write("content-length:".getBytes(StompDecoder.UTF8_CHARSET)); diff --git a/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompHeaderAccessor.java b/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompHeaderAccessor.java index dc467a9f..d38f8906 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompHeaderAccessor.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompHeaderAccessor.java @@ -29,21 +29,21 @@ import org.springframework.messaging.simp.SimpMessageHeaderAccessor; import org.springframework.messaging.simp.SimpMessageType; import org.springframework.messaging.support.MessageHeaderAccessor; import org.springframework.util.ClassUtils; +import org.springframework.util.CollectionUtils; import org.springframework.util.MimeType; import org.springframework.util.MimeTypeUtils; import org.springframework.util.StringUtils; /** - * A {@code MessageHeaderAccessor} to use when creating a {@code Message} from a - * decoded STOMP frame, or when encoding a {@code Message} to a STOMP frame. + * A {@code MessageHeaderAccessor} to use when creating a {@code Message} from + * a decoded STOMP frame, or when encoding a {@code Message} to a STOMP frame. * - * <p>When created from STOMP frame content, the actual STOMP headers are stored - * in the native header sub-map managed by the parent class + * <p>When created from STOMP frame content, the actual STOMP headers are + * stored in the native header sub-map managed by the parent class * {@link org.springframework.messaging.support.NativeMessageHeaderAccessor} - * while the parent class - * {@link org.springframework.messaging.simp.SimpMessageHeaderAccessor} manages - * common processing headers some of which are based on STOMP headers (e.g. - * destination, content-type, etc). + * while the parent class {@link SimpMessageHeaderAccessor} manages common + * processing headers some of which are based on STOMP headers + * (e.g. destination, content-type, etc). * * <p>An instance of this class can also be created by wrapping an existing * {@code Message}. That message may have been created with the more generic @@ -210,7 +210,7 @@ public class StompHeaderAccessor extends SimpMessageHeaderAccessor { } trySetStompHeaderForSubscriptionId(); if (getMessageId() == null) { - String messageId = getSessionId() + "-" + messageIdCounter.getAndIncrement(); + String messageId = getSessionId() + '-' + messageIdCounter.getAndIncrement(); setNativeHeader(STOMP_MESSAGE_ID_HEADER, messageId); } } @@ -502,12 +502,8 @@ public class StompHeaderAccessor extends SimpMessageHeaderAccessor { } public static Integer getContentLength(Map<String, List<String>> nativeHeaders) { - if (nativeHeaders.containsKey(STOMP_CONTENT_LENGTH_HEADER)) { - List<String> values = nativeHeaders.get(STOMP_CONTENT_LENGTH_HEADER); - String value = (values != null ? values.get(0) : null); - return Integer.valueOf(value); - } - return null; + List<String> values = nativeHeaders.get(STOMP_CONTENT_LENGTH_HEADER); + return (!CollectionUtils.isEmpty(values) ? Integer.valueOf(values.get(0)) : null); } diff --git a/spring-messaging/src/main/java/org/springframework/messaging/simp/user/MultiServerUserRegistry.java b/spring-messaging/src/main/java/org/springframework/messaging/simp/user/MultiServerUserRegistry.java index bdfb9112..7e24fafd 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/simp/user/MultiServerUserRegistry.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/simp/user/MultiServerUserRegistry.java @@ -77,7 +77,7 @@ public class MultiServerUserRegistry implements SimpUserRegistry, SmartApplicati catch (UnknownHostException ex) { host = "unknown"; } - return host + "-" + UUID.randomUUID(); + return host + '-' + UUID.randomUUID(); } 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 cbd11bb4..967fd664 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 @@ -566,7 +566,7 @@ public class MessageHeaderAccessor { * 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. + * (followed up with an assertion) or where an accessor will be created otherwise. * @return an accessor instance of the specified type, or {@code null} if none * @since 4.1 */ |