21 changed files with 745 additions and 952 deletions
@ -0,0 +1,163 @@
@@ -0,0 +1,163 @@
|
||||
/* |
||||
* Copyright 2002-2013 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. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.web.messaging; |
||||
|
||||
import java.util.Arrays; |
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
import org.springframework.http.MediaType; |
||||
import org.springframework.messaging.MessageHeaders; |
||||
import org.springframework.util.CollectionUtils; |
||||
|
||||
|
||||
/** |
||||
* |
||||
* @author Rossen Stoyanchev |
||||
* @since 4.0 |
||||
*/ |
||||
public class PubSubHeaders { |
||||
|
||||
private static final String DESTINATIONS = "destinations"; |
||||
|
||||
private static final String CONTENT_TYPE = "contentType"; |
||||
|
||||
private static final String MESSAGE_TYPE = "messageType"; |
||||
|
||||
private static final String SUBSCRIPTION_ID = "subscriptionId"; |
||||
|
||||
private static final String PROTOCOL_MESSAGE_TYPE = "protocolMessageType"; |
||||
|
||||
private static final String SESSION_ID = "sessionId"; |
||||
|
||||
private static final String RAW_HEADERS = "rawHeaders"; |
||||
|
||||
|
||||
private final Map<String, Object> messageHeaders; |
||||
|
||||
private final Map<String, String> rawHeaders; |
||||
|
||||
|
||||
/** |
||||
* Constructor for building new headers. |
||||
* |
||||
* @param messageType the message type |
||||
* @param protocolMessageType the protocol-specific message type or command |
||||
*/ |
||||
public PubSubHeaders(MessageType messageType, Object protocolMessageType) { |
||||
|
||||
this.messageHeaders = new HashMap<String, Object>(); |
||||
this.messageHeaders.put(MESSAGE_TYPE, messageType); |
||||
if (protocolMessageType != null) { |
||||
this.messageHeaders.put(PROTOCOL_MESSAGE_TYPE, protocolMessageType); |
||||
} |
||||
|
||||
this.rawHeaders = new HashMap<String, String>(); |
||||
this.messageHeaders.put(RAW_HEADERS, this.rawHeaders); |
||||
} |
||||
|
||||
public PubSubHeaders() { |
||||
this(MessageType.MESSAGE, null); |
||||
} |
||||
|
||||
/** |
||||
* Constructor for access to existing {@link MessageHeaders}. |
||||
* |
||||
* @param messageHeaders |
||||
*/ |
||||
@SuppressWarnings("unchecked") |
||||
public PubSubHeaders(MessageHeaders messageHeaders, boolean readOnly) { |
||||
|
||||
this.messageHeaders = readOnly ? messageHeaders : new HashMap<String, Object>(messageHeaders); |
||||
this.rawHeaders = this.messageHeaders.containsKey(RAW_HEADERS) ? |
||||
(Map<String, String>) messageHeaders.get(RAW_HEADERS) : new HashMap<String, String>(); |
||||
|
||||
if (this.messageHeaders.get(MESSAGE_TYPE) == null) { |
||||
this.messageHeaders.put(MESSAGE_TYPE, MessageType.MESSAGE); |
||||
} |
||||
} |
||||
|
||||
|
||||
public Map<String, Object> getMessageHeaders() { |
||||
return this.messageHeaders; |
||||
} |
||||
|
||||
public Map<String, String> getRawHeaders() { |
||||
return this.rawHeaders; |
||||
} |
||||
|
||||
public MessageType getMessageType() { |
||||
return (MessageType) this.messageHeaders.get(MESSAGE_TYPE); |
||||
} |
||||
|
||||
public void setProtocolMessageType(Object protocolMessageType) { |
||||
this.messageHeaders.put(PROTOCOL_MESSAGE_TYPE, protocolMessageType); |
||||
} |
||||
|
||||
public Object getProtocolMessageType() { |
||||
return this.messageHeaders.get(PROTOCOL_MESSAGE_TYPE); |
||||
} |
||||
|
||||
public void setDestination(String destination) { |
||||
this.messageHeaders.put(DESTINATIONS, Arrays.asList(destination)); |
||||
} |
||||
|
||||
public String getDestination() { |
||||
@SuppressWarnings("unchecked") |
||||
List<String> destination = (List<String>) messageHeaders.get(DESTINATIONS); |
||||
return CollectionUtils.isEmpty(destination) ? null : destination.get(0); |
||||
} |
||||
|
||||
@SuppressWarnings("unchecked") |
||||
public List<String> getDestinations() { |
||||
return (List<String>) messageHeaders.get(DESTINATIONS); |
||||
} |
||||
|
||||
public void setDestinations(List<String> destinations) { |
||||
if (destinations != null) { |
||||
this.messageHeaders.put(DESTINATIONS, destinations); |
||||
} |
||||
} |
||||
|
||||
public MediaType getContentType() { |
||||
return (MediaType) this.messageHeaders.get(CONTENT_TYPE); |
||||
} |
||||
|
||||
public void setContentType(MediaType mediaType) { |
||||
if (mediaType != null) { |
||||
this.messageHeaders.put(CONTENT_TYPE, mediaType); |
||||
} |
||||
} |
||||
|
||||
public String getSubscriptionId() { |
||||
return (String) this.messageHeaders.get(SUBSCRIPTION_ID); |
||||
} |
||||
|
||||
public void setSubscriptionId(String subscriptionId) { |
||||
this.messageHeaders.put(SUBSCRIPTION_ID, subscriptionId); |
||||
} |
||||
|
||||
public String getSessionId() { |
||||
return (String) this.messageHeaders.get(SESSION_ID); |
||||
} |
||||
|
||||
public void setSessionId(String sessionId) { |
||||
this.messageHeaders.put(SESSION_ID, sessionId); |
||||
} |
||||
|
||||
} |
||||
@ -1,78 +0,0 @@
@@ -1,78 +0,0 @@
|
||||
/* |
||||
* Copyright 2002-2013 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. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.web.messaging.stomp; |
||||
|
||||
import java.nio.charset.Charset; |
||||
|
||||
|
||||
/** |
||||
* |
||||
* @author Rossen Stoyanchev |
||||
* @since 4.0 |
||||
*/ |
||||
public class StompMessage { |
||||
|
||||
public static final Charset CHARSET = Charset.forName("UTF-8"); |
||||
|
||||
private final StompCommand command; |
||||
|
||||
private final StompHeaders headers; |
||||
|
||||
private final byte[] payload; |
||||
|
||||
private String sessionId; |
||||
|
||||
|
||||
public StompMessage(StompCommand command, StompHeaders headers, byte[] payload) { |
||||
this.command = command; |
||||
this.headers = (headers != null) ? headers : new StompHeaders(); |
||||
this.payload = payload; |
||||
} |
||||
|
||||
/** |
||||
* Constructor for empty payload message. |
||||
*/ |
||||
public StompMessage(StompCommand command, StompHeaders headers) { |
||||
this(command, headers, new byte[0]); |
||||
} |
||||
|
||||
public StompCommand getCommand() { |
||||
return this.command; |
||||
} |
||||
|
||||
public StompHeaders getHeaders() { |
||||
return this.headers; |
||||
} |
||||
|
||||
public byte[] getPayload() { |
||||
return this.payload; |
||||
} |
||||
|
||||
public void setSessionId(String sessionId) { |
||||
this.sessionId = sessionId; |
||||
} |
||||
|
||||
public String getSessionId() { |
||||
return this.sessionId; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return "StompMessage [" + command + ", headers=" + this.headers + ", payload=" + new String(this.payload) + "]"; |
||||
} |
||||
|
||||
} |
||||
@ -1,41 +0,0 @@
@@ -1,41 +0,0 @@
|
||||
/* |
||||
* Copyright 2002-2013 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. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.web.messaging.stomp; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
|
||||
/** |
||||
* @author Rossen Stoyanchev |
||||
* @since 4.0 |
||||
*/ |
||||
public interface StompSession { |
||||
|
||||
String getId(); |
||||
|
||||
/** |
||||
* TODO... |
||||
* <p> |
||||
* If the message is a STOMP ERROR message, the session will also be closed. |
||||
*/ |
||||
void sendMessage(StompMessage message) throws IOException; |
||||
|
||||
/** |
||||
* Register a task to be invoked if the underlying connection is closed. |
||||
*/ |
||||
void registerConnectionClosedTask(Runnable task); |
||||
|
||||
} |
||||
@ -1,92 +0,0 @@
@@ -1,92 +0,0 @@
|
||||
/* |
||||
* Copyright 2002-2013 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. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.web.messaging.stomp.socket; |
||||
|
||||
import java.io.IOException; |
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
import org.springframework.util.Assert; |
||||
import org.springframework.web.messaging.stomp.StompCommand; |
||||
import org.springframework.web.messaging.stomp.StompMessage; |
||||
import org.springframework.web.messaging.stomp.StompSession; |
||||
import org.springframework.web.messaging.stomp.support.StompMessageConverter; |
||||
import org.springframework.web.socket.CloseStatus; |
||||
import org.springframework.web.socket.TextMessage; |
||||
import org.springframework.web.socket.WebSocketSession; |
||||
|
||||
|
||||
/** |
||||
* @author Rossen Stoyanchev |
||||
* @since 4.0 |
||||
*/ |
||||
public class WebSocketStompSession implements StompSession { |
||||
|
||||
private final String id; |
||||
|
||||
private WebSocketSession webSocketSession; |
||||
|
||||
private final StompMessageConverter messageConverter; |
||||
|
||||
private final List<Runnable> connectionClosedTasks = new ArrayList<Runnable>(); |
||||
|
||||
|
||||
public WebSocketStompSession(WebSocketSession webSocketSession, StompMessageConverter messageConverter) { |
||||
Assert.notNull(webSocketSession, "webSocketSession is required"); |
||||
this.id = webSocketSession.getId(); |
||||
this.webSocketSession = webSocketSession; |
||||
this.messageConverter = messageConverter; |
||||
} |
||||
|
||||
@Override |
||||
public String getId() { |
||||
return this.id; |
||||
} |
||||
|
||||
@Override |
||||
public void sendMessage(StompMessage message) throws IOException { |
||||
|
||||
Assert.notNull(this.webSocketSession, "Cannot send message without active session"); |
||||
|
||||
try { |
||||
byte[] bytes = this.messageConverter.fromStompMessage(message); |
||||
this.webSocketSession.sendMessage(new TextMessage(new String(bytes, StompMessage.CHARSET))); |
||||
} |
||||
finally { |
||||
if (StompCommand.ERROR.equals(message.getCommand())) { |
||||
this.webSocketSession.close(CloseStatus.PROTOCOL_ERROR); |
||||
this.webSocketSession = null; |
||||
} |
||||
} |
||||
} |
||||
|
||||
public void registerConnectionClosedTask(Runnable task) { |
||||
this.connectionClosedTasks.add(task); |
||||
} |
||||
|
||||
public void handleConnectionClosed() { |
||||
for (Runnable task : this.connectionClosedTasks) { |
||||
try { |
||||
task.run(); |
||||
} |
||||
catch (Throwable t) { |
||||
// ignore
|
||||
} |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -1,102 +0,0 @@
@@ -1,102 +0,0 @@
|
||||
/* |
||||
* Copyright 2002-2013 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. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.web.messaging.stomp.support; |
||||
|
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
|
||||
import org.apache.commons.logging.Log; |
||||
import org.apache.commons.logging.LogFactory; |
||||
import org.springframework.http.MediaType; |
||||
import org.springframework.messaging.MessageHeaders; |
||||
import org.springframework.web.messaging.stomp.StompHeaders; |
||||
|
||||
|
||||
/** |
||||
* @author Rossen Stoyanchev |
||||
* @since 4.0 |
||||
*/ |
||||
public class StompHeaderMapper { |
||||
|
||||
private static Log logger = LogFactory.getLog(StompHeaderMapper.class); |
||||
|
||||
private static final String[][] stompHeaderNames; |
||||
|
||||
static { |
||||
stompHeaderNames = new String[2][StompHeaders.STANDARD_HEADER_NAMES.size()]; |
||||
for (int i=0 ; i < StompHeaders.STANDARD_HEADER_NAMES.size(); i++) { |
||||
stompHeaderNames[0][i] = StompHeaders.STANDARD_HEADER_NAMES.get(i); |
||||
stompHeaderNames[1][i] = "stomp." + StompHeaders.STANDARD_HEADER_NAMES.get(i); |
||||
} |
||||
} |
||||
|
||||
|
||||
public Map<String, Object> toMessageHeaders(StompHeaders stompHeaders) { |
||||
|
||||
Map<String, Object> headers = new HashMap<String, Object>(); |
||||
|
||||
// prefixed STOMP headers
|
||||
for (int i=0; i < stompHeaderNames[0].length; i++) { |
||||
String header = stompHeaderNames[0][i]; |
||||
if (stompHeaders.containsKey(header)) { |
||||
String prefixedHeader = stompHeaderNames[1][i]; |
||||
headers.put(prefixedHeader, stompHeaders.getFirst(header)); |
||||
} |
||||
} |
||||
|
||||
// for generic use (not-prefixed)
|
||||
if (stompHeaders.getDestination() != null) { |
||||
headers.put("destination", stompHeaders.getDestination()); |
||||
} |
||||
if (stompHeaders.getContentType() != null) { |
||||
headers.put("content-type", stompHeaders.getContentType()); |
||||
} |
||||
|
||||
return headers; |
||||
} |
||||
|
||||
public void fromMessageHeaders(MessageHeaders messageHeaders, StompHeaders stompHeaders) { |
||||
|
||||
// prefixed STOMP headers
|
||||
for (int i=0; i < stompHeaderNames[0].length; i++) { |
||||
String prefixedHeader = stompHeaderNames[1][i]; |
||||
if (messageHeaders.containsKey(prefixedHeader)) { |
||||
String header = stompHeaderNames[0][i]; |
||||
stompHeaders.add(header, (String) messageHeaders.get(prefixedHeader)); |
||||
} |
||||
} |
||||
|
||||
// generic (not prefixed)
|
||||
String destination = (String) messageHeaders.get("destination"); |
||||
if (destination != null) { |
||||
stompHeaders.setDestination(destination); |
||||
} |
||||
Object contentType = messageHeaders.get("content-type"); |
||||
if (contentType != null) { |
||||
if (contentType instanceof String) { |
||||
stompHeaders.setContentType(MediaType.valueOf((String) contentType)); |
||||
} |
||||
else if (contentType instanceof MediaType) { |
||||
stompHeaders.setContentType((MediaType) contentType); |
||||
} |
||||
else { |
||||
logger.warn("Invalid contentType class: " + contentType.getClass()); |
||||
} |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,138 @@
@@ -0,0 +1,138 @@
|
||||
/* |
||||
* Copyright 2002-2013 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. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.web.messaging.stomp.support; |
||||
|
||||
import java.util.Collections; |
||||
|
||||
import org.junit.Before; |
||||
import org.junit.Test; |
||||
import org.springframework.messaging.Message; |
||||
import org.springframework.messaging.MessageHeaders; |
||||
import org.springframework.web.messaging.MessageType; |
||||
import org.springframework.web.messaging.stomp.StompHeaders; |
||||
import org.springframework.web.messaging.stomp.StompCommand; |
||||
|
||||
import static org.junit.Assert.*; |
||||
|
||||
/** |
||||
* @author Gary Russell |
||||
* @author Rossen Stoyanchev |
||||
*/ |
||||
public class StompMessageConverterTests { |
||||
|
||||
private StompMessageConverter converter; |
||||
|
||||
|
||||
@Before |
||||
public void setup() { |
||||
this.converter = new StompMessageConverter(); |
||||
} |
||||
|
||||
@Test |
||||
public void connectFrame() throws Exception { |
||||
|
||||
String accept = "accept-version:1.1\n"; |
||||
String host = "host:github.org\n"; |
||||
String frame = "\n\n\nCONNECT\n" + accept + host + "\n"; |
||||
Message<byte[]> message = this.converter.toMessage(frame.getBytes("UTF-8"), "session-123"); |
||||
|
||||
assertEquals(0, message.getPayload().length); |
||||
|
||||
MessageHeaders messageHeaders = message.getHeaders(); |
||||
StompHeaders stompHeaders = new StompHeaders(messageHeaders, true); |
||||
assertEquals(6, stompHeaders.getMessageHeaders().size()); |
||||
assertEquals(MessageType.CONNECT, stompHeaders.getMessageType()); |
||||
assertEquals(StompCommand.CONNECT, stompHeaders.getStompCommand()); |
||||
assertEquals("session-123", stompHeaders.getSessionId()); |
||||
assertNotNull(messageHeaders.get(MessageHeaders.ID)); |
||||
assertNotNull(messageHeaders.get(MessageHeaders.TIMESTAMP)); |
||||
assertEquals(Collections.singleton("1.1"), stompHeaders.getAcceptVersion()); |
||||
assertEquals("github.org", stompHeaders.getRawHeaders().get("host")); |
||||
|
||||
String convertedBack = new String(this.converter.fromMessage(message), "UTF-8"); |
||||
|
||||
assertEquals("CONNECT\n", convertedBack.substring(0,8)); |
||||
assertTrue(convertedBack.contains(accept)); |
||||
assertTrue(convertedBack.contains(host)); |
||||
} |
||||
|
||||
@Test |
||||
public void connectWithEscapes() throws Exception { |
||||
|
||||
String accept = "accept-version:1.1\n"; |
||||
String host = "ho\\c\\ns\\rt:st\\nomp.gi\\cthu\\b.org\n"; |
||||
String frame = "CONNECT\n" + accept + host + "\n"; |
||||
Message<byte[]> message = this.converter.toMessage(frame.getBytes("UTF-8"), "session-123"); |
||||
|
||||
assertEquals(0, message.getPayload().length); |
||||
|
||||
MessageHeaders messageHeaders = message.getHeaders(); |
||||
StompHeaders stompHeaders = new StompHeaders(messageHeaders, true); |
||||
assertEquals(Collections.singleton("1.1"), stompHeaders.getAcceptVersion()); |
||||
assertEquals("st\nomp.gi:thu\\b.org", stompHeaders.getRawHeaders().get("ho:\ns\rt")); |
||||
|
||||
String convertedBack = new String(this.converter.fromMessage(message), "UTF-8"); |
||||
|
||||
assertEquals("CONNECT\n", convertedBack.substring(0,8)); |
||||
assertTrue(convertedBack.contains(accept)); |
||||
assertTrue(convertedBack.contains(host)); |
||||
} |
||||
|
||||
@Test |
||||
public void connectCR12() throws Exception { |
||||
|
||||
String accept = "accept-version:1.2\n"; |
||||
String host = "host:github.org\n"; |
||||
String test = "CONNECT\r\n" + accept.replaceAll("\n", "\r\n") + host.replaceAll("\n", "\r\n") + "\r\n"; |
||||
Message<byte[]> message = this.converter.toMessage(test.getBytes("UTF-8"), "session-123"); |
||||
|
||||
assertEquals(0, message.getPayload().length); |
||||
|
||||
MessageHeaders messageHeaders = message.getHeaders(); |
||||
StompHeaders stompHeaders = new StompHeaders(messageHeaders, true); |
||||
assertEquals(Collections.singleton("1.2"), stompHeaders.getAcceptVersion()); |
||||
assertEquals("github.org", stompHeaders.getRawHeaders().get("host")); |
||||
|
||||
String convertedBack = new String(this.converter.fromMessage(message), "UTF-8"); |
||||
|
||||
assertEquals("CONNECT\n", convertedBack.substring(0,8)); |
||||
assertTrue(convertedBack.contains(accept)); |
||||
assertTrue(convertedBack.contains(host)); |
||||
} |
||||
|
||||
@Test |
||||
public void connectWithEscapesAndCR12() throws Exception { |
||||
|
||||
String accept = "accept-version:1.1\n"; |
||||
String host = "ho\\c\\ns\\rt:st\\nomp.gi\\cthu\\b.org\n"; |
||||
String test = "\n\n\nCONNECT\r\n" + accept.replaceAll("\n", "\r\n") + host.replaceAll("\n", "\r\n") + "\r\n"; |
||||
Message<byte[]> message = this.converter.toMessage(test.getBytes("UTF-8"), "session-123"); |
||||
|
||||
assertEquals(0, message.getPayload().length); |
||||
|
||||
MessageHeaders messageHeaders = message.getHeaders(); |
||||
StompHeaders stompHeaders = new StompHeaders(messageHeaders, true); |
||||
assertEquals(Collections.singleton("1.1"), stompHeaders.getAcceptVersion()); |
||||
assertEquals("st\nomp.gi:thu\\b.org", stompHeaders.getRawHeaders().get("ho:\ns\rt")); |
||||
|
||||
String convertedBack = new String(this.converter.fromMessage(message), "UTF-8"); |
||||
|
||||
assertEquals("CONNECT\n", convertedBack.substring(0,8)); |
||||
assertTrue(convertedBack.contains(accept)); |
||||
assertTrue(convertedBack.contains(host)); |
||||
} |
||||
|
||||
} |
||||
Loading…
Reference in new issue