7 changed files with 402 additions and 39 deletions
@ -0,0 +1,227 @@
@@ -0,0 +1,227 @@
|
||||
/* |
||||
* 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.websocket.client; |
||||
|
||||
import java.io.IOException; |
||||
import java.net.URI; |
||||
|
||||
import javax.websocket.ContainerProvider; |
||||
import javax.websocket.DeploymentException; |
||||
import javax.websocket.Session; |
||||
import javax.websocket.WebSocketContainer; |
||||
|
||||
import org.apache.commons.logging.Log; |
||||
import org.apache.commons.logging.LogFactory; |
||||
import org.springframework.beans.BeansException; |
||||
import org.springframework.context.ApplicationContext; |
||||
import org.springframework.context.ApplicationContextAware; |
||||
import org.springframework.context.SmartLifecycle; |
||||
import org.springframework.core.task.SimpleAsyncTaskExecutor; |
||||
import org.springframework.core.task.TaskExecutor; |
||||
import org.springframework.util.Assert; |
||||
import org.springframework.web.util.UriComponentsBuilder; |
||||
|
||||
|
||||
/** |
||||
* |
||||
* @author Rossen Stoyanchev |
||||
* @since 4.0 |
||||
*/ |
||||
public abstract class AbstractEndpointConnectionManager implements ApplicationContextAware, SmartLifecycle { |
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass()); |
||||
|
||||
private final Class<?> endpointClass; |
||||
|
||||
private final Object endpointBean; |
||||
|
||||
private final URI uri; |
||||
|
||||
private boolean autoStartup = false; |
||||
|
||||
private int phase = Integer.MAX_VALUE; |
||||
|
||||
private final WebSocketContainer webSocketContainer = ContainerProvider.getWebSocketContainer(); |
||||
|
||||
private Session session; |
||||
|
||||
private ApplicationContext applicationContext; |
||||
|
||||
private TaskExecutor taskExecutor = new SimpleAsyncTaskExecutor("EndpointConnectionManager-"); |
||||
|
||||
private final Object lifecycleMonitor = new Object(); |
||||
|
||||
|
||||
public AbstractEndpointConnectionManager(Class<?> endpointClass, String uriTemplate, Object... uriVariables) { |
||||
Assert.notNull(endpointClass, "endpointClass is required"); |
||||
this.endpointClass = endpointClass; |
||||
this.endpointBean = null; |
||||
this.uri = initUri(uriTemplate, uriVariables); |
||||
} |
||||
|
||||
public AbstractEndpointConnectionManager(Object endpointBean, String uriTemplate, Object... uriVariables) { |
||||
Assert.notNull(endpointBean, "endpointBean is required"); |
||||
this.endpointClass = null; |
||||
this.endpointBean = endpointBean; |
||||
this.uri = initUri(uriTemplate, uriVariables); |
||||
} |
||||
|
||||
private static URI initUri(String uri, Object... uriVariables) { |
||||
return UriComponentsBuilder.fromUriString(uri).buildAndExpand(uriVariables).encode().toUri(); |
||||
} |
||||
|
||||
public void setAsyncSendTimeout(long timeoutInMillis) { |
||||
this.webSocketContainer.setAsyncSendTimeout(timeoutInMillis); |
||||
} |
||||
|
||||
public void setMaxSessionIdleTimeout(long timeoutInMillis) { |
||||
this.webSocketContainer.setDefaultMaxSessionIdleTimeout(timeoutInMillis); |
||||
} |
||||
|
||||
public void setMaxTextMessageBufferSize(int bufferSize) { |
||||
this.webSocketContainer.setDefaultMaxTextMessageBufferSize(bufferSize); |
||||
} |
||||
|
||||
public void setMaxBinaryMessageBufferSize(Integer bufferSize) { |
||||
this.webSocketContainer.setDefaultMaxBinaryMessageBufferSize(bufferSize); |
||||
} |
||||
|
||||
/** |
||||
* Set whether to auto-connect to the {@link #setDefaultUri(URI) default URI} after |
||||
* this endpoint connection factory has been initialized and the Spring context has |
||||
* been refreshed. |
||||
* <p>Default is "false". |
||||
*/ |
||||
public void setAutoStartup(boolean autoStartup) { |
||||
this.autoStartup = autoStartup; |
||||
} |
||||
|
||||
/** |
||||
* Return the value for the 'autoStartup' property. If "true", this endpoint |
||||
* connection factory will connect to the {@link #setDefaultUri(URI) default URI} upon |
||||
* a ContextRefreshedEvent. |
||||
*/ |
||||
public boolean isAutoStartup() { |
||||
return this.autoStartup; |
||||
} |
||||
|
||||
/** |
||||
* Specify the phase in which this endpoint connection factory should be |
||||
* auto-connected and closed. The startup order proceeds from lowest to highest, and |
||||
* the shutdown order is the reverse of that. By default this value is |
||||
* Integer.MAX_VALUE meaning that this endpoint connection factory connects as late as |
||||
* possible and is closed as soon as possible. |
||||
*/ |
||||
public void setPhase(int phase) { |
||||
this.phase = phase; |
||||
} |
||||
|
||||
/** |
||||
* Return the phase in which this endpoint connection factory will be auto-connected |
||||
* and stopped. |
||||
*/ |
||||
public int getPhase() { |
||||
return this.phase; |
||||
} |
||||
|
||||
@Override |
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { |
||||
this.applicationContext = applicationContext; |
||||
} |
||||
|
||||
protected URI getUri() { |
||||
return this.uri; |
||||
} |
||||
|
||||
protected WebSocketContainer getWebSocketContainer() { |
||||
return this.webSocketContainer; |
||||
} |
||||
|
||||
protected Object getEndpoint() { |
||||
if (this.endpointClass != null) { |
||||
return this.applicationContext.getAutowireCapableBeanFactory().createBean(this.endpointClass); |
||||
} |
||||
else { |
||||
return this.endpointBean; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Auto-connects to the configured {@link #setDefaultUri(URI) default URI}. |
||||
*/ |
||||
public void start() { |
||||
synchronized (this.lifecycleMonitor) { |
||||
if (!isRunning()) { |
||||
this.taskExecutor.execute(new Runnable() { |
||||
@Override |
||||
public void run() { |
||||
synchronized (lifecycleMonitor) { |
||||
try { |
||||
logger.info("Connecting to endpoint at URI " + uri); |
||||
session = connect(getEndpoint()); |
||||
logger.info("Successfully connected"); |
||||
} |
||||
catch (Exception ex) { |
||||
logger.error("Failed to connect to endpoint at " + uri, ex); |
||||
} |
||||
} |
||||
} |
||||
}); |
||||
} |
||||
} |
||||
} |
||||
|
||||
protected abstract Session connect(Object endpoint) throws DeploymentException, IOException; |
||||
|
||||
/** |
||||
* Deactivates the configured message endpoint. |
||||
*/ |
||||
public void stop() { |
||||
synchronized (this.lifecycleMonitor) { |
||||
if (isRunning()) { |
||||
try { |
||||
this.session.close(); |
||||
} |
||||
catch (IOException e) { |
||||
// ignore
|
||||
} |
||||
} |
||||
this.session = null; |
||||
} |
||||
} |
||||
|
||||
public void stop(Runnable callback) { |
||||
synchronized (this.lifecycleMonitor) { |
||||
this.stop(); |
||||
callback.run(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Return whether the configured message endpoint is currently active. |
||||
*/ |
||||
public boolean isRunning() { |
||||
synchronized (this.lifecycleMonitor) { |
||||
if ((this.session != null) && this.session.isOpen()) { |
||||
return true; |
||||
} |
||||
this.session = null; |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,46 @@
@@ -0,0 +1,46 @@
|
||||
/* |
||||
* 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.websocket.client; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
import javax.websocket.DeploymentException; |
||||
import javax.websocket.Session; |
||||
|
||||
|
||||
/** |
||||
* |
||||
* @author Rossen Stoyanchev |
||||
* @since 4.0 |
||||
*/ |
||||
public class AnnotatedEndpointConnectionManager extends AbstractEndpointConnectionManager { |
||||
|
||||
|
||||
public AnnotatedEndpointConnectionManager(Class<?> endpointClass, String uriTemplate, Object... uriVariables) { |
||||
super(endpointClass, uriTemplate, uriVariables); |
||||
} |
||||
|
||||
public AnnotatedEndpointConnectionManager(Object endpointBean, String uriTemplate, Object... uriVariables) { |
||||
super(endpointBean, uriTemplate, uriVariables); |
||||
} |
||||
|
||||
@Override |
||||
protected Session connect(Object endpoint) throws DeploymentException, IOException { |
||||
return getWebSocketContainer().connectToServer(endpoint, getUri()); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,78 @@
@@ -0,0 +1,78 @@
|
||||
/* |
||||
* 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.websocket.client; |
||||
|
||||
import java.io.IOException; |
||||
import java.util.Arrays; |
||||
import java.util.List; |
||||
|
||||
import javax.websocket.ClientEndpointConfig; |
||||
import javax.websocket.ClientEndpointConfig.Configurator; |
||||
import javax.websocket.Decoder; |
||||
import javax.websocket.DeploymentException; |
||||
import javax.websocket.Encoder; |
||||
import javax.websocket.Endpoint; |
||||
import javax.websocket.Extension; |
||||
import javax.websocket.Session; |
||||
|
||||
|
||||
/** |
||||
* |
||||
* @author Rossen Stoyanchev |
||||
* @since 4.0 |
||||
*/ |
||||
public class EndpointConnectionManager extends AbstractEndpointConnectionManager { |
||||
|
||||
private final ClientEndpointConfig.Builder configBuilder = ClientEndpointConfig.Builder.create(); |
||||
|
||||
|
||||
public EndpointConnectionManager(Class<? extends Endpoint> endpointClass, String uriTemplate, Object... uriVariables) { |
||||
super(endpointClass, uriTemplate, uriVariables); |
||||
} |
||||
|
||||
public EndpointConnectionManager(Endpoint endpointBean, String uriTemplate, Object... uriVariables) { |
||||
super(endpointBean, uriTemplate, uriVariables); |
||||
} |
||||
|
||||
public void setSubProtocols(String... subprotocols) { |
||||
this.configBuilder.preferredSubprotocols(Arrays.asList(subprotocols)); |
||||
} |
||||
|
||||
public void setExtensions(Extension... extensions) { |
||||
this.configBuilder.extensions(Arrays.asList(extensions)); |
||||
} |
||||
|
||||
public void setEncoders(List<Class<? extends Encoder>> encoders) { |
||||
this.configBuilder.encoders(encoders); |
||||
} |
||||
|
||||
public void setDecoders(List<Class<? extends Decoder>> decoders) { |
||||
this.configBuilder.decoders(decoders); |
||||
} |
||||
|
||||
public void setConfigurator(Configurator configurator) { |
||||
this.configBuilder.configurator(configurator); |
||||
} |
||||
|
||||
@Override |
||||
protected Session connect(Object endpoint) throws DeploymentException, IOException { |
||||
Endpoint typedEndpoint = (Endpoint) endpoint; |
||||
ClientEndpointConfig endpointConfig = this.configBuilder.build(); |
||||
return getWebSocketContainer().connectToServer(typedEndpoint, endpointConfig, getUri()); |
||||
} |
||||
|
||||
} |
||||
Loading…
Reference in new issue