mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/AbstractClientConnAdapter.java

branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
equal deleted inserted replaced
-1:000000000000 0:f18615bc85e8
1 /*
2 * ====================================================================
3 *
4 * Licensed to the Apache Software Foundation (ASF) under one or more
5 * contributor license agreements. See the NOTICE file distributed with
6 * this work for additional information regarding copyright ownership.
7 * The ASF licenses this file to You under the Apache License, Version 2.0
8 * (the "License"); you may not use this file except in compliance with
9 * 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, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ====================================================================
19 *
20 * This software consists of voluntary contributions made by many
21 * individuals on behalf of the Apache Software Foundation. For more
22 * information on the Apache Software Foundation, please see
23 * <http://www.apache.org/>.
24 *
25 */
26
27 package ch.boye.httpclientandroidlib.impl.conn;
28
29 import java.io.IOException;
30 import java.io.InterruptedIOException;
31 import java.net.InetAddress;
32 import java.net.Socket;
33 import java.util.concurrent.TimeUnit;
34
35 import javax.net.ssl.SSLSocket;
36 import javax.net.ssl.SSLSession;
37
38 import ch.boye.httpclientandroidlib.HttpException;
39 import ch.boye.httpclientandroidlib.HttpRequest;
40 import ch.boye.httpclientandroidlib.HttpEntityEnclosingRequest;
41 import ch.boye.httpclientandroidlib.HttpResponse;
42 import ch.boye.httpclientandroidlib.HttpConnectionMetrics;
43 import ch.boye.httpclientandroidlib.conn.OperatedClientConnection;
44 import ch.boye.httpclientandroidlib.conn.ManagedClientConnection;
45 import ch.boye.httpclientandroidlib.conn.ClientConnectionManager;
46 import ch.boye.httpclientandroidlib.protocol.HttpContext;
47
48 /**
49 * Abstract adapter from {@link OperatedClientConnection operated} to
50 * {@link ManagedClientConnection managed} client connections.
51 * Read and write methods are delegated to the wrapped connection.
52 * Operations affecting the connection state have to be implemented
53 * by derived classes. Operations for querying the connection state
54 * are delegated to the wrapped connection if there is one, or
55 * return a default value if there is none.
56 * <p>
57 * This adapter tracks the checkpoints for reusable communication states,
58 * as indicated by {@link #markReusable markReusable} and queried by
59 * {@link #isMarkedReusable isMarkedReusable}.
60 * All send and receive operations will automatically clear the mark.
61 * <p>
62 * Connection release calls are delegated to the connection manager,
63 * if there is one. {@link #abortConnection abortConnection} will
64 * clear the reusability mark first. The connection manager is
65 * expected to tolerate multiple calls to the release method.
66 *
67 * @since 4.0
68 */
69 public abstract class AbstractClientConnAdapter
70 implements ManagedClientConnection, HttpContext {
71
72 /**
73 * The connection manager, if any.
74 * This attribute MUST NOT be final, so the adapter can be detached
75 * from the connection manager without keeping a hard reference there.
76 */
77 private volatile ClientConnectionManager connManager;
78
79 /** The wrapped connection. */
80 private volatile OperatedClientConnection wrappedConnection;
81
82 /** The reusability marker. */
83 private volatile boolean markedReusable;
84
85 /** True if the connection has been shut down or released. */
86 private volatile boolean released;
87
88 /** The duration this is valid for while idle (in ms). */
89 private volatile long duration;
90
91 /**
92 * Creates a new connection adapter.
93 * The adapter is initially <i>not</i>
94 * {@link #isMarkedReusable marked} as reusable.
95 *
96 * @param mgr the connection manager, or <code>null</code>
97 * @param conn the connection to wrap, or <code>null</code>
98 */
99 protected AbstractClientConnAdapter(ClientConnectionManager mgr,
100 OperatedClientConnection conn) {
101 super();
102 connManager = mgr;
103 wrappedConnection = conn;
104 markedReusable = false;
105 released = false;
106 duration = Long.MAX_VALUE;
107 }
108
109 /**
110 * Detaches this adapter from the wrapped connection.
111 * This adapter becomes useless.
112 */
113 protected synchronized void detach() {
114 wrappedConnection = null;
115 connManager = null; // base class attribute
116 duration = Long.MAX_VALUE;
117 }
118
119 protected OperatedClientConnection getWrappedConnection() {
120 return wrappedConnection;
121 }
122
123 protected ClientConnectionManager getManager() {
124 return connManager;
125 }
126
127 /**
128 * @deprecated use {@link #assertValid(OperatedClientConnection)}
129 */
130 @Deprecated
131 protected final void assertNotAborted() throws InterruptedIOException {
132 if (isReleased()) {
133 throw new InterruptedIOException("Connection has been shut down");
134 }
135 }
136
137 /**
138 * @since 4.1
139 * @return value of released flag
140 */
141 protected boolean isReleased() {
142 return released;
143 }
144
145 /**
146 * Asserts that there is a valid wrapped connection to delegate to.
147 *
148 * @throws ConnectionShutdownException if there is no wrapped connection
149 * or connection has been aborted
150 */
151 protected final void assertValid(
152 final OperatedClientConnection wrappedConn) throws ConnectionShutdownException {
153 if (isReleased() || wrappedConn == null) {
154 throw new ConnectionShutdownException();
155 }
156 }
157
158 public boolean isOpen() {
159 OperatedClientConnection conn = getWrappedConnection();
160 if (conn == null)
161 return false;
162
163 return conn.isOpen();
164 }
165
166 public boolean isStale() {
167 if (isReleased())
168 return true;
169 OperatedClientConnection conn = getWrappedConnection();
170 if (conn == null)
171 return true;
172
173 return conn.isStale();
174 }
175
176 public void setSocketTimeout(int timeout) {
177 OperatedClientConnection conn = getWrappedConnection();
178 assertValid(conn);
179 conn.setSocketTimeout(timeout);
180 }
181
182 public int getSocketTimeout() {
183 OperatedClientConnection conn = getWrappedConnection();
184 assertValid(conn);
185 return conn.getSocketTimeout();
186 }
187
188 public HttpConnectionMetrics getMetrics() {
189 OperatedClientConnection conn = getWrappedConnection();
190 assertValid(conn);
191 return conn.getMetrics();
192 }
193
194 public void flush() throws IOException {
195 OperatedClientConnection conn = getWrappedConnection();
196 assertValid(conn);
197 conn.flush();
198 }
199
200 public boolean isResponseAvailable(int timeout) throws IOException {
201 OperatedClientConnection conn = getWrappedConnection();
202 assertValid(conn);
203 return conn.isResponseAvailable(timeout);
204 }
205
206 public void receiveResponseEntity(HttpResponse response)
207 throws HttpException, IOException {
208 OperatedClientConnection conn = getWrappedConnection();
209 assertValid(conn);
210 unmarkReusable();
211 conn.receiveResponseEntity(response);
212 }
213
214 public HttpResponse receiveResponseHeader()
215 throws HttpException, IOException {
216 OperatedClientConnection conn = getWrappedConnection();
217 assertValid(conn);
218 unmarkReusable();
219 return conn.receiveResponseHeader();
220 }
221
222 public void sendRequestEntity(HttpEntityEnclosingRequest request)
223 throws HttpException, IOException {
224 OperatedClientConnection conn = getWrappedConnection();
225 assertValid(conn);
226 unmarkReusable();
227 conn.sendRequestEntity(request);
228 }
229
230 public void sendRequestHeader(HttpRequest request)
231 throws HttpException, IOException {
232 OperatedClientConnection conn = getWrappedConnection();
233 assertValid(conn);
234 unmarkReusable();
235 conn.sendRequestHeader(request);
236 }
237
238 public InetAddress getLocalAddress() {
239 OperatedClientConnection conn = getWrappedConnection();
240 assertValid(conn);
241 return conn.getLocalAddress();
242 }
243
244 public int getLocalPort() {
245 OperatedClientConnection conn = getWrappedConnection();
246 assertValid(conn);
247 return conn.getLocalPort();
248 }
249
250 public InetAddress getRemoteAddress() {
251 OperatedClientConnection conn = getWrappedConnection();
252 assertValid(conn);
253 return conn.getRemoteAddress();
254 }
255
256 public int getRemotePort() {
257 OperatedClientConnection conn = getWrappedConnection();
258 assertValid(conn);
259 return conn.getRemotePort();
260 }
261
262 public boolean isSecure() {
263 OperatedClientConnection conn = getWrappedConnection();
264 assertValid(conn);
265 return conn.isSecure();
266 }
267
268 public SSLSession getSSLSession() {
269 OperatedClientConnection conn = getWrappedConnection();
270 assertValid(conn);
271 if (!isOpen())
272 return null;
273
274 SSLSession result = null;
275 Socket sock = conn.getSocket();
276 if (sock instanceof SSLSocket) {
277 result = ((SSLSocket)sock).getSession();
278 }
279 return result;
280 }
281
282 public void markReusable() {
283 markedReusable = true;
284 }
285
286 public void unmarkReusable() {
287 markedReusable = false;
288 }
289
290 public boolean isMarkedReusable() {
291 return markedReusable;
292 }
293
294 public void setIdleDuration(long duration, TimeUnit unit) {
295 if(duration > 0) {
296 this.duration = unit.toMillis(duration);
297 } else {
298 this.duration = -1;
299 }
300 }
301
302 public synchronized void releaseConnection() {
303 if (released) {
304 return;
305 }
306 released = true;
307 if (connManager != null) {
308 connManager.releaseConnection(this, duration, TimeUnit.MILLISECONDS);
309 }
310 }
311
312 public synchronized void abortConnection() {
313 if (released) {
314 return;
315 }
316 released = true;
317 unmarkReusable();
318 try {
319 shutdown();
320 } catch (IOException ignore) {
321 }
322 if (connManager != null) {
323 connManager.releaseConnection(this, duration, TimeUnit.MILLISECONDS);
324 }
325 }
326
327 public synchronized Object getAttribute(final String id) {
328 OperatedClientConnection conn = getWrappedConnection();
329 assertValid(conn);
330 if (conn instanceof HttpContext) {
331 return ((HttpContext) conn).getAttribute(id);
332 } else {
333 return null;
334 }
335 }
336
337 public synchronized Object removeAttribute(final String id) {
338 OperatedClientConnection conn = getWrappedConnection();
339 assertValid(conn);
340 if (conn instanceof HttpContext) {
341 return ((HttpContext) conn).removeAttribute(id);
342 } else {
343 return null;
344 }
345 }
346
347 public synchronized void setAttribute(final String id, final Object obj) {
348 OperatedClientConnection conn = getWrappedConnection();
349 assertValid(conn);
350 if (conn instanceof HttpContext) {
351 ((HttpContext) conn).setAttribute(id, obj);
352 }
353 }
354
355 }

mercurial