1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 package org.apache.commons.httpclient;
31
32 import java.io.IOException;
33 import java.io.InputStream;
34
35 import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
36 import org.apache.commons.logging.Log;
37 import org.apache.commons.logging.LogFactory;
38
39 /***
40 * A connection manager that provides access to a single HttpConnection. This
41 * manager makes no attempt to provide exclusive access to the contained
42 * HttpConnection.
43 *
44 * @author <a href="mailto:becke@u.washington.edu">Michael Becke</a>
45 * @author Eric Johnson
46 * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
47 * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
48 * @author Laura Werner
49 *
50 * @since 2.0
51 */
52 public class SimpleHttpConnectionManager implements HttpConnectionManager {
53
54 private static final Log LOG = LogFactory.getLog(SimpleHttpConnectionManager.class);
55
56 private static final String MISUSE_MESSAGE =
57 "SimpleHttpConnectionManager being used incorrectly. Be sure that"
58 + " HttpMethod.releaseConnection() is always called and that only one thread"
59 + " and/or method is using this connection manager at a time.";
60
61 /***
62 * Since the same connection is about to be reused, make sure the
63 * previous request was completely processed, and if not
64 * consume it now.
65 * @param conn The connection
66 */
67 static void finishLastResponse(HttpConnection conn) {
68 InputStream lastResponse = conn.getLastResponseInputStream();
69 if (lastResponse != null) {
70 conn.setLastResponseInputStream(null);
71 try {
72 lastResponse.close();
73 } catch (IOException ioe) {
74 conn.close();
75 }
76 }
77 }
78
79 /*** The http connection */
80 protected HttpConnection httpConnection;
81
82 /***
83 * Collection of parameters associated with this connection manager.
84 */
85 private HttpConnectionManagerParams params = new HttpConnectionManagerParams();
86
87 /***
88 * The time the connection was made idle.
89 */
90 private long idleStartTime = Long.MAX_VALUE;
91
92 /***
93 * Used to test if {@link #httpConnection} is currently in use
94 * (i.e. checked out). This is only used as a sanity check to help
95 * debug cases where this connection manager is being used incorrectly.
96 * It will not be used to enforce thread safety.
97 */
98 private volatile boolean inUse = false;
99
100 private boolean alwaysClose = false;
101
102 /***
103 * The connection manager created with this constructor will try to keep the
104 * connection open (alive) between consecutive requests if the alwaysClose
105 * parameter is set to <tt>false</tt>. Otherwise the connection manager will
106 * always close connections upon release.
107 *
108 * @param alwaysClose if set <tt>true</tt>, the connection manager will always
109 * close connections upon release.
110 */
111 public SimpleHttpConnectionManager(boolean alwaysClose) {
112 super();
113 this.alwaysClose = alwaysClose;
114 }
115
116 /***
117 * The connection manager created with this constructor will always try to keep
118 * the connection open (alive) between consecutive requests.
119 */
120 public SimpleHttpConnectionManager() {
121 super();
122 }
123
124 /***
125 * @see HttpConnectionManager#getConnection(HostConfiguration)
126 */
127 public HttpConnection getConnection(HostConfiguration hostConfiguration) {
128 return getConnection(hostConfiguration, 0);
129 }
130
131 /***
132 * Gets the staleCheckingEnabled value to be set on HttpConnections that are created.
133 *
134 * @return <code>true</code> if stale checking will be enabled on HttpConections
135 *
136 * @see HttpConnection#isStaleCheckingEnabled()
137 *
138 * @deprecated Use {@link HttpConnectionManagerParams#isStaleCheckingEnabled()},
139 * {@link HttpConnectionManager#getParams()}.
140 */
141 public boolean isConnectionStaleCheckingEnabled() {
142 return this.params.isStaleCheckingEnabled();
143 }
144
145 /***
146 * Sets the staleCheckingEnabled value to be set on HttpConnections that are created.
147 *
148 * @param connectionStaleCheckingEnabled <code>true</code> if stale checking will be enabled
149 * on HttpConections
150 *
151 * @see HttpConnection#setStaleCheckingEnabled(boolean)
152 *
153 * @deprecated Use {@link HttpConnectionManagerParams#setStaleCheckingEnabled(boolean)},
154 * {@link HttpConnectionManager#getParams()}.
155 */
156 public void setConnectionStaleCheckingEnabled(boolean connectionStaleCheckingEnabled) {
157 this.params.setStaleCheckingEnabled(connectionStaleCheckingEnabled);
158 }
159
160 /***
161 * This method always returns the same connection object. If the connection is already
162 * open, it will be closed and the new host configuration will be applied.
163 *
164 * @param hostConfiguration The host configuration specifying the connection
165 * details.
166 * @param timeout this parameter has no effect. The connection is always returned
167 * immediately.
168 * @since 3.0
169 */
170 public HttpConnection getConnectionWithTimeout(
171 HostConfiguration hostConfiguration, long timeout) {
172
173 if (httpConnection == null) {
174 httpConnection = new HttpConnection(hostConfiguration);
175 httpConnection.setHttpConnectionManager(this);
176 httpConnection.getParams().setDefaults(this.params);
177 } else {
178
179
180
181 if (!hostConfiguration.hostEquals(httpConnection)
182 || !hostConfiguration.proxyEquals(httpConnection)) {
183
184 if (httpConnection.isOpen()) {
185 httpConnection.close();
186 }
187
188 httpConnection.setHost(hostConfiguration.getHost());
189 httpConnection.setPort(hostConfiguration.getPort());
190 httpConnection.setProtocol(hostConfiguration.getProtocol());
191 httpConnection.setLocalAddress(hostConfiguration.getLocalAddress());
192
193 httpConnection.setProxyHost(hostConfiguration.getProxyHost());
194 httpConnection.setProxyPort(hostConfiguration.getProxyPort());
195 } else {
196 finishLastResponse(httpConnection);
197 }
198 }
199
200
201 idleStartTime = Long.MAX_VALUE;
202
203 if (inUse) LOG.warn(MISUSE_MESSAGE);
204 inUse = true;
205
206 return httpConnection;
207 }
208
209 /***
210 * @see HttpConnectionManager#getConnection(HostConfiguration, long)
211 *
212 * @deprecated Use #getConnectionWithTimeout(HostConfiguration, long)
213 */
214 public HttpConnection getConnection(
215 HostConfiguration hostConfiguration, long timeout) {
216 return getConnectionWithTimeout(hostConfiguration, timeout);
217 }
218
219 /***
220 * @see HttpConnectionManager#releaseConnection(org.apache.commons.httpclient.HttpConnection)
221 */
222 public void releaseConnection(HttpConnection conn) {
223 if (conn != httpConnection) {
224 throw new IllegalStateException("Unexpected release of an unknown connection.");
225 }
226 if (this.alwaysClose) {
227 httpConnection.close();
228 } else {
229
230 finishLastResponse(httpConnection);
231 }
232
233 inUse = false;
234
235
236 idleStartTime = System.currentTimeMillis();
237 }
238
239 /***
240 * Returns {@link HttpConnectionManagerParams parameters} associated
241 * with this connection manager.
242 *
243 * @since 2.1
244 *
245 * @see HttpConnectionManagerParams
246 */
247 public HttpConnectionManagerParams getParams() {
248 return this.params;
249 }
250
251 /***
252 * Assigns {@link HttpConnectionManagerParams parameters} for this
253 * connection manager.
254 *
255 * @since 2.1
256 *
257 * @see HttpConnectionManagerParams
258 */
259 public void setParams(final HttpConnectionManagerParams params) {
260 if (params == null) {
261 throw new IllegalArgumentException("Parameters may not be null");
262 }
263 this.params = params;
264 }
265
266 /***
267 * @since 3.0
268 */
269 public void closeIdleConnections(long idleTimeout) {
270 long maxIdleTime = System.currentTimeMillis() - idleTimeout;
271 if (idleStartTime <= maxIdleTime) {
272 httpConnection.close();
273 }
274 }
275
276 /***
277 * since 3.1
278 */
279 public void shutdown() {
280 httpConnection.close();
281 }
282
283 }