1/*
2 * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/conn/DefaultClientConnection.java $
3 * $Revision: 673450 $
4 * $Date: 2008-07-02 10:35:05 -0700 (Wed, 02 Jul 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.conn;
33
34
35import java.io.IOException;
36import java.net.Socket;
37
38import org.apache.commons.logging.Log;
39import org.apache.commons.logging.LogFactory;
40import org.apache.http.Header;
41import org.apache.http.HttpException;
42import org.apache.http.HttpHost;
43import org.apache.http.HttpRequest;
44import org.apache.http.HttpResponse;
45import org.apache.http.HttpResponseFactory;
46import org.apache.http.params.HttpParams;
47import org.apache.http.impl.SocketHttpClientConnection;
48import org.apache.http.io.HttpMessageParser;
49import org.apache.http.io.SessionInputBuffer;
50import org.apache.http.io.SessionOutputBuffer;
51
52import org.apache.http.conn.OperatedClientConnection;
53
54
55/**
56 * Default implementation of an operated client connection.
57 *
58 * @author <a href="mailto:rolandw at apache.org">Roland Weber</a>
59 *
60 *
61 * <!-- empty lines to avoid svn diff problems -->
62 * @version   $Revision: 673450 $ $Date: 2008-07-02 10:35:05 -0700 (Wed, 02 Jul 2008) $
63 *
64 * @since 4.0
65 */
66public class DefaultClientConnection extends SocketHttpClientConnection
67    implements OperatedClientConnection {
68
69    private final Log log = LogFactory.getLog(getClass());
70    private final Log headerLog = LogFactory.getLog("org.apache.http.headers");
71    private final Log wireLog = LogFactory.getLog("org.apache.http.wire");
72
73    /** The unconnected socket */
74    private volatile Socket socket;
75
76    /** The target host of this connection. */
77    private HttpHost targetHost;
78
79    /** Whether this connection is secure. */
80    private boolean connSecure;
81
82    /** True if this connection was shutdown. */
83    private volatile boolean shutdown;
84
85    public DefaultClientConnection() {
86        super();
87    }
88
89
90    // non-javadoc, see interface OperatedClientConnection
91    public final HttpHost getTargetHost() {
92        return this.targetHost;
93    }
94
95
96    // non-javadoc, see interface OperatedClientConnection
97    public final boolean isSecure() {
98        return this.connSecure;
99    }
100
101
102    @Override
103    public final Socket getSocket() {
104        return this.socket;
105    }
106
107
108    public void opening(Socket sock, HttpHost target) throws IOException {
109        assertNotOpen();
110        this.socket = sock;
111        this.targetHost = target;
112
113        // Check for shutdown after assigning socket, so that
114        if (this.shutdown) {
115            sock.close(); // allow this to throw...
116            // ...but if it doesn't, explicitly throw one ourselves.
117            throw new IOException("Connection already shutdown");
118        }
119    }
120
121
122    public void openCompleted(boolean secure, HttpParams params) throws IOException {
123        assertNotOpen();
124        if (params == null) {
125            throw new IllegalArgumentException
126                ("Parameters must not be null.");
127        }
128        this.connSecure = secure;
129        bind(this.socket, params);
130    }
131
132    /**
133     * Force-closes this connection.
134     * If the connection is still in the process of being open (the method
135     * {@link #opening opening} was already called but
136     * {@link #openCompleted openCompleted} was not), the associated
137     * socket that is being connected to a remote address will be closed.
138     * That will interrupt a thread that is blocked on connecting
139     * the socket.
140     * If the connection is not yet open, this will prevent the connection
141     * from being opened.
142     *
143     * @throws IOException      in case of a problem
144     */
145    @Override
146    public void shutdown() throws IOException {
147        log.debug("Connection shut down");
148        shutdown = true;
149
150        super.shutdown();
151        Socket sock = this.socket; // copy volatile attribute
152        if (sock != null)
153            sock.close();
154
155    } // shutdown
156
157
158    @Override
159    public void close() throws IOException {
160        log.debug("Connection closed");
161        super.close();
162    }
163
164
165    @Override
166    protected SessionInputBuffer createSessionInputBuffer(
167            final Socket socket,
168            int buffersize,
169            final HttpParams params) throws IOException {
170        SessionInputBuffer inbuffer = super.createSessionInputBuffer(
171                socket,
172                buffersize,
173                params);
174        if (wireLog.isDebugEnabled()) {
175            inbuffer = new LoggingSessionInputBuffer(inbuffer, new Wire(wireLog));
176        }
177        return inbuffer;
178    }
179
180
181    @Override
182    protected SessionOutputBuffer createSessionOutputBuffer(
183            final Socket socket,
184            int buffersize,
185            final HttpParams params) throws IOException {
186        SessionOutputBuffer outbuffer = super.createSessionOutputBuffer(
187                socket,
188                buffersize,
189                params);
190        if (wireLog.isDebugEnabled()) {
191            outbuffer = new LoggingSessionOutputBuffer(outbuffer, new Wire(wireLog));
192        }
193        return outbuffer;
194    }
195
196
197    @Override
198    protected HttpMessageParser createResponseParser(
199            final SessionInputBuffer buffer,
200            final HttpResponseFactory responseFactory,
201            final HttpParams params) {
202        // override in derived class to specify a line parser
203        return new DefaultResponseParser
204            (buffer, null, responseFactory, params);
205    }
206
207
208    // non-javadoc, see interface OperatedClientConnection
209    public void update(Socket sock, HttpHost target,
210                       boolean secure, HttpParams params)
211        throws IOException {
212
213        assertOpen();
214        if (target == null) {
215            throw new IllegalArgumentException
216                ("Target host must not be null.");
217        }
218        if (params == null) {
219            throw new IllegalArgumentException
220                ("Parameters must not be null.");
221        }
222
223        if (sock != null) {
224            this.socket = sock;
225            bind(sock, params);
226        }
227        targetHost = target;
228        connSecure = secure;
229
230    } // update
231
232
233    @Override
234    public HttpResponse receiveResponseHeader() throws HttpException, IOException {
235        HttpResponse response = super.receiveResponseHeader();
236        if (headerLog.isDebugEnabled()) {
237            headerLog.debug("<< " + response.getStatusLine().toString());
238            Header[] headers = response.getAllHeaders();
239            for (Header header : headers) {
240                headerLog.debug("<< " + header.toString());
241            }
242        }
243        return response;
244    }
245
246
247    @Override
248    public void sendRequestHeader(HttpRequest request) throws HttpException, IOException {
249        super.sendRequestHeader(request);
250        if (headerLog.isDebugEnabled()) {
251            headerLog.debug(">> " + request.getRequestLine().toString());
252            Header[] headers = request.getAllHeaders();
253            for (Header header : headers) {
254                headerLog.debug(">> " + header.toString());
255            }
256        }
257    }
258
259} // class DefaultClientConnection
260