Allow for providing Jetty HttpClient to Jetty Connector (#4089)
Signed-off-by: Jan Supol <jan.supol@oracle.com>
diff --git a/connectors/jetty-connector/src/main/java/org/glassfish/jersey/jetty/connector/JettyConnector.java b/connectors/jetty-connector/src/main/java/org/glassfish/jersey/jetty/connector/JettyConnector.java
index 68886e7..8346683 100644
--- a/connectors/jetty-connector/src/main/java/org/glassfish/jersey/jetty/connector/JettyConnector.java
+++ b/connectors/jetty-connector/src/main/java/org/glassfish/jersey/jetty/connector/JettyConnector.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -28,6 +28,7 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.concurrent.CancellationException;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;
@@ -136,18 +137,28 @@
* @param config client configuration.
*/
JettyConnector(final Client jaxrsClient, final Configuration config) {
- final SSLContext sslContext = jaxrsClient.getSslContext();
- final SslContextFactory sslContextFactory = new SslContextFactory();
- sslContextFactory.setSslContext(sslContext);
+ HttpClient httpClient = null;
+ if (config.isRegistered(JettyHttpClientSupplier.class)) {
+ Optional<Object> contract = config.getInstances().stream()
+ .filter(a-> JettyHttpClientSupplier.class.isInstance(a)).findFirst();
+ if (contract.isPresent()) {
+ httpClient = ((JettyHttpClientSupplier) contract.get()).getHttpClient();
+ }
+ }
+ if (httpClient == null) {
+ final SSLContext sslContext = jaxrsClient.getSslContext();
+ final SslContextFactory sslContextFactory = new SslContextFactory();
+ sslContextFactory.setSslContext(sslContext);
+ httpClient = new HttpClient(sslContextFactory);
+ }
+ this.client = httpClient;
Boolean enableHostnameVerification = (Boolean) config.getProperties()
- .get(JettyClientProperties.ENABLE_SSL_HOSTNAME_VERIFICATION);
+ .get(JettyClientProperties.ENABLE_SSL_HOSTNAME_VERIFICATION);
if (enableHostnameVerification != null && enableHostnameVerification) {
- sslContextFactory.setEndpointIdentificationAlgorithm("https");
+ client.getSslContextFactory().setEndpointIdentificationAlgorithm("https");
}
- this.client = new HttpClient(sslContextFactory);
-
final Object connectTimeout = config.getProperties().get(ClientProperties.CONNECT_TIMEOUT);
if (connectTimeout != null && connectTimeout instanceof Integer && (Integer) connectTimeout > 0) {
client.setConnectTimeout((Integer) connectTimeout);
diff --git a/connectors/jetty-connector/src/main/java/org/glassfish/jersey/jetty/connector/JettyHttpClientContract.java b/connectors/jetty-connector/src/main/java/org/glassfish/jersey/jetty/connector/JettyHttpClientContract.java
new file mode 100644
index 0000000..7547cd9
--- /dev/null
+++ b/connectors/jetty-connector/src/main/java/org/glassfish/jersey/jetty/connector/JettyHttpClientContract.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.jetty.connector;
+
+import org.eclipse.jetty.client.HttpClient;
+import org.glassfish.jersey.spi.Contract;
+
+/**
+ * A contract that allows for an optional registration of user predefined Jetty {@code HttpClient}
+ * that is consequently used by {@link JettyConnector}
+ */
+@Contract
+public interface JettyHttpClientContract {
+ /**
+ * Supply a user predefined HttpClient
+ * @return a user predefined HttpClient
+ */
+ HttpClient getHttpClient();
+}
diff --git a/connectors/jetty-connector/src/main/java/org/glassfish/jersey/jetty/connector/JettyHttpClientSupplier.java b/connectors/jetty-connector/src/main/java/org/glassfish/jersey/jetty/connector/JettyHttpClientSupplier.java
new file mode 100644
index 0000000..681165d
--- /dev/null
+++ b/connectors/jetty-connector/src/main/java/org/glassfish/jersey/jetty/connector/JettyHttpClientSupplier.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+package org.glassfish.jersey.jetty.connector;
+
+import org.eclipse.jetty.client.HttpClient;
+
+/**
+ * Jetty HttpClient supplier to be registered into Jersey configuration to be used by {@link JettyConnector}.
+ * Not every possible configuration option is covered by the Jetty Connector and this supplier offers a way to provide
+ * an HttpClient that has configured the options not covered by the Jetty Connector.
+ * <p>
+ * Typical usage:
+ * </p>
+ * <pre>
+ * {@code
+ * HttpClient httpClient = ...
+ *
+ * ClientConfig config = new ClientConfig();
+ * config.connectorProvider(new JettyConnectorProvider());
+ * config.register(new JettyHttpClientSupplier(httpClient));
+ * Client client = ClientBuilder.newClient(config);
+ * }
+ * </pre>
+ * <p>
+ * The {@code HttpClient} is configured as if it was created by {@link JettyConnector} the usual way.
+ * </p>
+ */
+public class JettyHttpClientSupplier implements JettyHttpClientContract {
+ private final HttpClient httpClient;
+
+ /**
+ * {@code HttpClient} supplier to be optionally registered to a {@link org.glassfish.jersey.client.ClientConfig}
+ * @param httpClient a HttpClient to be supplied when {@link JettyConnector#getHttpClient()} is called.
+ */
+ public JettyHttpClientSupplier(HttpClient httpClient) {
+ this.httpClient = httpClient;
+ }
+
+ @Override
+ public HttpClient getHttpClient() {
+ return httpClient;
+ }
+}
diff --git a/connectors/jetty-connector/src/test/java/org/glassfish/jersey/jetty/connector/UnderlyingHttpClientAccessTest.java b/connectors/jetty-connector/src/test/java/org/glassfish/jersey/jetty/connector/UnderlyingHttpClientAccessTest.java
index 7cefc2b..fc60fc7 100644
--- a/connectors/jetty-connector/src/test/java/org/glassfish/jersey/jetty/connector/UnderlyingHttpClientAccessTest.java
+++ b/connectors/jetty-connector/src/test/java/org/glassfish/jersey/jetty/connector/UnderlyingHttpClientAccessTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2019 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -24,8 +24,11 @@
import org.eclipse.jetty.client.HttpClient;
import org.junit.Test;
+
+import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertThat;
/**
* Test of access to the underlying HTTP client instance used by the connector.
@@ -54,4 +57,18 @@
hcOnClient, hcOnTarget
);
}
+
+ @Test
+ public void testGetProvidedClientInstance() {
+ final HttpClient httpClient = new HttpClient();
+ final ClientConfig clientConfig = new ClientConfig()
+ .connectorProvider(new JettyConnectorProvider())
+ .register(new JettyHttpClientSupplier(httpClient));
+ final Client client = ClientBuilder.newClient(clientConfig);
+ final WebTarget target = client.target("http://localhost/");
+ final HttpClient hcOnTarget = JettyConnectorProvider.getHttpClient(target);
+
+ assertThat("Instance provided to a ClientConfig differs from instance provided by JettyProvider",
+ httpClient, is(hcOnTarget));
+ }
}