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      * Assigns {@link HttpConnectionFactory} instance.
106      */
107     public final PoolingHttpClientConnectionManagerBuilder setConnectionFactory(
108             final HttpConnectionFactory<ManagedHttpClientConnection> connectionFactory) {
109         this.connectionFactory = connectionFactory;
110         return this;
111     }
112 
113     /**
114      * Assigns {@link org.apache.hc.client5.http.socket.LayeredConnectionSocketFactory} instance.
115      *
116      * @deprecated Use {@link #setTlsSocketStrategy(TlsSocketStrategy)}
117      */
118     @Deprecated
119     public final PoolingHttpClientConnectionManagerBuilder setSSLSocketFactory(
120             final org.apache.hc.client5.http.socket.LayeredConnectionSocketFactory sslSocketFactory) {
121         this.tlsSocketStrategy = (socket, target, port, attachment, context) ->
122                 (SSLSocket) sslSocketFactory.createLayeredSocket(socket, target, port, context);
123         return this;
124     }
125 
126     /**
127      * Assigns {@link TlsSocketStrategy} instance.
128      */
129     public final PoolingHttpClientConnectionManagerBuilder setTlsSocketStrategy(final TlsSocketStrategy tlsSocketStrategy) {
130         this.tlsSocketStrategy = tlsSocketStrategy;
131         return this;
132     }
133 
134     /**
135      * Assigns {@link DnsResolver} instance.
136      */
137     public final PoolingHttpClientConnectionManagerBuilder setDnsResolver(final DnsResolver dnsResolver) {
138         this.dnsResolver = dnsResolver;
139         return this;
140     }
141 
142     /**
143      * Assigns {@link SchemePortResolver} instance.
144      */
145     public final PoolingHttpClientConnectionManagerBuilder setSchemePortResolver(final SchemePortResolver schemePortResolver) {
146         this.schemePortResolver = schemePortResolver;
147         return this;
148     }
149 
150     /**
151      * Assigns {@link PoolConcurrencyPolicy} value.
152      */
153     public final PoolingHttpClientConnectionManagerBuilder setPoolConcurrencyPolicy(final PoolConcurrencyPolicy poolConcurrencyPolicy) {
154         this.poolConcurrencyPolicy = poolConcurrencyPolicy;
155         return this;
156     }
157 
158     /**
159      * Assigns {@link PoolReusePolicy} value.
160      */
161     public final PoolingHttpClientConnectionManagerBuilder setConnPoolPolicy(final PoolReusePolicy poolReusePolicy) {
162         this.poolReusePolicy = poolReusePolicy;
163         return this;
164     }
165 
166     /**
167      * Assigns maximum total connection value.
168      */
169     public final PoolingHttpClientConnectionManagerBuilder setMaxConnTotal(final int maxConnTotal) {
170         this.maxConnTotal = maxConnTotal;
171         return this;
172     }
173 
174     /**
175      * Assigns maximum connection per route value.
176      */
177     public final PoolingHttpClientConnectionManagerBuilder setMaxConnPerRoute(final int maxConnPerRoute) {
178         this.maxConnPerRoute = maxConnPerRoute;
179         return this;
180     }
181 
182     /**
183      * Assigns the same {@link SocketConfig} for all routes.
184      */
185     public final PoolingHttpClientConnectionManagerBuilder setDefaultSocketConfig(final SocketConfig config) {
186         this.socketConfigResolver = (route) -> config;
187         return this;
188     }
189 
190     /**
191      * Assigns {@link Resolver} of {@link SocketConfig} on a per route basis.
192      *
193      * @since 5.2
194      */
195     public final PoolingHttpClientConnectionManagerBuilder setSocketConfigResolver(
196             final Resolver<HttpRoute, SocketConfig> socketConfigResolver) {
197         this.socketConfigResolver = socketConfigResolver;
198         return this;
199     }
200 
201     /**
202      * Assigns the same {@link ConnectionConfig} for all routes.
203      *
204      * @since 5.2
205      */
206     public final PoolingHttpClientConnectionManagerBuilder setDefaultConnectionConfig(final ConnectionConfig config) {
207         this.connectionConfigResolver = (route) -> config;
208         return this;
209     }
210 
211     /**
212      * Assigns {@link Resolver} of {@link ConnectionConfig} on a per route basis.
213      *
214      * @since 5.2
215      */
216     public final PoolingHttpClientConnectionManagerBuilder setConnectionConfigResolver(
217             final Resolver<HttpRoute, ConnectionConfig> connectionConfigResolver) {
218         this.connectionConfigResolver = connectionConfigResolver;
219         return this;
220     }
221 
222     /**
223      * Assigns the same {@link TlsConfig} for all hosts.
224      *
225      * @since 5.2
226      */
227     public final PoolingHttpClientConnectionManagerBuilder setDefaultTlsConfig(final TlsConfig config) {
228         this.tlsConfigResolver = (host) -> config;
229         return this;
230     }
231 
232     /**
233      * Assigns {@link Resolver} of {@link TlsConfig} on a per host basis.
234      *
235      * @since 5.2
236      */
237     public final PoolingHttpClientConnectionManagerBuilder setTlsConfigResolver(
238             final Resolver<HttpHost, TlsConfig> tlsConfigResolver) {
239         this.tlsConfigResolver = tlsConfigResolver;
240         return this;
241     }
242 
243     /**
244      * Sets maximum time to live for persistent connections
245      *
246      * @deprecated Use {@link #setDefaultConnectionConfig(ConnectionConfig)}.
247      */
248     @Deprecated
249     public final PoolingHttpClientConnectionManagerBuilder setConnectionTimeToLive(final TimeValue timeToLive) {
250         setDefaultConnectionConfig(ConnectionConfig.custom()
251                 .setTimeToLive(timeToLive)
252                 .build());
253         return this;
254     }
255 
256     /**
257      * Sets period after inactivity after which persistent
258      * connections must be checked to ensure they are still valid.
259      *
260      * @deprecated Use {@link #setDefaultConnectionConfig(ConnectionConfig)}.
261      */
262     @Deprecated
263     public final PoolingHttpClientConnectionManagerBuilder setValidateAfterInactivity(final TimeValue validateAfterInactivity) {
264         setDefaultConnectionConfig(ConnectionConfig.custom()
265                 .setValidateAfterInactivity(validateAfterInactivity)
266                 .build());
267         return this;
268     }
269 
270     /**
271      * Use system properties when creating and configuring default
272      * implementations.
273      */
274     public final PoolingHttpClientConnectionManagerBuilder useSystemProperties() {
275         this.systemProperties = true;
276         return this;
277     }
278 
279     @Internal
280     protected HttpClientConnectionOperator createConnectionOperator(
281             final SchemePortResolver schemePortResolver,
282             final DnsResolver dnsResolver,
283             final TlsSocketStrategy tlsSocketStrategy) {
284         return new DefaultHttpClientConnectionOperator(schemePortResolver, dnsResolver,
285                 RegistryBuilder.<TlsSocketStrategy>create()
286                         .register(URIScheme.HTTPS.id, tlsSocketStrategy)
287                         .build());
288     }
289 
290     public PoolingHttpClientConnectionManager build() {
291         final TlsSocketStrategy tlsSocketStrategyCopy;
292         if (tlsSocketStrategy != null) {
293             tlsSocketStrategyCopy = tlsSocketStrategy;
294         } else {
295             if (systemProperties) {
296                 tlsSocketStrategyCopy = DefaultClientTlsStrategy.createSystemDefault();
297             } else {
298                 tlsSocketStrategyCopy = DefaultClientTlsStrategy.createDefault();
299             }
300         }
301 
302         final PoolingHttpClientConnectionManager poolingmgr = new PoolingHttpClientConnectionManager(
303                 createConnectionOperator(schemePortResolver, dnsResolver, tlsSocketStrategyCopy),
304                 poolConcurrencyPolicy,
305                 poolReusePolicy,
306                 null,
307                 connectionFactory);
308         poolingmgr.setSocketConfigResolver(socketConfigResolver);
309         poolingmgr.setConnectionConfigResolver(connectionConfigResolver);
310         poolingmgr.setTlsConfigResolver(tlsConfigResolver);
311         if (maxConnTotal > 0) {
312             poolingmgr.setMaxTotal(maxConnTotal);
313         }
314         if (maxConnPerRoute > 0) {
315             poolingmgr.setDefaultMaxPerRoute(maxConnPerRoute);
316         }
317         return poolingmgr;
318     }
319 
320 }