diff --git a/spring-websocket/src/main/java/org/springframework/web/socket/AbstractWebSocketMessage.java b/spring-websocket/src/main/java/org/springframework/web/socket/AbstractWebSocketMessage.java index b8e4eaefde..23727cd20f 100644 --- a/spring-websocket/src/main/java/org/springframework/web/socket/AbstractWebSocketMessage.java +++ b/spring-websocket/src/main/java/org/springframework/web/socket/AbstractWebSocketMessage.java @@ -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. @@ -89,11 +89,9 @@ public abstract class AbstractWebSocketMessage implements WebSocketMessage @Override public String toString() { return getClass().getSimpleName() + " payload= " + toStringPayload() - + ", length=" + getPayloadSize() + ", last=" + isLast() + "]"; + + ", byteCount=" + getPayloadLength() + ", last=" + isLast() + "]"; } protected abstract String toStringPayload(); - protected abstract int getPayloadSize(); - } diff --git a/spring-websocket/src/main/java/org/springframework/web/socket/BinaryMessage.java b/spring-websocket/src/main/java/org/springframework/web/socket/BinaryMessage.java index 8212bb0ef5..ab7137f847 100644 --- a/spring-websocket/src/main/java/org/springframework/web/socket/BinaryMessage.java +++ b/spring-websocket/src/main/java/org/springframework/web/socket/BinaryMessage.java @@ -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. @@ -83,7 +83,7 @@ public final class BinaryMessage extends AbstractWebSocketMessage { @Override - protected int getPayloadSize() { + public int getPayloadLength() { return getPayload().remaining(); } diff --git a/spring-websocket/src/main/java/org/springframework/web/socket/PingMessage.java b/spring-websocket/src/main/java/org/springframework/web/socket/PingMessage.java index ea036d0efe..a2c9c0bd77 100644 --- a/spring-websocket/src/main/java/org/springframework/web/socket/PingMessage.java +++ b/spring-websocket/src/main/java/org/springframework/web/socket/PingMessage.java @@ -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. @@ -44,13 +44,13 @@ public final class PingMessage extends AbstractWebSocketMessage { @Override - protected int getPayloadSize() { - return getPayload().remaining(); + public int getPayloadLength() { + return (getPayload() != null) ? getPayload().remaining() : 0; } @Override protected String toStringPayload() { - return getPayload().toString(); + return (getPayload() != null) ? getPayload().toString() : null; } } diff --git a/spring-websocket/src/main/java/org/springframework/web/socket/PongMessage.java b/spring-websocket/src/main/java/org/springframework/web/socket/PongMessage.java index e76fe3e0d1..5ede3a3cf1 100644 --- a/spring-websocket/src/main/java/org/springframework/web/socket/PongMessage.java +++ b/spring-websocket/src/main/java/org/springframework/web/socket/PongMessage.java @@ -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. @@ -44,7 +44,7 @@ public final class PongMessage extends AbstractWebSocketMessage { @Override - protected int getPayloadSize() { + public int getPayloadLength() { return (getPayload() != null) ? getPayload().remaining() : 0; } diff --git a/spring-websocket/src/main/java/org/springframework/web/socket/TextMessage.java b/spring-websocket/src/main/java/org/springframework/web/socket/TextMessage.java index 1be1ac1c97..7d482a3766 100644 --- a/spring-websocket/src/main/java/org/springframework/web/socket/TextMessage.java +++ b/spring-websocket/src/main/java/org/springframework/web/socket/TextMessage.java @@ -16,6 +16,8 @@ package org.springframework.web.socket; +import java.nio.charset.Charset; + /** * A text WebSocket message. * @@ -24,6 +26,10 @@ package org.springframework.web.socket; */ public final class TextMessage extends AbstractWebSocketMessage { + private static final Charset UTF_8 = Charset.forName("UTF-8"); + + private final byte[] bytes; + /** * Create a new text WebSocket message from the given CharSequence payload. @@ -31,6 +37,18 @@ public final class TextMessage extends AbstractWebSocketMessage { */ public TextMessage(CharSequence payload) { super(payload.toString(), true); + this.bytes = null; + } + + /** + * Create a new text WebSocket message from the given byte[]. It is assumed the + * byte array can be encoded into an UTF-8 String. + * + * @param payload the non-null payload + */ + public TextMessage(byte[] payload) { + super(new String(payload, UTF_8)); + this.bytes = payload; } /** @@ -43,17 +61,22 @@ public final class TextMessage extends AbstractWebSocketMessage { */ public TextMessage(CharSequence payload, boolean isLast) { super(payload.toString(), isLast); + this.bytes = null; } @Override - protected int getPayloadSize() { - return getPayload().length(); + public int getPayloadLength() { + return asBytes().length; + } + + public byte[] asBytes() { + return (this.bytes != null ? this.bytes : getPayload().getBytes(UTF_8)); } @Override protected String toStringPayload() { - return (getPayloadSize() > 10) ? getPayload().substring(0, 10) + ".." : getPayload(); + return (getPayloadLength() > 10) ? getPayload().substring(0, 10) + ".." : getPayload(); } } diff --git a/spring-websocket/src/main/java/org/springframework/web/socket/WebSocketMessage.java b/spring-websocket/src/main/java/org/springframework/web/socket/WebSocketMessage.java index 73cb3a0657..5881ed0c34 100644 --- a/spring-websocket/src/main/java/org/springframework/web/socket/WebSocketMessage.java +++ b/spring-websocket/src/main/java/org/springframework/web/socket/WebSocketMessage.java @@ -29,6 +29,12 @@ public interface WebSocketMessage { */ T getPayload(); + + /** + * Return the number of bytes contained in the message. + */ + int getPayloadLength(); + /** * When partial message support is available and requested via * {@link org.springframework.web.socket.WebSocketHandler#supportsPartialMessages()}, diff --git a/spring-websocket/src/main/java/org/springframework/web/socket/messaging/StompSubProtocolHandler.java b/spring-websocket/src/main/java/org/springframework/web/socket/messaging/StompSubProtocolHandler.java index 04506bb068..6bc65fdd6f 100644 --- a/spring-websocket/src/main/java/org/springframework/web/socket/messaging/StompSubProtocolHandler.java +++ b/spring-websocket/src/main/java/org/springframework/web/socket/messaging/StompSubProtocolHandler.java @@ -18,7 +18,6 @@ package org.springframework.web.socket.messaging; import java.io.IOException; import java.nio.ByteBuffer; -import java.nio.charset.Charset; import java.security.Principal; import java.util.Arrays; import java.util.List; @@ -56,13 +55,11 @@ import org.springframework.web.socket.WebSocketSession; public class StompSubProtocolHandler implements SubProtocolHandler { /** - * The name of the header set on the CONNECTED frame indicating the name of the user - * authenticated on the WebSocket session. + * The name of the header set on the CONNECTED frame indicating the name + * of the user authenticated on the WebSocket session. */ public static final String CONNECTED_USER_HEADER = "user-name"; - private static final Charset UTF8_CHARSET = Charset.forName("UTF-8"); - private static final Log logger = LogFactory.getLog(StompSubProtocolHandler.class); @@ -103,12 +100,12 @@ public class StompSubProtocolHandler implements SubProtocolHandler { Throwable decodeFailure = null; try { Assert.isInstanceOf(TextMessage.class, webSocketMessage); - String payload = ((TextMessage) webSocketMessage).getPayload(); - ByteBuffer byteBuffer = ByteBuffer.wrap(payload.getBytes(UTF8_CHARSET)); + TextMessage textMessage = (TextMessage) webSocketMessage; + ByteBuffer byteBuffer = ByteBuffer.wrap(textMessage.asBytes()); message = this.stompDecoder.decode(byteBuffer); if (message == null) { - decodeFailure = new IllegalStateException("Not a valid STOMP frame: " + payload); + decodeFailure = new IllegalStateException("Not a valid STOMP frame: " + textMessage.getPayload()); } } catch (Throwable ex) { @@ -150,9 +147,9 @@ public class StompSubProtocolHandler implements SubProtocolHandler { StompHeaderAccessor headers = StompHeaderAccessor.create(StompCommand.ERROR); headers.setMessage(error.getMessage()); Message message = MessageBuilder.withPayload(new byte[0]).setHeaders(headers).build(); - String payload = new String(this.stompEncoder.encode(message), UTF8_CHARSET); + byte[] bytes = this.stompEncoder.encode(message); try { - session.sendMessage(new TextMessage(payload)); + session.sendMessage(new TextMessage(bytes)); } catch (Throwable ex) { // ignore @@ -203,7 +200,7 @@ public class StompSubProtocolHandler implements SubProtocolHandler { byte[] bytes = this.stompEncoder.encode((Message) message); synchronized(session) { - session.sendMessage(new TextMessage(new String(bytes, UTF8_CHARSET))); + session.sendMessage(new TextMessage(bytes)); } }