1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package org.apache.http.impl.nio;
29
30 import java.io.IOException;
31 import java.nio.channels.SelectionKey;
32 import java.nio.charset.CharsetDecoder;
33 import java.nio.charset.CharsetEncoder;
34
35 import org.apache.http.HttpEntity;
36 import org.apache.http.HttpEntityEnclosingRequest;
37 import org.apache.http.HttpException;
38 import org.apache.http.HttpRequest;
39 import org.apache.http.HttpResponse;
40 import org.apache.http.HttpResponseFactory;
41 import org.apache.http.config.MessageConstraints;
42 import org.apache.http.entity.ContentLengthStrategy;
43 import org.apache.http.impl.nio.codecs.DefaultHttpRequestWriter;
44 import org.apache.http.impl.nio.codecs.DefaultHttpRequestWriterFactory;
45 import org.apache.http.impl.nio.codecs.DefaultHttpResponseParser;
46 import org.apache.http.impl.nio.codecs.DefaultHttpResponseParserFactory;
47 import org.apache.http.nio.NHttpClientEventHandler;
48 import org.apache.http.nio.NHttpClientHandler;
49 import org.apache.http.nio.NHttpClientIOTarget;
50 import org.apache.http.nio.NHttpMessageParser;
51 import org.apache.http.nio.NHttpMessageParserFactory;
52 import org.apache.http.nio.NHttpMessageWriter;
53 import org.apache.http.nio.NHttpMessageWriterFactory;
54 import org.apache.http.nio.reactor.EventMask;
55 import org.apache.http.nio.reactor.IOSession;
56 import org.apache.http.nio.reactor.SessionInputBuffer;
57 import org.apache.http.nio.reactor.SessionOutputBuffer;
58 import org.apache.http.nio.util.ByteBufferAllocator;
59 import org.apache.http.params.HttpParamConfig;
60 import org.apache.http.params.HttpParams;
61 import org.apache.http.util.Args;
62
63
64
65
66
67
68
69 @SuppressWarnings("deprecation")
70 public class DefaultNHttpClientConnection
71 extends NHttpConnectionBase implements NHttpClientIOTarget {
72
73 protected final NHttpMessageParser<HttpResponse> responseParser;
74 protected final NHttpMessageWriter<HttpRequest> requestWriter;
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89 @Deprecated
90 public DefaultNHttpClientConnection(
91 final IOSession session,
92 final HttpResponseFactory responseFactory,
93 final ByteBufferAllocator allocator,
94 final HttpParams params) {
95 super(session, allocator, params);
96 Args.notNull(responseFactory, "Response factory");
97 this.responseParser = createResponseParser(this.inbuf, responseFactory, params);
98 this.requestWriter = createRequestWriter(this.outbuf, params);
99 this.hasBufferedInput = false;
100 this.hasBufferedOutput = false;
101 this.session.setBufferStatus(this);
102 }
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126 public DefaultNHttpClientConnection(
127 final IOSession session,
128 final int bufferSize,
129 final int fragmentSizeHint,
130 final ByteBufferAllocator allocator,
131 final CharsetDecoder charDecoder,
132 final CharsetEncoder charEncoder,
133 final MessageConstraints constraints,
134 final ContentLengthStrategy incomingContentStrategy,
135 final ContentLengthStrategy outgoingContentStrategy,
136 final NHttpMessageWriterFactory<HttpRequest> requestWriterFactory,
137 final NHttpMessageParserFactory<HttpResponse> responseParserFactory) {
138 super(session, bufferSize, fragmentSizeHint, allocator, charDecoder, charEncoder,
139 constraints, incomingContentStrategy, outgoingContentStrategy);
140 this.requestWriter = (requestWriterFactory != null ? requestWriterFactory :
141 DefaultHttpRequestWriterFactory.INSTANCE).create(this.outbuf);
142 this.responseParser = (responseParserFactory != null ? responseParserFactory :
143 DefaultHttpResponseParserFactory.INSTANCE).create(this.inbuf, constraints);
144 }
145
146
147
148
149 public DefaultNHttpClientConnection(
150 final IOSession session,
151 final int bufferSize,
152 final CharsetDecoder charDecoder,
153 final CharsetEncoder charEncoder,
154 final MessageConstraints constraints) {
155 this(session, bufferSize, bufferSize, null, charDecoder, charEncoder, constraints,
156 null, null, null, null);
157 }
158
159
160
161
162 public DefaultNHttpClientConnection(final IOSession session, final int bufferSize) {
163 this(session, bufferSize, bufferSize, null, null, null, null, null, null, null, null);
164 }
165
166
167
168
169
170
171
172
173
174
175
176
177 @Deprecated
178 protected NHttpMessageParser<HttpResponse> createResponseParser(
179 final SessionInputBuffer buffer,
180 final HttpResponseFactory responseFactory,
181 final HttpParams params) {
182
183 final MessageConstraints constraints = HttpParamConfig.getMessageConstraints(params);
184 return new DefaultHttpResponseParser(buffer, null, responseFactory, constraints);
185 }
186
187
188
189
190
191
192
193
194
195
196
197
198 @Deprecated
199 protected NHttpMessageWriter<HttpRequest> createRequestWriter(
200 final SessionOutputBuffer buffer,
201 final HttpParams params) {
202
203 return new DefaultHttpRequestWriter(buffer, null);
204 }
205
206
207
208
209 protected void onResponseReceived(final HttpResponse response) {
210 }
211
212
213
214
215 protected void onRequestSubmitted(final HttpRequest request) {
216 }
217
218 @Override
219 public void resetInput() {
220 this.response = null;
221 this.contentDecoder = null;
222 this.responseParser.reset();
223 }
224
225 @Override
226 public void resetOutput() {
227 this.request = null;
228 this.contentEncoder = null;
229 this.requestWriter.reset();
230 }
231
232 public void consumeInput(final NHttpClientEventHandler handler) {
233 if (this.status != ACTIVE) {
234 this.session.clearEvent(EventMask.READ);
235 return;
236 }
237 try {
238 if (this.response == null) {
239 int bytesRead;
240 do {
241 bytesRead = this.responseParser.fillBuffer(this.session.channel());
242 if (bytesRead > 0) {
243 this.inTransportMetrics.incrementBytesTransferred(bytesRead);
244 }
245 this.response = this.responseParser.parse();
246 } while (bytesRead > 0 && this.response == null);
247 if (this.response != null) {
248 if (this.response.getStatusLine().getStatusCode() >= 200) {
249 final HttpEntity entity = prepareDecoder(this.response);
250 this.response.setEntity(entity);
251 this.connMetrics.incrementResponseCount();
252 }
253 this.hasBufferedInput = this.inbuf.hasData();
254 onResponseReceived(this.response);
255 handler.responseReceived(this);
256 if (this.contentDecoder == null) {
257 resetInput();
258 }
259 }
260 if (bytesRead == -1 && !this.inbuf.hasData()) {
261 handler.endOfInput(this);
262 }
263 }
264 if (this.contentDecoder != null && (this.session.getEventMask() & SelectionKey.OP_READ) > 0) {
265 handler.inputReady(this, this.contentDecoder);
266 if (this.contentDecoder.isCompleted()) {
267
268
269 resetInput();
270 }
271 }
272 } catch (final HttpException ex) {
273 resetInput();
274 handler.exception(this, ex);
275 } catch (final Exception ex) {
276 handler.exception(this, ex);
277 } finally {
278
279 this.hasBufferedInput = this.inbuf.hasData();
280 }
281 }
282
283 public void produceOutput(final NHttpClientEventHandler handler) {
284 try {
285 if (this.status == ACTIVE) {
286 if (this.contentEncoder == null && !this.outbuf.hasData()) {
287 handler.requestReady(this);
288 }
289 if (this.contentEncoder != null) {
290 handler.outputReady(this, this.contentEncoder);
291 if (this.contentEncoder.isCompleted()) {
292 resetOutput();
293 }
294 }
295 }
296 if (this.outbuf.hasData()) {
297 final int bytesWritten = this.outbuf.flush(this.session.channel());
298 if (bytesWritten > 0) {
299 this.outTransportMetrics.incrementBytesTransferred(bytesWritten);
300 }
301 }
302 if (!this.outbuf.hasData()) {
303 if (this.status == CLOSING) {
304 this.session.close();
305 this.status = CLOSED;
306 resetOutput();
307 }
308 }
309 } catch (final Exception ex) {
310 handler.exception(this, ex);
311 } finally {
312
313 this.hasBufferedOutput = this.outbuf.hasData();
314 }
315 }
316
317 @Override
318 public void submitRequest(final HttpRequest request) throws IOException, HttpException {
319 Args.notNull(request, "HTTP request");
320 assertNotClosed();
321 if (this.request != null) {
322 throw new HttpException("Request already submitted");
323 }
324 onRequestSubmitted(request);
325 this.requestWriter.write(request);
326 this.hasBufferedOutput = this.outbuf.hasData();
327
328 if (request instanceof HttpEntityEnclosingRequest
329 && ((HttpEntityEnclosingRequest) request).getEntity() != null) {
330 prepareEncoder(request);
331 this.request = request;
332 }
333 this.connMetrics.incrementRequestCount();
334 this.session.setEvent(EventMask.WRITE);
335 }
336
337 @Override
338 public boolean isRequestSubmitted() {
339 return this.request != null;
340 }
341
342 @Override
343 public void consumeInput(final NHttpClientHandler handler) {
344 consumeInput(new NHttpClientEventHandlerAdaptor(handler));
345 }
346
347 @Override
348 public void produceOutput(final NHttpClientHandler handler) {
349 produceOutput(new NHttpClientEventHandlerAdaptor(handler));
350 }
351
352 }