diff --git a/httpclient/src/main/java/org/apache/http/impl/conn/SingleClientConnManager.java b/httpclient/src/main/java/org/apache/http/impl/conn/SingleClientConnManager.java
index 86e334f27..1171fa732 100644
--- a/httpclient/src/main/java/org/apache/http/impl/conn/SingleClientConnManager.java
+++ b/httpclient/src/main/java/org/apache/http/impl/conn/SingleClientConnManager.java
@@ -34,6 +34,8 @@ package org.apache.http.impl.conn;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
+import net.jcip.annotations.ThreadSafe;
+
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.conn.ClientConnectionManager;
@@ -45,26 +47,21 @@ import org.apache.http.conn.routing.RouteTracker;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.params.HttpParams;
-
/**
- * A connection "manager" for a single connection.
- * This manager is good only for single-threaded use.
- * Allocation always returns the connection immediately,
- * even if it has not been released after the previous allocation.
- * In that case, a {@link #MISUSE_MESSAGE warning} is logged
- * and the previously issued connection is revoked.
+ * A connection manager for a single connection. This connection manager
+ * maintains only one active connection at a time. Even though this class
+ * is thread-safe it ought to be used by one execution thread only.
*
- * This class is derived from SimpleHttpConnectionManager
- * in HttpClient 3. See there for original authors.
- *
- *
- *
- *
- *
- * @version $Revision$
+ * SingleClientConnManager will make an effort to reuse the connection
+ * for subsequent requests with the same {@link HttpRoute route}.
+ * It will, however, close the existing connection and open it
+ * for the given route, if the route of the persistent connection does
+ * not match that of the connection request. If the connection has been
+ * already been allocated {@link IllegalStateException} is thrown.
*
* @since 4.0
*/
+@ThreadSafe
public class SingleClientConnManager implements ClientConnectionManager {
private final Log log = LogFactory.getLog(getClass());
@@ -76,10 +73,10 @@ public class SingleClientConnManager implements ClientConnectionManager {
/** The schemes supported by this connection manager. */
- protected SchemeRegistry schemeRegistry;
+ protected final SchemeRegistry schemeRegistry;
/** The operator for opening and updating connections. */
- protected ClientConnectionOperator connOperator;
+ protected final ClientConnectionOperator connOperator;
/** The one and only entry in this pool. */
protected PoolEntry uniquePoolEntry;
@@ -99,9 +96,6 @@ public class SingleClientConnManager implements ClientConnectionManager {
/** Indicates whether this connection manager is shut down. */
protected volatile boolean isShutDown;
-
-
-
/**
* Creates a new simple connection manager.
*
@@ -111,7 +105,6 @@ public class SingleClientConnManager implements ClientConnectionManager {
*/
public SingleClientConnManager(HttpParams params,
SchemeRegistry schreg) {
-
if (schreg == null) {
throw new IllegalArgumentException
("Scheme registry must not be null.");
@@ -123,9 +116,7 @@ public class SingleClientConnManager implements ClientConnectionManager {
this.lastReleaseTime = -1L;
this.alwaysShutDown = false; //@@@ from params? as argument?
this.isShutDown = false;
-
- } //
-
+ }
@Override
protected void finalize() throws Throwable {
@@ -133,13 +124,10 @@ public class SingleClientConnManager implements ClientConnectionManager {
super.finalize();
}
-
- // non-javadoc, see interface ClientConnectionManager
public SchemeRegistry getSchemeRegistry() {
return this.schemeRegistry;
}
-
/**
* Hook for creating the connection operator.
* It is called by the constructor.
@@ -154,24 +142,19 @@ public class SingleClientConnManager implements ClientConnectionManager {
*/
protected ClientConnectionOperator
createConnectionOperator(SchemeRegistry schreg) {
-
return new DefaultClientConnectionOperator(schreg);
}
-
/**
* Asserts that this manager is not shut down.
*
* @throws IllegalStateException if this manager is shut down
*/
- protected final void assertStillUp()
- throws IllegalStateException {
-
+ protected final void assertStillUp() throws IllegalStateException {
if (this.isShutDown)
throw new IllegalStateException("Manager is shut down.");
}
-
public final ClientConnectionRequest requestConnection(
final HttpRoute route,
final Object state) {
@@ -191,18 +174,15 @@ public class SingleClientConnManager implements ClientConnectionManager {
};
}
-
/**
* Obtains a connection.
- * This method does not block.
*
* @param route where the connection should point to
*
* @return a connection that can be used to communicate
* along the given route
*/
- public ManagedClientConnection getConnection(HttpRoute route, Object state) {
-
+ public synchronized ManagedClientConnection getConnection(HttpRoute route, Object state) {
if (route == null) {
throw new IllegalArgumentException("Route may not be null.");
}
@@ -213,7 +193,7 @@ public class SingleClientConnManager implements ClientConnectionManager {
}
if (managedConn != null)
- revokeConnection();
+ throw new IllegalStateException(MISUSE_MESSAGE);
// check re-usability of the connection
boolean recreate = false;
@@ -252,9 +232,9 @@ public class SingleClientConnManager implements ClientConnectionManager {
return managedConn;
}
-
- // non-javadoc, see interface ClientConnectionManager
- public void releaseConnection(ManagedClientConnection conn, long validDuration, TimeUnit timeUnit) {
+ public synchronized void releaseConnection(
+ ManagedClientConnection conn,
+ long validDuration, TimeUnit timeUnit) {
assertStillUp();
if (!(conn instanceof ConnAdapter)) {
@@ -292,7 +272,6 @@ public class SingleClientConnManager implements ClientConnectionManager {
sca.shutdown();
}
} catch (IOException iox) {
- //@@@ log as warning? let pass?
if (log.isDebugEnabled())
log.debug("Exception shutting down released connection.",
iox);
@@ -305,17 +284,15 @@ public class SingleClientConnManager implements ClientConnectionManager {
else
connectionExpiresTime = Long.MAX_VALUE;
}
- } // releaseConnection
+ }
- public void closeExpiredConnections() {
+ public synchronized void closeExpiredConnections() {
if(System.currentTimeMillis() >= connectionExpiresTime) {
closeIdleConnections(0, TimeUnit.MILLISECONDS);
}
}
-
- // non-javadoc, see interface ClientConnectionManager
- public void closeIdleConnections(long idletime, TimeUnit tunit) {
+ public synchronized void closeIdleConnections(long idletime, TimeUnit tunit) {
assertStillUp();
// idletime can be 0 or negative, no problem there
@@ -337,9 +314,7 @@ public class SingleClientConnManager implements ClientConnectionManager {
}
}
-
- // non-javadoc, see interface ClientConnectionManager
- public void shutdown() {
+ public synchronized void shutdown() {
this.isShutDown = true;
@@ -357,19 +332,14 @@ public class SingleClientConnManager implements ClientConnectionManager {
}
}
-
/**
- * Revokes the currently issued connection.
- * The adapter gets disconnected, the connection will be shut down.
+ * @deprecated no longer used
*/
+ @Deprecated
protected void revokeConnection() {
if (managedConn == null)
return;
-
- log.warn(MISUSE_MESSAGE);
-
managedConn.detach();
-
try {
uniquePoolEntry.shutdown();
} catch (IOException iox) {
@@ -378,7 +348,6 @@ public class SingleClientConnManager implements ClientConnectionManager {
}
}
-
/**
* The pool entry for this connection manager.
*/
@@ -395,29 +364,22 @@ public class SingleClientConnManager implements ClientConnectionManager {
/**
* Closes the connection in this pool entry.
*/
- protected void close()
- throws IOException {
-
+ protected void close() throws IOException {
shutdownEntry();
if (connection.isOpen())
connection.close();
}
-
/**
* Shuts down the connection in this pool entry.
*/
- protected void shutdown()
- throws IOException {
-
+ protected void shutdown() throws IOException {
shutdownEntry();
if (connection.isOpen())
connection.shutdown();
}
- } // class PoolEntry
-
-
+ }
/**
* The connection adapter used by this manager.
@@ -438,5 +400,4 @@ public class SingleClientConnManager implements ClientConnectionManager {
}
-
-} // class SingleClientConnManager
+}