jdk/src/share/classes/sun/net/www/protocol/https/HttpsClient.java
changeset 16499 88276d2da9c0
parent 14342 8435a30053c1
child 18178 ee71c923891d
--- a/jdk/src/share/classes/sun/net/www/protocol/https/HttpsClient.java	Thu Mar 21 19:19:08 2013 +0530
+++ b/jdk/src/share/classes/sun/net/www/protocol/https/HttpsClient.java	Thu Mar 21 17:33:15 2013 +0000
@@ -30,6 +30,7 @@
 import java.io.UnsupportedEncodingException;
 import java.io.PrintStream;
 import java.io.BufferedOutputStream;
+import java.net.InetAddress;
 import java.net.Socket;
 import java.net.SocketException;
 import java.net.URL;
@@ -46,11 +47,15 @@
 
 import javax.net.ssl.*;
 import sun.net.www.http.HttpClient;
+import sun.net.www.protocol.http.HttpURLConnection;
 import sun.security.action.*;
 
 import sun.security.util.HostnameChecker;
 import sun.security.ssl.SSLSocketImpl;
 
+import sun.util.logging.PlatformLogger;
+import static sun.net.www.protocol.http.HttpURLConnection.TunnelState.*;
+
 
 /**
  * This class provides HTTPS client URL support, building on the standard
@@ -274,15 +279,17 @@
     // This code largely ripped off from HttpClient.New, and
     // it uses the same keepalive cache.
 
-    static HttpClient New(SSLSocketFactory sf, URL url, HostnameVerifier hv)
+    static HttpClient New(SSLSocketFactory sf, URL url, HostnameVerifier hv,
+                          HttpURLConnection httpuc)
             throws IOException {
-        return HttpsClient.New(sf, url, hv, true);
+        return HttpsClient.New(sf, url, hv, true, httpuc);
     }
 
     /** See HttpClient for the model for this method. */
     static HttpClient New(SSLSocketFactory sf, URL url,
-            HostnameVerifier hv, boolean useCache) throws IOException {
-        return HttpsClient.New(sf, url, hv, (String)null, -1, useCache);
+            HostnameVerifier hv, boolean useCache,
+            HttpURLConnection httpuc) throws IOException {
+        return HttpsClient.New(sf, url, hv, (String)null, -1, useCache, httpuc);
     }
 
     /**
@@ -290,37 +297,74 @@
      * the specified proxy server.
      */
     static HttpClient New(SSLSocketFactory sf, URL url, HostnameVerifier hv,
-                           String proxyHost, int proxyPort) throws IOException {
-        return HttpsClient.New(sf, url, hv, proxyHost, proxyPort, true);
+                           String proxyHost, int proxyPort,
+                           HttpURLConnection httpuc) throws IOException {
+        return HttpsClient.New(sf, url, hv, proxyHost, proxyPort, true, httpuc);
     }
 
     static HttpClient New(SSLSocketFactory sf, URL url, HostnameVerifier hv,
-                           String proxyHost, int proxyPort, boolean useCache)
+                           String proxyHost, int proxyPort, boolean useCache,
+                           HttpURLConnection httpuc)
         throws IOException {
-        return HttpsClient.New(sf, url, hv, proxyHost, proxyPort, useCache, -1);
+        return HttpsClient.New(sf, url, hv, proxyHost, proxyPort, useCache, -1,
+                               httpuc);
     }
 
     static HttpClient New(SSLSocketFactory sf, URL url, HostnameVerifier hv,
                           String proxyHost, int proxyPort, boolean useCache,
-                          int connectTimeout)
+                          int connectTimeout, HttpURLConnection httpuc)
         throws IOException {
 
         return HttpsClient.New(sf, url, hv,
                                (proxyHost == null? null :
                                 HttpsClient.newHttpProxy(proxyHost, proxyPort)),
-                               useCache, connectTimeout);
+                               useCache, connectTimeout, httpuc);
     }
 
     static HttpClient New(SSLSocketFactory sf, URL url, HostnameVerifier hv,
                           Proxy p, boolean useCache,
-                          int connectTimeout)
-        throws IOException {
+                          int connectTimeout, HttpURLConnection httpuc)
+        throws IOException
+    {
+        if (p == null) {
+            p = Proxy.NO_PROXY;
+        }
         HttpsClient ret = null;
         if (useCache) {
             /* see if one's already around */
             ret = (HttpsClient) kac.get(url, sf);
+            if (ret != null && httpuc != null &&
+                httpuc.streaming() &&
+                httpuc.getRequestMethod() == "POST") {
+                if (!ret.available())
+                    ret = null;
+            }
+
             if (ret != null) {
-                ret.cachedHttpClient = true;
+                if ((ret.proxy != null && ret.proxy.equals(p)) ||
+                    (ret.proxy == null && p == null)) {
+                    synchronized (ret) {
+                        ret.cachedHttpClient = true;
+                        assert ret.inCache;
+                        ret.inCache = false;
+                        if (httpuc != null && ret.needsTunneling())
+                            httpuc.setTunnelState(TUNNELING);
+                        PlatformLogger logger = HttpURLConnection.getHttpLogger();
+                        if (logger.isLoggable(PlatformLogger.FINEST)) {
+                            logger.finest("KeepAlive stream retrieved from the cache, " + ret);
+                        }
+                    }
+                } else {
+                    // We cannot return this connection to the cache as it's
+                    // KeepAliveTimeout will get reset. We simply close the connection.
+                    // This should be fine as it is very rare that a connection
+                    // to the same host will not use the same proxy.
+                    synchronized(ret) {
+                        ret.inCache = false;
+                        ret.closeServer();
+                    }
+                    ret = null;
+                }
             }
         }
         if (ret == null) {
@@ -328,7 +372,11 @@
         } else {
             SecurityManager security = System.getSecurityManager();
             if (security != null) {
-                security.checkConnect(url.getHost(), url.getPort());
+                if (ret.proxy == Proxy.NO_PROXY || ret.proxy == null) {
+                    security.checkConnect(InetAddress.getByName(url.getHost()).getHostAddress(), url.getPort());
+                } else {
+                    security.checkConnect(url.getHost(), url.getPort());
+                }
             }
             ret.url = url;
         }
@@ -607,6 +655,11 @@
 
     @Override
     protected void putInKeepAliveCache() {
+        if (inCache) {
+            assert false : "Duplicate put to keep alive cache";
+            return;
+        }
+        inCache = true;
         kac.put(url, sslSocketFactory, this);
     }