8163520: Reuse cache entries
Reviewed-by: chegar, michaelm, weijun, aefimov, ahgross
--- a/jdk/src/java.base/share/classes/sun/net/www/http/HttpClient.java Mon Oct 03 19:55:49 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/net/www/http/HttpClient.java Thu Oct 20 15:10:52 2016 +0100
@@ -102,7 +102,15 @@
// from previous releases.
private static boolean retryPostProp = true;
+ /* Value of the system property jdk.ntlm.cache;
+ if false, then NTLM connections will not be cached.
+ The default value is 'true'. */
+ private static final boolean cacheNTLMProp;
+
volatile boolean keepingAlive; /* this is a keep-alive connection */
+ volatile boolean disableKeepAlive;/* keep-alive has been disabled for this
+ connection - this will be used when
+ recomputing the value of keepingAlive */
int keepAliveConnections = -1; /* number of keep-alives left */
/**Idle timeout value, in milliseconds. Zero means infinity,
@@ -152,6 +160,7 @@
Properties props = GetPropertyAction.privilegedGetProperties();
String keepAlive = props.getProperty("http.keepAlive");
String retryPost = props.getProperty("sun.net.http.retryPost");
+ String cacheNTLM = props.getProperty("jdk.ntlm.cache");
if (keepAlive != null) {
keepAliveProp = Boolean.parseBoolean(keepAlive);
@@ -161,8 +170,15 @@
if (retryPost != null) {
retryPostProp = Boolean.parseBoolean(retryPost);
- } else
+ } else {
retryPostProp = true;
+ }
+
+ if (cacheNTLM != null) {
+ cacheNTLMProp = Boolean.parseBoolean(cacheNTLM);
+ } else {
+ cacheNTLMProp = true;
+ }
}
@@ -723,6 +739,7 @@
nread += r;
}
String keep=null;
+ String authenticate=null;
ret = b[0] == 'H' && b[1] == 'T'
&& b[2] == 'T' && b[3] == 'P' && b[4] == '/' &&
b[5] == '1' && b[6] == '.';
@@ -751,17 +768,37 @@
*/
if (usingProxy) { // not likely a proxy will return this
keep = responses.findValue("Proxy-Connection");
+ authenticate = responses.findValue("Proxy-Authenticate");
}
if (keep == null) {
keep = responses.findValue("Connection");
+ authenticate = responses.findValue("WWW-Authenticate");
}
+
+ // 'disableKeepAlive' starts with the value false.
+ // It can transition from false to true, but once true
+ // it stays true.
+ // If cacheNTLMProp is false, and disableKeepAlive is false,
+ // then we need to examine the response headers to figure out
+ // whether we are doing NTLM authentication. If we do NTLM,
+ // 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) {
+ authenticate = authenticate.toLowerCase(Locale.US);
+ canKeepAlive = !authenticate.startsWith("ntlm ");
+ }
+ disableKeepAlive |= !canKeepAlive;
+
if (keep != null && keep.toLowerCase(Locale.US).equals("keep-alive")) {
/* some servers, notably Apache1.1, send something like:
* "Keep-Alive: timeout=15, max=1" which we should respect.
*/
- HeaderParser p = new HeaderParser(
+ if (disableKeepAlive) {
+ keepAliveConnections = 1;
+ } else {
+ HeaderParser p = new HeaderParser(
responses.findValue("Keep-Alive"));
- if (p != null) {
/* default should be larger in case of proxy */
keepAliveConnections = p.findInt("max", usingProxy?50:5);
keepAliveTimeout = p.findInt("timeout", usingProxy?60:5);
@@ -771,7 +808,7 @@
* We're talking 1.1 or later. Keep persistent until
* the server says to close.
*/
- if (keep != null) {
+ if (keep != null || disableKeepAlive) {
/*
* The only Connection token we understand is close.
* Paranoia: if there is any Connection header then
@@ -853,7 +890,7 @@
keepAliveConnections = 1;
keepingAlive = false;
} else {
- keepingAlive = true;
+ keepingAlive = !disableKeepAlive;
}
failedOnce = false;
} else {
@@ -886,7 +923,7 @@
(cl >= 0 ||
code == HttpURLConnection.HTTP_NOT_MODIFIED ||
code == HttpURLConnection.HTTP_NO_CONTENT)) {
- keepingAlive = true;
+ keepingAlive = !disableKeepAlive;
failedOnce = false;
} else if (keepingAlive) {
/* Previously we were keeping alive, and now we're not. Remove
--- a/jdk/src/java.base/share/classes/sun/net/www/protocol/http/AuthenticationInfo.java Mon Oct 03 19:55:49 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/http/AuthenticationInfo.java Thu Oct 20 15:10:52 2016 +0100
@@ -65,8 +65,7 @@
* repeatedly, via the Authenticator. Default is false, which means that this
* behavior is switched off.
*/
- static boolean serializeAuth;
-
+ static final boolean serializeAuth;
static {
serializeAuth = java.security.AccessController.doPrivileged(
new sun.security.action.GetBooleanAction(
@@ -106,6 +105,16 @@
public String getProtocolScheme() {
return protocol;
}
+ /**
+ * Whether we should cache this instance in the AuthCache.
+ * This method returns {@code true} by default.
+ * Subclasses may override this method to add
+ * additional restrictions.
+ * @return {@code true} by default.
+ */
+ protected boolean useAuthCache() {
+ return true;
+ }
/**
* requests is used to ensure that interaction with the
@@ -373,9 +382,11 @@
*/
void addToCache() {
String key = cacheKey(true);
- cache.put(key, this);
- if (supportsPreemptiveAuthorization()) {
- cache.put(cacheKey(false), this);
+ if (useAuthCache()) {
+ cache.put(key, this);
+ if (supportsPreemptiveAuthorization()) {
+ cache.put(cacheKey(false), this);
+ }
}
endAuthRequest(key);
}
--- a/jdk/src/java.base/unix/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java Mon Oct 03 19:55:49 2016 +0300
+++ b/jdk/src/java.base/unix/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java Thu Oct 20 15:10:52 2016 +0100
@@ -35,6 +35,7 @@
import java.security.GeneralSecurityException;
import java.util.Base64;
import java.util.Objects;
+import java.util.Properties;
import sun.net.www.HeaderParser;
import sun.net.www.protocol.http.AuthenticationInfo;
@@ -76,8 +77,15 @@
private String hostname;
/* Domain to use if not specified by user */
- private static String defaultDomain =
- GetPropertyAction.privilegedGetProperty("http.auth.ntlm.domain", "");
+ private static final String defaultDomain;
+ /* Whether cache is enabled for NTLM */
+ private static final boolean ntlmCache;
+ static {
+ Properties props = GetPropertyAction.privilegedGetProperties();
+ defaultDomain = props.getProperty("http.auth.ntlm.domain", "");
+ String ntlmCacheProp = props.getProperty("jdk.ntlm.cache", "true");
+ ntlmCache = Boolean.parseBoolean(ntlmCacheProp);
+ }
public static boolean supportsTransparentAuth () {
return false;
@@ -171,6 +179,11 @@
init (pw);
}
+ @Override
+ protected boolean useAuthCache() {
+ return ntlmCache && super.useAuthCache();
+ }
+
/**
* @return true if this authentication supports preemptive authorization
*/
--- a/jdk/src/java.base/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java Mon Oct 03 19:55:49 2016 +0300
+++ b/jdk/src/java.base/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java Thu Oct 20 15:10:52 2016 +0100
@@ -31,6 +31,7 @@
import java.net.UnknownHostException;
import java.net.URL;
import java.util.Objects;
+import java.util.Properties;
import sun.net.www.HeaderParser;
import sun.net.www.protocol.http.AuthenticationInfo;
import sun.net.www.protocol.http.AuthScheme;
@@ -51,12 +52,16 @@
NTLMAuthenticationCallback.getNTLMAuthenticationCallback();
private String hostname;
- private static String defaultDomain; /* Domain to use if not specified by user */
-
+ /* Domain to use if not specified by user */
+ private static final String defaultDomain;
+ /* Whether cache is enabled for NTLM */
+ private static final boolean ntlmCache;
static {
- defaultDomain = GetPropertyAction
- .privilegedGetProperty("http.auth.ntlm.domain", "domain");
- };
+ Properties props = GetPropertyAction.privilegedGetProperties();
+ defaultDomain = props.getProperty("http.auth.ntlm.domain", "domain");
+ String ntlmCacheProp = props.getProperty("jdk.ntlm.cache", "true");
+ ntlmCache = Boolean.parseBoolean(ntlmCacheProp);
+ }
private void init0() {
@@ -136,6 +141,11 @@
init (pw);
}
+ @Override
+ protected boolean useAuthCache() {
+ return ntlmCache && super.useAuthCache();
+ }
+
/**
* @return true if this authentication supports preemptive authorization
*/