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     @Override
160     public boolean isOpen() {
161         final OperatedClientConnection conn = getWrappedConnection();
162         if (conn == null) {
163             return false;
164         }
165 
166         return conn.isOpen();
167     }
168 
169     @Override
170     public boolean isStale() {
171         if (isReleased()) {
172             return true;
173         }
174         final OperatedClientConnection conn = getWrappedConnection();
175         if (conn == null) {
176             return true;
177         }
178 
179         return conn.isStale();
180     }
181 
182     @Override
183     public void setSocketTimeout(final int timeout) {
184         final OperatedClientConnection conn = getWrappedConnection();
185         assertValid(conn);
186         conn.setSocketTimeout(timeout);
187     }
188 
189     @Override
190     public int getSocketTimeout() {
191         final OperatedClientConnection conn = getWrappedConnection();
192         assertValid(conn);
193         return conn.getSocketTimeout();
194     }
195 
196     @Override
197     public HttpConnectionMetrics getMetrics() {
198         final OperatedClientConnection conn = getWrappedConnection();
199         assertValid(conn);
200         return conn.getMetrics();
201     }
202 
203     @Override
204     public void flush() throws IOException {
205         final OperatedClientConnection conn = getWrappedConnection();
206         assertValid(conn);
207         conn.flush();
208     }
209 
210     @Override
211     public boolean isResponseAvailable(final int timeout) throws IOException {
212         final OperatedClientConnection conn = getWrappedConnection();
213         assertValid(conn);
214         return conn.isResponseAvailable(timeout);
215     }
216 
217     @Override
218     public void receiveResponseEntity(final HttpResponse response)
219         throws HttpException, IOException {
220         final OperatedClientConnection conn = getWrappedConnection();
221         assertValid(conn);
222         unmarkReusable();
223         conn.receiveResponseEntity(response);
224     }
225 
226     @Override
227     public HttpResponse receiveResponseHeader()
228         throws HttpException, IOException {
229         final OperatedClientConnection conn = getWrappedConnection();
230         assertValid(conn);
231         unmarkReusable();
232         return conn.receiveResponseHeader();
233     }
234 
235     @Override
236     public void sendRequestEntity(final HttpEntityEnclosingRequest request)
237         throws HttpException, IOException {
238         final OperatedClientConnection conn = getWrappedConnection();
239         assertValid(conn);
240         unmarkReusable();
241         conn.sendRequestEntity(request);
242     }
243 
244     @Override
245     public void sendRequestHeader(final HttpRequest request)
246         throws HttpException, IOException {
247         final OperatedClientConnection conn = getWrappedConnection();
248         assertValid(conn);
249         unmarkReusable();
250         conn.sendRequestHeader(request);
251     }
252 
253     @Override
254     public InetAddress getLocalAddress() {
255         final OperatedClientConnection conn = getWrappedConnection();
256         assertValid(conn);
257         return conn.getLocalAddress();
258     }
259 
260     @Override
261     public int getLocalPort() {
262         final OperatedClientConnection conn = getWrappedConnection();
263         assertValid(conn);
264         return conn.getLocalPort();
265     }
266 
267     @Override
268     public InetAddress getRemoteAddress() {
269         final OperatedClientConnection conn = getWrappedConnection();
270         assertValid(conn);
271         return conn.getRemoteAddress();
272     }
273 
274     @Override
275     public int getRemotePort() {
276         final OperatedClientConnection conn = getWrappedConnection();
277         assertValid(conn);
278         return conn.getRemotePort();
279     }
280 
281     @Override
282     public boolean isSecure() {
283         final OperatedClientConnection conn = getWrappedConnection();
284         assertValid(conn);
285         return conn.isSecure();
286     }
287 
288     @Override
289     public void bind(final Socket socket) throws IOException {
290         throw new UnsupportedOperationException();
291     }
292 
293     @Override
294     public Socket getSocket() {
295         final OperatedClientConnection conn = getWrappedConnection();
296         assertValid(conn);
297         if (!isOpen()) {
298             return null;
299         }
300         return conn.getSocket();
301     }
302 
303     @Override
304     public SSLSession getSSLSession() {
305         final OperatedClientConnection conn = getWrappedConnection();
306         assertValid(conn);
307         if (!isOpen()) {
308             return null;
309         }
310 
311         SSLSession result = null;
312         final Socket    sock    = conn.getSocket();
313         if (sock instanceof SSLSocket) {
314             result = ((SSLSocket)sock).getSession();
315         }
316         return result;
317     }
318 
319     @Override
320     public void markReusable() {
321         markedReusable = true;
322     }
323 
324     @Override
325     public void unmarkReusable() {
326         markedReusable = false;
327     }
328 
329     @Override
330     public boolean isMarkedReusable() {
331         return markedReusable;
332     }
333 
334     @Override
335     public void setIdleDuration(final long duration, final TimeUnit unit) {
336         if(duration > 0) {
337             this.duration = unit.toMillis(duration);
338         } else {
339             this.duration = -1;
340         }
341     }
342 
343     @Override
344     public synchronized void releaseConnection() {
345         if (released) {
346             return;
347         }
348         released = true;
349         connManager.releaseConnection(this, duration, TimeUnit.MILLISECONDS);
350     }
351 
352     @Override
353     public synchronized void abortConnection() {
354         if (released) {
355             return;
356         }
357         released = true;
358         unmarkReusable();
359         try {
360             shutdown();
361         } catch (final IOException ignore) {
362         }
363         connManager.releaseConnection(this, duration, TimeUnit.MILLISECONDS);
364     }
365 
366     @Override
367     public Object getAttribute(final String id) {
368         final OperatedClientConnection conn = getWrappedConnection();
369         assertValid(conn);
370         if (conn instanceof HttpContext) {
371             return ((HttpContext) conn).getAttribute(id);
372         } else {
373             return null;
374         }
375     }
376 
377     @Override
378     public Object removeAttribute(final String id) {
379         final OperatedClientConnection conn = getWrappedConnection();
380         assertValid(conn);
381         if (conn instanceof HttpContext) {
382             return ((HttpContext) conn).removeAttribute(id);
383         } else {
384             return null;
385         }
386     }
387 
388     @Override
389     public void setAttribute(final String id, final Object obj) {
390         final OperatedClientConnection conn = getWrappedConnection();
391         assertValid(conn);
392         if (conn instanceof HttpContext) {
393             ((HttpContext) conn).setAttribute(id, obj);
394         }
395     }
396 
397 }