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  package org.apache.http.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.SSLSession;
36  import javax.net.ssl.SSLSocket;
37  
38  import org.apache.http.HttpConnectionMetrics;
39  import org.apache.http.HttpEntityEnclosingRequest;
40  import org.apache.http.HttpException;
41  import org.apache.http.HttpRequest;
42  import org.apache.http.HttpResponse;
43  import org.apache.http.annotation.NotThreadSafe;
44  import org.apache.http.conn.ClientConnectionManager;
45  import org.apache.http.conn.ManagedClientConnection;
46  import org.apache.http.conn.OperatedClientConnection;
47  import org.apache.http.protocol.HttpContext;
48  
49  /**
50   * Abstract adapter from {@link OperatedClientConnection operated} to
51   * {@link ManagedClientConnection managed} client connections.
52   * Read and write methods are delegated to the wrapped connection.
53   * Operations affecting the connection state have to be implemented
54   * by derived classes. Operations for querying the connection state
55   * are delegated to the wrapped connection if there is one, or
56   * return a default value if there is none.
57   * <p>
58   * This adapter tracks the checkpoints for reusable communication states,
59   * as indicated by {@link #markReusable markReusable} and queried by
60   * {@link #isMarkedReusable isMarkedReusable}.
61   * All send and receive operations will automatically clear the mark.
62   * <p>
63   * Connection release calls are delegated to the connection manager,
64   * if there is one. {@link #abortConnection abortConnection} will
65   * clear the reusability mark first. The connection manager is
66   * expected to tolerate multiple calls to the release method.
67   *
68   * @since 4.0
69   *
70   * @deprecated (4.2)  do not use
71   */
72  @Deprecated
73  @NotThreadSafe
74  public abstract class AbstractClientConnAdapter implements ManagedClientConnection, HttpContext {
75  
76      /**
77       * The connection manager.
78       */
79      private final ClientConnectionManager connManager;
80  
81      /** The wrapped connection. */
82      private volatile OperatedClientConnection wrappedConnection;
83  
84      /** The reusability marker. */
85      private volatile boolean markedReusable;
86  
87      /** True if the connection has been shut down or released. */
88      private volatile boolean released;
89  
90      /** The duration this is valid for while idle (in ms). */
91      private volatile long duration;
92  
93      /**
94       * Creates a new connection adapter.
95       * The adapter is initially <i>not</i>
96       * {@link #isMarkedReusable marked} as reusable.
97       *
98       * @param mgr       the connection manager, or {@code null}
99       * @param conn      the connection to wrap, or {@code null}
100      */
101     protected AbstractClientConnAdapter(final ClientConnectionManager mgr,
102                                         final OperatedClientConnection conn) {
103         super();
104         connManager = mgr;
105         wrappedConnection = conn;
106         markedReusable = false;
107         released = false;
108         duration = Long.MAX_VALUE;
109     }
110 
111     /**
112      * Detaches this adapter from the wrapped connection.
113      * This adapter becomes useless.
114      */
115     protected synchronized void detach() {
116         wrappedConnection = null;
117         duration = Long.MAX_VALUE;
118     }
119 
120     protected OperatedClientConnection getWrappedConnection() {
121         return wrappedConnection;
122     }
123 
124     protected ClientConnectionManager getManager() {
125         return connManager;
126     }
127 
128     /**
129      * @deprecated (4.1)  use {@link #assertValid(OperatedClientConnection)}
130      */
131     @Deprecated
132     protected final void assertNotAborted() throws InterruptedIOException {
133         if (isReleased()) {
134             throw new InterruptedIOException("Connection has been shut down");
135         }
136     }
137 
138     /**
139      * @since 4.1
140      * @return value of released flag
141      */
142     protected boolean isReleased() {
143         return released;
144     }
145 
146     /**
147      * Asserts that there is a valid wrapped connection to delegate to.
148      *
149      * @throws ConnectionShutdownException if there is no wrapped connection
150      *                                  or connection has been aborted
151      */
152     protected final void assertValid(
153             final OperatedClientConnection wrappedConn) throws ConnectionShutdownException {
154         if (isReleased() || wrappedConn == null) {
155             throw new ConnectionShutdownException();
156         }
157     }
158 
159     public boolean isOpen() {
160         final OperatedClientConnection conn = getWrappedConnection();
161         if (conn == null) {
162             return false;
163         }
164 
165         return conn.isOpen();
166     }
167 
168     public boolean isStale() {
169         if (isReleased()) {
170             return true;
171         }
172         final OperatedClientConnection conn = getWrappedConnection();
173         if (conn == null) {
174             return true;
175         }
176 
177         return conn.isStale();
178     }
179 
180     public void setSocketTimeout(final int timeout) {
181         final OperatedClientConnection conn = getWrappedConnection();
182         assertValid(conn);
183         conn.setSocketTimeout(timeout);
184     }
185 
186     public int getSocketTimeout() {
187         final OperatedClientConnection conn = getWrappedConnection();
188         assertValid(conn);
189         return conn.getSocketTimeout();
190     }
191 
192     public HttpConnectionMetrics getMetrics() {
193         final OperatedClientConnection conn = getWrappedConnection();
194         assertValid(conn);
195         return conn.getMetrics();
196     }
197 
198     public void flush() throws IOException {
199         final OperatedClientConnection conn = getWrappedConnection();
200         assertValid(conn);
201         conn.flush();
202     }
203 
204     public boolean isResponseAvailable(final int timeout) throws IOException {
205         final OperatedClientConnection conn = getWrappedConnection();
206         assertValid(conn);
207         return conn.isResponseAvailable(timeout);
208     }
209 
210     public void receiveResponseEntity(final HttpResponse response)
211         throws HttpException, IOException {
212         final OperatedClientConnection conn = getWrappedConnection();
213         assertValid(conn);
214         unmarkReusable();
215         conn.receiveResponseEntity(response);
216     }
217 
218     public HttpResponse receiveResponseHeader()
219         throws HttpException, IOException {
220         final OperatedClientConnection conn = getWrappedConnection();
221         assertValid(conn);
222         unmarkReusable();
223         return conn.receiveResponseHeader();
224     }
225 
226     public void sendRequestEntity(final HttpEntityEnclosingRequest request)
227         throws HttpException, IOException {
228         final OperatedClientConnection conn = getWrappedConnection();
229         assertValid(conn);
230         unmarkReusable();
231         conn.sendRequestEntity(request);
232     }
233 
234     public void sendRequestHeader(final HttpRequest request)
235         throws HttpException, IOException {
236         final OperatedClientConnection conn = getWrappedConnection();
237         assertValid(conn);
238         unmarkReusable();
239         conn.sendRequestHeader(request);
240     }
241 
242     public InetAddress getLocalAddress() {
243         final OperatedClientConnection conn = getWrappedConnection();
244         assertValid(conn);
245         return conn.getLocalAddress();
246     }
247 
248     public int getLocalPort() {
249         final OperatedClientConnection conn = getWrappedConnection();
250         assertValid(conn);
251         return conn.getLocalPort();
252     }
253 
254     public InetAddress getRemoteAddress() {
255         final OperatedClientConnection conn = getWrappedConnection();
256         assertValid(conn);
257         return conn.getRemoteAddress();
258     }
259 
260     public int getRemotePort() {
261         final OperatedClientConnection conn = getWrappedConnection();
262         assertValid(conn);
263         return conn.getRemotePort();
264     }
265 
266     public boolean isSecure() {
267         final OperatedClientConnection conn = getWrappedConnection();
268         assertValid(conn);
269         return conn.isSecure();
270     }
271 
272     public void bind(final Socket socket) throws IOException {
273         throw new UnsupportedOperationException();
274     }
275 
276     public Socket getSocket() {
277         final OperatedClientConnection conn = getWrappedConnection();
278         assertValid(conn);
279         if (!isOpen()) {
280             return null;
281         }
282         return conn.getSocket();
283     }
284 
285     public SSLSession getSSLSession() {
286         final OperatedClientConnection conn = getWrappedConnection();
287         assertValid(conn);
288         if (!isOpen()) {
289             return null;
290         }
291 
292         SSLSession result = null;
293         final Socket    sock    = conn.getSocket();
294         if (sock instanceof SSLSocket) {
295             result = ((SSLSocket)sock).getSession();
296         }
297         return result;
298     }
299 
300     public void markReusable() {
301         markedReusable = true;
302     }
303 
304     public void unmarkReusable() {
305         markedReusable = false;
306     }
307 
308     public boolean isMarkedReusable() {
309         return markedReusable;
310     }
311 
312     public void setIdleDuration(final long duration, final TimeUnit unit) {
313         if(duration > 0) {
314             this.duration = unit.toMillis(duration);
315         } else {
316             this.duration = -1;
317         }
318     }
319 
320     public synchronized void releaseConnection() {
321         if (released) {
322             return;
323         }
324         released = true;
325         connManager.releaseConnection(this, duration, TimeUnit.MILLISECONDS);
326     }
327 
328     public synchronized void abortConnection() {
329         if (released) {
330             return;
331         }
332         released = true;
333         unmarkReusable();
334         try {
335             shutdown();
336         } catch (final IOException ignore) {
337         }
338         connManager.releaseConnection(this, duration, TimeUnit.MILLISECONDS);
339     }
340 
341     public Object getAttribute(final String id) {
342         final OperatedClientConnection conn = getWrappedConnection();
343         assertValid(conn);
344         if (conn instanceof HttpContext) {
345             return ((HttpContext) conn).getAttribute(id);
346         } else {
347             return null;
348         }
349     }
350 
351     public Object removeAttribute(final String id) {
352         final OperatedClientConnection conn = getWrappedConnection();
353         assertValid(conn);
354         if (conn instanceof HttpContext) {
355             return ((HttpContext) conn).removeAttribute(id);
356         } else {
357             return null;
358         }
359     }
360 
361     public void setAttribute(final String id, final Object obj) {
362         final OperatedClientConnection conn = getWrappedConnection();
363         assertValid(conn);
364         if (conn instanceof HttpContext) {
365             ((HttpContext) conn).setAttribute(id, obj);
366         }
367     }
368 
369 }