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

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

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

mercurial