fix https+auth bug (#57)

Change-Id: Ic791c21271c9c9ca60b0ff4294feb5fe2165452a
diff --git a/pom.xml b/pom.xml
index f271922..c356050 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
 
     <groupId>com.baidu.hugegraph</groupId>
     <artifactId>hugegraph-common</artifactId>
-    <version>1.8.0</version>
+    <version>1.8.1</version>
 
     <name>hugegraph-common</name>
     <url>https://github.com/hugegraph/hugegraph-common</url>
@@ -260,7 +260,7 @@
                         <manifestEntries>
                             <!-- Must be on one line, otherwise the automatic
                                  upgrade script cannot replace the version number -->
-                            <Implementation-Version>1.8.0.0</Implementation-Version>
+                            <Implementation-Version>1.8.1.0</Implementation-Version>
                         </manifestEntries>
                     </archive>
                 </configuration>
diff --git a/src/main/java/com/baidu/hugegraph/rest/AbstractRestClient.java b/src/main/java/com/baidu/hugegraph/rest/AbstractRestClient.java
index e4907f6..3507169 100644
--- a/src/main/java/com/baidu/hugegraph/rest/AbstractRestClient.java
+++ b/src/main/java/com/baidu/hugegraph/rest/AbstractRestClient.java
@@ -47,6 +47,11 @@
 import javax.ws.rs.core.Variant;
 
 import org.apache.commons.lang3.tuple.Pair;
+import org.apache.http.config.Registry;
+import org.apache.http.config.RegistryBuilder;
+import org.apache.http.conn.socket.ConnectionSocketFactory;
+import org.apache.http.conn.socket.PlainConnectionSocketFactory;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
 import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
 import org.apache.http.pool.PoolStats;
 import org.glassfish.jersey.SslConfigurator;
@@ -60,6 +65,7 @@
 import org.glassfish.jersey.message.GZipEncoder;
 import org.glassfish.jersey.uri.UriComponent;
 
+import com.baidu.hugegraph.util.E;
 import com.baidu.hugegraph.util.ExecutorUtil;
 import com.google.common.collect.ImmutableMap;
 
@@ -112,25 +118,19 @@
 
     public AbstractRestClient(String url, String user, String password,
                               int timeout, int maxTotal, int maxPerRoute,
-                              String protocol, String trustStoreFile,
+                              String trustStoreFile,
                               String trustStorePassword) {
         this(url, new ConfigBuilder().configTimeout(timeout)
                                      .configUser(user, password)
                                      .configPool(maxTotal, maxPerRoute)
-                                     .configSSL(protocol, trustStoreFile,
+                                     .configSSL(trustStoreFile,
                                                 trustStorePassword)
                                      .build());
     }
 
     public AbstractRestClient(String url, ClientConfig config) {
-        Client client = null;
-        Object protocol = config.getProperty("protocol");
-        if (protocol != null && protocol.equals("https")) {
-            client = wrapTrustConfig(url, config);
-        } else {
-            client = ClientBuilder.newClient(config);
-        }
-        this.client = client;
+        configConnectionManager(url, config);
+        this.client = ClientBuilder.newClient(config);
         this.client.register(GZipEncoder.class);
         this.target = this.client.target(url);
         this.pool = (PoolingHttpClientConnectionManager) config.getProperty(
@@ -340,25 +340,69 @@
         return Pair.of(builder, entity);
     }
 
-    private static Client wrapTrustConfig(String url, ClientConfig config) {
-        SslConfigurator sslConfig = SslConfigurator.newInstance();
-        String trustStoreFile = config.getProperty("trustStoreFile").toString();
-        String trustStorePassword = config.getProperty("trustStorePassword")
-                                          .toString();
-        sslConfig.trustStoreFile(trustStoreFile)
-                 .trustStorePassword(trustStorePassword);
-        sslConfig.securityProtocol("SSL");
-        SSLContext context = sslConfig.createSSLContext();
+    private static void configConnectionManager(String url, ClientConfig conf) {
+        /*
+         * Using httpclient with connection pooling, and configuring the
+         * jersey connector, reference:
+         * http://www.theotherian.com/2013/08/jersey-client-2.0-httpclient-timeouts-max-connections.html
+         * https://stackoverflow.com/questions/43228051/memory-issue-with-jax-rs-using-jersey/46175943#46175943
+         *
+         * But the jersey that has been released in the maven central
+         * repository seems to have a bug.
+         * https://github.com/jersey/jersey/pull/3752
+         */
+        PoolingHttpClientConnectionManager pool = connectionManager(url, conf);
+        Object maxTotal = conf.getProperty("maxTotal");
+        Object maxPerRoute = conf.getProperty("maxPerRoute");
+        if (maxTotal != null) {
+            pool.setMaxTotal((int) maxTotal);
+        }
+        if (maxPerRoute != null) {
+            pool.setDefaultMaxPerRoute((int) maxPerRoute);
+        }
+        conf.property(ApacheClientProperties.CONNECTION_MANAGER, pool);
+        conf.connectorProvider(new ApacheConnectorProvider());
+    }
+
+    private static PoolingHttpClientConnectionManager connectionManager(
+                                                      String url,
+                                                      ClientConfig conf) {
+        String protocol = (String) conf.getProperty("protocol");
+        if (protocol == null || protocol.equals("http")) {
+            return new PoolingHttpClientConnectionManager(TTL, TimeUnit.HOURS);
+        }
+
+        assert protocol.equals("https");
+        String trustStoreFile = (String) conf.getProperty("trustStoreFile");
+        E.checkArgument(trustStoreFile != null && !trustStoreFile.isEmpty(),
+                        "The trust store file must be set when use https");
+        String trustStorePass = (String) conf.getProperty("trustStorePassword");
+        E.checkArgument(trustStorePass != null,
+                        "The trust store password must be set when use https");
+        SSLContext context = SslConfigurator.newInstance()
+                                            .trustStoreFile(trustStoreFile)
+                                            .trustStorePassword(trustStorePass)
+                                            .securityProtocol("SSL")
+                                            .createSSLContext();
         TrustManager[] trustAllManager = NoCheckTrustManager.create();
         try {
             context.init(null, trustAllManager, new SecureRandom());
         } catch (KeyManagementException e) {
             throw new ClientException("Failed to init security management", e);
         }
-        return ClientBuilder.newBuilder()
-                            .hostnameVerifier(new HostNameVerifier(url))
-                            .sslContext(context)
-                            .build();
+
+        HostnameVerifier verifier = new HostNameVerifier(url);
+        ConnectionSocketFactory httpSocketFactory, httpsSocketFactory;
+        httpSocketFactory = PlainConnectionSocketFactory.getSocketFactory();
+        httpsSocketFactory = new SSLConnectionSocketFactory(context, verifier);
+        Registry<ConnectionSocketFactory> registry =
+                RegistryBuilder.<ConnectionSocketFactory>create()
+                .register("http", httpSocketFactory)
+                .register("https", httpsSocketFactory)
+                .build();
+        return new PoolingHttpClientConnectionManager(registry, null,
+                                                      null, null, TTL,
+                                                      TimeUnit.HOURS);
     }
 
     public static String encode(String raw) {
@@ -441,22 +485,8 @@
         }
 
         public ConfigBuilder configPool(int maxTotal, int maxPerRoute) {
-            /*
-             * Using httpclient with connection pooling, and configuring the
-             * jersey connector, reference:
-             * http://www.theotherian.com/2013/08/jersey-client-2.0-httpclient-timeouts-max-connections.html
-             * https://stackoverflow.com/questions/43228051/memory-issue-with-jax-rs-using-jersey/46175943#46175943
-             *
-             * But the jersey that has been released in the maven central
-             * repository seems to have a bug.
-             * https://github.com/jersey/jersey/pull/3752
-             */
-            PoolingHttpClientConnectionManager pool;
-            pool = new PoolingHttpClientConnectionManager(TTL, TimeUnit.HOURS);
-            pool.setMaxTotal(maxTotal);
-            pool.setDefaultMaxPerRoute(maxPerRoute);
-            this.config.property(ApacheClientProperties.CONNECTION_MANAGER, pool);
-            this.config.connectorProvider(new ApacheConnectorProvider());
+            this.config.property("maxTotal", maxTotal);
+            this.config.property("maxPerRoute", maxPerRoute);
             return this;
         }
 
@@ -465,9 +495,14 @@
             return this;
         }
 
-        public ConfigBuilder configSSL(String protocol, String trustStoreFile,
+        public ConfigBuilder configSSL(String trustStoreFile,
                                        String trustStorePassword) {
-            this.config.property("protocol", protocol);
+            if (trustStoreFile == null || trustStoreFile.isEmpty() ||
+                trustStorePassword == null) {
+                this.config.property("protocol", "http");
+            } else {
+                this.config.property("protocol", "https");
+            }
             this.config.property("trustStoreFile", trustStoreFile);
             this.config.property("trustStorePassword", trustStorePassword);
             return this;
diff --git a/src/main/java/com/baidu/hugegraph/version/CommonVersion.java b/src/main/java/com/baidu/hugegraph/version/CommonVersion.java
index 28e0393..6a0e310 100644
--- a/src/main/java/com/baidu/hugegraph/version/CommonVersion.java
+++ b/src/main/java/com/baidu/hugegraph/version/CommonVersion.java
@@ -27,5 +27,5 @@
 
     // The second parameter of Version.of() is for all-in-one JAR
     public static final Version VERSION = Version.of(CommonVersion.class,
-                                                     "1.8.0");
+                                                     "1.8.1");
 }
diff --git a/src/test/java/com/baidu/hugegraph/unit/rest/RestClientTest.java b/src/test/java/com/baidu/hugegraph/unit/rest/RestClientTest.java
index 5649b1a..ab3c419 100644
--- a/src/test/java/com/baidu/hugegraph/unit/rest/RestClientTest.java
+++ b/src/test/java/com/baidu/hugegraph/unit/rest/RestClientTest.java
@@ -96,10 +96,10 @@
 
         public RestClientImpl(String url, String user, String password,
                               int timeout, int maxTotal, int maxPerRoute,
-                              String protocol, String trustStoreFile,
-                              String trustStorePassword, int status) {
+                              String trustStoreFile, String trustStorePassword,
+                              int status) {
             super(url, user, password, timeout, maxTotal, maxPerRoute,
-                  protocol, trustStoreFile, trustStorePassword);
+                  trustStoreFile, trustStorePassword);
             this.status = status;
             this.headers = ImmutableMultivaluedMap.empty();
             this.content = "";
@@ -225,7 +225,7 @@
         String trustStoreFile = "src/test/resources/cacerts.jks";
         String trustStorePassword = "changeit";
         RestClient client = new RestClientImpl("/test", "user", "", 1000,
-                                               10, 5, "https", trustStoreFile,
+                                               10, 5, trustStoreFile,
                                                trustStorePassword, 200);
         RestResult restResult = client.post("path", "body");
         Assert.assertEquals(200, restResult.status());