Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
   /*
    * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    *
    * This code is free software; you can redistribute it and/or modify it
    * under the terms of the GNU General Public License version 2 only, as
    * published by the Free Software Foundation.  Oracle designates this
    * particular file as subject to the "Classpath" exception as provided
    * by Oracle in the LICENSE file that accompanied this code.
   *
   * This code is distributed in the hope that it will be useful, but WITHOUT
   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   * version 2 for more details (a copy is included in the LICENSE file that
   * accompanied this code).
   *
   * You should have received a copy of the GNU General Public License version
   * 2 along with this work; if not, write to the Free Software Foundation,
   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   *
   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   * or visit www.oracle.com if you need additional information or have any
   * questions.
   */
  
  package sun.net.www.protocol.http;
  
  import java.util.Arrays;
  import java.net.URL;
  import java.net.Proxy;
  import java.net.URI;
  import java.io.*;
  import java.net.*;
  import java.util.Date;
  import java.util.Map;
  import java.util.List;
  import java.util.Locale;
  import java.util.HashSet;
  import java.util.HashMap;
  import java.util.Set;
  import sun.net.*;
  import sun.net.www.*;
  import static sun.net.www.protocol.http.AuthScheme.BASIC;
  import static sun.net.www.protocol.http.AuthScheme.DIGEST;
  import static sun.net.www.protocol.http.AuthScheme.NTLM;
  import static sun.net.www.protocol.http.AuthScheme.NEGOTIATE;
  import static sun.net.www.protocol.http.AuthScheme.KERBEROS;
  import static sun.net.www.protocol.http.AuthScheme.UNKNOWN;

A class to represent an HTTP connection to a remote object.
  
  
  
  public class HttpURLConnection extends java.net.HttpURLConnection {
  
      static String HTTP_CONNECT = "CONNECT";
  
      static final String version;
      public static final String userAgent;
  
      /* max # of allowed re-directs */
      static final int defaultmaxRedirects = 20;
      static final int maxRedirects;
 
     /* Not all servers support the (Proxy)-Authentication-Info headers.
      * By default, we don't require them to be sent
      */
     static final boolean validateProxy;
     static final boolean validateServer;
 
     private final static String RETRY_MSG1 =
         "cannot retry due to proxy authentication, in streaming mode";
     private final static String RETRY_MSG2 =
         "cannot retry due to server authentication, in streaming mode";
     private final static String RETRY_MSG3 =
         "cannot retry due to redirection, in streaming mode";
 
     /*
      * System properties related to error stream handling:
      *
      * sun.net.http.errorstream.enableBuffering = <boolean>
      *
      * With the above system property set to true (default is false),
      * when the response code is >=400, the HTTP handler will try to
      * buffer the response body (up to a certain amount and within a
      * time limit). Thus freeing up the underlying socket connection
      * for reuse. The rationale behind this is that usually when the
      * server responds with a >=400 error (client error or server
      * error, such as 404 file not found), the server will send a
      * small response body to explain who to contact and what to do to
      * recover. With this property set to true, even if the
      * application doesn't call getErrorStream(), read the response
      * body, and then call close(), the underlying socket connection
      * can still be kept-alive and reused. The following two system
      * properties provide further control to the error stream
      * buffering behaviour.
      *
      * sun.net.http.errorstream.timeout = <int>
      *     the timeout (in millisec) waiting the error stream
      *     to be buffered; default is 300 ms
      *
      * sun.net.http.errorstream.bufferSize = <int>
      *     the size (in bytes) to use for the buffering the error stream;
      *     default is 4k
      */
 
 
     /* Should we enable buffering of error streams? */
     private static boolean enableESBuffer = false;
 
     /* timeout waiting for read for buffered error stream;
      */
     private static int timeout4ESBuffer = 0;
 
     /* buffer size for buffered error stream;
     */
     private static int bufSize4ES = 0;
 
     /*
      * Restrict setting of request headers through the public api
      * consistent with JavaScript XMLHttpRequest2 with a few
      * exceptions. Disallowed headers are silently ignored for
      * backwards compatibility reasons rather than throwing a
      * SecurityException. For example, some applets set the
      * Host header since old JREs did not implement HTTP 1.1.
      * Additionally, any header starting with Sec- is
      * disallowed.
      *
      * The following headers are allowed for historical reasons:
      *
      * Accept-Charset, Accept-Encoding, Cookie, Cookie2, Date,
      * Referer, TE, User-Agent, headers beginning with Proxy-.
      *
      * The following headers are allowed in a limited form:
      *
      * Connection: close
      *
      * See http://www.w3.org/TR/XMLHttpRequest2.
      */
     private static final boolean allowRestrictedHeaders;
     private static final Set<StringrestrictedHeaderSet;
     private static final String[] restrictedHeaders = {
         /* Restricted by XMLHttpRequest2 */
         //"Accept-Charset",
         //"Accept-Encoding",
         "Access-Control-Request-Headers",
         "Access-Control-Request-Method",
         "Connection"/* close is allowed */
         "Content-Length",
         //"Cookie",
         //"Cookie2",
         "Content-Transfer-Encoding",
         //"Date",
         //"Expect",
         "Host",
         "Keep-Alive",
         "Origin",
         // "Referer",
         // "TE",
         "Trailer",
         "Transfer-Encoding",
         "Upgrade",
         //"User-Agent",
         "Via"
     };
 
     static {
          = java.security.AccessController.doPrivileged(
             new sun.security.action.GetIntegerAction(
                 "http.maxRedirects")).intValue();
          = java.security.AccessController.doPrivileged(
                     new sun.security.action.GetPropertyAction("java.version"));
         String agent = java.security.AccessController.doPrivileged(
                     new sun.security.action.GetPropertyAction("http.agent"));
         if (agent == null) {
             agent = "Java/"+;
         } else {
             agent = agent + " Java/"+;
         }
          = agent;
          = java.security.AccessController.doPrivileged(
                 new sun.security.action.GetBooleanAction(
                     "http.auth.digest.validateProxy")).booleanValue();
          = java.security.AccessController.doPrivileged(
                 new sun.security.action.GetBooleanAction(
                     "http.auth.digest.validateServer")).booleanValue();
 
          = java.security.AccessController.doPrivileged(
                 new sun.security.action.GetBooleanAction(
                     "sun.net.http.errorstream.enableBuffering")).booleanValue();
          = java.security.AccessController.doPrivileged(
                 new sun.security.action.GetIntegerAction(
                     "sun.net.http.errorstream.timeout", 300)).intValue();
         if ( <= 0) {
              = 300; // use the default
         }
 
          = java.security.AccessController.doPrivileged(
                 new sun.security.action.GetIntegerAction(
                     "sun.net.http.errorstream.bufferSize", 4096)).intValue();
         if ( <= 0) {
              = 4096; // use the default
         }
 
          = java.security.AccessController.doPrivileged(
                 new sun.security.action.GetBooleanAction(
                     "sun.net.http.allowRestrictedHeaders")).booleanValue();
         if (!) {
              = new HashSet<String>(.);
             for (int i=0; i < .i++) {
                 .add([i].toLowerCase());
             }
         } else {
              = null;
         }
     }
 
     static final String httpVersion = "HTTP/1.1";
     static final String acceptString =
         "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2";
 
     // the following http request headers should NOT have their values
     // returned for security reasons.
     private static final String[] EXCLUDE_HEADERS = {
             "Proxy-Authorization",
             "Authorization"
     };
 
     // also exclude system cookies when any might be set
     private static final String[] EXCLUDE_HEADERS2= {
             "Proxy-Authorization",
             "Authorization",
             "Cookie",
             "Cookie2"
     };
 
     protected HttpClient http;
     protected Handler handler;
     protected Proxy instProxy;
 
     private CookieHandler cookieHandler;
     private final ResponseCache cacheHandler;
 
     // the cached response, and cached response headers and body
     protected CacheResponse cachedResponse;
     private MessageHeader cachedHeaders;
     private InputStream cachedInputStream;
 
     /* output stream to server */
     protected PrintStream ps = null;
 
 
     /* buffered error stream */
     private InputStream errorStream = null;
 
     /* User set Cookies */
     private boolean setUserCookies = true;
     private String userCookies = null;
     private String userCookies2 = null;
 
     /* We only have a single static authenticator for now.
      * REMIND:  backwards compatibility with JDK 1.1.  Should be
      * eliminated for JDK 2.0.
      */
     @Deprecated
     private static HttpAuthenticator defaultAuth;
 
     /* all the headers we send
      * NOTE: do *NOT* dump out the content of 'requests' in the
      * output or stacktrace since it may contain security-sensitive
      * headers such as those defined in EXCLUDE_HEADERS.
      */
     private MessageHeader requests;
 
     /* The headers actually set by the user are recorded here also
      */
     private MessageHeader userHeaders;
 
     /* Headers and request method cannot be changed
      * once this flag is set in :-
      *     - getOutputStream()
      *     - getInputStream())
      *     - connect()
      * Access synchronized on this.
      */
     private boolean connecting = false;
 
     /* The following two fields are only used with Digest Authentication */
     String domain;      /* The list of authentication domains */
 
     /* Current credentials in use */
     boolean             needToCheck = true;
     private boolean doingNTLM2ndStage = false/* doing the 2nd stage of an NTLM server authentication */
     private boolean doingNTLMp2ndStage = false/* doing the 2nd stage of an NTLM proxy authentication */
 
     /* try auth without calling Authenticator. Used for transparent NTLM authentication */
     private boolean tryTransparentNTLMServer = true;
     private boolean tryTransparentNTLMProxy = true;
     private boolean useProxyResponseCode = false;
 
     /* Used by Windows specific code */
     private Object authObj;
 
     /* Set if the user is manually setting the Authorization or Proxy-Authorization headers */
     boolean isUserServerAuth;
     boolean isUserProxyAuth;
 
 
     /* Progress source */
     protected ProgressSource pi;
 
     /* all the response headers we get back */
     private MessageHeader responses;
     /* the stream _from_ the server */
     private InputStream inputStream = null;
     /* post stream _to_ the server, if any */
     private PosterOutputStream poster = null;
 
     /* Indicates if the std. request headers have been set in requests. */
     private boolean setRequests=false;
 
     /* Indicates whether a request has already failed or not */
     private boolean failedOnce=false;
 
     /* Remembered Exception, we will throw it again if somebody
        calls getInputStream after disconnect */
     private Exception rememberedException = null;
 
     /* If we decide we want to reuse a client, we put it here */
     private HttpClient reuseClient = null;
 
     /* Tunnel states */
     public enum TunnelState {
         /* No tunnel */
         NONE,
 
         /* Setting up a tunnel */
         SETUP,
 
         /* Tunnel has been successfully setup */
         TUNNELING
     }
 
     private TunnelState tunnelState = .;
 
     /* Redefine timeouts from java.net.URLConnection as we need -1 to mean
      * not set. This is to ensure backward compatibility.
      */
 
     /* A permission converted from a URLPermission */
 
     /* Logging support */
     private static final PlatformLogger logger =
             PlatformLogger.getLogger("sun.net.www.protocol.http.HttpURLConnection");
 
     /*
      * privileged request password authentication
      *
      */
     private static PasswordAuthentication
                             final String host,
                             final InetAddress addr,
                             final int port,
                             final String protocol,
                             final String prompt,
                             final String scheme,
                             final URL url,
                             final RequestorType authType) {
         return java.security.AccessController.doPrivileged(
             new java.security.PrivilegedAction<PasswordAuthentication>() {
                 public PasswordAuthentication run() {
                     if (.isLoggable(..)) {
                         .finest("Requesting Authentication: host =" + host + " url = " + url);
                     }
                     PasswordAuthentication pass = Authenticator.requestPasswordAuthentication(
                         hostaddrportprotocol,
                         promptschemeurlauthType);
                     if (.isLoggable(..)) {
                         .finest("Authentication returned: " + (pass != null ? pass.toString() : "null"));
                     }
                     return pass;
                 }
             });
     }
 
     private boolean isRestrictedHeader(String keyString value) {
         if () {
             return false;
         }
 
         key = key.toLowerCase();
         if (.contains(key)) {
             /*
              * Exceptions to restricted headers:
              *
              * Allow "Connection: close".
              */
             if (key.equals("connection") && value.equalsIgnoreCase("close")) {
                 return false;
             }
             return true;
         } else if (key.startsWith("sec-")) {
             return true;
         }
         return false;
     }
 
     /*
      * Checks the validity of http message header and whether the header
      * is restricted and throws IllegalArgumentException if invalid or
      * restricted.
      */
     private boolean isExternalMessageHeaderAllowed(String keyString value) {
         checkMessageHeader(keyvalue);
         if (!isRestrictedHeader(keyvalue)) {
             return true;
         }
         return false;
     }
 
     /* Logging support */
     public static PlatformLogger getHttpLogger() {
         return ;
     }
 
     /* Used for Windows NTLM implementation */
     public Object authObj() {
         return ;
     }
 
     public void authObj(Object authObj) {
         this. = authObj;
     }
 
     /*
      * checks the validity of http message header and throws
      * IllegalArgumentException if invalid.
      */
     private void checkMessageHeader(String keyString value) {
         char LF = '\n';
         int index = key.indexOf(LF);
         if (index != -1) {
             throw new IllegalArgumentException(
                 "Illegal character(s) in message header field: " + key);
         }
         else {
             if (value == null) {
                 return;
             }
 
             index = value.indexOf(LF);
             while (index != -1) {
                 index++;
                 if (index < value.length()) {
                     char c = value.charAt(index);
                     if ((c==' ') || (c=='\t')) {
                         // ok, check the next occurrence
                         index = value.indexOf(LFindex);
                         continue;
                     }
                 }
                 throw new IllegalArgumentException(
                     "Illegal character(s) in message header value: " + value);
             }
         }
     }
 
     public synchronized void setRequestMethod(String method)
                         throws ProtocolException {
         if () {
             throw new IllegalStateException("connect in progress");
         }
         super.setRequestMethod(method);
     }
 
     /* adds the standard key/val pairs to reqests if necessary & write to
      * given PrintStream
      */
     private void writeRequests() throws IOException {
         /* print all message headers in the MessageHeader
          * onto the wire - all the ones we've set and any
          * others that have been set
          */
         // send any pre-emptive authentication
         if (. && tunnelState() != .) {
             setPreemptiveProxyAuthentication();
         }
         if (!) {
 
             /* We're very particular about the order in which we
              * set the request headers here.  The order should not
              * matter, but some careless CGI programs have been
              * written to expect a very particular order of the
              * standard headers.  To name names, the order in which
              * Navigator3.0 sends them.  In particular, we make *sure*
              * to send Content-type: <> and Content-length:<> second
              * to last and last, respectively, in the case of a POST
              * request.
              */
             if (!) {
                 checkURLFile();
                 .prepend( + " " + getRequestURI()+" "  +
                                  null);
             }
             if (!getUseCaches()) {
                 .setIfNotSet ("Cache-Control""no-cache");
                 .setIfNotSet ("Pragma""no-cache");
             }
             .setIfNotSet("User-Agent");
             int port = .getPort();
             String host = .getHost();
             if (port != -1 && port != .getDefaultPort()) {
                 host += ":" + String.valueOf(port);
             }
             String reqHost = .findValue("Host");
             if (reqHost == null ||
                 (!reqHost.equalsIgnoreCase(host) && !checkSetHost()))
             {
                 .set("Host"host);
             }
             .setIfNotSet("Accept");
 
             /*
              * For HTTP/1.1 the default behavior is to keep connections alive.
              * However, we may be talking to a 1.0 server so we should set
              * keep-alive just in case, except if we have encountered an error
              * or if keep alive is disabled via a system property
              */
 
             // Try keep-alive only on first attempt
             if (! && .getHttpKeepAliveSet()) {
                 if (. && tunnelState() != .) {
                     .setIfNotSet("Proxy-Connection""keep-alive");
                 } else {
                     .setIfNotSet("Connection""keep-alive");
                 }
             } else {
                 /*
                  * RFC 2616 HTTP/1.1 section 14.10 says:
                  * HTTP/1.1 applications that do not support persistent
                  * connections MUST include the "close" connection option
                  * in every message
                  */
                 .setIfNotSet("Connection""close");
             }
             // Set modified since if necessary
             long modTime = getIfModifiedSince();
             if (modTime != 0 ) {
                 Date date = new Date(modTime);
                 //use the preferred date format according to RFC 2068(HTTP1.1),
                 // RFC 822 and RFC 1123
                 SimpleDateFormat fo =
                   new SimpleDateFormat ("EEE, dd MMM yyyy HH:mm:ss 'GMT'".);
                 fo.setTimeZone(TimeZone.getTimeZone("GMT"));
                 .setIfNotSet("If-Modified-Since"fo.format(date));
             }
             // check for preemptive authorization
             AuthenticationInfo sauth = AuthenticationInfo.getServerAuth();
             if (sauth != null && sauth.supportsPreemptiveAuthorization() ) {
                 // Sets "Authorization"
                 .setIfNotSet(sauth.getHeaderName(), sauth.getHeaderValue(,));
                  = sauth;
             }
 
             if (!.equals("PUT") && ( != null || streaming())) {
                 .setIfNotSet ("Content-type",
                         "application/x-www-form-urlencoded");
             }
 
             boolean chunked = false;
 
             if (streaming()) {
                 if ( != -1) {
                     .set ("Transfer-Encoding""chunked");
                     chunked = true;
                 } else { /* fixed content length */
                     if ( != -1) {
                         .set ("Content-Length",
                                       String.valueOf());
                     } else if ( != -1) {
                         .set ("Content-Length",
                                       String.valueOf());
                     }
                 }
             } else if ( != null) {
                 /* add Content-Length & POST/PUT data */
                 synchronized () {
                     /* close it, so no more data can be added */
                     .close();
                     .set("Content-Length",
                                  String.valueOf(.size()));
                 }
             }
 
             if (!chunked) {
                 if (.findValue("Transfer-Encoding") != null) {
                     .remove("Transfer-Encoding");
                     if (.isLoggable(..)) {
                         .warning(
                             "use streaming mode for chunked encoding");
                     }
                 }
             }
 
             // get applicable cookies based on the uri and request headers
             // add them to the existing request headers
             setCookieHeader();
 
             =true;
         }
         if (.isLoggable(..)) {
             .fine(.toString());
         }
         .writeRequests(streaming());
         if (.checkError()) {
             String proxyHost = .getProxyHostUsed();
             int proxyPort = .getProxyPortUsed();
             disconnectInternal();
             if () {
                 throw new IOException("Error writing to server");
             } else { // try once more
                 =true;
                 if (proxyHost != null) {
                     setProxiedClient(proxyHostproxyPort);
                 } else {
                     setNewClient ();
                 }
                  = (PrintStream.getOutputStream();
                 =true;
                  = new MessageHeader();
                 =false;
                 writeRequests();
             }
         }
     }
 
     private boolean checkSetHost() {
         SecurityManager s = System.getSecurityManager();
         if (s != null) {
             String name = s.getClass().getName();
             if (name.equals("sun.plugin2.applet.AWTAppletSecurityManager") ||
                 name.equals("sun.plugin2.applet.FXAppletSecurityManager") ||
                 name.equals("com.sun.javaws.security.JavaWebStartSecurity") ||
                 name.equals("sun.plugin.security.ActivatorSecurityManager"))
             {
                 int CHECK_SET_HOST = -2;
                 try {
                     s.checkConnect(.toExternalForm(), CHECK_SET_HOST);
                 } catch (SecurityException ex) {
                     return false;
                 }
             }
         }
         return true;
     }
 
     private void checkURLFile() {
         SecurityManager s = System.getSecurityManager();
         if (s != null) {
             String name = s.getClass().getName();
             if (name.equals("sun.plugin2.applet.AWTAppletSecurityManager") ||
                 name.equals("sun.plugin2.applet.FXAppletSecurityManager") ||
                 name.equals("com.sun.javaws.security.JavaWebStartSecurity") ||
                 name.equals("sun.plugin.security.ActivatorSecurityManager"))
             {
                 int CHECK_SUBPATH = -3;
                 try {
                     s.checkConnect(.toExternalForm(), CHECK_SUBPATH);
                 } catch (SecurityException ex) {
                     throw new SecurityException("denied access outside a permitted URL subpath"ex);
                 }
             }
         }
     }

    
Create a new HttpClient object, bypassing the cache of HTTP client objects/connections.

Parameters:
url the URL being accessed
 
     protected void setNewClient (URL url)
     throws IOException {
         setNewClient(urlfalse);
     }

    
Obtain a HttpsClient object. Use the cached copy if specified.

Parameters:
url the URL being accessed
useCache whether the cached connection should be used if present
 
     protected void setNewClient (URL urlboolean useCache)
         throws IOException {
          = HttpClient.New(urlnull, -1, useCachethis);
         .setReadTimeout();
     }


    
Create a new HttpClient object, set up so that it uses per-instance proxying to the given HTTP proxy. This bypasses the cache of HTTP client objects/connections.

Parameters:
url the URL being accessed
proxyHost the proxy host to use
proxyPort the proxy port to use
 
     protected void setProxiedClient (URL urlString proxyHostint proxyPort)
     throws IOException {
         setProxiedClient(urlproxyHostproxyPortfalse);
     }

    
Obtain a HttpClient object, set up so that it uses per-instance proxying to the given HTTP proxy. Use the cached copy of HTTP client objects/connections if specified.

Parameters:
url the URL being accessed
proxyHost the proxy host to use
proxyPort the proxy port to use
useCache whether the cached connection should be used if present
 
     protected void setProxiedClient (URL url,
                                            String proxyHostint proxyPort,
                                            boolean useCache)
         throws IOException {
         proxiedConnect(urlproxyHostproxyPortuseCache);
     }
 
     protected void proxiedConnect(URL url,
                                            String proxyHostint proxyPort,
                                            boolean useCache)
         throws IOException {
          = HttpClient.New (urlproxyHostproxyPortuseCache,
             this);
         .setReadTimeout();
     }
 
     protected HttpURLConnection(URL uHandler handler)
     throws IOException {
         // we set proxy == null to distinguish this case with the case
         // when per connection proxy is set
         this(unullhandler);
     }
 
     public HttpURLConnection(URL uString hostint port) {
         this(unew Proxy(.., InetSocketAddress.createUnresolved(hostport)));
     }

    
this constructor is used by other protocol handlers such as ftp that want to use http to fetch urls on their behalf
 
     public HttpURLConnection(URL uProxy p) {
         this(upnew Handler());
     }
 
     protected HttpURLConnection(URL uProxy pHandler handler) {
         super(u);
          = new MessageHeader();
          = new MessageHeader();
          = new MessageHeader();
         this. = handler;
          = p;
         if ( instanceof sun.net.ApplicationProxy) {
             /* Application set Proxies should not have access to cookies
              * in a secure environment unless explicitly allowed. */
             try {
                  = CookieHandler.getDefault();
             } catch (SecurityException se) { /* swallow exception */ }
         } else {
              = java.security.AccessController.doPrivileged(
                 new java.security.PrivilegedAction<CookieHandler>() {
                 public CookieHandler run() {
                     return CookieHandler.getDefault();
                 }
             });
         }
          = java.security.AccessController.doPrivileged(
             new java.security.PrivilegedAction<ResponseCache>() {
                 public ResponseCache run() {
                 return ResponseCache.getDefault();
             }
         });
     }

    

Deprecated.:
Use java.net.Authenticator.setDefault() instead.
 
     @Deprecated
     public static void setDefaultAuthenticator(HttpAuthenticator a) {
          = a;
     }

    
opens a stream allowing redirects only to the same host.
 
         throws IOException
     {
         boolean redir;
         int redirects = 0;
         InputStream in;
 
         do {
             if (c instanceof HttpURLConnection) {
                 ((HttpURLConnectionc).setInstanceFollowRedirects(false);
             }
 
             // We want to open the input stream before
             // getting headers, because getHeaderField()
             // et al swallow IOExceptions.
             in = c.getInputStream();
             redir = false;
 
             if (c instanceof HttpURLConnection) {
                 HttpURLConnection http = (HttpURLConnectionc;
                 int stat = http.getResponseCode();
                 if (stat >= 300 && stat <= 307 && stat != 306 &&
                         stat != .) {
                     URL base = http.getURL();
                     String loc = http.getHeaderField("Location");
                     URL target = null;
                     if (loc != null) {
                         target = new URL(baseloc);
                     }
                     http.disconnect();
                     if (target == null
                         || !base.getProtocol().equals(target.getProtocol())
                         || base.getPort() != target.getPort()
                         || !hostsEqual(basetarget)
                         || redirects >= 5)
                     {
                         throw new SecurityException("illegal URL redirect");
                     }
                     redir = true;
                     c = target.openConnection();
                     redirects++;
                 }
             }
         } while (redir);
         return in;
     }
 
 
     //
     // Same as java.net.URL.hostsEqual
     //
     private static boolean hostsEqual(URL u1URL u2) {
         final String h1 = u1.getHost();
         final String h2 = u2.getHost();
 
         if (h1 == null) {
             return h2 == null;
         } else if (h2 == null) {
             return false;
         } else if (h1.equalsIgnoreCase(h2)) {
             return true;
         }
         // Have to resolve addresses before comparing, otherwise
         // names like tachyon and tachyon.eng would compare different
         final boolean result[] = {false};
 
         java.security.AccessController.doPrivileged(
             new java.security.PrivilegedAction<Void>() {
                 public Void run() {
                 try {
                     InetAddress a1 = InetAddress.getByName(h1);
                     InetAddress a2 = InetAddress.getByName(h2);
                     result[0] = a1.equals(a2);
                 } catch(UnknownHostException | SecurityException e) {
                 }
                 return null;
             }
         });
 
         return result[0];
     }
 
     // overridden in HTTPS subclass
 
     public void connect() throws IOException {
         synchronized (this) {
              = true;
         }
         plainConnect();
     }
 
     private boolean checkReuseConnection () {
         if () {
             return true;
         }
         if ( != null) {
              = ;
             .setReadTimeout(getReadTimeout());
             . = false;
              = null;
              = true;
             return true;
         }
         return false;
     }
 
     private String getHostAndPort(URL url) {
         String host = url.getHost();
         final String hostarg = host;
         try {
             // lookup hostname and use IP address if available
             host = AccessController.doPrivileged(
                 new PrivilegedExceptionAction<String>() {
                     public String run() throws IOException {
                             InetAddress addr = InetAddress.getByName(hostarg);
                             return addr.getHostAddress();
                     }
                 }
             );
         } catch (PrivilegedActionException e) {}
         int port = url.getPort();
         if (port == -1) {
             String scheme = url.getProtocol();
             if ("http".equals(scheme)) {
                 return host + ":80";
             } else { // scheme must be https
                 return host + ":443";
             }
         }
         return host + ":" + Integer.toString(port);
     }
 
     protected void plainConnect()  throws IOException {
         synchronized (this) {
             if () {
                 return;
             }
         }
         SocketPermission p = URLtoSocketPermission(this.);
         if (p != null) {
             try {
                 AccessController.doPrivileged(
                     new PrivilegedExceptionAction<Void>() {
                         public Void run() throws IOException {
                             plainConnect0();
                             return null;
                         }
                     }, nullp
                 );
             } catch (PrivilegedActionException e) {
                     throw (IOExceptione.getException();
             }
         } else {
             // run without additional permission
             plainConnect0();
         }
    }

    
if the caller has a URLPermission for connecting to the given URL, then return a SocketPermission which permits access to that destination. Return null otherwise. The permission is cached in a field (which can only be changed by redirects)
        if ( != null) {
            return ;
        }
        SecurityManager sm = System.getSecurityManager();
        if (sm == null) {
            return null;
        }
        // the permission, which we might grant
        SocketPermission newPerm = new SocketPermission(
            getHostAndPort(url), "connect"
        );
        String actions = getRequestMethod()+":" +
                getUserSetHeaders().getHeaderNamesInList();
        String urlstring = url.getProtocol() + "://" + url.getAuthority()
                + url.getPath();
        URLPermission p = new URLPermission(urlstringactions);
        try {
            sm.checkPermission(p);
             = newPerm;
            return ;
        } catch (SecurityException e) {
            // fall thru
        }
        return null;
    }
    protected void plainConnect0()  throws IOException {
        // try to see if request can be served from local cache
        if ( != null && getUseCaches()) {
            try {
                URI uri = ParseUtil.toURI();
                if (uri != null) {
                     = .get(urigetRequestMethod(), getUserSetHeaders().getHeaders());
                    if ("https".equalsIgnoreCase(uri.getScheme())
                        && !( instanceof SecureCacheResponse)) {
                         = null;
                    }
                    if (.isLoggable(..)) {
                        .finest("Cache Request for " + uri + " / " + getRequestMethod());
                        .finest("From cache: " + ( != null ? .toString() : "null"));
                    }
                    if ( != null) {
                         = mapToMessageHeader(.getHeaders());
                         = .getBody();
                    }
                }
            } catch (IOException ioex) {
                // ignore and commence normal connection
            }
            if ( != null &&  != null) {
                 = true;
                return;
            } else {
                 = null;
            }
        }
        try {
            /* Try to open connections using the following scheme,
             * return on the first one that's successful:
             * 1) if (instProxy != null)
             *        connect to instProxy; raise exception if failed
             * 2) else use system default ProxySelector
             * 3) is 2) fails, make direct connection
             */
            if ( == null) { // no instance Proxy is set
                
Do we have to use a proxy?
                ProxySelector sel =
                    java.security.AccessController.doPrivileged(
                        new java.security.PrivilegedAction<ProxySelector>() {
                            public ProxySelector run() {
                                     return ProxySelector.getDefault();
                                 }
                             });
                if (sel != null) {
                    URI uri = sun.net.www.ParseUtil.toURI();
                    if (.isLoggable(..)) {
                        .finest("ProxySelector Request for " + uri);
                    }
                    Iterator<Proxyit = sel.select(uri).iterator();
                    Proxy p;
                    while (it.hasNext()) {
                        p = it.next();
                        try {
                            if (!) {
                                 = getNewHttpClient(p);
                                .setReadTimeout();
                            } else {
                                // make sure to construct new connection if first
                                // attempt failed
                                 = getNewHttpClient(pfalse);
                                .setReadTimeout();
                            }
                            if (.isLoggable(..)) {
                                if (p != null) {
                                    .finest("Proxy used: " + p.toString());
                                }
                            }
                            break;
                        } catch (IOException ioex) {
                            if (p != .) {
                                sel.connectFailed(urip.address(), ioex);
                                if (!it.hasNext()) {
                                    // fallback to direct connection
                                     = getNewHttpClient(nullfalse);
                                    .setReadTimeout();
                                    break;
                                }
                            } else {
                                throw ioex;
                            }
                            continue;
                        }
                    }
                } else {
                    // No proxy selector, create http client with no proxy
                    if (!) {
                         = getNewHttpClient(null);
                        .setReadTimeout();
                    } else {
                        // make sure to construct new connection if first
                        // attempt failed
                         = getNewHttpClient(nullfalse);
                        .setReadTimeout();
                    }
                }
            } else {
                if (!) {
                     = getNewHttpClient();
                    .setReadTimeout();
                } else {