/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* A class that implements a cache of idle Http connections for keep-alive
*
* @author Stephen R. Pietrowicz (NCSA)
* @author Dave Brown
*/
public class KeepAliveCache
implements Runnable {
/* maximum # keep-alive connections to maintain at once
* This should be 2 by the HTTP spec, but because we don't support pipe-lining
* a larger value is more appropriate. So we now set a default of 5, and the value
* refers to the number of idle connections per destination (in the cache) only.
* It can be reset by setting system property "http.maxConnections".
*/
static int getMaxConnections() {
if (result == -1) {
.intValue();
if (result <= 0)
}
return result;
}
/**
* Constructor
*/
public KeepAliveCache() {}
/**
* Register this URL and HttpClient (that supports keep-alive) with the cache
* @param url The URL contains info about the host and port
* @param http The HttpClient to be cached
*/
if (!startThread) {
if (!keepAliveTimer.isAlive()) {
startThread = true;
}
}
if (startThread) {
clear();
/* Unfortunately, we can't always believe the keep-alive timeout we got
* back from the server. If I'm connected through a Netscape proxy
* to a server that sent me a keep-alive
* time of 15 sec, the proxy unilaterally terminates my connection
* The robustness to get around this is in HttpClient.parseHTTP()
*/
final KeepAliveCache cache = this;
// We want to create the Keep-Alive-Timer in the
// system threadgroup
}
keepAliveTimer.setDaemon(true);
// Set the context class loader to null in order to avoid
// keeping a strong reference to an application classloader.
return null;
}
});
}
if (v == null) {
} else {
}
}
/* remove an obsolete HttpClient from its VectorCache */
if (v != null) {
v.remove(h);
if (v.empty()) {
}
}
}
/* called by a clientVector thread when all its connections have timed out
* and that vector of connections should be removed.
*/
super.remove(k);
}
/**
* Check to see if this URL has a cached HttpClient
*/
if (v == null) { // nothing in cache yet
return null;
}
return v.get();
}
/* Sleeps for an alloted timeout, then checks for timed out connections.
* Errs on the side of caution (leave connections idle for a relatively
* short time).
*/
public void run() {
do {
try {
} catch (InterruptedException e) {}
synchronized (this) {
/* Remove all unused HttpClients. Starting from the
* bottom of the stack (the least-recently used first).
* REMIND: It'd be nice to not remove *all* connections
* that aren't presently in use. One could have been added
* a second ago that's still perfectly valid, and we're
* needlessly axing it. But it's not clear how to do this
* cleanly, and doing it right may be more trouble than it's
* worth.
*/
= new ArrayList<KeepAliveKey>();
synchronized (v) {
int i;
for (i = 0; i < v.size(); i++) {
KeepAliveEntry e = v.elementAt(i);
HttpClient h = e.hc;
h.closeServer();
} else {
break;
}
}
if (v.size() == 0) {
}
}
}
}
}
} while (size() > 0);
return;
}
/*
* Do not serialize this class!
*/
throws IOException {
throw new NotSerializableException();
}
throws IOException, ClassNotFoundException {
throw new NotSerializableException();
}
}
/* FILO order for recycling HttpClients, should run in a thread
* to time them out. If > maxConns are in use, block.
*/
// sleep time in milliseconds, before cache clear
int nap;
}
if (empty()) {
return null;
} else {
// Loop until we find a connection that has not timed out
do {
KeepAliveEntry e = pop();
e.hc.closeServer();
} else {
}
return hc;
}
}
/* return a still valid, unused HttpClient */
h.closeServer(); // otherwise the connection remains in limbo
} else {
}
}
/*
* Do not serialize this class!
*/
throws IOException {
throw new NotSerializableException();
}
throws IOException, ClassNotFoundException {
throw new NotSerializableException();
}
}
class KeepAliveKey {
/**
* Constructor
*
* @param url the URL containing the protocol, host and port information
*/
}
/**
* Determine whether or not two objects of this type are equal
*/
if ((obj instanceof KeepAliveKey) == false)
return false;
}
/**
* The hashCode() for this object is the string hashCode() of
* concatenation of the protocol, host name and port.
*/
public int hashCode() {
}
}
class KeepAliveEntry {
long idleStartTime;
this.idleStartTime = idleStartTime;
}
}