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