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.conn.ClientConnectionManager;
44  import org.apache.http.conn.ManagedClientConnection;
45  import org.apache.http.conn.OperatedClientConnection;
46  import org.apache.http.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   * @deprecated (4.2)  do not use
70   */
71  @Deprecated
72  public abstract class AbstractClientConnAdapter implements ManagedClientConnection, HttpContext {
73  
74      /**
75       * The connection manager.
76       */
77      private final 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}
97       * @param conn      the connection to wrap, or {@code null}
98       */
99      protected AbstractClientConnAdapter(final ClientConnectionManager mgr,
100                                         final 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         duration = Long.MAX_VALUE;
116     }
117 
118     protected OperatedClientConnection getWrappedConnection() {
119         return wrappedConnection;
120     }
121 
122     protected ClientConnectionManager getManager() {
123         return connManager;
124     }
125 
126     /**
127      * @deprecated (4.1)  use {@link #assertValid(OperatedClientConnection)}
128      */
129     @Deprecated
130     protected final void assertNotAborted() throws InterruptedIOException {
131         if (isReleased()) {
132             throw new InterruptedIOException("Connection has been shut down");
133         }
134     }
135 
136     /**
137      * @since 4.1
138      * @return value of released flag
139      */
140     protected boolean isReleased() {
141         return released;
142     }
143 
144     /**
145      * Asserts that there is a valid wrapped connection to delegate to.
146      *
147      * @throws ConnectionShutdownException if there is no wrapped connection
148      *                                  or connection has been aborted
149      */
150     protected final void assertValid(
151             final OperatedClientConnection wrappedConn) throws ConnectionShutdownException {
152         if (isReleased() || wrappedConn == null) {
153             throw new ConnectionShutdownException();
154         }
155     }
156 
157     @Override
158     public boolean isOpen() {
159         final OperatedClientConnection conn = getWrappedConnection();
160         if (conn == null) {
161             return false;
162         }
163 
164         return conn.isOpen();
165     }
166 
167     @Override
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     @Override
181     public void setSocketTimeout(final int timeout) {
182         final OperatedClientConnection conn = getWrappedConnection();
183         assertValid(conn);
184         conn.setSocketTimeout(timeout);
185     }
186 
187     @Override
188     public int getSocketTimeout() {
189         final OperatedClientConnection conn = getWrappedConnection();
190         assertValid(conn);
191         return conn.getSocketTimeout();
192     }
193 
194     @Override
195     public HttpConnectionMetrics getMetrics() {
196         final OperatedClientConnection conn = getWrappedConnection();
197         assertValid(conn);
198         return conn.getMetrics();
199     }
200 
201     @Override
202     public void flush() throws IOException {
203         final OperatedClientConnection conn = getWrappedConnection();
204         assertValid(conn);
205         conn.flush();
206     }
207 
208     @Override
209     public boolean isResponseAvailable(final int timeout) throws IOException {
210         final OperatedClientConnection conn = getWrappedConnection();
211         assertValid(conn);
212         return conn.isResponseAvailable(timeout);
213     }
214 
215     @Override
216     public void receiveResponseEntity(final HttpResponse response)
217         throws HttpException, IOException {
218         final OperatedClientConnection conn = getWrappedConnection();
219         assertValid(conn);
220         unmarkReusable();
221         conn.receiveResponseEntity(response);
222     }
223 
224     @Override
225     public HttpResponse receiveResponseHeader()
226         throws HttpException, IOException {
227         final OperatedClientConnection conn = getWrappedConnection();
228         assertValid(conn);
229         unmarkReusable();
230         return conn.receiveResponseHeader();
231     }
232 
233     @Override
234     public void sendRequestEntity(final HttpEntityEnclosingRequest request)
235         throws HttpException, IOException {
236         final OperatedClientConnection conn = getWrappedConnection();
237         assertValid(conn);
238         unmarkReusable();
239         conn.sendRequestEntity(request);
240     }
241 
242     @Override
243     public void sendRequestHeader(final HttpRequest request)
244         throws HttpException, IOException {
245         final OperatedClientConnection conn = getWrappedConnection();
246         assertValid(conn);
247         unmarkReusable();
248         conn.sendRequestHeader(request);
249     }
250 
251     @Override
252     public InetAddress getLocalAddress() {
253         final OperatedClientConnection conn = getWrappedConnection();
254         assertValid(conn);
255         return conn.getLocalAddress();
256     }
257 
258     @Override
259     public int getLocalPort() {
260         final OperatedClientConnection conn = getWrappedConnection();
261         assertValid(conn);
262         return conn.getLocalPort();
263     }
264 
265     @Override
266     public InetAddress getRemoteAddress() {
267         final OperatedClientConnection conn = getWrappedConnection();
268         assertValid(conn);
269         return conn.getRemoteAddress();
270     }
271 
272     @Override
273     public int getRemotePort() {
274         final OperatedClientConnection conn = getWrappedConnection();
275         assertValid(conn);
276         return conn.getRemotePort();
277     }
278 
279     @Override
280     public boolean isSecure() {
281         final OperatedClientConnection conn = getWrappedConnection();
282         assertValid(conn);
283         return conn.isSecure();
284     }
285 
286     @Override
287     public void bind(final Socket socket) throws IOException {
288         throw new UnsupportedOperationException();
289     }
290 
291     @Override
292     public Socket getSocket() {
293         final OperatedClientConnection conn = getWrappedConnection();
294         assertValid(conn);
295         if (!isOpen()) {
296             return null;
297         }
298         return conn.getSocket();
299     }
300 
301     @Override
302     public SSLSession getSSLSession() {
303         final OperatedClientConnection conn = getWrappedConnection();
304         assertValid(conn);
305         if (!isOpen()) {
306             return null;
307         }
308 
309         SSLSession result = null;
310         final Socket    sock    = conn.getSocket();
311         if (sock instanceof SSLSocket) {
312             result = ((SSLSocket)sock).getSession();
313         }
314         return result;
315     }
316 
317     @Override
318     public void markReusable() {
319         markedReusable = true;
320     }
321 
322     @Override
323     public void unmarkReusable() {
324         markedReusable = false;
325     }
326 
327     @Override
328     public boolean isMarkedReusable() {
329         return markedReusable;
330     }
331 
332     @Override
333     public void setIdleDuration(final long duration, final TimeUnit unit) {
334         if(duration > 0) {
335             this.duration = unit.toMillis(duration);
336         } else {
337             this.duration = -1;
338         }
339     }
340 
341     @Override
342     public synchronized void releaseConnection() {
343         if (released) {
344             return;
345         }
346         released = true;
347         connManager.releaseConnection(this, duration, TimeUnit.MILLISECONDS);
348     }
349 
350     @Override
351     public synchronized void abortConnection() {
352         if (released) {
353             return;
354         }
355         released = true;
356         unmarkReusable();
357         try {
358             shutdown();
359         } catch (final IOException ignore) {
360         }
361         connManager.releaseConnection(this, duration, TimeUnit.MILLISECONDS);
362     }
363 
364     @Override
365     public Object getAttribute(final String id) {
366         final OperatedClientConnection conn = getWrappedConnection();
367         assertValid(conn);
368         if (conn instanceof HttpContext) {
369             return ((HttpContext) conn).getAttribute(id);
370         } else {
371             return null;
372         }
373     }
374 
375     @Override
376     public Object removeAttribute(final String id) {
377         final OperatedClientConnection conn = getWrappedConnection();
378         assertValid(conn);
379         if (conn instanceof HttpContext) {
380             return ((HttpContext) conn).removeAttribute(id);
381         } else {
382             return null;
383         }
384     }
385 
386     @Override
387     public void setAttribute(final String id, final Object obj) {
388         final OperatedClientConnection conn = getWrappedConnection();
389         assertValid(conn);
390         if (conn instanceof HttpContext) {
391             ((HttpContext) conn).setAttribute(id, obj);
392         }
393     }
394 
395 }