View Javadoc

1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
25   *
26   */
27  
28  package org.apache.http.impl;
29  
30  import java.io.IOException;
31  
32  import org.apache.http.HttpConnectionMetrics;
33  import org.apache.http.HttpEntity;
34  import org.apache.http.HttpEntityEnclosingRequest;
35  import org.apache.http.HttpException;
36  import org.apache.http.HttpRequest;
37  import org.apache.http.HttpRequestFactory;
38  import org.apache.http.HttpResponse;
39  import org.apache.http.HttpServerConnection;
40  import org.apache.http.annotation.NotThreadSafe;
41  import org.apache.http.impl.entity.DisallowIdentityContentLengthStrategy;
42  import org.apache.http.impl.entity.EntityDeserializer;
43  import org.apache.http.impl.entity.EntitySerializer;
44  import org.apache.http.impl.entity.LaxContentLengthStrategy;
45  import org.apache.http.impl.entity.StrictContentLengthStrategy;
46  import org.apache.http.impl.io.DefaultHttpRequestParser;
47  import org.apache.http.impl.io.HttpResponseWriter;
48  import org.apache.http.io.EofSensor;
49  import org.apache.http.io.HttpMessageParser;
50  import org.apache.http.io.HttpMessageWriter;
51  import org.apache.http.io.HttpTransportMetrics;
52  import org.apache.http.io.SessionInputBuffer;
53  import org.apache.http.io.SessionOutputBuffer;
54  import org.apache.http.params.HttpParams;
55  import org.apache.http.util.Args;
56  
57  /**
58   * Abstract server-side HTTP connection capable of transmitting and receiving
59   * data using arbitrary {@link SessionInputBuffer} and
60   * {@link SessionOutputBuffer} implementations.
61   * <p>
62   * The following parameters can be used to customize the behavior of this
63   * class:
64   * <ul>
65   *  <li>{@link org.apache.http.params.CoreProtocolPNames#STRICT_TRANSFER_ENCODING}</li>
66   *  <li>{@link org.apache.http.params.CoreConnectionPNames#MAX_HEADER_COUNT}</li>
67   *  <li>{@link org.apache.http.params.CoreConnectionPNames#MAX_LINE_LENGTH}</li>
68   * </ul>
69   *
70   * @since 4.0
71   *
72   * @deprecated (4.3) use {@link DefaultBHttpServerConnection}
73   */
74  @NotThreadSafe
75  @Deprecated
76  public abstract class AbstractHttpServerConnection implements HttpServerConnection {
77  
78      private final EntitySerializer entityserializer;
79      private final EntityDeserializer entitydeserializer;
80  
81      private SessionInputBuffer inbuffer = null;
82      private SessionOutputBuffer outbuffer = null;
83      private EofSensor eofSensor = null;
84      private HttpMessageParser<HttpRequest> requestParser = null;
85      private HttpMessageWriter<HttpResponse> responseWriter = null;
86      private HttpConnectionMetricsImpl metrics = null;
87  
88      /**
89       * Creates an instance of this class.
90       * <p>
91       * This constructor will invoke {@link #createEntityDeserializer()}
92       * and {@link #createEntitySerializer()} methods in order to initialize
93       * HTTP entity serializer and deserializer implementations for this
94       * connection.
95       */
96      public AbstractHttpServerConnection() {
97          super();
98          this.entityserializer = createEntitySerializer();
99          this.entitydeserializer = createEntityDeserializer();
100     }
101 
102     /**
103      * Asserts if the connection is open.
104      *
105      * @throws IllegalStateException if the connection is not open.
106      */
107     protected abstract void assertOpen() throws IllegalStateException;
108 
109     /**
110      * Creates an instance of {@link EntityDeserializer} with the
111      * {@link LaxContentLengthStrategy} implementation to be used for
112      * de-serializing entities received over this connection.
113      * <p>
114      * This method can be overridden in a super class in order to create
115      * instances of {@link EntityDeserializer} using a custom
116      * {@link org.apache.http.entity.ContentLengthStrategy}.
117      *
118      * @return HTTP entity deserializer
119      */
120     protected EntityDeserializer createEntityDeserializer() {
121         return new EntityDeserializer(new DisallowIdentityContentLengthStrategy(
122                 new LaxContentLengthStrategy(0)));
123     }
124 
125     /**
126      * Creates an instance of {@link EntitySerializer} with the
127      * {@link StrictContentLengthStrategy} implementation to be used for
128      * serializing HTTP entities sent over this connection.
129      * <p>
130      * This method can be overridden in a super class in order to create
131      * instances of {@link EntitySerializer} using a custom
132      * {@link org.apache.http.entity.ContentLengthStrategy}.
133      *
134      * @return HTTP entity serialzier.
135      */
136     protected EntitySerializer createEntitySerializer() {
137         return new EntitySerializer(new StrictContentLengthStrategy());
138     }
139 
140     /**
141      * Creates an instance of {@link DefaultHttpRequestFactory} to be used
142      * for creating {@link HttpRequest} objects received by over this
143      * connection.
144      * <p>
145      * This method can be overridden in a super class in order to provide
146      * a different implementation of the {@link HttpRequestFactory} interface.
147      *
148      * @return HTTP request factory.
149      */
150     protected HttpRequestFactory createHttpRequestFactory() {
151         return DefaultHttpRequestFactory.INSTANCE;
152     }
153 
154     /**
155      * Creates an instance of {@link HttpMessageParser} to be used for parsing
156      * HTTP requests received over this connection.
157      * <p>
158      * This method can be overridden in a super class in order to provide
159      * a different implementation of the {@link HttpMessageParser} interface or
160      * to pass a different implementation of the
161      * {@link org.apache.http.message.LineParser} to the
162      * {@link DefaultHttpRequestParser} constructor.
163      *
164      * @param buffer the session input buffer.
165      * @param requestFactory the HTTP request factory.
166      * @param params HTTP parameters.
167      * @return HTTP message parser.
168      */
169     protected HttpMessageParser<HttpRequest> createRequestParser(
170             final SessionInputBuffer buffer,
171             final HttpRequestFactory requestFactory,
172             final HttpParams params) {
173         return new DefaultHttpRequestParser(buffer, null, requestFactory, params);
174     }
175 
176     /**
177      * Creates an instance of {@link HttpMessageWriter} to be used for
178      * writing out HTTP responses sent over this connection.
179      * <p>
180      * This method can be overridden in a super class in order to provide
181      * a different implementation of the {@link HttpMessageWriter} interface or
182      * to pass a different implementation of
183      * {@link org.apache.http.message.LineFormatter} to the the default
184      * implementation {@link HttpResponseWriter}.
185      *
186      * @param buffer the session output buffer
187      * @param params HTTP parameters
188      * @return HTTP message writer
189      */
190     protected HttpMessageWriter<HttpResponse> createResponseWriter(
191             final SessionOutputBuffer buffer,
192             final HttpParams params) {
193         return new HttpResponseWriter(buffer, null, params);
194     }
195 
196     /**
197      * @since 4.1
198      */
199     protected HttpConnectionMetricsImpl createConnectionMetrics(
200             final HttpTransportMetrics inTransportMetric,
201             final HttpTransportMetrics outTransportMetric) {
202         return new HttpConnectionMetricsImpl(inTransportMetric, outTransportMetric);
203     }
204 
205     /**
206      * Initializes this connection object with {@link SessionInputBuffer} and
207      * {@link SessionOutputBuffer} instances to be used for sending and
208      * receiving data. These session buffers can be bound to any arbitrary
209      * physical output medium.
210      * <p>
211      * This method will invoke {@link #createHttpRequestFactory},
212      * {@link #createRequestParser(SessionInputBuffer, HttpRequestFactory, HttpParams)}
213      * and {@link #createResponseWriter(SessionOutputBuffer, HttpParams)}
214      * methods to initialize HTTP request parser and response writer for this
215      * connection.
216      *
217      * @param inbuffer the session input buffer.
218      * @param outbuffer the session output buffer.
219      * @param params HTTP parameters.
220      */
221     protected void init(
222             final SessionInputBuffer inbuffer,
223             final SessionOutputBuffer outbuffer,
224             final HttpParams params) {
225         this.inbuffer = Args.notNull(inbuffer, "Input session buffer");
226         this.outbuffer = Args.notNull(outbuffer, "Output session buffer");
227         if (inbuffer instanceof EofSensor) {
228             this.eofSensor = (EofSensor) inbuffer;
229         }
230         this.requestParser = createRequestParser(
231                 inbuffer,
232                 createHttpRequestFactory(),
233                 params);
234         this.responseWriter = createResponseWriter(
235                 outbuffer, params);
236         this.metrics = createConnectionMetrics(
237                 inbuffer.getMetrics(),
238                 outbuffer.getMetrics());
239     }
240 
241     public HttpRequest receiveRequestHeader()
242             throws HttpException, IOException {
243         assertOpen();
244         final HttpRequest request = this.requestParser.parse();
245         this.metrics.incrementRequestCount();
246         return request;
247     }
248 
249     public void receiveRequestEntity(final HttpEntityEnclosingRequest request)
250             throws HttpException, IOException {
251         Args.notNull(request, "HTTP request");
252         assertOpen();
253         final HttpEntity entity = this.entitydeserializer.deserialize(this.inbuffer, request);
254         request.setEntity(entity);
255     }
256 
257     protected void doFlush() throws IOException  {
258         this.outbuffer.flush();
259     }
260 
261     public void flush() throws IOException {
262         assertOpen();
263         doFlush();
264     }
265 
266     public void sendResponseHeader(final HttpResponse response)
267             throws HttpException, IOException {
268         Args.notNull(response, "HTTP response");
269         assertOpen();
270         this.responseWriter.write(response);
271         if (response.getStatusLine().getStatusCode() >= 200) {
272             this.metrics.incrementResponseCount();
273         }
274     }
275 
276     public void sendResponseEntity(final HttpResponse response)
277             throws HttpException, IOException {
278         if (response.getEntity() == null) {
279             return;
280         }
281         this.entityserializer.serialize(
282                 this.outbuffer,
283                 response,
284                 response.getEntity());
285     }
286 
287     protected boolean isEof() {
288         return this.eofSensor != null && this.eofSensor.isEof();
289     }
290 
291     public boolean isStale() {
292         if (!isOpen()) {
293             return true;
294         }
295         if (isEof()) {
296             return true;
297         }
298         try {
299             this.inbuffer.isDataAvailable(1);
300             return isEof();
301         } catch (final IOException ex) {
302             return true;
303         }
304     }
305 
306     public HttpConnectionMetrics getMetrics() {
307         return this.metrics;
308     }
309 
310 }