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