提交 47c4cf7a 编写于 作者: J Juergen Hoeller

Drop support for Jetty 9.3 and OkHttp 2.x

Issue: SPR-15038
上级 37726f42
/*
* Copyright 2002-2016 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.http.client;
import java.io.IOException;
import java.net.URI;
import com.squareup.okhttp.Call;
import com.squareup.okhttp.Callback;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.util.concurrent.SettableListenableFuture;
/**
* {@link AsyncClientHttpRequest} implementation based on OkHttp 2.x.
*
* <p>Created via the {@link OkHttpClientHttpRequestFactory}.
*
* @author Luciano Leggieri
* @author Arjen Poutsma
* @since 4.3
* @see org.springframework.http.client.OkHttp3AsyncClientHttpRequest
* @deprecated as of Spring 5.0, in favor of OkHttp 3.x
*/
@Deprecated
class OkHttpAsyncClientHttpRequest extends AbstractBufferingAsyncClientHttpRequest {
private final OkHttpClient client;
private final URI uri;
private final HttpMethod method;
public OkHttpAsyncClientHttpRequest(OkHttpClient client, URI uri, HttpMethod method) {
this.client = client;
this.uri = uri;
this.method = method;
}
@Override
public HttpMethod getMethod() {
return this.method;
}
@Override
public URI getURI() {
return this.uri;
}
@Override
protected ListenableFuture<ClientHttpResponse> executeInternal(HttpHeaders headers, byte[] content)
throws IOException {
Request request = OkHttpClientHttpRequestFactory.buildRequest(headers, content, this.uri, this.method);
return new OkHttpListenableFuture(this.client.newCall(request));
}
@Deprecated
private static class OkHttpListenableFuture extends SettableListenableFuture<ClientHttpResponse> {
private final Call call;
public OkHttpListenableFuture(Call call) {
this.call = call;
this.call.enqueue(new Callback() {
@Override
public void onResponse(Response response) {
set(new OkHttpClientHttpResponse(response));
}
@Override
public void onFailure(Request request, IOException ex) {
setException(ex);
}
});
}
@Override
protected void interruptTask() {
this.call.cancel();
}
}
}
/*
* Copyright 2002-2016 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.http.client;
import java.io.IOException;
import java.net.URI;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
/**
* {@link ClientHttpRequest} implementation based on OkHttp 2.x.
*
* <p>Created via the {@link OkHttpClientHttpRequestFactory}.
*
* @author Luciano Leggieri
* @author Arjen Poutsma
* @since 4.2
* @see org.springframework.http.client.OkHttp3ClientHttpRequest
* @deprecated as of Spring 5.0, in favor of OkHttp 3.x
*/
@Deprecated
class OkHttpClientHttpRequest extends AbstractBufferingClientHttpRequest {
private final OkHttpClient client;
private final URI uri;
private final HttpMethod method;
public OkHttpClientHttpRequest(OkHttpClient client, URI uri, HttpMethod method) {
this.client = client;
this.uri = uri;
this.method = method;
}
@Override
public HttpMethod getMethod() {
return this.method;
}
@Override
public URI getURI() {
return this.uri;
}
@Override
protected ClientHttpResponse executeInternal(HttpHeaders headers, byte[] content) throws IOException {
Request request = OkHttpClientHttpRequestFactory.buildRequest(headers, content, this.uri, this.method);
return new OkHttpClientHttpResponse(this.client.newCall(request).execute());
}
}
/*
* Copyright 2002-2016 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.http.client;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.RequestBody;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* {@link ClientHttpRequestFactory} implementation that uses
* <a href="http://square.github.io/okhttp/">OkHttp</a> 2.x to create requests.
*
* @author Luciano Leggieri
* @author Arjen Poutsma
* @since 4.2
* @see org.springframework.http.client.OkHttp3ClientHttpRequestFactory
* @deprecated as of Spring 5.0, in favor of OkHttp 3.x
*/
@Deprecated
public class OkHttpClientHttpRequestFactory
implements ClientHttpRequestFactory, AsyncClientHttpRequestFactory, DisposableBean {
private final OkHttpClient client;
private final boolean defaultClient;
/**
* Create a factory with a default {@link OkHttpClient} instance.
*/
public OkHttpClientHttpRequestFactory() {
this.client = new OkHttpClient();
this.defaultClient = true;
}
/**
* Create a factory with the given {@link OkHttpClient} instance.
* @param client the client to use
*/
public OkHttpClientHttpRequestFactory(OkHttpClient client) {
Assert.notNull(client, "OkHttpClient must not be null");
this.client = client;
this.defaultClient = false;
}
/**
* Sets the underlying read timeout in milliseconds.
* A value of 0 specifies an infinite timeout.
* @see OkHttpClient#setReadTimeout(long, TimeUnit)
*/
public void setReadTimeout(int readTimeout) {
this.client.setReadTimeout(readTimeout, TimeUnit.MILLISECONDS);
}
/**
* Sets the underlying write timeout in milliseconds.
* A value of 0 specifies an infinite timeout.
* @see OkHttpClient#setWriteTimeout(long, TimeUnit)
*/
public void setWriteTimeout(int writeTimeout) {
this.client.setWriteTimeout(writeTimeout, TimeUnit.MILLISECONDS);
}
/**
* Sets the underlying connect timeout in milliseconds.
* A value of 0 specifies an infinite timeout.
* @see OkHttpClient#setConnectTimeout(long, TimeUnit)
*/
public void setConnectTimeout(int connectTimeout) {
this.client.setConnectTimeout(connectTimeout, TimeUnit.MILLISECONDS);
}
@Override
public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) {
return new OkHttpClientHttpRequest(this.client, uri, httpMethod);
}
@Override
public AsyncClientHttpRequest createAsyncRequest(URI uri, HttpMethod httpMethod) {
return new OkHttpAsyncClientHttpRequest(this.client, uri, httpMethod);
}
@Override
public void destroy() throws IOException {
if (this.defaultClient) {
// Clean up the client if we created it in the constructor
if (this.client.getCache() != null) {
this.client.getCache().close();
}
this.client.getDispatcher().getExecutorService().shutdown();
}
}
static Request buildRequest(HttpHeaders headers, byte[] content, URI uri, HttpMethod method)
throws MalformedURLException {
com.squareup.okhttp.MediaType contentType = getContentType(headers);
RequestBody body = (content.length > 0 ||
com.squareup.okhttp.internal.http.HttpMethod.requiresRequestBody(method.name()) ?
RequestBody.create(contentType, content) : null);
Request.Builder builder = new Request.Builder().url(uri.toURL()).method(method.name(), body);
for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
String headerName = entry.getKey();
for (String headerValue : entry.getValue()) {
builder.addHeader(headerName, headerValue);
}
}
return builder.build();
}
private static com.squareup.okhttp.MediaType getContentType(HttpHeaders headers) {
String rawContentType = headers.getFirst(HttpHeaders.CONTENT_TYPE);
return (StringUtils.hasText(rawContentType) ?
com.squareup.okhttp.MediaType.parse(rawContentType) : null);
}
}
/*
* Copyright 2002-2016 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.http.client;
import java.io.IOException;
import java.io.InputStream;
import com.squareup.okhttp.Response;
import org.springframework.http.HttpHeaders;
import org.springframework.util.Assert;
/**
* {@link ClientHttpResponse} implementation based on OkHttp 2.x.
*
* @author Luciano Leggieri
* @author Arjen Poutsma
* @since 4.2
* @see org.springframework.http.client.OkHttp3ClientHttpResponse
* @deprecated as of Spring 5.0, in favor of OkHttp 3.x
*/
@Deprecated
class OkHttpClientHttpResponse extends AbstractClientHttpResponse {
private final Response response;
private HttpHeaders headers;
public OkHttpClientHttpResponse(Response response) {
Assert.notNull(response, "Response must not be null");
this.response = response;
}
@Override
public int getRawStatusCode() {
return this.response.code();
}
@Override
public String getStatusText() {
return this.response.message();
}
@Override
public InputStream getBody() throws IOException {
return this.response.body().byteStream();
}
@Override
public HttpHeaders getHeaders() {
if (this.headers == null) {
HttpHeaders headers = new HttpHeaders();
for (String headerName : this.response.headers().names()) {
for (String headerValue : this.response.headers(headerName)) {
headers.add(headerName, headerValue);
}
}
this.headers = headers;
}
return this.headers;
}
@Override
public void close() {
try {
this.response.body().close();
}
catch (IOException ex) {
// ignore
}
}
}
/*
* Copyright 2002-2016 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.http.client;
import org.junit.Test;
import org.springframework.http.HttpMethod;
/**
* @author Luciano Leggieri
*/
public class OkHttpAsyncClientHttpRequestFactoryTests extends AbstractAsyncHttpRequestFactoryTestCase {
@Override
@SuppressWarnings("deprecation")
protected AsyncClientHttpRequestFactory createRequestFactory() {
return new OkHttpClientHttpRequestFactory();
}
@Override
@Test
public void httpMethods() throws Exception {
super.httpMethods();
assertHttpMethod("patch", HttpMethod.PATCH);
}
}
/*
* Copyright 2002-2016 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.http.client;
import org.junit.Test;
import org.springframework.http.HttpMethod;
/**
* @author Luciano Leggieri
*/
public class OkHttpClientHttpRequestFactoryTests extends AbstractHttpRequestFactoryTestCase {
@Override
@SuppressWarnings("deprecation")
protected ClientHttpRequestFactory createRequestFactory() {
return new OkHttpClientHttpRequestFactory();
}
@Override
@Test
public void httpMethods() throws Exception {
super.httpMethods();
assertHttpMethod("patch", HttpMethod.PATCH);
}
}
......@@ -78,16 +78,17 @@ public class RestTemplateIntegrationTests extends AbstractMockWebServerTestCase
new SimpleClientHttpRequestFactory(),
new HttpComponentsClientHttpRequestFactory(),
new Netty4ClientHttpRequestFactory(),
new OkHttp3ClientHttpRequestFactory(),
new org.springframework.http.client.OkHttpClientHttpRequestFactory()
new OkHttp3ClientHttpRequestFactory()
);
}
@Before
public void setUpClient() {
public void setupClient() {
this.template = new RestTemplate(this.clientHttpRequestFactory);
}
@Test
public void getString() {
String s = template.getForObject(baseUrl + "/{method}", String.class, "get");
......
......@@ -44,17 +44,8 @@ import org.springframework.http.converter.GenericHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.util.DefaultUriBuilderFactory;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.fail;
import static org.mockito.BDDMockito.any;
import static org.mockito.BDDMockito.eq;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.mock;
import static org.mockito.BDDMockito.verify;
import static org.mockito.BDDMockito.willThrow;
import static org.junit.Assert.*;
import static org.mockito.BDDMockito.*;
/**
* @author Arjen Poutsma
......@@ -76,8 +67,9 @@ public class RestTemplateTests {
@SuppressWarnings("rawtypes")
private HttpMessageConverter converter;
@Before
public void setUp() {
public void setup() {
requestFactory = mock(ClientHttpRequestFactory.class);
request = mock(ClientHttpRequest.class);
response = mock(ClientHttpResponse.class);
......@@ -88,6 +80,7 @@ public class RestTemplateTests {
template.setErrorHandler(errorHandler);
}
@Test
public void varArgsTemplateVariables() throws Exception {
given(requestFactory.createRequest(new URI("http://example.com/hotels/42/bookings/21"), HttpMethod.GET))
......@@ -816,4 +809,5 @@ public class RestTemplateTests {
verify(response).close();
}
}
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2017 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.
......@@ -17,7 +17,6 @@
package org.springframework.web.socket.adapter.jetty;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.InetSocketAddress;
import java.net.URI;
import java.security.Principal;
......@@ -28,15 +27,12 @@ import java.util.Map;
import org.eclipse.jetty.websocket.api.RemoteEndpoint;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.UpgradeRequest;
import org.eclipse.jetty.websocket.api.UpgradeResponse;
import org.eclipse.jetty.websocket.api.WebSocketException;
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
import org.springframework.http.HttpHeaders;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.socket.BinaryMessage;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.PingMessage;
......@@ -47,7 +43,7 @@ import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.adapter.AbstractWebSocketSession;
/**
* A {@link WebSocketSession} for use with the Jetty 9.3/9.4 WebSocket API.
* A {@link WebSocketSession} for use with the Jetty 9.4 WebSocket API.
*
* @author Phillip Webb
* @author Rossen Stoyanchev
......@@ -57,36 +53,6 @@ import org.springframework.web.socket.adapter.AbstractWebSocketSession;
*/
public class JettyWebSocketSession extends AbstractWebSocketSession<Session> {
// As of Jetty 9.4, UpgradeRequest and UpgradeResponse are interfaces instead of classes
private static final boolean directInterfaceCalls;
private static Method getUpgradeRequest;
private static Method getUpgradeResponse;
private static Method getRequestURI;
private static Method getHeaders;
private static Method getUserPrincipal;
private static Method getAcceptedSubProtocol;
private static Method getExtensions;
static {
directInterfaceCalls = UpgradeRequest.class.isInterface();
if (!directInterfaceCalls) {
try {
getUpgradeRequest = Session.class.getMethod("getUpgradeRequest");
getUpgradeResponse = Session.class.getMethod("getUpgradeResponse");
getRequestURI = UpgradeRequest.class.getMethod("getRequestURI");
getHeaders = UpgradeRequest.class.getMethod("getHeaders");
getUserPrincipal = UpgradeRequest.class.getMethod("getUserPrincipal");
getAcceptedSubProtocol = UpgradeResponse.class.getMethod("getAcceptedSubProtocol");
getExtensions = UpgradeResponse.class.getMethod("getExtensions");
}
catch (NoSuchMethodException ex) {
throw new IllegalStateException("Incompatible Jetty API", ex);
}
}
}
private String id;
private URI uri;
......@@ -201,31 +167,23 @@ public class JettyWebSocketSession extends AbstractWebSocketSession<Session> {
@Override
public void initializeNativeSession(Session session) {
super.initializeNativeSession(session);
if (directInterfaceCalls) {
initializeJettySessionDirectly(session);
}
else {
initializeJettySessionReflectively(session);
}
}
private void initializeJettySessionDirectly(Session session) {
this.id = ObjectUtils.getIdentityHexString(getNativeSession());
this.uri = session.getUpgradeRequest().getRequestURI();
this.headers = new HttpHeaders();
this.headers.putAll(session.getUpgradeRequest().getHeaders());
this.headers = HttpHeaders.readOnlyHttpHeaders(this.headers);
HttpHeaders headers = new HttpHeaders();
headers.putAll(session.getUpgradeRequest().getHeaders());
this.headers = HttpHeaders.readOnlyHttpHeaders(headers);
this.acceptedProtocol = session.getUpgradeResponse().getAcceptedSubProtocol();
List<ExtensionConfig> jettyExtensions = session.getUpgradeResponse().getExtensions();
if (!CollectionUtils.isEmpty(jettyExtensions)) {
this.extensions = new ArrayList<>(jettyExtensions.size());
List<WebSocketExtension> extensions = new ArrayList<>(jettyExtensions.size());
for (ExtensionConfig jettyExtension : jettyExtensions) {
this.extensions.add(new WebSocketExtension(jettyExtension.getName(), jettyExtension.getParameters()));
extensions.add(new WebSocketExtension(jettyExtension.getName(), jettyExtension.getParameters()));
}
this.extensions = Collections.unmodifiableList(this.extensions);
this.extensions = Collections.unmodifiableList(extensions);
}
else {
this.extensions = Collections.emptyList();
......@@ -236,37 +194,6 @@ public class JettyWebSocketSession extends AbstractWebSocketSession<Session> {
}
}
@SuppressWarnings("unchecked")
private void initializeJettySessionReflectively(Session session) {
Object request = ReflectionUtils.invokeMethod(getUpgradeRequest, session);
Object response = ReflectionUtils.invokeMethod(getUpgradeResponse, session);
this.id = ObjectUtils.getIdentityHexString(getNativeSession());
this.uri = (URI) ReflectionUtils.invokeMethod(getRequestURI, request);
this.headers = new HttpHeaders();
this.headers.putAll((Map<String, List<String>>) ReflectionUtils.invokeMethod(getHeaders, request));
this.headers = HttpHeaders.readOnlyHttpHeaders(this.headers);
this.acceptedProtocol = (String) ReflectionUtils.invokeMethod(getAcceptedSubProtocol, response);
List<ExtensionConfig> extensions = (List<ExtensionConfig>) ReflectionUtils.invokeMethod(getExtensions, response);
if (!CollectionUtils.isEmpty(extensions)) {
this.extensions = new ArrayList<>(extensions.size());
for (ExtensionConfig extension : extensions) {
this.extensions.add(new WebSocketExtension(extension.getName(), extension.getParameters()));
}
this.extensions = Collections.unmodifiableList(this.extensions);
}
else {
this.extensions = Collections.emptyList();
}
if (this.user == null) {
this.user = (Principal) ReflectionUtils.invokeMethod(getUserPrincipal, request);
}
}
@Override
protected void sendTextMessage(TextMessage message) throws IOException {
......
......@@ -41,7 +41,6 @@ import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.http.server.ServletServerHttpResponse;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.web.context.ServletContextAware;
import org.springframework.web.socket.WebSocketExtension;
......@@ -53,8 +52,8 @@ import org.springframework.web.socket.server.HandshakeFailureException;
import org.springframework.web.socket.server.RequestUpgradeStrategy;
/**
* A {@link RequestUpgradeStrategy} for use with Jetty 9.3 and 9.4. Based on
* Jetty's internal {@code org.eclipse.jetty.websocket.server.WebSocketHandler} class.
* A {@link RequestUpgradeStrategy} for use with Jetty 9.4. Based on Jetty's
* internal {@code org.eclipse.jetty.websocket.server.WebSocketHandler} class.
*
* @author Phillip Webb
* @author Rossen Stoyanchev
......@@ -68,11 +67,9 @@ public class JettyRequestUpgradeStrategy implements RequestUpgradeStrategy, Serv
new NamedThreadLocal<>("WebSocketHandlerContainer");
// Configurable factory adapter due to Jetty 9.3.15+ API differences:
// using WebSocketServerFactory(ServletContext) as a version indicator
private final WebSocketServerFactoryAdapter factoryAdapter =
(ClassUtils.hasConstructor(WebSocketServerFactory.class, ServletContext.class) ?
new ModernJettyWebSocketServerFactoryAdapter() : new LegacyJettyWebSocketServerFactoryAdapter());
private WebSocketPolicy policy;
private WebSocketServerFactory factory;
private ServletContext servletContext;
......@@ -86,7 +83,7 @@ public class JettyRequestUpgradeStrategy implements RequestUpgradeStrategy, Serv
* its default constructor thus using a default {@link WebSocketPolicy}.
*/
public JettyRequestUpgradeStrategy() {
this.factoryAdapter.setPolicy(WebSocketPolicy.newServerPolicy());
this.policy = WebSocketPolicy.newServerPolicy();
}
/**
......@@ -97,7 +94,7 @@ public class JettyRequestUpgradeStrategy implements RequestUpgradeStrategy, Serv
*/
public JettyRequestUpgradeStrategy(WebSocketPolicy policy) {
Assert.notNull(policy, "WebSocketPolicy must not be null");
this.factoryAdapter.setPolicy(policy);
this.policy = policy;
}
/**
......@@ -106,7 +103,7 @@ public class JettyRequestUpgradeStrategy implements RequestUpgradeStrategy, Serv
*/
public JettyRequestUpgradeStrategy(WebSocketServerFactory factory) {
Assert.notNull(factory, "WebSocketServerFactory must not be null");
this.factoryAdapter.setFactory(factory);
this.factory = factory;
}
......@@ -120,7 +117,20 @@ public class JettyRequestUpgradeStrategy implements RequestUpgradeStrategy, Serv
if (!isRunning()) {
this.running = true;
try {
this.factoryAdapter.start();
if (this.factory == null) {
this.factory = new WebSocketServerFactory(servletContext, this.policy);
}
this.factory.setCreator(new WebSocketCreator() {
@Override
public Object createWebSocket(ServletUpgradeRequest request, ServletUpgradeResponse response) {
WebSocketHandlerContainer container = containerHolder.get();
Assert.state(container != null, "Expected WebSocketHandlerContainer");
response.setAcceptedSubProtocol(container.getSelectedProtocol());
response.setExtensions(container.getExtensionConfigs());
return container.getHandler();
}
});
this.factory.start();
}
catch (Throwable ex) {
throw new IllegalStateException("Unable to start Jetty WebSocketServerFactory", ex);
......@@ -132,11 +142,13 @@ public class JettyRequestUpgradeStrategy implements RequestUpgradeStrategy, Serv
public void stop() {
if (isRunning()) {
this.running = false;
try {
this.factoryAdapter.stop();
}
catch (Throwable ex) {
throw new IllegalStateException("Unable to stop Jetty WebSocketServerFactory", ex);
if (this.factory != null) {
try {
this.factory.stop();
}
catch (Throwable ex) {
throw new IllegalStateException("Unable to stop Jetty WebSocketServerFactory", ex);
}
}
}
}
......@@ -161,7 +173,7 @@ public class JettyRequestUpgradeStrategy implements RequestUpgradeStrategy, Serv
}
private List<WebSocketExtension> buildWebSocketExtensions() {
Set<String> names = this.factoryAdapter.getFactory().getExtensionFactory().getExtensionNames();
Set<String> names = this.factory.getExtensionFactory().getExtensionNames();
List<WebSocketExtension> result = new ArrayList<>(names.size());
for (String name : names) {
result.add(new WebSocketExtension(name));
......@@ -180,8 +192,7 @@ public class JettyRequestUpgradeStrategy implements RequestUpgradeStrategy, Serv
Assert.isInstanceOf(ServletServerHttpResponse.class, response, "ServletServerHttpResponse required");
HttpServletResponse servletResponse = ((ServletServerHttpResponse) response).getServletResponse();
Assert.isTrue(this.factoryAdapter.getFactory().isUpgradeRequest(servletRequest, servletResponse),
"Not a WebSocket handshake");
Assert.isTrue(this.factory.isUpgradeRequest(servletRequest, servletResponse), "Not a WebSocket handshake");
JettyWebSocketSession session = new JettyWebSocketSession(attributes, user);
JettyWebSocketHandlerAdapter handlerAdapter = new JettyWebSocketHandlerAdapter(wsHandler, session);
......@@ -191,7 +202,7 @@ public class JettyRequestUpgradeStrategy implements RequestUpgradeStrategy, Serv
try {
containerHolder.set(container);
this.factoryAdapter.getFactory().acceptWebSocket(servletRequest, servletResponse);
this.factory.acceptWebSocket(servletRequest, servletResponse);
}
catch (IOException ex) {
throw new HandshakeFailureException(
......@@ -240,93 +251,4 @@ public class JettyRequestUpgradeStrategy implements RequestUpgradeStrategy, Serv
}
}
private static abstract class WebSocketServerFactoryAdapter {
private WebSocketPolicy policy;
private WebSocketServerFactory factory;
public void setPolicy(WebSocketPolicy policy) {
this.policy = policy;
}
public void setFactory(WebSocketServerFactory factory) {
this.factory = factory;
}
public WebSocketServerFactory getFactory() {
return this.factory;
}
public void start() throws Exception {
if (this.factory == null) {
this.factory = createFactory(this.policy);
}
this.factory.setCreator(new WebSocketCreator() {
@Override
public Object createWebSocket(ServletUpgradeRequest request, ServletUpgradeResponse response) {
WebSocketHandlerContainer container = containerHolder.get();
Assert.state(container != null, "Expected WebSocketHandlerContainer");
response.setAcceptedSubProtocol(container.getSelectedProtocol());
response.setExtensions(container.getExtensionConfigs());
return container.getHandler();
}
});
startFactory(this.factory);
}
public void stop() throws Exception {
if (this.factory != null) {
stopFactory(this.factory);
}
}
protected abstract WebSocketServerFactory createFactory(WebSocketPolicy policy) throws Exception;
protected abstract void startFactory(WebSocketServerFactory factory) throws Exception;
protected abstract void stopFactory(WebSocketServerFactory factory) throws Exception;
}
// Jetty 9.3.15+
private class ModernJettyWebSocketServerFactoryAdapter extends WebSocketServerFactoryAdapter {
@Override
protected WebSocketServerFactory createFactory(WebSocketPolicy policy) throws Exception {
return new WebSocketServerFactory(servletContext, policy);
}
@Override
protected void startFactory(WebSocketServerFactory factory) throws Exception {
factory.start();
}
@Override
protected void stopFactory(WebSocketServerFactory factory) throws Exception {
factory.stop();
}
}
// Jetty <9.3.15
private class LegacyJettyWebSocketServerFactoryAdapter extends WebSocketServerFactoryAdapter {
@Override
protected WebSocketServerFactory createFactory(WebSocketPolicy policy) throws Exception {
return WebSocketServerFactory.class.getConstructor(WebSocketPolicy.class).newInstance(policy);
}
@Override
protected void startFactory(WebSocketServerFactory factory) throws Exception {
WebSocketServerFactory.class.getMethod("init", ServletContext.class).invoke(factory, servletContext);
}
@Override
protected void stopFactory(WebSocketServerFactory factory) throws Exception {
WebSocketServerFactory.class.getMethod("cleanup").invoke(factory);
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册