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