1/*
2 * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpcore/trunk/module-main/src/main/java/org/apache/http/impl/AbstractHttpServerConnection.java $
3 * $Revision: 618017 $
4 * $Date: 2008-02-03 08:42:22 -0800 (Sun, 03 Feb 2008) $
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
32package org.apache.http.impl;
33
34import java.io.IOException;
35
36import org.apache.http.HttpConnectionMetrics;
37import org.apache.http.HttpEntity;
38import org.apache.http.HttpEntityEnclosingRequest;
39import org.apache.http.HttpException;
40import org.apache.http.HttpRequest;
41import org.apache.http.HttpRequestFactory;
42import org.apache.http.HttpResponse;
43import org.apache.http.HttpServerConnection;
44import org.apache.http.impl.entity.EntityDeserializer;
45import org.apache.http.impl.entity.EntitySerializer;
46import org.apache.http.impl.entity.LaxContentLengthStrategy;
47import org.apache.http.impl.entity.StrictContentLengthStrategy;
48import org.apache.http.impl.io.HttpRequestParser;
49import org.apache.http.impl.io.HttpResponseWriter;
50import org.apache.http.io.HttpMessageParser;
51import org.apache.http.io.HttpMessageWriter;
52import org.apache.http.io.SessionInputBuffer;
53import org.apache.http.io.SessionOutputBuffer;
54import org.apache.http.params.HttpParams;
55
56/**
57 * Abstract server-side HTTP connection capable of transmitting and receiving data
58 * using arbitrary {@link SessionInputBuffer} and {@link SessionOutputBuffer}
59 *
60 * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
61 *
62 * @version $Revision: 618017 $
63 *
64 * @since 4.0
65 */
66public abstract class AbstractHttpServerConnection implements HttpServerConnection {
67
68    private final EntitySerializer entityserializer;
69    private final EntityDeserializer entitydeserializer;
70
71    private SessionInputBuffer inbuffer = null;
72    private SessionOutputBuffer outbuffer = null;
73    private HttpMessageParser requestParser = null;
74    private HttpMessageWriter responseWriter = null;
75    private HttpConnectionMetricsImpl metrics = null;
76
77
78
79    public AbstractHttpServerConnection() {
80        super();
81        this.entityserializer = createEntitySerializer();
82        this.entitydeserializer = createEntityDeserializer();
83    }
84
85    protected abstract void assertOpen() throws IllegalStateException;
86
87    protected EntityDeserializer createEntityDeserializer() {
88        return new EntityDeserializer(new LaxContentLengthStrategy());
89    }
90
91    protected EntitySerializer createEntitySerializer() {
92        return new EntitySerializer(new StrictContentLengthStrategy());
93    }
94
95    protected HttpRequestFactory createHttpRequestFactory() {
96        return new DefaultHttpRequestFactory();
97    }
98
99    protected HttpMessageParser createRequestParser(
100            final SessionInputBuffer buffer,
101            final HttpRequestFactory requestFactory,
102            final HttpParams params) {
103        // override in derived class to specify a line parser
104        return new HttpRequestParser(buffer, null, requestFactory, params);
105    }
106
107    protected HttpMessageWriter createResponseWriter(
108            final SessionOutputBuffer buffer,
109            final HttpParams params) {
110        // override in derived class to specify a line formatter
111        return new HttpResponseWriter(buffer, null, params);
112    }
113
114
115    protected void init(
116            final SessionInputBuffer inbuffer,
117            final SessionOutputBuffer outbuffer,
118            final HttpParams params) {
119        if (inbuffer == null) {
120            throw new IllegalArgumentException("Input session buffer may not be null");
121        }
122        if (outbuffer == null) {
123            throw new IllegalArgumentException("Output session buffer may not be null");
124        }
125        this.inbuffer = inbuffer;
126        this.outbuffer = outbuffer;
127        this.requestParser = createRequestParser(
128                inbuffer,
129                createHttpRequestFactory(),
130                params);
131        this.responseWriter = createResponseWriter(
132                outbuffer, params);
133        this.metrics = new HttpConnectionMetricsImpl(
134                inbuffer.getMetrics(),
135                outbuffer.getMetrics());
136    }
137
138    public HttpRequest receiveRequestHeader()
139            throws HttpException, IOException {
140        assertOpen();
141        HttpRequest request = (HttpRequest) this.requestParser.parse();
142        this.metrics.incrementRequestCount();
143        return request;
144    }
145
146    public void receiveRequestEntity(final HttpEntityEnclosingRequest request)
147            throws HttpException, IOException {
148        if (request == null) {
149            throw new IllegalArgumentException("HTTP request may not be null");
150        }
151        assertOpen();
152        HttpEntity entity = this.entitydeserializer.deserialize(this.inbuffer, request);
153        request.setEntity(entity);
154    }
155
156    protected void doFlush() throws IOException  {
157        this.outbuffer.flush();
158    }
159
160    public void flush() throws IOException {
161        assertOpen();
162        doFlush();
163    }
164
165    public void sendResponseHeader(final HttpResponse response)
166            throws HttpException, IOException {
167        if (response == null) {
168            throw new IllegalArgumentException("HTTP response may not be null");
169        }
170        assertOpen();
171        this.responseWriter.write(response);
172        if (response.getStatusLine().getStatusCode() >= 200) {
173            this.metrics.incrementResponseCount();
174        }
175    }
176
177    public void sendResponseEntity(final HttpResponse response)
178            throws HttpException, IOException {
179        if (response.getEntity() == null) {
180            return;
181        }
182        this.entityserializer.serialize(
183                this.outbuffer,
184                response,
185                response.getEntity());
186    }
187
188    public boolean isStale() {
189        assertOpen();
190        try {
191            this.inbuffer.isDataAvailable(1);
192            return false;
193        } catch (IOException ex) {
194            return true;
195        }
196    }
197
198    public HttpConnectionMetrics getMetrics() {
199        return this.metrics;
200    }
201
202}
203