blob: ac7ffca6824376d7d946989942a4e6a97214e4e3 [file] [log] [blame]
package org.apache.commons.vfs.provider.webdav;
import org.apache.commons.httpclient.HostConfiguration;
import org.apache.commons.httpclient.HttpConnection;
import org.apache.commons.httpclient.HttpConnectionManager;
import java.io.IOException;
import java.io.InputStream;
/**
* A connection manager that provides access to a single HttpConnection. This
* manager makes no attempt to provide exclusive access to the contained
* HttpConnection.
* <p/>
* imario@apache.org: Keep connection in ThreadLocal.
*
* @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
* @author <a href="mailto:becke@u.washington.edu">Michael Becke</a>
* @author Eric Johnson
* @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
* @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
* @author Laura Werner
* @since 2.0
*/
public class WebdavConnectionManager implements HttpConnectionManager
{
private static class ConnectionParameters
{
private boolean staleCheck;
public boolean isStaleCheckingEnabled()
{
return staleCheck;
}
public void setStaleCheckingEnabled(boolean b)
{
staleCheck = b;
}
public void populateParameters(HttpConnection connection)
{
connection.setStaleCheckingEnabled(staleCheck);
}
}
/**
* Since the same connection is about to be reused, make sure the
* previous request was completely processed, and if not
* consume it now.
*
* @param conn The connection
*/
static void finishLastResponse(HttpConnection conn)
{
InputStream lastResponse = conn.getLastResponseInputStream();
if (lastResponse != null)
{
conn.setLastResponseInputStream(null);
try
{
lastResponse.close();
}
catch (IOException ioe)
{
//FIXME: badness - close to force reconnect.
conn.close();
}
}
}
/**
* The thread data
*/
protected ThreadLocal localHttpConnection = new ThreadLocal()
{
protected Object initialValue()
{
return new Entry();
}
};
/**
* Collection of parameters associated with this connection manager.
*/
private ConnectionParameters params = new ConnectionParameters();
/**
* release the connection of the current thread
*/
public void releaseLocalConnection()
{
if (getLocalHttpConnection() != null)
{
releaseConnection(getLocalHttpConnection());
}
}
private static class Entry
{
/**
* The http connection
*/
private HttpConnection conn = null;
/**
* The time the connection was made idle.
*/
private long idleStartTime = Long.MAX_VALUE;
}
public WebdavConnectionManager()
{
}
protected HttpConnection getLocalHttpConnection()
{
return ((Entry) localHttpConnection.get()).conn;
}
protected void setLocalHttpConnection(HttpConnection conn)
{
((Entry) localHttpConnection.get()).conn = conn;
}
protected long getIdleStartTime()
{
return ((Entry) localHttpConnection.get()).idleStartTime;
}
protected void setIdleStartTime(long idleStartTime)
{
((Entry) localHttpConnection.get()).idleStartTime = idleStartTime;
}
/**
* @see HttpConnectionManager#getConnection(org.apache.commons.httpclient.HostConfiguration)
*/
public HttpConnection getConnection(HostConfiguration hostConfiguration)
{
return getConnection(hostConfiguration, 0);
}
/**
* Gets the staleCheckingEnabled value to be set on HttpConnections that are created.
*
* @return <code>true</code> if stale checking will be enabled on HttpConections
* @see HttpConnection#isStaleCheckingEnabled()
* @deprecated Use {@link HttpConnectionManagerParams#isStaleCheckingEnabled()},
* {@link HttpConnectionManager#getParams()}.
*/
public boolean isConnectionStaleCheckingEnabled()
{
return this.params.isStaleCheckingEnabled();
}
/**
* Sets the staleCheckingEnabled value to be set on HttpConnections that are created.
*
* @param connectionStaleCheckingEnabled <code>true</code> if stale checking will be enabled
* on HttpConections
* @see HttpConnection#setStaleCheckingEnabled(boolean)
* @deprecated Use {@link HttpConnectionManagerParams#setStaleCheckingEnabled(boolean)},
* {@link HttpConnectionManager#getParams()}.
*/
public void setConnectionStaleCheckingEnabled(boolean connectionStaleCheckingEnabled)
{
this.params.setStaleCheckingEnabled(connectionStaleCheckingEnabled);
}
/**
* @see HttpConnectionManager#getConnection(HostConfiguration, long)
* @since 3.0
*/
public HttpConnection getConnectionWithTimeout(
HostConfiguration hostConfiguration, long timeout)
{
HttpConnection httpConnection = getLocalHttpConnection();
if (httpConnection == null)
{
httpConnection = new HttpConnection(hostConfiguration);
setLocalHttpConnection(httpConnection);
httpConnection.setHttpConnectionManager(this);
this.params.populateParameters(httpConnection);
}
else
{
// make sure the host and proxy are correct for this connection
// close it and set the values if they are not
if (!hostConfiguration.hostEquals(httpConnection)
|| !hostConfiguration.proxyEquals(httpConnection))
{
if (httpConnection.isOpen())
{
httpConnection.close();
}
httpConnection.setHost(hostConfiguration.getHost());
httpConnection.setPort(hostConfiguration.getPort());
httpConnection.setProtocol(hostConfiguration.getProtocol());
httpConnection.setLocalAddress(hostConfiguration.getLocalAddress());
httpConnection.setProxyHost(hostConfiguration.getProxyHost());
httpConnection.setProxyPort(hostConfiguration.getProxyPort());
}
else
{
finishLastResponse(httpConnection);
}
}
// remove the connection from the timeout handler
setIdleStartTime(Long.MAX_VALUE);
return httpConnection;
}
/**
* @see HttpConnectionManager#getConnection(HostConfiguration, long)
* @deprecated Use #getConnectionWithTimeout(HostConfiguration, long)
*/
public HttpConnection getConnection(
HostConfiguration hostConfiguration, long timeout)
{
return getConnectionWithTimeout(hostConfiguration, timeout);
}
/**
* @see HttpConnectionManager#releaseConnection(org.apache.commons.httpclient.HttpConnection)
*/
public void releaseConnection(HttpConnection conn)
{
if (conn != getLocalHttpConnection())
{
throw new IllegalStateException("Unexpected release of an unknown connection.");
}
finishLastResponse(getLocalHttpConnection());
// track the time the connection was made idle
setIdleStartTime(System.currentTimeMillis());
}
/**
* @since 3.0
*/
public void closeIdleConnections(long idleTimeout)
{
long maxIdleTime = System.currentTimeMillis() - idleTimeout;
if (getIdleStartTime() <= maxIdleTime)
{
getLocalHttpConnection().close();
}
}
}