/lib/src/org/apache/http/impl/conn/AbstractPoolEntry.java
Java | 294 lines | 123 code | 41 blank | 130 comment | 35 complexity | 16ad0b24ec8d03b0dc0b9d8095ef2470 MD5 | raw file
Possible License(s): GPL-3.0
1/* 2 * ==================================================================== 3 * 4 * Licensed to the Apache Software Foundation (ASF) under one or more 5 * contributor license agreements. See the NOTICE file distributed with 6 * this work for additional information regarding copyright ownership. 7 * The ASF licenses this file to You under the Apache License, Version 2.0 8 * (the "License"); you may not use this file except in compliance with 9 * 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, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * ==================================================================== 19 * 20 * This software consists of voluntary contributions made by many 21 * individuals on behalf of the Apache Software Foundation. For more 22 * information on the Apache Software Foundation, please see 23 * <http://www.apache.org/>. 24 * 25 */ 26 27package org.apache.http.impl.conn; 28 29import java.io.IOException; 30 31import org.apache.http.HttpHost; 32import org.apache.http.params.HttpParams; 33import org.apache.http.protocol.HttpContext; 34import org.apache.http.conn.routing.HttpRoute; 35import org.apache.http.conn.routing.RouteTracker; 36import org.apache.http.conn.ClientConnectionOperator; 37import org.apache.http.conn.OperatedClientConnection; 38 39/** 40 * A pool entry for use by connection manager implementations. 41 * Pool entries work in conjunction with an 42 * {@link AbstractClientConnAdapter adapter}. 43 * The adapter is handed out to applications that obtain a connection. 44 * The pool entry stores the underlying connection and tracks the 45 * {@link HttpRoute route} established. 46 * The adapter delegates methods for establishing the route to 47 * its pool entry. 48 * <p> 49 * If the managed connections is released or revoked, the adapter 50 * gets disconnected, but the pool entry still contains the 51 * underlying connection and the established route. 52 * 53 * @since 4.0 54 */ 55public abstract class AbstractPoolEntry { 56 57 /** The connection operator. */ 58 protected final ClientConnectionOperator connOperator; 59 60 /** The underlying connection being pooled or used. */ 61 protected final OperatedClientConnection connection; 62 63 /** The route for which this entry gets allocated. */ 64 //@@@ currently accessed from connection manager(s) as attribute 65 //@@@ avoid that, derived classes should decide whether update is allowed 66 //@@@ SCCM: yes, TSCCM: no 67 protected volatile HttpRoute route; 68 69 /** Connection state object */ 70 protected volatile Object state; 71 72 /** The tracked route, or <code>null</code> before tracking starts. */ 73 protected volatile RouteTracker tracker; 74 75 76 /** 77 * Creates a new pool entry. 78 * 79 * @param connOperator the Connection Operator for this entry 80 * @param route the planned route for the connection, 81 * or <code>null</code> 82 */ 83 protected AbstractPoolEntry(ClientConnectionOperator connOperator, 84 HttpRoute route) { 85 super(); 86 if (connOperator == null) { 87 throw new IllegalArgumentException("Connection operator may not be null"); 88 } 89 this.connOperator = connOperator; 90 this.connection = connOperator.createConnection(); 91 this.route = route; 92 this.tracker = null; 93 } 94 95 /** 96 * Returns the state object associated with this pool entry. 97 * 98 * @return The state object 99 */ 100 public Object getState() { 101 return state; 102 } 103 104 /** 105 * Assigns a state object to this pool entry. 106 * 107 * @param state The state object 108 */ 109 public void setState(final Object state) { 110 this.state = state; 111 } 112 113 /** 114 * Opens the underlying connection. 115 * 116 * @param route the route along which to open the connection 117 * @param context the context for opening the connection 118 * @param params the parameters for opening the connection 119 * 120 * @throws IOException in case of a problem 121 */ 122 public void open(HttpRoute route, 123 HttpContext context, HttpParams params) 124 throws IOException { 125 126 if (route == null) { 127 throw new IllegalArgumentException 128 ("Route must not be null."); 129 } 130 if (params == null) { 131 throw new IllegalArgumentException 132 ("Parameters must not be null."); 133 } 134 if ((this.tracker != null) && this.tracker.isConnected()) { 135 throw new IllegalStateException("Connection already open."); 136 } 137 138 // - collect the arguments 139 // - call the operator 140 // - update the tracking data 141 // In this order, we can be sure that only a successful 142 // opening of the connection will be tracked. 143 144 this.tracker = new RouteTracker(route); 145 final HttpHost proxy = route.getProxyHost(); 146 147 connOperator.openConnection 148 (this.connection, 149 (proxy != null) ? proxy : route.getTargetHost(), 150 route.getLocalAddress(), 151 context, params); 152 153 RouteTracker localTracker = tracker; // capture volatile 154 155 // If this tracker was reset while connecting, 156 // fail early. 157 if (localTracker == null) { 158 throw new IOException("Request aborted"); 159 } 160 161 if (proxy == null) { 162 localTracker.connectTarget(this.connection.isSecure()); 163 } else { 164 localTracker.connectProxy(proxy, this.connection.isSecure()); 165 } 166 167 } 168 169 /** 170 * Tracks tunnelling of the connection to the target. 171 * The tunnel has to be established outside by sending a CONNECT 172 * request to the (last) proxy. 173 * 174 * @param secure <code>true</code> if the tunnel should be 175 * considered secure, <code>false</code> otherwise 176 * @param params the parameters for tunnelling the connection 177 * 178 * @throws IOException in case of a problem 179 */ 180 public void tunnelTarget(boolean secure, HttpParams params) 181 throws IOException { 182 183 if (params == null) { 184 throw new IllegalArgumentException 185 ("Parameters must not be null."); 186 } 187 188 if ((this.tracker == null) || !this.tracker.isConnected()) { 189 throw new IllegalStateException("Connection not open."); 190 } 191 if (this.tracker.isTunnelled()) { 192 throw new IllegalStateException 193 ("Connection is already tunnelled."); 194 } 195 196 this.connection.update(null, tracker.getTargetHost(), 197 secure, params); 198 this.tracker.tunnelTarget(secure); 199 } 200 201 /** 202 * Tracks tunnelling of the connection to a chained proxy. 203 * The tunnel has to be established outside by sending a CONNECT 204 * request to the previous proxy. 205 * 206 * @param next the proxy to which the tunnel was established. 207 * See {@link org.apache.http.conn.ManagedClientConnection#tunnelProxy 208 * ManagedClientConnection.tunnelProxy} 209 * for details. 210 * @param secure <code>true</code> if the tunnel should be 211 * considered secure, <code>false</code> otherwise 212 * @param params the parameters for tunnelling the connection 213 * 214 * @throws IOException in case of a problem 215 */ 216 public void tunnelProxy(HttpHost next, boolean secure, HttpParams params) 217 throws IOException { 218 219 if (next == null) { 220 throw new IllegalArgumentException 221 ("Next proxy must not be null."); 222 } 223 if (params == null) { 224 throw new IllegalArgumentException 225 ("Parameters must not be null."); 226 } 227 228 //@@@ check for proxy in planned route? 229 if ((this.tracker == null) || !this.tracker.isConnected()) { 230 throw new IllegalStateException("Connection not open."); 231 } 232 233 this.connection.update(null, next, secure, params); 234 this.tracker.tunnelProxy(next, secure); 235 } 236 237 /** 238 * Layers a protocol on top of an established tunnel. 239 * 240 * @param context the context for layering 241 * @param params the parameters for layering 242 * 243 * @throws IOException in case of a problem 244 */ 245 public void layerProtocol(HttpContext context, HttpParams params) 246 throws IOException { 247 248 //@@@ is context allowed to be null? depends on operator? 249 if (params == null) { 250 throw new IllegalArgumentException 251 ("Parameters must not be null."); 252 } 253 254 if ((this.tracker == null) || !this.tracker.isConnected()) { 255 throw new IllegalStateException("Connection not open."); 256 } 257 if (!this.tracker.isTunnelled()) { 258 //@@@ allow this? 259 throw new IllegalStateException 260 ("Protocol layering without a tunnel not supported."); 261 } 262 if (this.tracker.isLayered()) { 263 throw new IllegalStateException 264 ("Multiple protocol layering not supported."); 265 } 266 267 // - collect the arguments 268 // - call the operator 269 // - update the tracking data 270 // In this order, we can be sure that only a successful 271 // layering on top of the connection will be tracked. 272 273 final HttpHost target = tracker.getTargetHost(); 274 275 connOperator.updateSecureConnection(this.connection, target, 276 context, params); 277 278 this.tracker.layerProtocol(this.connection.isSecure()); 279 280 } 281 282 /** 283 * Shuts down the entry. 284 * 285 * If {@link #open(HttpRoute, HttpContext, HttpParams)} is in progress, 286 * this will cause that open to possibly throw an {@link IOException}. 287 */ 288 protected void shutdownEntry() { 289 tracker = null; 290 state = null; 291 } 292 293} 294