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 package org.apache.http.impl.nio.client;
28
29 import java.io.IOException;
30 import java.net.URI;
31 import java.util.Queue;
32 import java.util.concurrent.ConcurrentLinkedQueue;
33 import java.util.concurrent.Future;
34
35 import org.apache.commons.logging.Log;
36 import org.apache.commons.logging.LogFactory;
37 import org.apache.http.ConnectionReuseStrategy;
38 import org.apache.http.HttpHost;
39 import org.apache.http.HttpRequest;
40 import org.apache.http.HttpRequestInterceptor;
41 import org.apache.http.HttpResponse;
42 import org.apache.http.HttpResponseInterceptor;
43 import org.apache.http.auth.AuthSchemeRegistry;
44 import org.apache.http.client.AuthenticationStrategy;
45 import org.apache.http.client.ClientProtocolException;
46 import org.apache.http.client.CookieStore;
47 import org.apache.http.client.CredentialsProvider;
48 import org.apache.http.client.RedirectStrategy;
49 import org.apache.http.client.UserTokenHandler;
50 import org.apache.http.client.methods.HttpUriRequest;
51 import org.apache.http.client.params.AuthPolicy;
52 import org.apache.http.client.params.CookiePolicy;
53 import org.apache.http.client.protocol.ClientContext;
54 import org.apache.http.client.utils.URIUtils;
55 import org.apache.http.concurrent.BasicFuture;
56 import org.apache.http.concurrent.FutureCallback;
57 import org.apache.http.conn.ConnectionKeepAliveStrategy;
58 import org.apache.http.conn.routing.HttpRoutePlanner;
59 import org.apache.http.cookie.CookieSpecRegistry;
60 import org.apache.http.impl.DefaultConnectionReuseStrategy;
61 import org.apache.http.impl.auth.BasicSchemeFactory;
62 import org.apache.http.impl.auth.DigestSchemeFactory;
63 import org.apache.http.impl.auth.KerberosSchemeFactory;
64 import org.apache.http.impl.auth.NTLMSchemeFactory;
65 import org.apache.http.impl.auth.SPNegoSchemeFactory;
66 import org.apache.http.impl.client.BasicCookieStore;
67 import org.apache.http.impl.client.BasicCredentialsProvider;
68 import org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy;
69 import org.apache.http.impl.client.DefaultRedirectStrategy;
70 import org.apache.http.impl.client.DefaultUserTokenHandler;
71 import org.apache.http.impl.client.ProxyAuthenticationStrategy;
72 import org.apache.http.impl.client.TargetAuthenticationStrategy;
73 import org.apache.http.impl.cookie.BestMatchSpecFactory;
74 import org.apache.http.impl.cookie.BrowserCompatSpecFactory;
75 import org.apache.http.impl.cookie.IgnoreSpecFactory;
76 import org.apache.http.impl.cookie.NetscapeDraftSpecFactory;
77 import org.apache.http.impl.cookie.RFC2109SpecFactory;
78 import org.apache.http.impl.cookie.RFC2965SpecFactory;
79 import org.apache.http.impl.nio.DefaultHttpClientIODispatch;
80 import org.apache.http.impl.nio.conn.DefaultHttpAsyncRoutePlanner;
81 import org.apache.http.impl.nio.conn.PoolingClientAsyncConnectionManager;
82 import org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor;
83 import org.apache.http.impl.nio.reactor.IOReactorConfig;
84 import org.apache.http.nio.client.HttpAsyncClient;
85 import org.apache.http.nio.client.methods.HttpAsyncMethods;
86 import org.apache.http.nio.conn.ClientAsyncConnectionManager;
87 import org.apache.http.nio.protocol.HttpAsyncRequestExecutionHandler;
88 import org.apache.http.nio.protocol.HttpAsyncRequestExecutor;
89 import org.apache.http.nio.protocol.HttpAsyncRequestProducer;
90 import org.apache.http.nio.protocol.HttpAsyncResponseConsumer;
91 import org.apache.http.nio.reactor.IOEventDispatch;
92 import org.apache.http.nio.reactor.IOReactorException;
93 import org.apache.http.nio.reactor.IOReactorStatus;
94 import org.apache.http.params.HttpParams;
95 import org.apache.http.protocol.BasicHttpContext;
96 import org.apache.http.protocol.BasicHttpProcessor;
97 import org.apache.http.protocol.DefaultedHttpContext;
98 import org.apache.http.protocol.HttpContext;
99 import org.apache.http.protocol.HttpProcessor;
100 import org.apache.http.protocol.ImmutableHttpProcessor;
101
102 @Deprecated
103 public abstract class AbstractHttpAsyncClient implements HttpAsyncClient {
104
105 private final Log log = LogFactory.getLog(getClass());
106 private final ClientAsyncConnectionManager connmgr;
107 private final Queue<HttpAsyncRequestExecutionHandler<?>> queue;
108
109 private Thread reactorThread;
110 private BasicHttpProcessor mutableProcessor;
111 private ImmutableHttpProcessor protocolProcessor;
112 private ConnectionReuseStrategy reuseStrategy;
113 private ConnectionKeepAliveStrategy keepAliveStrategy;
114 private RedirectStrategy redirectStrategy;
115 private CookieSpecRegistry supportedCookieSpecs;
116 private CookieStore cookieStore;
117 private AuthSchemeRegistry supportedAuthSchemes;
118 private AuthenticationStrategy targetAuthStrategy;
119 private AuthenticationStrategy proxyAuthStrategy;
120 private CredentialsProvider credsProvider;
121 private HttpRoutePlanner routePlanner;
122 private UserTokenHandler userTokenHandler;
123 private HttpParams params;
124
125 private volatile boolean terminated;
126
127 protected AbstractHttpAsyncClient(final ClientAsyncConnectionManager connmgr) {
128 super();
129 this.connmgr = connmgr;
130 this.queue = new ConcurrentLinkedQueue<HttpAsyncRequestExecutionHandler<?>>();
131 }
132
133 protected AbstractHttpAsyncClient(final IOReactorConfig config) throws IOReactorException {
134 super();
135 final DefaultConnectingIOReactor defaultioreactor = new DefaultConnectingIOReactor(config);
136 defaultioreactor.setExceptionHandler(new InternalIOReactorExceptionHandler(this.log));
137 this.connmgr = new PoolingClientAsyncConnectionManager(defaultioreactor);
138 this.queue = new ConcurrentLinkedQueue<HttpAsyncRequestExecutionHandler<?>>();
139 }
140
141 protected abstract HttpParams createHttpParams();
142
143 protected abstract BasicHttpProcessor createHttpProcessor();
144
145 protected HttpContext createHttpContext() {
146 final HttpContext context = new BasicHttpContext();
147 context.setAttribute(
148 ClientContext.SCHEME_REGISTRY,
149 getConnectionManager().getSchemeRegistry());
150 context.setAttribute(
151 ClientContext.AUTHSCHEME_REGISTRY,
152 getAuthSchemes());
153 context.setAttribute(
154 ClientContext.COOKIESPEC_REGISTRY,
155 getCookieSpecs());
156 context.setAttribute(
157 ClientContext.COOKIE_STORE,
158 getCookieStore());
159 context.setAttribute(
160 ClientContext.CREDS_PROVIDER,
161 getCredentialsProvider());
162 return context;
163 }
164
165 protected ConnectionReuseStrategy createConnectionReuseStrategy() {
166 return new DefaultConnectionReuseStrategy();
167 }
168
169 protected ConnectionKeepAliveStrategy createConnectionKeepAliveStrategy() {
170 return new DefaultConnectionKeepAliveStrategy();
171 }
172
173 protected AuthSchemeRegistry createAuthSchemeRegistry() {
174 final AuthSchemeRegistry registry = new AuthSchemeRegistry();
175 registry.register(
176 AuthPolicy.BASIC,
177 new BasicSchemeFactory());
178 registry.register(
179 AuthPolicy.DIGEST,
180 new DigestSchemeFactory());
181 registry.register(
182 AuthPolicy.NTLM,
183 new NTLMSchemeFactory());
184 registry.register(
185 AuthPolicy.SPNEGO,
186 new SPNegoSchemeFactory());
187 registry.register(
188 AuthPolicy.KERBEROS,
189 new KerberosSchemeFactory());
190 return registry;
191 }
192
193 protected CookieSpecRegistry createCookieSpecRegistry() {
194 final CookieSpecRegistry registry = new CookieSpecRegistry();
195 registry.register(
196 CookiePolicy.BEST_MATCH,
197 new BestMatchSpecFactory());
198 registry.register(
199 CookiePolicy.BROWSER_COMPATIBILITY,
200 new BrowserCompatSpecFactory());
201 registry.register(
202 CookiePolicy.NETSCAPE,
203 new NetscapeDraftSpecFactory());
204 registry.register(
205 CookiePolicy.RFC_2109,
206 new RFC2109SpecFactory());
207 registry.register(
208 CookiePolicy.RFC_2965,
209 new RFC2965SpecFactory());
210 registry.register(
211 CookiePolicy.IGNORE_COOKIES,
212 new IgnoreSpecFactory());
213 return registry;
214 }
215
216 protected AuthenticationStrategy createTargetAuthenticationStrategy() {
217 return new TargetAuthenticationStrategy();
218 }
219
220 protected AuthenticationStrategy createProxyAuthenticationStrategy() {
221 return new ProxyAuthenticationStrategy();
222 }
223
224 protected CookieStore createCookieStore() {
225 return new BasicCookieStore();
226 }
227
228 protected CredentialsProvider createCredentialsProvider() {
229 return new BasicCredentialsProvider();
230 }
231
232 protected HttpRoutePlanner createHttpRoutePlanner() {
233 return new DefaultHttpAsyncRoutePlanner(getConnectionManager().getSchemeRegistry());
234 }
235
236 protected UserTokenHandler createUserTokenHandler() {
237 return new DefaultUserTokenHandler();
238 }
239
240 public synchronized final HttpParams getParams() {
241 if (this.params == null) {
242 this.params = createHttpParams();
243 }
244 return this.params;
245 }
246
247 public synchronized void setParams(final HttpParams params) {
248 this.params = params;
249 }
250
251 public synchronized ClientAsyncConnectionManager getConnectionManager() {
252 return this.connmgr;
253 }
254
255 public synchronized final ConnectionReuseStrategy getConnectionReuseStrategy() {
256 if (this.reuseStrategy == null) {
257 this.reuseStrategy = createConnectionReuseStrategy();
258 }
259 return this.reuseStrategy;
260 }
261
262 public synchronized void setReuseStrategy(final ConnectionReuseStrategy reuseStrategy) {
263 this.reuseStrategy = reuseStrategy;
264 }
265
266 public synchronized final ConnectionKeepAliveStrategy getConnectionKeepAliveStrategy() {
267 if (this.keepAliveStrategy == null) {
268 this.keepAliveStrategy = createConnectionKeepAliveStrategy();
269 }
270 return this.keepAliveStrategy;
271 }
272
273 public synchronized void setKeepAliveStrategy(final ConnectionKeepAliveStrategy keepAliveStrategy) {
274 this.keepAliveStrategy = keepAliveStrategy;
275 }
276
277 public synchronized final RedirectStrategy getRedirectStrategy() {
278 if (this.redirectStrategy == null) {
279 this.redirectStrategy = new DefaultRedirectStrategy();
280 }
281 return this.redirectStrategy;
282 }
283
284 public synchronized void setRedirectStrategy(final RedirectStrategy redirectStrategy) {
285 this.redirectStrategy = redirectStrategy;
286 }
287
288 public synchronized final AuthSchemeRegistry getAuthSchemes() {
289 if (this.supportedAuthSchemes == null) {
290 this.supportedAuthSchemes = createAuthSchemeRegistry();
291 }
292 return this.supportedAuthSchemes;
293 }
294
295 public synchronized void setAuthSchemes(final AuthSchemeRegistry authSchemeRegistry) {
296 this.supportedAuthSchemes = authSchemeRegistry;
297 }
298
299 public synchronized final CookieSpecRegistry getCookieSpecs() {
300 if (this.supportedCookieSpecs == null) {
301 this.supportedCookieSpecs = createCookieSpecRegistry();
302 }
303 return this.supportedCookieSpecs;
304 }
305
306 public synchronized void setCookieSpecs(final CookieSpecRegistry cookieSpecRegistry) {
307 this.supportedCookieSpecs = cookieSpecRegistry;
308 }
309
310 public synchronized final AuthenticationStrategy getTargetAuthenticationStrategy() {
311 if (this.targetAuthStrategy == null) {
312 this.targetAuthStrategy = createTargetAuthenticationStrategy();
313 }
314 return this.targetAuthStrategy;
315 }
316
317 public synchronized void setTargetAuthenticationStrategy(
318 final AuthenticationStrategy targetAuthStrategy) {
319 this.targetAuthStrategy = targetAuthStrategy;
320 }
321
322 public synchronized final AuthenticationStrategy getProxyAuthenticationStrategy() {
323 if (this.proxyAuthStrategy == null) {
324 this.proxyAuthStrategy = createProxyAuthenticationStrategy();
325 }
326 return this.proxyAuthStrategy;
327 }
328
329 public synchronized void setProxyAuthenticationStrategy(
330 final AuthenticationStrategy proxyAuthStrategy) {
331 this.proxyAuthStrategy = proxyAuthStrategy;
332 }
333
334 public synchronized final CookieStore getCookieStore() {
335 if (this.cookieStore == null) {
336 this.cookieStore = createCookieStore();
337 }
338 return this.cookieStore;
339 }
340
341 public synchronized void setCookieStore(final CookieStore cookieStore) {
342 this.cookieStore = cookieStore;
343 }
344
345 public synchronized final CredentialsProvider getCredentialsProvider() {
346 if (this.credsProvider == null) {
347 this.credsProvider = createCredentialsProvider();
348 }
349 return this.credsProvider;
350 }
351
352 public synchronized void setCredentialsProvider(final CredentialsProvider credsProvider) {
353 this.credsProvider = credsProvider;
354 }
355
356 public synchronized final HttpRoutePlanner getRoutePlanner() {
357 if (this.routePlanner == null) {
358 this.routePlanner = createHttpRoutePlanner();
359 }
360 return this.routePlanner;
361 }
362
363 public synchronized void setRoutePlanner(final HttpRoutePlanner routePlanner) {
364 this.routePlanner = routePlanner;
365 }
366
367 public synchronized final UserTokenHandler getUserTokenHandler() {
368 if (this.userTokenHandler == null) {
369 this.userTokenHandler = createUserTokenHandler();
370 }
371 return this.userTokenHandler;
372 }
373
374
375 public synchronized void setUserTokenHandler(final UserTokenHandler userTokenHandler) {
376 this.userTokenHandler = userTokenHandler;
377 }
378
379 protected synchronized final BasicHttpProcessor getHttpProcessor() {
380 if (this.mutableProcessor == null) {
381 this.mutableProcessor = createHttpProcessor();
382 }
383 return this.mutableProcessor;
384 }
385
386 private synchronized final HttpProcessor getProtocolProcessor() {
387 if (this.protocolProcessor == null) {
388
389 final BasicHttpProcessor proc = getHttpProcessor();
390
391 final int reqc = proc.getRequestInterceptorCount();
392 final HttpRequestInterceptor[] reqinterceptors = new HttpRequestInterceptor[reqc];
393 for (int i = 0; i < reqc; i++) {
394 reqinterceptors[i] = proc.getRequestInterceptor(i);
395 }
396 final int resc = proc.getResponseInterceptorCount();
397 final HttpResponseInterceptor[] resinterceptors = new HttpResponseInterceptor[resc];
398 for (int i = 0; i < resc; i++) {
399 resinterceptors[i] = proc.getResponseInterceptor(i);
400 }
401 this.protocolProcessor = new ImmutableHttpProcessor(reqinterceptors, resinterceptors);
402 }
403 return this.protocolProcessor;
404 }
405
406 public synchronized int getResponseInterceptorCount() {
407 return getHttpProcessor().getResponseInterceptorCount();
408 }
409
410 public synchronized HttpResponseInterceptor getResponseInterceptor(final int index) {
411 return getHttpProcessor().getResponseInterceptor(index);
412 }
413
414 public synchronized HttpRequestInterceptor getRequestInterceptor(final int index) {
415 return getHttpProcessor().getRequestInterceptor(index);
416 }
417
418 public synchronized int getRequestInterceptorCount() {
419 return getHttpProcessor().getRequestInterceptorCount();
420 }
421
422 public synchronized void addResponseInterceptor(final HttpResponseInterceptor itcp) {
423 getHttpProcessor().addInterceptor(itcp);
424 this.protocolProcessor = null;
425 }
426
427 public synchronized void addResponseInterceptor(final HttpResponseInterceptor itcp, final int index) {
428 getHttpProcessor().addInterceptor(itcp, index);
429 this.protocolProcessor = null;
430 }
431
432 public synchronized void clearResponseInterceptors() {
433 getHttpProcessor().clearResponseInterceptors();
434 this.protocolProcessor = null;
435 }
436
437 public synchronized void removeResponseInterceptorByClass(final Class<? extends HttpResponseInterceptor> clazz) {
438 getHttpProcessor().removeResponseInterceptorByClass(clazz);
439 this.protocolProcessor = null;
440 }
441
442 public synchronized void addRequestInterceptor(final HttpRequestInterceptor itcp) {
443 getHttpProcessor().addInterceptor(itcp);
444 this.protocolProcessor = null;
445 }
446
447 public synchronized void addRequestInterceptor(final HttpRequestInterceptor itcp, final int index) {
448 getHttpProcessor().addInterceptor(itcp, index);
449 this.protocolProcessor = null;
450 }
451
452 public synchronized void clearRequestInterceptors() {
453 getHttpProcessor().clearRequestInterceptors();
454 this.protocolProcessor = null;
455 }
456
457 public synchronized void removeRequestInterceptorByClass(final Class<? extends HttpRequestInterceptor> clazz) {
458 getHttpProcessor().removeRequestInterceptorByClass(clazz);
459 this.protocolProcessor = null;
460 }
461
462 private void doExecute() {
463 final InternalRequestExecutor handler = new InternalRequestExecutor(this.log, new HttpAsyncRequestExecutor());
464 try {
465 final IOEventDispatch ioEventDispatch = new DefaultHttpClientIODispatch(handler, getParams());
466 this.connmgr.execute(ioEventDispatch);
467 } catch (final Exception ex) {
468 this.log.error("I/O reactor terminated abnormally", ex);
469 } finally {
470 this.terminated = true;
471 while (!this.queue.isEmpty()) {
472 final HttpAsyncRequestExecutionHandler<?> exchangeHandler = this.queue.remove();
473 exchangeHandler.cancel();
474 }
475 }
476 }
477
478 public IOReactorStatus getStatus() {
479 return this.connmgr.getStatus();
480 }
481
482 public synchronized void start() {
483 this.reactorThread = new Thread() {
484
485 @Override
486 public void run() {
487 doExecute();
488 }
489
490 };
491 this.reactorThread.start();
492 }
493
494 public void shutdown() throws InterruptedException {
495 try {
496 this.connmgr.shutdown(5000);
497 } catch (final IOException ex) {
498 this.log.error("I/O error shutting down", ex);
499 }
500 if (this.reactorThread != null) {
501 this.reactorThread.join();
502 }
503 }
504
505 @Override
506 public <T> Future<T> execute(
507 final HttpAsyncRequestProducer requestProducer,
508 final HttpAsyncResponseConsumer<T> responseConsumer,
509 final HttpContext context,
510 final FutureCallback<T> callback) {
511 if (this.terminated) {
512 throw new IllegalStateException("Client has been shut down");
513 }
514 final BasicFuture<T> future = new BasicFuture<T>(callback);
515 final ResultCallback<T> resultCallback = new DefaultResultCallback<T>(future, this.queue);
516 final DefaultAsyncRequestDirector<T> httpexchange;
517 synchronized (this) {
518 final HttpContext defaultContext = createHttpContext();
519 final HttpContext execContext;
520 if (context == null) {
521 execContext = defaultContext;
522 } else {
523 execContext = new DefaultedHttpContext(context, defaultContext);
524 }
525 httpexchange = new DefaultAsyncRequestDirector<T>(
526 this.log,
527 requestProducer,
528 responseConsumer,
529 execContext,
530 resultCallback,
531 this.connmgr,
532 getProtocolProcessor(),
533 getRoutePlanner(),
534 getConnectionReuseStrategy(),
535 getConnectionKeepAliveStrategy(),
536 getRedirectStrategy(),
537 getTargetAuthenticationStrategy(),
538 getProxyAuthenticationStrategy(),
539 getUserTokenHandler(),
540 getParams());
541 }
542 this.queue.add(httpexchange);
543 httpexchange.start();
544 return future;
545 }
546
547 @Override
548 public <T> Future<T> execute(
549 final HttpAsyncRequestProducer requestProducer,
550 final HttpAsyncResponseConsumer<T> responseConsumer,
551 final FutureCallback<T> callback) {
552 return execute(requestProducer, responseConsumer, new BasicHttpContext(), callback);
553 }
554
555 @Override
556 public Future<HttpResponse> execute(
557 final HttpHost target, final HttpRequest request, final HttpContext context,
558 final FutureCallback<HttpResponse> callback) {
559 return execute(
560 HttpAsyncMethods.create(target, request),
561 HttpAsyncMethods.createConsumer(),
562 context, callback);
563 }
564
565 @Override
566 public Future<HttpResponse> execute(
567 final HttpHost target, final HttpRequest request,
568 final FutureCallback<HttpResponse> callback) {
569 return execute(target, request, new BasicHttpContext(), callback);
570 }
571
572 @Override
573 public Future<HttpResponse> execute(
574 final HttpUriRequest request,
575 final FutureCallback<HttpResponse> callback) {
576 return execute(request, new BasicHttpContext(), callback);
577 }
578
579 @Override
580 public Future<HttpResponse> execute(
581 final HttpUriRequest request,
582 final HttpContext context,
583 final FutureCallback<HttpResponse> callback) {
584 final HttpHost target;
585 try {
586 target = determineTarget(request);
587 } catch (final ClientProtocolException ex) {
588 final BasicFuture<HttpResponse> future = new BasicFuture<HttpResponse>(callback);
589 future.failed(ex);
590 return future;
591 }
592 return execute(target, request, context, callback);
593 }
594
595 private HttpHost determineTarget(final HttpUriRequest request) throws ClientProtocolException {
596
597
598 HttpHost target = null;
599
600 final URI requestURI = request.getURI();
601 if (requestURI.isAbsolute()) {
602 target = URIUtils.extractHost(requestURI);
603 if (target == null) {
604 throw new ClientProtocolException(
605 "URI does not specify a valid host name: " + requestURI);
606 }
607 }
608 return target;
609 }
610
611 }