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.conn;
29  
30  import java.io.IOException;
31  import java.io.InterruptedIOException;
32  import java.net.Socket;
33  import java.util.HashMap;
34  import java.util.Map;
35  
36  import javax.net.ssl.SSLSession;
37  import javax.net.ssl.SSLSocket;
38  
39  import org.apache.commons.logging.Log;
40  import org.apache.commons.logging.LogFactory;
41  import org.apache.http.Header;
42  import org.apache.http.HttpException;
43  import org.apache.http.HttpHost;
44  import org.apache.http.HttpRequest;
45  import org.apache.http.HttpResponse;
46  import org.apache.http.HttpResponseFactory;
47  import org.apache.http.annotation.NotThreadSafe;
48  import org.apache.http.conn.OperatedClientConnection;
49  import org.apache.http.conn.ManagedHttpClientConnection;
50  import org.apache.http.impl.SocketHttpClientConnection;
51  import org.apache.http.io.HttpMessageParser;
52  import org.apache.http.io.SessionInputBuffer;
53  import org.apache.http.io.SessionOutputBuffer;
54  import org.apache.http.params.BasicHttpParams;
55  import org.apache.http.params.HttpParams;
56  import org.apache.http.params.HttpProtocolParams;
57  import org.apache.http.protocol.HttpContext;
58  import org.apache.http.util.Args;
59  
60  /**
61   * Default implementation of an operated client connection.
62   *
63   * @since 4.0
64   *
65   * @deprecated (4.3) use {@link ManagedHttpClientConnectionFactory}.
66   */
67  @NotThreadSafe // connSecure, targetHost
68  @Deprecated
69  public class DefaultClientConnection extends SocketHttpClientConnection
70      implements OperatedClientConnection, ManagedHttpClientConnection, HttpContext {
71  
72      private final Log log = LogFactory.getLog(getClass());
73      private final Log headerLog = LogFactory.getLog("org.apache.http.headers");
74      private final Log wireLog = LogFactory.getLog("org.apache.http.wire");
75  
76      /** The unconnected socket */
77      private volatile Socket socket;
78  
79      /** The target host of this connection. */
80      private HttpHost targetHost;
81  
82      /** Whether this connection is secure. */
83      private boolean connSecure;
84  
85      /** True if this connection was shutdown. */
86      private volatile boolean shutdown;
87  
88      /** connection specific attributes */
89      private final Map<String, Object> attributes;
90  
91      public DefaultClientConnection() {
92          super();
93          this.attributes = new HashMap<String, Object>();
94      }
95  
96      @Override
97      public String getId() {
98          return null;
99      }
100 
101     @Override
102     public final HttpHost getTargetHost() {
103         return this.targetHost;
104     }
105 
106     @Override
107     public final boolean isSecure() {
108         return this.connSecure;
109     }
110 
111     @Override
112     public final Socket getSocket() {
113         return this.socket;
114     }
115 
116     @Override
117     public SSLSession getSSLSession() {
118         if (this.socket instanceof SSLSocket) {
119             return ((SSLSocket) this.socket).getSession();
120         } else {
121             return null;
122         }
123     }
124 
125     @Override
126     public void opening(final Socket sock, final HttpHost target) throws IOException {
127         assertNotOpen();
128         this.socket = sock;
129         this.targetHost = target;
130 
131         // Check for shutdown after assigning socket, so that
132         if (this.shutdown) {
133             sock.close(); // allow this to throw...
134             // ...but if it doesn't, explicitly throw one ourselves.
135             throw new InterruptedIOException("Connection already shutdown");
136         }
137     }
138 
139     @Override
140     public void openCompleted(final boolean secure, final HttpParams params) throws IOException {
141         Args.notNull(params, "Parameters");
142         assertNotOpen();
143         this.connSecure = secure;
144         bind(this.socket, params);
145     }
146 
147     /**
148      * Force-closes this connection.
149      * If the connection is still in the process of being open (the method
150      * {@link #opening opening} was already called but
151      * {@link #openCompleted openCompleted} was not), the associated
152      * socket that is being connected to a remote address will be closed.
153      * That will interrupt a thread that is blocked on connecting
154      * the socket.
155      * If the connection is not yet open, this will prevent the connection
156      * from being opened.
157      *
158      * @throws IOException      in case of a problem
159      */
160     @Override
161     public void shutdown() throws IOException {
162         shutdown = true;
163         try {
164             super.shutdown();
165             if (log.isDebugEnabled()) {
166                 log.debug("Connection " + this + " shut down");
167             }
168             final Socket sock = this.socket; // copy volatile attribute
169             if (sock != null) {
170                 sock.close();
171             }
172         } catch (final IOException ex) {
173             log.debug("I/O error shutting down connection", ex);
174         }
175     }
176 
177     @Override
178     public void close() throws IOException {
179         try {
180             super.close();
181             if (log.isDebugEnabled()) {
182                 log.debug("Connection " + this + " closed");
183             }
184         } catch (final IOException ex) {
185             log.debug("I/O error closing connection", ex);
186         }
187     }
188 
189     @Override
190     protected SessionInputBuffer createSessionInputBuffer(
191             final Socket socket,
192             final int buffersize,
193             final HttpParams params) throws IOException {
194         SessionInputBuffer inbuffer = super.createSessionInputBuffer(
195                 socket,
196                 buffersize > 0 ? buffersize : 8192,
197                 params);
198         if (wireLog.isDebugEnabled()) {
199             inbuffer = new LoggingSessionInputBuffer(
200                     inbuffer,
201                     new Wire(wireLog),
202                     HttpProtocolParams.getHttpElementCharset(params));
203         }
204         return inbuffer;
205     }
206 
207     @Override
208     protected SessionOutputBuffer createSessionOutputBuffer(
209             final Socket socket,
210             final int buffersize,
211             final HttpParams params) throws IOException {
212         SessionOutputBuffer outbuffer = super.createSessionOutputBuffer(
213                 socket,
214                 buffersize > 0 ? buffersize : 8192,
215                 params);
216         if (wireLog.isDebugEnabled()) {
217             outbuffer = new LoggingSessionOutputBuffer(
218                     outbuffer,
219                     new Wire(wireLog),
220                     HttpProtocolParams.getHttpElementCharset(params));
221         }
222         return outbuffer;
223     }
224 
225     @Override
226     protected HttpMessageParser<HttpResponse> createResponseParser(
227             final SessionInputBuffer buffer,
228             final HttpResponseFactory responseFactory,
229             final HttpParams params) {
230         // override in derived class to specify a line parser
231         return new DefaultHttpResponseParser
232             (buffer, null, responseFactory, params);
233     }
234 
235     @Override
236     public void bind(final Socket socket) throws IOException {
237         bind(socket, new BasicHttpParams());
238     }
239 
240     @Override
241     public void update(final Socket sock, final HttpHost target,
242                        final boolean secure, final HttpParams params)
243         throws IOException {
244 
245         assertOpen();
246         Args.notNull(target, "Target host");
247         Args.notNull(params, "Parameters");
248 
249         if (sock != null) {
250             this.socket = sock;
251             bind(sock, params);
252         }
253         targetHost = target;
254         connSecure = secure;
255     }
256 
257     @Override
258     public HttpResponse receiveResponseHeader() throws HttpException, IOException {
259         final HttpResponse response = super.receiveResponseHeader();
260         if (log.isDebugEnabled()) {
261             log.debug("Receiving response: " + response.getStatusLine());
262         }
263         if (headerLog.isDebugEnabled()) {
264             headerLog.debug("<< " + response.getStatusLine().toString());
265             final Header[] headers = response.getAllHeaders();
266             for (final Header header : headers) {
267                 headerLog.debug("<< " + header.toString());
268             }
269         }
270         return response;
271     }
272 
273     @Override
274     public void sendRequestHeader(final HttpRequest request) throws HttpException, IOException {
275         if (log.isDebugEnabled()) {
276             log.debug("Sending request: " + request.getRequestLine());
277         }
278         super.sendRequestHeader(request);
279         if (headerLog.isDebugEnabled()) {
280             headerLog.debug(">> " + request.getRequestLine().toString());
281             final Header[] headers = request.getAllHeaders();
282             for (final Header header : headers) {
283                 headerLog.debug(">> " + header.toString());
284             }
285         }
286     }
287 
288     @Override
289     public Object getAttribute(final String id) {
290         return this.attributes.get(id);
291     }
292 
293     @Override
294     public Object removeAttribute(final String id) {
295         return this.attributes.remove(id);
296     }
297 
298     @Override
299     public void setAttribute(final String id, final Object obj) {
300         this.attributes.put(id, obj);
301     }
302 
303 }