8170814: Reuse cache entries (part II)
Reviewed-by: chegar, ahgross, weijun, aefimov, michaelm
--- a/jdk/src/java.base/share/classes/sun/net/www/http/HttpClient.java Sat Nov 19 13:10:18 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/net/www/http/HttpClient.java Tue Dec 20 18:02:26 2016 +0000
@@ -106,6 +106,11 @@
if false, then NTLM connections will not be cached.
The default value is 'true'. */
private static final boolean cacheNTLMProp;
+ /* Value of the system property jdk.spnego.cache;
+ if false, then connections authentified using the Negotiate/Kerberos
+ scheme will not be cached.
+ The default value is 'true'. */
+ private static final boolean cacheSPNEGOProp;
volatile boolean keepingAlive; /* this is a keep-alive connection */
volatile boolean disableKeepAlive;/* keep-alive has been disabled for this
@@ -161,6 +166,7 @@
String keepAlive = props.getProperty("http.keepAlive");
String retryPost = props.getProperty("sun.net.http.retryPost");
String cacheNTLM = props.getProperty("jdk.ntlm.cache");
+ String cacheSPNEGO = props.getProperty("jdk.spnego.cache");
if (keepAlive != null) {
keepAliveProp = Boolean.parseBoolean(keepAlive);
@@ -180,6 +186,11 @@
cacheNTLMProp = true;
}
+ if (cacheSPNEGO != null) {
+ cacheSPNEGOProp = Boolean.parseBoolean(cacheSPNEGO);
+ } else {
+ cacheSPNEGOProp = true;
+ }
}
/**
@@ -784,9 +795,16 @@
// and cacheNTLMProp is false, than we can't keep this connection
// alive: we will switch disableKeepAlive to true.
boolean canKeepAlive = !disableKeepAlive;
- if (canKeepAlive && cacheNTLMProp == false && authenticate != null) {
+ if (canKeepAlive && (cacheNTLMProp == false || cacheSPNEGOProp == false)
+ && authenticate != null) {
authenticate = authenticate.toLowerCase(Locale.US);
- canKeepAlive = !authenticate.startsWith("ntlm ");
+ if (cacheNTLMProp == false) {
+ canKeepAlive &= !authenticate.startsWith("ntlm ");
+ }
+ if (cacheSPNEGOProp == false) {
+ canKeepAlive &= !authenticate.startsWith("negotiate ");
+ canKeepAlive &= !authenticate.startsWith("kerberos ");
+ }
}
disableKeepAlive |= !canKeepAlive;
--- a/jdk/src/java.base/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java Sat Nov 19 13:10:18 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java Tue Dec 20 18:02:26 2016 +0000
@@ -34,6 +34,7 @@
import sun.util.logging.PlatformLogger;
import static sun.net.www.protocol.http.AuthScheme.NEGOTIATE;
import static sun.net.www.protocol.http.AuthScheme.KERBEROS;
+import sun.security.action.GetPropertyAction;
/**
* NegotiateAuthentication:
@@ -55,7 +56,14 @@
// if it's true, a cached Negotiator is put into <code>cache</code>.
// the cache can be used only once, so after the first use, it's cleaned.
static HashMap <String, Boolean> supported = null;
- static HashMap <String, Negotiator> cache = null;
+ static ThreadLocal <HashMap <String, Negotiator>> cache = null;
+ /* Whether cache is enabled for Negotiate/Kerberos */
+ private static final boolean cacheSPNEGO;
+ static {
+ String spnegoCacheProp =
+ GetPropertyAction.privilegedGetProperty("jdk.spnego.cache", "true");
+ cacheSPNEGO = Boolean.parseBoolean(spnegoCacheProp);
+ }
// The HTTP Negotiate Helper
private Negotiator negotiator = null;
@@ -119,8 +127,7 @@
*/
private static synchronized boolean isSupportedImpl(HttpCallerInfo hci) {
if (supported == null) {
- supported = new HashMap <String, Boolean>();
- cache = new HashMap <String, Negotiator>();
+ supported = new HashMap<>();
}
String hostname = hci.host;
hostname = hostname.toLowerCase();
@@ -133,7 +140,15 @@
supported.put(hostname, true);
// the only place cache.put is called. here we can make sure
// the object is valid and the oneToken inside is not null
- cache.put(hostname, neg);
+ if (cache == null) {
+ cache = new ThreadLocal<>() {
+ @Override
+ protected HashMap<String, Negotiator> initialValue() {
+ return new HashMap<>();
+ }
+ };
+ }
+ cache.get().put(hostname, neg);
return true;
} else {
supported.put(hostname, false);
@@ -141,6 +156,16 @@
}
}
+ private static synchronized HashMap<String, Negotiator> getCache() {
+ if (cache == null) return null;
+ return cache.get();
+ }
+
+ @Override
+ protected boolean useAuthCache() {
+ return super.useAuthCache() && cacheSPNEGO;
+ }
+
/**
* Not supported. Must use the setHeaders() method
*/
@@ -198,12 +223,11 @@
*/
private byte[] firstToken() throws IOException {
negotiator = null;
- if (cache != null) {
- synchronized(cache) {
- negotiator = cache.get(getHost());
- if (negotiator != null) {
- cache.remove(getHost()); // so that it is only used once
- }
+ HashMap <String, Negotiator> cachedMap = getCache();
+ if (cachedMap != null) {
+ negotiator = cachedMap.get(getHost());
+ if (negotiator != null) {
+ cachedMap.remove(getHost()); // so that it is only used once
}
}
if (negotiator == null) {