You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@knox.apache.org by su...@apache.org on 2017/01/11 20:03:53 UTC

knox git commit: KNOX-805 ability to define custom HttpClient (Vincent Devillers via Sumit Gupta)

Repository: knox
Updated Branches:
  refs/heads/master 7458fa670 -> e2e39f3fa


KNOX-805 ability to define custom HttpClient (Vincent Devillers via Sumit Gupta)


Project: http://git-wip-us.apache.org/repos/asf/knox/repo
Commit: http://git-wip-us.apache.org/repos/asf/knox/commit/e2e39f3f
Tree: http://git-wip-us.apache.org/repos/asf/knox/tree/e2e39f3f
Diff: http://git-wip-us.apache.org/repos/asf/knox/diff/e2e39f3f

Branch: refs/heads/master
Commit: e2e39f3faa2f75ac632c425fe916bfed1c6bcc0d
Parents: 7458fa6
Author: Sumit Gupta <su...@apache.org>
Authored: Wed Jan 11 14:55:54 2017 -0500
Committer: Sumit Gupta <su...@apache.org>
Committed: Wed Jan 11 15:03:47 2017 -0500

----------------------------------------------------------------------
 gateway-shell/pom.xml                           |   5 +
 .../hadoop/gateway/shell/ClientContext.java     | 206 +++++++++++++++++++
 .../org/apache/hadoop/gateway/shell/Hadoop.java | 158 +++++++-------
 3 files changed, 298 insertions(+), 71 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/knox/blob/e2e39f3f/gateway-shell/pom.xml
----------------------------------------------------------------------
diff --git a/gateway-shell/pom.xml b/gateway-shell/pom.xml
index a698eed..a6f1ea2 100644
--- a/gateway-shell/pom.xml
+++ b/gateway-shell/pom.xml
@@ -76,6 +76,11 @@
             <groupId>commons-io</groupId>
             <artifactId>commons-io</artifactId>
         </dependency>
+        <dependency>
+            <groupId>commons-configuration</groupId>
+            <artifactId>commons-configuration</artifactId>
+            <version>1.6</version>
+        </dependency>
 
         <dependency>
             <groupId>junit</groupId>

http://git-wip-us.apache.org/repos/asf/knox/blob/e2e39f3f/gateway-shell/src/main/java/org/apache/hadoop/gateway/shell/ClientContext.java
----------------------------------------------------------------------
diff --git a/gateway-shell/src/main/java/org/apache/hadoop/gateway/shell/ClientContext.java b/gateway-shell/src/main/java/org/apache/hadoop/gateway/shell/ClientContext.java
new file mode 100644
index 0000000..6055f68
--- /dev/null
+++ b/gateway-shell/src/main/java/org/apache/hadoop/gateway/shell/ClientContext.java
@@ -0,0 +1,206 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.hadoop.gateway.shell;
+
+import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration.MapConfiguration;
+import org.apache.commons.configuration.SubsetConfiguration;
+
+import java.util.HashMap;
+
+public class ClientContext {
+
+  private final Configuration configuration;
+  private final PoolContext poolContext;
+  private final SocketContext socketContext;
+  private final ConnectionContext connectionContext;
+
+  private ClientContext() {
+    configuration = new MapConfiguration(new HashMap<>());
+    poolContext = new PoolContext(this);
+    socketContext = new SocketContext(this);
+    connectionContext = new ConnectionContext(this);
+  }
+
+  private static class Context {
+    private final ClientContext clientContext;
+    protected final Configuration configuration;
+
+    private Context(ClientContext clientContext, String prefix) {
+      this.clientContext = clientContext;
+      this.configuration = new SubsetConfiguration(clientContext.configuration, prefix);
+    }
+
+    public ClientContext end() {
+      return clientContext;
+    }
+  }
+
+  public static class PoolContext extends Context {
+
+    private PoolContext(ClientContext clientContext) {
+      super(clientContext, "pool");
+    }
+
+    public int maxTotal() {
+      return configuration.getInt("total", 20);
+    }
+
+    public PoolContext maxTotal(final int timeout) {
+      configuration.addProperty("total", timeout);
+      return this;
+    }
+
+    public int defaultMaxPerRoute() {
+      return configuration.getInt("max-per-route", 20);
+    }
+
+    public PoolContext defaultMaxPerRoute(final int reuseaddr) {
+      configuration.addProperty("max-per-route", reuseaddr);
+      return this;
+    }
+  }
+
+  public static class SocketContext extends Context {
+
+    private SocketContext(ClientContext clientContext) {
+      super(clientContext, "socket");
+    }
+
+    public int timeout() {
+      return configuration.getInt("timeout", 0);
+    }
+
+    public SocketContext timeout(final int timeout) {
+      configuration.addProperty("timeout", timeout);
+      return this;
+    }
+
+    public boolean reuseAddress() {
+      return configuration.getBoolean("reuse-address", false);
+    }
+
+    public SocketContext reuseAddress(final boolean reuseAddress) {
+      configuration.addProperty("reuse-address", reuseAddress);
+      return this;
+    }
+
+    public int linger() {
+      return configuration.getInt("linger", -1);
+    }
+
+    public SocketContext linger(final int value) {
+      configuration.addProperty("linger", value);
+      return this;
+    }
+
+    public boolean keepalive() {
+      return configuration.getBoolean("keepalive", false);
+    }
+
+    public SocketContext keepalive(final boolean enableKeepalive) {
+      configuration.addProperty("keepalive", enableKeepalive);
+      return this;
+    }
+
+    public boolean tcpNoDelay() {
+      return configuration.getBoolean("nodelay", true);
+    }
+
+    public SocketContext tcpNoDelay(final boolean value) {
+      configuration.addProperty("nodelay", value);
+      return this;
+    }
+  }
+
+  public static class ConnectionContext extends Context {
+
+    private ConnectionContext(ClientContext clientContext) {
+      super(clientContext, "connection");
+    }
+
+    public int timeout() {
+      return configuration.getInt("timeout", 0);
+    }
+
+    public ConnectionContext timeout(final int timeout) {
+      configuration.addProperty("timeout", timeout);
+      return this;
+    }
+
+    public boolean staleChecking() {
+      return configuration.getBoolean("stalecheck", true);
+    }
+
+    public ConnectionContext staleChecking(final boolean value) {
+      configuration.addProperty("stalecheck", value);
+      return this;
+    }
+
+    public boolean secure() {
+      return configuration.getBoolean("secure", true);
+    }
+
+    public ConnectionContext secure(final boolean value) {
+      configuration.addProperty("secure", value);
+      return this;
+    }
+
+    public int bufferSize() {
+      return configuration.getInt("buffer-size", -1);
+    }
+
+    public ConnectionContext bufferSize(final int size) {
+      configuration.addProperty("buffer-size", size);
+      return this;
+    }
+  }
+
+  public PoolContext pool() {
+    return poolContext;
+  }
+
+  public SocketContext socket() {
+    return socketContext;
+  }
+
+  public ConnectionContext connection() {
+    return connectionContext;
+  }
+
+  public static ClientContext with(final String username, final String password, final String url) {
+    ClientContext context = new ClientContext();
+    context.configuration.addProperty("username", username);
+    context.configuration.addProperty("password", password);
+    context.configuration.addProperty("url", url);
+    return context;
+  }
+
+  public String username() {
+    return configuration.getString("username");
+  }
+
+  public String password() {
+    return configuration.getString("password");
+  }
+
+  public String url() {
+    return configuration.getString("url");
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/knox/blob/e2e39f3f/gateway-shell/src/main/java/org/apache/hadoop/gateway/shell/Hadoop.java
----------------------------------------------------------------------
diff --git a/gateway-shell/src/main/java/org/apache/hadoop/gateway/shell/Hadoop.java b/gateway-shell/src/main/java/org/apache/hadoop/gateway/shell/Hadoop.java
index 6bfc407..651b061 100644
--- a/gateway-shell/src/main/java/org/apache/hadoop/gateway/shell/Hadoop.java
+++ b/gateway-shell/src/main/java/org/apache/hadoop/gateway/shell/Hadoop.java
@@ -24,19 +24,28 @@ import org.apache.http.HttpResponse;
 import org.apache.http.auth.AuthScope;
 import org.apache.http.auth.UsernamePasswordCredentials;
 import org.apache.http.client.AuthCache;
-import org.apache.http.client.protocol.ClientContext;
-import org.apache.http.conn.scheme.PlainSocketFactory;
-import org.apache.http.conn.scheme.Scheme;
-import org.apache.http.conn.scheme.SchemeRegistry;
-import org.apache.http.conn.ssl.SSLContextBuilder;
-import org.apache.http.conn.ssl.SSLSocketFactory;
+import org.apache.http.client.CredentialsProvider;
+import org.apache.http.config.ConnectionConfig;
+import org.apache.http.config.Registry;
+import org.apache.http.config.RegistryBuilder;
+import org.apache.http.config.SocketConfig;
+import org.apache.http.conn.socket.ConnectionSocketFactory;
+import org.apache.http.conn.socket.PlainConnectionSocketFactory;
+import org.apache.http.conn.ssl.NoopHostnameVerifier;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
 import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
+import org.apache.http.conn.ssl.TrustStrategy;
 import org.apache.http.impl.auth.BasicScheme;
 import org.apache.http.impl.client.BasicAuthCache;
-import org.apache.http.impl.client.DefaultHttpClient;
-import org.apache.http.impl.conn.PoolingClientConnectionManager;
+import org.apache.http.impl.client.BasicCredentialsProvider;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
 import org.apache.http.protocol.BasicHttpContext;
+import org.apache.http.ssl.SSLContexts;
 
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.SSLContext;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
@@ -57,8 +66,6 @@ import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 
-import javax.net.ssl.SSLContext;
-
 public class Hadoop {
 
   private static final String GATEWAY_CLIENT_TRUST_DEFAULT_PASS = "changeit";
@@ -69,69 +76,91 @@ public class Hadoop {
 
   String base;
   HttpHost host;
-  DefaultHttpClient client;
+  CloseableHttpClient client;
   BasicHttpContext context;
-  String username;
-  String password;
   ExecutorService executor;
 
   public static Hadoop login( String url, String username, String password ) throws URISyntaxException {
-    return new Hadoop( url, username, password, true );
+    return new Hadoop(ClientContext.with(username, password, url));
   }
 
-  public static Hadoop loginInsecure( String url, String username, String password ) throws URISyntaxException {
-    System.out.println("**************** WARNING ******************\n"
-        + "This is an insecure client instance and may\n"
-        + "leave the interactions subject to a man in\n"
-        + "the middle attack. Please use the login()\n"
-        + "method instead of loginInsecure() for any\n"
-        + "sensitive or production usecases.\n"
-        + "*******************************************");
-    return new Hadoop( url, username, password );
+  public static Hadoop loginInsecure(String url, String username, String password) throws URISyntaxException {
+    return new Hadoop(ClientContext.with(username, password, url)
+            .connection().secure(false).end());
   }
 
-  private Hadoop( String url, String username, String password ) throws HadoopException, URISyntaxException {
-    this(url, username, password, false);
-  }
-
-  private Hadoop( String url, String username, String password, boolean secure ) throws HadoopException, URISyntaxException {
+  public Hadoop( ClientContext clientContext) throws HadoopException, URISyntaxException {
     this.executor = Executors.newCachedThreadPool();
-    this.base = url;
-    this.username = username;
-    this.password = password;
-
-    URI uri = new URI( url );
-    host = new HttpHost( uri.getHost(), uri.getPort(), uri.getScheme() );
+    this.base = clientContext.url();
 
     try {
-      if (!secure) {
-        client = createInsecureClient();
-      }
-      else {
-        client = createClient();
-      }
-      client.getCredentialsProvider().setCredentials(
-          new AuthScope( host.getHostName(), host.getPort() ),
-          new UsernamePasswordCredentials( username, password ) );
-      AuthCache authCache = new BasicAuthCache();
-      BasicScheme authScheme = new BasicScheme();
-      authCache.put( host, authScheme );
-      context = new BasicHttpContext();
-      context.setAttribute( ClientContext.AUTH_CACHE, authCache );
-    } catch( GeneralSecurityException e ) {
-      throw new HadoopException( "Failed to create HTTP client.", e );
+      client = createClient(clientContext);
+    } catch (GeneralSecurityException e) {
+      throw new HadoopException("Failed to create HTTP client.", e);
     }
   }
 
-  private static DefaultHttpClient createClient() throws GeneralSecurityException {
-    SchemeRegistry registry = new SchemeRegistry();
+  private CloseableHttpClient createClient(ClientContext clientContext) throws GeneralSecurityException {
+
+    // SSL
+    HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE;
+    TrustStrategy trustStrategy = TrustSelfSignedStrategy.INSTANCE;
+    if (clientContext.connection().secure()) {
+      hostnameVerifier = SSLConnectionSocketFactory.getDefaultHostnameVerifier();
+    } else {
+      System.out.println("**************** WARNING ******************\n"
+              + "This is an insecure client instance and may\n"
+              + "leave the interactions subject to a man in\n"
+              + "the middle attack. Please use the login()\n"
+              + "method instead of loginInsecure() for any\n"
+              + "sensitive or production usecases.\n"
+              + "*******************************************");
+    }
+
     KeyStore trustStore = getTrustStore();
-    SSLSocketFactory socketFactory = new SSLSocketFactory(trustStore);
-    registry.register( new Scheme( "https", 443, socketFactory ) );
-    registry.register( new Scheme( "http", 80, new PlainSocketFactory() ) );
-    PoolingClientConnectionManager mgr = new PoolingClientConnectionManager( registry );
-    DefaultHttpClient client = new DefaultHttpClient( mgr, new DefaultHttpClient().getParams() );
-    return client;
+    SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(trustStore, trustStrategy).build();
+    Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
+            .register("http", PlainConnectionSocketFactory.getSocketFactory())
+            .register("https", new SSLConnectionSocketFactory(sslContext, hostnameVerifier)).build();
+
+    // Pool
+    PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry);
+    connectionManager.setMaxTotal(clientContext.pool().maxTotal());
+    connectionManager.setDefaultMaxPerRoute(clientContext.pool().defaultMaxPerRoute());
+
+    ConnectionConfig connectionConfig = ConnectionConfig.custom()
+            .setBufferSize(clientContext.connection().bufferSize())
+            .build();
+    connectionManager.setDefaultConnectionConfig(connectionConfig);
+
+    SocketConfig socketConfig = SocketConfig.custom()
+            .setSoKeepAlive(clientContext.socket().keepalive())
+            .setSoLinger(clientContext.socket().linger())
+            .setSoReuseAddress(clientContext.socket().reuseAddress())
+            .setSoTimeout(clientContext.socket().timeout())
+            .setTcpNoDelay(clientContext.socket().tcpNoDelay())
+            .build();
+    connectionManager.setDefaultSocketConfig(socketConfig);
+
+    // Auth
+    URI uri = URI.create(clientContext.url());
+    host = new HttpHost(uri.getHost(), uri.getPort(), uri.getScheme());
+
+    CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
+    credentialsProvider.setCredentials(
+            new AuthScope(host.getHostName(), host.getPort()),
+            new UsernamePasswordCredentials(clientContext.username(), clientContext.password()));
+
+    AuthCache authCache = new BasicAuthCache();
+    BasicScheme authScheme = new BasicScheme();
+    authCache.put(host, authScheme);
+    context = new BasicHttpContext();
+    context.setAttribute(org.apache.http.client.protocol.HttpClientContext.AUTH_CACHE, authCache);
+
+    return HttpClients.custom()
+            .setConnectionManager(connectionManager)
+            .setDefaultCredentialsProvider(credentialsProvider)
+            .build();
   }
 
   private static KeyStore getTrustStore() throws GeneralSecurityException {
@@ -197,18 +226,6 @@ public class Hadoop {
     return ks;
   }
 
-  private static DefaultHttpClient createInsecureClient() throws GeneralSecurityException {
-    SchemeRegistry registry = new SchemeRegistry();
-    SSLSocketFactory socketFactory = new SSLSocketFactory(
-        new TrustSelfSignedStrategy(),
-        SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER );
-    registry.register( new Scheme( "https", 443, socketFactory ) );
-    registry.register( new Scheme( "http", 80, new PlainSocketFactory() ) );
-    PoolingClientConnectionManager mgr = new PoolingClientConnectionManager( registry );
-    DefaultHttpClient client = new DefaultHttpClient( mgr, new DefaultHttpClient().getParams() );
-    return client;
-  }
-
   public String base() {
     return base;
   }
@@ -254,5 +271,4 @@ public class Hadoop {
     executor.shutdown();
     return executor.awaitTermination( timeout, unit );
   }
-
 }