Home | History | Annotate | Download | only in impl
      1 /*
      2  * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpcore/trunk/module-main/src/main/java/org/apache/http/impl/AbstractHttpClientConnection.java $
      3  * $Revision: 627457 $
      4  * $Date: 2008-02-13 07:14:19 -0800 (Wed, 13 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 
     32 package org.apache.http.impl;
     33 
     34 import java.io.IOException;
     35 
     36 import org.apache.http.HttpClientConnection;
     37 import org.apache.http.HttpConnectionMetrics;
     38 import org.apache.http.HttpEntity;
     39 import org.apache.http.HttpEntityEnclosingRequest;
     40 import org.apache.http.HttpException;
     41 import org.apache.http.HttpRequest;
     42 import org.apache.http.HttpResponse;
     43 import org.apache.http.HttpResponseFactory;
     44 import org.apache.http.impl.entity.EntityDeserializer;
     45 import org.apache.http.impl.entity.EntitySerializer;
     46 import org.apache.http.impl.entity.LaxContentLengthStrategy;
     47 import org.apache.http.impl.entity.StrictContentLengthStrategy;
     48 import org.apache.http.impl.io.HttpRequestWriter;
     49 import org.apache.http.impl.io.HttpResponseParser;
     50 import org.apache.http.impl.io.SocketInputBuffer;
     51 import org.apache.http.io.HttpMessageParser;
     52 import org.apache.http.io.HttpMessageWriter;
     53 import org.apache.http.io.SessionInputBuffer;
     54 import org.apache.http.io.SessionOutputBuffer;
     55 import org.apache.http.params.HttpParams;
     56 
     57 /**
     58  * Abstract client-side HTTP connection capable of transmitting and receiving data
     59  * using arbitrary {@link SessionInputBuffer} and {@link SessionOutputBuffer}
     60  *
     61  * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
     62  *
     63  * @version $Revision: 627457 $
     64  *
     65  * @since 4.0
     66  */
     67 public abstract class AbstractHttpClientConnection implements HttpClientConnection {
     68 
     69     private final EntitySerializer entityserializer;
     70     private final EntityDeserializer entitydeserializer;
     71 
     72     private SessionInputBuffer inbuffer = null;
     73     private SessionOutputBuffer outbuffer = null;
     74     private HttpMessageParser responseParser = null;
     75     private HttpMessageWriter requestWriter = null;
     76     private HttpConnectionMetricsImpl metrics = null;
     77 
     78 
     79 
     80     public AbstractHttpClientConnection() {
     81         super();
     82         this.entityserializer = createEntitySerializer();
     83         this.entitydeserializer = createEntityDeserializer();
     84     }
     85 
     86     protected abstract void assertOpen() throws IllegalStateException;
     87 
     88     protected EntityDeserializer createEntityDeserializer() {
     89         return new EntityDeserializer(new LaxContentLengthStrategy());
     90     }
     91 
     92     protected EntitySerializer createEntitySerializer() {
     93         return new EntitySerializer(new StrictContentLengthStrategy());
     94     }
     95 
     96     protected HttpResponseFactory createHttpResponseFactory() {
     97         return new DefaultHttpResponseFactory();
     98     }
     99 
    100     protected HttpMessageParser createResponseParser(
    101             final SessionInputBuffer buffer,
    102             final HttpResponseFactory responseFactory,
    103             final HttpParams params) {
    104         // override in derived class to specify a line parser
    105         return new HttpResponseParser(buffer, null, responseFactory, params);
    106     }
    107 
    108     protected HttpMessageWriter createRequestWriter(
    109             final SessionOutputBuffer buffer,
    110             final HttpParams params) {
    111         // override in derived class to specify a line formatter
    112         return new HttpRequestWriter(buffer, null, params);
    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.responseParser = createResponseParser(
    128                 inbuffer,
    129                 createHttpResponseFactory(),
    130                 params);
    131         this.requestWriter = createRequestWriter(
    132                 outbuffer, params);
    133         this.metrics = new HttpConnectionMetricsImpl(
    134                 inbuffer.getMetrics(),
    135                 outbuffer.getMetrics());
    136     }
    137 
    138     public boolean isResponseAvailable(int timeout) throws IOException {
    139         assertOpen();
    140         return this.inbuffer.isDataAvailable(timeout);
    141     }
    142 
    143     public void sendRequestHeader(final HttpRequest request)
    144             throws HttpException, IOException {
    145         if (request == null) {
    146             throw new IllegalArgumentException("HTTP request may not be null");
    147         }
    148         assertOpen();
    149         this.requestWriter.write(request);
    150         this.metrics.incrementRequestCount();
    151     }
    152 
    153     public void sendRequestEntity(final HttpEntityEnclosingRequest request)
    154             throws HttpException, IOException {
    155         if (request == null) {
    156             throw new IllegalArgumentException("HTTP request may not be null");
    157         }
    158         assertOpen();
    159         if (request.getEntity() == null) {
    160             return;
    161         }
    162         this.entityserializer.serialize(
    163                 this.outbuffer,
    164                 request,
    165                 request.getEntity());
    166     }
    167 
    168     protected void doFlush() throws IOException {
    169         this.outbuffer.flush();
    170     }
    171 
    172     public void flush() throws IOException {
    173         assertOpen();
    174         doFlush();
    175     }
    176 
    177     public HttpResponse receiveResponseHeader()
    178             throws HttpException, IOException {
    179         assertOpen();
    180         HttpResponse response = (HttpResponse) this.responseParser.parse();
    181         if (response.getStatusLine().getStatusCode() >= 200) {
    182             this.metrics.incrementResponseCount();
    183         }
    184         return response;
    185     }
    186 
    187     public void receiveResponseEntity(final HttpResponse response)
    188             throws HttpException, IOException {
    189         if (response == null) {
    190             throw new IllegalArgumentException("HTTP response may not be null");
    191         }
    192         assertOpen();
    193         HttpEntity entity = this.entitydeserializer.deserialize(this.inbuffer, response);
    194         response.setEntity(entity);
    195     }
    196 
    197     public boolean isStale() {
    198         if (!isOpen()) {
    199             return true;
    200         }
    201         try {
    202             // BEGIN android-added
    203             //     don't reuse connections when the socket input stream is exhausted
    204             if (inbuffer instanceof SocketInputBuffer) {
    205                 return ((SocketInputBuffer) inbuffer).isStale();
    206             }
    207             // END android-added
    208             this.inbuffer.isDataAvailable(1);
    209             return false;
    210         } catch (IOException ex) {
    211             return true;
    212         }
    213     }
    214 
    215     public HttpConnectionMetrics getMetrics() {
    216         return this.metrics;
    217     }
    218 
    219 }
    220