29
29
import org .springframework .util .MultiValueMap ;
30
30
31
31
/**
32
- * A decoder for STOMP frames.
32
+ * Decodes STOMP frames from a {@link ByteBuffer}. If the buffer does not contain
33
+ * enough data to form a complete STOMP frame, the buffer is reset and the value
34
+ * returned is {@code null} indicating that no message could be read.
33
35
*
34
36
* @author Andy Wilkinson
37
+ * @author Rossen Stoyanchev
35
38
* @since 4.0
36
39
*/
37
40
public class StompDecoder {
@@ -45,15 +48,18 @@ public class StompDecoder {
45
48
46
49
/**
47
50
* Decodes a STOMP frame in the given {@code buffer} into a {@link Message}.
51
+ * If the given ByteBuffer contains partial STOMP frame content, the method
52
+ * resets the buffer and returns {@code null}.
48
53
*
49
54
* @param buffer The buffer to decode the frame from
50
- * @return The decoded message
55
+ *
56
+ * @return The decoded message or {@code null}
51
57
*/
52
58
public Message <byte []> decode (ByteBuffer buffer ) {
53
- skipLeadingEol (buffer );
54
59
55
60
Message <byte []> decodedMessage = null ;
56
61
62
+ skipLeadingEol (buffer );
57
63
buffer .mark ();
58
64
59
65
String command = readCommand (buffer );
@@ -65,34 +71,38 @@ public Message<byte[]> decode(ByteBuffer buffer) {
65
71
if (payload != null ) {
66
72
StompCommand stompCommand = StompCommand .valueOf (command );
67
73
if ((payload .length > 0 ) && (!stompCommand .isBodyAllowed ())) {
68
- throw new StompConversionException (stompCommand +
69
- " isn't allowed to have a body but has payload length=" + payload .length +
70
- ", headers=" + headers );
74
+ throw new StompConversionException (stompCommand + " shouldn't have but " +
75
+ "has a payload with length=" + payload .length + ", headers=" + headers );
71
76
}
72
-
73
77
decodedMessage = MessageBuilder .withPayload (payload )
74
78
.setHeaders (StompHeaderAccessor .create (stompCommand , headers )).build ();
75
-
76
79
if (logger .isDebugEnabled ()) {
77
80
logger .debug ("Decoded " + decodedMessage );
78
81
}
79
- } else {
80
- if (logger .isDebugEnabled ()) {
81
- logger .debug ("Received incomplete frame. Resetting buffer" );
82
+ }
83
+ else {
84
+ if (logger .isTraceEnabled ()) {
85
+ logger .trace ("Received incomplete frame. Resetting buffer" );
82
86
}
83
87
buffer .reset ();
84
88
}
85
89
}
86
90
else {
87
- decodedMessage = MessageBuilder .withPayload (HEARTBEAT_PAYLOAD ).setHeaders (
88
- StompHeaderAccessor .create (SimpMessageType .HEARTBEAT )).build ();
89
91
if (logger .isTraceEnabled ()) {
90
92
logger .trace ("Decoded heartbeat" );
91
93
}
94
+ decodedMessage = MessageBuilder .withPayload (HEARTBEAT_PAYLOAD ).setHeaders (
95
+ StompHeaderAccessor .create (SimpMessageType .HEARTBEAT )).build ();
92
96
}
93
-
94
97
return decodedMessage ;
98
+ }
95
99
100
+ private void skipLeadingEol (ByteBuffer buffer ) {
101
+ while (true ) {
102
+ if (!isEol (buffer )) {
103
+ break ;
104
+ }
105
+ }
96
106
}
97
107
98
108
private String readCommand (ByteBuffer buffer ) {
@@ -143,17 +153,17 @@ private byte[] readPayload(ByteBuffer buffer, MultiValueMap<String, String> head
143
153
String contentLengthString = headers .getFirst ("content-length" );
144
154
if (contentLengthString != null ) {
145
155
int contentLength = Integer .valueOf (contentLengthString );
146
- byte [] payload = new byte [contentLength ];
147
156
if (buffer .remaining () > contentLength ) {
157
+ byte [] payload = new byte [contentLength ];
148
158
buffer .get (payload );
149
159
if (buffer .get () != 0 ) {
150
160
throw new StompConversionException ("Frame must be terminated with a null octet" );
151
161
}
152
- } else {
162
+ return payload ;
163
+ }
164
+ else {
153
165
return null ;
154
166
}
155
-
156
- return payload ;
157
167
}
158
168
else {
159
169
ByteArrayOutputStream payload = new ByteArrayOutputStream ();
@@ -170,14 +180,6 @@ private byte[] readPayload(ByteBuffer buffer, MultiValueMap<String, String> head
170
180
return null ;
171
181
}
172
182
173
- private void skipLeadingEol (ByteBuffer buffer ) {
174
- while (true ) {
175
- if (!isEol (buffer )) {
176
- break ;
177
- }
178
- }
179
- }
180
-
181
183
private boolean isEol (ByteBuffer buffer ) {
182
184
if (buffer .remaining () > 0 ) {
183
185
byte b = buffer .get ();
0 commit comments