Drop support for Jetty 9.3 and OkHttp 2.x
Issue: SPR-15038
This commit is contained in:
@@ -1,105 +0,0 @@
|
||||
/*
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
/*
|
||||
* 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());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,149 +0,0 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* 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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user