View Javadoc

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