Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/apache/http/impl/DefaultHttpClientConnection.java


1   /*
2    * $HeadURL: https://svn.apache.org/repos/asf/jakarta/httpcomponents/httpcore/tags/4.0-alpha2/src/java/org/apache/http/impl/DefaultHttpClientConnection.java $
3    * $Revision: 411100 $
4    * $Date: 2006-06-02 11:12:04 +0200 (Fri, 02 Jun 2006) $
5    *
6    * ====================================================================
7    *
8    *  Copyright 1999-2006 The Apache Software Foundation
9    *
10   *  Licensed under the Apache License, Version 2.0 (the "License");
11   *  you may not use this file except in compliance with the License.
12   *  You may obtain a copy of the License at
13   *
14   *      http://www.apache.org/licenses/LICENSE-2.0
15   *
16   *  Unless required by applicable law or agreed to in writing, software
17   *  distributed under the License is distributed on an "AS IS" BASIS,
18   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19   *  See the License for the specific language governing permissions and
20   *  limitations under the License.
21   * ====================================================================
22   *
23   * This software consists of voluntary contributions made by many
24   * individuals on behalf of the Apache Software Foundation.  For more
25   * information on the Apache Software Foundation, please see
26   * <http://www.apache.org/>.
27   *
28   */
29  
30  package org.apache.http.impl;
31  
32  import java.io.IOException;
33  import java.net.InetAddress;
34  import java.net.Socket;
35  
36  import org.apache.http.Header;
37  import org.apache.http.HttpClientConnection;
38  import org.apache.http.HttpEntity;
39  import org.apache.http.HttpEntityEnclosingRequest;
40  import org.apache.http.HttpException;
41  import org.apache.http.HttpHost;
42  import org.apache.http.HttpRequest;
43  import org.apache.http.HttpResponse;
44  import org.apache.http.HttpResponseFactory;
45  import org.apache.http.NoHttpResponseException;
46  import org.apache.http.ProtocolException;
47  import org.apache.http.RequestLine;
48  import org.apache.http.StatusLine;
49  import org.apache.http.entity.EntityDeserializer;
50  import org.apache.http.entity.EntitySerializer;
51  import org.apache.http.impl.entity.DefaultEntitySerializer;
52  import org.apache.http.impl.entity.DefaultEntityDeserializer;
53  import org.apache.http.io.CharArrayBuffer;
54  import org.apache.http.io.SocketFactory;
55  import org.apache.http.params.HttpConnectionParams;
56  import org.apache.http.params.HttpParams;
57  import org.apache.http.params.HttpProtocolParams;
58  import org.apache.http.protocol.HTTP;
59  import org.apache.http.util.HeaderUtils;
60  
61  /**
62   * Default implementation of a client-side HTTP connection.
63   *
64   * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
65   *
66   * @version $Revision: 411100 $
67   * 
68   * @since 4.0
69   */
70  public class DefaultHttpClientConnection 
71          extends AbstractHttpConnection implements HttpClientConnection {
72  
73      private HttpHost targethost = null;
74      private InetAddress localAddress = null;
75      private int maxHeaderCount = -1;
76  
77      private final CharArrayBuffer buffer; 
78      
79      /*
80       * Dependent interfaces
81       */
82      private HttpResponseFactory responsefactory = null;
83      private EntitySerializer entityserializer = null;
84      private EntityDeserializer entitydeserializer = null;
85      
86      public DefaultHttpClientConnection(final HttpHost targethost, final InetAddress localAddress) {
87          super();
88          this.targethost = targethost;
89          this.localAddress = localAddress;
90          this.buffer = new CharArrayBuffer(128);
91          this.responsefactory = new DefaultHttpResponseFactory();
92          this.entityserializer = new DefaultEntitySerializer();
93          this.entitydeserializer = new DefaultEntityDeserializer();
94      }
95      
96      public DefaultHttpClientConnection(final HttpHost targethost) {
97          this(targethost, null);
98      }
99      
100     public DefaultHttpClientConnection() {
101         this(null, null);
102     }
103     
104     public void setResponseFactory(final HttpResponseFactory responsefactory) {
105         if (responsefactory == null) {
106             throw new IllegalArgumentException("Factory may not be null");
107         }
108         this.responsefactory = responsefactory;
109     }
110 
111     public void setEntityDeserializer(final EntityDeserializer entitydeserializer) {
112         if (entitydeserializer == null) {
113             throw new IllegalArgumentException("Entity deserializer may not be null");
114         }
115         this.entitydeserializer = entitydeserializer;
116     }
117 
118     public void setEntitySerializer(final EntitySerializer entityserializer) {
119         if (entityserializer == null) {
120             throw new IllegalArgumentException("Entity serializer may not be null");
121         }
122         this.entityserializer = entityserializer;
123     }
124 
125     public void open(final HttpParams params) throws IOException {
126         if (params == null) {
127             throw new IllegalArgumentException("HTTP parameters may not be null");
128         }
129         assertNotOpen();
130         if (this.targethost == null) {
131           throw new IllegalStateException("Target host not specified");
132         }
133         SocketFactory socketfactory = this.targethost.getScheme().getSocketFactory();
134         Socket socket = socketfactory.createSocket(
135                 this.targethost.getHostName(), this.targethost.getPort(), 
136                 this.localAddress, 0, 
137                 params);
138         bind(socket, params);
139         this.maxHeaderCount = params.getIntParameter(HttpConnectionParams.MAX_HEADER_COUNT, -1);
140     }
141     
142     public HttpHost getTargetHost() {
143         return this.targethost;
144     }
145     
146     public InetAddress getLocalAddress() {
147         return this.localAddress;
148     }
149     
150     public void setTargetHost(final HttpHost targethost) {
151         if (targethost == null) {
152             throw new IllegalArgumentException("Target host may not be null");
153         }
154         assertNotOpen();
155         this.targethost = targethost;
156     }
157 
158     public void setLocalAddress(final InetAddress localAddress) {
159         assertNotOpen();
160         this.localAddress = localAddress;
161     }
162     
163     public boolean isResponseAvailable(int timeout) throws IOException {
164         assertOpen();
165         return this.datareceiver.isDataAvailable(timeout);
166     }
167 
168     public void sendRequestHeader(final HttpRequest request) 
169             throws HttpException, IOException {
170         if (request == null) {
171             throw new IllegalArgumentException("HTTP request may not be null");
172         }
173         assertOpen();
174         sendRequestLine(request);
175         sendRequestHeaders(request);
176     }
177 
178     public void sendRequestEntity(final HttpEntityEnclosingRequest request) 
179             throws HttpException, IOException {
180         if (request == null) {
181             throw new IllegalArgumentException("HTTP request may not be null");
182         }
183         assertOpen();
184         if (request.getEntity() == null) {
185             return;
186         }
187         this.entityserializer.serialize(
188                 this.datatransmitter,
189                 request,
190                 request.getEntity());
191     }
192 
193     public void flush() throws IOException {
194         this.datatransmitter.flush();
195     }
196     
197     protected void sendRequestLine(final HttpRequest request) 
198             throws HttpException, IOException {
199         this.buffer.clear();
200         RequestLine.format(this.buffer, request.getRequestLine());
201         this.datatransmitter.writeLine(this.buffer);
202     }
203 
204     protected void sendRequestHeaders(final HttpRequest request) 
205             throws HttpException, IOException {
206         Header[] headers = request.getAllHeaders();
207         for (int i = 0; i < headers.length; i++) {
208             this.buffer.clear();
209             Header.format(this.buffer, headers[i]);
210             this.datatransmitter.writeLine(this.buffer);
211         }
212         this.buffer.clear();
213         this.datatransmitter.writeLine(this.buffer);
214     }
215 
216     public HttpResponse receiveResponseHeader(final HttpParams params) 
217             throws HttpException, IOException {
218         if (params == null) {
219             throw new IllegalArgumentException("HTTP parameters may not be null");
220         }
221         assertOpen();
222         HttpResponse response = readResponseStatusLine(params);
223         readResponseHeaders(response);
224         return response;
225     }
226 
227     public void receiveResponseEntity(final HttpResponse response)
228             throws HttpException, IOException {
229         if (response == null) {
230             throw new IllegalArgumentException("HTTP response may not be null");
231         }
232         assertOpen();
233         HttpEntity entity = this.entitydeserializer.deserialize(this.datareceiver, response);
234         response.setEntity(entity);
235     }
236     
237     /**
238      * Tests if the string starts with 'HTTP' signature.
239      * @param buffer buffer to test
240      * @return <tt>true</tt> if the line starts with 'HTTP' 
241      *   signature, <tt>false</tt> otherwise.
242      */
243     private static boolean startsWithHTTP(final CharArrayBuffer buffer) {
244         try {
245             int i = 0;
246             while (HTTP.isWhitespace(buffer.charAt(i))) {
247                 ++i;
248             }
249             return buffer.charAt(i) == 'H' 
250                 && buffer.charAt(i + 1) == 'T'
251                 && buffer.charAt(i + 2) == 'T'
252                 && buffer.charAt(i + 3) == 'P';
253         } catch (IndexOutOfBoundsException e) {
254             return false;
255         }
256     }
257     
258     protected HttpResponse readResponseStatusLine(final HttpParams params) 
259                 throws HttpException, IOException {
260         // clear the buffer
261         this.buffer.clear();
262         //read out the HTTP status string
263         int maxGarbageLines = params.getIntParameter(
264                 HttpProtocolParams.STATUS_LINE_GARBAGE_LIMIT, Integer.MAX_VALUE);
265         int count = 0;
266         do {
267             int i = this.datareceiver.readLine(this.buffer);
268             if (i == -1 && count == 0) {
269                 // The server just dropped connection on us
270                 throw new NoHttpResponseException("The server " + 
271                         this.targethost.getHostName() + " failed to respond");
272             }
273             if (startsWithHTTP(this.buffer)) {
274                 // Got one
275                 break;
276             } else if (i == -1 || count >= maxGarbageLines) {
277                 // Giving up
278                 throw new ProtocolException("The server " + this.targethost.getHostName() + 
279                         " failed to respond with a valid HTTP response");
280             }
281             count++;
282         } while(true);
283         //create the status line from the status string
284         StatusLine statusline = StatusLine.parse(this.buffer, 0, this.buffer.length());
285         HttpResponse response = this.responsefactory.newHttpResponse(statusline);
286         response.getParams().setDefaults(params);
287         return response;
288     }
289 
290     protected void readResponseHeaders(final HttpResponse response) 
291             throws HttpException, IOException {
292         Header[] headers = HeaderUtils.parseHeaders(this.datareceiver, this.maxHeaderCount);
293         for (int i = 0; i < headers.length; i++) {
294             response.addHeader(headers[i]);
295         }
296     }
297     
298 }