src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java
branchJDK-8229867-branch
changeset 57968 8595871a5446
parent 57879 095c2f21dd10
equal deleted inserted replaced
57966:e89c7aaf2906 57968:8595871a5446
    79 import java.util.TimeZone;
    79 import java.util.TimeZone;
    80 import java.net.MalformedURLException;
    80 import java.net.MalformedURLException;
    81 import java.nio.ByteBuffer;
    81 import java.nio.ByteBuffer;
    82 import java.util.Objects;
    82 import java.util.Objects;
    83 import java.util.Properties;
    83 import java.util.Properties;
       
    84 import java.util.concurrent.locks.ReentrantLock;
       
    85 
    84 import static sun.net.www.protocol.http.AuthScheme.BASIC;
    86 import static sun.net.www.protocol.http.AuthScheme.BASIC;
    85 import static sun.net.www.protocol.http.AuthScheme.DIGEST;
    87 import static sun.net.www.protocol.http.AuthScheme.DIGEST;
    86 import static sun.net.www.protocol.http.AuthScheme.NTLM;
    88 import static sun.net.www.protocol.http.AuthScheme.NTLM;
    87 import static sun.net.www.protocol.http.AuthScheme.NEGOTIATE;
    89 import static sun.net.www.protocol.http.AuthScheme.NEGOTIATE;
    88 import static sun.net.www.protocol.http.AuthScheme.KERBEROS;
    90 import static sun.net.www.protocol.http.AuthScheme.KERBEROS;
    95  */
    97  */
    96 
    98 
    97 
    99 
    98 public class HttpURLConnection extends java.net.HttpURLConnection {
   100 public class HttpURLConnection extends java.net.HttpURLConnection {
    99 
   101 
   100     static String HTTP_CONNECT = "CONNECT";
   102     static final String HTTP_CONNECT = "CONNECT";
   101 
   103 
   102     static final String version;
   104     static final String version;
   103     public static final String userAgent;
   105     public static final String userAgent;
   104 
   106 
   105     /* max # of allowed re-directs */
   107     /* max # of allowed re-directs */
   350     /* Headers and request method cannot be changed
   352     /* Headers and request method cannot be changed
   351      * once this flag is set in :-
   353      * once this flag is set in :-
   352      *     - getOutputStream()
   354      *     - getOutputStream()
   353      *     - getInputStream())
   355      *     - getInputStream())
   354      *     - connect()
   356      *     - connect()
   355      * Access synchronized on this.
   357      * Access synchronized on connectionLock.
   356      */
   358      */
   357     private boolean connecting = false;
   359     private boolean connecting = false;
   358 
   360 
   359     /* The following two fields are only used with Digest Authentication */
   361     /* The following two fields are only used with Digest Authentication */
   360     String domain;      /* The list of authentication domains */
   362     String domain;      /* The list of authentication domains */
   381 
   383 
   382     String serverAuthKey, proxyAuthKey;
   384     String serverAuthKey, proxyAuthKey;
   383 
   385 
   384     /* Progress source */
   386     /* Progress source */
   385     protected ProgressSource pi;
   387     protected ProgressSource pi;
       
   388 
       
   389     /* Lock */
       
   390     final ReentrantLock connectionLock = new ReentrantLock();
   386 
   391 
   387     /* all the response headers we get back */
   392     /* all the response headers we get back */
   388     private MessageHeader responses;
   393     private MessageHeader responses;
   389     /* the stream _from_ the server */
   394     /* the stream _from_ the server */
   390     private InputStream inputStream = null;
   395     private InputStream inputStream = null;
   511     public void authObj(Object authObj) {
   516     public void authObj(Object authObj) {
   512         this.authObj = authObj;
   517         this.authObj = authObj;
   513     }
   518     }
   514 
   519 
   515     @Override
   520     @Override
   516     public synchronized void setAuthenticator(Authenticator auth) {
   521     public void setAuthenticator(Authenticator auth) {
   517         if (connecting || connected) {
   522         connectionLock.lock();
   518             throw new IllegalStateException(
   523         try {
   519                   "Authenticator must be set before connecting");
   524             if (connecting || connected) {
   520         }
   525                 throw new IllegalStateException(
   521         authenticator = Objects.requireNonNull(auth);
   526                         "Authenticator must be set before connecting");
   522         authenticatorKey = AuthenticatorKeys.getKey(authenticator);
   527             }
       
   528             authenticator = Objects.requireNonNull(auth);
       
   529             authenticatorKey = AuthenticatorKeys.getKey(authenticator);
       
   530         } finally {
       
   531             connectionLock.unlock();
       
   532         }
   523     }
   533     }
   524 
   534 
   525     public String getAuthenticatorKey() {
   535     public String getAuthenticatorKey() {
   526         String k = authenticatorKey;
   536         String k = authenticatorKey;
   527         if (k == null) return AuthenticatorKeys.getKey(authenticator);
   537         if (k == null) return AuthenticatorKeys.getKey(authenticator);
   560                     "Illegal character(s) in message header value: " + value);
   570                     "Illegal character(s) in message header value: " + value);
   561             }
   571             }
   562         }
   572         }
   563     }
   573     }
   564 
   574 
   565     public synchronized void setRequestMethod(String method)
   575     public void setRequestMethod(String method)
   566                         throws ProtocolException {
   576                         throws ProtocolException {
   567         if (connecting) {
   577         connectionLock.lock();
   568             throw new IllegalStateException("connect in progress");
   578         try {
   569         }
   579             if (connecting) {
   570         super.setRequestMethod(method);
   580                 throw new IllegalStateException("connect in progress");
       
   581             }
       
   582             super.setRequestMethod(method);
       
   583         } finally {
       
   584             connectionLock.unlock();
       
   585         }
   571     }
   586     }
   572 
   587 
   573     /* adds the standard key/val pairs to reqests if necessary & write to
   588     /* adds the standard key/val pairs to reqests if necessary & write to
   574      * given PrintStream
   589      * given PrintStream
   575      */
   590      */
   680                                       String.valueOf(fixedContentLength));
   695                                       String.valueOf(fixedContentLength));
   681                     }
   696                     }
   682                 }
   697                 }
   683             } else if (poster != null) {
   698             } else if (poster != null) {
   684                 /* add Content-Length & POST/PUT data */
   699                 /* add Content-Length & POST/PUT data */
       
   700                 // safe to synchronize on poster: this is
       
   701                 // a simple subclass of ByteArrayOutputStream
   685                 synchronized (poster) {
   702                 synchronized (poster) {
   686                     /* close it, so no more data can be added */
   703                     /* close it, so no more data can be added */
   687                     poster.close();
   704                     poster.close();
   688                     requests.set("Content-Length",
   705                     requests.set("Content-Length",
   689                                  String.valueOf(poster.size()));
   706                                  String.valueOf(poster.size()));
  1007     }
  1024     }
  1008 
  1025 
  1009     // overridden in HTTPS subclass
  1026     // overridden in HTTPS subclass
  1010 
  1027 
  1011     public void connect() throws IOException {
  1028     public void connect() throws IOException {
  1012         synchronized (this) {
  1029         connectionLock.lock();
       
  1030         try {
  1013             connecting = true;
  1031             connecting = true;
       
  1032         } finally {
       
  1033             connectionLock.unlock();
  1014         }
  1034         }
  1015         plainConnect();
  1035         plainConnect();
  1016     }
  1036     }
  1017 
  1037 
  1018     private boolean checkReuseConnection () {
  1038     private boolean checkReuseConnection () {
  1055         }
  1075         }
  1056         return host + ":" + Integer.toString(port);
  1076         return host + ":" + Integer.toString(port);
  1057     }
  1077     }
  1058 
  1078 
  1059     protected void plainConnect()  throws IOException {
  1079     protected void plainConnect()  throws IOException {
  1060         synchronized (this) {
  1080         connectionLock.lock();
       
  1081         try {
  1061             if (connected) {
  1082             if (connected) {
  1062                 return;
  1083                 return;
  1063             }
  1084             }
       
  1085         } finally {
       
  1086             connectionLock.unlock();
  1064         }
  1087         }
  1065         SocketPermission p = URLtoSocketPermission(this.url);
  1088         SocketPermission p = URLtoSocketPermission(this.url);
  1066         if (p != null) {
  1089         if (p != null) {
  1067             try {
  1090             try {
  1068                 AccessController.doPrivilegedWithCombiner(
  1091                 AccessController.doPrivilegedWithCombiner(
  1321      * Disallowed:
  1344      * Disallowed:
  1322      * - get input, [read input,] get output, [write output]
  1345      * - get input, [read input,] get output, [write output]
  1323      */
  1346      */
  1324 
  1347 
  1325     @Override
  1348     @Override
  1326     public synchronized OutputStream getOutputStream() throws IOException {
  1349     public OutputStream getOutputStream() throws IOException {
  1327         connecting = true;
  1350         connectionLock.lock();
  1328         SocketPermission p = URLtoSocketPermission(this.url);
  1351         try {
  1329 
  1352             connecting = true;
  1330         if (p != null) {
  1353             SocketPermission p = URLtoSocketPermission(this.url);
  1331             try {
  1354 
  1332                 return AccessController.doPrivilegedWithCombiner(
  1355             if (p != null) {
  1333                     new PrivilegedExceptionAction<>() {
  1356                 try {
  1334                         public OutputStream run() throws IOException {
  1357                     return AccessController.doPrivilegedWithCombiner(
  1335                             return getOutputStream0();
  1358                             new PrivilegedExceptionAction<>() {
  1336                         }
  1359                                 public OutputStream run() throws IOException {
  1337                     }, null, p
  1360                                     return getOutputStream0();
  1338                 );
  1361                                 }
  1339             } catch (PrivilegedActionException e) {
  1362                             }, null, p
  1340                 throw (IOException) e.getException();
  1363                     );
  1341             }
  1364                 } catch (PrivilegedActionException e) {
  1342         } else {
  1365                     throw (IOException) e.getException();
  1343             return getOutputStream0();
  1366                 }
  1344         }
  1367             } else {
  1345     }
  1368                 return getOutputStream0();
  1346 
  1369             }
  1347     private synchronized OutputStream getOutputStream0() throws IOException {
  1370         } finally {
       
  1371             connectionLock.unlock();
       
  1372         }
       
  1373     }
       
  1374 
       
  1375     private OutputStream getOutputStream0() throws IOException {
       
  1376         assert connectionLock.isHeldByCurrentThread();
  1348         try {
  1377         try {
  1349             if (!doOutput) {
  1378             if (!doOutput) {
  1350                 throw new ProtocolException("cannot write to a URLConnection"
  1379                 throw new ProtocolException("cannot write to a URLConnection"
  1351                                + " if doOutput=false - call setDoOutput(true)");
  1380                                + " if doOutput=false - call setDoOutput(true)");
  1352             }
  1381             }
  1432     private void setCookieHeader() throws IOException {
  1461     private void setCookieHeader() throws IOException {
  1433         if (cookieHandler != null) {
  1462         if (cookieHandler != null) {
  1434             // we only want to capture the user defined Cookies once, as
  1463             // we only want to capture the user defined Cookies once, as
  1435             // they cannot be changed by user code after we are connected,
  1464             // they cannot be changed by user code after we are connected,
  1436             // only internally.
  1465             // only internally.
  1437             synchronized (this) {
  1466         if (setUserCookies) {
  1438                 if (setUserCookies) {
  1467             // we should only reach here when called from
  1439                     int k = requests.getKey("Cookie");
  1468             // writeRequest, which in turn is only called by
  1440                     if (k != -1)
  1469             // getInputStream0
  1441                         userCookies = requests.getValue(k);
  1470             assert connectionLock.isHeldByCurrentThread();
  1442                     k = requests.getKey("Cookie2");
  1471             int k = requests.getKey("Cookie");
  1443                     if (k != -1)
  1472             if (k != -1)
  1444                         userCookies2 = requests.getValue(k);
  1473                 userCookies = requests.getValue(k);
  1445                     setUserCookies = false;
  1474             k = requests.getKey("Cookie2");
  1446                 }
  1475             if (k != -1)
  1447             }
  1476                 userCookies2 = requests.getValue(k);
       
  1477             setUserCookies = false;
       
  1478         }
  1448 
  1479 
  1449             // remove old Cookie header before setting new one.
  1480             // remove old Cookie header before setting new one.
  1450             requests.remove("Cookie");
  1481             requests.remove("Cookie");
  1451             requests.remove("Cookie2");
  1482             requests.remove("Cookie2");
  1452 
  1483 
  1499 
  1530 
  1500         } // end of getting cookies
  1531         } // end of getting cookies
  1501     }
  1532     }
  1502 
  1533 
  1503     @Override
  1534     @Override
  1504     public synchronized InputStream getInputStream() throws IOException {
  1535     public InputStream getInputStream() throws IOException {
  1505         connecting = true;
  1536         connectionLock.lock();
  1506         SocketPermission p = URLtoSocketPermission(this.url);
  1537         try {
  1507 
  1538             connecting = true;
  1508         if (p != null) {
  1539             SocketPermission p = URLtoSocketPermission(this.url);
  1509             try {
  1540 
  1510                 return AccessController.doPrivilegedWithCombiner(
  1541             if (p != null) {
  1511                     new PrivilegedExceptionAction<>() {
  1542                 try {
  1512                         public InputStream run() throws IOException {
  1543                     return AccessController.doPrivilegedWithCombiner(
  1513                             return getInputStream0();
  1544                             new PrivilegedExceptionAction<>() {
  1514                         }
  1545                                 public InputStream run() throws IOException {
  1515                     }, null, p
  1546                                     return getInputStream0();
  1516                 );
  1547                                 }
  1517             } catch (PrivilegedActionException e) {
  1548                             }, null, p
  1518                 throw (IOException) e.getException();
  1549                     );
  1519             }
  1550                 } catch (PrivilegedActionException e) {
  1520         } else {
  1551                     throw (IOException) e.getException();
  1521             return getInputStream0();
  1552                 }
       
  1553             } else {
       
  1554                 return getInputStream0();
       
  1555             }
       
  1556         } finally {
       
  1557             connectionLock.unlock();
  1522         }
  1558         }
  1523     }
  1559     }
  1524 
  1560 
  1525     @SuppressWarnings("empty-statement")
  1561     @SuppressWarnings("empty-statement")
  1526     private synchronized InputStream getInputStream0() throws IOException {
  1562     private InputStream getInputStream0() throws IOException {
  1527 
  1563 
       
  1564         assert connectionLock.isHeldByCurrentThread();
  1528         if (!doInput) {
  1565         if (!doInput) {
  1529             throw new ProtocolException("Cannot read from URLConnection"
  1566             throw new ProtocolException("Cannot read from URLConnection"
  1530                    + " if doInput=false (call setDoInput(true))");
  1567                    + " if doInput=false (call setDoInput(true))");
  1531         }
  1568         }
  1532 
  1569 
  2051     }
  2088     }
  2052 
  2089 
  2053     /**
  2090     /**
  2054      * establish a tunnel through proxy server
  2091      * establish a tunnel through proxy server
  2055      */
  2092      */
  2056     public synchronized void doTunneling() throws IOException {
  2093     public void doTunneling() throws IOException {
       
  2094         connectionLock.lock();
       
  2095         try {
       
  2096             doTunneling0();
       
  2097         } finally{
       
  2098             connectionLock.unlock();
       
  2099         }
       
  2100     }
       
  2101 
       
  2102     private void doTunneling0() throws IOException {
  2057         int retryTunnel = 0;
  2103         int retryTunnel = 0;
  2058         String statusLine = "";
  2104         String statusLine = "";
  2059         int respCode = 0;
  2105         int respCode = 0;
  2060         AuthenticationInfo proxyAuthentication = null;
  2106         AuthenticationInfo proxyAuthentication = null;
  2061         String proxyHost = null;
  2107         String proxyHost = null;
  2421     }
  2467     }
  2422 
  2468 
  2423     /**
  2469     /**
  2424      * Gets the authentication for an HTTP server, and applies it to
  2470      * Gets the authentication for an HTTP server, and applies it to
  2425      * the connection.
  2471      * the connection.
  2426      * @param authHdr the AuthenticationHeader which tells what auth scheme is
  2472      * @param authhdr the AuthenticationHeader which tells what auth scheme is
  2427      * preferred.
  2473      * preferred.
  2428      */
  2474      */
  2429     @SuppressWarnings("fallthrough")
  2475     @SuppressWarnings("fallthrough")
  2430     private AuthenticationInfo getServerAuthentication (AuthenticationHeader authhdr) {
  2476     private AuthenticationInfo getServerAuthentication (AuthenticationHeader authhdr) {
  2431         /* get authorization from authenticator */
  2477         /* get authorization from authenticator */
  3164      * Sets request property. If a property with the key already
  3210      * Sets request property. If a property with the key already
  3165      * exists, overwrite its value with the new value.
  3211      * exists, overwrite its value with the new value.
  3166      * @param value the value to be set
  3212      * @param value the value to be set
  3167      */
  3213      */
  3168     @Override
  3214     @Override
  3169     public synchronized void setRequestProperty(String key, String value) {
  3215     public void setRequestProperty(String key, String value) {
  3170         if (connected || connecting)
  3216         connectionLock.lock();
  3171             throw new IllegalStateException("Already connected");
  3217         try {
  3172         if (key == null)
  3218             if (connected || connecting)
  3173             throw new NullPointerException ("key is null");
  3219                 throw new IllegalStateException("Already connected");
  3174 
  3220             if (key == null)
  3175         if (isExternalMessageHeaderAllowed(key, value)) {
  3221                 throw new NullPointerException("key is null");
  3176             requests.set(key, value);
  3222 
  3177             if (!key.equalsIgnoreCase("Content-Type")) {
  3223             if (isExternalMessageHeaderAllowed(key, value)) {
  3178                 userHeaders.set(key, value);
  3224                 requests.set(key, value);
  3179             }
  3225                 if (!key.equalsIgnoreCase("Content-Type")) {
       
  3226                     userHeaders.set(key, value);
       
  3227                 }
       
  3228             }
       
  3229         } finally {
       
  3230             connectionLock.unlock();
  3180         }
  3231         }
  3181     }
  3232     }
  3182 
  3233 
  3183     MessageHeader getUserSetHeaders() {
  3234     MessageHeader getUserSetHeaders() {
  3184         return userHeaders;
  3235         return userHeaders;
  3190      * existing values associated with the same key.
  3241      * existing values associated with the same key.
  3191      *
  3242      *
  3192      * @param   key     the keyword by which the request is known
  3243      * @param   key     the keyword by which the request is known
  3193      *                  (e.g., "<code>accept</code>").
  3244      *                  (e.g., "<code>accept</code>").
  3194      * @param   value  the value associated with it.
  3245      * @param   value  the value associated with it.
  3195      * @see #getRequestProperties(java.lang.String)
  3246      * @see #getRequestProperty(java.lang.String)
  3196      * @since 1.4
  3247      * @since 1.4
  3197      */
  3248      */
  3198     @Override
  3249     @Override
  3199     public synchronized void addRequestProperty(String key, String value) {
  3250     public void addRequestProperty(String key, String value) {
  3200         if (connected || connecting)
  3251         connectionLock.lock();
  3201             throw new IllegalStateException("Already connected");
  3252         try {
  3202         if (key == null)
  3253             if (connected || connecting)
  3203             throw new NullPointerException ("key is null");
  3254                 throw new IllegalStateException("Already connected");
  3204 
  3255             if (key == null)
  3205         if (isExternalMessageHeaderAllowed(key, value)) {
  3256                 throw new NullPointerException("key is null");
  3206             requests.add(key, value);
  3257 
  3207             if (!key.equalsIgnoreCase("Content-Type")) {
  3258             if (isExternalMessageHeaderAllowed(key, value)) {
       
  3259                 requests.add(key, value);
       
  3260                 if (!key.equalsIgnoreCase("Content-Type")) {
  3208                     userHeaders.add(key, value);
  3261                     userHeaders.add(key, value);
  3209             }
  3262                 }
       
  3263             }
       
  3264         } finally {
       
  3265             connectionLock.unlock();
  3210         }
  3266         }
  3211     }
  3267     }
  3212 
  3268 
  3213     //
  3269     //
  3214     // Set a property for authentication.  This can safely disregard
  3270     // Set a property for authentication.  This can safely disregard
  3215     // the connected test.
  3271     // the connected test.
  3216     //
  3272     //
  3217     public void setAuthenticationProperty(String key, String value) {
  3273     public void setAuthenticationProperty(String key, String value) {
  3218         checkMessageHeader(key, value);
  3274         // use lock here to avoid the need for external synchronization
  3219         requests.set(key, value);
  3275         // in AuthenticationInfo subclasses
       
  3276         connectionLock.lock();
       
  3277         try {
       
  3278             checkMessageHeader(key, value);
       
  3279             requests.set(key, value);
       
  3280         } finally {
       
  3281             connectionLock.unlock();
       
  3282         }
  3220     }
  3283     }
  3221 
  3284 
  3222     @Override
  3285     @Override
  3223     public synchronized String getRequestProperty (String key) {
  3286     public String getRequestProperty (String key) {
  3224         if (key == null) {
  3287         connectionLock.lock();
  3225             return null;
  3288         try {
  3226         }
  3289             if (key == null) {
  3227 
       
  3228         // don't return headers containing security sensitive information
       
  3229         for (int i=0; i < EXCLUDE_HEADERS.length; i++) {
       
  3230             if (key.equalsIgnoreCase(EXCLUDE_HEADERS[i])) {
       
  3231                 return null;
  3290                 return null;
  3232             }
  3291             }
  3233         }
  3292 
  3234         if (!setUserCookies) {
  3293             // don't return headers containing security sensitive information
  3235             if (key.equalsIgnoreCase("Cookie")) {
  3294             for (int i = 0; i < EXCLUDE_HEADERS.length; i++) {
  3236                 return userCookies;
  3295                 if (key.equalsIgnoreCase(EXCLUDE_HEADERS[i])) {
  3237             }
  3296                     return null;
  3238             if (key.equalsIgnoreCase("Cookie2")) {
  3297                 }
  3239                 return userCookies2;
  3298             }
  3240             }
  3299             if (!setUserCookies) {
  3241         }
  3300                 if (key.equalsIgnoreCase("Cookie")) {
  3242         return requests.findValue(key);
  3301                     return userCookies;
       
  3302                 }
       
  3303                 if (key.equalsIgnoreCase("Cookie2")) {
       
  3304                     return userCookies2;
       
  3305                 }
       
  3306             }
       
  3307             return requests.findValue(key);
       
  3308         } finally {
       
  3309             connectionLock.unlock();
       
  3310         }
  3243     }
  3311     }
  3244 
  3312 
  3245     /**
  3313     /**
  3246      * Returns an unmodifiable Map of general request
  3314      * Returns an unmodifiable Map of general request
  3247      * properties for this connection. The Map keys
  3315      * properties for this connection. The Map keys
  3253      * @return  a Map of the general request properties for this connection.
  3321      * @return  a Map of the general request properties for this connection.
  3254      * @throws IllegalStateException if already connected
  3322      * @throws IllegalStateException if already connected
  3255      * @since 1.4
  3323      * @since 1.4
  3256      */
  3324      */
  3257     @Override
  3325     @Override
  3258     public synchronized Map<String, List<String>> getRequestProperties() {
  3326     public Map<String, List<String>> getRequestProperties() {
  3259         if (connected)
  3327         connectionLock.lock();
  3260             throw new IllegalStateException("Already connected");
  3328         try {
  3261 
  3329             if (connected)
  3262         // exclude headers containing security-sensitive info
  3330                 throw new IllegalStateException("Already connected");
  3263         if (setUserCookies) {
  3331 
  3264             return requests.getHeaders(EXCLUDE_HEADERS);
  3332             // exclude headers containing security-sensitive info
  3265         }
  3333             if (setUserCookies) {
  3266         /*
  3334                 return requests.getHeaders(EXCLUDE_HEADERS);
  3267          * The cookies in the requests message headers may have
  3335             }
  3268          * been modified. Use the saved user cookies instead.
  3336             /*
  3269          */
  3337              * The cookies in the requests message headers may have
  3270         Map<String, List<String>> userCookiesMap = null;
  3338              * been modified. Use the saved user cookies instead.
  3271         if (userCookies != null || userCookies2 != null) {
  3339              */
  3272             userCookiesMap = new HashMap<>();
  3340             Map<String, List<String>> userCookiesMap = null;
  3273             if (userCookies != null) {
  3341             if (userCookies != null || userCookies2 != null) {
  3274                 userCookiesMap.put("Cookie", Arrays.asList(userCookies));
  3342                 userCookiesMap = new HashMap<>();
  3275             }
  3343                 if (userCookies != null) {
  3276             if (userCookies2 != null) {
  3344                     userCookiesMap.put("Cookie", Arrays.asList(userCookies));
  3277                 userCookiesMap.put("Cookie2", Arrays.asList(userCookies2));
  3345                 }
  3278             }
  3346                 if (userCookies2 != null) {
  3279         }
  3347                     userCookiesMap.put("Cookie2", Arrays.asList(userCookies2));
  3280         return requests.filterAndAddHeaders(EXCLUDE_HEADERS2, userCookiesMap);
  3348                 }
       
  3349             }
       
  3350             return requests.filterAndAddHeaders(EXCLUDE_HEADERS2, userCookiesMap);
       
  3351         } finally {
       
  3352             connectionLock.unlock();
       
  3353         }
  3281     }
  3354     }
  3282 
  3355 
  3283     @Override
  3356     @Override
  3284     public void setConnectTimeout(int timeout) {
  3357     public void setConnectTimeout(int timeout) {
  3285         if (timeout < 0)
  3358         if (timeout < 0)
  3319      *
  3392      *
  3320      * @param timeout an <code>int</code> that specifies the timeout
  3393      * @param timeout an <code>int</code> that specifies the timeout
  3321      * value to be used in milliseconds
  3394      * value to be used in milliseconds
  3322      * @throws IllegalArgumentException if the timeout parameter is negative
  3395      * @throws IllegalArgumentException if the timeout parameter is negative
  3323      *
  3396      *
  3324      * @see java.net.URLConnectiongetReadTimeout()
  3397      * @see java.net.URLConnection#getReadTimeout()
  3325      * @see java.io.InputStream#read()
  3398      * @see java.io.InputStream#read()
  3326      * @since 1.5
  3399      * @since 1.5
  3327      */
  3400      */
  3328     @Override
  3401     @Override
  3329     public void setReadTimeout(int timeout) {
  3402     public void setReadTimeout(int timeout) {
  3438          * @param   readlimit   the maximum limit of bytes that can be read before
  3511          * @param   readlimit   the maximum limit of bytes that can be read before
  3439          *                      the mark position becomes invalid.
  3512          *                      the mark position becomes invalid.
  3440          * @see     java.io.FilterInputStream#in
  3513          * @see     java.io.FilterInputStream#in
  3441          * @see     java.io.FilterInputStream#reset()
  3514          * @see     java.io.FilterInputStream#reset()
  3442          */
  3515          */
       
  3516         // safe to use synchronized here: super method is synchronized too
  3443         @Override
  3517         @Override
  3444         public synchronized void mark(int readlimit) {
  3518         public synchronized void mark(int readlimit) {
  3445             super.mark(readlimit);
  3519             super.mark(readlimit);
  3446             if (cacheRequest != null) {
  3520             if (cacheRequest != null) {
  3447                 marked = true;
  3521                 marked = true;
  3468          * @exception  IOException  if the stream has not been marked or if the
  3542          * @exception  IOException  if the stream has not been marked or if the
  3469          *               mark has been invalidated.
  3543          *               mark has been invalidated.
  3470          * @see        java.io.FilterInputStream#in
  3544          * @see        java.io.FilterInputStream#in
  3471          * @see        java.io.FilterInputStream#mark(int)
  3545          * @see        java.io.FilterInputStream#mark(int)
  3472          */
  3546          */
       
  3547         // safe to use synchronized here: super method is synchronized too
  3473         @Override
  3548         @Override
  3474         public synchronized void reset() throws IOException {
  3549         public synchronized void reset() throws IOException {
  3475             super.reset();
  3550             super.reset();
  3476             if (cacheRequest != null) {
  3551             if (cacheRequest != null) {
  3477                 marked = false;
  3552                 marked = false;