Polish spring-websocket code

Minor polish to formatting and assertion messages.
This commit is contained in:
Phillip Webb 2013-06-27 09:52:55 -07:00
parent 2d018e5019
commit 60532cbd1e
77 changed files with 254 additions and 286 deletions

View File

@ -91,8 +91,8 @@ public class DefaultDocumentLoader implements DocumentLoader {
factory.setNamespaceAware(namespaceAware);
if (validationMode != XmlValidationModeDetector.VALIDATION_NONE) {
factory.setFeature("http://apache.org/xml/features/validation/schema", false);
factory.setValidating(true);
if (validationMode == XmlValidationModeDetector.VALIDATION_XSD) {
// Enforce namespace aware for XSD...
factory.setNamespaceAware(true);

View File

@ -13,11 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.web.socket;
import java.nio.ByteBuffer;
/**
* A {@link WebSocketMessage} that contains a binary {@link ByteBuffer} payload.
*
@ -79,6 +79,7 @@ public final class BinaryMessage extends WebSocketMessage<ByteBuffer> {
}
}
/**
* Returns access to the message payload as a byte array. NOTE: the returned array
* should be considered read-only and should not be modified.

View File

@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.web.socket;
import org.eclipse.jetty.websocket.api.StatusCode;
@ -148,8 +149,8 @@ public final class CloseStatus {
/**
* Create a new {@link CloseStatus} instance.
* @param code
* @param reason
* @param code the status code
* @param reason the reason
*/
public CloseStatus(int code, String reason) {
Assert.isTrue((code >= 1000 && code < 5000), "Invalid code");
@ -157,6 +158,7 @@ public final class CloseStatus {
this.reason = reason;
}
/**
* Returns the status code.
*/

View File

@ -16,7 +16,6 @@
package org.springframework.web.socket;
/**
* A {@link WebSocketMessage} that contains a textual {@link String} payload.
*
@ -25,11 +24,9 @@ package org.springframework.web.socket;
*/
public final class TextMessage extends WebSocketMessage<String> {
/**
* Create a new {@link TextMessage} instance.
* @param payload the payload
* @param isLast whether this the last part of a message received or transmitted in parts
*/
public TextMessage(CharSequence payload) {
super(payload.toString(), true);
@ -44,6 +41,7 @@ public final class TextMessage extends WebSocketMessage<String> {
super(payload.toString(), isLast);
}
@Override
protected int getPayloadSize() {
return getPayload().length();

View File

@ -19,18 +19,15 @@ package org.springframework.web.socket;
/**
* A handler for WebSocket messages and lifecycle events.
*
* <p>
* Implementations of this interface are encouraged to handle exceptions locally where it
* makes sense or alternatively let the exception bubble up in which case the exception is
* logged and the session closed with {@link CloseStatus#SERVER_ERROR SERVER_ERROR(1011)}
* by default. The exception handling strategy is provided by
* <p>Implementations of this interface are encouraged to handle exceptions locally where
* it makes sense or alternatively let the exception bubble up in which case the exception
* is logged and the session closed with
* {@link CloseStatus#SERVER_ERROR SERVER_ERROR(1011)} by default. The exception handling
* strategy is provided by
* {@link org.springframework.web.socket.support.ExceptionWebSocketHandlerDecorator
* ExceptionWebSocketHandlerDecorator}, which can be customized or replaced by decorating
* the {@link WebSocketHandler} with a different decorator.
*
* @param <T> The type of message being handled {@link TextMessage}, {@link BinaryMessage}
* (or {@link WebSocketMessage} for both).
*
* @author Rossen Stoyanchev
* @author Phillip Webb
* @since 4.0
@ -40,7 +37,6 @@ public interface WebSocketHandler {
/**
* Invoked after WebSocket negotiation has succeeded and the WebSocket connection is
* opened and ready for use.
*
* @throws Exception this method can handle or propagate exceptions; see class-level
* Javadoc for details.
*/
@ -48,7 +44,6 @@ public interface WebSocketHandler {
/**
* Invoked when a new WebSocket message arrives.
*
* @throws Exception this method can handle or propagate exceptions; see class-level
* Javadoc for details.
*/
@ -56,7 +51,6 @@ public interface WebSocketHandler {
/**
* Handle an error from the underlying WebSocket message transport.
*
* @throws Exception this method can handle or propagate exceptions; see class-level
* Javadoc for details.
*/
@ -67,7 +61,6 @@ public interface WebSocketHandler {
* transport error has occurred. Although the session may technically still be open,
* depending on the underlying implementation, sending messages at this point is
* discouraged and most likely will not succeed.
*
* @throws Exception this method can handle or propagate exceptions; see class-level
* Javadoc for details.
*/

View File

@ -44,6 +44,7 @@ public abstract class WebSocketMessage<T> {
this.last = isLast;
}
/**
* Returns the message payload. This will never be {@code null}.
*/

View File

@ -26,7 +26,6 @@ import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketMessage;
import org.springframework.web.socket.WebSocketSession;
/**
* An abstract base class for implementations of {@link WebSocketSession}.
*

View File

@ -23,7 +23,6 @@ import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketSession;
/**
* A convenient base class for {@link WebSocketHandler} implementation that process binary
* messages only. Text messages are rejected with {@link CloseStatus#NOT_ACCEPTABLE}. All
@ -35,7 +34,6 @@ import org.springframework.web.socket.WebSocketSession;
*/
public class BinaryWebSocketHandlerAdapter extends WebSocketHandlerAdapter {
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) {
try {

View File

@ -21,7 +21,6 @@ import java.security.Principal;
import org.springframework.web.socket.WebSocketSession;
/**
* A WebSocketSession with configurable properties.
*

View File

@ -39,12 +39,12 @@ public class JettyWebSocketListenerAdapter implements WebSocketListener {
private final WebSocketHandler webSocketHandler;
private JettyWebSocketSessionAdapter wsSession;
private final JettyWebSocketSessionAdapter wsSession;
public JettyWebSocketListenerAdapter(WebSocketHandler webSocketHandler, JettyWebSocketSessionAdapter wsSession) {
Assert.notNull(webSocketHandler, "webSocketHandler is required");
Assert.notNull(wsSession, "wsSession is required");
Assert.notNull(webSocketHandler, "webSocketHandler must not be null");
Assert.notNull(wsSession, "wsSession must not be null");
this.webSocketHandler = webSocketHandler;
this.wsSession = wsSession;
}

View File

@ -29,7 +29,6 @@ import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
/**
* Adapts a Jetty {@link org.eclipse.jetty.websocket.api.Session} to
* {@link WebSocketSession}.
@ -48,7 +47,7 @@ public class JettyWebSocketSessionAdapter
@Override
public void initSession(Session session) {
Assert.notNull(session, "session is required");
Assert.notNull(session, "session must not be null");
this.session = session;
}
@ -122,4 +121,4 @@ public class JettyWebSocketSessionAdapter
this.session.close(status.getCode(), status.getReason());
}
}
}

View File

@ -32,7 +32,6 @@ import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.support.ExceptionWebSocketHandlerDecorator;
/**
* Adapts a {@link WebSocketHandler} to a standard {@link Endpoint}.
*
@ -49,8 +48,8 @@ public class StandardEndpointAdapter extends Endpoint {
public StandardEndpointAdapter(WebSocketHandler handler, StandardWebSocketSessionAdapter wsSession) {
Assert.notNull(handler, "handler is required");
Assert.notNull(wsSession, "wsSession is required");
Assert.notNull(handler, "handler must not be null");
Assert.notNull(wsSession, "wsSession must not be null");
this.handler = handler;
this.wsSession = wsSession;
}

View File

@ -48,7 +48,7 @@ public class StandardWebSocketSessionAdapter extends AbstractWebSocketSesssionAd
@Override
public void initSession(javax.websocket.Session session) {
Assert.notNull(session, "session is required");
Assert.notNull(session, "session must not be null");
this.session = session;
}

View File

@ -23,7 +23,6 @@ import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketSession;
/**
* A convenient base class for {@link WebSocketHandler} implementation that process text
* messages only. Binary messages are rejected with {@link CloseStatus#NOT_ACCEPTABLE}. All
@ -35,7 +34,6 @@ import org.springframework.web.socket.WebSocketSession;
*/
public class TextWebSocketHandlerAdapter extends WebSocketHandlerAdapter {
@Override
protected void handleBinaryMessage(WebSocketSession session, BinaryMessage message) {
try {

View File

@ -23,7 +23,6 @@ import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketMessage;
import org.springframework.web.socket.WebSocketSession;
/**
* A convenient base class for {@link WebSocketHandler} implementation with empty methods.
*

View File

@ -48,18 +48,21 @@ public abstract class ConnectionManagerSupport implements SmartLifecycle {
private int phase = Integer.MAX_VALUE;
private TaskExecutor taskExecutor = new SimpleAsyncTaskExecutor("EndpointConnectionManager-");
private final TaskExecutor taskExecutor = new SimpleAsyncTaskExecutor("EndpointConnectionManager-");
private final Object lifecycleMonitor = new Object();
public ConnectionManagerSupport(String uriTemplate, Object... uriVariables) {
this.uri = UriComponentsBuilder.fromUriString(uriTemplate).buildAndExpand(uriVariables).encode().toUri();
this.uri = UriComponentsBuilder.fromUriString(uriTemplate).buildAndExpand(
uriVariables).encode().toUri();
}
/**
* Set whether to auto-connect to the remote endpoint after this connection manager
* has been initialized and the Spring context has been refreshed.
*
* <p>Default is "false".
*/
public void setAutoStartup(boolean autoStartup) {
@ -111,8 +114,7 @@ public abstract class ConnectionManagerSupport implements SmartLifecycle {
}
/**
* Connect to the configured {@link #setDefaultUri(URI) default URI}. If already
* connected, the method has no impact.
* Start the websocket connection. If already connected, the method has no impact.
*/
@Override
public final void start() {

View File

@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.web.socket.client;
import java.net.URI;
@ -25,15 +26,14 @@ import org.springframework.web.socket.WebSocketSession;
* Contract for initiating a WebSocket request. As an alternative considering using the
* declarative style {@link WebSocketConnectionManager} that starts a WebSocket connection
* to a pre-configured URI when the application starts.
*
*
* @author Rossen Stoyanchev
* @since 4.0
*
*
* @see WebSocketConnectionManager
*/
public interface WebSocketClient {
WebSocketSession doHandshake(WebSocketHandler webSocketHandler,
String uriTemplate, Object... uriVariables) throws WebSocketConnectFailureException;

View File

@ -27,7 +27,6 @@ import org.springframework.core.NestedRuntimeException;
@SuppressWarnings("serial")
public class WebSocketConnectFailureException extends NestedRuntimeException {
public WebSocketConnectFailureException(String msg, Throwable cause) {
super(msg, cause);
}

View File

@ -57,10 +57,11 @@ public class WebSocketConnectionManager extends ConnectionManagerSupport {
this.syncClientLifecycle = ((client instanceof SmartLifecycle) && !((SmartLifecycle) client).isRunning());
}
/**
* Decorate the WebSocketHandler provided to the class constructor.
* <p>
* By default {@link LoggingWebSocketHandlerDecorator} is added.
*
* <p>By default {@link LoggingWebSocketHandlerDecorator} is added.
*/
protected WebSocketHandler decorateWebSocketHandler(WebSocketHandler handler) {
return new LoggingWebSocketHandlerDecorator(handler);
@ -88,7 +89,7 @@ public class WebSocketConnectionManager extends ConnectionManagerSupport {
@Override
public void stopInternal() throws Exception {
if (this.syncClientLifecycle) {
((SmartLifecycle) client).stop();
((SmartLifecycle) this.client).stop();
}
super.stopInternal();
}

View File

@ -61,14 +61,14 @@ public class EndpointConnectionManager extends ConnectionManagerSupport implemen
public EndpointConnectionManager(Endpoint endpoint, String uriTemplate, Object... uriVariables) {
super(uriTemplate, uriVariables);
Assert.notNull(endpoint, "endpoint is required");
Assert.notNull(endpoint, "endpoint must not be null");
this.endpointProvider = null;
this.endpoint = endpoint;
}
public EndpointConnectionManager(Class<? extends Endpoint> endpointClass, String uriTemplate, Object... uriVars) {
super(uriTemplate, uriVars);
Assert.notNull(endpointClass, "endpointClass is required");
Assert.notNull(endpointClass, "endpointClass must not be null");
this.endpointProvider = new BeanCreatingHandlerProvider<Endpoint>(endpointClass);
this.endpoint = null;
}

View File

@ -45,7 +45,7 @@ import org.springframework.web.util.UriComponentsBuilder;
/**
* Initiates WebSocket requests to a WebSocket server programatically through the standard
* Java WebSocket API .
* Java WebSocket API.
*
* @author Rossen Stoyanchev
* @since 4.0
@ -62,15 +62,16 @@ public class StandardWebSocketClient implements WebSocketClient {
}
public StandardWebSocketClient(WebSocketContainer webSocketContainer) {
Assert.notNull(webSocketContainer, "webSocketContainer is required");
Assert.notNull(webSocketContainer, "webSocketContainer must not be null");
this.webSocketContainer = webSocketContainer;
}
@Override
public WebSocketSession doHandshake(WebSocketHandler webSocketHandler, String uriTemplate, Object... uriVariables)
throws WebSocketConnectFailureException {
Assert.notNull(uriTemplate, "uriTemplate is required");
Assert.notNull(uriTemplate, "uriTemplate must not be null");
UriComponents uriComponents = UriComponentsBuilder.fromUriString(uriTemplate).buildAndExpand(uriVariables).encode();
return doHandshake(webSocketHandler, null, uriComponents.toUri());
}
@ -79,8 +80,8 @@ public class StandardWebSocketClient implements WebSocketClient {
public WebSocketSession doHandshake(WebSocketHandler webSocketHandler, HttpHeaders httpHeaders, URI uri)
throws WebSocketConnectFailureException {
Assert.notNull(webSocketHandler, "webSocketHandler is required");
Assert.notNull(uri, "uri is required");
Assert.notNull(webSocketHandler, "webSocketHandler must not be null");
Assert.notNull(uri, "uri must not be null");
httpHeaders = (httpHeaders != null) ? httpHeaders : new HttpHeaders();

View File

@ -32,8 +32,10 @@ import org.springframework.web.socket.client.WebSocketConnectFailureException;
import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;
/**
* Initiates WebSocket requests to a WebSocket server programatically through the Jetty
* WebSocket API.
*
* @author Rossen Stoyanchev
* @since 4.0
*/
@ -134,8 +136,8 @@ public class JettyWebSocketClient implements WebSocketClient, SmartLifecycle {
public WebSocketSession doHandshake(WebSocketHandler webSocketHandler, HttpHeaders headers, URI uri)
throws WebSocketConnectFailureException {
Assert.notNull(webSocketHandler, "webSocketHandler is required");
Assert.notNull(uri, "uri is required");
Assert.notNull(webSocketHandler, "webSocketHandler must not be null");
Assert.notNull(uri, "uri must not be null");
if (logger.isDebugEnabled()) {
logger.debug("Connecting to " + uri);

View File

@ -41,8 +41,8 @@ import org.springframework.web.socket.WebSocketHandler;
/**
* A default implemnetation of {@link HandshakeHandler}.
* <p>
* A container-specific {@link RequestUpgradeStrategy} is required since standard Java
*
* <p>A container-specific {@link RequestUpgradeStrategy} is required since standard Java
* WebSocket currently does not provide a way to initiate a WebSocket handshake.
* Currently available are implementations for Tomcat and GlassFish.
*
@ -57,7 +57,7 @@ public class DefaultHandshakeHandler implements HandshakeHandler {
private List<String> supportedProtocols = new ArrayList<String>();
private RequestUpgradeStrategy requestUpgradeStrategy;
private final RequestUpgradeStrategy requestUpgradeStrategy;
/**

View File

@ -18,14 +18,13 @@ package org.springframework.web.socket.server;
import org.springframework.core.NestedRuntimeException;
/**
* Thrown when handshake processing failed to complete due to an internal, unrecoverable
* error. This implies a server error (HTTP status code 500) as opposed to a failure in
* the handshake negotiation.
* <p>
* By contrast, when handshake negotiation fails, the response status code will be 200 and
* the response headers and body will have been updated to reflect the cause for the
*
* <p>By contrast, when handshake negotiation fails, the response status code will be 200
* and the response headers and body will have been updated to reflect the cause for the
* failure. A {@link HandshakeHandler} implementation will have protected methods to
* customize updates to the response in those cases.
*
@ -35,7 +34,6 @@ import org.springframework.core.NestedRuntimeException;
@SuppressWarnings("serial")
public class HandshakeFailureException extends NestedRuntimeException {
public HandshakeFailureException(String msg, Throwable cause) {
super(msg, cause);
}

View File

@ -33,7 +33,6 @@ import org.springframework.web.socket.support.PerConnectionWebSocketHandler;
*/
public interface HandshakeHandler {
/**
* Initiate the handshake.
*

View File

@ -43,10 +43,10 @@ import org.springframework.util.ReflectionUtils;
* {@link ServerEndpoint} and registers them as well. Although not required, it is likely
* annotated endpoints should have their {@code configurator} property set to
* {@link SpringConfigurator}.
* <p>
* When this class is used, by declaring it in Spring configuration, it should be possible
* to turn off a Servlet container's scan for WebSocket endpoints. This can be done with
* the help of the {@code <absolute-ordering>} element in web.xml.
*
* <p>When this class is used, by declaring it in Spring configuration, it should be
* possible to turn off a Servlet container's scan for WebSocket endpoints. This can be
* done with the help of the {@code <absolute-ordering>} element in web.xml.
*
* @author Rossen Stoyanchev
* @since 4.0
@ -123,7 +123,7 @@ public class ServerEndpointExporter implements InitializingBean, BeanPostProcess
@Override
public void afterPropertiesSet() throws Exception {
Assert.notNull(serverContainer, "javax.websocket.server.ServerContainer not available");
Assert.state(this.serverContainer != null, "javax.websocket.server.ServerContainer not available");
List<Class<?>> allClasses = new ArrayList<Class<?>>(this.annotatedEndpointClasses);
allClasses.addAll(this.annotatedEndpointBeanTypes);

View File

@ -35,14 +35,13 @@ import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.util.Assert;
import org.springframework.web.socket.support.BeanCreatingHandlerProvider;
/**
* An implementation of {@link javax.websocket.server.ServerEndpointConfig} that also
* contains the target {@link javax.websocket.Endpoint}, provided either as a reference or
* as a bean name.
* <p>
* {@link ServerEndpointRegistration} beans are detected by {@link ServerEndpointExporter}
* and registered with a Java WebSocket runtime at startup.
*
* <p>{@link ServerEndpointRegistration} beans are detected by
* {@link ServerEndpointExporter} and registered with a Java WebSocket runtime at startup.
*
* @author Rossen Stoyanchev
* @since 4.0
@ -67,26 +66,32 @@ public class ServerEndpointRegistration implements ServerEndpointConfig, BeanFac
private final Map<String, Object> userProperties = new HashMap<String, Object>();
private Configurator configurator = new EndpointRegistrationConfigurator();
private final Configurator configurator = new EndpointRegistrationConfigurator();
/**
* Class constructor with the {@code javax.webscoket.Endpoint} class.
*
* @param path
* @param endpointClass
* Create a new {@link ServerEndpointRegistration} instance from an
* {@code javax.webscoket.Endpoint} class.
* @param path the endpoint path
* @param endpointClass the endpoint class
*/
public ServerEndpointRegistration(String path, Class<? extends Endpoint> endpointClass) {
Assert.hasText(path, "path must not be empty");
Assert.notNull(endpointClass, "endpointClass is required");
Assert.notNull(endpointClass, "endpointClass must not be null");
this.path = path;
this.endpointProvider = new BeanCreatingHandlerProvider<Endpoint>(endpointClass);
this.endpoint = null;
}
/**
* Create a new {@link ServerEndpointRegistration} instance from an
* {@code javax.webscoket.Endpoint} instance.
* @param path the endpoint path
* @param endpoint the endpoint instance
*/
public ServerEndpointRegistration(String path, Endpoint endpoint) {
Assert.hasText(path, "path must not be empty");
Assert.notNull(endpoint, "endpoint is required");
Assert.notNull(endpoint, "endpoint must not be null");
this.path = path;
this.endpointProvider = null;
this.endpoint = endpoint;
@ -188,7 +193,7 @@ public class ServerEndpointRegistration implements ServerEndpointConfig, BeanFac
@SuppressWarnings("unchecked")
@Override
public <T> T getEndpointInstance(Class<T> clazz) throws InstantiationException {
return (T) ServerEndpointRegistration.this.getEndpoint();
return (T) getEndpoint();
}
@Override

View File

@ -33,9 +33,9 @@ import org.springframework.web.socket.sockjs.SockJsService;
* {@code javax.servlet.ServletContext} attribute, simply declaring this FactoryBean and
* using its setters allows configuring the {@code ServerContainer} through Spring
* configuration.
* <p>
* This is useful even if the {@code ServerContainer} is not injected into any other bean.
* For example, an application can configure a {@link DefaultHandshakeHandler}, a
*
* <p>This is useful even if the {@code ServerContainer} is not injected into any other
* bean. For example, an application can configure a {@link DefaultHandshakeHandler}, a
* {@link SockJsService}, or {@link ServerEndpointExporter}, and separately declare this
* FactoryBean in order to customize the properties of the (one and only)
* {@code ServerContainer} instance.
@ -112,8 +112,8 @@ public class ServletServerContainerFactoryBean
@Override
public void afterPropertiesSet() throws Exception {
Assert.notNull(this.serverContainer,
"A ServletContext is required to access the javax.websocket.server.ServerContainer instance");
Assert.state(this.serverContainer != null, "A ServletContext is required to "
+ "access the javax.websocket.server.ServerContainer instance");
if (this.asyncSendTimeout != null) {
this.serverContainer.setAsyncSendTimeout(this.asyncSendTimeout);

View File

@ -29,6 +29,7 @@ import org.springframework.web.context.WebApplicationContext;
/**
* A {@link javax.websocket.server.ServerEndpointConfig.Configurator} for initializing
* {@link ServerEndpoint}-annotated classes through Spring.
*
* <p>
* <pre class="code">
* &#064;ServerEndpoint(value = "/echo", configurator = SpringConfigurator.class)

View File

@ -21,7 +21,6 @@ import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.adapter.ConfigurableWebSocketSession;
/**
* Copies information from the handshake HTTP request and response to a given
* {@link WebSocketSession}.
@ -31,7 +30,6 @@ import org.springframework.web.socket.adapter.ConfigurableWebSocketSession;
*/
public class ServerWebSocketSessionInitializer {
public void initialize(ServerHttpRequest request, ServerHttpResponse response, ConfigurableWebSocketSession session) {
session.setUri(request.getURI());
session.setRemoteHostName(request.getRemoteHostName());

View File

@ -35,14 +35,15 @@ import org.springframework.web.socket.support.ExceptionWebSocketHandlerDecorator
import org.springframework.web.socket.support.LoggingWebSocketHandlerDecorator;
/**
* An {@link HttpRequestHandler} for processing WebSocket handshake requests.
* <p>
* This is the main class to use when configuring a server WebSocket at a specific URL. It
* is a very thin wrapper around a {@link HandshakeHandler} and a {@link WebSocketHandler}
* instance also adapting the {@link HttpServletRequest} and {@link HttpServletResponse}
* to {@link ServerHttpRequest} and {@link ServerHttpResponse} respectively.
* <p>
* The {@link #decorateWebSocketHandler(WebSocketHandler)} method decorates the given
* A {@link HttpRequestHandler} for processing WebSocket handshake requests.
*
* <p>This is the main class to use when configuring a server WebSocket at a specific URL.
* It is a very thin wrapper around a {@link HandshakeHandler} and a
* {@link WebSocketHandler} instance also adapting the {@link HttpServletRequest} and
* {@link HttpServletResponse} to {@link ServerHttpRequest} and {@link ServerHttpResponse}
* respectively.
*
* <p>The {@link #decorateWebSocketHandler(WebSocketHandler)} method decorates the given
* WebSocketHandler with a logging and exception handling decorators. This method can
* be overridden to change that.
*
@ -61,16 +62,17 @@ public class WebSocketHttpRequestHandler implements HttpRequestHandler {
}
public WebSocketHttpRequestHandler( WebSocketHandler webSocketHandler, HandshakeHandler handshakeHandler) {
Assert.notNull(webSocketHandler, "webSocketHandler is required");
Assert.notNull(handshakeHandler, "handshakeHandler is required");
Assert.notNull(webSocketHandler, "webSocketHandler must not be null");
Assert.notNull(handshakeHandler, "handshakeHandler must not be null");
this.webSocketHandler = decorateWebSocketHandler(webSocketHandler);
this.handshakeHandler = new DefaultHandshakeHandler();
}
/**
* Decorate the WebSocketHandler provided to the class constructor.
* <p>
* By default {@link ExceptionWebSocketHandlerDecorator} and
*
* <p>By default {@link ExceptionWebSocketHandlerDecorator} and
* {@link LoggingWebSocketHandlerDecorator} are applied are added.
*/
protected WebSocketHandler decorateWebSocketHandler(WebSocketHandler handler) {

View File

@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.web.socket.sockjs;
import java.io.IOException;
@ -27,6 +28,7 @@ import java.util.List;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.TimeUnit;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@ -48,8 +50,8 @@ import org.springframework.web.socket.WebSocketHandler;
* support, SockJS path resolution, and processing for static SockJS requests (e.g.
* "/info", "/iframe.html", etc). Sub-classes are responsible for handling transport
* requests.
* <p>
* It is expected that this service is mapped correctly to one or more prefixes such as
*
* <p>It is expected that this service is mapped correctly to one or more prefixes such as
* "/echo" including all sub-URLs (e.g. "/echo/**"). A SockJS service itself is generally
* unaware of request mapping details but nevertheless must be able to extract the SockJS
* path, which is the portion of the request path following the prefix. In most cases,
@ -63,7 +65,7 @@ public abstract class AbstractSockJsService implements SockJsService, SockJsConf
protected final Log logger = LogFactory.getLog(getClass());
private static final int ONE_YEAR = 365 * 24 * 60 * 60;
private static final long ONE_YEAR = TimeUnit.DAYS.toSeconds(365);
private String name = "SockJSService@" + ObjectUtils.getIdentityHexString(this);
@ -88,10 +90,11 @@ public abstract class AbstractSockJsService implements SockJsService, SockJsConf
public AbstractSockJsService(TaskScheduler scheduler) {
Assert.notNull(scheduler, "scheduler is required");
Assert.notNull(scheduler, "scheduler must not be null");
this.taskScheduler = scheduler;
}
/**
* A unique name for the service mainly for logging purposes.
*/
@ -107,8 +110,8 @@ public abstract class AbstractSockJsService implements SockJsService, SockJsConf
* Use this property to configure one or more prefixes that this SockJS service is
* allowed to serve. The prefix (e.g. "/echo") is needed to extract the SockJS
* specific portion of the URL (e.g. "${prefix}/info", "${prefix}/iframe.html", etc).
* <p>
* This property is not strictly required. In most cases, the SockJS path can be
*
* <p>This property is not strictly required. In most cases, the SockJS path can be
* auto-detected since the initial request from the SockJS client is of the form
* "{prefix}/info". Assuming the SockJS service is mapped correctly (e.g. using
* Ant-style pattern "/echo/**") this should work fine. This property can be used
@ -144,8 +147,8 @@ public abstract class AbstractSockJsService implements SockJsService, SockJsConf
* a domain local to the SockJS server. The iframe does need to load the
* SockJS javascript client library and this option allows configuring its
* url.
* <p>
* By default this is set to point to
*
* <p>By default this is set to point to
* "https://d1fxtkz8shb9d2.cloudfront.net/sockjs-0.3.4.min.js".
*/
public AbstractSockJsService setSockJsClientLibraryUrl(String clientLibraryUrl) {
@ -168,15 +171,15 @@ public abstract class AbstractSockJsService implements SockJsService, SockJsConf
@Override
public int getStreamBytesLimit() {
return streamBytesLimit;
return this.streamBytesLimit;
}
/**
* Some load balancers do sticky sessions, but only if there is a JSESSIONID
* cookie. Even if it is set to a dummy value, it doesn't matter since
* session information is added by the load balancer.
* <p>
* Set this option to indicate if a JSESSIONID cookie should be created. The
*
* <p>Set this option to indicate if a JSESSIONID cookie should be created. The
* default value is "true".
*/
public AbstractSockJsService setJsessionIdCookieRequired(boolean jsessionIdCookieRequired) {
@ -211,8 +214,8 @@ public abstract class AbstractSockJsService implements SockJsService, SockJsConf
* The amount of time in milliseconds before a client is considered
* disconnected after not having a receiving connection, i.e. an active
* connection over which the server can send data to the client.
* <p>
* The default value is 5000.
*
* <p>The default value is 5000.
*/
public void setDisconnectDelay(long disconnectDelay) {
this.disconnectDelay = disconnectDelay;
@ -228,8 +231,8 @@ public abstract class AbstractSockJsService implements SockJsService, SockJsConf
/**
* Some load balancers don't support websockets. This option can be used to
* disable the WebSocket transport on the server side.
* <p>
* The default value is "true".
*
* <p>The default value is "true".
*/
public void setWebSocketsEnabled(boolean webSocketsEnabled) {
this.webSocketsEnabled = webSocketsEnabled;
@ -245,12 +248,6 @@ public abstract class AbstractSockJsService implements SockJsService, SockJsConf
/**
* TODO
*
* @param request
* @param response
* @param sockJsPath
*
* @throws Exception
*/
@Override
public final void handleRequest(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler handler)
@ -441,6 +438,7 @@ public abstract class AbstractSockJsService implements SockJsService, SockJsConf
void handle(ServerHttpRequest request, ServerHttpResponse response) throws IOException;
}
private static final Random random = new Random();
private final SockJsRequestHandler infoHandler = new SockJsRequestHandler() {

View File

@ -34,7 +34,6 @@ import org.springframework.web.socket.WebSocketMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.adapter.ConfigurableWebSocketSession;
/**
* An abstract base class SockJS sessions implementing {@link WebSocketSession}.
*
@ -58,24 +57,26 @@ public abstract class AbstractSockJsSession implements ConfigurableWebSocketSess
private final SockJsConfiguration sockJsConfig;
private WebSocketHandler handler;
private final WebSocketHandler handler;
private State state = State.NEW;
private long timeCreated = System.currentTimeMillis();
private final long timeCreated = System.currentTimeMillis();
private long timeLastActive = timeCreated;
private long timeLastActive = this.timeCreated;
private ScheduledFuture<?> heartbeatTask;
/**
* @param sessionId
* @param sessionId the session ID
* @param config the sockJS configuration
* @param webSocketHandler the recipient of SockJS messages
*/
public AbstractSockJsSession(String sessionId, SockJsConfiguration config, WebSocketHandler webSocketHandler) {
Assert.notNull(sessionId, "sessionId is required");
Assert.notNull(webSocketHandler, "webSocketHandler is required");
public AbstractSockJsSession(String sessionId, SockJsConfiguration config,
WebSocketHandler webSocketHandler) {
Assert.notNull(sessionId, "sessionId must not be null");
Assert.notNull(webSocketHandler, "webSocketHandler must not be null");
this.id = sessionId;
this.handler = webSocketHandler;
this.sockJsConfig = config;
@ -191,7 +192,7 @@ public abstract class AbstractSockJsSession implements ConfigurableWebSocketSess
/**
* Invoked in reaction to the underlying connection being closed by the remote side
* (or the WebSocket container) in order to perform cleanup and notify the
* {@link TextMessageHandler}. This is in contrast to {@link #close()} that pro-actively
* {@link WebSocketHandler}. This is in contrast to {@link #close()} that pro-actively
* closes the connection.
*/
public final void delegateConnectionClosed(CloseStatus status) throws Exception {
@ -224,7 +225,8 @@ public abstract class AbstractSockJsSession implements ConfigurableWebSocketSess
/**
* {@inheritDoc}
* <p>Performs cleanup and notifies the {@link SockJsHandler}.
*
* <p>Performs cleanup and notifies the {@link WebSocketHandler}.
*/
@Override
public final void close() throws IOException {
@ -233,7 +235,8 @@ public abstract class AbstractSockJsSession implements ConfigurableWebSocketSess
/**
* {@inheritDoc}
* <p>Performs cleanup and notifies the {@link SockJsHandler}.
*
* <p>Performs cleanup and notifies the {@link WebSocketHandler}.
*/
@Override
public final void close(CloseStatus status) throws IOException {
@ -329,7 +332,7 @@ public abstract class AbstractSockJsSession implements ConfigurableWebSocketSess
}
protected void scheduleHeartbeat() {
Assert.notNull(this.sockJsConfig.getTaskScheduler(), "heartbeatScheduler not configured");
Assert.state(this.sockJsConfig.getTaskScheduler() != null, "heartbeatScheduler not configured");
cancelHeartbeat();
if (!isActive()) {
return;

View File

@ -35,8 +35,8 @@ public interface SockJsConfiguration {
* closed. After that client will open a new request. Setting this value to
* one effectively disables streaming and will make streaming transports to
* behave like polling transports.
* <p>
* The default value is 128K (i.e. 128 * 1024).
*
* <p>The default value is 128K (i.e. 128 * 1024).
*/
public int getStreamBytesLimit();
@ -44,8 +44,8 @@ public interface SockJsConfiguration {
* The amount of time in milliseconds when the server has not sent any
* messages and after which the server should send a heartbeat frame to the
* client in order to keep the connection from breaking.
* <p>
* The default value is 25,000 (25 seconds).
*
* <p>The default value is 25,000 (25 seconds).
*/
public long getHeartbeatTime();

View File

@ -44,7 +44,7 @@ public class SockJsFrame {
private SockJsFrame(String content) {
Assert.notNull("content is required");
Assert.notNull("content must not be null");
this.content = content;
}
@ -144,7 +144,7 @@ public class SockJsFrame {
}
public static String prepareContent(String... messages) {
Assert.notNull(messages, "messages required");
Assert.notNull(messages, "messages must not be null");
StringBuilder sb = new StringBuilder();
sb.append("a[");
for (int i=0; i < messages.length; i++) {
@ -172,14 +172,12 @@ public class SockJsFrame {
private final String format;
public DefaultFrameFormat(String format) {
Assert.notNull(format, "format is required");
Assert.notNull(format, "format must not be null");
this.format = format;
}
/**
*
* @param format a String with a single %s formatting character where the
* frame content is to be inserted; e.g. "data: %s\r\n\r\n"
* @param frame the SockJs frame.
* @return new SockJsFrame instance with the formatted content
*/
@Override

View File

@ -32,7 +32,6 @@ import org.springframework.web.socket.WebSocketHandler;
*/
public interface SockJsService {
void handleRequest(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler handler)
throws IOException, TransportErrorException;

View File

@ -22,7 +22,6 @@ import org.springframework.web.socket.WebSocketHandler;
* A factory for creating a SockJS session. {@link TransportHandler}s typically also serve
* as SockJS session factories.
*
* @param <S> The type of session being created
* @author Rossen Stoyanchev
* @since 4.0
*/

View File

@ -19,15 +19,14 @@ package org.springframework.web.socket.sockjs;
import org.springframework.core.NestedRuntimeException;
import org.springframework.web.socket.WebSocketHandler;
/**
* Raised when a TransportHandler fails during request processing.
* <p>
* If the underlying exception occurs while sending messages to the client, the session is
* closed and the {@link WebSocketHandler} notified.
* <p>
* If the underlying exception occurs while processing an incoming HTTP request, including
* over HTTP POST, the session will remain open. Only the incoming request is rejected.
* Raised when a TransportHandler fails during request processing. If the underlying
* exception occurs while sending messages to the client, the session is closed and the
* {@link WebSocketHandler} notified.
*
* <p>If the underlying exception occurs while processing an incoming HTTP request,
* including over HTTP POST, the session will remain open. Only the incoming request is
* rejected.
*
* @author Rossen Stoyanchev
* @since 4.0
@ -43,7 +42,7 @@ public class TransportErrorException extends NestedRuntimeException {
}
public String getSockJsSessionId() {
return sockJsSessionId;
return this.sockJsSessionId;
}
@Override

View File

@ -17,6 +17,7 @@
package org.springframework.web.socket.sockjs;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -54,12 +55,13 @@ public enum TransportType {
private final List<String> headerHints;
private static final Map<String, TransportType> transportTypes = new HashMap<String, TransportType>();
private static final Map<String, TransportType> TRANSPORT_TYPES;
static {
Map<String, TransportType> transportTypes = new HashMap<String, TransportType>();
for (TransportType type : values()) {
transportTypes.put(type.value, type);
}
TRANSPORT_TYPES = Collections.unmodifiableMap(transportTypes);
}
@ -94,7 +96,7 @@ public enum TransportType {
}
public static TransportType fromValue(String value) {
return transportTypes.get(value);
return TRANSPORT_TYPES.get(value);
}
@Override

View File

@ -120,6 +120,7 @@ public class DefaultSockJsService extends AbstractSockJsService {
}
}
protected final Set<TransportHandler> getDefaultTransportHandlers() {
Set<TransportHandler> result = new HashSet<TransportHandler>();
result.add(new XhrPollingTransportHandler());

View File

@ -34,14 +34,13 @@ import org.springframework.web.socket.support.ExceptionWebSocketHandlerDecorator
import org.springframework.web.socket.support.LoggingWebSocketHandlerDecorator;
/**
* An {@link HttpRequestHandler} for processing SockJS requests.
* <p>
* This is the main class to use when configuring a SockJS service at a specific URL. It
* is a very thin wrapper around a {@link SockJsService} and a {@link WebSocketHandler}
* instance also adapting the {@link HttpServletRequest} and {@link HttpServletResponse}
* to {@link ServerHttpRequest} and {@link ServerHttpResponse} respectively.
* <p>
* The {@link #decorateWebSocketHandler(WebSocketHandler)} method decorates the given
* An {@link HttpRequestHandler} for processing SockJS requests. This is the main class
* to use when configuring a SockJS service at a specific URL. It is a very thin wrapper
* around a {@link SockJsService} and a {@link WebSocketHandler} instance also adapting
* the {@link HttpServletRequest} and {@link HttpServletResponse} to
* {@link ServerHttpRequest} and {@link ServerHttpResponse} respectively.
*
* <p>The {@link #decorateWebSocketHandler(WebSocketHandler)} method decorates the given
* WebSocketHandler with a logging and exception handling decorators. This method can be
* overridden to change that.
*
@ -56,19 +55,22 @@ public class SockJsHttpRequestHandler implements HttpRequestHandler {
/**
* Class constructor with {@link SockJsHandler} instance ...
* Create a new {@link SockJsHttpRequestHandler}.
* @param sockJsService the SockJS service
* @param webSocketHandler the websocket handler
*/
public SockJsHttpRequestHandler(SockJsService sockJsService, WebSocketHandler webSocketHandler) {
Assert.notNull(sockJsService, "sockJsService is required");
Assert.notNull(webSocketHandler, "webSocketHandler is required");
Assert.notNull(sockJsService, "sockJsService must not be null");
Assert.notNull(webSocketHandler, "webSocketHandler must not be null");
this.sockJsService = sockJsService;
this.webSocketHandler = decorateWebSocketHandler(webSocketHandler);
}
/**
* Decorate the WebSocketHandler provided to the class constructor.
* <p>
* By default {@link ExceptionWebSocketHandlerDecorator} and
*
* <p>By default {@link ExceptionWebSocketHandlerDecorator} and
* {@link LoggingWebSocketHandlerDecorator} are applied are added.
*/
protected WebSocketHandler decorateWebSocketHandler(WebSocketHandler handler) {

View File

@ -54,6 +54,7 @@ public abstract class AbstractHttpSockJsSession extends AbstractSockJsSession {
super(sessionId, config, handler);
}
public synchronized void setInitialRequest(ServerHttpRequest request, ServerHttpResponse response,
FrameFormat frameFormat) throws TransportErrorException {

View File

@ -48,7 +48,7 @@ public class EventSourceTransportHandler extends AbstractHttpSendingTransportHan
@Override
public StreamingSockJsSession createSession(String sessionId, WebSocketHandler handler) {
Assert.notNull(getSockJsConfig(), "This transport requires SockJsConfiguration");
Assert.state(getSockJsConfig() != null, "This transport requires SockJsConfiguration");
return new StreamingSockJsSession(sessionId, getSockJsConfig(), handler) {
@Override
protected void writePrelude() throws IOException {

View File

@ -45,6 +45,10 @@ public class HtmlFileTransportHandler extends AbstractHttpSendingTransportHandle
private static final String PARTIAL_HTML_CONTENT;
// Safari needs at least 1024 bytes to parse the website.
// http://code.google.com/p/browsersec/wiki/Part2#Survey_of_content_sniffing_behaviors
private static final int MINIMUM_PARTIAL_HTML_CONTENT_LENGTH = 1024;
static {
StringBuilder sb = new StringBuilder(
"<!doctype html>\n" +
@ -61,11 +65,8 @@ public class HtmlFileTransportHandler extends AbstractHttpSendingTransportHandle
" </script>"
);
// Safari needs at least 1024 bytes to parse the website.
// http://code.google.com/p/browsersec/wiki/Part2#Survey_of_content_sniffing_behaviors
int spaces = 1024 - sb.length();
for (int i=0; i < spaces; i++) {
sb.append(' ');
while(sb.length() < MINIMUM_PARTIAL_HTML_CONTENT_LENGTH) {
sb.append(" ");
}
PARTIAL_HTML_CONTENT = sb.toString();
@ -84,7 +85,7 @@ public class HtmlFileTransportHandler extends AbstractHttpSendingTransportHandle
@Override
public StreamingSockJsSession createSession(String sessionId, WebSocketHandler handler) {
Assert.notNull(getSockJsConfig(), "This transport requires SockJsConfiguration");
Assert.state(getSockJsConfig() != null, "This transport requires SockJsConfiguration");
return new StreamingSockJsSession(sessionId, getSockJsConfig(), handler) {

View File

@ -51,7 +51,7 @@ public class JsonpPollingTransportHandler extends AbstractHttpSendingTransportHa
@Override
public PollingSockJsSession createSession(String sessionId, WebSocketHandler handler) {
Assert.notNull(getSockJsConfig(), "This transport requires SockJsConfiguration");
Assert.state(getSockJsConfig() != null, "This transport requires SockJsConfiguration");
return new PollingSockJsSession(sessionId, getSockJsConfig(), handler);
}

View File

@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.web.socket.sockjs.transport;
import java.io.IOException;
@ -32,6 +33,7 @@ public class PollingSockJsSession extends AbstractHttpSockJsSession {
super(sessionId, config, handler);
}
@Override
protected void flushCache() throws IOException {
cancelHeartbeat();

View File

@ -26,13 +26,12 @@ import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.adapter.TextWebSocketHandlerAdapter;
import org.springframework.web.socket.sockjs.SockJsConfiguration;
/**
* An implementation of {@link WebSocketHandler} that adds SockJS messages frames, sends
* SockJS heartbeat messages, and delegates lifecycle events and messages to a target
* {@link WebSocketHandler}.
* <p>
* Methods in this class allow exceptions from the wrapped {@link WebSocketHandler} to
*
* <p>Methods in this class allow exceptions from the wrapped {@link WebSocketHandler} to
* propagate. However, any exceptions resulting from SockJS message handling (e.g. while
* sending SockJS frames or heartbeat messages) are caught and treated as transport
* errors, i.e. routed to the
@ -46,7 +45,7 @@ public class SockJsWebSocketHandler extends TextWebSocketHandlerAdapter {
private final SockJsConfiguration sockJsConfig;
private WebSocketServerSockJsSession session;
private final WebSocketServerSockJsSession session;
private final AtomicInteger sessionCount = new AtomicInteger(0);
@ -54,9 +53,9 @@ public class SockJsWebSocketHandler extends TextWebSocketHandlerAdapter {
public SockJsWebSocketHandler(SockJsConfiguration config,
WebSocketHandler webSocketHandler, WebSocketServerSockJsSession session) {
Assert.notNull(config, "sockJsConfig is required");
Assert.notNull(webSocketHandler, "webSocketHandler is required");
Assert.notNull(session, "session is required");
Assert.notNull(config, "config must not be null");
Assert.notNull(webSocketHandler, "webSocketHandler must not be null");
Assert.notNull(session, "session must not be null");
this.sockJsConfig = config;
this.session = session;

View File

@ -29,7 +29,6 @@ import org.springframework.web.socket.sockjs.SockJsFrame;
import com.fasterxml.jackson.databind.ObjectMapper;
/**
* A SockJS session for use with the WebSocket transport.
*
@ -48,6 +47,7 @@ public class WebSocketServerSockJsSession extends AbstractSockJsSession {
super(sessionId, config, handler);
}
public void initWebSocketSession(WebSocketSession session) throws Exception {
this.webSocketSession = session;
try {
@ -75,7 +75,7 @@ public class WebSocketServerSockJsSession extends AbstractSockJsSession {
}
String[] messages;
try {
messages = objectMapper.readValue(payload, String[].class);
messages = this.objectMapper.readValue(payload, String[].class);
}
catch (IOException ex) {
logger.error("Broken data received. Terminating WebSocket connection abruptly", ex);

View File

@ -31,12 +31,11 @@ import org.springframework.web.socket.sockjs.TransportErrorException;
import org.springframework.web.socket.sockjs.TransportHandler;
import org.springframework.web.socket.sockjs.TransportType;
/**
* A WebSocket {@link TransportHandler}. Uses {@link SockJsWebSocketHandler} and
* {@link WebSocketServerSockJsSession} to add SockJS processing.
* <p>
* Also implements {@link HandshakeHandler} to support raw WebSocket communication at
*
* <p>Also implements {@link HandshakeHandler} to support raw WebSocket communication at
* SockJS URL "/websocket".
*
* @author Rossen Stoyanchev
@ -51,10 +50,11 @@ public class WebSocketTransportHandler implements ConfigurableTransportHandler,
public WebSocketTransportHandler(HandshakeHandler handshakeHandler) {
Assert.notNull(handshakeHandler, "handshakeHandler is required");
Assert.notNull(handshakeHandler, "handshakeHandler must not be null");
this.handshakeHandler = handshakeHandler;
}
@Override
public TransportType getTransportType() {
return TransportType.WEBSOCKET;

View File

@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.web.socket.sockjs.transport;
import java.nio.charset.Charset;
@ -26,7 +27,6 @@ import org.springframework.web.socket.sockjs.SockJsFrame.FrameFormat;
import org.springframework.web.socket.sockjs.TransportHandler;
import org.springframework.web.socket.sockjs.TransportType;
/**
* A {@link TransportHandler} based on XHR (long) polling.
*
@ -35,7 +35,6 @@ import org.springframework.web.socket.sockjs.TransportType;
*/
public class XhrPollingTransportHandler extends AbstractHttpSendingTransportHandler {
@Override
public TransportType getTransportType() {
return TransportType.XHR;
@ -53,7 +52,7 @@ public class XhrPollingTransportHandler extends AbstractHttpSendingTransportHand
@Override
public PollingSockJsSession createSession(String sessionId, WebSocketHandler handler) {
Assert.notNull(getSockJsConfig(), "This transport requires SockJsConfiguration");
Assert.state(getSockJsConfig() != null, "This transport requires SockJsConfiguration");
return new PollingSockJsSession(sessionId, getSockJsConfig(), handler);
}

View File

@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.web.socket.sockjs.transport;
import java.io.IOException;
@ -27,7 +28,6 @@ import org.springframework.web.socket.sockjs.SockJsFrame.FrameFormat;
import org.springframework.web.socket.sockjs.TransportHandler;
import org.springframework.web.socket.sockjs.TransportType;
/**
* A {@link TransportHandler} that sends messages over an HTTP streaming request.
*
@ -36,7 +36,6 @@ import org.springframework.web.socket.sockjs.TransportType;
*/
public class XhrStreamingTransportHandler extends AbstractHttpSendingTransportHandler {
@Override
public TransportType getTransportType() {
return TransportType.XHR_STREAMING;
@ -49,7 +48,7 @@ public class XhrStreamingTransportHandler extends AbstractHttpSendingTransportHa
@Override
public StreamingSockJsSession createSession(String sessionId, WebSocketHandler handler) {
Assert.notNull(getSockJsConfig(), "This transport requires SockJsConfiguration");
Assert.state(getSockJsConfig() != null, "This transport requires SockJsConfiguration");
return new StreamingSockJsSession(sessionId, getSockJsConfig(), handler) {

View File

@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.web.socket.sockjs.transport;
import java.io.IOException;
@ -22,7 +23,6 @@ import org.springframework.http.server.ServerHttpRequest;
import org.springframework.web.socket.sockjs.TransportHandler;
import org.springframework.web.socket.sockjs.TransportType;
/**
* A {@link TransportHandler} that receives messages over HTTP.
*
@ -30,7 +30,6 @@ import org.springframework.web.socket.sockjs.TransportType;
*/
public class XhrTransportHandler extends AbstractHttpReceivingTransportHandler {
@Override
public TransportType getTransportType() {
return TransportType.XHR_SEND;

View File

@ -18,9 +18,8 @@
* Server-side support for SockJS transports including
* {@link org.springframework.web.socket.sockjs.TransportHandler} implementations
* for processing incoming requests and their
* {@link org.springframework.sockjs.SockJsSession} counterparts for
* {@link org.springframework.web.socket.sockjs.AbstractSockJsSession session} counterparts for
* sending messages over the various transports.
*
*/
package org.springframework.web.socket.sockjs.transport;

View File

@ -29,7 +29,7 @@ import org.springframework.util.Assert;
* Instantiates a target handler through a Spring {@link BeanFactory} and also provides
* an equivalent destroy method. Mainly for internal use to assist with initializing and
* destroying handlers with per-connection lifecycle.
*
*
* @author Rossen Stoyanchev
* @since 4.0
*/
@ -43,7 +43,7 @@ public class BeanCreatingHandlerProvider<T> implements BeanFactoryAware {
public BeanCreatingHandlerProvider(Class<? extends T> handlerType) {
Assert.notNull(handlerType, "handlerType is required");
Assert.notNull(handlerType, "handlerType must not be null");
this.handlerType = handlerType;
}
@ -83,7 +83,7 @@ public class BeanCreatingHandlerProvider<T> implements BeanFactoryAware {
@Override
public String toString() {
return "BeanCreatingHandlerProvider [handlerClass=" + handlerType + "]";
return "BeanCreatingHandlerProvider [handlerClass=" + this.handlerType + "]";
}
}

View File

@ -23,7 +23,6 @@ import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketMessage;
import org.springframework.web.socket.WebSocketSession;
/**
* An exception handling {@link WebSocketHandlerDecorator}. Traps all {@link Throwable}
* instances that escape from the decorated handler and closes the session with
@ -34,13 +33,14 @@ import org.springframework.web.socket.WebSocketSession;
*/
public class ExceptionWebSocketHandlerDecorator extends WebSocketHandlerDecorator {
private Log logger = LogFactory.getLog(ExceptionWebSocketHandlerDecorator.class);
private final Log logger = LogFactory.getLog(ExceptionWebSocketHandlerDecorator.class);
public ExceptionWebSocketHandlerDecorator(WebSocketHandler delegate) {
super(delegate);
}
@Override
public void afterConnectionEstablished(WebSocketSession session) {
try {

View File

@ -23,7 +23,6 @@ import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketMessage;
import org.springframework.web.socket.WebSocketSession;
/**
* A {@link WebSocketHandlerDecorator} that adds logging to WebSocket lifecycle events.
*
@ -32,7 +31,7 @@ import org.springframework.web.socket.WebSocketSession;
*/
public class LoggingWebSocketHandlerDecorator extends WebSocketHandlerDecorator {
private Log logger = LogFactory.getLog(LoggingWebSocketHandlerDecorator.class);
private final Log logger = LogFactory.getLog(LoggingWebSocketHandlerDecorator.class);
public LoggingWebSocketHandlerDecorator(WebSocketHandler delegate) {

View File

@ -22,7 +22,6 @@ import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketMessage;
import org.springframework.web.socket.WebSocketSession;
/**
* @author Rossen Stoyanchev
* @since 4.0
@ -33,7 +32,7 @@ public class WebSocketHandlerDecorator implements WebSocketHandler {
public WebSocketHandlerDecorator(WebSocketHandler delegate) {
Assert.notNull(delegate, "delegate is required");
Assert.notNull(delegate, "delegate must not be null");
this.delegate = delegate;
}
@ -43,7 +42,7 @@ public class WebSocketHandlerDecorator implements WebSocketHandler {
}
public WebSocketHandler getLastHandler() {
WebSocketHandler result = delegate;
WebSocketHandler result = this.delegate;
while (result instanceof WebSocketHandlerDecorator) {
result = ((WebSocketHandlerDecorator) result).getDelegate();
}
@ -75,7 +74,6 @@ public class WebSocketHandlerDecorator implements WebSocketHandler {
return this.delegate.supportsPartialMessages();
}
@Override
public String toString() {
return getClass().getSimpleName() + " [delegate=" + this.delegate + "]";

View File

@ -24,7 +24,6 @@ import org.springframework.http.server.ServletServerHttpResponse;
import org.springframework.mock.web.test.MockHttpServletRequest;
import org.springframework.mock.web.test.MockHttpServletResponse;
/**
* @author Rossen Stoyanchev
*/

View File

@ -24,7 +24,6 @@ import org.springframework.web.socket.WebSocketHandler;
import static org.mockito.Mockito.*;
/**
* Test fixture for {@link JettyWebSocketListenerAdapter}.
*

View File

@ -30,7 +30,6 @@ import static org.junit.Assert.*;
import static org.mockito.Matchers.*;
import static org.mockito.Mockito.*;
/**
* Test fixture for {@link StandardEndpointAdapter}.
*
@ -52,30 +51,30 @@ public class StandardEndpointAdapterTests {
this.session = mock(Session.class);
this.webSocketHandler = mock(WebSocketHandler.class);
this.webSocketSession = new StandardWebSocketSessionAdapter();
this.adapter = new StandardEndpointAdapter(webSocketHandler, webSocketSession);
this.adapter = new StandardEndpointAdapter(this.webSocketHandler, this.webSocketSession);
}
@Test
public void onOpen() throws Throwable {
this.adapter.onOpen(session, null);
this.adapter.onOpen(this.session, null);
verify(this.webSocketHandler).afterConnectionEstablished(this.webSocketSession);
verify(session, atLeast(2)).addMessageHandler(any(MessageHandler.Whole.class));
verify(this.session, atLeast(2)).addMessageHandler(any(MessageHandler.Whole.class));
when(session.getId()).thenReturn("123");
when(this.session.getId()).thenReturn("123");
assertEquals("123", this.webSocketSession.getId());
}
@Test
public void onClose() throws Throwable {
this.adapter.onClose(session, new CloseReason(CloseCodes.NORMAL_CLOSURE, "reason"));
this.adapter.onClose(this.session, new CloseReason(CloseCodes.NORMAL_CLOSURE, "reason"));
verify(this.webSocketHandler).afterConnectionClosed(this.webSocketSession, CloseStatus.NORMAL.withReason("reason"));
}
@Test
public void onError() throws Throwable {
Exception exception = new Exception();
this.adapter.onError(session, exception);
this.adapter.onError(this.session, exception);
verify(this.webSocketHandler).handleTransportError(this.webSocketSession, exception);
}

View File

@ -33,7 +33,6 @@ import org.springframework.web.socket.support.WebSocketHandlerDecorator;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
/**
* Test fixture for {@link WebSocketConnectionManager}.
*
@ -41,7 +40,6 @@ import static org.mockito.Mockito.*;
*/
public class WebSocketConnectionManagerTests {
@Test
public void openConnection() throws Exception {

View File

@ -38,7 +38,6 @@ import org.springframework.web.socket.adapter.WebSocketHandlerAdapter;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
/**
* Test fixture for {@link StandardWebSocketClient}.
*
@ -46,7 +45,6 @@ import static org.mockito.Mockito.*;
*/
public class StandardWebSocketClientTests {
@Test
public void doHandshake() throws Exception {

View File

@ -31,7 +31,6 @@ import org.springframework.web.context.support.AnnotationConfigWebApplicationCon
import static org.mockito.Mockito.*;
/**
* Test fixture for {@link ServerEndpointExporter}.
*
@ -51,7 +50,7 @@ public class ServerEndpointExporterTests {
this.serverContainer = mock(ServerContainer.class);
MockServletContext servletContext = new MockServletContext();
servletContext.setAttribute("javax.websocket.server.ServerContainer", serverContainer);
servletContext.setAttribute("javax.websocket.server.ServerContainer", this.serverContainer);
this.webAppContext = new AnnotationConfigWebApplicationContext();
this.webAppContext.register(Config.class);

View File

@ -29,7 +29,6 @@ import org.springframework.context.annotation.Configuration;
import static org.junit.Assert.*;
/**
* Test fixture for {@link ServerEndpointRegistration}.
*

View File

@ -32,10 +32,8 @@ import org.springframework.web.context.support.AnnotationConfigWebApplicationCon
import static org.junit.Assert.*;
public class SpringConfiguratorTests {
private MockServletContext servletContext;
private ContextLoader contextLoader;
@ -50,7 +48,7 @@ public class SpringConfiguratorTests {
this.webAppContext = new AnnotationConfigWebApplicationContext();
this.webAppContext.register(Config.class);
this.contextLoader = new ContextLoader(webAppContext);
this.contextLoader = new ContextLoader(this.webAppContext);
this.contextLoader.initWebApplicationContext(this.servletContext);
}

View File

@ -180,7 +180,7 @@ public class AbstractSockJsServiceTests extends AbstractHttpRequestTests {
assertTrue(this.servletResponse.getContentAsString().startsWith("<!DOCTYPE html>\n"));
assertEquals(496, this.servletResponse.getContentLength());
assertEquals("public, max-age=31536000", this.response.getHeaders().getCacheControl());
assertEquals("\"0da1ed070012f304e47b83c81c48ad620\"", response.getHeaders().getETag());
assertEquals("\"0da1ed070012f304e47b83c81c48ad620\"", this.response.getHeaders().getETag());
}
@Test

View File

@ -29,7 +29,6 @@ import static org.junit.Assert.*;
import static org.mockito.Matchers.*;
import static org.mockito.Mockito.*;
/**
* Test fixture for {@link AbstractSockJsSession}.
*

View File

@ -23,7 +23,6 @@ import org.springframework.web.socket.WebSocketHandler;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
/**
* Base class for {@link AbstractSockJsSession} classes.
*

View File

@ -19,7 +19,6 @@ package org.springframework.web.socket.sockjs;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
/**
* @author Rossen Stoyanchev
*/
@ -34,7 +33,7 @@ public class StubSockJsConfig implements SockJsConfiguration {
@Override
public int getStreamBytesLimit() {
return streamBytesLimit;
return this.streamBytesLimit;
}
public void setStreamBytesLimit(int streamBytesLimit) {
@ -43,7 +42,7 @@ public class StubSockJsConfig implements SockJsConfiguration {
@Override
public long getHeartbeatTime() {
return heartbeatTime;
return this.heartbeatTime;
}
public void setHeartbeatTime(long heartbeatTime) {
@ -52,7 +51,7 @@ public class StubSockJsConfig implements SockJsConfiguration {
@Override
public TaskScheduler getTaskScheduler() {
return taskScheduler;
return this.taskScheduler;
}
public void setTaskScheduler(TaskScheduler taskScheduler) {

View File

@ -23,7 +23,6 @@ import java.util.List;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.WebSocketHandler;
/**
* @author Rossen Stoyanchev
*/
@ -95,7 +94,7 @@ public class TestSockJsSession extends AbstractSockJsSession {
protected void writeFrameInternal(SockJsFrame frame) throws Exception {
this.sockJsFramesWritten.add(frame);
if (this.exceptionOnWriteFrame != null) {
throw exceptionOnWriteFrame;
throw this.exceptionOnWriteFrame;
}
}

View File

@ -20,13 +20,11 @@ import org.junit.Test;
import static org.junit.Assert.*;
/**
* @author Rossen Stoyanchev
*/
public class TransportTypeTests {
@Test
public void testFromValue() {
assertEquals(TransportType.WEBSOCKET, TransportType.fromValue("websocket"));

View File

@ -48,7 +48,6 @@ import static org.mockito.Mockito.*;
*/
public class DefaultSockJsServiceTests extends AbstractHttpRequestTests {
@Override
@Before
public void setUp() {

View File

@ -62,24 +62,24 @@ public class HttpSendingTransportHandlerTests extends AbstractHttpRequestTests
public void handleRequestXhr() throws Exception {
XhrPollingTransportHandler transportHandler = new XhrPollingTransportHandler();
transportHandler.setSockJsConfiguration(sockJsConfig);
transportHandler.setSockJsConfiguration(this.sockJsConfig);
AbstractSockJsSession session = transportHandler.createSession("1", webSocketHandler);
transportHandler.handleRequest(request, response, webSocketHandler, session);
AbstractSockJsSession session = transportHandler.createSession("1", this.webSocketHandler);
transportHandler.handleRequest(this.request, this.response, this.webSocketHandler, session);
assertEquals("application/javascript;charset=UTF-8", this.response.getHeaders().getContentType().toString());
assertEquals("o\n", this.servletResponse.getContentAsString());
assertFalse("Polling request should complete after open frame", this.servletRequest.isAsyncStarted());
verify(webSocketHandler).afterConnectionEstablished(session);
verify(this.webSocketHandler).afterConnectionEstablished(session);
resetResponse();
transportHandler.handleRequest(request, response, webSocketHandler, session);
transportHandler.handleRequest(this.request, this.response, this.webSocketHandler, session);
assertTrue("Polling request should remain open", this.servletRequest.isAsyncStarted());
verify(this.taskScheduler).schedule(any(Runnable.class), any(Date.class));
resetRequestAndResponse();
transportHandler.handleRequest(request, response, webSocketHandler, session);
transportHandler.handleRequest(this.request, this.response, this.webSocketHandler, session);
assertFalse("Request should have been rejected", this.servletRequest.isAsyncStarted());
assertEquals("c[2010,\"Another connection still open\"]\n", this.servletResponse.getContentAsString());
@ -89,70 +89,70 @@ public class HttpSendingTransportHandlerTests extends AbstractHttpRequestTests
public void jsonpTransport() throws Exception {
JsonpPollingTransportHandler transportHandler = new JsonpPollingTransportHandler();
transportHandler.setSockJsConfiguration(sockJsConfig);
PollingSockJsSession session = transportHandler.createSession("1", webSocketHandler);
transportHandler.setSockJsConfiguration(this.sockJsConfig);
PollingSockJsSession session = transportHandler.createSession("1", this.webSocketHandler);
transportHandler.handleRequest(request, response, webSocketHandler, session);
transportHandler.handleRequest(this.request, this.response, this.webSocketHandler, session);
assertEquals(500, this.servletResponse.getStatus());
assertEquals("\"callback\" parameter required", this.servletResponse.getContentAsString());
resetRequestAndResponse();
this.servletRequest.addParameter("c", "callback");
transportHandler.handleRequest(request, response, webSocketHandler, session);
transportHandler.handleRequest(this.request, this.response, this.webSocketHandler, session);
assertEquals("application/javascript;charset=UTF-8", this.response.getHeaders().getContentType().toString());
assertFalse("Polling request should complete after open frame", this.servletRequest.isAsyncStarted());
verify(webSocketHandler).afterConnectionEstablished(session);
verify(this.webSocketHandler).afterConnectionEstablished(session);
}
@Test
public void handleRequestXhrStreaming() throws Exception {
XhrStreamingTransportHandler transportHandler = new XhrStreamingTransportHandler();
transportHandler.setSockJsConfiguration(sockJsConfig);
AbstractSockJsSession session = transportHandler.createSession("1", webSocketHandler);
transportHandler.setSockJsConfiguration(this.sockJsConfig);
AbstractSockJsSession session = transportHandler.createSession("1", this.webSocketHandler);
transportHandler.handleRequest(request, response, webSocketHandler, session);
transportHandler.handleRequest(this.request, this.response, this.webSocketHandler, session);
assertEquals("application/javascript;charset=UTF-8", this.response.getHeaders().getContentType().toString());
assertTrue("Streaming request not started", this.servletRequest.isAsyncStarted());
verify(webSocketHandler).afterConnectionEstablished(session);
verify(this.webSocketHandler).afterConnectionEstablished(session);
}
@Test
public void htmlFileTransport() throws Exception {
HtmlFileTransportHandler transportHandler = new HtmlFileTransportHandler();
transportHandler.setSockJsConfiguration(sockJsConfig);
StreamingSockJsSession session = transportHandler.createSession("1", webSocketHandler);
transportHandler.setSockJsConfiguration(this.sockJsConfig);
StreamingSockJsSession session = transportHandler.createSession("1", this.webSocketHandler);
transportHandler.handleRequest(request, response, webSocketHandler, session);
transportHandler.handleRequest(this.request, this.response, this.webSocketHandler, session);
assertEquals(500, this.servletResponse.getStatus());
assertEquals("\"callback\" parameter required", this.servletResponse.getContentAsString());
resetRequestAndResponse();
this.servletRequest.addParameter("c", "callback");
transportHandler.handleRequest(request, response, webSocketHandler, session);
transportHandler.handleRequest(this.request, this.response, this.webSocketHandler, session);
assertEquals("text/html;charset=UTF-8", this.response.getHeaders().getContentType().toString());
assertTrue("Streaming request not started", this.servletRequest.isAsyncStarted());
verify(webSocketHandler).afterConnectionEstablished(session);
verify(this.webSocketHandler).afterConnectionEstablished(session);
}
@Test
public void eventSourceTransport() throws Exception {
EventSourceTransportHandler transportHandler = new EventSourceTransportHandler();
transportHandler.setSockJsConfiguration(sockJsConfig);
StreamingSockJsSession session = transportHandler.createSession("1", webSocketHandler);
transportHandler.setSockJsConfiguration(this.sockJsConfig);
StreamingSockJsSession session = transportHandler.createSession("1", this.webSocketHandler);
transportHandler.handleRequest(request, response, webSocketHandler, session);
transportHandler.handleRequest(this.request, this.response, this.webSocketHandler, session);
assertEquals("text/event-stream;charset=UTF-8", this.response.getHeaders().getContentType().toString());
assertTrue("Streaming request not started", this.servletRequest.isAsyncStarted());
verify(webSocketHandler).afterConnectionEstablished(session);
verify(this.webSocketHandler).afterConnectionEstablished(session);
}
@Test
@ -162,23 +162,23 @@ public class HttpSendingTransportHandlerTests extends AbstractHttpRequestTests
SockJsFrame frame = SockJsFrame.openFrame();
FrameFormat format = new XhrPollingTransportHandler().getFrameFormat(request);
FrameFormat format = new XhrPollingTransportHandler().getFrameFormat(this.request);
SockJsFrame formatted = format.format(frame);
assertEquals(frame.getContent() + "\n", formatted.getContent());
format = new XhrStreamingTransportHandler().getFrameFormat(request);
format = new XhrStreamingTransportHandler().getFrameFormat(this.request);
formatted = format.format(frame);
assertEquals(frame.getContent() + "\n", formatted.getContent());
format = new HtmlFileTransportHandler().getFrameFormat(request);
format = new HtmlFileTransportHandler().getFrameFormat(this.request);
formatted = format.format(frame);
assertEquals("<script>\np(\"" + frame.getContent() + "\");\n</script>\r\n", formatted.getContent());
format = new EventSourceTransportHandler().getFrameFormat(request);
format = new EventSourceTransportHandler().getFrameFormat(this.request);
formatted = format.format(frame);
assertEquals("data: " + frame.getContent() + "\r\n\r\n", formatted.getContent());
format = new JsonpPollingTransportHandler().getFrameFormat(request);
format = new JsonpPollingTransportHandler().getFrameFormat(this.request);
formatted = format.format(frame);
assertEquals("callback(\"" + frame.getContent() + "\");\r\n", formatted.getContent());
}

View File

@ -36,7 +36,6 @@ import static org.junit.Assert.*;
import static org.mockito.Matchers.*;
import static org.mockito.Mockito.*;
/**
* Test fixture for {@link WebSocketServerSockJsSession}.
*

View File

@ -26,8 +26,6 @@ import org.springframework.context.annotation.Configuration;
import static org.junit.Assert.*;
/**
* Test fixture for {@link BeanCreatingHandlerProvider}.
*

View File

@ -26,7 +26,6 @@ import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.WebSocketMessage;
import org.springframework.web.socket.WebSocketSession;
/**
* A {@link WebSocketSession} for use in tests.
*
@ -58,7 +57,7 @@ public class TestWebSocketSession implements WebSocketSession {
*/
@Override
public String getId() {
return id;
return this.id;
}
/**
@ -73,7 +72,7 @@ public class TestWebSocketSession implements WebSocketSession {
*/
@Override
public URI getUri() {
return uri;
return this.uri;
}
/**
@ -88,7 +87,7 @@ public class TestWebSocketSession implements WebSocketSession {
*/
@Override
public boolean isSecure() {
return secure;
return this.secure;
}
/**
@ -103,7 +102,7 @@ public class TestWebSocketSession implements WebSocketSession {
*/
@Override
public Principal getPrincipal() {
return principal;
return this.principal;
}
/**
@ -118,7 +117,7 @@ public class TestWebSocketSession implements WebSocketSession {
*/
@Override
public String getRemoteHostName() {
return remoteHostName;
return this.remoteHostName;
}
/**
@ -133,7 +132,7 @@ public class TestWebSocketSession implements WebSocketSession {
*/
@Override
public String getRemoteAddress() {
return remoteAddress;
return this.remoteAddress;
}
/**
@ -148,7 +147,7 @@ public class TestWebSocketSession implements WebSocketSession {
*/
@Override
public boolean isOpen() {
return open;
return this.open;
}
/**

View File

@ -21,7 +21,6 @@ import org.springframework.web.socket.adapter.WebSocketHandlerAdapter;
import static org.junit.Assert.*;
/**
* Test fixture for {@link WebSocketHandlerDecorator}.
*