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.Experimental;
39  import org.apache.hc.core5.annotation.Internal;
40  import org.apache.hc.core5.function.Resolver;
41  import org.apache.hc.core5.http.HttpHost;
42  import org.apache.hc.core5.http.URIScheme;
43  import org.apache.hc.core5.http.config.RegistryBuilder;
44  import org.apache.hc.core5.http.nio.ssl.TlsStrategy;
45  import org.apache.hc.core5.pool.PoolConcurrencyPolicy;
46  import org.apache.hc.core5.pool.PoolReusePolicy;
47  import org.apache.hc.core5.util.ReflectionUtils;
48  import org.apache.hc.core5.util.TimeValue;
49  
50  /**
51   * Builder for {@link PoolingAsyncClientConnectionManager} instances.
52   * <p>
53   * When a particular component is not explicitly set this class will
54   * use its default implementation. System properties will be taken
55   * into account when configuring the default implementations when
56   * {@link #useSystemProperties()} method is called prior to calling
57   * {@link #build()}.
58   * </p>
59   * <ul>
60   *  <li>ssl.TrustManagerFactory.algorithm</li>
61   *  <li>javax.net.ssl.trustStoreType</li>
62   *  <li>javax.net.ssl.trustStore</li>
63   *  <li>javax.net.ssl.trustStoreProvider</li>
64   *  <li>javax.net.ssl.trustStorePassword</li>
65   *  <li>ssl.KeyManagerFactory.algorithm</li>
66   *  <li>javax.net.ssl.keyStoreType</li>
67   *  <li>javax.net.ssl.keyStore</li>
68   *  <li>javax.net.ssl.keyStoreProvider</li>
69   *  <li>javax.net.ssl.keyStorePassword</li>
70   *  <li>https.protocols</li>
71   *  <li>https.cipherSuites</li>
72   * </ul>
73   *
74   * @since 5.0
75   */
76  public class PoolingAsyncClientConnectionManagerBuilder {
77  
78      private TlsStrategy tlsStrategy;
79      private SchemePortResolver schemePortResolver;
80      private DnsResolver dnsResolver;
81      private PoolConcurrencyPolicy poolConcurrencyPolicy;
82      private PoolReusePolicy poolReusePolicy;
83  
84      private boolean systemProperties;
85  
86      private int maxConnTotal;
87      private int maxConnPerRoute;
88  
89      private Resolver<HttpRoute, ConnectionConfig> connectionConfigResolver;
90      private Resolver<HttpHost, TlsConfig> tlsConfigResolver;
91      private boolean messageMultiplexing;
92  
93      public static PoolingAsyncClientConnectionManagerBuilder create() {
94          return new PoolingAsyncClientConnectionManagerBuilder();
95      }
96  
97      @Internal
98      protected PoolingAsyncClientConnectionManagerBuilder() {
99          super();
100     }
101 
102     /**
103      * Sets {@link TlsStrategy} instance for TLS connections.
104      *
105      * @return this instance.
106      */
107     public final PoolingAsyncClientConnectionManagerBuilder setTlsStrategy(
108             final TlsStrategy tlsStrategy) {
109         this.tlsStrategy = tlsStrategy;
110         return this;
111     }
112 
113     /**
114      * Sets {@link DnsResolver} instance.
115      *
116      * @return this instance.
117      */
118     public final PoolingAsyncClientConnectionManagerBuilder setDnsResolver(final DnsResolver dnsResolver) {
119         this.dnsResolver = dnsResolver;
120         return this;
121     }
122 
123     /**
124      * Sets {@link SchemePortResolver} instance.
125      *
126      * @return this instance.
127      */
128     public final PoolingAsyncClientConnectionManagerBuilder setSchemePortResolver(final SchemePortResolver schemePortResolver) {
129         this.schemePortResolver = schemePortResolver;
130         return this;
131     }
132 
133     /**
134      * Sets {@link PoolConcurrencyPolicy} value.
135      *
136      * @return this instance.
137      */
138     public final PoolingAsyncClientConnectionManagerBuilder setPoolConcurrencyPolicy(final PoolConcurrencyPolicy poolConcurrencyPolicy) {
139         this.poolConcurrencyPolicy = poolConcurrencyPolicy;
140         return this;
141     }
142 
143     /**
144      * Sets {@link PoolReusePolicy} value.
145      *
146      * @return this instance.
147      */
148     public final PoolingAsyncClientConnectionManagerBuilder setConnPoolPolicy(final PoolReusePolicy poolReusePolicy) {
149         this.poolReusePolicy = poolReusePolicy;
150         return this;
151     }
152 
153     /**
154      * Sets maximum total connection value.
155      *
156      * @return this instance.
157      */
158     public final PoolingAsyncClientConnectionManagerBuilder setMaxConnTotal(final int maxConnTotal) {
159         this.maxConnTotal = maxConnTotal;
160         return this;
161     }
162 
163     /**
164      * Sets maximum connection per route value.
165      *
166      * @return this instance.
167      */
168     public final PoolingAsyncClientConnectionManagerBuilder setMaxConnPerRoute(final int maxConnPerRoute) {
169         this.maxConnPerRoute = maxConnPerRoute;
170         return this;
171     }
172 
173     /**
174      * Sets the same {@link ConnectionConfig} for all routes.
175      *
176      * @return this instance.
177      * @since 5.2
178      */
179     public final PoolingAsyncClientConnectionManagerBuilder setDefaultConnectionConfig(final ConnectionConfig config) {
180         this.connectionConfigResolver = route -> config;
181         return this;
182     }
183 
184     /**
185      * Sets {@link Resolver} of {@link ConnectionConfig} on a per route basis.
186      *
187      * @return this instance.
188      * @since 5.2
189      */
190     public final PoolingAsyncClientConnectionManagerBuilder setConnectionConfigResolver(
191             final Resolver<HttpRoute, ConnectionConfig> connectionConfigResolver) {
192         this.connectionConfigResolver = connectionConfigResolver;
193         return this;
194     }
195 
196     /**
197      * Sets the same {@link TlsConfig} for all hosts.
198      *
199      * @return this instance.
200      * @since 5.2
201      */
202     public final PoolingAsyncClientConnectionManagerBuilder setDefaultTlsConfig(final TlsConfig config) {
203         this.tlsConfigResolver = host -> config;
204         return this;
205     }
206 
207     /**
208      * Sets {@link Resolver} of {@link TlsConfig} on a per host basis.
209      *
210      * @return this instance.
211      * @since 5.2
212      */
213     public final PoolingAsyncClientConnectionManagerBuilder setTlsConfigResolver(
214             final Resolver<HttpHost, TlsConfig> tlsConfigResolver) {
215         this.tlsConfigResolver = tlsConfigResolver;
216         return this;
217     }
218 
219     /**
220      * Sets maximum time to live for persistent connections
221      *
222      * @return this instance.
223      * @deprecated Use {@link #setDefaultConnectionConfig(ConnectionConfig)}
224      */
225     @Deprecated
226     public final PoolingAsyncClientConnectionManagerBuilder setConnectionTimeToLive(final TimeValue timeToLive) {
227         setDefaultConnectionConfig(ConnectionConfig.custom()
228                 .setTimeToLive(timeToLive)
229                 .build());
230         return this;
231     }
232 
233     /**
234      * Sets period after inactivity after which persistent
235      * connections must be checked to ensure they are still valid.
236      *
237      * @return this instance.
238      * @deprecated Use {@link #setConnectionConfigResolver(Resolver)}.
239      */
240     @Deprecated
241     public final PoolingAsyncClientConnectionManagerBuilder setValidateAfterInactivity(final TimeValue validateAfterInactivity) {
242         setDefaultConnectionConfig(ConnectionConfig.custom()
243                 .setValidateAfterInactivity(validateAfterInactivity)
244                 .build());
245         return this;
246     }
247 
248     /**
249      * Use system properties when creating and configuring default
250      * implementations.
251      *
252      * @return this instance.
253      */
254     public final PoolingAsyncClientConnectionManagerBuilder useSystemProperties() {
255         this.systemProperties = true;
256         return this;
257     }
258 
259     /**
260      * Use experimental connections pool implementation that acts as a caching facade
261      * in front of a standard connection pool and shares already leased connections
262      * to multiplex message exchanges over active HTTP/2 connections.
263      *<p>
264      * Please note this flag has no effect on HTTP/1.1 and HTTP/1.0 connections.
265      *<p>
266      * This feature is considered experimenal
267      *
268      * @since 5.5
269      * @return this instance.
270      */
271     @Experimental
272     public final PoolingAsyncClientConnectionManagerBuilder setMessageMultiplexing(final boolean messageMultiplexing) {
273         this.messageMultiplexing = messageMultiplexing;
274         return this;
275     }
276 
277     @Internal
278     protected AsyncClientConnectionOperator createConnectionOperator(
279             final TlsStrategy tlsStrategy,
280             final SchemePortResolver schemePortResolver,
281             final DnsResolver dnsResolver) {
282         return new DefaultAsyncClientConnectionOperator(
283                 RegistryBuilder.<TlsStrategy>create()
284                         .register(URIScheme.HTTPS.getId(), tlsStrategy)
285                         .build(),
286                 schemePortResolver,
287                 dnsResolver);
288     }
289 
290     public PoolingAsyncClientConnectionManager build() {
291         final TlsStrategy tlsStrategyCopy;
292         if (tlsStrategy != null) {
293             tlsStrategyCopy = tlsStrategy;
294         } else {
295             if (ReflectionUtils.determineJRELevel() <= 8 && ConscryptClientTlsStrategy.isSupported()) {
296                 if (systemProperties) {
297                     tlsStrategyCopy = ConscryptClientTlsStrategy.getSystemDefault();
298                 } else {
299                     tlsStrategyCopy = ConscryptClientTlsStrategy.getDefault();
300                 }
301             } else {
302                 if (systemProperties) {
303                     tlsStrategyCopy = DefaultClientTlsStrategy.createSystemDefault();
304                 } else {
305                     tlsStrategyCopy = DefaultClientTlsStrategy.createDefault();
306                 }
307             }
308         }
309         final PoolingAsyncClientConnectionManager poolingmgr = new PoolingAsyncClientConnectionManager(
310                 createConnectionOperator(tlsStrategyCopy, schemePortResolver, dnsResolver),
311                 poolConcurrencyPolicy,
312                 poolReusePolicy,
313                 null,
314                 messageMultiplexing);
315         poolingmgr.setConnectionConfigResolver(connectionConfigResolver);
316         poolingmgr.setTlsConfigResolver(tlsConfigResolver);
317         if (maxConnTotal > 0) {
318             poolingmgr.setMaxTotal(maxConnTotal);
319         }
320         if (maxConnPerRoute > 0) {
321             poolingmgr.setDefaultMaxPerRoute(maxConnPerRoute);
322         }
323         return poolingmgr;
324     }
325 
326 }