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.http.impl.client;
29  
30  import java.io.Closeable;
31  import java.net.ProxySelector;
32  import java.util.ArrayList;
33  import java.util.Collection;
34  import java.util.LinkedList;
35  import java.util.List;
36  
37  import javax.net.ssl.SSLContext;
38  import javax.net.ssl.SSLSocketFactory;
39  
40  import org.apache.http.ConnectionReuseStrategy;
41  import org.apache.http.Header;
42  import org.apache.http.HttpHost;
43  import org.apache.http.HttpRequestInterceptor;
44  import org.apache.http.HttpResponseInterceptor;
45  import org.apache.http.annotation.NotThreadSafe;
46  import org.apache.http.auth.AuthSchemeProvider;
47  import org.apache.http.client.AuthenticationStrategy;
48  import org.apache.http.client.BackoffManager;
49  import org.apache.http.client.ConnectionBackoffStrategy;
50  import org.apache.http.client.CookieStore;
51  import org.apache.http.client.CredentialsProvider;
52  import org.apache.http.client.HttpRequestRetryHandler;
53  import org.apache.http.client.RedirectStrategy;
54  import org.apache.http.client.ServiceUnavailableRetryStrategy;
55  import org.apache.http.client.UserTokenHandler;
56  import org.apache.http.client.config.AuthSchemes;
57  import org.apache.http.client.config.CookieSpecs;
58  import org.apache.http.client.config.RequestConfig;
59  import org.apache.http.client.protocol.RequestAcceptEncoding;
60  import org.apache.http.client.protocol.RequestAddCookies;
61  import org.apache.http.client.protocol.RequestAuthCache;
62  import org.apache.http.client.protocol.RequestClientConnControl;
63  import org.apache.http.client.protocol.RequestDefaultHeaders;
64  import org.apache.http.client.protocol.RequestExpectContinue;
65  import org.apache.http.client.protocol.ResponseContentEncoding;
66  import org.apache.http.client.protocol.ResponseProcessCookies;
67  import org.apache.http.config.ConnectionConfig;
68  import org.apache.http.config.Lookup;
69  import org.apache.http.config.RegistryBuilder;
70  import org.apache.http.config.SocketConfig;
71  import org.apache.http.conn.ConnectionKeepAliveStrategy;
72  import org.apache.http.conn.HttpClientConnectionManager;
73  import org.apache.http.conn.SchemePortResolver;
74  import org.apache.http.conn.routing.HttpRoutePlanner;
75  import org.apache.http.conn.socket.ConnectionSocketFactory;
76  import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
77  import org.apache.http.conn.socket.PlainConnectionSocketFactory;
78  import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
79  import org.apache.http.conn.ssl.SSLContexts;
80  import org.apache.http.conn.ssl.X509HostnameVerifier;
81  import org.apache.http.cookie.CookieSpecProvider;
82  import org.apache.http.impl.DefaultConnectionReuseStrategy;
83  import org.apache.http.impl.NoConnectionReuseStrategy;
84  import org.apache.http.impl.auth.BasicSchemeFactory;
85  import org.apache.http.impl.auth.DigestSchemeFactory;
86  import org.apache.http.impl.auth.KerberosSchemeFactory;
87  import org.apache.http.impl.auth.NTLMSchemeFactory;
88  import org.apache.http.impl.auth.SPNegoSchemeFactory;
89  import org.apache.http.impl.conn.DefaultProxyRoutePlanner;
90  import org.apache.http.impl.conn.DefaultRoutePlanner;
91  import org.apache.http.impl.conn.DefaultSchemePortResolver;
92  import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
93  import org.apache.http.impl.conn.SystemDefaultRoutePlanner;
94  import org.apache.http.impl.cookie.BestMatchSpecFactory;
95  import org.apache.http.impl.cookie.BrowserCompatSpecFactory;
96  import org.apache.http.impl.cookie.IgnoreSpecFactory;
97  import org.apache.http.impl.cookie.NetscapeDraftSpecFactory;
98  import org.apache.http.impl.cookie.RFC2109SpecFactory;
99  import org.apache.http.impl.cookie.RFC2965SpecFactory;
100 import org.apache.http.impl.execchain.BackoffStrategyExec;
101 import org.apache.http.impl.execchain.ClientExecChain;
102 import org.apache.http.impl.execchain.MainClientExec;
103 import org.apache.http.impl.execchain.ProtocolExec;
104 import org.apache.http.impl.execchain.RedirectExec;
105 import org.apache.http.impl.execchain.RetryExec;
106 import org.apache.http.impl.execchain.ServiceUnavailableRetryExec;
107 import org.apache.http.protocol.HttpProcessor;
108 import org.apache.http.protocol.HttpProcessorBuilder;
109 import org.apache.http.protocol.HttpRequestExecutor;
110 import org.apache.http.protocol.RequestContent;
111 import org.apache.http.protocol.RequestTargetHost;
112 import org.apache.http.protocol.RequestUserAgent;
113 import org.apache.http.util.TextUtils;
114 import org.apache.http.util.VersionInfo;
115 
116 /**
117  * Builder for {@link CloseableHttpClient} instances.
118  * <p/>
119  * When a particular component is not explicitly this class will
120  * use its default implementation. System properties will be taken
121  * into account when configuring the default implementations when
122  * {@link #useSystemProperties()} method is called prior to calling
123  * {@link #build()}.
124  * <ul>
125  *  <li>ssl.TrustManagerFactory.algorithm</li>
126  *  <li>javax.net.ssl.trustStoreType</li>
127  *  <li>javax.net.ssl.trustStore</li>
128  *  <li>javax.net.ssl.trustStoreProvider</li>
129  *  <li>javax.net.ssl.trustStorePassword</li>
130  *  <li>ssl.KeyManagerFactory.algorithm</li>
131  *  <li>javax.net.ssl.keyStoreType</li>
132  *  <li>javax.net.ssl.keyStore</li>
133  *  <li>javax.net.ssl.keyStoreProvider</li>
134  *  <li>javax.net.ssl.keyStorePassword</li>
135  *  <li>https.protocols</li>
136  *  <li>https.cipherSuites</li>
137  *  <li>http.proxyHost</li>
138  *  <li>http.proxyPort</li>
139  *  <li>http.nonProxyHosts</li>
140  *  <li>http.keepAlive</li>
141  *  <li>http.maxConnections</li>
142  *  <li>http.agent</li>
143  * </ul>
144  * <p/>
145  * Please note that some settings used by this class can be mutually
146  * exclusive and may not apply when building {@link CloseableHttpClient}
147  * instances.
148  *
149  * @since 4.3
150  */
151 @NotThreadSafe
152 public class HttpClientBuilder {
153 
154     private HttpRequestExecutor requestExec;
155     private X509HostnameVerifier hostnameVerifier;
156     private LayeredConnectionSocketFactory sslSocketFactory;
157     private SSLContext sslcontext;
158     private HttpClientConnectionManager connManager;
159     private SchemePortResolver schemePortResolver;
160     private ConnectionReuseStrategy reuseStrategy;
161     private ConnectionKeepAliveStrategy keepAliveStrategy;
162     private AuthenticationStrategy targetAuthStrategy;
163     private AuthenticationStrategy proxyAuthStrategy;
164     private UserTokenHandler userTokenHandler;
165     private HttpProcessor httpprocessor;
166 
167     private LinkedList<HttpRequestInterceptor> requestFirst;
168     private LinkedList<HttpRequestInterceptor> requestLast;
169     private LinkedList<HttpResponseInterceptor> responseFirst;
170     private LinkedList<HttpResponseInterceptor> responseLast;
171 
172     private HttpRequestRetryHandler retryHandler;
173     private HttpRoutePlanner routePlanner;
174     private RedirectStrategy redirectStrategy;
175     private ConnectionBackoffStrategy connectionBackoffStrategy;
176     private BackoffManager backoffManager;
177     private ServiceUnavailableRetryStrategy serviceUnavailStrategy;
178     private Lookup<AuthSchemeProvider> authSchemeRegistry;
179     private Lookup<CookieSpecProvider> cookieSpecRegistry;
180     private CookieStore cookieStore;
181     private CredentialsProvider credentialsProvider;
182     private String userAgent;
183     private HttpHost proxy;
184     private Collection<? extends Header> defaultHeaders;
185     private SocketConfig defaultSocketConfig;
186     private ConnectionConfig defaultConnectionConfig;
187     private RequestConfig defaultRequestConfig;
188 
189     private boolean systemProperties;
190     private boolean redirectHandlingDisabled;
191     private boolean automaticRetriesDisabled;
192     private boolean contentCompressionDisabled;
193     private boolean cookieManagementDisabled;
194     private boolean authCachingDisabled;
195     private boolean connectionStateDisabled;
196 
197     private int maxConnTotal = 0;
198     private int maxConnPerRoute = 0;
199 
200     private List<Closeable> closeables;
201 
202     static final String DEFAULT_USER_AGENT;
203     static {
204         final VersionInfo vi = VersionInfo.loadVersionInfo
205                 ("org.apache.http.client", HttpClientBuilder.class.getClassLoader());
206         final String release = (vi != null) ?
207                 vi.getRelease() : VersionInfo.UNAVAILABLE;
208         DEFAULT_USER_AGENT = "Apache-HttpClient/" + release + " (java 1.5)";
209     }
210 
211     public static HttpClientBuilder create() {
212         return new HttpClientBuilder();
213     }
214 
215     protected HttpClientBuilder() {
216         super();
217     }
218 
219     /**
220      * Assigns {@link HttpRequestExecutor} instance.
221      */
222     public final HttpClientBuilder setRequestExecutor(final HttpRequestExecutor requestExec) {
223         this.requestExec = requestExec;
224         return this;
225     }
226 
227     /**
228      * Assigns {@link X509HostnameVerifier} instance.
229      * <p/>
230      * Please note this value can be overridden by the {@link #setConnectionManager(
231      *   org.apache.http.conn.HttpClientConnectionManager)} and the {@link #setSSLSocketFactory(
232      *   org.apache.http.conn.socket.LayeredConnectionSocketFactory)} methods.
233      */
234     public final HttpClientBuilder setHostnameVerifier(final X509HostnameVerifier hostnameVerifier) {
235         this.hostnameVerifier = hostnameVerifier;
236         return this;
237     }
238 
239     /**
240      * Assigns {@link SSLContext} instance.
241      * <p/>
242      * <p/>
243      * Please note this value can be overridden by the {@link #setConnectionManager(
244      *   org.apache.http.conn.HttpClientConnectionManager)} and the {@link #setSSLSocketFactory(
245      *   org.apache.http.conn.socket.LayeredConnectionSocketFactory)} methods.
246      */
247     public final HttpClientBuilder setSslcontext(final SSLContext sslcontext) {
248         this.sslcontext = sslcontext;
249         return this;
250     }
251 
252     /**
253      * Assigns {@link LayeredConnectionSocketFactory} instance.
254      * <p/>
255      * Please note this value can be overridden by the {@link #setConnectionManager(
256      *   org.apache.http.conn.HttpClientConnectionManager)} method.
257      */
258     public final HttpClientBuilder setSSLSocketFactory(
259             final LayeredConnectionSocketFactory sslSocketFactory) {
260         this.sslSocketFactory = sslSocketFactory;
261         return this;
262     }
263 
264     /**
265      * Assigns maximum total connection value.
266      * <p/>
267      * Please note this value can be overridden by the {@link #setConnectionManager(
268      *   org.apache.http.conn.HttpClientConnectionManager)} method.
269      */
270     public final HttpClientBuilder setMaxConnTotal(final int maxConnTotal) {
271         this.maxConnTotal = maxConnTotal;
272         return this;
273     }
274 
275     /**
276      * Assigns maximum connection per route value.
277      * <p/>
278      * Please note this value can be overridden by the {@link #setConnectionManager(
279      *   org.apache.http.conn.HttpClientConnectionManager)} method.
280      */
281     public final HttpClientBuilder setMaxConnPerRoute(final int maxConnPerRoute) {
282         this.maxConnPerRoute = maxConnPerRoute;
283         return this;
284     }
285 
286     /**
287      * Assigns default {@link SocketConfig}.
288      * <p/>
289      * Please note this value can be overridden by the {@link #setConnectionManager(
290      *   org.apache.http.conn.HttpClientConnectionManager)} method.
291      */
292     public final HttpClientBuilder setDefaultSocketConfig(final SocketConfig config) {
293         this.defaultSocketConfig = config;
294         return this;
295     }
296 
297     /**
298      * Assigns default {@link ConnectionConfig}.
299      * <p/>
300      * Please note this value can be overridden by the {@link #setConnectionManager(
301      *   org.apache.http.conn.HttpClientConnectionManager)} method.
302      */
303     public final HttpClientBuilder setDefaultConnectionConfig(final ConnectionConfig config) {
304         this.defaultConnectionConfig = config;
305         return this;
306     }
307 
308     /**
309      * Assigns {@link HttpClientConnectionManager} instance.
310      */
311     public final HttpClientBuilder setConnectionManager(
312             final HttpClientConnectionManager connManager) {
313         this.connManager = connManager;
314         return this;
315     }
316 
317     /**
318      * Assigns {@link ConnectionReuseStrategy} instance.
319      */
320     public final HttpClientBuilder setConnectionReuseStrategy(
321             final ConnectionReuseStrategy reuseStrategy) {
322         this.reuseStrategy = reuseStrategy;
323         return this;
324     }
325 
326     /**
327      * Assigns {@link ConnectionKeepAliveStrategy} instance.
328      */
329     public final HttpClientBuilder setKeepAliveStrategy(
330             final ConnectionKeepAliveStrategy keepAliveStrategy) {
331         this.keepAliveStrategy = keepAliveStrategy;
332         return this;
333     }
334 
335     /**
336      * Assigns {@link AuthenticationStrategy} instance for proxy
337      * authentication.
338      */
339     public final HttpClientBuilder setTargetAuthenticationStrategy(
340             final AuthenticationStrategy targetAuthStrategy) {
341         this.targetAuthStrategy = targetAuthStrategy;
342         return this;
343     }
344 
345     /**
346      * Assigns {@link AuthenticationStrategy} instance for target
347      * host authentication.
348      */
349     public final HttpClientBuilder setProxyAuthenticationStrategy(
350             final AuthenticationStrategy proxyAuthStrategy) {
351         this.proxyAuthStrategy = proxyAuthStrategy;
352         return this;
353     }
354 
355     /**
356      * Assigns {@link UserTokenHandler} instance.
357      * <p/>
358      * Please note this value can be overridden by the {@link #disableConnectionState()}
359      * method.
360      */
361     public final HttpClientBuilder setUserTokenHandler(final UserTokenHandler userTokenHandler) {
362         this.userTokenHandler = userTokenHandler;
363         return this;
364     }
365 
366     /**
367      * Disables connection state tracking.
368      */
369     public final HttpClientBuilder disableConnectionState() {
370         connectionStateDisabled = true;
371         return this;
372     }
373 
374     /**
375      * Assigns {@link SchemePortResolver} instance.
376      */
377     public final HttpClientBuilder setSchemePortResolver(
378             final SchemePortResolver schemePortResolver) {
379         this.schemePortResolver = schemePortResolver;
380         return this;
381     }
382 
383     /**
384      * Assigns <tt>User-Agent</tt> value.
385      * <p/>
386      * Please note this value can be overridden by the {@link #setHttpProcessor(
387      * org.apache.http.protocol.HttpProcessor)} method.
388      */
389     public final HttpClientBuilder setUserAgent(final String userAgent) {
390         this.userAgent = userAgent;
391         return this;
392     }
393 
394     /**
395      * Assigns default request header values.
396      * <p/>
397      * Please note this value can be overridden by the {@link #setHttpProcessor(
398      * org.apache.http.protocol.HttpProcessor)} method.
399      */
400     public final HttpClientBuilder setDefaultHeaders(final Collection<? extends Header> defaultHeaders) {
401         this.defaultHeaders = defaultHeaders;
402         return this;
403     }
404 
405     /**
406      * Adds this protocol interceptor to the head of the protocol processing list.
407      * <p/>
408      * Please note this value can be overridden by the {@link #setHttpProcessor(
409      * org.apache.http.protocol.HttpProcessor)} method.
410      */
411     public final HttpClientBuilder addInterceptorFirst(final HttpResponseInterceptor itcp) {
412         if (itcp == null) {
413             return this;
414         }
415         if (responseFirst == null) {
416             responseFirst = new LinkedList<HttpResponseInterceptor>();
417         }
418         responseFirst.addFirst(itcp);
419         return this;
420     }
421 
422     /**
423      * Adds this protocol interceptor to the tail of the protocol processing list.
424      * <p/>
425      * Please note this value can be overridden by the {@link #setHttpProcessor(
426      * org.apache.http.protocol.HttpProcessor)} method.
427      */
428     public final HttpClientBuilder addInterceptorLast(final HttpResponseInterceptor itcp) {
429         if (itcp == null) {
430             return this;
431         }
432         if (responseLast == null) {
433             responseLast = new LinkedList<HttpResponseInterceptor>();
434         }
435         responseLast.addLast(itcp);
436         return this;
437     }
438 
439     /**
440      * Adds this protocol interceptor to the head of the protocol processing list.
441      * <p/>
442      * Please note this value can be overridden by the {@link #setHttpProcessor(
443      * org.apache.http.protocol.HttpProcessor)} method.
444      */
445     public final HttpClientBuilder addInterceptorFirst(final HttpRequestInterceptor itcp) {
446         if (itcp == null) {
447             return this;
448         }
449         if (requestFirst == null) {
450             requestFirst = new LinkedList<HttpRequestInterceptor>();
451         }
452         requestFirst.addFirst(itcp);
453         return this;
454     }
455 
456     /**
457      * Adds this protocol interceptor to the tail of the protocol processing list.
458      * <p/>
459      * Please note this value can be overridden by the {@link #setHttpProcessor(
460      * org.apache.http.protocol.HttpProcessor)} method.
461      */
462     public final HttpClientBuilder addInterceptorLast(final HttpRequestInterceptor itcp) {
463         if (itcp == null) {
464             return this;
465         }
466         if (requestLast == null) {
467             requestLast = new LinkedList<HttpRequestInterceptor>();
468         }
469         requestLast.addLast(itcp);
470         return this;
471     }
472 
473     /**
474      * Disables state (cookie) management.
475      * <p/>
476      * Please note this value can be overridden by the {@link #setHttpProcessor(
477      * org.apache.http.protocol.HttpProcessor)} method.
478      */
479     public final HttpClientBuilder disableCookieManagement() {
480         this.cookieManagementDisabled = true;
481         return this;
482     }
483 
484     /**
485      * Disables automatic content decompression.
486      * <p/>
487      * Please note this value can be overridden by the {@link #setHttpProcessor(
488      * org.apache.http.protocol.HttpProcessor)} method.
489      */
490     public final HttpClientBuilder disableContentCompression() {
491         contentCompressionDisabled = true;
492         return this;
493     }
494 
495     /**
496      * Disables authentication scheme caching.
497      * <p/>
498      * Please note this value can be overridden by the {@link #setHttpProcessor(
499      * org.apache.http.protocol.HttpProcessor)} method.
500      */
501     public final HttpClientBuilder disableAuthCaching() {
502         this.authCachingDisabled = true;
503         return this;
504     }
505 
506     /**
507      * Assigns {@link HttpProcessor} instance.
508      */
509     public final HttpClientBuilder setHttpProcessor(final HttpProcessor httpprocessor) {
510         this.httpprocessor = httpprocessor;
511         return this;
512     }
513 
514     /**
515      * Assigns {@link HttpRequestRetryHandler} instance.
516      * <p/>
517      * Please note this value can be overridden by the {@link #disableAutomaticRetries()}
518      * method.
519      */
520     public final HttpClientBuilder setRetryHandler(final HttpRequestRetryHandler retryHandler) {
521         this.retryHandler = retryHandler;
522         return this;
523     }
524 
525     /**
526      * Disables automatic request recovery and re-execution.
527      */
528     public final HttpClientBuilder disableAutomaticRetries() {
529         automaticRetriesDisabled = true;
530         return this;
531     }
532 
533     /**
534      * Assigns default proxy value.
535      * <p/>
536      * Please note this value can be overridden by the {@link #setRoutePlanner(
537      *   org.apache.http.conn.routing.HttpRoutePlanner)} method.
538      */
539     public final HttpClientBuilder setProxy(final HttpHost proxy) {
540         this.proxy = proxy;
541         return this;
542     }
543 
544     /**
545      * Assigns {@link HttpRoutePlanner} instance.
546      */
547     public final HttpClientBuilder setRoutePlanner(final HttpRoutePlanner routePlanner) {
548         this.routePlanner = routePlanner;
549         return this;
550     }
551 
552     /**
553      * Assigns {@link RedirectStrategy} instance.
554      * <p/>
555      * Please note this value can be overridden by the {@link #disableRedirectHandling()}
556      * method.
557 `     */
558     public final HttpClientBuilder setRedirectStrategy(final RedirectStrategy redirectStrategy) {
559         this.redirectStrategy = redirectStrategy;
560         return this;
561     }
562 
563     /**
564      * Disables automatic redirect handling.
565      */
566     public final HttpClientBuilder disableRedirectHandling() {
567         redirectHandlingDisabled = true;
568         return this;
569     }
570 
571     /**
572      * Assigns {@link ConnectionBackoffStrategy} instance.
573      */
574     public final HttpClientBuilder setConnectionBackoffStrategy(
575             final ConnectionBackoffStrategy connectionBackoffStrategy) {
576         this.connectionBackoffStrategy = connectionBackoffStrategy;
577         return this;
578     }
579 
580     /**
581      * Assigns {@link BackoffManager} instance.
582      */
583     public final HttpClientBuilder setBackoffManager(final BackoffManager backoffManager) {
584         this.backoffManager = backoffManager;
585         return this;
586     }
587 
588     /**
589      * Assigns {@link ServiceUnavailableRetryStrategy} instance.
590      */
591     public final HttpClientBuilder setServiceUnavailableRetryStrategy(
592             final ServiceUnavailableRetryStrategy serviceUnavailStrategy) {
593         this.serviceUnavailStrategy = serviceUnavailStrategy;
594         return this;
595     }
596 
597     /**
598      * Assigns default {@link CookieStore} instance which will be used for
599      * request execution if not explicitly set in the client execution context.
600      */
601     public final HttpClientBuilder setDefaultCookieStore(final CookieStore cookieStore) {
602         this.cookieStore = cookieStore;
603         return this;
604     }
605 
606     /**
607      * Assigns default {@link CredentialsProvider} instance which will be used
608      * for request execution if not explicitly set in the client execution
609      * context.
610      */
611     public final HttpClientBuilder setDefaultCredentialsProvider(
612             final CredentialsProvider credentialsProvider) {
613         this.credentialsProvider = credentialsProvider;
614         return this;
615     }
616 
617     /**
618      * Assigns default {@link org.apache.http.auth.AuthScheme} registry which will
619      * be used for request execution if not explicitly set in the client execution
620      * context.
621      */
622     public final HttpClientBuilder setDefaultAuthSchemeRegistry(
623             final Lookup<AuthSchemeProvider> authSchemeRegistry) {
624         this.authSchemeRegistry = authSchemeRegistry;
625         return this;
626     }
627 
628     /**
629      * Assigns default {@link org.apache.http.cookie.CookieSpec} registry which will
630      * be used for request execution if not explicitly set in the client execution
631      * context.
632      */
633     public final HttpClientBuilder setDefaultCookieSpecRegistry(
634             final Lookup<CookieSpecProvider> cookieSpecRegistry) {
635         this.cookieSpecRegistry = cookieSpecRegistry;
636         return this;
637     }
638 
639     /**
640      * Assigns default {@link RequestConfig} instance which will be used
641      * for request execution if not explicitly set in the client execution
642      * context.
643      */
644     public final HttpClientBuilder setDefaultRequestConfig(final RequestConfig config) {
645         this.defaultRequestConfig = config;
646         return this;
647     }
648 
649     /**
650      * Use system properties when creating and configuring default
651      * implementations.
652      */
653     public final HttpClientBuilder useSystemProperties() {
654         systemProperties = true;
655         return this;
656     }
657 
658     /**
659      * For internal use.
660      */
661     protected ClientExecChain decorateMainExec(final ClientExecChain mainExec) {
662         return mainExec;
663     }
664 
665     /**
666      * For internal use.
667      */
668     protected ClientExecChain decorateProtocolExec(final ClientExecChain protocolExec) {
669         return protocolExec;
670     }
671 
672     /**
673      * For internal use.
674      */
675     protected void addCloseable(final Closeable closeable) {
676         if (closeable == null) {
677             return;
678         }
679         if (closeables == null) {
680             closeables = new ArrayList<Closeable>();
681         }
682         closeables.add(closeable);
683     }
684 
685     private static String[] split(final String s) {
686         if (TextUtils.isBlank(s)) {
687             return null;
688         }
689         return s.split(" *, *");
690     }
691 
692     public CloseableHttpClient build() {
693         // Create main request executor
694         HttpRequestExecutor requestExec = this.requestExec;
695         if (requestExec == null) {
696             requestExec = new HttpRequestExecutor();
697         }
698         HttpClientConnectionManager connManager = this.connManager;
699         if (connManager == null) {
700             LayeredConnectionSocketFactory sslSocketFactory = this.sslSocketFactory;
701             if (sslSocketFactory == null) {
702                 final String[] supportedProtocols = systemProperties ? split(
703                         System.getProperty("https.protocols")) : null;
704                 final String[] supportedCipherSuites = systemProperties ? split(
705                         System.getProperty("https.cipherSuites")) : null;
706                 X509HostnameVerifier hostnameVerifier = this.hostnameVerifier;
707                 if (hostnameVerifier == null) {
708                     hostnameVerifier = SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER;
709                 }
710                 if (sslcontext != null) {
711                     sslSocketFactory = new SSLConnectionSocketFactory(
712                             sslcontext, supportedProtocols, supportedCipherSuites, hostnameVerifier);
713                 } else {
714                     if (systemProperties) {
715                         sslSocketFactory = new SSLConnectionSocketFactory(
716                                 (SSLSocketFactory) SSLSocketFactory.getDefault(),
717                                 supportedProtocols, supportedCipherSuites, hostnameVerifier);
718                     } else {
719                         sslSocketFactory = new SSLConnectionSocketFactory(
720                                 SSLContexts.createDefault(),
721                                 hostnameVerifier);
722                     }
723                 }
724             }
725             @SuppressWarnings("resource")
726             final PoolingHttpClientConnectionManager poolingmgr = new PoolingHttpClientConnectionManager(
727                     RegistryBuilder.<ConnectionSocketFactory>create()
728                         .register("http", PlainConnectionSocketFactory.getSocketFactory())
729                         .register("https", sslSocketFactory)
730                         .build());
731             if (defaultSocketConfig != null) {
732                 poolingmgr.setDefaultSocketConfig(defaultSocketConfig);
733             }
734             if (defaultConnectionConfig != null) {
735                 poolingmgr.setDefaultConnectionConfig(defaultConnectionConfig);
736             }
737             if (systemProperties) {
738                 String s = System.getProperty("http.keepAlive", "true");
739                 if ("true".equalsIgnoreCase(s)) {
740                     s = System.getProperty("http.maxConnections", "5");
741                     final int max = Integer.parseInt(s);
742                     poolingmgr.setDefaultMaxPerRoute(max);
743                     poolingmgr.setMaxTotal(2 * max);
744                 }
745             }
746             if (maxConnTotal > 0) {
747                 poolingmgr.setMaxTotal(maxConnTotal);
748             }
749             if (maxConnPerRoute > 0) {
750                 poolingmgr.setDefaultMaxPerRoute(maxConnPerRoute);
751             }
752             connManager = poolingmgr;
753         }
754         ConnectionReuseStrategy reuseStrategy = this.reuseStrategy;
755         if (reuseStrategy == null) {
756             if (systemProperties) {
757                 final String s = System.getProperty("http.keepAlive", "true");
758                 if ("true".equalsIgnoreCase(s)) {
759                     reuseStrategy = DefaultConnectionReuseStrategy.INSTANCE;
760                 } else {
761                     reuseStrategy = NoConnectionReuseStrategy.INSTANCE;
762                 }
763             } else {
764                 reuseStrategy = DefaultConnectionReuseStrategy.INSTANCE;
765             }
766         }
767         ConnectionKeepAliveStrategy keepAliveStrategy = this.keepAliveStrategy;
768         if (keepAliveStrategy == null) {
769             keepAliveStrategy = DefaultConnectionKeepAliveStrategy.INSTANCE;
770         }
771         AuthenticationStrategy targetAuthStrategy = this.targetAuthStrategy;
772         if (targetAuthStrategy == null) {
773             targetAuthStrategy = TargetAuthenticationStrategy.INSTANCE;
774         }
775         AuthenticationStrategy proxyAuthStrategy = this.proxyAuthStrategy;
776         if (proxyAuthStrategy == null) {
777             proxyAuthStrategy = ProxyAuthenticationStrategy.INSTANCE;
778         }
779         UserTokenHandler userTokenHandler = this.userTokenHandler;
780         if (userTokenHandler == null) {
781             if (!connectionStateDisabled) {
782                 userTokenHandler = DefaultUserTokenHandler.INSTANCE;
783             } else {
784                 userTokenHandler = NoopUserTokenHandler.INSTANCE;
785             }
786         }
787         ClientExecChain execChain = new MainClientExec(
788                 requestExec,
789                 connManager,
790                 reuseStrategy,
791                 keepAliveStrategy,
792                 targetAuthStrategy,
793                 proxyAuthStrategy,
794                 userTokenHandler);
795 
796         execChain = decorateMainExec(execChain);
797 
798         HttpProcessor httpprocessor = this.httpprocessor;
799         if (httpprocessor == null) {
800 
801             String userAgent = this.userAgent;
802             if (userAgent == null) {
803                 if (systemProperties) {
804                     userAgent = System.getProperty("http.agent");
805                 }
806                 if (userAgent == null) {
807                     userAgent = DEFAULT_USER_AGENT;
808                 }
809             }
810 
811             final HttpProcessorBuilder b = HttpProcessorBuilder.create();
812             if (requestFirst != null) {
813                 for (final HttpRequestInterceptor i: requestFirst) {
814                     b.addFirst(i);
815                 }
816             }
817             if (responseFirst != null) {
818                 for (final HttpResponseInterceptor i: responseFirst) {
819                     b.addFirst(i);
820                 }
821             }
822             b.addAll(
823                     new RequestDefaultHeaders(defaultHeaders),
824                     new RequestContent(),
825                     new RequestTargetHost(),
826                     new RequestClientConnControl(),
827                     new RequestUserAgent(userAgent),
828                     new RequestExpectContinue());
829             if (!cookieManagementDisabled) {
830                 b.add(new RequestAddCookies());
831             }
832             if (!contentCompressionDisabled) {
833                 b.add(new RequestAcceptEncoding());
834             }
835             if (!authCachingDisabled) {
836                 b.add(new RequestAuthCache());
837             }
838             if (!cookieManagementDisabled) {
839                 b.add(new ResponseProcessCookies());
840             }
841             if (!contentCompressionDisabled) {
842                 b.add(new ResponseContentEncoding());
843             }
844             if (requestLast != null) {
845                 for (final HttpRequestInterceptor i: requestLast) {
846                     b.addLast(i);
847                 }
848             }
849             if (responseLast != null) {
850                 for (final HttpResponseInterceptor i: responseLast) {
851                     b.addLast(i);
852                 }
853             }
854             httpprocessor = b.build();
855         }
856         execChain = new ProtocolExec(execChain, httpprocessor);
857 
858         execChain = decorateProtocolExec(execChain);
859 
860         // Add request retry executor, if not disabled
861         if (!automaticRetriesDisabled) {
862             HttpRequestRetryHandler retryHandler = this.retryHandler;
863             if (retryHandler == null) {
864                 retryHandler = DefaultHttpRequestRetryHandler.INSTANCE;
865             }
866             execChain = new RetryExec(execChain, retryHandler);
867         }
868 
869         HttpRoutePlanner routePlanner = this.routePlanner;
870         if (routePlanner == null) {
871             SchemePortResolver schemePortResolver = this.schemePortResolver;
872             if (schemePortResolver == null) {
873                 schemePortResolver = DefaultSchemePortResolver.INSTANCE;
874             }
875             if (proxy != null) {
876                 routePlanner = new DefaultProxyRoutePlanner(proxy, schemePortResolver);
877             } else if (systemProperties) {
878                 routePlanner = new SystemDefaultRoutePlanner(
879                         schemePortResolver, ProxySelector.getDefault());
880             } else {
881                 routePlanner = new DefaultRoutePlanner(schemePortResolver);
882             }
883         }
884         // Add redirect executor, if not disabled
885         if (!redirectHandlingDisabled) {
886             RedirectStrategy redirectStrategy = this.redirectStrategy;
887             if (redirectStrategy == null) {
888                 redirectStrategy = DefaultRedirectStrategy.INSTANCE;
889             }
890             execChain = new RedirectExec(execChain, routePlanner, redirectStrategy);
891         }
892 
893         // Optionally, add service unavailable retry executor
894         final ServiceUnavailableRetryStrategy serviceUnavailStrategy = this.serviceUnavailStrategy;
895         if (serviceUnavailStrategy != null) {
896             execChain = new ServiceUnavailableRetryExec(execChain, serviceUnavailStrategy);
897         }
898         // Optionally, add connection back-off executor
899         final BackoffManager backoffManager = this.backoffManager;
900         final ConnectionBackoffStrategy connectionBackoffStrategy = this.connectionBackoffStrategy;
901         if (backoffManager != null && connectionBackoffStrategy != null) {
902             execChain = new BackoffStrategyExec(execChain, connectionBackoffStrategy, backoffManager);
903         }
904 
905         Lookup<AuthSchemeProvider> authSchemeRegistry = this.authSchemeRegistry;
906         if (authSchemeRegistry == null) {
907             authSchemeRegistry = RegistryBuilder.<AuthSchemeProvider>create()
908                 .register(AuthSchemes.BASIC, new BasicSchemeFactory())
909                 .register(AuthSchemes.DIGEST, new DigestSchemeFactory())
910                 .register(AuthSchemes.NTLM, new NTLMSchemeFactory())
911                 .register(AuthSchemes.SPNEGO, new SPNegoSchemeFactory())
912                 .register(AuthSchemes.KERBEROS, new KerberosSchemeFactory())
913                 .build();
914         }
915         Lookup<CookieSpecProvider> cookieSpecRegistry = this.cookieSpecRegistry;
916         if (cookieSpecRegistry == null) {
917             cookieSpecRegistry = RegistryBuilder.<CookieSpecProvider>create()
918                 .register(CookieSpecs.BEST_MATCH, new BestMatchSpecFactory())
919                 .register(CookieSpecs.STANDARD, new RFC2965SpecFactory())
920                 .register(CookieSpecs.BROWSER_COMPATIBILITY, new BrowserCompatSpecFactory())
921                 .register(CookieSpecs.NETSCAPE, new NetscapeDraftSpecFactory())
922                 .register(CookieSpecs.IGNORE_COOKIES, new IgnoreSpecFactory())
923                 .register("rfc2109", new RFC2109SpecFactory())
924                 .register("rfc2965", new RFC2965SpecFactory())
925                 .build();
926         }
927 
928         CookieStore defaultCookieStore = this.cookieStore;
929         if (defaultCookieStore == null) {
930             defaultCookieStore = new BasicCookieStore();
931         }
932 
933         CredentialsProvider defaultCredentialsProvider = this.credentialsProvider;
934         if (defaultCredentialsProvider == null) {
935             if (systemProperties) {
936                 defaultCredentialsProvider = new SystemDefaultCredentialsProvider();
937             } else {
938                 defaultCredentialsProvider = new BasicCredentialsProvider();
939             }
940         }
941 
942         return new InternalHttpClient(
943                 execChain,
944                 connManager,
945                 routePlanner,
946                 cookieSpecRegistry,
947                 authSchemeRegistry,
948                 defaultCookieStore,
949                 defaultCredentialsProvider,
950                 defaultRequestConfig != null ? defaultRequestConfig : RequestConfig.DEFAULT,
951                 closeables != null ? new ArrayList<Closeable>(closeables) : null);
952     }
953 
954 }