Update upstream source from tag 'upstream/4.1.5'
Update to upstream version '4.1.5'
with Debian dir d3cfd87bbd0a6b1cbc3dc4c04be63f7d0e456aa4
Jérôme Charaoui
1 year, 6 months ago
0 | 0 | Apache HttpComponents AsyncClient |
1 | Copyright 2010-2017 The Apache Software Foundation | |
1 | Copyright 2010-2021 The Apache Software Foundation | |
2 | 2 | |
3 | 3 | This product includes software developed at |
4 | 4 | The Apache Software Foundation (http://www.apache.org/). |
0 | Release 4.1.5 | |
1 | ------------------- | |
2 | ||
3 | This is a maintenance release that fixes a number of issues discovered since 4.1.4. | |
4 | ||
5 | Changelog | |
6 | ------------------- | |
7 | ||
8 | * Upgraded HttpCore to version 4.4.15 and HttpClient to version 4.5.13. | |
9 | Contributed by Oleg Kalnichevski <olegk at apache.org> | |
10 | ||
11 | * HTTPASYNC-160: HttpAsyncClient in INACTIVE or STOPPED state throws a IllegalStateException | |
12 | causing the current thread to terminate. | |
13 | Contributed by Oleg Kalnichevski <olegk at apache.org> | |
14 | ||
15 | * HTTPASYNC-156: Possible deadlock condition in case of concurrent connection request | |
16 | completion and cancellation. | |
17 | Contributed by Oleg Kalnichevski <olegk at apache.org> | |
18 | ||
19 | * HTTPASYNC-155: Runtime exception in AbstractClientExchangeHandler can cause the I/O reactor | |
20 | to shut down. | |
21 | Contributed by Oleg Kalnichevski <olegk at apache.org> | |
22 | ||
23 | * Added connection time to live parameter to HttpAsyncClientBuilder. | |
24 | Contributed by Oleg Kalnichevski <olegk at apache.org> | |
25 | ||
26 | * Bug fix: PipeliningClientExchangeHandlerImpl to fail result future in case of an execution | |
27 | failure. | |
28 | Contributed by Oleg Kalnichevski <olegk at apache.org> | |
29 | ||
30 | * HTTPASYNC-152: InternalIODispatch#createConnection to throw CancelledKeyException instead | |
31 | of IllegalStateException. | |
32 | Contributed by Oleg Kalnichevski <olegk at apache.org> | |
33 | ||
34 | ||
0 | 35 | Release 4.1.4 |
1 | 36 | ------------------- |
2 | 37 |
27 | 27 | <parent> |
28 | 28 | <groupId>org.apache.httpcomponents</groupId> |
29 | 29 | <artifactId>httpcomponents-asyncclient</artifactId> |
30 | <version>4.1.4</version> | |
30 | <version>4.1.5</version> | |
31 | 31 | </parent> |
32 | 32 | <artifactId>httpasyncclient</artifactId> |
33 | 33 | <name>Apache HttpAsyncClient</name> |
136 | 136 | <artifactId>maven-javadoc-plugin</artifactId> |
137 | 137 | <version>${hc.javadoc.version}</version> |
138 | 138 | <configuration> |
139 | <!-- reduce console output. Can override with -Dquiet=false --> | |
140 | <quiet>true</quiet> | |
139 | 141 | <source>${maven.compiler.source}</source> |
140 | 142 | <links> |
141 | <link>http://download.oracle.com/javase/1.5.0/docs/api/</link> | |
142 | <link>http://hc.apache.org/httpcomponents-core-ga/httpcore/apidocs/</link> | |
143 | <link>http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/</link> | |
143 | <link>http://docs.oracle.com/javase/6/docs/api/</link> | |
144 | <link>https://hc.apache.org/httpcomponents-core-4.4.x/current/httpcore/apidocs/</link> | |
145 | <link>https://hc.apache.org/httpcomponents-client-4.5.x/current/httpclient/apidocs/</link> | |
144 | 146 | </links> |
145 | 147 | </configuration> |
146 | 148 | <reportSets> |
154 | 156 | |
155 | 157 | <plugin> |
156 | 158 | <artifactId>maven-project-info-reports-plugin</artifactId> |
157 | <version>${hc.project-info.version}</version> | |
158 | 159 | <inherited>false</inherited> |
159 | 160 | <reportSets> |
160 | 161 | <reportSet> |
169 | 170 | |
170 | 171 | <plugin> |
171 | 172 | <artifactId>maven-jxr-plugin</artifactId> |
172 | <version>${hc.jxr.version}</version> | |
173 | 173 | </plugin> |
174 | 174 | |
175 | 175 | <plugin> |
176 | 176 | <artifactId>maven-surefire-report-plugin</artifactId> |
177 | <version>${hc.surefire-report.version}</version> | |
178 | 177 | </plugin> |
179 | 178 | |
180 | 179 | </plugins> |
181 | 180 | </reporting> |
182 | 181 | |
183 | </project> | |
182 | </project>⏎ |
+1
-1
70 | 70 | } |
71 | 71 | |
72 | 72 | @Override |
73 | protected void onCharReceived(final CharBuffer buf, final IOControl ioctrl) throws IOException { | |
73 | protected void onCharReceived(final CharBuffer buf, final IOControl ioControl) throws IOException { | |
74 | 74 | while (buf.hasRemaining()) { |
75 | 75 | System.out.print(buf.get()); |
76 | 76 | } |
+1
-1
112 | 112 | } |
113 | 113 | |
114 | 114 | @Override |
115 | protected void onCharReceived(final CharBuffer buf, final IOControl ioctrl) throws IOException { | |
115 | protected void onCharReceived(final CharBuffer buf, final IOControl ioControl) throws IOException { | |
116 | 116 | while (buf.hasRemaining()) { |
117 | 117 | System.out.print(buf.get()); |
118 | 118 | } |
97 | 97 | } |
98 | 98 | |
99 | 99 | @Override |
100 | protected void onCharReceived(final CharBuffer buf, final IOControl ioctrl) throws IOException { | |
100 | protected void onCharReceived(final CharBuffer buf, final IOControl ioControl) throws IOException { | |
101 | 101 | // Do something useful |
102 | 102 | } |
103 | 103 |
+6
-0
35 | 35 | import org.apache.commons.logging.Log; |
36 | 36 | import org.apache.http.ConnectionClosedException; |
37 | 37 | import org.apache.http.ConnectionReuseStrategy; |
38 | import org.apache.http.HttpException; | |
38 | 39 | import org.apache.http.HttpHost; |
39 | 40 | import org.apache.http.HttpResponse; |
40 | 41 | import org.apache.http.client.config.RequestConfig; |
44 | 45 | import org.apache.http.conn.ConnectionKeepAliveStrategy; |
45 | 46 | import org.apache.http.conn.routing.HttpRoute; |
46 | 47 | import org.apache.http.conn.routing.RouteTracker; |
48 | import org.apache.http.impl.conn.ConnectionShutdownException; | |
47 | 49 | import org.apache.http.nio.NHttpClientConnection; |
48 | 50 | import org.apache.http.nio.conn.NHttpClientConnectionManager; |
49 | 51 | import org.apache.http.nio.protocol.HttpAsyncClientExchangeHandler; |
333 | 335 | managedConn.requestOutput(); |
334 | 336 | } |
335 | 337 | } |
338 | } catch (final ConnectionShutdownException runex) { | |
339 | failed(runex); | |
336 | 340 | } catch (final RuntimeException runex) { |
337 | 341 | failed(runex); |
338 | 342 | throw runex; |
399 | 403 | })); |
400 | 404 | } |
401 | 405 | |
406 | abstract void start() throws HttpException, IOException; | |
407 | ||
402 | 408 | abstract void releaseResources(); |
403 | 409 | |
404 | 410 | abstract void executionFailed(final Exception ex); |
+12
-7
26 | 26 | package org.apache.http.impl.nio.client; |
27 | 27 | |
28 | 28 | import java.io.IOException; |
29 | import java.util.concurrent.CancellationException; | |
29 | 30 | import java.util.concurrent.ThreadFactory; |
30 | 31 | import java.util.concurrent.atomic.AtomicReference; |
31 | 32 | |
34 | 35 | import org.apache.http.nio.NHttpClientEventHandler; |
35 | 36 | import org.apache.http.nio.conn.NHttpClientConnectionManager; |
36 | 37 | import org.apache.http.nio.reactor.IOEventDispatch; |
37 | import org.apache.http.util.Asserts; | |
38 | 38 | |
39 | 39 | abstract class CloseableHttpAsyncClientBase extends CloseableHttpPipeliningClient { |
40 | 40 | |
84 | 84 | } |
85 | 85 | } |
86 | 86 | |
87 | protected void ensureRunning() { | |
88 | final Status currentStatus = this.status.get(); | |
89 | Asserts.check(currentStatus == Status.ACTIVE, "Request cannot be executed; " + | |
90 | "I/O reactor status: %s", currentStatus); | |
91 | } | |
92 | ||
93 | 87 | @Override |
94 | 88 | public void close() { |
95 | 89 | if (this.status.compareAndSet(Status.ACTIVE, Status.STOPPED)) { |
113 | 107 | return this.status.get() == Status.ACTIVE; |
114 | 108 | } |
115 | 109 | |
110 | final void execute(final AbstractClientExchangeHandler handler) { | |
111 | try { | |
112 | if (!isRunning()) { | |
113 | throw new CancellationException("Request execution cancelled"); | |
114 | } | |
115 | handler.start(); | |
116 | } catch (final Exception ex) { | |
117 | handler.failed(ex); | |
118 | } | |
119 | } | |
120 | ||
116 | 121 | } |
+5
-4
117 | 117 | return cancelled; |
118 | 118 | } |
119 | 119 | |
120 | @Override | |
120 | 121 | public void start() throws HttpException, IOException { |
121 | 122 | final HttpHost target = this.requestProducer.getTarget(); |
122 | 123 | final HttpRequest original = this.requestProducer.generateRequest(); |
135 | 136 | |
136 | 137 | @Override |
137 | 138 | public void produceContent( |
138 | final ContentEncoder encoder, final IOControl ioctrl) throws IOException { | |
139 | this.exec.produceContent(this.state, encoder, ioctrl); | |
139 | final ContentEncoder encoder, final IOControl ioControl) throws IOException { | |
140 | this.exec.produceContent(this.state, encoder, ioControl); | |
140 | 141 | } |
141 | 142 | |
142 | 143 | @Override |
152 | 153 | |
153 | 154 | @Override |
154 | 155 | public void consumeContent( |
155 | final ContentDecoder decoder, final IOControl ioctrl) throws IOException { | |
156 | this.exec.consumeContent(this.state, decoder, ioctrl); | |
156 | final ContentDecoder decoder, final IOControl ioControl) throws IOException { | |
157 | this.exec.consumeContent(this.state, decoder, ioControl); | |
157 | 158 | if (!decoder.isCompleted() && this.responseConsumer.isDone()) { |
158 | 159 | markConnectionNonReusable(); |
159 | 160 | try { |
+27
-3
31 | 31 | import java.util.LinkedList; |
32 | 32 | import java.util.concurrent.Executors; |
33 | 33 | import java.util.concurrent.ThreadFactory; |
34 | import java.util.concurrent.TimeUnit; | |
34 | 35 | |
35 | 36 | import javax.net.ssl.HostnameVerifier; |
36 | 37 | import javax.net.ssl.SSLContext; |
84 | 85 | import org.apache.http.impl.conn.DefaultProxyRoutePlanner; |
85 | 86 | import org.apache.http.impl.conn.DefaultRoutePlanner; |
86 | 87 | import org.apache.http.impl.conn.DefaultSchemePortResolver; |
88 | import org.apache.http.impl.conn.SystemDefaultDnsResolver; | |
87 | 89 | import org.apache.http.impl.conn.SystemDefaultRoutePlanner; |
88 | 90 | import org.apache.http.impl.cookie.DefaultCookieSpecProvider; |
89 | 91 | import org.apache.http.impl.cookie.IgnoreSpecProvider; |
90 | 92 | import org.apache.http.impl.cookie.NetscapeDraftSpecProvider; |
91 | 93 | import org.apache.http.impl.cookie.RFC6265CookieSpecProvider; |
94 | import org.apache.http.impl.nio.conn.ManagedNHttpClientConnectionFactory; | |
92 | 95 | import org.apache.http.impl.nio.conn.PoolingNHttpClientConnectionManager; |
93 | 96 | import org.apache.http.impl.nio.reactor.IOReactorConfig; |
94 | 97 | import org.apache.http.nio.NHttpClientEventHandler; |
186 | 189 | |
187 | 190 | private int maxConnTotal = 0; |
188 | 191 | private int maxConnPerRoute = 0; |
192 | private long connTimeToLive = -1; | |
193 | private TimeUnit connTimeToLiveTimeUnit = TimeUnit.MILLISECONDS; | |
189 | 194 | |
190 | 195 | public static HttpAsyncClientBuilder create() { |
191 | 196 | return new HttpAsyncClientBuilder(); |
265 | 270 | */ |
266 | 271 | public final HttpAsyncClientBuilder setMaxConnPerRoute(final int maxConnPerRoute) { |
267 | 272 | this.maxConnPerRoute = maxConnPerRoute; |
273 | return this; | |
274 | } | |
275 | ||
276 | /** | |
277 | * Sets maximum time to live for persistent connections | |
278 | * <p> | |
279 | * Please note this value can be overridden by the {@link #setConnectionManager( | |
280 | * org.apache.http.nio.conn.NHttpClientConnectionManager)} method. | |
281 | * | |
282 | * @since 4.1 | |
283 | */ | |
284 | public final HttpAsyncClientBuilder setConnectionTimeToLive(final long connTimeToLive, final TimeUnit connTimeToLiveTimeUnit) { | |
285 | this.connTimeToLive = connTimeToLive; | |
286 | this.connTimeToLiveTimeUnit = connTimeToLiveTimeUnit; | |
268 | 287 | return this; |
269 | 288 | } |
270 | 289 | |
663 | 682 | sslStrategy = new SSLIOSessionStrategy( |
664 | 683 | sslcontext, supportedProtocols, supportedCipherSuites, hostnameVerifier); |
665 | 684 | } |
666 | final ConnectingIOReactor ioreactor = IOReactorUtils.create( | |
685 | final ConnectingIOReactor ioReactor = IOReactorUtils.create( | |
667 | 686 | defaultIOReactorConfig != null ? defaultIOReactorConfig : IOReactorConfig.DEFAULT, threadFactory); |
668 | 687 | final PoolingNHttpClientConnectionManager poolingmgr = new PoolingNHttpClientConnectionManager( |
669 | ioreactor, | |
688 | ioReactor, | |
689 | ManagedNHttpClientConnectionFactory.INSTANCE, | |
670 | 690 | RegistryBuilder.<SchemeIOSessionStrategy>create() |
671 | 691 | .register("http", NoopIOSessionStrategy.INSTANCE) |
672 | 692 | .register("https", sslStrategy) |
673 | .build()); | |
693 | .build(), | |
694 | DefaultSchemePortResolver.INSTANCE, | |
695 | SystemDefaultDnsResolver.INSTANCE, | |
696 | connTimeToLive, | |
697 | connTimeToLiveTimeUnit); | |
674 | 698 | if (defaultConnectionConfig != null) { |
675 | 699 | poolingmgr.setDefaultConnectionConfig(defaultConnectionConfig); |
676 | 700 | } |
85 | 85 | * aspects only. This client does not support HTTP state management, authentication |
86 | 86 | * and automatic redirects. |
87 | 87 | */ |
88 | public static CloseableHttpAsyncClient createMinimal(final ConnectingIOReactor ioreactor) { | |
89 | Args.notNull(ioreactor, "I/O reactor"); | |
90 | return createMinimal(new PoolingNHttpClientConnectionManager(ioreactor), false); | |
88 | public static CloseableHttpAsyncClient createMinimal(final ConnectingIOReactor ioReactor) { | |
89 | Args.notNull(ioReactor, "I/O reactor"); | |
90 | return createMinimal(new PoolingNHttpClientConnectionManager(ioReactor), false); | |
91 | 91 | } |
92 | 92 | |
93 | 93 | /** |
137 | 137 | * |
138 | 138 | * @since 4.1 |
139 | 139 | */ |
140 | public static CloseableHttpPipeliningClient createPipelining(final ConnectingIOReactor ioreactor) { | |
141 | return createPipelining(new PoolingNHttpClientConnectionManager(ioreactor), false); | |
140 | public static CloseableHttpPipeliningClient createPipelining(final ConnectingIOReactor ioReactor) { | |
141 | return createPipelining(new PoolingNHttpClientConnectionManager(ioReactor), false); | |
142 | 142 | } |
143 | 143 | |
144 | 144 | /** |
+2
-2
50 | 50 | void produceContent( |
51 | 51 | InternalState state, |
52 | 52 | ContentEncoder encoder, |
53 | IOControl ioctrl) throws IOException; | |
53 | IOControl ioControl) throws IOException; | |
54 | 54 | |
55 | 55 | void requestCompleted( |
56 | 56 | InternalState state, |
64 | 64 | void consumeContent( |
65 | 65 | InternalState state, |
66 | 66 | ContentDecoder decoder, |
67 | IOControl ioctrl) throws IOException; | |
67 | IOControl ioControl) throws IOException; | |
68 | 68 | |
69 | 69 | void responseCompleted( |
70 | 70 | InternalState state, |
+1
-7
119 | 119 | final HttpAsyncResponseConsumer<T> responseConsumer, |
120 | 120 | final HttpContext context, |
121 | 121 | final FutureCallback<T> callback) { |
122 | ensureRunning(); | |
123 | 122 | final BasicFuture<T> future = new BasicFuture<T>(callback); |
124 | 123 | final HttpClientContext localcontext = HttpClientContext.adapt( |
125 | 124 | context != null ? context : new BasicHttpContext()); |
126 | 125 | setupContext(localcontext); |
127 | 126 | |
128 | @SuppressWarnings("resource") | |
129 | 127 | final DefaultClientExchangeHandlerImpl<T> handler = new DefaultClientExchangeHandlerImpl<T>( |
130 | 128 | this.log, |
131 | 129 | requestProducer, |
136 | 134 | this.connReuseStrategy, |
137 | 135 | this.keepaliveStrategy, |
138 | 136 | this.exec); |
139 | try { | |
140 | handler.start(); | |
141 | } catch (final Exception ex) { | |
142 | handler.failed(ex); | |
143 | } | |
137 | execute(handler); | |
144 | 138 | return new FutureWrapper<T>(future, handler); |
145 | 139 | } |
146 | 140 |
+7
-1
27 | 27 | package org.apache.http.impl.nio.client; |
28 | 28 | |
29 | 29 | import java.io.IOException; |
30 | import java.nio.channels.CancelledKeyException; | |
30 | 31 | |
31 | 32 | import org.apache.commons.logging.Log; |
32 | 33 | import org.apache.commons.logging.LogFactory; |
52 | 53 | |
53 | 54 | @Override |
54 | 55 | protected DefaultNHttpClientConnection createConnection(final IOSession session) { |
55 | throw new IllegalStateException("Connection must be created by connection manager"); | |
56 | // This method should never get called under normal circumstances | |
57 | // Connection object should be created by the connection manager | |
58 | // upon completion of the session request | |
59 | log.debug("Unexpected invocation of #createConnection"); | |
60 | session.close(); | |
61 | throw new CancelledKeyException(); | |
56 | 62 | } |
57 | 63 | |
58 | 64 | @Override |
252 | 252 | public void produceContent( |
253 | 253 | final InternalState state, |
254 | 254 | final ContentEncoder encoder, |
255 | final IOControl ioctrl) throws IOException { | |
255 | final IOControl ioControl) throws IOException { | |
256 | 256 | if (this.log.isDebugEnabled()) { |
257 | 257 | this.log.debug("[exchange: " + state.getId() + "] produce content"); |
258 | 258 | } |
259 | 259 | final HttpAsyncRequestProducer requestProducer = state.getRequestProducer(); |
260 | 260 | state.setRequestContentProduced(); |
261 | requestProducer.produceContent(encoder, ioctrl); | |
261 | requestProducer.produceContent(encoder, ioControl); | |
262 | 262 | if (encoder.isCompleted()) { |
263 | 263 | requestProducer.resetRequest(); |
264 | 264 | } |
285 | 285 | this.log.debug("[exchange: " + state.getId() + "] Response received " + response.getStatusLine()); |
286 | 286 | } |
287 | 287 | final HttpClientContext context = state.getLocalContext(); |
288 | context.setAttribute(HttpClientContext.HTTP_RESPONSE, response); | |
288 | context.setAttribute(HttpCoreContext.HTTP_RESPONSE, response); | |
289 | 289 | this.httpProcessor.process(response, context); |
290 | 290 | |
291 | 291 | handler.setCurrentResponse(response); |
319 | 319 | public void consumeContent( |
320 | 320 | final InternalState state, |
321 | 321 | final ContentDecoder decoder, |
322 | final IOControl ioctrl) throws IOException { | |
322 | final IOControl ioControl) throws IOException { | |
323 | 323 | if (this.log.isDebugEnabled()) { |
324 | 324 | this.log.debug("[exchange: " + state.getId() + "] Consume content"); |
325 | 325 | } |
326 | 326 | if (state.getFinalResponse() != null) { |
327 | 327 | final HttpAsyncResponseConsumer<?> responseConsumer = state.getResponseConsumer(); |
328 | responseConsumer.consumeContent(decoder, ioctrl); | |
328 | responseConsumer.consumeContent(decoder, ioControl); | |
329 | 329 | } else { |
330 | 330 | final ByteBuffer tmpbuf = state.getTmpbuf(); |
331 | 331 | tmpbuf.clear(); |
513 | 513 | } |
514 | 514 | } |
515 | 515 | |
516 | localContext.setAttribute(HttpClientContext.HTTP_REQUEST, currentRequest); | |
517 | localContext.setAttribute(HttpClientContext.HTTP_TARGET_HOST, target); | |
516 | localContext.setAttribute(HttpCoreContext.HTTP_REQUEST, currentRequest); | |
517 | localContext.setAttribute(HttpCoreContext.HTTP_TARGET_HOST, target); | |
518 | 518 | localContext.setAttribute(HttpClientContext.HTTP_ROUTE, route); |
519 | 519 | this.httpProcessor.process(currentRequest, localContext); |
520 | 520 | } |
539 | 539 | |
540 | 540 | private boolean handleConnectResponse( |
541 | 541 | final InternalState state, |
542 | final AbstractClientExchangeHandler handler) throws HttpException { | |
542 | final AbstractClientExchangeHandler handler) { | |
543 | 543 | final HttpClientContext localContext = state.getLocalContext(); |
544 | 544 | final RequestConfig config = localContext.getRequestConfig(); |
545 | 545 | if (config.isAuthenticationEnabled()) { |
598 | 598 | |
599 | 599 | private boolean needAuthentication( |
600 | 600 | final InternalState state, |
601 | final AbstractClientExchangeHandler handler) throws HttpException { | |
601 | final AbstractClientExchangeHandler handler) { | |
602 | 602 | final HttpClientContext localContext = state.getLocalContext(); |
603 | 603 | final CredentialsProvider credsProvider = localContext.getCredentialsProvider(); |
604 | 604 | if (credsProvider != null) { |
+8
-7
119 | 119 | return cancelled; |
120 | 120 | } |
121 | 121 | |
122 | @Override | |
122 | 123 | public void start() throws HttpException, IOException { |
123 | 124 | final HttpHost target = this.requestProducer.getTarget(); |
124 | 125 | final HttpRequest original = this.requestProducer.generateRequest(); |
142 | 143 | setCurrentRequest(request); |
143 | 144 | setRoute(route); |
144 | 145 | |
145 | this.localContext.setAttribute(HttpClientContext.HTTP_REQUEST, request); | |
146 | this.localContext.setAttribute(HttpClientContext.HTTP_TARGET_HOST, target); | |
146 | this.localContext.setAttribute(HttpCoreContext.HTTP_REQUEST, request); | |
147 | this.localContext.setAttribute(HttpCoreContext.HTTP_TARGET_HOST, target); | |
147 | 148 | this.localContext.setAttribute(HttpClientContext.HTTP_ROUTE, route); |
148 | 149 | |
149 | 150 | this.httpProcessor.process(request, this.localContext); |
170 | 171 | |
171 | 172 | @Override |
172 | 173 | public void produceContent( |
173 | final ContentEncoder encoder, final IOControl ioctrl) throws IOException { | |
174 | final ContentEncoder encoder, final IOControl ioControl) throws IOException { | |
174 | 175 | if (this.log.isDebugEnabled()) { |
175 | 176 | this.log.debug("[exchange: " + getId() + "] produce content"); |
176 | 177 | } |
177 | this.requestProducer.produceContent(encoder, ioctrl); | |
178 | this.requestProducer.produceContent(encoder, ioControl); | |
178 | 179 | if (encoder.isCompleted()) { |
179 | 180 | this.requestProducer.resetRequest(); |
180 | 181 | } |
194 | 195 | if (this.log.isDebugEnabled()) { |
195 | 196 | this.log.debug("[exchange: " + getId() + "] Response received " + response.getStatusLine()); |
196 | 197 | } |
197 | this.localContext.setAttribute(HttpClientContext.HTTP_RESPONSE, response); | |
198 | this.localContext.setAttribute(HttpCoreContext.HTTP_RESPONSE, response); | |
198 | 199 | this.httpProcessor.process(response, this.localContext); |
199 | 200 | |
200 | 201 | setCurrentResponse(response); |
204 | 205 | |
205 | 206 | @Override |
206 | 207 | public void consumeContent( |
207 | final ContentDecoder decoder, final IOControl ioctrl) throws IOException { | |
208 | final ContentDecoder decoder, final IOControl ioControl) throws IOException { | |
208 | 209 | if (this.log.isDebugEnabled()) { |
209 | 210 | this.log.debug("[exchange: " + getId() + "] Consume content"); |
210 | 211 | } |
211 | this.responseConsumer.consumeContent(decoder, ioctrl); | |
212 | this.responseConsumer.consumeContent(decoder, ioControl); | |
212 | 213 | if (!decoder.isCompleted() && this.responseConsumer.isDone()) { |
213 | 214 | markConnectionNonReusable(); |
214 | 215 | try { |
+2
-14
89 | 89 | final HttpAsyncResponseConsumer<T> responseConsumer, |
90 | 90 | final HttpContext context, |
91 | 91 | final FutureCallback<T> callback) { |
92 | ensureRunning(); | |
93 | 92 | final BasicFuture<T> future = new BasicFuture<T>(callback); |
94 | 93 | final HttpClientContext localcontext = HttpClientContext.adapt( |
95 | 94 | context != null ? context : new BasicHttpContext()); |
96 | 95 | |
97 | @SuppressWarnings("resource") | |
98 | 96 | final MinimalClientExchangeHandlerImpl<T> handler = new MinimalClientExchangeHandlerImpl<T>( |
99 | 97 | this.log, |
100 | 98 | requestProducer, |
105 | 103 | this.httpProcessor, |
106 | 104 | this.connReuseStrategy, |
107 | 105 | this.keepaliveStrategy); |
108 | try { | |
109 | handler.start(); | |
110 | } catch (final Exception ex) { | |
111 | handler.failed(ex); | |
112 | } | |
106 | execute(handler); | |
113 | 107 | return new FutureWrapper<T>(future, handler); |
114 | 108 | } |
115 | 109 | |
120 | 114 | final List<? extends HttpAsyncResponseConsumer<T>> responseConsumers, |
121 | 115 | final HttpContext context, |
122 | 116 | final FutureCallback<List<T>> callback) { |
123 | ensureRunning(); | |
124 | 117 | final BasicFuture<List<T>> future = new BasicFuture<List<T>>(callback); |
125 | 118 | final HttpClientContext localcontext = HttpClientContext.adapt( |
126 | 119 | context != null ? context : new BasicHttpContext()); |
127 | @SuppressWarnings("resource") | |
128 | 120 | final PipeliningClientExchangeHandlerImpl<T> handler = new PipeliningClientExchangeHandlerImpl<T>( |
129 | 121 | this.log, |
130 | 122 | target, |
136 | 128 | this.httpProcessor, |
137 | 129 | this.connReuseStrategy, |
138 | 130 | this.keepaliveStrategy); |
139 | try { | |
140 | handler.start(); | |
141 | } catch (final Exception ex) { | |
142 | handler.failed(ex); | |
143 | } | |
131 | execute(handler); | |
144 | 132 | return new FutureWrapper<List<T>>(future, handler); |
145 | 133 | } |
146 | 134 |
+20
-15
144 | 144 | |
145 | 145 | @Override |
146 | 146 | void executionFailed(final Exception ex) { |
147 | final HttpAsyncRequestProducer requestProducer = this.requestProducerRef.get(); | |
148 | if (requestProducer != null) { | |
149 | requestProducer.failed(ex); | |
150 | } | |
151 | final HttpAsyncResponseConsumer<T> responseConsumer = this.responseConsumerRef.get(); | |
152 | if (responseConsumer != null) { | |
153 | responseConsumer.failed(ex); | |
154 | } | |
155 | for (final HttpAsyncResponseConsumer<T> cancellable: this.responseConsumerQueue) { | |
156 | cancellable.cancel(); | |
147 | try { | |
148 | final HttpAsyncRequestProducer requestProducer = this.requestProducerRef.get(); | |
149 | if (requestProducer != null) { | |
150 | requestProducer.failed(ex); | |
151 | } | |
152 | final HttpAsyncResponseConsumer<T> responseConsumer = this.responseConsumerRef.get(); | |
153 | if (responseConsumer != null) { | |
154 | responseConsumer.failed(ex); | |
155 | } | |
156 | for (final HttpAsyncResponseConsumer<T> cancellable: this.responseConsumerQueue) { | |
157 | cancellable.cancel(); | |
158 | } | |
159 | } finally { | |
160 | this.resultFuture.failed(ex); | |
157 | 161 | } |
158 | 162 | } |
159 | 163 | |
165 | 169 | return cancelled; |
166 | 170 | } |
167 | 171 | |
172 | @Override | |
168 | 173 | public void start() throws HttpException, IOException { |
169 | 174 | if (this.log.isDebugEnabled()) { |
170 | 175 | this.log.debug("[exchange: " + getId() + "] start execution"); |
173 | 178 | final HttpRoute route = new HttpRoute(this.target); |
174 | 179 | setRoute(route); |
175 | 180 | |
176 | this.localContext.setAttribute(HttpClientContext.HTTP_TARGET_HOST, this.target); | |
181 | this.localContext.setAttribute(HttpCoreContext.HTTP_TARGET_HOST, this.target); | |
177 | 182 | this.localContext.setAttribute(HttpClientContext.HTTP_ROUTE, route); |
178 | 183 | |
179 | 184 | requestConnection(); |
213 | 218 | |
214 | 219 | @Override |
215 | 220 | public void produceContent( |
216 | final ContentEncoder encoder, final IOControl ioctrl) throws IOException { | |
221 | final ContentEncoder encoder, final IOControl ioControl) throws IOException { | |
217 | 222 | if (this.log.isDebugEnabled()) { |
218 | 223 | this.log.debug("[exchange: " + getId() + "] produce content"); |
219 | 224 | } |
220 | 225 | final HttpAsyncRequestProducer requestProducer = this.requestProducerRef.get(); |
221 | 226 | Asserts.check(requestProducer != null, "Inconsistent state: request producer is null"); |
222 | requestProducer.produceContent(encoder, ioctrl); | |
227 | requestProducer.produceContent(encoder, ioControl); | |
223 | 228 | if (encoder.isCompleted()) { |
224 | 229 | requestProducer.resetRequest(); |
225 | 230 | } |
267 | 272 | |
268 | 273 | @Override |
269 | 274 | public void consumeContent( |
270 | final ContentDecoder decoder, final IOControl ioctrl) throws IOException { | |
275 | final ContentDecoder decoder, final IOControl ioControl) throws IOException { | |
271 | 276 | if (this.log.isDebugEnabled()) { |
272 | 277 | this.log.debug("[exchange: " + getId() + "] Consume content"); |
273 | 278 | } |
274 | 279 | final HttpAsyncResponseConsumer<T> responseConsumer = this.responseConsumerRef.get(); |
275 | 280 | Asserts.check(responseConsumer != null, "Inconsistent state: response consumer is null"); |
276 | responseConsumer.consumeContent(decoder, ioctrl); | |
281 | responseConsumer.consumeContent(decoder, ioControl); | |
277 | 282 | } |
278 | 283 | |
279 | 284 | @Override |
45 | 45 | private final Log log = LogFactory.getLog(CPool.class); |
46 | 46 | |
47 | 47 | private final long timeToLive; |
48 | private final TimeUnit tunit; | |
48 | private final TimeUnit timeUnit; | |
49 | 49 | |
50 | 50 | public CPool( |
51 | final ConnectingIOReactor ioreactor, | |
51 | final ConnectingIOReactor ioReactor, | |
52 | 52 | final NIOConnFactory<HttpRoute, ManagedNHttpClientConnection> connFactory, |
53 | 53 | final SocketAddressResolver<HttpRoute> addressResolver, |
54 | 54 | final int defaultMaxPerRoute, final int maxTotal, |
55 | final long timeToLive, final TimeUnit tunit) { | |
56 | super(ioreactor, connFactory, addressResolver, defaultMaxPerRoute, maxTotal); | |
55 | final long timeToLive, final TimeUnit timeUnit) { | |
56 | super(ioReactor, connFactory, addressResolver, defaultMaxPerRoute, maxTotal); | |
57 | 57 | this.timeToLive = timeToLive; |
58 | this.tunit = tunit; | |
58 | this.timeUnit = timeUnit; | |
59 | 59 | } |
60 | 60 | |
61 | 61 | @Override |
62 | 62 | protected CPoolEntry createEntry(final HttpRoute route, final ManagedNHttpClientConnection conn) { |
63 | final CPoolEntry entry = new CPoolEntry(this.log, conn.getId(), route, conn, this.timeToLive, this.tunit); | |
63 | final CPoolEntry entry = new CPoolEntry(this.log, conn.getId(), route, conn, this.timeToLive, this.timeUnit); | |
64 | 64 | entry.setSocketTimeout(conn.getSocketTimeout()); |
65 | 65 | return entry; |
66 | 66 | } |
48 | 48 | final String id, |
49 | 49 | final HttpRoute route, |
50 | 50 | final ManagedNHttpClientConnection conn, |
51 | final long timeToLive, final TimeUnit tunit) { | |
52 | super(id, route, conn, timeToLive, tunit); | |
51 | final long timeToLive, final TimeUnit timeUnit) { | |
52 | super(id, route, conn, timeToLive, timeUnit); | |
53 | 53 | this.log = log; |
54 | 54 | } |
55 | 55 |
151 | 151 | @Override |
152 | 152 | public boolean isOpen() { |
153 | 153 | final CPoolEntry local = this.poolEntry; |
154 | if (local != null) { | |
155 | return !local.isClosed(); | |
156 | } else { | |
157 | return false; | |
158 | } | |
154 | return local != null ? !local.isClosed() : false; | |
159 | 155 | } |
160 | 156 | |
161 | 157 | @Override |
162 | 158 | public boolean isStale() { |
163 | 159 | final NHttpClientConnection conn = getConnection(); |
164 | if (conn != null) { | |
165 | return !conn.isOpen(); | |
166 | } else { | |
167 | return false; | |
168 | } | |
160 | return conn != null ? !conn.isOpen() : false; | |
169 | 161 | } |
170 | 162 | |
171 | 163 | @Override |
247 | 239 | } |
248 | 240 | |
249 | 241 | @Override |
250 | public void bind(final IOSession iosession) { | |
251 | getValidConnection().bind(iosession); | |
242 | public void bind(final IOSession ioSession) { | |
243 | getValidConnection().bind(ioSession); | |
252 | 244 | } |
253 | 245 | |
254 | 246 | @Override |
42 | 42 | private final ByteChannel channel; |
43 | 43 | private final String id; |
44 | 44 | private final Log log; |
45 | private final Wire wirelog; | |
46 | ||
47 | public LoggingIOSession(final IOSession session, final String id, final Log log, final Log wirelog) { | |
45 | private final Wire wireLog; | |
46 | ||
47 | public LoggingIOSession(final IOSession session, final String id, final Log log, final Log wireLog) { | |
48 | 48 | super(); |
49 | 49 | this.session = session; |
50 | 50 | this.channel = new LoggingByteChannel(); |
51 | 51 | this.id = id; |
52 | 52 | this.log = log; |
53 | this.wirelog = new Wire(wirelog, this.id); | |
53 | this.wireLog = new Wire(wireLog, this.id); | |
54 | 54 | } |
55 | 55 | |
56 | 56 | @Override |
204 | 204 | if (log.isDebugEnabled()) { |
205 | 205 | log.debug(id + " " + session + ": " + bytesRead + " bytes read"); |
206 | 206 | } |
207 | if (bytesRead > 0 && wirelog.isEnabled()) { | |
207 | if (bytesRead > 0 && wireLog.isEnabled()) { | |
208 | 208 | final ByteBuffer b = dst.duplicate(); |
209 | 209 | final int p = b.position(); |
210 | 210 | b.limit(p); |
211 | 211 | b.position(p - bytesRead); |
212 | wirelog.input(b); | |
212 | wireLog.input(b); | |
213 | 213 | } |
214 | 214 | return bytesRead; |
215 | 215 | } |
220 | 220 | if (log.isDebugEnabled()) { |
221 | 221 | log.debug(id + " " + session + ": " + byteWritten + " bytes written"); |
222 | 222 | } |
223 | if (byteWritten > 0 && wirelog.isEnabled()) { | |
223 | if (byteWritten > 0 && wireLog.isEnabled()) { | |
224 | 224 | final ByteBuffer b = src.duplicate(); |
225 | 225 | final int p = b.position(); |
226 | 226 | b.limit(p); |
227 | 227 | b.position(p - byteWritten); |
228 | wirelog.output(b); | |
228 | wireLog.output(b); | |
229 | 229 | } |
230 | 230 | return byteWritten; |
231 | 231 | } |
+17
-17
54 | 54 | */ |
55 | 55 | public class ManagedNHttpClientConnectionFactory implements NHttpConnectionFactory<ManagedNHttpClientConnection> { |
56 | 56 | |
57 | private final Log headerlog = LogFactory.getLog("org.apache.http.headers"); | |
58 | private final Log wirelog = LogFactory.getLog("org.apache.http.wire"); | |
57 | private final Log headerLog = LogFactory.getLog("org.apache.http.headers"); | |
58 | private final Log wireLog = LogFactory.getLog("org.apache.http.wire"); | |
59 | 59 | private final Log log = LogFactory.getLog(ManagedNHttpClientConnectionImpl.class); |
60 | 60 | |
61 | 61 | private static final AtomicLong COUNTER = new AtomicLong(); |
84 | 84 | |
85 | 85 | @Override |
86 | 86 | public ManagedNHttpClientConnection create( |
87 | final IOSession iosession, final ConnectionConfig config) { | |
87 | final IOSession ioSession, final ConnectionConfig config) { | |
88 | 88 | final String id = "http-outgoing-" + Long.toString(COUNTER.getAndIncrement()); |
89 | CharsetDecoder chardecoder = null; | |
90 | CharsetEncoder charencoder = null; | |
89 | CharsetDecoder charDecoder = null; | |
90 | CharsetEncoder charEncoder = null; | |
91 | 91 | final Charset charset = config.getCharset(); |
92 | 92 | final CodingErrorAction malformedInputAction = config.getMalformedInputAction() != null ? |
93 | 93 | config.getMalformedInputAction() : CodingErrorAction.REPORT; |
94 | 94 | final CodingErrorAction unmappableInputAction = config.getUnmappableInputAction() != null ? |
95 | 95 | config.getUnmappableInputAction() : CodingErrorAction.REPORT; |
96 | 96 | if (charset != null) { |
97 | chardecoder = charset.newDecoder(); | |
98 | chardecoder.onMalformedInput(malformedInputAction); | |
99 | chardecoder.onUnmappableCharacter(unmappableInputAction); | |
100 | charencoder = charset.newEncoder(); | |
101 | charencoder.onMalformedInput(malformedInputAction); | |
102 | charencoder.onUnmappableCharacter(unmappableInputAction); | |
97 | charDecoder = charset.newDecoder(); | |
98 | charDecoder.onMalformedInput(malformedInputAction); | |
99 | charDecoder.onUnmappableCharacter(unmappableInputAction); | |
100 | charEncoder = charset.newEncoder(); | |
101 | charEncoder.onMalformedInput(malformedInputAction); | |
102 | charEncoder.onUnmappableCharacter(unmappableInputAction); | |
103 | 103 | } |
104 | 104 | final ManagedNHttpClientConnection conn = new ManagedNHttpClientConnectionImpl( |
105 | 105 | id, |
106 | 106 | this.log, |
107 | this.headerlog, | |
108 | this.wirelog, | |
109 | iosession, | |
107 | this.headerLog, | |
108 | this.wireLog, | |
109 | ioSession, | |
110 | 110 | config.getBufferSize(), |
111 | 111 | config.getFragmentSizeHint(), |
112 | 112 | this.allocator, |
113 | chardecoder, | |
114 | charencoder, | |
113 | charDecoder, | |
114 | charEncoder, | |
115 | 115 | config.getMessageConstraints(), |
116 | 116 | null, |
117 | 117 | null, |
118 | 118 | this.requestWriterFactory, |
119 | 119 | this.responseParserFactory); |
120 | iosession.setAttribute(IOEventDispatch.CONNECTION_KEY, conn); | |
120 | ioSession.setAttribute(IOEventDispatch.CONNECTION_KEY, conn); | |
121 | 121 | return conn; |
122 | 122 | } |
123 | 123 |
+31
-33
49 | 49 | class ManagedNHttpClientConnectionImpl |
50 | 50 | extends DefaultNHttpClientConnection implements ManagedNHttpClientConnection { |
51 | 51 | |
52 | private final Log headerlog; | |
53 | private final Log wirelog; | |
52 | private final Log headerLog; | |
53 | private final Log wireLog; | |
54 | 54 | private final Log log; |
55 | 55 | |
56 | 56 | private final String id; |
59 | 59 | public ManagedNHttpClientConnectionImpl( |
60 | 60 | final String id, |
61 | 61 | final Log log, |
62 | final Log headerlog, | |
63 | final Log wirelog, | |
64 | final IOSession iosession, | |
65 | final int buffersize, | |
62 | final Log headerLog, | |
63 | final Log wireLog, | |
64 | final IOSession ioSession, | |
65 | final int bufferSize, | |
66 | 66 | final int fragmentSizeHint, |
67 | 67 | final ByteBufferAllocator allocator, |
68 | final CharsetDecoder chardecoder, | |
69 | final CharsetEncoder charencoder, | |
68 | final CharsetDecoder charDecoder, | |
69 | final CharsetEncoder charEncoder, | |
70 | 70 | final MessageConstraints constraints, |
71 | 71 | final ContentLengthStrategy incomingContentStrategy, |
72 | 72 | final ContentLengthStrategy outgoingContentStrategy, |
73 | 73 | final NHttpMessageWriterFactory<HttpRequest> requestWriterFactory, |
74 | 74 | final NHttpMessageParserFactory<HttpResponse> responseParserFactory) { |
75 | super(iosession, buffersize, fragmentSizeHint, allocator, chardecoder, charencoder, constraints, | |
75 | super(ioSession, bufferSize, fragmentSizeHint, allocator, charDecoder, charEncoder, constraints, | |
76 | 76 | incomingContentStrategy, outgoingContentStrategy, |
77 | 77 | requestWriterFactory, responseParserFactory); |
78 | 78 | this.id = id; |
79 | 79 | this.log = log; |
80 | this.headerlog = headerlog; | |
81 | this.wirelog = wirelog; | |
82 | this.original = iosession; | |
83 | if (this.log.isDebugEnabled() || this.wirelog.isDebugEnabled()) { | |
84 | super.bind(new LoggingIOSession(iosession, this.id, this.log, this.wirelog)); | |
80 | this.headerLog = headerLog; | |
81 | this.wireLog = wireLog; | |
82 | this.original = ioSession; | |
83 | if (this.log.isDebugEnabled() || this.wireLog.isDebugEnabled()) { | |
84 | super.bind(new LoggingIOSession(ioSession, this.id, this.log, this.wireLog)); | |
85 | 85 | } |
86 | 86 | } |
87 | 87 | |
88 | 88 | @Override |
89 | public void bind(final IOSession iosession) { | |
90 | Args.notNull(iosession, "I/O session"); | |
91 | Asserts.check(!iosession.isClosed(), "I/O session is closed"); | |
89 | public void bind(final IOSession ioSession) { | |
90 | Args.notNull(ioSession, "I/O session"); | |
91 | Asserts.check(!ioSession.isClosed(), "I/O session is closed"); | |
92 | 92 | this.status = ACTIVE; |
93 | this.original = iosession; | |
94 | if (this.log.isDebugEnabled() || this.wirelog.isDebugEnabled()) { | |
95 | this.log.debug(this.id + " Upgrade session " + iosession); | |
96 | super.bind(new LoggingIOSession(iosession, this.id, this.log, this.wirelog)); | |
93 | this.original = ioSession; | |
94 | if (this.log.isDebugEnabled() || this.wireLog.isDebugEnabled()) { | |
95 | this.log.debug(this.id + " Upgrade session " + ioSession); | |
96 | super.bind(new LoggingIOSession(ioSession, this.id, this.log, this.wireLog)); | |
97 | 97 | } else { |
98 | super.bind(iosession); | |
98 | super.bind(ioSession); | |
99 | 99 | } |
100 | 100 | } |
101 | 101 | |
106 | 106 | |
107 | 107 | @Override |
108 | 108 | public SSLSession getSSLSession() { |
109 | if (this.original instanceof SSLIOSession) { | |
110 | return ((SSLIOSession) this.original).getSSLSession(); | |
111 | } else { | |
112 | return null; | |
113 | } | |
109 | return this.original instanceof SSLIOSession | |
110 | ? ((SSLIOSession) this.original).getSSLSession() | |
111 | : null; | |
114 | 112 | } |
115 | 113 | |
116 | 114 | @Override |
120 | 118 | |
121 | 119 | @Override |
122 | 120 | protected void onResponseReceived(final HttpResponse response) { |
123 | if (response != null && this.headerlog.isDebugEnabled()) { | |
124 | this.headerlog.debug(this.id + " << " + response.getStatusLine().toString()); | |
121 | if (response != null && this.headerLog.isDebugEnabled()) { | |
122 | this.headerLog.debug(this.id + " << " + response.getStatusLine().toString()); | |
125 | 123 | final Header[] headers = response.getAllHeaders(); |
126 | 124 | for (final Header header : headers) { |
127 | this.headerlog.debug(this.id + " << " + header.toString()); | |
125 | this.headerLog.debug(this.id + " << " + header.toString()); | |
128 | 126 | } |
129 | 127 | } |
130 | 128 | } |
131 | 129 | |
132 | 130 | @Override |
133 | 131 | protected void onRequestSubmitted(final HttpRequest request) { |
134 | if (request != null && this.headerlog.isDebugEnabled()) { | |
135 | this.headerlog.debug(this.id + " >> " + request.getRequestLine().toString()); | |
132 | if (request != null && this.headerLog.isDebugEnabled()) { | |
133 | this.headerLog.debug(this.id + " >> " + request.getRequestLine().toString()); | |
136 | 134 | final Header[] headers = request.getAllHeaders(); |
137 | 135 | for (final Header header : headers) { |
138 | this.headerlog.debug(this.id + " >> " + header.toString()); | |
136 | this.headerLog.debug(this.id + " >> " + header.toString()); | |
139 | 137 | } |
140 | 138 | } |
141 | 139 | } |
+81
-79
96 | 96 | |
97 | 97 | private final Log log = LogFactory.getLog(getClass()); |
98 | 98 | |
99 | static final String IOSESSION_FACTORY_REGISTRY = "http.iosession-factory-registry"; | |
100 | ||
101 | private final ConnectingIOReactor ioreactor; | |
99 | static final String IOSESSION_FACTORY_REGISTRY = "http.ioSession-factory-registry"; | |
100 | ||
101 | private final ConnectingIOReactor ioReactor; | |
102 | 102 | private final ConfigData configData; |
103 | 103 | private final CPool pool; |
104 | private final Registry<SchemeIOSessionStrategy> iosessionFactoryRegistry; | |
104 | private final Registry<SchemeIOSessionStrategy> ioSessionFactoryRegistry; | |
105 | 105 | |
106 | 106 | private static Registry<SchemeIOSessionStrategy> getDefaultRegistry() { |
107 | 107 | return RegistryBuilder.<SchemeIOSessionStrategy>create() |
110 | 110 | .build(); |
111 | 111 | } |
112 | 112 | |
113 | public PoolingNHttpClientConnectionManager(final ConnectingIOReactor ioreactor) { | |
114 | this(ioreactor, getDefaultRegistry()); | |
115 | } | |
116 | ||
117 | public PoolingNHttpClientConnectionManager( | |
118 | final ConnectingIOReactor ioreactor, | |
119 | final Registry<SchemeIOSessionStrategy> iosessionFactoryRegistry) { | |
120 | this(ioreactor, null, iosessionFactoryRegistry, (DnsResolver) null); | |
121 | } | |
122 | ||
123 | public PoolingNHttpClientConnectionManager( | |
124 | final ConnectingIOReactor ioreactor, | |
113 | public PoolingNHttpClientConnectionManager(final ConnectingIOReactor ioReactor) { | |
114 | this(ioReactor, getDefaultRegistry()); | |
115 | } | |
116 | ||
117 | public PoolingNHttpClientConnectionManager( | |
118 | final ConnectingIOReactor ioReactor, | |
119 | final Registry<SchemeIOSessionStrategy> ioSessionFactoryRegistry) { | |
120 | this(ioReactor, null, ioSessionFactoryRegistry, (DnsResolver) null); | |
121 | } | |
122 | ||
123 | public PoolingNHttpClientConnectionManager( | |
124 | final ConnectingIOReactor ioReactor, | |
125 | 125 | final NHttpConnectionFactory<ManagedNHttpClientConnection> connFactory, |
126 | 126 | final DnsResolver dnsResolver) { |
127 | this(ioreactor, connFactory, getDefaultRegistry(), dnsResolver); | |
128 | } | |
129 | ||
130 | public PoolingNHttpClientConnectionManager( | |
131 | final ConnectingIOReactor ioreactor, | |
127 | this(ioReactor, connFactory, getDefaultRegistry(), dnsResolver); | |
128 | } | |
129 | ||
130 | public PoolingNHttpClientConnectionManager( | |
131 | final ConnectingIOReactor ioReactor, | |
132 | 132 | final NHttpConnectionFactory<ManagedNHttpClientConnection> connFactory, |
133 | 133 | final SocketAddressResolver<HttpRoute> socketAddressResolver) { |
134 | this(ioreactor, connFactory, getDefaultRegistry(), socketAddressResolver); | |
135 | } | |
136 | ||
137 | public PoolingNHttpClientConnectionManager( | |
138 | final ConnectingIOReactor ioreactor, | |
134 | this(ioReactor, connFactory, getDefaultRegistry(), socketAddressResolver); | |
135 | } | |
136 | ||
137 | public PoolingNHttpClientConnectionManager( | |
138 | final ConnectingIOReactor ioReactor, | |
139 | 139 | final NHttpConnectionFactory<ManagedNHttpClientConnection> connFactory) { |
140 | this(ioreactor, connFactory, getDefaultRegistry(), (DnsResolver) null); | |
141 | } | |
142 | ||
143 | public PoolingNHttpClientConnectionManager( | |
144 | final ConnectingIOReactor ioreactor, | |
140 | this(ioReactor, connFactory, getDefaultRegistry(), (DnsResolver) null); | |
141 | } | |
142 | ||
143 | public PoolingNHttpClientConnectionManager( | |
144 | final ConnectingIOReactor ioReactor, | |
145 | 145 | final NHttpConnectionFactory<ManagedNHttpClientConnection> connFactory, |
146 | final Registry<SchemeIOSessionStrategy> iosessionFactoryRegistry) { | |
147 | this(ioreactor, connFactory, iosessionFactoryRegistry, (DnsResolver) null); | |
148 | } | |
149 | ||
150 | public PoolingNHttpClientConnectionManager( | |
151 | final ConnectingIOReactor ioreactor, | |
146 | final Registry<SchemeIOSessionStrategy> ioSessionFactoryRegistry) { | |
147 | this(ioReactor, connFactory, ioSessionFactoryRegistry, (DnsResolver) null); | |
148 | } | |
149 | ||
150 | public PoolingNHttpClientConnectionManager( | |
151 | final ConnectingIOReactor ioReactor, | |
152 | 152 | final NHttpConnectionFactory<ManagedNHttpClientConnection> connFactory, |
153 | final Registry<SchemeIOSessionStrategy> iosessionFactoryRegistry, | |
153 | final Registry<SchemeIOSessionStrategy> ioSessionFactoryRegistry, | |
154 | 154 | final DnsResolver dnsResolver) { |
155 | this(ioreactor, connFactory, iosessionFactoryRegistry, null, dnsResolver, | |
155 | this(ioReactor, connFactory, ioSessionFactoryRegistry, null, dnsResolver, | |
156 | 156 | -1, TimeUnit.MILLISECONDS); |
157 | 157 | } |
158 | 158 | |
159 | 159 | public PoolingNHttpClientConnectionManager( |
160 | final ConnectingIOReactor ioreactor, | |
160 | final ConnectingIOReactor ioReactor, | |
161 | 161 | final NHttpConnectionFactory<ManagedNHttpClientConnection> connFactory, |
162 | final Registry<SchemeIOSessionStrategy> iosessionFactoryRegistry, | |
162 | final Registry<SchemeIOSessionStrategy> ioSessionFactoryRegistry, | |
163 | 163 | final SocketAddressResolver<HttpRoute> socketAddressResolver) { |
164 | this(ioreactor, connFactory, iosessionFactoryRegistry, socketAddressResolver, | |
164 | this(ioReactor, connFactory, ioSessionFactoryRegistry, socketAddressResolver, | |
165 | 165 | -1, TimeUnit.MILLISECONDS); |
166 | 166 | } |
167 | 167 | |
168 | 168 | public PoolingNHttpClientConnectionManager( |
169 | final ConnectingIOReactor ioreactor, | |
169 | final ConnectingIOReactor ioReactor, | |
170 | 170 | final NHttpConnectionFactory<ManagedNHttpClientConnection> connFactory, |
171 | final Registry<SchemeIOSessionStrategy> iosessionFactoryRegistry, | |
171 | final Registry<SchemeIOSessionStrategy> ioSessionFactoryRegistry, | |
172 | 172 | final SchemePortResolver schemePortResolver, |
173 | 173 | final DnsResolver dnsResolver, |
174 | final long timeToLive, final TimeUnit tunit) { | |
175 | this(ioreactor, connFactory, iosessionFactoryRegistry, | |
176 | new InternalAddressResolver(schemePortResolver, dnsResolver), timeToLive, tunit); | |
177 | } | |
178 | ||
179 | public PoolingNHttpClientConnectionManager( | |
180 | final ConnectingIOReactor ioreactor, | |
174 | final long timeToLive, final TimeUnit timeUnit) { | |
175 | this(ioReactor, connFactory, ioSessionFactoryRegistry, | |
176 | new InternalAddressResolver(schemePortResolver, dnsResolver), timeToLive, timeUnit); | |
177 | } | |
178 | ||
179 | public PoolingNHttpClientConnectionManager( | |
180 | final ConnectingIOReactor ioReactor, | |
181 | 181 | final NHttpConnectionFactory<ManagedNHttpClientConnection> connFactory, |
182 | final Registry<SchemeIOSessionStrategy> iosessionFactoryRegistry, | |
182 | final Registry<SchemeIOSessionStrategy> ioSessionFactoryRegistry, | |
183 | 183 | final SocketAddressResolver<HttpRoute> socketAddressResolver, |
184 | final long timeToLive, final TimeUnit tunit) { | |
184 | final long timeToLive, final TimeUnit timeUnit) { | |
185 | 185 | super(); |
186 | Args.notNull(ioreactor, "I/O reactor"); | |
187 | Args.notNull(iosessionFactoryRegistry, "I/O session factory registry"); | |
186 | Args.notNull(ioReactor, "I/O reactor"); | |
187 | Args.notNull(ioSessionFactoryRegistry, "I/O session factory registry"); | |
188 | 188 | Args.notNull(socketAddressResolver, "Socket address resolver"); |
189 | this.ioreactor = ioreactor; | |
189 | this.ioReactor = ioReactor; | |
190 | 190 | this.configData = new ConfigData(); |
191 | this.pool = new CPool(ioreactor, | |
191 | this.pool = new CPool(ioReactor, | |
192 | 192 | new InternalConnectionFactory(this.configData, connFactory), |
193 | 193 | socketAddressResolver, |
194 | 2, 20, timeToLive, tunit != null ? tunit : TimeUnit.MILLISECONDS); | |
195 | this.iosessionFactoryRegistry = iosessionFactoryRegistry; | |
194 | 2, 20, timeToLive, timeUnit != null ? timeUnit : TimeUnit.MILLISECONDS); | |
195 | this.ioSessionFactoryRegistry = ioSessionFactoryRegistry; | |
196 | 196 | } |
197 | 197 | |
198 | 198 | PoolingNHttpClientConnectionManager( |
199 | final ConnectingIOReactor ioreactor, | |
199 | final ConnectingIOReactor ioReactor, | |
200 | 200 | final CPool pool, |
201 | final Registry<SchemeIOSessionStrategy> iosessionFactoryRegistry) { | |
201 | final Registry<SchemeIOSessionStrategy> ioSessionFactoryRegistry) { | |
202 | 202 | super(); |
203 | this.ioreactor = ioreactor; | |
203 | this.ioReactor = ioReactor; | |
204 | 204 | this.configData = new ConfigData(); |
205 | 205 | this.pool = pool; |
206 | this.iosessionFactoryRegistry = iosessionFactoryRegistry; | |
206 | this.ioSessionFactoryRegistry = ioSessionFactoryRegistry; | |
207 | 207 | } |
208 | 208 | |
209 | 209 | @Override |
217 | 217 | |
218 | 218 | @Override |
219 | 219 | public void execute(final IOEventDispatch eventDispatch) throws IOException { |
220 | this.ioreactor.execute(eventDispatch); | |
220 | this.ioReactor.execute(eventDispatch); | |
221 | 221 | } |
222 | 222 | |
223 | 223 | public void shutdown(final long waitMs) throws IOException { |
271 | 271 | final Object state, |
272 | 272 | final long connectTimeout, |
273 | 273 | final long leaseTimeout, |
274 | final TimeUnit tunit, | |
274 | final TimeUnit timeUnit, | |
275 | 275 | final FutureCallback<NHttpClientConnection> callback) { |
276 | 276 | Args.notNull(route, "HTTP route"); |
277 | 277 | if (this.log.isDebugEnabled()) { |
284 | 284 | } else { |
285 | 285 | host = route.getTargetHost(); |
286 | 286 | } |
287 | final SchemeIOSessionStrategy sf = this.iosessionFactoryRegistry.lookup( | |
287 | final SchemeIOSessionStrategy sf = this.ioSessionFactoryRegistry.lookup( | |
288 | 288 | host.getSchemeName()); |
289 | 289 | if (sf == null) { |
290 | 290 | resultFuture.failed(new UnsupportedSchemeException(host.getSchemeName() + |
292 | 292 | return resultFuture; |
293 | 293 | } |
294 | 294 | final Future<CPoolEntry> leaseFuture = this.pool.lease(route, state, |
295 | connectTimeout, leaseTimeout, tunit != null ? tunit : TimeUnit.MILLISECONDS, | |
295 | connectTimeout, leaseTimeout, timeUnit != null ? timeUnit : TimeUnit.MILLISECONDS, | |
296 | 296 | new FutureCallback<CPoolEntry>() { |
297 | 297 | |
298 | 298 | @Override |
302 | 302 | log.debug("Connection leased: " + format(entry) + formatStats(entry.getRoute())); |
303 | 303 | } |
304 | 304 | final NHttpClientConnection managedConn = CPoolProxy.newProxy(entry); |
305 | if (!resultFuture.completed(managedConn)) { | |
306 | pool.release(entry, true); | |
305 | synchronized (managedConn) { | |
306 | if (!resultFuture.completed(managedConn)) { | |
307 | pool.release(entry, true); | |
308 | } | |
307 | 309 | } |
308 | 310 | } |
309 | 311 | |
361 | 363 | final NHttpClientConnection managedConn, |
362 | 364 | final Object state, |
363 | 365 | final long keepalive, |
364 | final TimeUnit tunit) { | |
366 | final TimeUnit timeUnit) { | |
365 | 367 | Args.notNull(managedConn, "Managed connection"); |
366 | 368 | synchronized (managedConn) { |
367 | 369 | final CPoolEntry entry = CPoolProxy.detach(managedConn); |
375 | 377 | try { |
376 | 378 | if (conn.isOpen()) { |
377 | 379 | entry.setState(state); |
378 | entry.updateExpiry(keepalive, tunit != null ? tunit : TimeUnit.MILLISECONDS); | |
380 | entry.updateExpiry(keepalive, timeUnit != null ? timeUnit : TimeUnit.MILLISECONDS); | |
379 | 381 | if (this.log.isDebugEnabled()) { |
380 | 382 | final String s; |
381 | 383 | if (keepalive > 0) { |
400 | 402 | Lookup<SchemeIOSessionStrategy> reg = (Lookup<SchemeIOSessionStrategy>) context.getAttribute( |
401 | 403 | IOSESSION_FACTORY_REGISTRY); |
402 | 404 | if (reg == null) { |
403 | reg = this.iosessionFactoryRegistry; | |
405 | reg = this.ioSessionFactoryRegistry; | |
404 | 406 | } |
405 | 407 | return reg; |
406 | 408 | } |
485 | 487 | } |
486 | 488 | |
487 | 489 | @Override |
488 | public void closeIdleConnections(final long idleTimeout, final TimeUnit tunit) { | |
490 | public void closeIdleConnections(final long idleTimeout, final TimeUnit timeUnit) { | |
489 | 491 | if (this.log.isDebugEnabled()) { |
490 | this.log.debug("Closing connections idle longer than " + idleTimeout + " " + tunit); | |
491 | } | |
492 | this.pool.closeIdle(idleTimeout, tunit); | |
492 | this.log.debug("Closing connections idle longer than " + idleTimeout + " " + timeUnit); | |
493 | } | |
494 | this.pool.closeIdle(idleTimeout, timeUnit); | |
493 | 495 | } |
494 | 496 | |
495 | 497 | @Override |
610 | 612 | |
611 | 613 | @Override |
612 | 614 | public ManagedNHttpClientConnection create( |
613 | final HttpRoute route, final IOSession iosession) throws IOException { | |
615 | final HttpRoute route, final IOSession ioSession) throws IOException { | |
614 | 616 | ConnectionConfig config = null; |
615 | 617 | if (route.getProxyHost() != null) { |
616 | 618 | config = this.configData.getConnectionConfig(route.getProxyHost()); |
624 | 626 | if (config == null) { |
625 | 627 | config = ConnectionConfig.DEFAULT; |
626 | 628 | } |
627 | final ManagedNHttpClientConnection conn = this.connFactory.create(iosession, config); | |
628 | iosession.setAttribute(IOEventDispatch.CONNECTION_KEY, conn); | |
629 | final ManagedNHttpClientConnection conn = this.connFactory.create(ioSession, config); | |
630 | ioSession.setAttribute(IOEventDispatch.CONNECTION_KEY, conn); | |
629 | 631 | return conn; |
630 | 632 | } |
631 | 633 |
+4
-4
61 | 61 | * if the consumer is temporarily unable to consume more content. |
62 | 62 | * |
63 | 63 | * @param buf chunk of content. |
64 | * @param ioctrl I/O control of the underlying connection. | |
64 | * @param ioControl I/O control of the underlying connection. | |
65 | 65 | * @throws IOException in case of an I/O error |
66 | 66 | */ |
67 | 67 | protected abstract void onByteReceived( |
68 | ByteBuffer buf, IOControl ioctrl) throws IOException; | |
68 | ByteBuffer buf, IOControl ioControl) throws IOException; | |
69 | 69 | |
70 | 70 | @Override |
71 | 71 | protected final void onEntityEnclosed( |
74 | 74 | |
75 | 75 | @Override |
76 | 76 | protected final void onContentReceived( |
77 | final ContentDecoder decoder, final IOControl ioctrl) throws IOException { | |
77 | final ContentDecoder decoder, final IOControl ioControl) throws IOException { | |
78 | 78 | Asserts.notNull(this.bbuf, "Byte buffer"); |
79 | 79 | final int bytesRead = decoder.read(this.bbuf); |
80 | 80 | if (bytesRead <= 0) { |
81 | 81 | return; |
82 | 82 | } |
83 | 83 | this.bbuf.flip(); |
84 | onByteReceived(this.bbuf, ioctrl); | |
84 | onByteReceived(this.bbuf, ioControl); | |
85 | 85 | this.bbuf.clear(); |
86 | 86 | } |
87 | 87 |
+11
-11
52 | 52 | private final ByteBuffer bbuf; |
53 | 53 | private final CharBuffer cbuf; |
54 | 54 | |
55 | private CharsetDecoder chardecoder; | |
55 | private CharsetDecoder charDecoder; | |
56 | 56 | |
57 | 57 | public AsyncCharConsumer(final int bufSize) { |
58 | 58 | super(); |
70 | 70 | * if the consumer is temporarily unable to consume more content. |
71 | 71 | * |
72 | 72 | * @param buf chunk of content. |
73 | * @param ioctrl I/O control of the underlying connection. | |
73 | * @param ioControl I/O control of the underlying connection. | |
74 | 74 | * @throws IOException in case of an I/O error |
75 | 75 | */ |
76 | 76 | protected abstract void onCharReceived( |
77 | CharBuffer buf, IOControl ioctrl) throws IOException; | |
77 | CharBuffer buf, IOControl ioControl) throws IOException; | |
78 | 78 | |
79 | 79 | /** |
80 | 80 | * Invoked to create a @{link CharsetDecoder} for contentType. |
97 | 97 | @Override |
98 | 98 | protected final void onEntityEnclosed( |
99 | 99 | final HttpEntity entity, final ContentType contentType) throws IOException { |
100 | this.chardecoder = createDecoder(contentType != null ? contentType : ContentType.DEFAULT_TEXT); | |
100 | this.charDecoder = createDecoder(contentType != null ? contentType : ContentType.DEFAULT_TEXT); | |
101 | 101 | } |
102 | 102 | |
103 | 103 | @Override |
104 | 104 | protected final void onContentReceived( |
105 | final ContentDecoder decoder, final IOControl ioctrl) throws IOException { | |
105 | final ContentDecoder decoder, final IOControl ioControl) throws IOException { | |
106 | 106 | Asserts.notNull(this.bbuf, "Byte buffer"); |
107 | 107 | |
108 | 108 | final int bytesRead = decoder.read(this.bbuf); |
111 | 111 | } |
112 | 112 | this.bbuf.flip(); |
113 | 113 | final boolean completed = decoder.isCompleted(); |
114 | CoderResult result = this.chardecoder.decode(this.bbuf, this.cbuf, completed); | |
115 | handleDecodingResult(result, ioctrl); | |
114 | CoderResult result = this.charDecoder.decode(this.bbuf, this.cbuf, completed); | |
115 | handleDecodingResult(result, ioControl); | |
116 | 116 | this.bbuf.compact(); |
117 | 117 | if (completed) { |
118 | result = this.chardecoder.flush(this.cbuf); | |
119 | handleDecodingResult(result, ioctrl); | |
118 | result = this.charDecoder.flush(this.cbuf); | |
119 | handleDecodingResult(result, ioControl); | |
120 | 120 | } |
121 | 121 | } |
122 | 122 | |
123 | 123 | private void handleDecodingResult( |
124 | final CoderResult result, final IOControl ioctrl) throws IOException { | |
124 | final CoderResult result, final IOControl ioControl) throws IOException { | |
125 | 125 | if (result.isError()) { |
126 | 126 | result.throwException(); |
127 | 127 | } |
128 | 128 | this.cbuf.flip(); |
129 | 129 | if (this.cbuf.hasRemaining()) { |
130 | onCharReceived(this.cbuf, ioctrl); | |
130 | onCharReceived(this.cbuf, ioControl); | |
131 | 131 | } |
132 | 132 | this.cbuf.clear(); |
133 | 133 | } |
+1
-1
97 | 97 | |
98 | 98 | @Override |
99 | 99 | public synchronized void produceContent( |
100 | final ContentEncoder encoder, final IOControl ioctrl) throws IOException { | |
100 | final ContentEncoder encoder, final IOControl ioControl) throws IOException { | |
101 | 101 | if (this.fileChannel == null) { |
102 | 102 | this.fileChannel = this.accessfile.getChannel(); |
103 | 103 | this.idx = 0; |
+1
-1
89 | 89 | |
90 | 90 | @Override |
91 | 91 | protected void onContentReceived( |
92 | final ContentDecoder decoder, final IOControl ioctrl) throws IOException { | |
92 | final ContentDecoder decoder, final IOControl ioControl) throws IOException { | |
93 | 93 | Asserts.notNull(this.fileChannel, "File channel"); |
94 | 94 | final long transferred; |
95 | 95 | if (decoder instanceof FileContentDecoder) { |
+1
-1
50 | 50 | /** |
51 | 51 | * Binds connection to the given I/O session. |
52 | 52 | */ |
53 | void bind(IOSession iosession); | |
53 | void bind(IOSession ioSession); | |
54 | 54 | |
55 | 55 | /** |
56 | 56 | * Returns the underlying I/O session. |
+2
-2
164 | 164 | * All expired connections will also be closed. |
165 | 165 | * |
166 | 166 | * @param idletime the idle time of connections to be closed |
167 | * @param tunit the unit for the {@code idletime} | |
167 | * @param timeUnit the unit for the {@code idletime} | |
168 | 168 | * |
169 | 169 | * @see #closeExpiredConnections() |
170 | 170 | */ |
171 | void closeIdleConnections(long idletime, TimeUnit tunit); | |
171 | void closeIdleConnections(long idletime, TimeUnit timeUnit); | |
172 | 172 | |
173 | 173 | /** |
174 | 174 | * Closes all expired connections in the pool. |
36 | 36 | */ |
37 | 37 | public interface NHttpConnectionFactory<T extends NHttpConnection> { |
38 | 38 | |
39 | T create(IOSession iosession, ConnectionConfig config); | |
39 | T create(IOSession ioSession, ConnectionConfig config); | |
40 | 40 | |
41 | 41 | } |
39 | 39 | public static final NoopIOSessionStrategy INSTANCE = new NoopIOSessionStrategy(); |
40 | 40 | |
41 | 41 | @Override |
42 | public IOSession upgrade(final HttpHost host, final IOSession iosession) { | |
43 | return iosession; | |
42 | public IOSession upgrade(final HttpHost host, final IOSession ioSession) { | |
43 | return ioSession; | |
44 | 44 | } |
45 | 45 | |
46 | 46 | @Override |
52 | 52 | * Decorates the original {@link IOSession} with a transport level security |
53 | 53 | * protocol implementation. |
54 | 54 | * @param host the target host. |
55 | * @param iosession the I/O session. | |
55 | * @param ioSession the I/O session. | |
56 | 56 | * @return upgraded I/O session. |
57 | 57 | */ |
58 | IOSession upgrade(HttpHost host, IOSession iosession) throws IOException; | |
58 | IOSession upgrade(HttpHost host, IOSession ioSession) throws IOException; | |
59 | 59 | |
60 | 60 | } |
+19
-10
62 | 62 | */ |
63 | 63 | public class SSLIOSessionStrategy implements SchemeIOSessionStrategy { |
64 | 64 | |
65 | /** | |
66 | * @deprecated Do not use. | |
67 | */ | |
65 | 68 | @Deprecated |
66 | 69 | public static final X509HostnameVerifier ALLOW_ALL_HOSTNAME_VERIFIER = |
67 | 70 | new AllowAllHostnameVerifier(); |
68 | 71 | |
72 | /** | |
73 | * @deprecated Do not use. | |
74 | */ | |
69 | 75 | @Deprecated |
70 | 76 | public static final X509HostnameVerifier BROWSER_COMPATIBLE_HOSTNAME_VERIFIER = |
71 | 77 | new BrowserCompatHostnameVerifier(); |
72 | 78 | |
79 | /** | |
80 | * @deprecated Do not use. | |
81 | */ | |
73 | 82 | @Deprecated |
74 | 83 | public static final X509HostnameVerifier STRICT_HOSTNAME_VERIFIER = |
75 | 84 | new StrictHostnameVerifier(); |
159 | 168 | } |
160 | 169 | |
161 | 170 | @Override |
162 | public SSLIOSession upgrade(final HttpHost host, final IOSession iosession) throws IOException { | |
163 | Asserts.check(!(iosession instanceof SSLIOSession), "I/O session is already upgraded to TLS/SSL"); | |
164 | final SSLIOSession ssliosession = new SSLIOSession( | |
165 | iosession, | |
171 | public SSLIOSession upgrade(final HttpHost host, final IOSession ioSession) throws IOException { | |
172 | Asserts.check(!(ioSession instanceof SSLIOSession), "I/O session is already upgraded to TLS/SSL"); | |
173 | final SSLIOSession sslioSession = new SSLIOSession( | |
174 | ioSession, | |
166 | 175 | SSLMode.CLIENT, |
167 | 176 | host, |
168 | 177 | this.sslContext, |
182 | 191 | |
183 | 192 | @Override |
184 | 193 | public void verify( |
185 | final IOSession iosession, | |
194 | final IOSession ioSession, | |
186 | 195 | final SSLSession sslsession) throws SSLException { |
187 | verifySession(host, iosession, sslsession); | |
196 | verifySession(host, ioSession, sslsession); | |
188 | 197 | } |
189 | 198 | |
190 | 199 | }); |
191 | iosession.setAttribute(SSLIOSession.SESSION_KEY, ssliosession); | |
192 | ssliosession.initialize(); | |
193 | return ssliosession; | |
200 | ioSession.setAttribute(SSLIOSession.SESSION_KEY, sslioSession); | |
201 | sslioSession.initialize(); | |
202 | return sslioSession; | |
194 | 203 | } |
195 | 204 | |
196 | 205 | protected void initializeEngine(final SSLEngine engine) { |
198 | 207 | |
199 | 208 | protected void verifySession( |
200 | 209 | final HttpHost host, |
201 | final IOSession iosession, | |
210 | final IOSession ioSession, | |
202 | 211 | final SSLSession sslsession) throws SSLException { |
203 | 212 | if (!this.hostnameVerifier.verify(host.getHostName(), sslsession)) { |
204 | 213 | final Certificate[] certs = sslsession.getPeerCertificates(); |
+3
-3
131 | 131 | |
132 | 132 | protected AbstractHttpAsyncClient(final IOReactorConfig config) throws IOReactorException { |
133 | 133 | super(); |
134 | final DefaultConnectingIOReactor defaultioreactor = new DefaultConnectingIOReactor(config); | |
135 | defaultioreactor.setExceptionHandler(new InternalIOReactorExceptionHandler(this.log)); | |
136 | this.connmgr = new PoolingClientAsyncConnectionManager(defaultioreactor); | |
134 | final DefaultConnectingIOReactor defaultioReactor = new DefaultConnectingIOReactor(config); | |
135 | defaultioReactor.setExceptionHandler(new InternalIOReactorExceptionHandler(this.log)); | |
136 | this.connmgr = new PoolingClientAsyncConnectionManager(defaultioReactor); | |
137 | 137 | this.queue = new ConcurrentLinkedQueue<HttpAsyncRequestExecutionHandler<?>>(); |
138 | 138 | } |
139 | 139 |
+18
-22
104 | 104 | private final HttpContext localContext; |
105 | 105 | private final ResultCallback<T> resultCallback; |
106 | 106 | private final ClientAsyncConnectionManager connmgr; |
107 | private final HttpProcessor httppocessor; | |
107 | private final HttpProcessor httpPocessor; | |
108 | 108 | private final HttpRoutePlanner routePlanner; |
109 | 109 | private final HttpRouteDirector routeDirector; |
110 | 110 | private final ConnectionReuseStrategy reuseStrategy; |
144 | 144 | final HttpContext localContext, |
145 | 145 | final ResultCallback<T> callback, |
146 | 146 | final ClientAsyncConnectionManager connmgr, |
147 | final HttpProcessor httppocessor, | |
147 | final HttpProcessor httpPocessor, | |
148 | 148 | final HttpRoutePlanner routePlanner, |
149 | 149 | final ConnectionReuseStrategy reuseStrategy, |
150 | 150 | final ConnectionKeepAliveStrategy keepaliveStrategy, |
160 | 160 | this.localContext = localContext; |
161 | 161 | this.resultCallback = callback; |
162 | 162 | this.connmgr = connmgr; |
163 | this.httppocessor = httppocessor; | |
163 | this.httpPocessor = httpPocessor; | |
164 | 164 | this.routePlanner = routePlanner; |
165 | 165 | this.reuseStrategy = reuseStrategy; |
166 | 166 | this.keepaliveStrategy = keepaliveStrategy; |
327 | 327 | |
328 | 328 | @Override |
329 | 329 | public synchronized void produceContent( |
330 | final ContentEncoder encoder, final IOControl ioctrl) throws IOException { | |
330 | final ContentEncoder encoder, final IOControl ioControl) throws IOException { | |
331 | 331 | if (this.log.isDebugEnabled()) { |
332 | 332 | this.log.debug("[exchange: " + this.id + "] produce content"); |
333 | 333 | } |
334 | 334 | this.requestContentProduced = true; |
335 | this.requestProducer.produceContent(encoder, ioctrl); | |
335 | this.requestProducer.produceContent(encoder, ioControl); | |
336 | 336 | if (encoder.isCompleted()) { |
337 | 337 | this.requestProducer.resetRequest(); |
338 | 338 | } |
403 | 403 | |
404 | 404 | @Override |
405 | 405 | public synchronized void consumeContent( |
406 | final ContentDecoder decoder, final IOControl ioctrl) throws IOException { | |
406 | final ContentDecoder decoder, final IOControl ioControl) throws IOException { | |
407 | 407 | if (this.log.isDebugEnabled()) { |
408 | 408 | this.log.debug("[exchange: " + this.id + "] Consume content"); |
409 | 409 | } |
410 | 410 | if (this.finalResponse != null) { |
411 | this.responseConsumer.consumeContent(decoder, ioctrl); | |
411 | this.responseConsumer.consumeContent(decoder, ioControl); | |
412 | 412 | } else { |
413 | 413 | if (this.tmpbuf == null) { |
414 | 414 | this.tmpbuf = ByteBuffer.allocate(2048); |
686 | 686 | } |
687 | 687 | |
688 | 688 | private RequestWrapper wrapRequest(final HttpRequest request) throws ProtocolException { |
689 | if (request instanceof HttpEntityEnclosingRequest) { | |
690 | return new EntityEnclosingRequestWrapper((HttpEntityEnclosingRequest) request); | |
691 | } else { | |
692 | return new RequestWrapper(request); | |
693 | } | |
689 | return request instanceof HttpEntityEnclosingRequest | |
690 | ? new EntityEnclosingRequestWrapper((HttpEntityEnclosingRequest) request) | |
691 | : new RequestWrapper(request); | |
694 | 692 | } |
695 | 693 | |
696 | 694 | protected void rewriteRequestURI( |
771 | 769 | return null; |
772 | 770 | } |
773 | 771 | |
774 | private RoutedRequest handleConnectResponse() throws HttpException { | |
772 | private RoutedRequest handleConnectResponse() { | |
775 | 773 | RoutedRequest followup = null; |
776 | 774 | if (HttpClientParams.isAuthenticating(this.params)) { |
777 | 775 | final CredentialsProvider credsProvider = (CredentialsProvider) this.localContext.getAttribute( |
840 | 838 | } |
841 | 839 | |
842 | 840 | private RoutedRequest handleTargetChallenge( |
843 | final CredentialsProvider credsProvider) throws HttpException { | |
841 | final CredentialsProvider credsProvider) { | |
844 | 842 | final HttpRoute route = this.mainRequest.getRoute(); |
845 | 843 | HttpHost target = (HttpHost) this.localContext.getAttribute( |
846 | 844 | ExecutionContext.HTTP_TARGET_HOST); |
853 | 851 | this.targetAuthStrategy, this.targetAuthState, this.localContext)) { |
854 | 852 | // Re-try the same request via the same route |
855 | 853 | return this.mainRequest; |
856 | } else { | |
857 | return null; | |
858 | } | |
854 | } | |
855 | return null; | |
859 | 856 | } |
860 | 857 | return null; |
861 | 858 | } |
862 | 859 | |
863 | 860 | private RoutedRequest handleProxyChallenge( |
864 | final CredentialsProvider credsProvider) throws HttpException { | |
861 | final CredentialsProvider credsProvider) { | |
865 | 862 | final HttpRoute route = this.mainRequest.getRoute(); |
866 | 863 | final HttpHost proxy = route.getProxyHost(); |
867 | 864 | if (this.authenticator.isAuthenticationRequested(proxy, this.currentResponse, |
870 | 867 | this.proxyAuthStrategy, this.proxyAuthState, this.localContext)) { |
871 | 868 | // Re-try the same request via the same route |
872 | 869 | return this.mainRequest; |
873 | } else { | |
874 | return null; | |
875 | } | |
870 | } | |
871 | return null; | |
876 | 872 | } |
877 | 873 | return null; |
878 | 874 | } |
884 | 880 | |
885 | 881 | @Override |
886 | 882 | public HttpProcessor getHttpProcessor() { |
887 | return this.httppocessor; | |
883 | return this.httpPocessor; | |
888 | 884 | } |
889 | 885 | |
890 | 886 | @Override |
+20
-20
41 | 41 | public class DefaultClientAsyncConnection |
42 | 42 | extends DefaultNHttpClientConnection implements ClientAsyncConnection { |
43 | 43 | |
44 | private final Log headerlog = LogFactory.getLog("org.apache.http.headers"); | |
45 | private final Log wirelog = LogFactory.getLog("org.apache.http.wire"); | |
44 | private final Log headerLog = LogFactory.getLog("org.apache.http.headers"); | |
45 | private final Log wireLog = LogFactory.getLog("org.apache.http.wire"); | |
46 | 46 | private final Log log; |
47 | 47 | |
48 | 48 | private final String id; |
50 | 50 | |
51 | 51 | public DefaultClientAsyncConnection( |
52 | 52 | final String id, |
53 | final IOSession iosession, | |
53 | final IOSession ioSession, | |
54 | 54 | final HttpResponseFactory responseFactory, |
55 | 55 | final ByteBufferAllocator allocator, |
56 | 56 | final HttpParams params) { |
57 | super(iosession, responseFactory, allocator, params); | |
57 | super(ioSession, responseFactory, allocator, params); | |
58 | 58 | this.id = id; |
59 | this.original = iosession; | |
60 | this.log = LogFactory.getLog(iosession.getClass()); | |
61 | if (this.log.isDebugEnabled() || this.wirelog.isDebugEnabled()) { | |
62 | bind(new LoggingIOSession(iosession, this.id, this.log, this.wirelog)); | |
59 | this.original = ioSession; | |
60 | this.log = LogFactory.getLog(ioSession.getClass()); | |
61 | if (this.log.isDebugEnabled() || this.wireLog.isDebugEnabled()) { | |
62 | bind(new LoggingIOSession(ioSession, this.id, this.log, this.wireLog)); | |
63 | 63 | } |
64 | 64 | } |
65 | 65 | |
66 | 66 | @Override |
67 | public void upgrade(final IOSession iosession) { | |
68 | this.original = iosession; | |
69 | if (this.log.isDebugEnabled() || this.wirelog.isDebugEnabled()) { | |
70 | this.log.debug(this.id + " Upgrade session " + iosession); | |
71 | bind(new LoggingIOSession(iosession, this.id, this.headerlog, this.wirelog)); | |
67 | public void upgrade(final IOSession ioSession) { | |
68 | this.original = ioSession; | |
69 | if (this.log.isDebugEnabled() || this.wireLog.isDebugEnabled()) { | |
70 | this.log.debug(this.id + " Upgrade session " + ioSession); | |
71 | bind(new LoggingIOSession(ioSession, this.id, this.headerLog, this.wireLog)); | |
72 | 72 | } else { |
73 | bind(iosession); | |
73 | bind(ioSession); | |
74 | 74 | } |
75 | 75 | } |
76 | 76 | |
85 | 85 | |
86 | 86 | @Override |
87 | 87 | protected void onResponseReceived(final HttpResponse response) { |
88 | if (response != null && this.headerlog.isDebugEnabled()) { | |
89 | this.headerlog.debug(this.id + " << " + response.getStatusLine().toString()); | |
88 | if (response != null && this.headerLog.isDebugEnabled()) { | |
89 | this.headerLog.debug(this.id + " << " + response.getStatusLine().toString()); | |
90 | 90 | final Header[] headers = response.getAllHeaders(); |
91 | 91 | for (final Header header : headers) { |
92 | this.headerlog.debug(this.id + " << " + header.toString()); | |
92 | this.headerLog.debug(this.id + " << " + header.toString()); | |
93 | 93 | } |
94 | 94 | } |
95 | 95 | } |
96 | 96 | |
97 | 97 | @Override |
98 | 98 | protected void onRequestSubmitted(final HttpRequest request) { |
99 | if (request != null && this.headerlog.isDebugEnabled()) { | |
100 | this.headerlog.debug(this.id + " >> " + request.getRequestLine().toString()); | |
99 | if (request != null && this.headerLog.isDebugEnabled()) { | |
100 | this.headerLog.debug(this.id + " >> " + request.getRequestLine().toString()); | |
101 | 101 | final Header[] headers = request.getAllHeaders(); |
102 | 102 | for (final Header header : headers) { |
103 | this.headerlog.debug(this.id + " >> " + header.toString()); | |
103 | this.headerLog.debug(this.id + " >> " + header.toString()); | |
104 | 104 | } |
105 | 105 | } |
106 | 106 | } |
+18
-18
54 | 54 | public class DefaultClientAsyncConnectionFactory |
55 | 55 | implements ClientAsyncConnectionFactory, NHttpConnectionFactory<ManagedNHttpClientConnection> { |
56 | 56 | |
57 | private final Log headerlog = LogFactory.getLog("org.apache.http.headers"); | |
58 | private final Log wirelog = LogFactory.getLog("org.apache.http.wire"); | |
57 | private final Log headerLog = LogFactory.getLog("org.apache.http.headers"); | |
58 | private final Log wireLog = LogFactory.getLog("org.apache.http.wire"); | |
59 | 59 | private final Log log = LogFactory.getLog(ManagedNHttpClientConnectionImpl.class); |
60 | 60 | |
61 | 61 | public static final DefaultClientAsyncConnectionFactory INSTANCE = new DefaultClientAsyncConnectionFactory(null, null); |
88 | 88 | @Deprecated |
89 | 89 | public ClientAsyncConnection create( |
90 | 90 | final String id, |
91 | final IOSession iosession, | |
91 | final IOSession ioSession, | |
92 | 92 | final HttpParams params) { |
93 | 93 | return new DefaultClientAsyncConnection( |
94 | id, iosession, this.responseFactory, this.allocator, params); | |
94 | id, ioSession, this.responseFactory, this.allocator, params); | |
95 | 95 | } |
96 | 96 | |
97 | 97 | @Deprecated |
106 | 106 | |
107 | 107 | @Override |
108 | 108 | public ManagedNHttpClientConnection create( |
109 | final IOSession iosession, final ConnectionConfig config) { | |
109 | final IOSession ioSession, final ConnectionConfig config) { | |
110 | 110 | final String id = "http-outgoing-" + Long.toString(COUNTER.getAndIncrement()); |
111 | CharsetDecoder chardecoder = null; | |
112 | CharsetEncoder charencoder = null; | |
111 | CharsetDecoder charDecoder = null; | |
112 | CharsetEncoder charEncoder = null; | |
113 | 113 | final Charset charset = config.getCharset(); |
114 | 114 | final CodingErrorAction malformedInputAction = config.getMalformedInputAction() != null ? |
115 | 115 | config.getMalformedInputAction() : CodingErrorAction.REPORT; |
116 | 116 | final CodingErrorAction unmappableInputAction = config.getUnmappableInputAction() != null ? |
117 | 117 | config.getUnmappableInputAction() : CodingErrorAction.REPORT; |
118 | 118 | if (charset != null) { |
119 | chardecoder = charset.newDecoder(); | |
120 | chardecoder.onMalformedInput(malformedInputAction); | |
121 | chardecoder.onUnmappableCharacter(unmappableInputAction); | |
122 | charencoder = charset.newEncoder(); | |
123 | charencoder.onMalformedInput(malformedInputAction); | |
124 | charencoder.onUnmappableCharacter(unmappableInputAction); | |
119 | charDecoder = charset.newDecoder(); | |
120 | charDecoder.onMalformedInput(malformedInputAction); | |
121 | charDecoder.onUnmappableCharacter(unmappableInputAction); | |
122 | charEncoder = charset.newEncoder(); | |
123 | charEncoder.onMalformedInput(malformedInputAction); | |
124 | charEncoder.onUnmappableCharacter(unmappableInputAction); | |
125 | 125 | } |
126 | 126 | final ManagedNHttpClientConnection conn = new ManagedNHttpClientConnectionImpl( |
127 | 127 | id, |
128 | 128 | this.log, |
129 | this.headerlog, | |
130 | this.wirelog, | |
131 | iosession, | |
129 | this.headerLog, | |
130 | this.wireLog, | |
131 | ioSession, | |
132 | 132 | config.getBufferSize(), |
133 | 133 | config.getFragmentSizeHint(), |
134 | 134 | this.allocator, |
135 | chardecoder, charencoder, config.getMessageConstraints(), | |
135 | charDecoder, charEncoder, config.getMessageConstraints(), | |
136 | 136 | null, null, null, |
137 | 137 | this.responseParserFactory); |
138 | iosession.setAttribute(IOEventDispatch.CONNECTION_KEY, conn); | |
138 | ioSession.setAttribute(IOEventDispatch.CONNECTION_KEY, conn); | |
139 | 139 | return conn; |
140 | 140 | } |
141 | 141 |
+6
-6
47 | 47 | private final Log log; |
48 | 48 | private final AsyncSchemeRegistry schemeRegistry; |
49 | 49 | private final long connTimeToLive; |
50 | private final TimeUnit tunit; | |
50 | private final TimeUnit timeUnit; | |
51 | 51 | |
52 | 52 | HttpNIOConnPool( |
53 | 53 | final Log log, |
54 | final ConnectingIOReactor ioreactor, | |
54 | final ConnectingIOReactor ioReactor, | |
55 | 55 | final AsyncSchemeRegistry schemeRegistry, |
56 | final long connTimeToLive, final TimeUnit tunit) { | |
57 | super(ioreactor, new HttpNIOConnPoolFactory(), 2, 20); | |
56 | final long connTimeToLive, final TimeUnit timeUnit) { | |
57 | super(ioReactor, new HttpNIOConnPoolFactory(), 2, 20); | |
58 | 58 | this.log = log; |
59 | 59 | this.schemeRegistry = schemeRegistry; |
60 | 60 | this.connTimeToLive = connTimeToLive; |
61 | this.tunit = tunit; | |
61 | this.timeUnit = timeUnit; | |
62 | 62 | } |
63 | 63 | |
64 | 64 | @Override |
84 | 84 | @Override |
85 | 85 | protected HttpPoolEntry createEntry(final HttpRoute route, final IOSession session) { |
86 | 86 | final String id = Long.toString(COUNTER.getAndIncrement()); |
87 | return new HttpPoolEntry(this.log, id, route, session, this.connTimeToLive, this.tunit); | |
87 | return new HttpPoolEntry(this.log, id, route, session, this.connTimeToLive, this.timeUnit); | |
88 | 88 | } |
89 | 89 | |
90 | 90 | } |
+2
-2
44 | 44 | private final RouteTracker tracker; |
45 | 45 | |
46 | 46 | HttpPoolEntry(final Log log, final String id, final HttpRoute route, final IOSession session, |
47 | final long timeToLive, final TimeUnit tunit) { | |
48 | super(id, route, session, timeToLive, tunit); | |
47 | final long timeToLive, final TimeUnit timeUnit) { | |
48 | super(id, route, session, timeToLive, timeUnit); | |
49 | 49 | this.log = log; |
50 | 50 | this.tracker = new RouteTracker(route); |
51 | 51 | } |
+15
-25
133 | 133 | @Override |
134 | 134 | public boolean isOpen() { |
135 | 135 | final ClientAsyncConnection conn = getConnection(); |
136 | if (conn != null) { | |
137 | return conn.isOpen(); | |
138 | } else { | |
139 | return false; | |
140 | } | |
136 | return conn != null ? conn.isOpen() : false; | |
141 | 137 | } |
142 | 138 | |
143 | 139 | @Override |
274 | 270 | @Override |
275 | 271 | public SSLSession getSSLSession() { |
276 | 272 | final ClientAsyncConnection conn = ensureConnection(); |
277 | final IOSession iosession = conn.getIOSession(); | |
278 | if (iosession instanceof SSLIOSession) { | |
279 | return ((SSLIOSession) iosession).getSSLSession(); | |
280 | } else { | |
281 | return null; | |
282 | } | |
273 | final IOSession ioSession = conn.getIOSession(); | |
274 | return ioSession instanceof SSLIOSession | |
275 | ? ((SSLIOSession) ioSession).getSSLSession() | |
276 | : null; | |
283 | 277 | } |
284 | 278 | |
285 | 279 | @Override |
340 | 334 | |
341 | 335 | final HttpHost target = route.getTargetHost(); |
342 | 336 | final HttpHost proxy = route.getProxyHost(); |
343 | IOSession iosession = entry.getConnection(); | |
337 | IOSession ioSession = entry.getConnection(); | |
344 | 338 | |
345 | 339 | if (proxy == null) { |
346 | 340 | final AsyncScheme scheme = getSchemeRegistry(context).getScheme(target); |
347 | 341 | final LayeringStrategy layeringStrategy = scheme.getLayeringStrategy(); |
348 | 342 | if (layeringStrategy != null) { |
349 | iosession = layeringStrategy.layer(iosession); | |
343 | ioSession = layeringStrategy.layer(ioSession); | |
350 | 344 | } |
351 | 345 | } |
352 | 346 | |
353 | 347 | final ClientAsyncConnection conn = this.connFactory.create( |
354 | 348 | "http-outgoing-" + entry.getId(), |
355 | iosession, | |
349 | ioSession, | |
356 | 350 | params); |
357 | iosession.setAttribute(IOEventDispatch.CONNECTION_KEY, conn); | |
351 | ioSession.setAttribute(IOEventDispatch.CONNECTION_KEY, conn); | |
358 | 352 | |
359 | 353 | if (proxy == null) { |
360 | 354 | tracker.connectTarget(conn.getIOSession() instanceof SSLIOSession); |
409 | 403 | throw new IllegalStateException(scheme.getName() + |
410 | 404 | " scheme does not provider support for protocol layering"); |
411 | 405 | } |
412 | final IOSession iosession = entry.getConnection(); | |
413 | final ClientAsyncConnection conn = (ClientAsyncConnection) iosession.getAttribute( | |
406 | final IOSession ioSession = entry.getConnection(); | |
407 | final ClientAsyncConnection conn = (ClientAsyncConnection) ioSession.getAttribute( | |
414 | 408 | IOEventDispatch.CONNECTION_KEY); |
415 | conn.upgrade((SSLIOSession) layeringStrategy.layer(iosession)); | |
409 | conn.upgrade(layeringStrategy.layer(ioSession)); | |
416 | 410 | tracker.layerProtocol(layeringStrategy.isSecure()); |
417 | 411 | } |
418 | 412 | |
431 | 425 | return; |
432 | 426 | } |
433 | 427 | this.reusable = false; |
434 | final IOSession iosession = this.poolEntry.getConnection(); | |
435 | final ClientAsyncConnection conn = (ClientAsyncConnection) iosession.getAttribute( | |
428 | final IOSession ioSession = this.poolEntry.getConnection(); | |
429 | final ClientAsyncConnection conn = (ClientAsyncConnection) ioSession.getAttribute( | |
436 | 430 | IOEventDispatch.CONNECTION_KEY); |
437 | 431 | try { |
438 | 432 | conn.shutdown(); |
444 | 438 | |
445 | 439 | @Override |
446 | 440 | public synchronized String toString() { |
447 | if (this.poolEntry != null) { | |
448 | return this.poolEntry.toString(); | |
449 | } else { | |
450 | return "released"; | |
451 | } | |
441 | return this.poolEntry != null ? this.poolEntry.toString() : "released"; | |
452 | 442 | } |
453 | 443 | |
454 | 444 | } |
+24
-24
52 | 52 | |
53 | 53 | private final Log log = LogFactory.getLog(getClass()); |
54 | 54 | |
55 | private final ConnectingIOReactor ioreactor; | |
55 | private final ConnectingIOReactor ioReactor; | |
56 | 56 | private final HttpNIOConnPool pool; |
57 | 57 | private final AsyncSchemeRegistry schemeRegistry; |
58 | 58 | private final ClientAsyncConnectionFactory connFactory; |
59 | 59 | |
60 | 60 | public PoolingClientAsyncConnectionManager( |
61 | final ConnectingIOReactor ioreactor, | |
61 | final ConnectingIOReactor ioReactor, | |
62 | 62 | final AsyncSchemeRegistry schemeRegistry, |
63 | final long timeToLive, final TimeUnit tunit) { | |
63 | final long timeToLive, final TimeUnit timeUnit) { | |
64 | 64 | super(); |
65 | Args.notNull(ioreactor, "I/O reactor"); | |
65 | Args.notNull(ioReactor, "I/O reactor"); | |
66 | 66 | Args.notNull(schemeRegistry, "Scheme registory"); |
67 | Args.notNull(tunit, "Time unit"); | |
68 | this.ioreactor = ioreactor; | |
69 | this.pool = new HttpNIOConnPool(this.log, ioreactor, schemeRegistry, timeToLive, tunit); | |
67 | Args.notNull(timeUnit, "Time unit"); | |
68 | this.ioReactor = ioReactor; | |
69 | this.pool = new HttpNIOConnPool(this.log, ioReactor, schemeRegistry, timeToLive, timeUnit); | |
70 | 70 | this.schemeRegistry = schemeRegistry; |
71 | 71 | this.connFactory = createClientAsyncConnectionFactory(); |
72 | 72 | } |
73 | 73 | |
74 | 74 | public PoolingClientAsyncConnectionManager( |
75 | final ConnectingIOReactor ioreactor, | |
75 | final ConnectingIOReactor ioReactor, | |
76 | 76 | final AsyncSchemeRegistry schemeRegistry) throws IOReactorException { |
77 | this(ioreactor, schemeRegistry, -1, TimeUnit.MILLISECONDS); | |
77 | this(ioReactor, schemeRegistry, -1, TimeUnit.MILLISECONDS); | |
78 | 78 | } |
79 | 79 | |
80 | 80 | public PoolingClientAsyncConnectionManager( |
81 | final ConnectingIOReactor ioreactor) throws IOReactorException { | |
82 | this(ioreactor, AsyncSchemeRegistryFactory.createDefault()); | |
81 | final ConnectingIOReactor ioReactor) throws IOReactorException { | |
82 | this(ioReactor, AsyncSchemeRegistryFactory.createDefault()); | |
83 | 83 | } |
84 | 84 | |
85 | 85 | @Override |
102 | 102 | |
103 | 103 | @Override |
104 | 104 | public void execute(final IOEventDispatch eventDispatch) throws IOException { |
105 | this.ioreactor.execute(eventDispatch); | |
105 | this.ioReactor.execute(eventDispatch); | |
106 | 106 | } |
107 | 107 | |
108 | 108 | @Override |
109 | 109 | public IOReactorStatus getStatus() { |
110 | return this.ioreactor.getStatus(); | |
110 | return this.ioReactor.getStatus(); | |
111 | 111 | } |
112 | 112 | |
113 | 113 | @Override |
161 | 161 | final HttpRoute route, |
162 | 162 | final Object state, |
163 | 163 | final long connectTimeout, |
164 | final TimeUnit tunit, | |
164 | final TimeUnit timeUnit, | |
165 | 165 | final FutureCallback<ManagedClientAsyncConnection> callback) { |
166 | 166 | Args.notNull(route, "HTTP route"); |
167 | Args.notNull(tunit, "Time unit"); | |
167 | Args.notNull(timeUnit, "Time unit"); | |
168 | 168 | if (this.log.isDebugEnabled()) { |
169 | 169 | this.log.debug("Connection request: " + format(route, state) + formatStats(route)); |
170 | 170 | } |
171 | 171 | final BasicFuture<ManagedClientAsyncConnection> future = new BasicFuture<ManagedClientAsyncConnection>( |
172 | 172 | callback); |
173 | this.pool.lease(route, state, connectTimeout, tunit, new InternalPoolEntryCallback(future)); | |
173 | this.pool.lease(route, state, connectTimeout, timeUnit, new InternalPoolEntryCallback(future)); | |
174 | 174 | return future; |
175 | 175 | } |
176 | 176 | |
178 | 178 | public void releaseConnection( |
179 | 179 | final ManagedClientAsyncConnection conn, |
180 | 180 | final long keepalive, |
181 | final TimeUnit tunit) { | |
181 | final TimeUnit timeUnit) { | |
182 | 182 | Args.notNull(conn, "HTTP connection"); |
183 | 183 | if (!(conn instanceof ManagedClientAsyncConnectionImpl)) { |
184 | 184 | throw new IllegalArgumentException("Connection class mismatch, " + |
185 | 185 | "connection not obtained from this manager"); |
186 | 186 | } |
187 | Args.notNull(tunit, "Time unit"); | |
187 | Args.notNull(timeUnit, "Time unit"); | |
188 | 188 | final ManagedClientAsyncConnectionImpl managedConn = (ManagedClientAsyncConnectionImpl) conn; |
189 | 189 | final ClientAsyncConnectionManager manager = managedConn.getManager(); |
190 | 190 | if (manager != null && manager != this) { |
210 | 210 | } |
211 | 211 | } |
212 | 212 | if (managedConn.isOpen()) { |
213 | entry.updateExpiry(keepalive, tunit != null ? tunit : TimeUnit.MILLISECONDS); | |
213 | entry.updateExpiry(keepalive, timeUnit != null ? timeUnit : TimeUnit.MILLISECONDS); | |
214 | 214 | if (this.log.isDebugEnabled()) { |
215 | 215 | final String s; |
216 | 216 | if (keepalive > 0) { |
217 | s = "for " + keepalive + " " + tunit; | |
217 | s = "for " + keepalive + " " + timeUnit; | |
218 | 218 | } else { |
219 | 219 | s = "indefinitely"; |
220 | 220 | } |
272 | 272 | return this.pool.getMaxPerRoute(route); |
273 | 273 | } |
274 | 274 | |
275 | public void closeIdleConnections(final long idleTimeout, final TimeUnit tunit) { | |
275 | public void closeIdleConnections(final long idleTimeout, final TimeUnit timeUnit) { | |
276 | 276 | if (log.isDebugEnabled()) { |
277 | log.debug("Closing connections idle longer than " + idleTimeout + " " + tunit); | |
278 | } | |
279 | this.pool.closeIdle(idleTimeout, tunit); | |
277 | log.debug("Closing connections idle longer than " + idleTimeout + " " + timeUnit); | |
278 | } | |
279 | this.pool.closeIdle(idleTimeout, timeUnit); | |
280 | 280 | } |
281 | 281 | |
282 | 282 | public void closeExpiredConnections() { |
+1
-1
32 | 32 | @Deprecated |
33 | 33 | public interface ClientAsyncConnection extends NHttpClientConnection, HttpInetConnection { |
34 | 34 | |
35 | void upgrade(IOSession iosession); | |
35 | void upgrade(IOSession ioSession); | |
36 | 36 | |
37 | 37 | IOSession getIOSession(); |
38 | 38 |
+1
-1
31 | 31 | @Deprecated |
32 | 32 | public interface ClientAsyncConnectionFactory { |
33 | 33 | |
34 | ClientAsyncConnection create(String id, IOSession iosession, HttpParams params); | |
34 | ClientAsyncConnection create(String id, IOSession ioSession, HttpParams params); | |
35 | 35 | |
36 | 36 | } |
+1
-1
58 | 58 | |
59 | 59 | void layerProtocol(HttpContext context, HttpParams params) throws IOException; |
60 | 60 | |
61 | void setIdleDuration(long duration, TimeUnit tunit); | |
61 | void setIdleDuration(long duration, TimeUnit timeUnit); | |
62 | 62 | |
63 | 63 | } |
+1
-2
98 | 98 | return this.name.equals(that.name) |
99 | 99 | && this.defaultPort == that.defaultPort |
100 | 100 | && this.strategy.equals(that.strategy); |
101 | } else { | |
102 | return false; | |
103 | 101 | } |
102 | return false; | |
104 | 103 | } |
105 | 104 | |
106 | 105 | @Override |
+1
-1
32 | 32 | |
33 | 33 | boolean isSecure(); |
34 | 34 | |
35 | IOSession layer(IOSession iosession); | |
35 | IOSession layer(IOSession ioSession); | |
36 | 36 | |
37 | 37 | } |
+9
-9
183 | 183 | } |
184 | 184 | |
185 | 185 | @Override |
186 | public SSLIOSession layer(final IOSession iosession) { | |
187 | final SSLIOSession ssliosession = new SSLIOSession( | |
188 | iosession, | |
186 | public SSLIOSession layer(final IOSession ioSession) { | |
187 | final SSLIOSession sslioSession = new SSLIOSession( | |
188 | ioSession, | |
189 | 189 | SSLMode.CLIENT, |
190 | 190 | this.sslContext, |
191 | 191 | new SSLSetupHandler() { |
198 | 198 | |
199 | 199 | @Override |
200 | 200 | public void verify( |
201 | final IOSession iosession, | |
201 | final IOSession ioSession, | |
202 | 202 | final SSLSession sslsession) throws SSLException { |
203 | verifySession(iosession, sslsession); | |
203 | verifySession(ioSession, sslsession); | |
204 | 204 | } |
205 | 205 | |
206 | 206 | }); |
207 | iosession.setAttribute(SSLIOSession.SESSION_KEY, ssliosession); | |
208 | return ssliosession; | |
207 | ioSession.setAttribute(SSLIOSession.SESSION_KEY, sslioSession); | |
208 | return sslioSession; | |
209 | 209 | } |
210 | 210 | |
211 | 211 | protected void initializeEngine(final SSLEngine engine) { |
212 | 212 | } |
213 | 213 | |
214 | 214 | protected void verifySession( |
215 | final IOSession iosession, | |
215 | final IOSession ioSession, | |
216 | 216 | final SSLSession sslsession) throws SSLException { |
217 | final InetSocketAddress address = (InetSocketAddress) iosession.getRemoteAddress(); | |
217 | final InetSocketAddress address = (InetSocketAddress) ioSession.getRemoteAddress(); | |
218 | 218 | |
219 | 219 | final Certificate[] certs = sslsession.getPeerCertificates(); |
220 | 220 | final X509Certificate x509 = (X509Certificate) certs[0]; |
+72
-71
60 | 60 | import org.junit.Test; |
61 | 61 | import org.mockito.ArgumentCaptor; |
62 | 62 | import org.mockito.Captor; |
63 | import org.mockito.Matchers; | |
63 | 64 | import org.mockito.Mock; |
64 | 65 | import org.mockito.Mockito; |
65 | 66 | import org.mockito.MockitoAnnotations; |
67 | 68 | public class TestPoolingHttpClientAsyncConnectionManager { |
68 | 69 | |
69 | 70 | @Mock |
70 | private ConnectingIOReactor ioreactor; | |
71 | private ConnectingIOReactor ioReactor; | |
71 | 72 | @Mock |
72 | 73 | private CPool pool; |
73 | 74 | @Mock |
89 | 90 | @Mock |
90 | 91 | private SessionRequest sessionRequest; |
91 | 92 | @Mock |
92 | private IOSession iosession; | |
93 | private IOSession ioSession; | |
93 | 94 | |
94 | 95 | private Registry<SchemeIOSessionStrategy> layeringStrategyRegistry; |
95 | 96 | private PoolingNHttpClientConnectionManager connman; |
104 | 105 | .register("https", sslStrategy) |
105 | 106 | .build(); |
106 | 107 | connman = new PoolingNHttpClientConnectionManager( |
107 | ioreactor, pool, layeringStrategyRegistry); | |
108 | ioReactor, pool, layeringStrategyRegistry); | |
108 | 109 | } |
109 | 110 | |
110 | 111 | @Test |
130 | 131 | Assert.assertNotNull(future); |
131 | 132 | |
132 | 133 | Mockito.verify(pool).lease( |
133 | Mockito.same(route), | |
134 | Mockito.eq("some state"), | |
135 | Mockito.eq(1000L), | |
136 | Mockito.eq(2000L), | |
137 | Mockito.eq(TimeUnit.MILLISECONDS), | |
134 | Matchers.same(route), | |
135 | Matchers.eq("some state"), | |
136 | Matchers.eq(1000L), | |
137 | Matchers.eq(2000L), | |
138 | Matchers.eq(TimeUnit.MILLISECONDS), | |
138 | 139 | poolEntryCallbackCaptor.capture()); |
139 | 140 | final FutureCallback<CPoolEntry> callaback = poolEntryCallbackCaptor.getValue(); |
140 | 141 | final Log log = Mockito.mock(Log.class); |
144 | 145 | |
145 | 146 | Assert.assertTrue(future.isDone()); |
146 | 147 | final NHttpClientConnection managedConn = future.get(); |
147 | Mockito.verify(connCallback).completed(Mockito.<NHttpClientConnection>any()); | |
148 | Mockito.verify(connCallback).completed(Matchers.<NHttpClientConnection>any()); | |
148 | 149 | |
149 | 150 | Mockito.when(conn.isOpen()).thenReturn(Boolean.TRUE); |
150 | 151 | connman.releaseConnection(managedConn, "new state", 5, TimeUnit.SECONDS); |
166 | 167 | Assert.assertNotNull(future); |
167 | 168 | |
168 | 169 | Mockito.verify(pool).lease( |
169 | Mockito.same(route), | |
170 | Mockito.eq("some state"), | |
171 | Mockito.eq(1000L), | |
172 | Mockito.eq(2000L), | |
173 | Mockito.eq(TimeUnit.MILLISECONDS), | |
170 | Matchers.same(route), | |
171 | Matchers.eq("some state"), | |
172 | Matchers.eq(1000L), | |
173 | Matchers.eq(2000L), | |
174 | Matchers.eq(TimeUnit.MILLISECONDS), | |
174 | 175 | poolEntryCallbackCaptor.capture()); |
175 | 176 | final FutureCallback<CPoolEntry> callaback = poolEntryCallbackCaptor.getValue(); |
176 | 177 | final Log log = Mockito.mock(Log.class); |
179 | 180 | |
180 | 181 | Assert.assertTrue(future.isDone()); |
181 | 182 | final NHttpClientConnection managedConn = future.get(); |
182 | Mockito.verify(connCallback).completed(Mockito.<NHttpClientConnection>any()); | |
183 | Mockito.verify(connCallback).completed(Matchers.<NHttpClientConnection>any()); | |
183 | 184 | |
184 | 185 | Mockito.when(conn.isOpen()).thenReturn(Boolean.TRUE); |
185 | 186 | connman.releaseConnection(managedConn, "new state", 5, TimeUnit.SECONDS); |
197 | 198 | future.cancel(true); |
198 | 199 | |
199 | 200 | Mockito.verify(pool).lease( |
200 | Mockito.same(route), | |
201 | Mockito.eq("some state"), | |
202 | Mockito.eq(1000L), | |
203 | Mockito.eq(2000L), | |
204 | Mockito.eq(TimeUnit.MILLISECONDS), | |
201 | Matchers.same(route), | |
202 | Matchers.eq("some state"), | |
203 | Matchers.eq(1000L), | |
204 | Matchers.eq(2000L), | |
205 | Matchers.eq(TimeUnit.MILLISECONDS), | |
205 | 206 | poolEntryCallbackCaptor.capture()); |
206 | 207 | final FutureCallback<CPoolEntry> callaback = poolEntryCallbackCaptor.getValue(); |
207 | 208 | final Log log = Mockito.mock(Log.class); |
221 | 222 | Assert.assertNotNull(future); |
222 | 223 | |
223 | 224 | Mockito.verify(pool).lease( |
224 | Mockito.same(route), | |
225 | Mockito.eq("some state"), | |
226 | Mockito.eq(1000L), | |
227 | Mockito.eq(2000L), | |
228 | Mockito.eq(TimeUnit.MILLISECONDS), | |
225 | Matchers.same(route), | |
226 | Matchers.eq("some state"), | |
227 | Matchers.eq(1000L), | |
228 | Matchers.eq(2000L), | |
229 | Matchers.eq(TimeUnit.MILLISECONDS), | |
229 | 230 | poolEntryCallbackCaptor.capture()); |
230 | 231 | final FutureCallback<CPoolEntry> callaback = poolEntryCallbackCaptor.getValue(); |
231 | 232 | callaback.failed(new Exception()); |
243 | 244 | Assert.assertNotNull(future); |
244 | 245 | |
245 | 246 | Mockito.verify(pool).lease( |
246 | Mockito.same(route), | |
247 | Mockito.eq("some state"), | |
248 | Mockito.eq(1000L), | |
249 | Mockito.eq(2000L), | |
250 | Mockito.eq(TimeUnit.MILLISECONDS), | |
247 | Matchers.same(route), | |
248 | Matchers.eq("some state"), | |
249 | Matchers.eq(1000L), | |
250 | Matchers.eq(2000L), | |
251 | Matchers.eq(TimeUnit.MILLISECONDS), | |
251 | 252 | poolEntryCallbackCaptor.capture()); |
252 | 253 | final FutureCallback<CPoolEntry> callaback = poolEntryCallbackCaptor.getValue(); |
253 | 254 | callaback.cancelled(); |
267 | 268 | final CPoolEntry poolentry = new CPoolEntry(log, "some-id", route, conn, -1, TimeUnit.MILLISECONDS); |
268 | 269 | final NHttpClientConnection managedConn = CPoolProxy.newProxy(poolentry); |
269 | 270 | |
270 | Mockito.when(conn.getIOSession()).thenReturn(iosession); | |
271 | Mockito.when(sslStrategy.upgrade(target, iosession)).thenReturn(iosession); | |
271 | Mockito.when(conn.getIOSession()).thenReturn(ioSession); | |
272 | Mockito.when(sslStrategy.upgrade(target, ioSession)).thenReturn(ioSession); | |
272 | 273 | |
273 | 274 | connman.startRoute(managedConn, route, context); |
274 | 275 | |
275 | Mockito.verify(noopStrategy, Mockito.never()).upgrade(target, iosession); | |
276 | Mockito.verify(conn, Mockito.never()).bind(iosession); | |
276 | Mockito.verify(noopStrategy, Mockito.never()).upgrade(target, ioSession); | |
277 | Mockito.verify(conn, Mockito.never()).bind(ioSession); | |
277 | 278 | |
278 | 279 | Assert.assertFalse(connman.isRouteComplete(managedConn)); |
279 | 280 | } |
289 | 290 | poolentry.markRouteComplete(); |
290 | 291 | final NHttpClientConnection managedConn = CPoolProxy.newProxy(poolentry); |
291 | 292 | |
292 | Mockito.when(conn.getIOSession()).thenReturn(iosession); | |
293 | Mockito.when(sslStrategy.upgrade(target, iosession)).thenReturn(iosession); | |
293 | Mockito.when(conn.getIOSession()).thenReturn(ioSession); | |
294 | Mockito.when(sslStrategy.upgrade(target, ioSession)).thenReturn(ioSession); | |
294 | 295 | |
295 | 296 | connman.startRoute(managedConn, route, context); |
296 | 297 | |
297 | Mockito.verify(sslStrategy).upgrade(target, iosession); | |
298 | Mockito.verify(conn).bind(iosession); | |
298 | Mockito.verify(sslStrategy).upgrade(target, ioSession); | |
299 | Mockito.verify(conn).bind(ioSession); | |
299 | 300 | } |
300 | 301 | |
301 | 302 | @Test |
313 | 314 | final CPoolEntry poolentry = new CPoolEntry(log, "some-id", route, conn, -1, TimeUnit.MILLISECONDS); |
314 | 315 | final NHttpClientConnection managedConn = CPoolProxy.newProxy(poolentry); |
315 | 316 | |
316 | Mockito.when(conn.getIOSession()).thenReturn(iosession); | |
317 | Mockito.when(sslStrategy.upgrade(target, iosession)).thenReturn(iosession); | |
317 | Mockito.when(conn.getIOSession()).thenReturn(ioSession); | |
318 | Mockito.when(sslStrategy.upgrade(target, ioSession)).thenReturn(ioSession); | |
318 | 319 | |
319 | 320 | connman.startRoute(managedConn, route, context); |
320 | 321 | |
321 | Mockito.verify(noopStrategy, Mockito.never()).upgrade(target, iosession); | |
322 | Mockito.verify(conn, Mockito.never()).bind(iosession); | |
322 | Mockito.verify(noopStrategy, Mockito.never()).upgrade(target, ioSession); | |
323 | Mockito.verify(conn, Mockito.never()).bind(ioSession); | |
323 | 324 | |
324 | 325 | Assert.assertFalse(connman.isRouteComplete(managedConn)); |
325 | 326 | } |
335 | 336 | poolentry.markRouteComplete(); |
336 | 337 | final NHttpClientConnection managedConn = CPoolProxy.newProxy(poolentry); |
337 | 338 | |
338 | Mockito.when(conn.getIOSession()).thenReturn(iosession); | |
339 | Mockito.when(sslStrategy.upgrade(target, iosession)).thenReturn(iosession); | |
339 | Mockito.when(conn.getIOSession()).thenReturn(ioSession); | |
340 | Mockito.when(sslStrategy.upgrade(target, ioSession)).thenReturn(ioSession); | |
340 | 341 | |
341 | 342 | connman.startRoute(managedConn, route, context); |
342 | 343 | } |
352 | 353 | poolentry.markRouteComplete(); |
353 | 354 | final NHttpClientConnection managedConn = CPoolProxy.newProxy(poolentry); |
354 | 355 | |
355 | Mockito.when(conn.getIOSession()).thenReturn(iosession); | |
356 | Mockito.when(sslStrategy.upgrade(target, iosession)).thenReturn(iosession); | |
356 | Mockito.when(conn.getIOSession()).thenReturn(ioSession); | |
357 | Mockito.when(sslStrategy.upgrade(target, ioSession)).thenReturn(ioSession); | |
357 | 358 | |
358 | 359 | connman.upgrade(managedConn, route, context); |
359 | 360 | |
360 | Mockito.verify(sslStrategy).upgrade(target, iosession); | |
361 | Mockito.verify(conn).bind(iosession); | |
361 | Mockito.verify(sslStrategy).upgrade(target, ioSession); | |
362 | Mockito.verify(conn).bind(ioSession); | |
362 | 363 | } |
363 | 364 | |
364 | 365 | @Test(expected=UnsupportedSchemeException.class) |
372 | 373 | poolentry.markRouteComplete(); |
373 | 374 | final NHttpClientConnection managedConn = CPoolProxy.newProxy(poolentry); |
374 | 375 | |
375 | Mockito.when(conn.getIOSession()).thenReturn(iosession); | |
376 | Mockito.when(sslStrategy.upgrade(target, iosession)).thenReturn(iosession); | |
376 | Mockito.when(conn.getIOSession()).thenReturn(ioSession); | |
377 | Mockito.when(sslStrategy.upgrade(target, ioSession)).thenReturn(ioSession); | |
377 | 378 | |
378 | 379 | connman.upgrade(managedConn, route, context); |
379 | 380 | } |
389 | 390 | poolentry.markRouteComplete(); |
390 | 391 | final NHttpClientConnection managedConn = CPoolProxy.newProxy(poolentry); |
391 | 392 | |
392 | Mockito.when(conn.getIOSession()).thenReturn(iosession); | |
393 | Mockito.when(sslStrategy.upgrade(target, iosession)).thenReturn(iosession); | |
393 | Mockito.when(conn.getIOSession()).thenReturn(ioSession); | |
394 | Mockito.when(sslStrategy.upgrade(target, ioSession)).thenReturn(ioSession); | |
394 | 395 | |
395 | 396 | connman.upgrade(managedConn, route, context); |
396 | 397 | } |
406 | 407 | poolentry.markRouteComplete(); |
407 | 408 | final NHttpClientConnection managedConn = CPoolProxy.newProxy(poolentry); |
408 | 409 | |
409 | Mockito.when(conn.getIOSession()).thenReturn(iosession); | |
410 | Mockito.when(sslStrategy.upgrade(target, iosession)).thenReturn(iosession); | |
410 | Mockito.when(conn.getIOSession()).thenReturn(ioSession); | |
411 | Mockito.when(sslStrategy.upgrade(target, ioSession)).thenReturn(ioSession); | |
411 | 412 | |
412 | 413 | connman.startRoute(managedConn, route, context); |
413 | 414 | connman.routeComplete(managedConn, route, context); |
456 | 457 | configData, connFactory); |
457 | 458 | |
458 | 459 | final HttpRoute route = new HttpRoute(new HttpHost("somehost", 80)); |
459 | internalConnFactory.create(route, iosession); | |
460 | ||
461 | Mockito.verify(sslStrategy, Mockito.never()).upgrade(Mockito.eq(new HttpHost("somehost", 80)), | |
462 | Mockito.<IOSession>any()); | |
463 | Mockito.verify(connFactory).create(Mockito.same(iosession), Mockito.<ConnectionConfig>any()); | |
460 | internalConnFactory.create(route, ioSession); | |
461 | ||
462 | Mockito.verify(sslStrategy, Mockito.never()).upgrade(Matchers.eq(new HttpHost("somehost", 80)), | |
463 | Matchers.<IOSession>any()); | |
464 | Mockito.verify(connFactory).create(Matchers.same(ioSession), Matchers.<ConnectionConfig>any()); | |
464 | 465 | } |
465 | 466 | |
466 | 467 | @Test |
476 | 477 | final ConnectionConfig config = ConnectionConfig.custom().build(); |
477 | 478 | configData.setConnectionConfig(proxy, config); |
478 | 479 | |
479 | internalConnFactory.create(route, iosession); | |
480 | ||
481 | Mockito.verify(connFactory).create(iosession, config); | |
480 | internalConnFactory.create(route, ioSession); | |
481 | ||
482 | Mockito.verify(connFactory).create(ioSession, config); | |
482 | 483 | } |
483 | 484 | |
484 | 485 | @Test |
493 | 494 | final ConnectionConfig config = ConnectionConfig.custom().build(); |
494 | 495 | configData.setConnectionConfig(target, config); |
495 | 496 | |
496 | internalConnFactory.create(route, iosession); | |
497 | ||
498 | Mockito.verify(connFactory).create(iosession, config); | |
497 | internalConnFactory.create(route, ioSession); | |
498 | ||
499 | Mockito.verify(connFactory).create(ioSession, config); | |
499 | 500 | } |
500 | 501 | |
501 | 502 | @Test |
510 | 511 | final ConnectionConfig config = ConnectionConfig.custom().build(); |
511 | 512 | configData.setDefaultConnectionConfig(config); |
512 | 513 | |
513 | internalConnFactory.create(route, iosession); | |
514 | ||
515 | Mockito.verify(connFactory).create(iosession, config); | |
514 | internalConnFactory.create(route, ioSession); | |
515 | ||
516 | Mockito.verify(connFactory).create(ioSession, config); | |
516 | 517 | } |
517 | 518 | |
518 | 519 | @Test |
526 | 527 | |
527 | 528 | configData.setDefaultConnectionConfig(null); |
528 | 529 | |
529 | internalConnFactory.create(route, iosession); | |
530 | ||
531 | Mockito.verify(connFactory).create(iosession, ConnectionConfig.DEFAULT); | |
530 | internalConnFactory.create(route, ioSession); | |
531 | ||
532 | Mockito.verify(connFactory).create(ioSession, ConnectionConfig.DEFAULT); | |
532 | 533 | } |
533 | 534 | |
534 | 535 | @Test |
54 | 54 | |
55 | 55 | public abstract class AbstractAsyncTest { |
56 | 56 | |
57 | public enum ProtocolScheme { http, https }; | |
57 | public enum ProtocolScheme { http, https } | |
58 | 58 | |
59 | 59 | protected final ProtocolScheme scheme; |
60 | 60 |
+1
-1
216 | 216 | final BasicAsyncResponseConsumer responseConsumer = new BasicAsyncResponseConsumer() { |
217 | 217 | |
218 | 218 | @Override |
219 | public void onContentReceived(final ContentDecoder decoder, final IOControl ioctrl) | |
219 | public void onContentReceived(final ContentDecoder decoder, final IOControl ioControl) | |
220 | 220 | throws IOException { |
221 | 221 | throw new IOException("Kaboom"); |
222 | 222 | } |
+4
-4
199 | 199 | @Override |
200 | 200 | public synchronized void produceContent( |
201 | 201 | final ContentEncoder encoder, |
202 | final IOControl ioctrl) throws IOException { | |
203 | ioctrl.shutdown(); | |
202 | final IOControl ioControl) throws IOException { | |
203 | ioControl.shutdown(); | |
204 | 204 | } |
205 | 205 | |
206 | 206 | }); |
276 | 276 | |
277 | 277 | @Override |
278 | 278 | public void consumeContent( |
279 | final ContentDecoder decoder, final IOControl ioctrl) throws IOException { | |
279 | final ContentDecoder decoder, final IOControl ioControl) throws IOException { | |
280 | 280 | throw new IllegalStateException(); |
281 | 281 | } |
282 | 282 | |
358 | 358 | |
359 | 359 | @Override |
360 | 360 | public void consumeContent( |
361 | final ContentDecoder decoder, final IOControl ioctrl) throws IOException { | |
361 | final ContentDecoder decoder, final IOControl ioControl) throws IOException { | |
362 | 362 | } |
363 | 363 | |
364 | 364 | @Override |
+1
-1
181 | 181 | @Override |
182 | 182 | protected void onContentReceived( |
183 | 183 | final ContentDecoder decoder, |
184 | final IOControl ioctrl) throws IOException { | |
184 | final IOControl ioControl) throws IOException { | |
185 | 185 | final ByteBuffer buf = ByteBuffer.allocate(2048); |
186 | 186 | decoder.read(buf); |
187 | 187 | } |
+6
-5
47 | 47 | import org.junit.Assert; |
48 | 48 | import org.junit.Before; |
49 | 49 | import org.junit.Test; |
50 | import org.mockito.Matchers; | |
50 | 51 | import org.mockito.Mockito; |
51 | 52 | |
52 | 53 | public class TestAsyncConsumers extends HttpAsyncTestBase { |
75 | 76 | } |
76 | 77 | |
77 | 78 | @Override |
78 | protected void onByteReceived(final ByteBuffer buf, final IOControl ioctrl) { | |
79 | protected void onByteReceived(final ByteBuffer buf, final IOControl ioControl) { | |
79 | 80 | this.count.addAndGet(buf.remaining()); |
80 | 81 | } |
81 | 82 | |
127 | 128 | } |
128 | 129 | |
129 | 130 | @Override |
130 | protected void onCharReceived(final CharBuffer buf, final IOControl ioctrl) throws IOException { | |
131 | protected void onCharReceived(final CharBuffer buf, final IOControl ioControl) throws IOException { | |
131 | 132 | while (buf.hasRemaining()) { |
132 | 133 | this.sb.append(buf.get()); |
133 | 134 | } |
205 | 206 | final Future<String> future = this.httpclient.execute(httppost, consumer, null); |
206 | 207 | final String result = future.get(); |
207 | 208 | Assert.assertEquals(s, result); |
208 | Mockito.verify(consumer).buildResult(Mockito.any(HttpContext.class)); | |
209 | Mockito.verify(consumer).buildResult(Matchers.any(HttpContext.class)); | |
209 | 210 | Mockito.verify(consumer).releaseResources(); |
210 | 211 | } |
211 | 212 | |
217 | 218 | ContentType.create("text/plain", Consts.ASCII)); |
218 | 219 | final AsyncCharConsumer<String> consumer = Mockito.spy(new BufferingCharConsumer()); |
219 | 220 | Mockito.doThrow(new IOException("Kaboom")).when(consumer).onCharReceived( |
220 | Mockito.any(CharBuffer.class), Mockito.any(IOControl.class)); | |
221 | Matchers.any(CharBuffer.class), Matchers.any(IOControl.class)); | |
221 | 222 | |
222 | 223 | final Future<String> future = this.httpclient.execute(httppost, consumer, null); |
223 | 224 | try { |
239 | 240 | target.toURI() + "/echo/stuff", "stuff", |
240 | 241 | ContentType.create("text/plain", Consts.ASCII)); |
241 | 242 | final BufferingCharConsumer consumer = Mockito.spy(new BufferingCharConsumer()); |
242 | Mockito.doThrow(new HttpException("Kaboom")).when(consumer).buildResult(Mockito.any(HttpContext.class)); | |
243 | Mockito.doThrow(new HttpException("Kaboom")).when(consumer).buildResult(Matchers.any(HttpContext.class)); | |
243 | 244 | |
244 | 245 | final Future<String> future = this.httpclient.execute(httppost, consumer, null); |
245 | 246 | try { |
173 | 173 | |
174 | 174 | boolean ok = true; |
175 | 175 | |
176 | final InputStream instream = requestEntity.getContent(); | |
176 | final InputStream inStream = requestEntity.getContent(); | |
177 | 177 | try { |
178 | 178 | final ContentType contentType = ContentType.getOrDefault(requestEntity); |
179 | 179 | Charset charset = contentType.getCharset(); |
180 | 180 | if (charset == null) { |
181 | 181 | charset = Consts.ISO_8859_1; |
182 | 182 | } |
183 | final LineIterator it = IOUtils.lineIterator(instream, charset.name()); | |
183 | final LineIterator it = IOUtils.lineIterator(inStream, charset.name()); | |
184 | 184 | int count = 0; |
185 | 185 | while (it.hasNext()) { |
186 | 186 | final String line = it.next(); |
193 | 193 | count++; |
194 | 194 | } |
195 | 195 | } finally { |
196 | instream.close(); | |
196 | inStream.close(); | |
197 | 197 | } |
198 | 198 | if (ok) { |
199 | 199 | final NFileEntity responseEntity = new NFileEntity(TEST_FILE, |
221 | 221 | final Integer status = future.get(); |
222 | 222 | Assert.assertNotNull(status); |
223 | 223 | Assert.assertEquals(HttpStatus.SC_OK, status.intValue()); |
224 | final InputStream instream = new FileInputStream(this.tmpfile); | |
224 | final InputStream inStream = new FileInputStream(this.tmpfile); | |
225 | 225 | try { |
226 | final LineIterator it = IOUtils.lineIterator(instream, ASCII.name()); | |
226 | final LineIterator it = IOUtils.lineIterator(inStream, ASCII.name()); | |
227 | 227 | int count = 0; |
228 | 228 | while (it.hasNext()) { |
229 | 229 | final String line = it.next(); |
233 | 233 | count++; |
234 | 234 | } |
235 | 235 | } finally { |
236 | instream.close(); | |
236 | inStream.close(); | |
237 | 237 | } |
238 | 238 | } |
239 | 239 | |
249 | 249 | final Integer status = future.get(); |
250 | 250 | Assert.assertNotNull(status); |
251 | 251 | Assert.assertEquals(HttpStatus.SC_OK, status.intValue()); |
252 | final InputStream instream = new FileInputStream(this.tmpfile); | |
252 | final InputStream inStream = new FileInputStream(this.tmpfile); | |
253 | 253 | try { |
254 | final LineIterator it = IOUtils.lineIterator(instream, ASCII.name()); | |
254 | final LineIterator it = IOUtils.lineIterator(inStream, ASCII.name()); | |
255 | 255 | int count = 0; |
256 | 256 | while (it.hasNext()) { |
257 | 257 | final String line = it.next(); |
261 | 261 | count++; |
262 | 262 | } |
263 | 263 | } finally { |
264 | instream.close(); | |
264 | inStream.close(); | |
265 | 265 | } |
266 | 266 | } |
267 | 267 |
27 | 27 | <parent> |
28 | 28 | <groupId>org.apache.httpcomponents</groupId> |
29 | 29 | <artifactId>httpcomponents-asyncclient</artifactId> |
30 | <version>4.1.4</version> | |
30 | <version>4.1.5</version> | |
31 | 31 | </parent> |
32 | 32 | <artifactId>httpasyncclient-cache</artifactId> |
33 | 33 | <name>Apache HttpAsyncClient Cache</name> |
118 | 118 | <artifactId>maven-javadoc-plugin</artifactId> |
119 | 119 | <version>${hc.javadoc.version}</version> |
120 | 120 | <configuration> |
121 | <!-- reduce console output. Can override with -Dquiet=false --> | |
122 | <quiet>true</quiet> | |
121 | 123 | <source>${maven.compiler.source}</source> |
122 | 124 | <links> |
123 | <link>http://download.oracle.com/javase/1.5.0/docs/api/</link> | |
124 | <link>http://hc.apache.org/httpcomponents-core-ga/httpcore/apidocs/</link> | |
125 | <link>http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/</link> | |
125 | <link>http://docs.oracle.com/javase/6/docs/api/</link> | |
126 | <link>https://hc.apache.org/httpcomponents-core-4.4.x/current/httpcore/apidocs/</link> | |
127 | <link>https://hc.apache.org/httpcomponents-client-4.5.x/current/httpclient/apidocs/</link> | |
126 | 128 | </links> |
127 | 129 | </configuration> |
128 | 130 | <reportSets> |
136 | 138 | |
137 | 139 | <plugin> |
138 | 140 | <artifactId>maven-project-info-reports-plugin</artifactId> |
139 | <version>${hc.project-info.version}</version> | |
140 | 141 | <inherited>false</inherited> |
141 | 142 | <reportSets> |
142 | 143 | <reportSet> |
151 | 152 | |
152 | 153 | <plugin> |
153 | 154 | <artifactId>maven-jxr-plugin</artifactId> |
154 | <version>${hc.jxr.version}</version> | |
155 | 155 | </plugin> |
156 | 156 | |
157 | 157 | <plugin> |
158 | 158 | <artifactId>maven-surefire-report-plugin</artifactId> |
159 | <version>${hc.surefire-report.version}</version> | |
160 | 159 | </plugin> |
161 | 160 | |
162 | 161 | </plugins> |
163 | 162 | </reporting> |
164 | 163 | |
165 | </project> | |
164 | </project>⏎ |
+5
-4
72 | 72 | import org.apache.http.nio.reactor.IOReactorException; |
73 | 73 | import org.apache.http.protocol.HTTP; |
74 | 74 | import org.apache.http.protocol.HttpContext; |
75 | import org.apache.http.protocol.HttpCoreContext; | |
75 | 76 | import org.apache.http.util.Args; |
76 | 77 | import org.apache.http.util.EntityUtils; |
77 | 78 | import org.apache.http.util.VersionInfo; |
364 | 365 | return; |
365 | 366 | } |
366 | 367 | clientContext.setAttribute(HttpClientContext.HTTP_ROUTE, new HttpRoute(target)); |
367 | clientContext.setAttribute(HttpClientContext.HTTP_TARGET_HOST, target); | |
368 | clientContext.setAttribute(HttpClientContext.HTTP_REQUEST, request); | |
369 | clientContext.setAttribute(HttpClientContext.HTTP_RESPONSE, out); | |
370 | clientContext.setAttribute(HttpClientContext.HTTP_REQ_SENT, Boolean.TRUE); | |
368 | clientContext.setAttribute(HttpCoreContext.HTTP_TARGET_HOST, target); | |
369 | clientContext.setAttribute(HttpCoreContext.HTTP_REQUEST, request); | |
370 | clientContext.setAttribute(HttpCoreContext.HTTP_RESPONSE, out); | |
371 | clientContext.setAttribute(HttpCoreContext.HTTP_REQ_SENT, Boolean.TRUE); | |
371 | 372 | future.completed(out); |
372 | 373 | } |
373 | 374 |
27 | 27 | <parent> |
28 | 28 | <groupId>org.apache.httpcomponents</groupId> |
29 | 29 | <artifactId>httpcomponents-asyncclient</artifactId> |
30 | <version>4.1.4</version> | |
30 | <version>4.1.5</version> | |
31 | 31 | </parent> |
32 | 32 | <artifactId>httpasyncclient-osgi</artifactId> |
33 | 33 | <name>Apache HttpAsyncClient OSGi bundle</name> |
119 | 119 | org.apache.http.ssl;version=${httpcore.osgi.import.version}, |
120 | 120 | * |
121 | 121 | </Import-Package> |
122 | <Include-Resource /> | |
122 | <Include-Resource/> | |
123 | 123 | <!-- Stop the JAVA_1_n_HOME variables from being treated as headers by Bnd --> |
124 | 124 | <_removeheaders>JAVA_1_3_HOME,JAVA_1_4_HOME</_removeheaders> |
125 | 125 | </instructions> |
141 | 141 | <plugin> |
142 | 142 | <groupId>org.codehaus.mojo</groupId> |
143 | 143 | <artifactId>clirr-maven-plugin</artifactId> |
144 | <version>${hc.clirr.version}</version> | |
145 | 144 | <configuration> |
146 | 145 | <skip>true</skip> |
147 | 146 | </configuration> |
148 | 147 | </plugin> |
149 | 148 | <plugin> |
150 | 149 | <artifactId>maven-project-info-reports-plugin</artifactId> |
151 | <version>${hc.project-info.version}</version> | |
152 | 150 | <inherited>false</inherited> |
153 | 151 | <reportSets> |
154 | 152 | <reportSet> |
164 | 162 | </plugins> |
165 | 163 | </reporting> |
166 | 164 | |
167 | </project> | |
165 | </project>⏎ |
24 | 24 | <http://www.apache.org />. |
25 | 25 | --><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> |
26 | 26 | <parent> |
27 | <artifactId>project</artifactId> | |
28 | <groupId>org.apache.httpcomponents</groupId> | |
29 | <version>7</version> | |
30 | <relativePath>../project/pom.xml</relativePath> | |
31 | </parent> | |
32 | <modelVersion>4.0.0</modelVersion> | |
27 | <groupId>org.apache.httpcomponents</groupId> | |
28 | <artifactId>httpcomponents-parent</artifactId> | |
29 | <version>11</version> | |
30 | </parent> | |
31 | <modelVersion>4.0.0</modelVersion> | |
33 | 32 | <artifactId>httpcomponents-asyncclient</artifactId> |
34 | 33 | <name>Apache HttpComponents AsyncClient</name> |
35 | <version>4.1.4</version> | |
34 | <version>4.1.5</version> | |
36 | 35 | <description>Apache components to build asynchronous client side HTTP services</description> |
37 | 36 | <url>http://hc.apache.org/httpcomponents-asyncclient</url> |
38 | 37 | <inceptionYear>2010</inceptionYear> |
62 | 61 | <url>https://svn.apache.org/repos/asf/httpcomponents/httpasyncclient/branches/4.1.x</url> |
63 | 62 | </scm> |
64 | 63 | |
64 | <distributionManagement> | |
65 | <site> | |
66 | <id>apache.website</id> | |
67 | <name>Apache HttpComponents Website</name> | |
68 | <url>scm:svn:https://svn.apache.org/repos/asf/httpcomponents/site/components/httpcomponents-asyncclient-4.1.x/LATEST/</url> | |
69 | </site> | |
70 | </distributionManagement> | |
71 | ||
65 | 72 | <properties> |
66 | 73 | <maven.compiler.source>1.6</maven.compiler.source> |
67 | 74 | <maven.compiler.target>1.6</maven.compiler.target> |
68 | <httpcore.version>4.4.10</httpcore.version> | |
69 | <httpclient.version>4.5.6</httpclient.version> | |
75 | <httpcore.version>4.4.15</httpcore.version> | |
76 | <httpclient.version>4.5.13</httpclient.version> | |
70 | 77 | <commons-logging.version>1.2</commons-logging.version> |
71 | 78 | <commons-io.version>2.4</commons-io.version> |
72 | 79 | <junit.version>4.11</junit.version> |
73 | 80 | <easymock.version>2.5.2</easymock.version> |
74 | 81 | <mockito.version>1.8.5</mockito.version> |
75 | <hc.stylecheck.version>1</hc.stylecheck.version> | |
76 | <api.comparison.version>4.0</api.comparison.version> | |
82 | <api.comparison.version>4.1</api.comparison.version> | |
77 | 83 | </properties> |
78 | 84 | |
79 | 85 | <dependencyManagement> |
185 | 191 | <source>${maven.compiler.source}</source> |
186 | 192 | <links> |
187 | 193 | <link>http://docs.oracle.com/javase/6/docs/api/</link> |
188 | <link>http://hc.apache.org/httpcomponents-core-ga/httpcore/apidocs/</link> | |
189 | <link>http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/</link> | |
194 | <link>https://hc.apache.org/httpcomponents-core-4.4.x/current/httpcore/apidocs/</link> | |
195 | <link>https://hc.apache.org/httpcomponents-client-4.5.x/current/httpclient/apidocs/</link> | |
190 | 196 | </links> |
191 | 197 | </configuration> |
192 | 198 | </plugin> |
196 | 202 | <plugin> |
197 | 203 | <groupId>org.apache.maven.plugins</groupId> |
198 | 204 | <artifactId>maven-checkstyle-plugin</artifactId> |
199 | <version>2.9.1</version> | |
200 | <dependencies> | |
201 | <dependency> | |
202 | <groupId>org.apache.httpcomponents</groupId> | |
203 | <artifactId>hc-stylecheck</artifactId> | |
204 | <version>${hc.stylecheck.version}</version> | |
205 | </dependency> | |
206 | </dependencies> | |
207 | <configuration> | |
208 | <encoding>UTF-8</encoding> | |
209 | </configuration> | |
210 | <executions> | |
211 | <execution> | |
212 | <id>validate-main</id> | |
213 | <phase>validate</phase> | |
214 | <configuration> | |
215 | <configLocation>hc-stylecheck/default.xml</configLocation> | |
216 | <headerLocation>hc-stylecheck/asl2.header</headerLocation> | |
217 | <consoleOutput>true</consoleOutput> | |
218 | <failsOnError>true</failsOnError> | |
219 | <linkXRef>false</linkXRef> | |
220 | <sourceDirectory>${basedir}/src/main</sourceDirectory> | |
221 | </configuration> | |
222 | <goals> | |
223 | <goal>checkstyle</goal> | |
224 | </goals> | |
225 | </execution> | |
226 | <execution> | |
227 | <id>validate-test</id> | |
228 | <phase>validate</phase> | |
229 | <configuration> | |
230 | <configLocation>hc-stylecheck/default.xml</configLocation> | |
231 | <headerLocation>hc-stylecheck/asl2.header</headerLocation> | |
232 | <consoleOutput>true</consoleOutput> | |
233 | <failsOnError>true</failsOnError> | |
234 | <linkXRef>false</linkXRef> | |
235 | <sourceDirectory>${basedir}/src/test</sourceDirectory> | |
236 | </configuration> | |
237 | <goals> | |
238 | <goal>checkstyle</goal> | |
239 | </goals> | |
240 | </execution> | |
241 | <execution> | |
242 | <id>validate-examples</id> | |
243 | <phase>validate</phase> | |
244 | <configuration> | |
245 | <configLocation>hc-stylecheck/minimal.xml</configLocation> | |
246 | <headerLocation>hc-stylecheck/asl2.header</headerLocation> | |
247 | <consoleOutput>true</consoleOutput> | |
248 | <failsOnError>true</failsOnError> | |
249 | <linkXRef>false</linkXRef> | |
250 | <sourceDirectory>${basedir}/src/examples</sourceDirectory> | |
251 | </configuration> | |
252 | <goals> | |
253 | <goal>checkstyle</goal> | |
254 | </goals> | |
255 | </execution> | |
256 | </executions> | |
205 | <configuration> | |
206 | <configLocation>hc-stylecheck/default.xml</configLocation> | |
207 | <headerLocation>hc-stylecheck/asl2.header</headerLocation> | |
208 | <consoleOutput>true</consoleOutput> | |
209 | <failsOnError>true</failsOnError> | |
210 | <linkXRef>false</linkXRef> | |
211 | <sourceDirectories> | |
212 | <sourceDirectory>${basedir}/src/main/</sourceDirectory> | |
213 | <sourceDirectory>${basedir}/src/test</sourceDirectory> | |
214 | </sourceDirectories> | |
215 | <excludes>**/java-deprecated/**</excludes> | |
216 | </configuration> | |
257 | 217 | </plugin> |
258 | 218 | <plugin> |
259 | 219 | <groupId>org.codehaus.mojo</groupId> |
260 | 220 | <artifactId>clirr-maven-plugin</artifactId> |
261 | <version>${hc.clirr.version}</version> | |
262 | 221 | <configuration> |
263 | 222 | <comparisonVersion>${api.comparison.version}</comparisonVersion> |
264 | 223 | </configuration> |
266 | 225 | <plugin> |
267 | 226 | <groupId>org.apache.rat</groupId> |
268 | 227 | <artifactId>apache-rat-plugin</artifactId> |
269 | <version>0.12</version> | |
270 | 228 | <executions> |
271 | 229 | <execution> |
272 | 230 | <phase>verify</phase> |
288 | 246 | |
289 | 247 | <reporting> |
290 | 248 | <plugins> |
291 | ||
292 | 249 | <plugin> |
293 | 250 | <artifactId>maven-project-info-reports-plugin</artifactId> |
294 | <version>${hc.project-info.version}</version> | |
295 | 251 | <inherited>false</inherited> |
296 | 252 | <reportSets> |
297 | 253 | <reportSet> |
298 | 254 | <reports> |
255 | <report>dependency-info</report> | |
299 | 256 | <report>dependency-management</report> |
300 | <report>issue-tracking</report> | |
301 | <report>license</report> | |
257 | <report>issue-management</report> | |
258 | <report>licenses</report> | |
259 | <report>mailing-lists</report> | |
302 | 260 | <report>scm</report> |
303 | 261 | <report>summary</report> |
304 | 262 | </reports> |
306 | 264 | </reportSets> |
307 | 265 | </plugin> |
308 | 266 | |
267 | <plugin> | |
268 | <groupId>org.codehaus.mojo</groupId> | |
269 | <artifactId>clirr-maven-plugin</artifactId> | |
270 | <configuration> | |
271 | <comparisonVersion>${api.comparison.version}</comparisonVersion> | |
272 | </configuration> | |
273 | </plugin> | |
274 | ||
309 | 275 | </plugins> |
310 | 276 | </reporting> |
311 | 277 | |
312 | </project> | |
278 | </project>⏎ |