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  import java.net.InetAddress;
32  import java.net.InetSocketAddress;
33  import java.net.Socket;
34  import java.net.SocketAddress;
35  import java.net.SocketException;
36  
37  import org.apache.http.HttpInetConnection;
38  import org.apache.http.impl.io.SocketInputBuffer;
39  import org.apache.http.impl.io.SocketOutputBuffer;
40  import org.apache.http.io.SessionInputBuffer;
41  import org.apache.http.io.SessionOutputBuffer;
42  import org.apache.http.params.CoreConnectionPNames;
43  import org.apache.http.params.HttpParams;
44  import org.apache.http.util.Args;
45  import org.apache.http.util.Asserts;
46  
47  /**
48   * Implementation of a client-side HTTP connection that can be bound to an
49   * arbitrary {@link Socket} for receiving data from and transmitting data to
50   * a remote server.
51   *
52   * @since 4.0
53   *
54   * @deprecated (4.3) use {@link DefaultBHttpClientConnection}
55   */
56  @Deprecated
57  public class SocketHttpClientConnection
58          extends AbstractHttpClientConnection implements HttpInetConnection {
59  
60      private volatile boolean open;
61      private volatile Socket socket = null;
62  
63      public SocketHttpClientConnection() {
64          super();
65      }
66  
67      protected void assertNotOpen() {
68          Asserts.check(!this.open, "Connection is already open");
69      }
70  
71      @Override
72      protected void assertOpen() {
73          Asserts.check(this.open, "Connection is not open");
74      }
75  
76      /**
77       * Creates an instance of {@link SocketInputBuffer} to be used for
78       * receiving data from the given {@link Socket}.
79       * <p>
80       * This method can be overridden in a super class in order to provide
81       * a custom implementation of {@link SessionInputBuffer} interface.
82       *
83       * @see SocketInputBuffer#SocketInputBuffer(Socket, int, HttpParams)
84       *
85       * @param socket the socket.
86       * @param bufferSize the buffer size.
87       * @param params HTTP parameters.
88       * @return session input buffer.
89       * @throws IOException in case of an I/O error.
90       */
91      protected SessionInputBuffer createSessionInputBuffer(
92              final Socket socket,
93              final int bufferSize,
94              final HttpParams params) throws IOException {
95          return new SocketInputBuffer(socket, bufferSize, params);
96      }
97  
98      /**
99       * Creates an instance of {@link SessionOutputBuffer} to be used for
100      * sending data to the given {@link Socket}.
101      * <p>
102      * This method can be overridden in a super class in order to provide
103      * a custom implementation of {@link SocketOutputBuffer} interface.
104      *
105      * @see SocketOutputBuffer#SocketOutputBuffer(Socket, int, HttpParams)
106      *
107      * @param socket the socket.
108      * @param bufferSize the buffer size.
109      * @param params HTTP parameters.
110      * @return session output buffer.
111      * @throws IOException in case of an I/O error.
112      */
113     protected SessionOutputBuffer createSessionOutputBuffer(
114             final Socket socket,
115             final int bufferSize,
116             final HttpParams params) throws IOException {
117         return new SocketOutputBuffer(socket, bufferSize, params);
118     }
119 
120     /**
121      * Binds this connection to the given {@link Socket}. This socket will be
122      * used by the connection to send and receive data.
123      * <p>
124      * This method will invoke {@link #createSessionInputBuffer(Socket, int, HttpParams)}
125      * and {@link #createSessionOutputBuffer(Socket, int, HttpParams)} methods
126      * to create session input / output buffers bound to this socket and then
127      * will invoke {@link #init(SessionInputBuffer, SessionOutputBuffer, HttpParams)}
128      * method to pass references to those buffers to the underlying HTTP message
129      * parser and formatter.
130      * <p>
131      * After this method's execution the connection status will be reported
132      * as open and the {@link #isOpen()} will return {@code true}.
133      *
134      * @param socket the socket.
135      * @param params HTTP parameters.
136      * @throws IOException in case of an I/O error.
137      */
138     protected void bind(
139             final Socket socket,
140             final HttpParams params) throws IOException {
141         Args.notNull(socket, "Socket");
142         Args.notNull(params, "HTTP parameters");
143         this.socket = socket;
144 
145         final int bufferSize = params.getIntParameter(CoreConnectionPNames.SOCKET_BUFFER_SIZE, -1);
146         init(
147                 createSessionInputBuffer(socket, bufferSize, params),
148                 createSessionOutputBuffer(socket, bufferSize, params),
149                 params);
150 
151         this.open = true;
152     }
153 
154     @Override
155     public boolean isOpen() {
156         return this.open;
157     }
158 
159     protected Socket getSocket() {
160         return this.socket;
161     }
162 
163     @Override
164     public InetAddress getLocalAddress() {
165         if (this.socket != null) {
166             return this.socket.getLocalAddress();
167         }
168         return null;
169     }
170 
171     @Override
172     public int getLocalPort() {
173         if (this.socket != null) {
174             return this.socket.getLocalPort();
175         }
176         return -1;
177     }
178 
179     @Override
180     public InetAddress getRemoteAddress() {
181         if (this.socket != null) {
182             return this.socket.getInetAddress();
183         }
184         return null;
185     }
186 
187     @Override
188     public int getRemotePort() {
189         if (this.socket != null) {
190             return this.socket.getPort();
191         }
192         return -1;
193     }
194 
195     @Override
196     public void setSocketTimeout(final int timeout) {
197         assertOpen();
198         if (this.socket != null) {
199             try {
200                 this.socket.setSoTimeout(timeout);
201             } catch (final SocketException ignore) {
202                 // It is not quite clear from the Sun's documentation if there are any
203                 // other legitimate cases for a socket exception to be thrown when setting
204                 // SO_TIMEOUT besides the socket being already closed
205             }
206         }
207     }
208 
209     @Override
210     public int getSocketTimeout() {
211         if (this.socket != null) {
212             try {
213                 return this.socket.getSoTimeout();
214             } catch (final SocketException ignore) {
215                 // ignore
216             }
217         }
218         return -1;
219     }
220 
221     @Override
222     public void shutdown() throws IOException {
223         this.open = false;
224         final Socket tmpsocket = this.socket;
225         if (tmpsocket != null) {
226             tmpsocket.close();
227         }
228     }
229 
230     @Override
231     public void close() throws IOException {
232         if (!this.open) {
233             return;
234         }
235         this.open = false;
236         final Socket sock = this.socket;
237         try {
238             doFlush();
239             try {
240                 try {
241                     sock.shutdownOutput();
242                 } catch (final IOException ignore) {
243                     // ignore
244                 }
245                 try {
246                     sock.shutdownInput();
247                 } catch (final IOException ignore) {
248                     // ignore
249                 }
250             } catch (final UnsupportedOperationException ignore) {
251                 // if one isn't supported, the other one isn't either
252             }
253         } finally {
254             sock.close();
255         }
256     }
257 
258     private static void formatAddress(final StringBuilder buffer, final SocketAddress socketAddress) {
259         if (socketAddress instanceof InetSocketAddress) {
260             final InetSocketAddress addr = ((InetSocketAddress) socketAddress);
261             buffer.append(addr.getAddress() != null ? addr.getAddress().getHostAddress() :
262                 addr.getAddress())
263             .append(':')
264             .append(addr.getPort());
265         } else {
266             buffer.append(socketAddress);
267         }
268     }
269 
270     @Override
271     public String toString() {
272         if (this.socket != null) {
273             final StringBuilder buffer = new StringBuilder();
274             final SocketAddress remoteAddress = this.socket.getRemoteSocketAddress();
275             final SocketAddress localAddress = this.socket.getLocalSocketAddress();
276             if (remoteAddress != null && localAddress != null) {
277                 formatAddress(buffer, localAddress);
278                 buffer.append("<->");
279                 formatAddress(buffer, remoteAddress);
280             }
281             return buffer.toString();
282         }
283         return super.toString();
284     }
285 
286 }