httpurlconnection.java

来自「This is a resource based on j2me embedde」· Java 代码 · 共 1,596 行 · 第 1/4 页

JAVA
1,596
字号
/* * @(#)HttpURLConnection.java	1.86 06/10/10 * * Copyright  1990-2008 Sun Microsystems, Inc. All Rights Reserved.   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER   *    * This program 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.    *    * This program 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 at /legal/license.txt).    *    * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa   * Clara, CA 95054 or visit www.sun.com if you need additional   * information or have any questions.  * */package sun.net.www.protocol.http;import java.net.URL;import java.net.URLConnection;import java.net.ProtocolException;import java.net.PasswordAuthentication;import java.net.Authenticator;import java.net.InetAddress;import java.net.UnknownHostException;import java.net.SocketTimeoutException;import java.io.*;import java.util.Date;import java.util.Map;import java.util.Locale;import java.util.StringTokenizer;import sun.net.*;import sun.net.www.*;import sun.net.www.http.HttpClient;import sun.net.www.http.PosterOutputStream;import sun.net.www.http.ChunkedInputStream;import java.text.SimpleDateFormat;import java.util.TimeZone;import java.net.MalformedURLException;/** * A class to represent an HTTP connection to a remote object. */public class HttpURLConnection extends java.net.HttpURLConnection {        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;    static {	maxRedirects = ((Integer)java.security.AccessController.doPrivileged(		new sun.security.action.GetIntegerAction("http.maxRedirects", 		defaultmaxRedirects))).intValue();	version = (String) java.security.AccessController.doPrivileged(                    new sun.security.action.GetPropertyAction("java.version"));	String agent = (String) java.security.AccessController.doPrivileged(		    new sun.security.action.GetPropertyAction("http.agent"));	if (agent == null) {	    agent = "Java/"+version;	} else {	    agent = agent + " Java/"+version;	}	userAgent = agent;	validateProxy = ((Boolean)java.security.AccessController.doPrivileged(		new sun.security.action.GetBooleanAction(		    "http.auth.digest.validateProxy"))).booleanValue();	validateServer = ((Boolean)java.security.AccessController.doPrivileged(		new sun.security.action.GetBooleanAction(		    "http.auth.digest.validateServer"))).booleanValue();    }    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"    };    protected HttpClient http;    protected Handler handler;    /* output stream to server */    protected PrintStream ps = null;    /* We only have a single static authenticator for now.     * For backwards compatibility with JDK 1.1.  Should be     * eliminated for JDK 2.0.     */    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 following two fields are only used with Digest Authentication */    String domain; 	/* The list of authentication domains */    DigestAuthentication.Parameters digestparams;    /* Current credentials in use */    AuthenticationInfo  currentProxyCredentials = null;    AuthenticationInfo  currentServerCredentials = null;    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 */    Object authObj;     /* Progress entry */    protected ProgressEntry pe;    /* 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;    /*     * privileged request password authentication      *     */    private static PasswordAuthentication     privilegedRequestPasswordAuthentication(					    final String host,					    final InetAddress addr,					    final int port,					    final String protocol,					    final String prompt,					    final String scheme) {	return (PasswordAuthentication)	    java.security.AccessController.doPrivileged( 		new java.security.PrivilegedAction() {		public Object run() {		    return Authenticator.requestPasswordAuthentication(				       host, addr, port, protocol, prompt, scheme);		}	    });    }    /*      * checks the validity of http message header and throws      * IllegalArgumentException if invalid.     */    private void checkMessageHeader(String key, String 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(LF, index);			continue;		    }		}		throw new IllegalArgumentException(		    "Illegal character(s) in message header value: " + value);	    }	}    }    /* 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	 */	if (!setRequests) {	    /* 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 (!failedOnce)		requests.prepend(method + " " + http.getURLFile()+" "  + 				 httpVersion, null);	    if (!getUseCaches()) {		requests.setIfNotSet ("Cache-Control", "no-cache");		requests.setIfNotSet ("Pragma", "no-cache");	    }	    requests.setIfNotSet("User-Agent", userAgent);	    int port = url.getPort();	    String host = url.getHost();	    if (port != -1 && port != 80) {		host += ":" + String.valueOf(port);	    }	    requests.setIfNotSet("Host", host);	    requests.setIfNotSet("Accept", acceptString);	    /*	     * 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 (!failedOnce && http.getHttpKeepAliveSet()) {		if (http.usingProxy) {		    requests.setIfNotSet("Proxy-Connection", "keep-alive");		} else {		    requests.setIfNotSet("Connection", "keep-alive");		}	    } 	    // send any pre-emptive authentication	    if (http.usingProxy) {		setPreemptiveProxyAuthentication(requests);	    }            // 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'", Locale.US);		fo.setTimeZone(TimeZone.getTimeZone("GMT"));                requests.setIfNotSet("If-Modified-Since", fo.format(date));            }	    // check for preemptive authorization	    AuthenticationInfo sauth = AuthenticationInfo.getServerAuth(url);	    if (sauth != null && sauth.supportsPreemptiveAuthorization() ) {		// Sets "Authorization"		requests.setIfNotSet(sauth.getHeaderName(), sauth.getHeaderValue(url,method));		currentServerCredentials = sauth;	    }	    if (poster != null) {		/* add Content-Length & POST/PUT data */		synchronized (poster) {		    /* close it, so no more data can be added */		    poster.close();		    if (!method.equals("PUT")) {			String type = "application/x-www-form-urlencoded";			requests.setIfNotSet("Content-Type", type);		    }		    requests.set("Content-Length", 				 String.valueOf(poster.size()));		}	    }	    setRequests=true;	}	http.writeRequests(requests, poster);	if (ps.checkError()) {	    String proxyHost = http.getProxyHostUsed();	    int proxyPort = http.getProxyPortUsed();	    disconnectInternal();	    if (failedOnce) {		throw new IOException("Error writing to server");	    } else { // try once more		failedOnce=true;		if (proxyHost != null) {		    setProxiedClient(url, proxyHost, proxyPort);		} else {		    setNewClient (url);		}		ps = (PrintStream) http.getOutputStream();		connected=true;		responses = new MessageHeader();		setRequests=false;		writeRequests();	    }	}    }    /**     * Create a new HttpClient object, bypassing the cache of     * HTTP client objects/connections.     *     * @param url	the URL being accessed     */    protected void setNewClient (URL url)    throws IOException {	setNewClient(url, false);    }    /**     * Obtain a HttpsClient object. Use the cached copy if specified.      *     * @param url       the URL being accessed     * @param useCache  whether the cached connection should be used     *        if present     */    protected void setNewClient (URL url, boolean useCache)	throws IOException {	http = HttpClient.New(url, useCache);    }    /**     * 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.     *     * @param url	the URL being accessed     * @param proxyHost	the proxy host to use     * @param proxyPort	the proxy port to use     */    protected void setProxiedClient (URL url, String proxyHost, int proxyPort)    throws IOException {	setProxiedClient(url, proxyHost, proxyPort, false);     }    /**     * 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.     *     * @param url       the URL being accessed     * @param proxyHost the proxy host to use     * @param proxyPort the proxy port to use     * @param useCache  whether the cached connection should be used     *        if present     */    protected void setProxiedClient (URL url,					   String proxyHost, int proxyPort,					   boolean useCache)	throws IOException {	proxiedConnect(url, proxyHost, proxyPort, useCache);    }    protected void proxiedConnect(URL url,					   String proxyHost, int proxyPort,					   boolean useCache)	throws IOException {	SecurityManager security = System.getSecurityManager(); 	if (security != null) { 	    security.checkConnect(proxyHost, proxyPort); 	}	http = HttpClient.New (url, proxyHost, proxyPort, useCache);    }    protected HttpURLConnection(URL u, Handler handler)    throws IOException {	super(u);	requests = new MessageHeader();	responses = new MessageHeader();

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?