View Javadoc
1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
25   *
26   */
27  
28  package org.apache.hc.client5.http.impl.nio;
29  
30  import org.apache.hc.client5.http.DnsResolver;
31  import org.apache.hc.client5.http.HttpRoute;
32  import org.apache.hc.client5.http.SchemePortResolver;
33  import org.apache.hc.client5.http.config.ConnectionConfig;
34  import org.apache.hc.client5.http.config.TlsConfig;
35  import org.apache.hc.client5.http.nio.AsyncClientConnectionOperator;
36  import org.apache.hc.client5.http.ssl.ConscryptClientTlsStrategy;
37  import org.apache.hc.client5.http.ssl.DefaultClientTlsStrategy;
38  import org.apache.hc.core5.annotation.Internal;
39  import org.apache.hc.core5.function.Resolver;
40  import org.apache.hc.core5.http.HttpHost;
41  import org.apache.hc.core5.http.URIScheme;
42  import org.apache.hc.core5.http.config.RegistryBuilder;
43  import org.apache.hc.core5.http.nio.ssl.TlsStrategy;
44  import org.apache.hc.core5.pool.PoolConcurrencyPolicy;
45  import org.apache.hc.core5.pool.PoolReusePolicy;
46  import org.apache.hc.core5.util.ReflectionUtils;
47  import org.apache.hc.core5.util.TimeValue;
48  
49  /**
50   * Builder for {@link PoolingAsyncClientConnectionManager} instances.
51   * <p>
52   * When a particular component is not explicitly set this class will
53   * use its default implementation. System properties will be taken
54   * into account when configuring the default implementations when
55   * {@link #useSystemProperties()} method is called prior to calling
56   * {@link #build()}.
57   * </p>
58   * <ul>
59   *  <li>ssl.TrustManagerFactory.algorithm</li>
60   *  <li>javax.net.ssl.trustStoreType</li>
61   *  <li>javax.net.ssl.trustStore</li>
62   *  <li>javax.net.ssl.trustStoreProvider</li>
63   *  <li>javax.net.ssl.trustStorePassword</li>
64   *  <li>ssl.KeyManagerFactory.algorithm</li>
65   *  <li>javax.net.ssl.keyStoreType</li>
66   *  <li>javax.net.ssl.keyStore</li>
67   *  <li>javax.net.ssl.keyStoreProvider</li>
68   *  <li>javax.net.ssl.keyStorePassword</li>
69   *  <li>https.protocols</li>
70   *  <li>https.cipherSuites</li>
71   * </ul>
72   *
73   * @since 5.0
74   */
75  public class PoolingAsyncClientConnectionManagerBuilder {
76  
77      private TlsStrategy tlsStrategy;
78      private SchemePortResolver schemePortResolver;
79      private DnsResolver dnsResolver;
80      private PoolConcurrencyPolicy poolConcurrencyPolicy;
81      private PoolReusePolicy poolReusePolicy;
82  
83      private boolean systemProperties;
84  
85      private int maxConnTotal;
86      private int maxConnPerRoute;
87  
88      private Resolver<HttpRoute, ConnectionConfig> connectionConfigResolver;
89      private Resolver<HttpHost, TlsConfig> tlsConfigResolver;
90  
91      public static PoolingAsyncClientConnectionManagerBuilder create() {
92          return new PoolingAsyncClientConnectionManagerBuilder();
93      }
94  
95      @Internal
96      protected PoolingAsyncClientConnectionManagerBuilder() {
97          super();
98      }
99  
100     /**
101      * Assigns {@link TlsStrategy} instance for TLS connections.
102      */
103     public final PoolingAsyncClientConnectionManagerBuilder setTlsStrategy(
104             final TlsStrategy tlsStrategy) {
105         this.tlsStrategy = tlsStrategy;
106         return this;
107     }
108 
109     /**
110      * Assigns {@link DnsResolver} instance.
111      */
112     public final PoolingAsyncClientConnectionManagerBuilder setDnsResolver(final DnsResolver dnsResolver) {
113         this.dnsResolver = dnsResolver;
114         return this;
115     }
116 
117     /**
118      * Assigns {@link SchemePortResolver} instance.
119      */
120     public final PoolingAsyncClientConnectionManagerBuilder setSchemePortResolver(final SchemePortResolver schemePortResolver) {
121         this.schemePortResolver = schemePortResolver;
122         return this;
123     }
124 
125     /**
126      * Assigns {@link PoolConcurrencyPolicy} value.
127      */
128     public final PoolingAsyncClientConnectionManagerBuilder setPoolConcurrencyPolicy(final PoolConcurrencyPolicy poolConcurrencyPolicy) {
129         this.poolConcurrencyPolicy = poolConcurrencyPolicy;
130         return this;
131     }
132 
133     /**
134      * Assigns {@link PoolReusePolicy} value.
135      */
136     public final PoolingAsyncClientConnectionManagerBuilder setConnPoolPolicy(final PoolReusePolicy poolReusePolicy) {
137         this.poolReusePolicy = poolReusePolicy;
138         return this;
139     }
140 
141     /**
142      * Assigns maximum total connection value.
143      */
144     public final PoolingAsyncClientConnectionManagerBuilder setMaxConnTotal(final int maxConnTotal) {
145         this.maxConnTotal = maxConnTotal;
146         return this;
147     }
148 
149     /**
150      * Assigns maximum connection per route value.
151      */
152     public final PoolingAsyncClientConnectionManagerBuilder setMaxConnPerRoute(final int maxConnPerRoute) {
153         this.maxConnPerRoute = maxConnPerRoute;
154         return this;
155     }
156 
157     /**
158      * Assigns the same {@link ConnectionConfig} for all routes.
159      *
160      * @since 5.2
161      */
162     public final PoolingAsyncClientConnectionManagerBuilder setDefaultConnectionConfig(final ConnectionConfig config) {
163         this.connectionConfigResolver = (route) -> config;
164         return this;
165     }
166 
167     /**
168      * Assigns {@link Resolver} of {@link ConnectionConfig} on a per route basis.
169      *
170      * @since 5.2
171      */
172     public final PoolingAsyncClientConnectionManagerBuilder setConnectionConfigResolver(
173             final Resolver<HttpRoute, ConnectionConfig> connectionConfigResolver) {
174         this.connectionConfigResolver = connectionConfigResolver;
175         return this;
176     }
177 
178     /**
179      * Assigns the same {@link TlsConfig} for all hosts.
180      *
181      * @since 5.2
182      */
183     public final PoolingAsyncClientConnectionManagerBuilder setDefaultTlsConfig(final TlsConfig config) {
184         this.tlsConfigResolver = (host) -> config;
185         return this;
186     }
187 
188     /**
189      * Assigns {@link Resolver} of {@link TlsConfig} on a per host basis.
190      *
191      * @since 5.2
192      */
193     public final PoolingAsyncClientConnectionManagerBuilder setTlsConfigResolver(
194             final Resolver<HttpHost, TlsConfig> tlsConfigResolver) {
195         this.tlsConfigResolver = tlsConfigResolver;
196         return this;
197     }
198 
199     /**
200      * Sets maximum time to live for persistent connections
201      *
202      * @deprecated Use {@link #setDefaultConnectionConfig(ConnectionConfig)}
203      */
204     @Deprecated
205     public final PoolingAsyncClientConnectionManagerBuilder setConnectionTimeToLive(final TimeValue timeToLive) {
206         setDefaultConnectionConfig(ConnectionConfig.custom()
207                 .setTimeToLive(timeToLive)
208                 .build());
209         return this;
210     }
211 
212     /**
213      * Sets period after inactivity after which persistent
214      * connections must be checked to ensure they are still valid.
215      *
216      * @deprecated Use {@link #setConnectionConfigResolver(Resolver)}.
217      */
218     @Deprecated
219     public final PoolingAsyncClientConnectionManagerBuilder setValidateAfterInactivity(final TimeValue validateAfterInactivity) {
220         setDefaultConnectionConfig(ConnectionConfig.custom()
221                 .setValidateAfterInactivity(validateAfterInactivity)
222                 .build());
223         return this;
224     }
225 
226     /**
227      * Use system properties when creating and configuring default
228      * implementations.
229      */
230     public final PoolingAsyncClientConnectionManagerBuilder useSystemProperties() {
231         this.systemProperties = true;
232         return this;
233     }
234 
235     @Internal
236     protected AsyncClientConnectionOperator createConnectionOperator(
237             final TlsStrategy tlsStrategy,
238             final SchemePortResolver schemePortResolver,
239             final DnsResolver dnsResolver) {
240         return new DefaultAsyncClientConnectionOperator(
241                 RegistryBuilder.<TlsStrategy>create()
242                         .register(URIScheme.HTTPS.getId(), tlsStrategy)
243                         .build(),
244                 schemePortResolver,
245                 dnsResolver);
246     }
247 
248     public PoolingAsyncClientConnectionManager build() {
249         final TlsStrategy tlsStrategyCopy;
250         if (tlsStrategy != null) {
251             tlsStrategyCopy = tlsStrategy;
252         } else {
253             if (ReflectionUtils.determineJRELevel() <= 8 && ConscryptClientTlsStrategy.isSupported()) {
254                 if (systemProperties) {
255                     tlsStrategyCopy = ConscryptClientTlsStrategy.getSystemDefault();
256                 } else {
257                     tlsStrategyCopy = ConscryptClientTlsStrategy.getDefault();
258                 }
259             } else {
260                 if (systemProperties) {
261                     tlsStrategyCopy = DefaultClientTlsStrategy.createSystemDefault();
262                 } else {
263                     tlsStrategyCopy = DefaultClientTlsStrategy.createDefault();
264                 }
265             }
266         }
267         final PoolingAsyncClientConnectionManager poolingmgr = new PoolingAsyncClientConnectionManager(
268                 createConnectionOperator(tlsStrategyCopy, schemePortResolver, dnsResolver),
269                 poolConcurrencyPolicy,
270                 poolReusePolicy,
271                 null);
272         poolingmgr.setConnectionConfigResolver(connectionConfigResolver);
273         poolingmgr.setTlsConfigResolver(tlsConfigResolver);
274         if (maxConnTotal > 0) {
275             poolingmgr.setMaxTotal(maxConnTotal);
276         }
277         if (maxConnPerRoute > 0) {
278             poolingmgr.setDefaultMaxPerRoute(maxConnPerRoute);
279         }
280         return poolingmgr;
281     }
282 
283 }