CloseableHttpClient and CloseableHttpAsyncClient to implement ModalClosable
diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/AbstractHttp1IntegrationTestBase.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/AbstractHttp1IntegrationTestBase.java
index 424b719..f9867fb 100644
--- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/AbstractHttp1IntegrationTestBase.java
+++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/AbstractHttp1IntegrationTestBase.java
@@ -99,7 +99,7 @@
         @Override
         protected void after() {
             if (httpclient != null) {
-                httpclient.shutdown(CloseMode.GRACEFUL);
+                httpclient.close(CloseMode.GRACEFUL);
                 httpclient = null;
             }
         }
diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/AbstractIntegrationTestBase.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/AbstractIntegrationTestBase.java
index 03d9a4d..d13a608 100644
--- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/AbstractIntegrationTestBase.java
+++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/AbstractIntegrationTestBase.java
@@ -63,7 +63,7 @@
         @Override
         protected void after() {
             if (httpclient != null) {
-                httpclient.shutdown(CloseMode.GRACEFUL);
+                httpclient.close(CloseMode.GRACEFUL);
                 httpclient = null;
             }
         }
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/AbstractHttpAsyncClientBase.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/AbstractHttpAsyncClientBase.java
index 916bd07..eb92d14 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/AbstractHttpAsyncClientBase.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/AbstractHttpAsyncClientBase.java
@@ -112,19 +112,23 @@
         ioReactor.initiateShutdown();
     }
 
+    void internalClose(final CloseMode closeMode) {
+    }
+
     @Override
-    public final void shutdown(final CloseMode closeMode) {
+    public final void close(final CloseMode closeMode) {
         if (log.isDebugEnabled()) {
             log.debug("Shutdown " + closeMode);
         }
         ioReactor.initiateShutdown();
         ioReactor.close(closeMode);
         executorService.shutdownNow();
+        internalClose(closeMode);
     }
 
     @Override
     public void close() {
-        shutdown(CloseMode.GRACEFUL);
+        close(CloseMode.GRACEFUL);
     }
 
 }
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/CloseableHttpAsyncClient.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/CloseableHttpAsyncClient.java
index b42f457..c80dbff 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/CloseableHttpAsyncClient.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/CloseableHttpAsyncClient.java
@@ -26,7 +26,6 @@
  */
 package org.apache.hc.client5.http.impl.async;
 
-import java.io.Closeable;
 import java.util.concurrent.Future;
 
 import org.apache.hc.client5.http.async.HttpAsyncClient;
@@ -45,17 +44,18 @@
 import org.apache.hc.core5.http.nio.AsyncResponseConsumer;
 import org.apache.hc.core5.http.protocol.HttpContext;
 import org.apache.hc.core5.io.CloseMode;
+import org.apache.hc.core5.io.ModalCloseable;
 import org.apache.hc.core5.reactor.IOReactorStatus;
 import org.apache.hc.core5.util.Args;
 import org.apache.hc.core5.util.TimeValue;
 
 /**
- * Base implementation of {@link HttpAsyncClient} that also implements {@link Closeable}.
+ * Base implementation of {@link HttpAsyncClient} that also implements {@link ModalCloseable}.
  *
  * @since 5.0
  */
 @Contract(threading = ThreadingBehavior.STATELESS)
-public abstract class CloseableHttpAsyncClient implements HttpAsyncClient, Closeable {
+public abstract class CloseableHttpAsyncClient implements HttpAsyncClient, ModalCloseable {
 
     public abstract void start();
 
@@ -65,7 +65,13 @@
 
     public abstract void initiateShutdown();
 
-    public abstract void shutdown(CloseMode closeMode);
+    /**
+     * @deprecated Use {@link #close(CloseMode)}
+     */
+    @Deprecated
+    public void shutdown(final CloseMode closeMode) {
+        close(closeMode);
+    }
 
     public final <T> Future<T> execute(
             final AsyncRequestProducer requestProducer,
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalAbstractHttpAsyncClient.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalAbstractHttpAsyncClient.java
index 58e56c0..35aedc6 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalAbstractHttpAsyncClient.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalAbstractHttpAsyncClient.java
@@ -30,6 +30,7 @@
 import java.io.IOException;
 import java.util.List;
 import java.util.Set;
+import java.util.concurrent.ConcurrentLinkedQueue;
 import java.util.concurrent.Future;
 import java.util.concurrent.ThreadFactory;
 import java.util.concurrent.atomic.AtomicBoolean;
@@ -64,6 +65,8 @@
 import org.apache.hc.core5.http.nio.HandlerFactory;
 import org.apache.hc.core5.http.nio.RequestChannel;
 import org.apache.hc.core5.http.protocol.HttpContext;
+import org.apache.hc.core5.io.CloseMode;
+import org.apache.hc.core5.io.ModalCloseable;
 import org.apache.hc.core5.reactor.DefaultConnectingIOReactor;
 
 abstract class InternalAbstractHttpAsyncClient extends AbstractHttpAsyncClientBase {
@@ -74,7 +77,7 @@
     private final CookieStore cookieStore;
     private final CredentialsProvider credentialsProvider;
     private final RequestConfig defaultConfig;
-    private final List<Closeable> closeables;
+    private final ConcurrentLinkedQueue<Closeable> closeables;
 
     InternalAbstractHttpAsyncClient(
             final DefaultConnectingIOReactor ioReactor,
@@ -94,18 +97,22 @@
         this.cookieStore = cookieStore;
         this.credentialsProvider = credentialsProvider;
         this.defaultConfig = defaultConfig;
-        this.closeables = closeables;
+        this.closeables = closeables != null ? new ConcurrentLinkedQueue<>(closeables) : null;
     }
 
     @Override
-    public void close() {
-        super.close();
-        if (closeables != null) {
-            for (final Closeable closeable: closeables) {
+    void internalClose(final CloseMode closeMode) {
+        if (this.closeables != null) {
+            Closeable closeable;
+            while ((closeable = this.closeables.poll()) != null) {
                 try {
-                    closeable.close();
+                    if (closeable instanceof ModalCloseable) {
+                        ((ModalCloseable) closeable).close(closeMode);
+                    } else {
+                        closeable.close();
+                    }
                 } catch (final IOException ex) {
-                    log.error(ex.getMessage(), ex);
+                    this.log.error(ex.getMessage(), ex);
                 }
             }
         }
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/classic/CloseableHttpClient.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/classic/CloseableHttpClient.java
index fb1d352..6495a88 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/classic/CloseableHttpClient.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/classic/CloseableHttpClient.java
@@ -27,7 +27,6 @@
 
 package org.apache.hc.client5.http.impl.classic;
 
-import java.io.Closeable;
 import java.io.IOException;
 import java.net.URI;
 import java.net.URISyntaxException;
@@ -44,17 +43,18 @@
 import org.apache.hc.core5.http.io.HttpClientResponseHandler;
 import org.apache.hc.core5.http.io.entity.EntityUtils;
 import org.apache.hc.core5.http.protocol.HttpContext;
+import org.apache.hc.core5.io.ModalCloseable;
 import org.apache.hc.core5.util.Args;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- * Base implementation of {@link HttpClient} that also implements {@link Closeable}.
+ * Base implementation of {@link HttpClient} that also implements {@link ModalCloseable}.
  *
  * @since 4.3
  */
 @Contract(threading = ThreadingBehavior.SAFE)
-public abstract class CloseableHttpClient implements HttpClient, Closeable {
+public abstract class CloseableHttpClient implements HttpClient, ModalCloseable {
 
     private final Logger log = LoggerFactory.getLogger(getClass());
 
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/classic/InternalHttpClient.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/classic/InternalHttpClient.java
index 88b3230..0240cc4 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/classic/InternalHttpClient.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/classic/InternalHttpClient.java
@@ -30,6 +30,7 @@
 import java.io.Closeable;
 import java.io.IOException;
 import java.util.List;
+import java.util.concurrent.ConcurrentLinkedQueue;
 
 import org.apache.hc.client5.http.ClientProtocolException;
 import org.apache.hc.client5.http.HttpRoute;
@@ -59,6 +60,8 @@
 import org.apache.hc.core5.http.impl.io.HttpRequestExecutor;
 import org.apache.hc.core5.http.protocol.BasicHttpContext;
 import org.apache.hc.core5.http.protocol.HttpContext;
+import org.apache.hc.core5.io.CloseMode;
+import org.apache.hc.core5.io.ModalCloseable;
 import org.apache.hc.core5.net.URIAuthority;
 import org.apache.hc.core5.util.Args;
 import org.slf4j.Logger;
@@ -88,7 +91,7 @@
     private final CookieStore cookieStore;
     private final CredentialsProvider credentialsProvider;
     private final RequestConfig defaultConfig;
-    private final List<Closeable> closeables;
+    private final ConcurrentLinkedQueue<Closeable> closeables;
 
     public InternalHttpClient(
             final HttpClientConnectionManager connManager,
@@ -111,7 +114,7 @@
         this.cookieStore = cookieStore;
         this.credentialsProvider = credentialsProvider;
         this.defaultConfig = defaultConfig;
-        this.closeables = closeables;
+        this.closeables = closeables != null ?  new ConcurrentLinkedQueue<>(closeables) : null;
     }
 
     private HttpRoute determineRoute(
@@ -186,10 +189,20 @@
 
     @Override
     public void close() {
+        close(CloseMode.GRACEFUL);
+    }
+
+    @Override
+    public void close(final CloseMode closeMode) {
         if (this.closeables != null) {
-            for (final Closeable closeable: this.closeables) {
+            Closeable closeable;
+            while ((closeable = this.closeables.poll()) != null) {
                 try {
-                    closeable.close();
+                    if (closeable instanceof ModalCloseable) {
+                        ((ModalCloseable) closeable).close(closeMode);
+                    } else {
+                        closeable.close();
+                    }
                 } catch (final IOException ex) {
                     this.log.error(ex.getMessage(), ex);
                 }
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/classic/MinimalHttpClient.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/classic/MinimalHttpClient.java
index e316c1d..5dfb662 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/classic/MinimalHttpClient.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/classic/MinimalHttpClient.java
@@ -186,4 +186,9 @@
         this.connManager.close();
     }
 
+    @Override
+    public void close(final CloseMode closeMode) {
+        this.connManager.close(closeMode);
+    }
+
 }
diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientAuthentication.java b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientAuthentication.java
index 08278f3..8925ace 100644
--- a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientAuthentication.java
+++ b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientAuthentication.java
@@ -83,7 +83,7 @@
         future.get();
 
         System.out.println("Shutting down");
-        httpclient.shutdown(CloseMode.GRACEFUL);
+        httpclient.close(CloseMode.GRACEFUL);
 
     }
 }
diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientConnectionEviction.java b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientConnectionEviction.java
index 8f9d2cd..543f185 100644
--- a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientConnectionEviction.java
+++ b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientConnectionEviction.java
@@ -121,7 +121,7 @@
         future2.get();
 
         System.out.println("Shutting down");
-        client.shutdown(CloseMode.GRACEFUL);
+        client.close(CloseMode.GRACEFUL);
     }
 
 }
diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientCustomSSL.java b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientCustomSSL.java
index 2f1bb92..8184adc 100644
--- a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientCustomSSL.java
+++ b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientCustomSSL.java
@@ -133,7 +133,7 @@
             future.get();
 
             System.out.println("Shutting down");
-            client.shutdown(CloseMode.GRACEFUL);
+            client.close(CloseMode.GRACEFUL);
         }
     }
 
diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientFullDuplexExchange.java b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientFullDuplexExchange.java
index 1481e01..53f869e 100644
--- a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientFullDuplexExchange.java
+++ b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientFullDuplexExchange.java
@@ -151,7 +151,7 @@
         latch.await(1, TimeUnit.MINUTES);
 
         System.out.println("Shutting down");
-        client.shutdown(CloseMode.GRACEFUL);
+        client.close(CloseMode.GRACEFUL);
     }
 
 }
diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientH2FullDuplexExchange.java b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientH2FullDuplexExchange.java
index f3ea5f5..4a7727e 100644
--- a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientH2FullDuplexExchange.java
+++ b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientH2FullDuplexExchange.java
@@ -147,7 +147,7 @@
         latch.await(1, TimeUnit.MINUTES);
 
         System.out.println("Shutting down");
-        client.shutdown(CloseMode.GRACEFUL);
+        client.close(CloseMode.GRACEFUL);
     }
 
 }
diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientH2Multiplexing.java b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientH2Multiplexing.java
index e10af5a..94c3a67 100644
--- a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientH2Multiplexing.java
+++ b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientH2Multiplexing.java
@@ -104,7 +104,7 @@
         }
 
         System.out.println("Shutting down");
-        client.shutdown(CloseMode.GRACEFUL);
+        client.close(CloseMode.GRACEFUL);
     }
 
 }
diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientH2ServerPush.java b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientH2ServerPush.java
index 12ec238..4a16dbc 100644
--- a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientH2ServerPush.java
+++ b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientH2ServerPush.java
@@ -155,7 +155,7 @@
         future.get();
 
         System.out.println("Shutting down");
-        client.shutdown(CloseMode.GRACEFUL);
+        client.close(CloseMode.GRACEFUL);
     }
 
 }
diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientHttp1Pipelining.java b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientHttp1Pipelining.java
index 9c3d377..0b1f3c7 100644
--- a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientHttp1Pipelining.java
+++ b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientHttp1Pipelining.java
@@ -103,7 +103,7 @@
         }
 
         System.out.println("Shutting down");
-        client.shutdown(CloseMode.GRACEFUL);
+        client.close(CloseMode.GRACEFUL);
     }
 
 }
diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientHttpExchange.java b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientHttpExchange.java
index 9d4c212..ff96d02 100644
--- a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientHttpExchange.java
+++ b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientHttpExchange.java
@@ -87,7 +87,7 @@
         }
 
         System.out.println("Shutting down");
-        client.shutdown(CloseMode.GRACEFUL);
+        client.close(CloseMode.GRACEFUL);
     }
 
 }
diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientHttpExchangeStreaming.java b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientHttpExchangeStreaming.java
index c7c884f..dc3e87b 100644
--- a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientHttpExchangeStreaming.java
+++ b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientHttpExchangeStreaming.java
@@ -110,7 +110,7 @@
         }
 
         System.out.println("Shutting down");
-        client.shutdown(CloseMode.GRACEFUL);
+        client.close(CloseMode.GRACEFUL);
     }
 
 }
diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientInterceptors.java b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientInterceptors.java
index e1a6d97..82b5ff2 100644
--- a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientInterceptors.java
+++ b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientInterceptors.java
@@ -150,7 +150,7 @@
         }
 
         System.out.println("Shutting down");
-        client.shutdown(CloseMode.GRACEFUL);
+        client.close(CloseMode.GRACEFUL);
     }
 
 }
diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientMessageTrailers.java b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientMessageTrailers.java
index db2b916..d9201ce 100644
--- a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientMessageTrailers.java
+++ b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientMessageTrailers.java
@@ -116,7 +116,7 @@
         future.get();
 
         System.out.println("Shutting down");
-        client.shutdown(CloseMode.GRACEFUL);
+        client.close(CloseMode.GRACEFUL);
     }
 
 }
diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientTlsAlpn.java b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientTlsAlpn.java
index 412307a..97baeec 100644
--- a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientTlsAlpn.java
+++ b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientTlsAlpn.java
@@ -115,7 +115,7 @@
             future.get();
 
             System.out.println("Shutting down");
-            client.shutdown(CloseMode.GRACEFUL);
+            client.close(CloseMode.GRACEFUL);
         }
     }
 
diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/ReactiveClientFullDuplexExchange.java b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/ReactiveClientFullDuplexExchange.java
index 9803e2c..9a787b9 100644
--- a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/ReactiveClientFullDuplexExchange.java
+++ b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/ReactiveClientFullDuplexExchange.java
@@ -111,6 +111,6 @@
         requestFuture.get(1, TimeUnit.MINUTES);
 
         System.out.println("Shutting down");
-        client.shutdown(CloseMode.GRACEFUL);
+        client.close(CloseMode.GRACEFUL);
     }
 }