~ubuntu-branches/ubuntu/trusty/httpcomponents-core/trusty

« back to all changes in this revision

Viewing changes to httpcore-nio/src/main/java/org/apache/http/impl/nio/DefaultNHttpServerConnection.java

  • Committer: Bazaar Package Importer
  • Author(s): David Paleino
  • Date: 2010-06-12 08:37:34 UTC
  • Revision ID: james.westby@ubuntu.com-20100612083734-1y8kp6qm4sjk60az
Tags: upstream-4.0.1
ImportĀ upstreamĀ versionĀ 4.0.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * $HeadURL: https://svn.apache.org/repos/asf/httpcomponents/httpcore/tags/4.0.1/httpcore-nio/src/main/java/org/apache/http/impl/nio/DefaultNHttpServerConnection.java $
 
3
 * $Revision: 744535 $
 
4
 * $Date: 2009-02-14 18:17:22 +0100 (Sat, 14 Feb 2009) $
 
5
 *
 
6
 * ====================================================================
 
7
 * Licensed to the Apache Software Foundation (ASF) under one
 
8
 * or more contributor license agreements.  See the NOTICE file
 
9
 * distributed with this work for additional information
 
10
 * regarding copyright ownership.  The ASF licenses this file
 
11
 * to you under the Apache License, Version 2.0 (the
 
12
 * "License"); you may not use this file except in compliance
 
13
 * with the License.  You may obtain a copy of the License at
 
14
 *
 
15
 *   http://www.apache.org/licenses/LICENSE-2.0
 
16
 *
 
17
 * Unless required by applicable law or agreed to in writing,
 
18
 * software distributed under the License is distributed on an
 
19
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 
20
 * KIND, either express or implied.  See the License for the
 
21
 * specific language governing permissions and limitations
 
22
 * under the License.
 
23
 * ====================================================================
 
24
 *
 
25
 * This software consists of voluntary contributions made by many
 
26
 * individuals on behalf of the Apache Software Foundation.  For more
 
27
 * information on the Apache Software Foundation, please see
 
28
 * <http://www.apache.org/>.
 
29
 *
 
30
 */
 
31
 
 
32
package org.apache.http.impl.nio;
 
33
 
 
34
import java.io.IOException;
 
35
 
 
36
import org.apache.http.HttpEntity;
 
37
import org.apache.http.HttpEntityEnclosingRequest;
 
38
import org.apache.http.HttpException;
 
39
import org.apache.http.HttpRequest;
 
40
import org.apache.http.HttpRequestFactory;
 
41
import org.apache.http.HttpResponse;
 
42
import org.apache.http.impl.nio.codecs.HttpRequestParser;
 
43
import org.apache.http.impl.nio.codecs.HttpResponseWriter;
 
44
import org.apache.http.nio.NHttpMessageParser;
 
45
import org.apache.http.nio.NHttpMessageWriter;
 
46
import org.apache.http.nio.NHttpServerConnection;
 
47
import org.apache.http.nio.NHttpServerIOTarget;
 
48
import org.apache.http.nio.NHttpServiceHandler;
 
49
import org.apache.http.nio.reactor.EventMask;
 
50
import org.apache.http.nio.reactor.IOSession;
 
51
import org.apache.http.nio.reactor.SessionInputBuffer;
 
52
import org.apache.http.nio.reactor.SessionOutputBuffer;
 
53
import org.apache.http.nio.util.ByteBufferAllocator;
 
54
import org.apache.http.params.CoreConnectionPNames;
 
55
import org.apache.http.params.HttpParams;
 
56
 
 
57
/**
 
58
 * Default implementation of the {@link NHttpServerConnection} interface.
 
59
 * 
 
60
 *
 
61
 * @version $Revision: 744535 $
 
62
 *
 
63
 * @since 4.0
 
64
 */
 
65
public class DefaultNHttpServerConnection 
 
66
    extends NHttpConnectionBase implements NHttpServerIOTarget {
 
67
 
 
68
    protected final NHttpMessageParser requestParser;
 
69
    protected final NHttpMessageWriter responseWriter;
 
70
    
 
71
    /**
 
72
     * Creates a new instance of this class given the underlying I/O session.
 
73
     * <p>
 
74
     * The following HTTP parameters affect configuration of this connection:
 
75
     * <p>
 
76
     * The {@link CoreConnectionPNames#SOCKET_BUFFER_SIZE}
 
77
     * parameter determines the size of the internal socket buffer. If not 
 
78
     * defined or set to <code>-1</code> the default value will be chosen
 
79
     * automatically.
 
80
     * 
 
81
     * @param session the underlying I/O session.
 
82
     * @param requestFactory HTTP request factory.
 
83
     * @param allocator byte buffer allocator.
 
84
     * @param params HTTP parameters.
 
85
     */
 
86
    public DefaultNHttpServerConnection(
 
87
            final IOSession session,
 
88
            final HttpRequestFactory requestFactory,
 
89
            final ByteBufferAllocator allocator,
 
90
            final HttpParams params) {
 
91
        super(session, allocator, params);
 
92
        if (requestFactory == null) {
 
93
            throw new IllegalArgumentException("Request factory may not be null");
 
94
        }
 
95
        this.requestParser = createRequestParser(this.inbuf, requestFactory, params);
 
96
        this.responseWriter = createResponseWriter(this.outbuf, params);
 
97
    }
 
98
 
 
99
    /**
 
100
     * Creates an instance of {@link HttpRequestParser} to be used 
 
101
     * by this connection for parsing incoming {@link HttpRequest} messages.
 
102
     * <p>
 
103
     * This method can be overridden in a super class in order to provide 
 
104
     * a different implementation of the {@link NHttpMessageParser} interface. 
 
105
     * 
 
106
     * @return HTTP response parser.
 
107
     */
 
108
    protected NHttpMessageParser createRequestParser(
 
109
            final SessionInputBuffer buffer,
 
110
            final HttpRequestFactory requestFactory,
 
111
            final HttpParams params) {
 
112
        // override in derived class to specify a line parser
 
113
        return new HttpRequestParser(buffer, null, requestFactory, params);
 
114
    }
 
115
    
 
116
    /**
 
117
     * Creates an instance of {@link HttpResponseWriter} to be used 
 
118
     * by this connection for writing out outgoing {@link HttpResponse} 
 
119
     * messages.
 
120
     * <p>
 
121
     * This method can be overridden by a super class in order to provide 
 
122
     * a different implementation of the {@link NHttpMessageWriter} interface. 
 
123
     * 
 
124
     * @return HTTP response parser.
 
125
     */
 
126
    protected NHttpMessageWriter createResponseWriter(
 
127
            final SessionOutputBuffer buffer,
 
128
            final HttpParams params) {
 
129
        // override in derived class to specify a line formatter
 
130
        return new HttpResponseWriter(buffer, null, params);
 
131
    }
 
132
    
 
133
    public void resetInput() {
 
134
        this.request = null;
 
135
        this.contentDecoder = null;
 
136
        this.requestParser.reset();
 
137
    }
 
138
    
 
139
    public void resetOutput() {
 
140
        this.response = null;
 
141
        this.contentEncoder = null;
 
142
        this.responseWriter.reset();
 
143
    }
 
144
    
 
145
    public void consumeInput(final NHttpServiceHandler handler) {
 
146
        if (this.status != ACTIVE) {
 
147
            this.session.clearEvent(EventMask.READ);
 
148
            return;
 
149
        }
 
150
        try {
 
151
            if (this.request == null) {
 
152
                int bytesRead;
 
153
                do {
 
154
                    bytesRead = this.requestParser.fillBuffer(this.session.channel());
 
155
                    if (bytesRead > 0) {
 
156
                        this.inTransportMetrics.incrementBytesTransferred(bytesRead);
 
157
                    }
 
158
                    this.request = (HttpRequest) this.requestParser.parse();
 
159
                } while (bytesRead > 0 && this.request == null);                
 
160
                if (this.request != null) {
 
161
                    if (this.request instanceof HttpEntityEnclosingRequest) {
 
162
                        // Receive incoming entity
 
163
                        HttpEntity entity = prepareDecoder(this.request);
 
164
                        ((HttpEntityEnclosingRequest)this.request).setEntity(entity);
 
165
                    }
 
166
                    this.connMetrics.incrementRequestCount();
 
167
                    handler.requestReceived(this);
 
168
                    if (this.contentDecoder == null) {
 
169
                        // No request entity is expected
 
170
                        // Ready to receive a new request
 
171
                        resetInput();
 
172
                    }
 
173
                }
 
174
                if (bytesRead == -1) {
 
175
                    close();
 
176
                }
 
177
            }
 
178
            if (this.contentDecoder != null) {
 
179
                handler.inputReady(this, this.contentDecoder);
 
180
                if (this.contentDecoder.isCompleted()) {
 
181
                    // Request entity received
 
182
                    // Ready to receive a new request
 
183
                    resetInput();
 
184
                }
 
185
            }
 
186
        } catch (IOException ex) {
 
187
            handler.exception(this, ex);
 
188
        } catch (HttpException ex) {
 
189
            resetInput();
 
190
            handler.exception(this, ex);
 
191
        } finally {
 
192
            // Finally set buffered input flag
 
193
            this.hasBufferedInput = this.inbuf.hasData();
 
194
        }
 
195
    }
 
196
 
 
197
    public void produceOutput(final NHttpServiceHandler handler) {
 
198
        try {
 
199
            if (this.outbuf.hasData()) {
 
200
                int bytesWritten = this.outbuf.flush(this.session.channel());
 
201
                if (bytesWritten > 0) {
 
202
                    this.outTransportMetrics.incrementBytesTransferred(bytesWritten);
 
203
                }
 
204
            }
 
205
            if (!this.outbuf.hasData()) {
 
206
                if (this.status == CLOSING) {
 
207
                    this.session.close();
 
208
                    this.status = CLOSED;
 
209
                    resetOutput();
 
210
                    return;
 
211
                } else {
 
212
                    if (this.contentEncoder != null) {
 
213
                        handler.outputReady(this, this.contentEncoder);
 
214
                        if (this.contentEncoder.isCompleted()) {
 
215
                            resetOutput();
 
216
                        }
 
217
                    }
 
218
                }
 
219
                
 
220
                if (this.contentEncoder == null && !this.outbuf.hasData()) {
 
221
                    if (this.status == CLOSING) {
 
222
                        this.session.close();
 
223
                        this.status = CLOSED;
 
224
                        return;
 
225
                    }
 
226
                    
 
227
                    this.session.clearEvent(EventMask.WRITE);
 
228
               
 
229
                    handler.responseReady(this);
 
230
                }
 
231
            }
 
232
        } catch (IOException ex) {
 
233
            handler.exception(this, ex);
 
234
        } finally {
 
235
            // Finally set the buffered output flag
 
236
            this.hasBufferedOutput = this.outbuf.hasData();
 
237
        }
 
238
    }
 
239
    
 
240
    public void submitResponse(final HttpResponse response) throws IOException, HttpException {
 
241
        if (response == null) {
 
242
            throw new IllegalArgumentException("HTTP response may not be null");
 
243
        }
 
244
        assertNotClosed();
 
245
        if (this.response != null) {
 
246
            throw new HttpException("Response already submitted");
 
247
        }
 
248
        this.responseWriter.write(response);
 
249
        this.hasBufferedOutput = this.outbuf.hasData();
 
250
 
 
251
        if (response.getStatusLine().getStatusCode() >= 200) {
 
252
            this.connMetrics.incrementRequestCount();
 
253
            if (response.getEntity() != null) {
 
254
                this.response = response;
 
255
                prepareEncoder(response);
 
256
            }
 
257
        }
 
258
 
 
259
        this.session.setEvent(EventMask.WRITE);
 
260
    }
 
261
 
 
262
    public boolean isResponseSubmitted() {
 
263
        return this.response != null;
 
264
    }
 
265
 
 
266
    @Override
 
267
    public String toString() {
 
268
        StringBuffer buffer = new StringBuffer();
 
269
        buffer.append("[");
 
270
        if (isOpen()) {
 
271
            buffer.append(this.session.getRemoteAddress());
 
272
        } else {
 
273
            buffer.append("closed");
 
274
        }
 
275
        buffer.append("]");
 
276
        return buffer.toString();
 
277
    }
 
278
    
 
279
}