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