|
17 | 17 | import java.io.InputStream; |
18 | 18 | import java.io.PrintWriter; |
19 | 19 | import java.io.StringWriter; |
| 20 | +import java.lang.reflect.Field; |
20 | 21 | import java.net.InetSocketAddress; |
21 | 22 | import java.net.Proxy; |
22 | 23 | import java.net.Socket; |
@@ -105,9 +106,11 @@ public class HttpUtil { |
105 | 106 | new ConcurrentHashMap<>(); |
106 | 107 |
|
107 | 108 | /** Handle on the static connection manager, to gather statistics mainly */ |
| 109 | + // TODO SNOW-1943242 consider making it HttpClientSettingsKey bound |
108 | 110 | private static PoolingHttpClientConnectionManager connectionManager = null; |
109 | 111 |
|
110 | 112 | /** default request configuration, to be copied on individual requests. */ |
| 113 | + // TODO SNOW-1943242 consider making it HttpClientSettingsKey bound |
111 | 114 | private static RequestConfig DefaultRequestConfig = null; |
112 | 115 |
|
113 | 116 | private static boolean socksProxyDisabled = false; |
@@ -350,6 +353,8 @@ public static CloseableHttpClient buildHttpClient( |
350 | 353 | .build(); |
351 | 354 |
|
352 | 355 | // Build a connection manager with enough connections |
| 356 | + // TODO SNOW-1943242 consider not creating connection manager if already exists and/or |
| 357 | + // synchronization |
353 | 358 | connectionManager = |
354 | 359 | new PoolingHttpClientConnectionManager( |
355 | 360 | registry, null, null, null, timeToLive, TimeUnit.SECONDS); |
@@ -497,8 +502,33 @@ public static CloseableHttpClient initHttpClientWithoutDecompression( |
497 | 502 | */ |
498 | 503 | public static CloseableHttpClient initHttpClient(HttpClientSettingsKey key, File ocspCacheFile) { |
499 | 504 | updateRoutePlanner(key); |
500 | | - return httpClient.computeIfAbsent( |
501 | | - key, k -> buildHttpClient(key, ocspCacheFile, key.getGzipDisabled())); |
| 505 | + CloseableHttpClient closeableHttpClient = |
| 506 | + httpClient.computeIfAbsent( |
| 507 | + key, k -> buildHttpClient(key, ocspCacheFile, key.getGzipDisabled())); |
| 508 | + if (detectClosedConnectionManager(closeableHttpClient)) { |
| 509 | + // TODO SNOW-1943242 consider dropping connectionManager |
| 510 | + httpClient.remove(key); |
| 511 | + return httpClient.computeIfAbsent( |
| 512 | + key, k -> buildHttpClient(key, ocspCacheFile, key.getGzipDisabled())); |
| 513 | + } |
| 514 | + return closeableHttpClient; |
| 515 | + } |
| 516 | + |
| 517 | + private static boolean detectClosedConnectionManager(CloseableHttpClient closeableHttpClient) |
| 518 | + throws RuntimeException { |
| 519 | + // There is no simple way to detect is the connection manager is closed... |
| 520 | + try { |
| 521 | + Field connManagerField = closeableHttpClient.getClass().getDeclaredField("connManager"); |
| 522 | + connManagerField.setAccessible(true); |
| 523 | + PoolingHttpClientConnectionManager connectionManager = |
| 524 | + (PoolingHttpClientConnectionManager) connManagerField.get(closeableHttpClient); |
| 525 | + Field isShutdownField = connectionManager.getClass().getDeclaredField("isShutDown"); |
| 526 | + isShutdownField.setAccessible(true); |
| 527 | + AtomicBoolean isShutdown = (AtomicBoolean) isShutdownField.get(connectionManager); |
| 528 | + return isShutdown.get(); |
| 529 | + } catch (NoSuchFieldException | IllegalAccessException e) { |
| 530 | + throw new RuntimeException(e); |
| 531 | + } |
502 | 532 | } |
503 | 533 |
|
504 | 534 | /** |
|
0 commit comments