Wed, 31 Dec 2014 07:22:50 +0100
Correct previous dual key logic pending first delivery installment.
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 */
28 package ch.boye.httpclientandroidlib.impl;
30 import java.io.IOException;
31 import java.net.InetAddress;
32 import java.net.Socket;
33 import java.net.SocketException;
35 import ch.boye.httpclientandroidlib.HttpInetConnection;
36 import ch.boye.httpclientandroidlib.impl.io.SocketInputBuffer;
37 import ch.boye.httpclientandroidlib.impl.io.SocketOutputBuffer;
38 import ch.boye.httpclientandroidlib.io.SessionInputBuffer;
39 import ch.boye.httpclientandroidlib.io.SessionOutputBuffer;
40 import ch.boye.httpclientandroidlib.params.HttpConnectionParams;
41 import ch.boye.httpclientandroidlib.params.HttpParams;
43 /**
44 * Implementation of a server-side HTTP connection that can be bound to a
45 * network Socket in order to receive and transmit data.
46 * <p>
47 * The following parameters can be used to customize the behavior of this
48 * class:
49 * <ul>
50 * <li>{@link ch.boye.httpclientandroidlib.params.CoreProtocolPNames#STRICT_TRANSFER_ENCODING}</li>
51 * <li>{@link ch.boye.httpclientandroidlib.params.CoreProtocolPNames#HTTP_ELEMENT_CHARSET}</li>
52 * <li>{@link ch.boye.httpclientandroidlib.params.CoreConnectionPNames#SOCKET_BUFFER_SIZE}</li>
53 * <li>{@link ch.boye.httpclientandroidlib.params.CoreConnectionPNames#MAX_LINE_LENGTH}</li>
54 * <li>{@link ch.boye.httpclientandroidlib.params.CoreConnectionPNames#MAX_HEADER_COUNT}</li>
55 * </ul>
56 *
57 * @since 4.0
58 */
59 public class SocketHttpServerConnection extends
60 AbstractHttpServerConnection implements HttpInetConnection {
62 private volatile boolean open;
63 private volatile Socket socket = null;
65 public SocketHttpServerConnection() {
66 super();
67 }
69 protected void assertNotOpen() {
70 if (this.open) {
71 throw new IllegalStateException("Connection is already open");
72 }
73 }
75 protected void assertOpen() {
76 if (!this.open) {
77 throw new IllegalStateException("Connection is not open");
78 }
79 }
81 /**
82 * @deprecated Use {@link #createSessionInputBuffer(Socket, int, HttpParams)}
83 */
84 protected SessionInputBuffer createHttpDataReceiver(
85 final Socket socket,
86 int buffersize,
87 final HttpParams params) throws IOException {
88 return createSessionInputBuffer(socket, buffersize, params);
89 }
91 /**
92 * @deprecated Use {@link #createSessionOutputBuffer(Socket, int, HttpParams)}
93 */
94 protected SessionOutputBuffer createHttpDataTransmitter(
95 final Socket socket,
96 int buffersize,
97 final HttpParams params) throws IOException {
98 return createSessionOutputBuffer(socket, buffersize, params);
99 }
101 /**
102 * Creates an instance of {@link SocketInputBuffer} to be used for
103 * receiving data from the given {@link Socket}.
104 * <p>
105 * This method can be overridden in a super class in order to provide
106 * a custom implementation of {@link SessionInputBuffer} interface.
107 *
108 * @see SocketInputBuffer#SocketInputBuffer(Socket, int, HttpParams)
109 *
110 * @param socket the socket.
111 * @param buffersize the buffer size.
112 * @param params HTTP parameters.
113 * @return session input buffer.
114 * @throws IOException in case of an I/O error.
115 */
116 protected SessionInputBuffer createSessionInputBuffer(
117 final Socket socket,
118 int buffersize,
119 final HttpParams params) throws IOException {
120 return new SocketInputBuffer(socket, buffersize, params);
121 }
123 /**
124 * Creates an instance of {@link SessionOutputBuffer} to be used for
125 * sending data to the given {@link Socket}.
126 * <p>
127 * This method can be overridden in a super class in order to provide
128 * a custom implementation of {@link SocketOutputBuffer} interface.
129 *
130 * @see SocketOutputBuffer#SocketOutputBuffer(Socket, int, HttpParams)
131 *
132 * @param socket the socket.
133 * @param buffersize the buffer size.
134 * @param params HTTP parameters.
135 * @return session output buffer.
136 * @throws IOException in case of an I/O error.
137 */
138 protected SessionOutputBuffer createSessionOutputBuffer(
139 final Socket socket,
140 int buffersize,
141 final HttpParams params) throws IOException {
142 return new SocketOutputBuffer(socket, buffersize, params);
143 }
145 /**
146 * Binds this connection to the given {@link Socket}. This socket will be
147 * used by the connection to send and receive data.
148 * <p>
149 * This method will invoke {@link #createSessionInputBuffer(Socket, int, HttpParams)}
150 * and {@link #createSessionOutputBuffer(Socket, int, HttpParams)} methods
151 * to create session input / output buffers bound to this socket and then
152 * will invoke {@link #init(SessionInputBuffer, SessionOutputBuffer, HttpParams)}
153 * method to pass references to those buffers to the underlying HTTP message
154 * parser and formatter.
155 * <p>
156 * After this method's execution the connection status will be reported
157 * as open and the {@link #isOpen()} will return <code>true</code>.
158 *
159 * @param socket the socket.
160 * @param params HTTP parameters.
161 * @throws IOException in case of an I/O error.
162 */
163 protected void bind(final Socket socket, final HttpParams params) throws IOException {
164 if (socket == null) {
165 throw new IllegalArgumentException("Socket may not be null");
166 }
167 if (params == null) {
168 throw new IllegalArgumentException("HTTP parameters may not be null");
169 }
170 this.socket = socket;
172 int buffersize = HttpConnectionParams.getSocketBufferSize(params);
174 init(
175 createHttpDataReceiver(socket, buffersize, params),
176 createHttpDataTransmitter(socket, buffersize, params),
177 params);
179 this.open = true;
180 }
182 protected Socket getSocket() {
183 return this.socket;
184 }
186 public boolean isOpen() {
187 return this.open;
188 }
190 public InetAddress getLocalAddress() {
191 if (this.socket != null) {
192 return this.socket.getLocalAddress();
193 } else {
194 return null;
195 }
196 }
198 public int getLocalPort() {
199 if (this.socket != null) {
200 return this.socket.getLocalPort();
201 } else {
202 return -1;
203 }
204 }
206 public InetAddress getRemoteAddress() {
207 if (this.socket != null) {
208 return this.socket.getInetAddress();
209 } else {
210 return null;
211 }
212 }
214 public int getRemotePort() {
215 if (this.socket != null) {
216 return this.socket.getPort();
217 } else {
218 return -1;
219 }
220 }
222 public void setSocketTimeout(int timeout) {
223 assertOpen();
224 if (this.socket != null) {
225 try {
226 this.socket.setSoTimeout(timeout);
227 } catch (SocketException ignore) {
228 // It is not quite clear from the Sun's documentation if there are any
229 // other legitimate cases for a socket exception to be thrown when setting
230 // SO_TIMEOUT besides the socket being already closed
231 }
232 }
233 }
235 public int getSocketTimeout() {
236 if (this.socket != null) {
237 try {
238 return this.socket.getSoTimeout();
239 } catch (SocketException ignore) {
240 return -1;
241 }
242 } else {
243 return -1;
244 }
245 }
247 public void shutdown() throws IOException {
248 this.open = false;
249 Socket tmpsocket = this.socket;
250 if (tmpsocket != null) {
251 tmpsocket.close();
252 }
253 }
255 public void close() throws IOException {
256 if (!this.open) {
257 return;
258 }
259 this.open = false;
260 this.open = false;
261 Socket sock = this.socket;
262 try {
263 doFlush();
264 try {
265 try {
266 sock.shutdownOutput();
267 } catch (IOException ignore) {
268 }
269 try {
270 sock.shutdownInput();
271 } catch (IOException ignore) {
272 }
273 } catch (UnsupportedOperationException ignore) {
274 // if one isn't supported, the other one isn't either
275 }
276 } finally {
277 sock.close();
278 }
279 }
281 }