1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package org.apache.hc.client5.http.impl.async;
29
30 import java.io.Closeable;
31 import java.io.IOException;
32 import java.net.InetSocketAddress;
33 import java.security.AccessController;
34 import java.security.PrivilegedAction;
35 import java.util.ArrayList;
36 import java.util.Collection;
37 import java.util.LinkedList;
38 import java.util.List;
39 import java.util.concurrent.ThreadFactory;
40
41 import org.apache.hc.client5.http.AuthenticationStrategy;
42 import org.apache.hc.client5.http.DnsResolver;
43 import org.apache.hc.client5.http.HttpRequestRetryStrategy;
44 import org.apache.hc.client5.http.SchemePortResolver;
45 import org.apache.hc.client5.http.async.AsyncExecChainHandler;
46 import org.apache.hc.client5.http.auth.AuthSchemeFactory;
47 import org.apache.hc.client5.http.auth.StandardAuthScheme;
48 import org.apache.hc.client5.http.auth.CredentialsProvider;
49 import org.apache.hc.client5.http.config.RequestConfig;
50 import org.apache.hc.client5.http.cookie.BasicCookieStore;
51 import org.apache.hc.client5.http.cookie.CookieSpecFactory;
52 import org.apache.hc.client5.http.cookie.CookieStore;
53 import org.apache.hc.client5.http.impl.ChainElement;
54 import org.apache.hc.client5.http.impl.CookieSpecSupport;
55 import org.apache.hc.client5.http.impl.DefaultAuthenticationStrategy;
56 import org.apache.hc.client5.http.impl.DefaultHttpRequestRetryStrategy;
57 import org.apache.hc.client5.http.impl.DefaultRedirectStrategy;
58 import org.apache.hc.client5.http.impl.DefaultSchemePortResolver;
59 import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider;
60 import org.apache.hc.client5.http.impl.auth.BasicSchemeFactory;
61 import org.apache.hc.client5.http.impl.auth.DigestSchemeFactory;
62 import org.apache.hc.client5.http.impl.auth.KerberosSchemeFactory;
63 import org.apache.hc.client5.http.impl.auth.NTLMSchemeFactory;
64 import org.apache.hc.client5.http.impl.auth.SPNegoSchemeFactory;
65 import org.apache.hc.client5.http.impl.auth.SystemDefaultCredentialsProvider;
66 import org.apache.hc.client5.http.impl.nio.MultihomeConnectionInitiator;
67 import org.apache.hc.client5.http.impl.routing.DefaultRoutePlanner;
68 import org.apache.hc.client5.http.protocol.RedirectStrategy;
69 import org.apache.hc.client5.http.protocol.RequestAddCookies;
70 import org.apache.hc.client5.http.protocol.RequestAuthCache;
71 import org.apache.hc.client5.http.protocol.RequestDefaultHeaders;
72 import org.apache.hc.client5.http.protocol.RequestExpectContinue;
73 import org.apache.hc.client5.http.protocol.ResponseProcessCookies;
74 import org.apache.hc.client5.http.routing.HttpRoutePlanner;
75 import org.apache.hc.client5.http.ssl.DefaultClientTlsStrategy;
76 import org.apache.hc.core5.annotation.Internal;
77 import org.apache.hc.core5.concurrent.DefaultThreadFactory;
78 import org.apache.hc.core5.function.Callback;
79 import org.apache.hc.core5.function.Resolver;
80 import org.apache.hc.core5.http.Header;
81 import org.apache.hc.core5.http.HttpException;
82 import org.apache.hc.core5.http.HttpHost;
83 import org.apache.hc.core5.http.HttpRequest;
84 import org.apache.hc.core5.http.HttpRequestInterceptor;
85 import org.apache.hc.core5.http.HttpResponseInterceptor;
86 import org.apache.hc.core5.http.config.CharCodingConfig;
87 import org.apache.hc.core5.http.config.Lookup;
88 import org.apache.hc.core5.http.config.NamedElementChain;
89 import org.apache.hc.core5.http.config.RegistryBuilder;
90 import org.apache.hc.core5.http.nio.AsyncPushConsumer;
91 import org.apache.hc.core5.http.nio.HandlerFactory;
92 import org.apache.hc.core5.http.nio.command.ShutdownCommand;
93 import org.apache.hc.core5.http.nio.ssl.TlsStrategy;
94 import org.apache.hc.core5.http.protocol.DefaultHttpProcessor;
95 import org.apache.hc.core5.http.protocol.HttpContext;
96 import org.apache.hc.core5.http.protocol.HttpProcessor;
97 import org.apache.hc.core5.http.protocol.HttpProcessorBuilder;
98 import org.apache.hc.core5.http.protocol.RequestTargetHost;
99 import org.apache.hc.core5.http.protocol.RequestUserAgent;
100 import org.apache.hc.core5.http2.config.H2Config;
101 import org.apache.hc.core5.http2.nio.pool.H2ConnPool;
102 import org.apache.hc.core5.http2.protocol.H2RequestConnControl;
103 import org.apache.hc.core5.http2.protocol.H2RequestContent;
104 import org.apache.hc.core5.http2.protocol.H2RequestTargetHost;
105 import org.apache.hc.core5.io.CloseMode;
106 import org.apache.hc.core5.reactor.Command;
107 import org.apache.hc.core5.reactor.DefaultConnectingIOReactor;
108 import org.apache.hc.core5.reactor.IOEventHandlerFactory;
109 import org.apache.hc.core5.reactor.IOReactorConfig;
110 import org.apache.hc.core5.reactor.IOSession;
111 import org.apache.hc.core5.util.Args;
112 import org.apache.hc.core5.util.TimeValue;
113 import org.apache.hc.core5.util.VersionInfo;
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129 public class H2AsyncClientBuilder {
130
131 private static class RequestInterceptorEntry {
132
133 enum Postion { FIRST, LAST }
134
135 final RequestInterceptorEntry.Postion postion;
136 final HttpRequestInterceptor interceptor;
137
138 private RequestInterceptorEntry(final RequestInterceptorEntry.Postion postion, final HttpRequestInterceptor interceptor) {
139 this.postion = postion;
140 this.interceptor = interceptor;
141 }
142 }
143
144 private static class ResponseInterceptorEntry {
145
146 enum Postion { FIRST, LAST }
147
148 final ResponseInterceptorEntry.Postion postion;
149 final HttpResponseInterceptor interceptor;
150
151 private ResponseInterceptorEntry(final ResponseInterceptorEntry.Postion postion, final HttpResponseInterceptor interceptor) {
152 this.postion = postion;
153 this.interceptor = interceptor;
154 }
155 }
156
157 private static class ExecInterceptorEntry {
158
159 enum Postion { BEFORE, AFTER, REPLACE, FIRST, LAST }
160
161 final ExecInterceptorEntry.Postion postion;
162 final String name;
163 final AsyncExecChainHandler interceptor;
164 final String existing;
165
166 private ExecInterceptorEntry(
167 final ExecInterceptorEntry.Postion postion,
168 final String name,
169 final AsyncExecChainHandler interceptor,
170 final String existing) {
171 this.postion = postion;
172 this.name = name;
173 this.interceptor = interceptor;
174 this.existing = existing;
175 }
176
177 }
178
179 private IOReactorConfig ioReactorConfig;
180 private H2Config h2Config;
181 private CharCodingConfig charCodingConfig;
182 private SchemePortResolver schemePortResolver;
183 private AuthenticationStrategy targetAuthStrategy;
184 private AuthenticationStrategy proxyAuthStrategy;
185
186 private LinkedList<RequestInterceptorEntry> requestInterceptors;
187 private LinkedList<ResponseInterceptorEntry> responseInterceptors;
188 private LinkedList<ExecInterceptorEntry> execInterceptors;
189
190 private HttpRoutePlanner routePlanner;
191 private RedirectStrategy redirectStrategy;
192 private HttpRequestRetryStrategy retryStrategy;
193
194 private Lookup<AuthSchemeFactory> authSchemeRegistry;
195 private Lookup<CookieSpecFactory> cookieSpecRegistry;
196 private CookieStore cookieStore;
197 private CredentialsProvider credentialsProvider;
198
199 private String userAgent;
200 private Collection<? extends Header> defaultHeaders;
201 private RequestConfig defaultRequestConfig;
202 private boolean evictIdleConnections;
203 private TimeValue maxIdleTime;
204
205 private boolean systemProperties;
206 private boolean automaticRetriesDisabled;
207 private boolean redirectHandlingDisabled;
208 private boolean cookieManagementDisabled;
209 private boolean authCachingDisabled;
210
211 private DnsResolver dnsResolver;
212 private TlsStrategy tlsStrategy;
213
214 private ThreadFactory threadFactory;
215
216 private List<Closeable> closeables;
217
218 public static H2AsyncClientBuilder create() {
219 return new H2AsyncClientBuilder();
220 }
221
222 protected H2AsyncClientBuilder() {
223 super();
224 }
225
226
227
228
229 public final H2AsyncClientBuilder setH2Config(final H2Config h2Config) {
230 this.h2Config = h2Config;
231 return this;
232 }
233
234
235
236
237 public final H2AsyncClientBuilder setIOReactorConfig(final IOReactorConfig ioReactorConfig) {
238 this.ioReactorConfig = ioReactorConfig;
239 return this;
240 }
241
242
243
244
245 public final H2AsyncClientBuilder setCharCodingConfig(final CharCodingConfig charCodingConfig) {
246 this.charCodingConfig = charCodingConfig;
247 return this;
248 }
249
250
251
252
253
254 public final H2AsyncClientBuilder setTargetAuthenticationStrategy(
255 final AuthenticationStrategy targetAuthStrategy) {
256 this.targetAuthStrategy = targetAuthStrategy;
257 return this;
258 }
259
260
261
262
263
264 public final H2AsyncClientBuilder setProxyAuthenticationStrategy(
265 final AuthenticationStrategy proxyAuthStrategy) {
266 this.proxyAuthStrategy = proxyAuthStrategy;
267 return this;
268 }
269
270
271
272
273 public final H2AsyncClientBuilder addResponseInterceptorFirst(final HttpResponseInterceptor interceptor) {
274 Args.notNull(interceptor, "Interceptor");
275 if (responseInterceptors == null) {
276 responseInterceptors = new LinkedList<>();
277 }
278 responseInterceptors.add(new ResponseInterceptorEntry(ResponseInterceptorEntry.Postion.FIRST, interceptor));
279 return this;
280 }
281
282
283
284
285 public final H2AsyncClientBuilder addResponseInterceptorLast(final HttpResponseInterceptor interceptor) {
286 Args.notNull(interceptor, "Interceptor");
287 if (responseInterceptors == null) {
288 responseInterceptors = new LinkedList<>();
289 }
290 responseInterceptors.add(new ResponseInterceptorEntry(ResponseInterceptorEntry.Postion.LAST, interceptor));
291 return this;
292 }
293
294
295
296
297 public final H2AsyncClientBuilder addExecInterceptorBefore(final String existing, final String name, final AsyncExecChainHandler interceptor) {
298 Args.notBlank(existing, "Existing");
299 Args.notBlank(name, "Name");
300 Args.notNull(interceptor, "Interceptor");
301 if (execInterceptors == null) {
302 execInterceptors = new LinkedList<>();
303 }
304 execInterceptors.add(new ExecInterceptorEntry(ExecInterceptorEntry.Postion.BEFORE, name, interceptor, existing));
305 return this;
306 }
307
308
309
310
311 public final H2AsyncClientBuilder addExecInterceptorAfter(final String existing, final String name, final AsyncExecChainHandler interceptor) {
312 Args.notBlank(existing, "Existing");
313 Args.notBlank(name, "Name");
314 Args.notNull(interceptor, "Interceptor");
315 if (execInterceptors == null) {
316 execInterceptors = new LinkedList<>();
317 }
318 execInterceptors.add(new ExecInterceptorEntry(ExecInterceptorEntry.Postion.AFTER, name, interceptor, existing));
319 return this;
320 }
321
322
323
324
325 public final H2AsyncClientBuilder replaceExecInterceptor(final String existing, final AsyncExecChainHandler interceptor) {
326 Args.notBlank(existing, "Existing");
327 Args.notNull(interceptor, "Interceptor");
328 if (execInterceptors == null) {
329 execInterceptors = new LinkedList<>();
330 }
331 execInterceptors.add(new ExecInterceptorEntry(ExecInterceptorEntry.Postion.REPLACE, existing, interceptor, existing));
332 return this;
333 }
334
335
336
337
338 public final H2AsyncClientBuilder addExecInterceptorFirst(final String name, final AsyncExecChainHandler interceptor) {
339 Args.notNull(name, "Name");
340 Args.notNull(interceptor, "Interceptor");
341 execInterceptors.add(new ExecInterceptorEntry(ExecInterceptorEntry.Postion.FIRST, name, interceptor, null));
342 return this;
343 }
344
345
346
347
348 public final H2AsyncClientBuilder addExecInterceptorLast(final String name, final AsyncExecChainHandler interceptor) {
349 Args.notNull(name, "Name");
350 Args.notNull(interceptor, "Interceptor");
351 execInterceptors.add(new ExecInterceptorEntry(ExecInterceptorEntry.Postion.LAST, name, interceptor, null));
352 return this;
353 }
354
355
356
357
358 public final H2AsyncClientBuilder addRequestInterceptorFirst(final HttpRequestInterceptor interceptor) {
359 Args.notNull(interceptor, "Interceptor");
360 if (requestInterceptors == null) {
361 requestInterceptors = new LinkedList<>();
362 }
363 requestInterceptors.add(new RequestInterceptorEntry(RequestInterceptorEntry.Postion.FIRST, interceptor));
364 return this;
365 }
366
367
368
369
370 public final H2AsyncClientBuilder addRequestInterceptorLast(final HttpRequestInterceptor interceptor) {
371 Args.notNull(interceptor, "Interceptor");
372 if (requestInterceptors == null) {
373 requestInterceptors = new LinkedList<>();
374 }
375 requestInterceptors.add(new RequestInterceptorEntry(RequestInterceptorEntry.Postion.LAST, interceptor));
376 return this;
377 }
378
379
380
381
382
383
384
385 public final H2AsyncClientBuilder setRetryStrategy(final HttpRequestRetryStrategy retryStrategy) {
386 this.retryStrategy = retryStrategy;
387 return this;
388 }
389
390
391
392
393
394
395
396
397 public H2AsyncClientBuilder setRedirectStrategy(final RedirectStrategy redirectStrategy) {
398 this.redirectStrategy = redirectStrategy;
399 return this;
400 }
401
402
403
404
405 public final H2AsyncClientBuilder setSchemePortResolver(final SchemePortResolver schemePortResolver) {
406 this.schemePortResolver = schemePortResolver;
407 return this;
408 }
409
410
411
412
413 public final H2AsyncClientBuilder setDnsResolver(final DnsResolver dnsResolver) {
414 this.dnsResolver = dnsResolver;
415 return this;
416 }
417
418
419
420
421 public final H2AsyncClientBuilder setTlsStrategy(final TlsStrategy tlsStrategy) {
422 this.tlsStrategy = tlsStrategy;
423 return this;
424 }
425
426
427
428
429 public final H2AsyncClientBuilder setThreadFactory(final ThreadFactory threadFactory) {
430 this.threadFactory = threadFactory;
431 return this;
432 }
433
434
435
436
437 public final H2AsyncClientBuilder setUserAgent(final String userAgent) {
438 this.userAgent = userAgent;
439 return this;
440 }
441
442
443
444
445 public final H2AsyncClientBuilder setDefaultHeaders(final Collection<? extends Header> defaultHeaders) {
446 this.defaultHeaders = defaultHeaders;
447 return this;
448 }
449
450
451
452
453 public final H2AsyncClientBuilder setRoutePlanner(final HttpRoutePlanner routePlanner) {
454 this.routePlanner = routePlanner;
455 return this;
456 }
457
458
459
460
461
462
463 public final H2AsyncClientBuilder setDefaultCredentialsProvider(final CredentialsProvider credentialsProvider) {
464 this.credentialsProvider = credentialsProvider;
465 return this;
466 }
467
468
469
470
471
472
473 public final H2AsyncClientBuilder setDefaultAuthSchemeRegistry(final Lookup<AuthSchemeFactory> authSchemeRegistry) {
474 this.authSchemeRegistry = authSchemeRegistry;
475 return this;
476 }
477
478
479
480
481
482
483 public final H2AsyncClientBuilder setDefaultCookieSpecRegistry(final Lookup<CookieSpecFactory> cookieSpecRegistry) {
484 this.cookieSpecRegistry = cookieSpecRegistry;
485 return this;
486 }
487
488
489
490
491
492 public final H2AsyncClientBuilder setDefaultCookieStore(final CookieStore cookieStore) {
493 this.cookieStore = cookieStore;
494 return this;
495 }
496
497
498
499
500
501
502 public final H2AsyncClientBuilder setDefaultRequestConfig(final RequestConfig config) {
503 this.defaultRequestConfig = config;
504 return this;
505 }
506
507
508
509
510
511 public final H2AsyncClientBuilder useSystemProperties() {
512 this.systemProperties = true;
513 return this;
514 }
515
516
517
518
519 public final H2AsyncClientBuilder disableRedirectHandling() {
520 redirectHandlingDisabled = true;
521 return this;
522 }
523
524
525
526
527 public final H2AsyncClientBuilder disableAutomaticRetries() {
528 automaticRetriesDisabled = true;
529 return this;
530 }
531
532
533
534
535 public final H2AsyncClientBuilder disableCookieManagement() {
536 this.cookieManagementDisabled = true;
537 return this;
538 }
539
540
541
542
543 public final H2AsyncClientBuilder disableAuthCaching() {
544 this.authCachingDisabled = true;
545 return this;
546 }
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562 public final H2AsyncClientBuilder evictIdleConnections(final TimeValue maxIdleTime) {
563 this.evictIdleConnections = true;
564 this.maxIdleTime = maxIdleTime;
565 return this;
566 }
567
568
569
570
571
572
573 @Internal
574 protected void customizeExecChain(final NamedElementChain<AsyncExecChainHandler> execChainDefinition) {
575 }
576
577
578
579
580
581
582 @Internal
583 protected void addCloseable(final Closeable closeable) {
584 if (closeable == null) {
585 return;
586 }
587 if (closeables == null) {
588 closeables = new ArrayList<>();
589 }
590 closeables.add(closeable);
591 }
592
593 public CloseableHttpAsyncClient build() {
594 final NamedElementChain<AsyncExecChainHandler> execChainDefinition = new NamedElementChain<>();
595 execChainDefinition.addLast(
596 new H2AsyncMainClientExec(),
597 ChainElement.MAIN_TRANSPORT.name());
598
599 AuthenticationStrategy targetAuthStrategyCopy = this.targetAuthStrategy;
600 if (targetAuthStrategyCopy == null) {
601 targetAuthStrategyCopy = DefaultAuthenticationStrategy.INSTANCE;
602 }
603 AuthenticationStrategy proxyAuthStrategyCopy = this.proxyAuthStrategy;
604 if (proxyAuthStrategyCopy == null) {
605 proxyAuthStrategyCopy = DefaultAuthenticationStrategy.INSTANCE;
606 }
607
608 String userAgentCopy = this.userAgent;
609 if (userAgentCopy == null) {
610 if (systemProperties) {
611 userAgentCopy = getProperty("http.agent", null);
612 }
613 if (userAgentCopy == null) {
614 userAgentCopy = VersionInfo.getSoftwareInfo("Apache-HttpAsyncClient",
615 "org.apache.hc.client5", getClass());
616 }
617 }
618
619 execChainDefinition.addFirst(
620 new AsyncConnectExec(
621 new DefaultHttpProcessor(new RequestTargetHost(), new RequestUserAgent(userAgentCopy)),
622 proxyAuthStrategyCopy),
623 ChainElement.CONNECT.name());
624
625 final HttpProcessorBuilder b = HttpProcessorBuilder.create();
626 if (requestInterceptors != null) {
627 for (final RequestInterceptorEntry entry: requestInterceptors) {
628 if (entry.postion == RequestInterceptorEntry.Postion.FIRST) {
629 b.addFirst(entry.interceptor);
630 }
631 }
632 }
633 if (responseInterceptors != null) {
634 for (final ResponseInterceptorEntry entry: responseInterceptors) {
635 if (entry.postion == ResponseInterceptorEntry.Postion.FIRST) {
636 b.addFirst(entry.interceptor);
637 }
638 }
639 }
640 b.addAll(
641 new RequestDefaultHeaders(defaultHeaders),
642 new RequestUserAgent(userAgentCopy),
643 new RequestExpectContinue());
644 if (!cookieManagementDisabled) {
645 b.add(new RequestAddCookies());
646 }
647 if (!authCachingDisabled) {
648 b.add(new RequestAuthCache());
649 }
650 if (!cookieManagementDisabled) {
651 b.add(new ResponseProcessCookies());
652 }
653 if (requestInterceptors != null) {
654 for (final RequestInterceptorEntry entry: requestInterceptors) {
655 if (entry.postion == RequestInterceptorEntry.Postion.LAST) {
656 b.addFirst(entry.interceptor);
657 }
658 }
659 }
660 if (responseInterceptors != null) {
661 for (final ResponseInterceptorEntry entry: responseInterceptors) {
662 if (entry.postion == ResponseInterceptorEntry.Postion.LAST) {
663 b.addLast(entry.interceptor);
664 }
665 }
666 }
667
668 final HttpProcessor httpProcessor = b.build();
669 execChainDefinition.addFirst(
670 new AsyncProtocolExec(httpProcessor, targetAuthStrategyCopy, proxyAuthStrategyCopy),
671 ChainElement.PROTOCOL.name());
672
673
674 if (!automaticRetriesDisabled) {
675 HttpRequestRetryStrategy retryStrategyCopy = this.retryStrategy;
676 if (retryStrategyCopy == null) {
677 retryStrategyCopy = DefaultHttpRequestRetryStrategy.INSTANCE;
678 }
679 execChainDefinition.addFirst(
680 new AsyncHttpRequestRetryExec(retryStrategyCopy),
681 ChainElement.RETRY.name());
682 }
683
684 HttpRoutePlanner routePlannerCopy = this.routePlanner;
685 if (routePlannerCopy == null) {
686 SchemePortResolver schemePortResolverCopy = this.schemePortResolver;
687 if (schemePortResolverCopy == null) {
688 schemePortResolverCopy = DefaultSchemePortResolver.INSTANCE;
689 }
690 routePlannerCopy = new DefaultRoutePlanner(schemePortResolverCopy);
691 }
692
693
694 if (!redirectHandlingDisabled) {
695 RedirectStrategy redirectStrategyCopy = this.redirectStrategy;
696 if (redirectStrategyCopy == null) {
697 redirectStrategyCopy = DefaultRedirectStrategy.INSTANCE;
698 }
699 execChainDefinition.addFirst(
700 new AsyncRedirectExec(routePlannerCopy, redirectStrategyCopy),
701 ChainElement.REDIRECT.name());
702 }
703
704 final AsyncPushConsumerRegistrymerRegistry.html#AsyncPushConsumerRegistry">AsyncPushConsumerRegistry pushConsumerRegistry = new AsyncPushConsumerRegistry();
705 final IOEventHandlerFactory ioEventHandlerFactory = new H2AsyncClientEventHandlerFactory(
706 new DefaultHttpProcessor(new H2RequestContent(), new H2RequestTargetHost(), new H2RequestConnControl()),
707 new HandlerFactory<AsyncPushConsumer>() {
708
709 @Override
710 public AsyncPushConsumer create(final HttpRequest request, final HttpContext context) throws HttpException {
711 return pushConsumerRegistry.get(request);
712 }
713
714 },
715 h2Config != null ? h2Config : H2Config.DEFAULT,
716 charCodingConfig != null ? charCodingConfig : CharCodingConfig.DEFAULT);
717 final DefaultConnectingIOReactor ioReactor = new DefaultConnectingIOReactor(
718 ioEventHandlerFactory,
719 ioReactorConfig != null ? ioReactorConfig : IOReactorConfig.DEFAULT,
720 threadFactory != null ? threadFactory : new DefaultThreadFactory("httpclient-dispatch", true),
721 LoggingIOSessionDecorator.INSTANCE,
722 LoggingExceptionCallback.INSTANCE,
723 null,
724 new Callback<IOSession>() {
725
726 @Override
727 public void execute(final IOSession ioSession) {
728 ioSession.enqueue(new ShutdownCommand(CloseMode.GRACEFUL), Command.Priority.IMMEDIATE);
729 }
730
731 });
732
733 if (execInterceptors != null) {
734 for (final ExecInterceptorEntry entry: execInterceptors) {
735 switch (entry.postion) {
736 case AFTER:
737 execChainDefinition.addAfter(entry.existing, entry.interceptor, entry.name);
738 break;
739 case BEFORE:
740 execChainDefinition.addBefore(entry.existing, entry.interceptor, entry.name);
741 break;
742 case REPLACE:
743 execChainDefinition.replace(entry.existing, entry.interceptor);
744 break;
745 case FIRST:
746 execChainDefinition.addFirst(entry.interceptor, entry.name);
747 break;
748 case LAST:
749 execChainDefinition.addLast(entry.interceptor, entry.name);
750 break;
751 }
752 }
753 }
754
755 customizeExecChain(execChainDefinition);
756
757 NamedElementChain<AsyncExecChainHandler>.Node current = execChainDefinition.getLast();
758 AsyncExecChainElement execChain = null;
759 while (current != null) {
760 execChain = new AsyncExecChainElement(current.getValue(), execChain);
761 current = current.getPrevious();
762 }
763
764 Lookup<AuthSchemeFactory> authSchemeRegistryCopy = this.authSchemeRegistry;
765 if (authSchemeRegistryCopy == null) {
766 authSchemeRegistryCopy = RegistryBuilder.<AuthSchemeFactory>create()
767 .register(StandardAuthScheme.BASIC, BasicSchemeFactory.INSTANCE)
768 .register(StandardAuthScheme.DIGEST, DigestSchemeFactory.INSTANCE)
769 .register(StandardAuthScheme.NTLM, NTLMSchemeFactory.INSTANCE)
770 .register(StandardAuthScheme.SPNEGO, SPNegoSchemeFactory.DEFAULT)
771 .register(StandardAuthScheme.KERBEROS, KerberosSchemeFactory.DEFAULT)
772 .build();
773 }
774 Lookup<CookieSpecFactory> cookieSpecRegistryCopy = this.cookieSpecRegistry;
775 if (cookieSpecRegistryCopy == null) {
776 cookieSpecRegistryCopy = CookieSpecSupport.createDefault();
777 }
778
779 CookieStore cookieStoreCopy = this.cookieStore;
780 if (cookieStoreCopy == null) {
781 cookieStoreCopy = new BasicCookieStore();
782 }
783
784 CredentialsProvider credentialsProviderCopy = this.credentialsProvider;
785 if (credentialsProviderCopy == null) {
786 if (systemProperties) {
787 credentialsProviderCopy = new SystemDefaultCredentialsProvider();
788 } else {
789 credentialsProviderCopy = new BasicCredentialsProvider();
790 }
791 }
792
793 TlsStrategy tlsStrategyCopy = this.tlsStrategy;
794 if (tlsStrategyCopy == null) {
795 if (systemProperties) {
796 tlsStrategyCopy = DefaultClientTlsStrategy.getSystemDefault();
797 } else {
798 tlsStrategyCopy = DefaultClientTlsStrategy.getDefault();
799 }
800 }
801
802 final MultihomeConnectionInitiatornInitiator.html#MultihomeConnectionInitiator">MultihomeConnectionInitiator connectionInitiator = new MultihomeConnectionInitiator(ioReactor, dnsResolver);
803 final H2ConnPool connPool = new H2ConnPool(connectionInitiator, new Resolver<HttpHost, InetSocketAddress>() {
804
805 @Override
806 public InetSocketAddress resolve(final HttpHost host) {
807 return null;
808 }
809
810 }, tlsStrategyCopy);
811
812 List<Closeable> closeablesCopy = closeables != null ? new ArrayList<>(closeables) : null;
813 if (closeablesCopy == null) {
814 closeablesCopy = new ArrayList<>(1);
815 }
816 if (evictIdleConnections) {
817 final IdleConnectionEvictornEvictor.html#IdleConnectionEvictor">IdleConnectionEvictor connectionEvictor = new IdleConnectionEvictor(connPool,
818 maxIdleTime != null ? maxIdleTime : TimeValue.ofSeconds(30L));
819 closeablesCopy.add(new Closeable() {
820
821 @Override
822 public void close() throws IOException {
823 connectionEvictor.shutdown();
824 }
825
826 });
827 connectionEvictor.start();
828 }
829 closeablesCopy.add(connPool);
830
831 return new InternalH2AsyncClient(
832 ioReactor,
833 execChain,
834 pushConsumerRegistry,
835 threadFactory != null ? threadFactory : new DefaultThreadFactory("httpclient-main", true),
836 connPool,
837 routePlannerCopy,
838 cookieSpecRegistryCopy,
839 authSchemeRegistryCopy,
840 cookieStoreCopy,
841 credentialsProviderCopy,
842 defaultRequestConfig,
843 closeablesCopy);
844 }
845
846 private static String getProperty(final String key, final String defaultValue) {
847 return AccessController.doPrivileged(new PrivilegedAction<String>() {
848 @Override
849 public String run() {
850 return System.getProperty(key, defaultValue);
851 }
852 });
853 }
854
855 static class IdleConnectionEvictor implements Closeable {
856
857 private final Thread thread;
858
859 public IdleConnectionEvictor(final H2ConnPool connPool, final TimeValue maxIdleTime) {
860 this.thread = new DefaultThreadFactory("idle-connection-evictor", true).newThread(new Runnable() {
861 @Override
862 public void run() {
863 try {
864 while (!Thread.currentThread().isInterrupted()) {
865 maxIdleTime.sleep();
866 connPool.closeIdle(maxIdleTime);
867 }
868 } catch (final InterruptedException ex) {
869 Thread.currentThread().interrupt();
870 } catch (final Exception ex) {
871 }
872
873 }
874 });
875 }
876
877 public void start() {
878 thread.start();
879 }
880
881 public void shutdown() {
882 thread.interrupt();
883 }
884
885 @Override
886 public void close() throws IOException {
887 shutdown();
888 }
889
890 }
891
892 }