diff --git a/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompCommand.java b/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompCommand.java index b39d6e53a6..e7be4e7509 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompCommand.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompCommand.java @@ -17,10 +17,9 @@ package org.springframework.messaging.simp.stomp; import java.util.Arrays; +import java.util.Collection; import java.util.HashMap; -import java.util.HashSet; import java.util.Map; -import java.util.Set; import org.springframework.messaging.simp.SimpMessageType; @@ -51,36 +50,38 @@ public enum StompCommand { RECEIPT, ERROR; + private static Map messageTypes = new HashMap(); - private static Map messageTypeLookup = new HashMap(); - - private static Set destinationRequiredLookup = - new HashSet(Arrays.asList(SEND, SUBSCRIBE, MESSAGE)); - - private static Set subscriptionIdRequiredLookup = - new HashSet(Arrays.asList(SUBSCRIBE, UNSUBSCRIBE, MESSAGE)); + private static Collection destinationRequired = Arrays.asList(SEND, SUBSCRIBE, MESSAGE); + private static Collection subscriptionIdRequired = Arrays.asList(SUBSCRIBE, UNSUBSCRIBE, MESSAGE); + private static Collection bodyAllowed = Arrays.asList(SEND, MESSAGE, ERROR); static { - messageTypeLookup.put(StompCommand.CONNECT, SimpMessageType.CONNECT); - messageTypeLookup.put(StompCommand.STOMP, SimpMessageType.CONNECT); - messageTypeLookup.put(StompCommand.SEND, SimpMessageType.MESSAGE); - messageTypeLookup.put(StompCommand.MESSAGE, SimpMessageType.MESSAGE); - messageTypeLookup.put(StompCommand.SUBSCRIBE, SimpMessageType.SUBSCRIBE); - messageTypeLookup.put(StompCommand.UNSUBSCRIBE, SimpMessageType.UNSUBSCRIBE); - messageTypeLookup.put(StompCommand.DISCONNECT, SimpMessageType.DISCONNECT); + messageTypes.put(StompCommand.CONNECT, SimpMessageType.CONNECT); + messageTypes.put(StompCommand.STOMP, SimpMessageType.CONNECT); + messageTypes.put(StompCommand.SEND, SimpMessageType.MESSAGE); + messageTypes.put(StompCommand.MESSAGE, SimpMessageType.MESSAGE); + messageTypes.put(StompCommand.SUBSCRIBE, SimpMessageType.SUBSCRIBE); + messageTypes.put(StompCommand.UNSUBSCRIBE, SimpMessageType.UNSUBSCRIBE); + messageTypes.put(StompCommand.DISCONNECT, SimpMessageType.DISCONNECT); } public SimpMessageType getMessageType() { - SimpMessageType type = messageTypeLookup.get(this); + SimpMessageType type = messageTypes.get(this); return (type != null) ? type : SimpMessageType.OTHER; } public boolean requiresDestination() { - return destinationRequiredLookup.contains(this); + return destinationRequired.contains(this); } public boolean requiresSubscriptionId() { - return subscriptionIdRequiredLookup.contains(this); + return subscriptionIdRequired.contains(this); + } + + public boolean isBodyAllowed() { + return bodyAllowed.contains(this); } } + 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 5b1a0d446b..00f3a59b33 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 @@ -29,9 +29,9 @@ import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; /** - * A decoder for STOMP frames + * A decoder for STOMP frames. * - * @author awilkinson + * @author Andy Wilkinson * @since 4.0 */ public class StompDecoder { @@ -60,8 +60,15 @@ public class StompDecoder { MultiValueMap headers = readHeaders(buffer); byte[] payload = readPayload(buffer, headers); - decodedMessage = MessageBuilder.withPayload(payload).setHeaders( - StompHeaderAccessor.create(StompCommand.valueOf(command), headers)).build(); + StompCommand stompCommand = StompCommand.valueOf(command); + if ((payload.length > 0) && (!stompCommand.isBodyAllowed())) { + throw new StompConversionException(stompCommand + + " isn't allowed to have a body but has payload length=" + payload.length + + ", headers=" + headers); + } + + decodedMessage = MessageBuilder.withPayload(payload) + .setHeaders(StompHeaderAccessor.create(stompCommand, headers)).build(); } else { decodedMessage = MessageBuilder.withPayload(HEARTBEAT_PAYLOAD).setHeaders( 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 603d298834..901260472e 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 @@ -29,7 +29,7 @@ import org.springframework.messaging.Message; import org.springframework.messaging.simp.SimpMessageType; /** - * An encoder for STOMP frames + * An encoder for STOMP frames. * * @author Andy Wilkinson * @since 4.0 diff --git a/spring-messaging/src/main/java/org/springframework/messaging/support/converter/MessageConversionException.java b/spring-messaging/src/main/java/org/springframework/messaging/support/converter/MessageConversionException.java index ae8f863c70..31fdbadd0f 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/support/converter/MessageConversionException.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/support/converter/MessageConversionException.java @@ -20,12 +20,15 @@ import org.springframework.messaging.Message; import org.springframework.messaging.MessagingException; /** + * An exception raised by {@link MessageConverter} implementations. + * * @author Mark Fisher * @since 4.0 */ @SuppressWarnings("serial") public class MessageConversionException extends MessagingException { + public MessageConversionException(String description, Throwable cause) { super(description, cause); } diff --git a/spring-messaging/src/test/java/org/springframework/messaging/simp/stomp/StompCodecTests.java b/spring-messaging/src/test/java/org/springframework/messaging/simp/stomp/StompCodecTests.java index 5854b963eb..5cd5e995c1 100644 --- a/spring-messaging/src/test/java/org/springframework/messaging/simp/stomp/StompCodecTests.java +++ b/spring-messaging/src/test/java/org/springframework/messaging/simp/stomp/StompCodecTests.java @@ -133,6 +133,11 @@ public class StompCodecTests { assertEquals("alpha:bravo\r\n\\", headers.getFirstNativeHeader("a:\r\n\\b")); } + @Test(expected=StompConversionException.class) + public void decodeFrameBodyNotAllowed() { + decode("CONNECT\naccept-version:1.2\n\nThe body of the message\0"); + } + @Test public void decodeMultipleFramesFromSameBuffer() { String frame1 = "SEND\ndestination:test\n\nThe body of the message\0";