src/java.base/share/classes/sun/net/www/http/HttpClient.java
branchJDK-8229867-branch
changeset 57968 8595871a5446
parent 53563 a4b7ea85d668
equal deleted inserted replaced
57966:e89c7aaf2906 57968:8595871a5446
     1 /*
     1 /*
     2  * Copyright (c) 1994, 2016, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 1994, 2019, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    28 import java.io.*;
    28 import java.io.*;
    29 import java.net.*;
    29 import java.net.*;
    30 import java.util.Locale;
    30 import java.util.Locale;
    31 import java.util.Objects;
    31 import java.util.Objects;
    32 import java.util.Properties;
    32 import java.util.Properties;
       
    33 import java.util.concurrent.locks.Lock;
       
    34 import java.util.concurrent.locks.ReentrantLock;
       
    35 
    33 import sun.net.NetworkClient;
    36 import sun.net.NetworkClient;
    34 import sun.net.ProgressSource;
    37 import sun.net.ProgressSource;
    35 import sun.net.www.MessageHeader;
    38 import sun.net.www.MessageHeader;
    36 import sun.net.www.HeaderParser;
    39 import sun.net.www.HeaderParser;
    37 import sun.net.www.MeteredStream;
    40 import sun.net.www.MeteredStream;
    45 /**
    48 /**
    46  * @author Herb Jellinek
    49  * @author Herb Jellinek
    47  * @author Dave Brown
    50  * @author Dave Brown
    48  */
    51  */
    49 public class HttpClient extends NetworkClient {
    52 public class HttpClient extends NetworkClient {
       
    53     protected final ReentrantLock clientLock = new ReentrantLock();
       
    54 
    50     // whether this httpclient comes from the cache
    55     // whether this httpclient comes from the cache
    51     protected boolean cachedHttpClient = false;
    56     protected boolean cachedHttpClient = false;
    52 
    57 
    53     protected boolean inCache;
    58     protected boolean inCache;
    54 
    59 
   313             if (ret != null) {
   318             if (ret != null) {
   314                 String ak = httpuc == null ? AuthenticatorKeys.DEFAULT
   319                 String ak = httpuc == null ? AuthenticatorKeys.DEFAULT
   315                      : httpuc.getAuthenticatorKey();
   320                      : httpuc.getAuthenticatorKey();
   316                 boolean compatible = Objects.equals(ret.proxy, p)
   321                 boolean compatible = Objects.equals(ret.proxy, p)
   317                      && Objects.equals(ret.getAuthenticatorKey(), ak);
   322                      && Objects.equals(ret.getAuthenticatorKey(), ak);
       
   323                 final Lock lock = ret.clientLock;
   318                 if (compatible) {
   324                 if (compatible) {
   319                     synchronized (ret) {
   325                     lock.lock();
       
   326                     try {
   320                         ret.cachedHttpClient = true;
   327                         ret.cachedHttpClient = true;
   321                         assert ret.inCache;
   328                         assert ret.inCache;
   322                         ret.inCache = false;
   329                         ret.inCache = false;
   323                         if (httpuc != null && ret.needsTunneling())
   330                         if (httpuc != null && ret.needsTunneling())
   324                             httpuc.setTunnelState(TUNNELING);
   331                             httpuc.setTunnelState(TUNNELING);
   325                         logFinest("KeepAlive stream retrieved from the cache, " + ret);
   332                         logFinest("KeepAlive stream retrieved from the cache, " + ret);
       
   333                     } finally {
       
   334                         lock.unlock();
   326                     }
   335                     }
   327                 } else {
   336                 } else {
   328                     // We cannot return this connection to the cache as it's
   337                     // We cannot return this connection to the cache as it's
   329                     // KeepAliveTimeout will get reset. We simply close the connection.
   338                     // KeepAliveTimeout will get reset. We simply close the connection.
   330                     // This should be fine as it is very rare that a connection
   339                     // This should be fine as it is very rare that a connection
   331                     // to the same host will not use the same proxy.
   340                     // to the same host will not use the same proxy.
   332                     synchronized(ret) {
   341                     lock.lock();
       
   342                     try  {
   333                         ret.inCache = false;
   343                         ret.inCache = false;
   334                         ret.closeServer();
   344                         ret.closeServer();
       
   345                     } finally {
       
   346                         lock.unlock();
   335                     }
   347                     }
   336                     ret = null;
   348                     ret = null;
   337                 }
   349                 }
   338             }
   350             }
   339         }
   351         }
   407         } else {
   419         } else {
   408             closeServer();
   420             closeServer();
   409         }
   421         }
   410     }
   422     }
   411 
   423 
   412     protected synchronized boolean available() {
   424     protected boolean available() {
   413         boolean available = true;
   425         boolean available = true;
   414         int old = -1;
   426         int old = -1;
   415 
   427 
       
   428         clientLock.lock();
   416         try {
   429         try {
   417             try {
   430             try {
   418                 old = serverSocket.getSoTimeout();
   431                 old = serverSocket.getSoTimeout();
   419                 serverSocket.setSoTimeout(1);
   432                 serverSocket.setSoTimeout(1);
   420                 BufferedInputStream tmpbuf =
   433                 BufferedInputStream tmpbuf =
   434             }
   447             }
   435         } catch (IOException e) {
   448         } catch (IOException e) {
   436             logFinest("HttpClient.available(): " +
   449             logFinest("HttpClient.available(): " +
   437                         "SocketException: not available");
   450                         "SocketException: not available");
   438             available = false;
   451             available = false;
       
   452         } finally {
       
   453             clientLock.unlock();
   439         }
   454         }
   440         return available;
   455         return available;
   441     }
   456     }
   442 
   457 
   443     protected synchronized void putInKeepAliveCache() {
   458     protected void putInKeepAliveCache() {
   444         if (inCache) {
   459         clientLock.lock();
   445             assert false : "Duplicate put to keep alive cache";
   460         try {
   446             return;
   461             if (inCache) {
   447         }
   462                 assert false : "Duplicate put to keep alive cache";
   448         inCache = true;
   463                 return;
   449         kac.put(url, null, this);
   464             }
   450     }
   465             inCache = true;
   451 
   466             kac.put(url, null, this);
   452     protected synchronized boolean isInKeepAliveCache() {
   467         } finally {
   453         return inCache;
   468             clientLock.unlock();
       
   469         }
       
   470     }
       
   471 
       
   472     protected boolean isInKeepAliveCache() {
       
   473         clientLock.lock();
       
   474         try {
       
   475             return inCache;
       
   476         } finally {
       
   477             clientLock.unlock();
       
   478         }
   454     }
   479     }
   455 
   480 
   456     /*
   481     /*
   457      * Close an idle connection to this URL (if it exists in the
   482      * Close an idle connection to this URL (if it exists in the
   458      * cache).
   483      * cache).
   495     }
   520     }
   496 
   521 
   497     /*
   522     /*
   498      * Returns true if this httpclient is from cache
   523      * Returns true if this httpclient is from cache
   499      */
   524      */
   500     public synchronized boolean isCachedConnection() {
   525     public boolean isCachedConnection() {
   501         return cachedHttpClient;
   526         clientLock.lock();
       
   527         try {
       
   528             return cachedHttpClient;
       
   529         } finally {
       
   530             clientLock.unlock();
       
   531         }
   502     }
   532     }
   503 
   533 
   504     /*
   534     /*
   505      * Finish any work left after the socket connection is
   535      * Finish any work left after the socket connection is
   506      * established.  In the normal http case, it's a NO-OP. Subclass
   536      * established.  In the normal http case, it's a NO-OP. Subclass
   514     }
   544     }
   515 
   545 
   516     /*
   546     /*
   517      * call openServer in a privileged block
   547      * call openServer in a privileged block
   518      */
   548      */
   519     private synchronized void privilegedOpenServer(final InetSocketAddress server)
   549     private void privilegedOpenServer(final InetSocketAddress server)
   520          throws IOException
   550          throws IOException
   521     {
   551     {
       
   552         assert clientLock.isHeldByCurrentThread();
   522         try {
   553         try {
   523             java.security.AccessController.doPrivileged(
   554             java.security.AccessController.doPrivileged(
   524                 new java.security.PrivilegedExceptionAction<>() {
   555                 new java.security.PrivilegedExceptionAction<>() {
   525                     public Void run() throws IOException {
   556                     public Void run() throws IOException {
   526                     openServer(server.getHostString(), server.getPort());
   557                     openServer(server.getHostString(), server.getPort());
   542         super.openServer(proxyHost, proxyPort);
   573         super.openServer(proxyHost, proxyPort);
   543     }
   574     }
   544 
   575 
   545     /*
   576     /*
   546      */
   577      */
   547     protected synchronized void openServer() throws IOException {
   578     protected void openServer() throws IOException {
   548 
   579 
   549         SecurityManager security = System.getSecurityManager();
   580         SecurityManager security = System.getSecurityManager();
   550 
   581 
   551         if (security != null) {
   582         clientLock.lock();
   552             security.checkConnect(host, port);
   583         try {
   553         }
   584             if (security != null) {
   554 
   585                 security.checkConnect(host, port);
   555         if (keepingAlive) { // already opened
   586             }
   556             return;
   587 
   557         }
   588             if (keepingAlive) { // already opened
   558 
       
   559         if (url.getProtocol().equals("http") ||
       
   560             url.getProtocol().equals("https") ) {
       
   561 
       
   562             if ((proxy != null) && (proxy.type() == Proxy.Type.HTTP)) {
       
   563                 sun.net.www.URLConnection.setProxiedHost(host);
       
   564                 privilegedOpenServer((InetSocketAddress) proxy.address());
       
   565                 usingProxy = true;
       
   566                 return;
   589                 return;
       
   590             }
       
   591 
       
   592             if (url.getProtocol().equals("http") ||
       
   593                     url.getProtocol().equals("https")) {
       
   594 
       
   595                 if ((proxy != null) && (proxy.type() == Proxy.Type.HTTP)) {
       
   596                     sun.net.www.URLConnection.setProxiedHost(host);
       
   597                     privilegedOpenServer((InetSocketAddress) proxy.address());
       
   598                     usingProxy = true;
       
   599                     return;
       
   600                 } else {
       
   601                     // make direct connection
       
   602                     openServer(host, port);
       
   603                     usingProxy = false;
       
   604                     return;
       
   605                 }
       
   606 
   567             } else {
   607             } else {
   568                 // make direct connection
   608                 /* we're opening some other kind of url, most likely an
   569                 openServer(host, port);
   609                  * ftp url.
   570                 usingProxy = false;
   610                  */
   571                 return;
   611                 if ((proxy != null) && (proxy.type() == Proxy.Type.HTTP)) {
   572             }
   612                     sun.net.www.URLConnection.setProxiedHost(host);
   573 
   613                     privilegedOpenServer((InetSocketAddress) proxy.address());
   574         } else {
   614                     usingProxy = true;
   575             /* we're opening some other kind of url, most likely an
   615                     return;
   576              * ftp url.
   616                 } else {
   577              */
   617                     // make direct connection
   578             if ((proxy != null) && (proxy.type() == Proxy.Type.HTTP)) {
   618                     super.openServer(host, port);
   579                 sun.net.www.URLConnection.setProxiedHost(host);
   619                     usingProxy = false;
   580                 privilegedOpenServer((InetSocketAddress) proxy.address());
   620                     return;
   581                 usingProxy = true;
   621                 }
   582                 return;
   622             }
   583             } else {
   623         } finally {
   584                 // make direct connection
   624             clientLock.unlock();
   585                 super.openServer(host, port);
       
   586                 usingProxy = false;
       
   587                 return;
       
   588             }
       
   589         }
   625         }
   590     }
   626     }
   591 
   627 
   592     public String getURLFile() throws IOException {
   628     public String getURLFile() throws IOException {
   593 
   629 
  1004         }
  1040         }
  1005 
  1041 
  1006         return ret;
  1042         return ret;
  1007     }
  1043     }
  1008 
  1044 
  1009     public synchronized InputStream getInputStream() {
  1045     public InputStream getInputStream() {
  1010         return serverInput;
  1046         clientLock.lock();
       
  1047         try {
       
  1048             return serverInput;
       
  1049         } finally {
       
  1050             clientLock.unlock();
       
  1051         }
  1011     }
  1052     }
  1012 
  1053 
  1013     public OutputStream getOutputStream() {
  1054     public OutputStream getOutputStream() {
  1014         return serverOutput;
  1055         return serverOutput;
  1015     }
  1056     }