ConnectorProvider support added to mp rest client (#4347)

* ConnectorProvider support added to mp rest client

Signed-off-by: David Kral <david.k.kral@oracle.com>
diff --git a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/RestClientBuilderImpl.java b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/RestClientBuilderImpl.java
index e963850..b67aa43 100644
--- a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/RestClientBuilderImpl.java
+++ b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/RestClientBuilderImpl.java
@@ -31,7 +31,6 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
-import java.util.ServiceLoader;
 import java.util.Set;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
@@ -59,8 +58,11 @@
 import org.eclipse.microprofile.rest.client.ext.AsyncInvocationInterceptorFactory;
 import org.eclipse.microprofile.rest.client.ext.ResponseExceptionMapper;
 import org.eclipse.microprofile.rest.client.spi.RestClientListener;
+import org.glassfish.jersey.client.ClientConfig;
 import org.glassfish.jersey.client.Initializable;
+import org.glassfish.jersey.client.spi.ConnectorProvider;
 import org.glassfish.jersey.ext.cdi1x.internal.CdiUtil;
+import org.glassfish.jersey.internal.ServiceFinder;
 import org.glassfish.jersey.internal.inject.InjectionManager;
 import org.glassfish.jersey.internal.inject.InjectionManagerSupplier;
 import org.glassfish.jersey.internal.util.ReflectionHelper;
@@ -92,6 +94,7 @@
     private KeyStore sslTrustStore;
     private KeyStore sslKeyStore;
     private char[] sslKeyStorePassword;
+    private ConnectorProvider connector;
 
     RestClientBuilderImpl() {
         clientBuilder = ClientBuilder.newBuilder();
@@ -142,15 +145,15 @@
             throw new IllegalStateException("Base uri/url cannot be null!");
         }
 
+        for (RestClientListener restClientListener : ServiceFinder.find(RestClientListener.class)) {
+            restClientListener.onNewClient(interfaceClass, this);
+        }
+
         //Provider registration part
         processProviders(interfaceClass);
         InjectionManagerExposer injectionManagerExposer = new InjectionManagerExposer();
         register(injectionManagerExposer);
 
-        for (RestClientListener restClientListener : ServiceLoader.load(RestClientListener.class)) {
-            restClientListener.onNewClient(interfaceClass, this);
-        }
-
         //We need to check first if default exception mapper was not disabled by property on builder.
         registerExceptionMapper();
         //sort all AsyncInvocationInterceptorFactory by priority
@@ -174,7 +177,16 @@
             clientBuilder.keyStore(sslKeyStore, sslKeyStorePassword);
         }
 
-        Client client = clientBuilder.build();
+        Client client;
+        if (connector == null) {
+            client = clientBuilder.build();
+        } else {
+            ClientConfig config = new ClientConfig();
+            config.loadFrom(getConfiguration());
+            config.connectorProvider(connector);
+            client = ClientBuilder.newClient(config);
+        }
+
         if (client instanceof Initializable) {
             ((Initializable) client).preInitialize();
         }
@@ -377,7 +389,8 @@
     private boolean isSupportedCustomProvider(Class<?> providerClass) {
         return ResponseExceptionMapper.class.isAssignableFrom(providerClass)
                 || ParamConverterProvider.class.isAssignableFrom(providerClass)
-                || AsyncInvocationInterceptorFactory.class.isAssignableFrom(providerClass);
+                || AsyncInvocationInterceptorFactory.class.isAssignableFrom(providerClass)
+                || ConnectorProvider.class.isAssignableFrom(providerClass);
     }
 
     private void registerCustomProvider(Object instance, Integer priority) {
@@ -399,6 +412,9 @@
                     .add(new AsyncInvocationInterceptorFactoryPriorityWrapper((AsyncInvocationInterceptorFactory) instance,
                                                                               priority));
         }
+        if (instance instanceof ConnectorProvider) {
+            connector = (ConnectorProvider) instance;
+        }
     }
 
     private static class InjectionManagerExposer implements Feature {
diff --git a/tests/integration/microprofile/rest-client/pom.xml b/tests/integration/microprofile/rest-client/pom.xml
index bbda656..7367703 100644
--- a/tests/integration/microprofile/rest-client/pom.xml
+++ b/tests/integration/microprofile/rest-client/pom.xml
@@ -87,6 +87,11 @@
             <type>pom</type>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.glassfish.jersey.connectors</groupId>
+            <artifactId>jersey-apache-connector</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
     <profiles>
diff --git a/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/restclient/ConnectorTest.java b/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/restclient/ConnectorTest.java
new file mode 100644
index 0000000..6a3cb19
--- /dev/null
+++ b/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/restclient/ConnectorTest.java
@@ -0,0 +1,70 @@
+/*
+ * 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.restclient;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.concurrent.CountDownLatch;
+
+import org.apache.http.conn.ConnectionRequest;
+import org.apache.http.conn.routing.HttpRoute;
+import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
+import org.eclipse.microprofile.rest.client.RestClientBuilder;
+import org.glassfish.jersey.apache.connector.ApacheClientProperties;
+import org.glassfish.jersey.apache.connector.ApacheConnectorProvider;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
+import org.junit.Test;
+
+import static org.testng.Assert.assertEquals;
+
+/**
+ * Created by David Kral.
+ */
+public class ConnectorTest extends JerseyTest {
+
+    @Override
+    protected ResourceConfig configure() {
+        enable(TestProperties.LOG_TRAFFIC);
+        return new ResourceConfig(ApplicationResourceImpl.class);
+    }
+
+    @Test
+    public void testConnector() throws URISyntaxException {
+        CountDownLatch countDownLatch = new CountDownLatch(1);
+        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager() {
+
+            @Override
+            public ConnectionRequest requestConnection(HttpRoute route, Object state) {
+                countDownLatch.countDown();
+                return super.requestConnection(route, state);
+            }
+
+        };
+
+        ApplicationResource app = RestClientBuilder.newBuilder()
+                .baseUri(new URI("http://localhost:9998"))
+                .property(ApacheClientProperties.CONNECTION_MANAGER, connectionManager)
+                .register(ApacheConnectorProvider.class)
+                .build(ApplicationResource.class);
+
+        app.getTestMap();
+        assertEquals(countDownLatch.getCount(), 0);
+    }
+
+}