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  
32  import org.apache.http.HttpHost;
33  import org.apache.http.conn.ClientConnectionOperator;
34  import org.apache.http.conn.OperatedClientConnection;
35  import org.apache.http.conn.routing.HttpRoute;
36  import org.apache.http.conn.routing.RouteTracker;
37  import org.apache.http.params.HttpParams;
38  import org.apache.http.protocol.HttpContext;
39  import org.apache.http.util.Args;
40  import org.apache.http.util.Asserts;
41  
42  /**
43   * A pool entry for use by connection manager implementations.
44   * Pool entries work in conjunction with an
45   * {@link AbstractClientConnAdapter adapter}.
46   * The adapter is handed out to applications that obtain a connection.
47   * The pool entry stores the underlying connection and tracks the
48   * {@link HttpRoute route} established.
49   * The adapter delegates methods for establishing the route to
50   * its pool entry.
51   * <p>
52   * If the managed connections is released or revoked, the adapter
53   * gets disconnected, but the pool entry still contains the
54   * underlying connection and the established route.
55   *
56   * @since 4.0
57   *
58   * @deprecated (4.2)  do not use
59   */
60  @Deprecated
61  public abstract class AbstractPoolEntry {
62  
63      /** The connection operator. */
64      protected final ClientConnectionOperator connOperator;
65  
66      /** The underlying connection being pooled or used. */
67      protected final OperatedClientConnection connection;
68  
69      /** The route for which this entry gets allocated. */
70      //@@@ currently accessed from connection manager(s) as attribute
71      //@@@ avoid that, derived classes should decide whether update is allowed
72      //@@@ SCCM: yes, TSCCM: no
73      protected volatile HttpRoute route;
74  
75      /** Connection state object */
76      protected volatile Object state;
77  
78      /** The tracked route, or {@code null} before tracking starts. */
79      protected volatile RouteTracker tracker;
80  
81  
82      /**
83       * Creates a new pool entry.
84       *
85       * @param connOperator     the Connection Operator for this entry
86       * @param route   the planned route for the connection,
87       *                or {@code null}
88       */
89      protected AbstractPoolEntry(final ClientConnectionOperator connOperator,
90                                  final HttpRoute route) {
91          super();
92          Args.notNull(connOperator, "Connection operator");
93          this.connOperator = connOperator;
94          this.connection = connOperator.createConnection();
95          this.route = route;
96          this.tracker = null;
97      }
98  
99      /**
100      * Returns the state object associated with this pool entry.
101      *
102      * @return The state object
103      */
104     public Object getState() {
105         return state;
106     }
107 
108     /**
109      * Assigns a state object to this pool entry.
110      *
111      * @param state The state object
112      */
113     public void setState(final Object state) {
114         this.state = state;
115     }
116 
117     /**
118      * Opens the underlying connection.
119      *
120      * @param route         the route along which to open the connection
121      * @param context       the context for opening the connection
122      * @param params        the parameters for opening the connection
123      *
124      * @throws IOException  in case of a problem
125      */
126     public void open(final HttpRoute route,
127                      final HttpContext context, final HttpParams params)
128         throws IOException {
129 
130         Args.notNull(route, "Route");
131         Args.notNull(params, "HTTP parameters");
132         if (this.tracker != null) {
133             Asserts.check(!this.tracker.isConnected(), "Connection already open");
134         }
135         // - collect the arguments
136         // - call the operator
137         // - update the tracking data
138         // In this order, we can be sure that only a successful
139         // opening of the connection will be tracked.
140 
141         this.tracker = new RouteTracker(route);
142         final HttpHost proxy  = route.getProxyHost();
143 
144         connOperator.openConnection
145             (this.connection,
146              (proxy != null) ? proxy : route.getTargetHost(),
147              route.getLocalAddress(),
148              context, params);
149 
150         final RouteTracker localTracker = tracker; // capture volatile
151 
152         // If this tracker was reset while connecting,
153         // fail early.
154         if (localTracker == null) {
155             throw new InterruptedIOException("Request aborted");
156         }
157 
158         if (proxy == null) {
159             localTracker.connectTarget(this.connection.isSecure());
160         } else {
161             localTracker.connectProxy(proxy, this.connection.isSecure());
162         }
163 
164     }
165 
166     /**
167      * Tracks tunnelling of the connection to the target.
168      * The tunnel has to be established outside by sending a CONNECT
169      * request to the (last) proxy.
170      *
171      * @param secure    {@code true} if the tunnel should be
172      *                  considered secure, {@code false} otherwise
173      * @param params    the parameters for tunnelling the connection
174      *
175      * @throws IOException  in case of a problem
176      */
177     public void tunnelTarget(final boolean secure, final HttpParams params)
178         throws IOException {
179 
180         Args.notNull(params, "HTTP parameters");
181         Asserts.notNull(this.tracker, "Route tracker");
182         Asserts.check(this.tracker.isConnected(), "Connection not open");
183         Asserts.check(!this.tracker.isTunnelled(), "Connection is already tunnelled");
184 
185         this.connection.update(null, tracker.getTargetHost(),
186                                secure, params);
187         this.tracker.tunnelTarget(secure);
188     }
189 
190     /**
191      * Tracks tunnelling of the connection to a chained proxy.
192      * The tunnel has to be established outside by sending a CONNECT
193      * request to the previous proxy.
194      *
195      * @param next      the proxy to which the tunnel was established.
196      *  See {@link org.apache.http.conn.ManagedClientConnection#tunnelProxy
197      *                                  ManagedClientConnection.tunnelProxy}
198      *                  for details.
199      * @param secure    {@code true} if the tunnel should be
200      *                  considered secure, {@code false} otherwise
201      * @param params    the parameters for tunnelling the connection
202      *
203      * @throws IOException  in case of a problem
204      */
205     public void tunnelProxy(final HttpHost next, final boolean secure, final HttpParams params)
206         throws IOException {
207 
208         Args.notNull(next, "Next proxy");
209         Args.notNull(params, "Parameters");
210 
211         Asserts.notNull(this.tracker, "Route tracker");
212         Asserts.check(this.tracker.isConnected(), "Connection not open");
213 
214         this.connection.update(null, next, secure, params);
215         this.tracker.tunnelProxy(next, secure);
216     }
217 
218     /**
219      * Layers a protocol on top of an established tunnel.
220      *
221      * @param context   the context for layering
222      * @param params    the parameters for layering
223      *
224      * @throws IOException  in case of a problem
225      */
226     public void layerProtocol(final HttpContext context, final HttpParams params)
227         throws IOException {
228 
229         //@@@ is context allowed to be null? depends on operator?
230         Args.notNull(params, "HTTP parameters");
231         Asserts.notNull(this.tracker, "Route tracker");
232         Asserts.check(this.tracker.isConnected(), "Connection not open");
233         Asserts.check(this.tracker.isTunnelled(), "Protocol layering without a tunnel not supported");
234         Asserts.check(!this.tracker.isLayered(), "Multiple protocol layering not supported");
235         // - collect the arguments
236         // - call the operator
237         // - update the tracking data
238         // In this order, we can be sure that only a successful
239         // layering on top of the connection will be tracked.
240 
241         final HttpHost target = tracker.getTargetHost();
242 
243         connOperator.updateSecureConnection(this.connection, target,
244                                              context, params);
245 
246         this.tracker.layerProtocol(this.connection.isSecure());
247 
248     }
249 
250     /**
251      * Shuts down the entry.
252      *
253      * If {@link #open(HttpRoute, HttpContext, HttpParams)} is in progress,
254      * this will cause that open to possibly throw an {@link IOException}.
255      */
256     protected void shutdownEntry() {
257         tracker = null;
258         state = null;
259     }
260 
261 }
262