httpclient.java

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

JAVA
983
字号
     /*     * call super.openServer in a privileged block     */    private synchronized void privilegedSuperOpenServer(final String proxyHost,						        final int proxyPort)	throws IOException    {	try {	    java.security.AccessController.doPrivileged(		new java.security.PrivilegedExceptionAction() {		public Object run() throws IOException		{		    superOpenServer(proxyHost, proxyPort);		    return null;		}	    });	} catch (java.security.PrivilegedActionException pae) {	    throw (IOException) pae.getException();	}    }    /**     * Determines if the given host address is a loopback address or     * not. Any IP address starting with 127 is a loopback address     * although typically this is set to 127.0.0.1. A request for     * the address "localhost" will also be treated as loopback.     */    private boolean isLoopback(String host) {	if (host == null || host.length() == 0)	    return false;	if (host.equalsIgnoreCase("localhost"))	    return true;        if (!Character.isDigit(host.charAt(0))) {	    return false;	} else {	    /* The string (probably) represents a numerical IP address.	     * Parse it into int's. Compare the first int	     * component to 127 and return if it is not	     * 127. Otherwise, just make sure the rest of the	     * address is a valid address.	     */	    boolean firstInt = true;	    int hitDots = 0;	    char[] data = host.toCharArray();	    for(int i = 0; i < data.length; i++) {		char c = data[i];		if (c < 48 || c > 57) { // !digit		    return false;		}		int b = 0x00; // the value of one integer component		while(c != '.') {		    if (c < 48 || c > 57) { // !digit			return false;		    }		    b = b*10 + c - '0';		    if (++i >= data.length)			break;		    c = data[i];		}		if(b > 0xFF) { /* invalid - bigger than a byte */		    return false;		}		/* 		 * If the first integer component is not 127 we may		 * as well stop.		 */		if (firstInt) {		    firstInt = false;		    if (b != 0x7F)			return false;		}				hitDots++;	    }	    	    if(hitDots != 4 || host.endsWith(".")) {		return false;	    }	}	return true;    }    /*     */    protected synchronized void openServer() throws IOException {	SecurityManager security = System.getSecurityManager();	if (security != null) {	    security.checkConnect(host, port);	}	if (keepingAlive) { // already opened	    return;	}	/* Try to open connections in this order, return on the	 * first one that's successful:	 * 1) if (instProxy != null)	 *        connect to instProxy	 *        _raise_exception_ if failure	 *        usingProxy=true	 * 2) if (proxyHost != null) and !(proxyDisabled || host is on dontProxy list)	 *        connect to proxyHost;	 *        usingProxy=true;	 * 3) connect locally	 *    usingProxy = false;	 */	String urlHost = url.getHost().toLowerCase();	boolean loopback = isLoopback(urlHost);	if (url.getProtocol().equals("http") ||	    url.getProtocol().equals("https") ) {	    	    if ((instProxy != null) && !loopback) {		privilegedOpenServer(instProxy, instProxyPort);		usingProxy = true;		return;	    }	    String proxyHost = getProxyHost();	    if ((proxyHost != null) &&		(!(proxyDisabled ||		   loopback ||		   matchNonProxyHosts(urlHost) ||		   matchNonProxyHosts(host)))) {		try {		    int proxyPort = getProxyPort();		    privilegedOpenServer(proxyHost, proxyPort);		    instProxy = proxyHost;		    instProxyPort = proxyPort;		    usingProxy = true;		    return;		} catch (IOException e) {		    // continue in this case - try locally		}	    }	    // try locally - let Exception get raised	    openServer(host, port);	    usingProxy = false;	    return;	} else {	    /* we're opening some other kind of url, most likely an	     * ftp url. In this case:	     * 1) try instProxy (== FTP proxy)	     * 2) try HttpProxy	     * 3) directly	     */	    if ((instProxy != null) && !loopback) {		privilegedSuperOpenServer(instProxy, instProxyPort);		usingProxy = true;		return;	    }			    String proxyHost = getProxyHost();	    if ((proxyHost != null) &&		(!(proxyDisabled ||		   loopback ||		   matchNonProxyHosts(urlHost) ||		   matchNonProxyHosts(host)))) {		try {		    int proxyPort = getProxyPort();		    privilegedSuperOpenServer(proxyHost, proxyPort);		    instProxy = proxyHost;		    instProxyPort = proxyPort;		    usingProxy = true; 		    return;		} catch (IOException e) {		    // continue in this case - try locally		}	    }	    // try locally	    super.openServer(host, port);	    usingProxy = false;	    return;	}    }    public String getURLFile() throws IOException {	String fileName = url.getFile();	if ((fileName == null) || (fileName.length() == 0))	    fileName = "/";	if (usingProxy) {	    fileName = url.toExternalForm();	}	if (fileName.indexOf('\n') == -1)	    return fileName;	else	    throw new java.net.MalformedURLException("Illegal character in URL");    }    /**     * @deprecated      */    public void writeRequests(MessageHeader head) {	requests = head;	requests.print(serverOutput);	serverOutput.flush();    }    public void writeRequests(MessageHeader head, 			      PosterOutputStream pos) throws IOException {	requests = head;	requests.print(serverOutput);	poster = pos;	if (poster != null)	    poster.writeTo(serverOutput);	serverOutput.flush();    }    /** Parse the first line of the HTTP request.  It usually looks	something like: "HTTP/1.0 <number> comment\r\n". */    public boolean parseHTTP(MessageHeader responses, ProgressEntry pe)    throws IOException {	/* If "HTTP/*" is found in the beginning, return true.  Let         * HttpURLConnection parse the mime header itself.	 *	 * If this isn't valid HTTP, then we don't try to parse a header	 * out of the beginning of the response into the responses,	 * and instead just queue up the output stream to it's very beginning.	 * This seems most reasonable, and is what the NN browser does.	 */	try {	    serverInput = serverSocket.getInputStream();	    serverInput = new BufferedInputStream(serverInput);	    return (parseHTTPHeader(responses, pe));	} catch (IOException e) {	    closeServer();            if (!failedOnce && requests != null) {                // try once more		failedOnce = true;		openServer();		writeRequests(requests, poster);		return parseHTTP(responses, pe);	    } else {		throw e;	    }	}    }    public int setTimeout (int timeout) throws SocketException {	int old = serverSocket.getSoTimeout ();	serverSocket.setSoTimeout (timeout);	return old;    }    private boolean parseHTTPHeader(MessageHeader responses, ProgressEntry pe)    throws IOException {	/* If "HTTP/*" is found in the beginning, return true.  Let         * HttpURLConnection parse the mime header itself.	 *	 * If this isn't valid HTTP, then we don't try to parse a header	 * out of the beginning of the response into the responses,	 * and instead just queue up the output stream to it's very beginning.	 * This seems most reasonable, and is what the NN browser does.	 */	keepAliveConnections = -1;	keepAliveTimeout = 0;	boolean ret = false;	byte[] b = new byte[8];	try {	    int nread = 0;	    serverInput.mark(10);	    while (nread < 8) {		int r = serverInput.read(b, nread, 8 - nread);		if (r < 0) {		    break;		}		nread += r;	    }	    String keep=null;	    ret = b[0] == 'H' && b[1] == 'T'		    && b[2] == 'T' && b[3] == 'P' && b[4] == '/' &&		b[5] == '1' && b[6] == '.';	    serverInput.reset();	    if (ret) { // is valid HTTP - response started w/ "HTTP/1."		responses.parseHeader(serverInput);		/* decide if we're keeping alive:		 * Note:  There's a spec, but most current		 * servers (10/1/96) that support this differ in dialects.		 * If the server/client misunderstand each other, the		 * protocol should fall back onto HTTP/1.0, no keep-alive.		 */		if (usingProxy) { // not likely a proxy will return this		    keep = responses.findValue("Proxy-Connection");		}		if (keep == null) {		    keep = responses.findValue("Connection");		}		if (keep != null && keep.toLowerCase().equals("keep-alive")) {		    /* some servers, notably Apache1.1, send something like:		     * "Keep-Alive: timeout=15, max=1" which we should respect.		     */		    HeaderParser p = new HeaderParser(			    responses.findValue("Keep-Alive"));		    if (p != null) {			/* default should be larger in case of proxy */			keepAliveConnections = p.findInt("max", usingProxy?50:5);			keepAliveTimeout = p.findInt("timeout", usingProxy?60:5);		    }		} else if (b[7] != '0') {		    /*		     * We're talking 1.1 or later. Keep persistent until		     * the server says to close.		     */		    if (keep != null) {			/*			 * The only Connection token we understand is close.			 * Paranoia: if there is any Connection header then			 * treat as non-persistent.			 */		        keepAliveConnections = 1;		    } else {		        keepAliveConnections = 5;		    }		}	    } else if (nread != 8) {                if (!failedOnce && requests != null) {		    failedOnce = true;		    closeServer();		    openServer();		    writeRequests(requests, poster);		    return parseHTTP(responses, pe);		}		throw new SocketException("Unexpected end of file from server");	    } else {		// we can't vouche for what this is....		responses.set("Content-type", "unknown/unknown");	    }	} catch (IOException e) {	    throw e;	}	int code = -1;	try {	    String resp;	    resp = responses.getValue(0);            /* should have no leading/trailing LWS             * expedite the typical case by assuming it has             * form "HTTP/1.x <WS> 2XX <mumble>"             */            int ind;            ind = resp.indexOf(' ');            while(resp.charAt(ind) == ' ')                ind++;            code = Integer.parseInt(resp.substring(ind, ind + 3));	} catch (Exception e) {}	if (code == HTTP_CONTINUE) {	    responses.reset();	    return parseHTTPHeader(responses, pe);	}   	int cl = -1;	/*	 * Set things up to parse the entity body of the reply.	 * We should be smarter about avoid pointless work when	 * the HTTP method and response code indicate there will be	 * no entity body to parse.	 */	String te = null;	try {	    te = responses.findValue("Transfer-Encoding");	} catch (Exception e) {}	if (te != null && te.equalsIgnoreCase("chunked")) {	    serverInput = new ChunkedInputStream(serverInput, this, responses);	    /*  	     * If keep alive not specified then close after the stream	     * has completed.	     */	    if (keepAliveConnections < 0) {		keepAliveConnections = 1; 	    }	    keepingAlive = true;	    failedOnce = false;	} else {	    /* 	     * If it's a keep alive connection then we will keep 	     * (alive if :-	     * 1. content-length is specified, or 	     * 2. "Not-Modified" or "No-Content" responses - RFC 2616 states that  	     *    204 or 304 response must not include a message body. 	     */	    try {	        cl = Integer.parseInt(responses.findValue("content-length"));	    } catch (Exception e) {}	    if (keepAliveConnections > 1 && 		(cl >= 0 ||		 code == HttpURLConnection.HTTP_NOT_MODIFIED || 		 code == HttpURLConnection.HTTP_NO_CONTENT)) { 	        keepingAlive = true;	    } else if (keepingAlive) {	        /* Previously we were keeping alive, and now we're not.  Remove	         * this from the cache (but only here, once) - otherwise we get	         * multiple removes and the cache count gets messed up.	         */	        keepingAlive=false;	    }	}	/* finally wrap a KeepAlive/MeteredStream around it if appropriate */	if (cl > 0) {	    pe.setType(url.getFile(), responses.findValue("content-type"));	    pe.update(0, cl);	    if (isKeepingAlive()) {		serverInput = new KeepAliveStream(serverInput, pe, this);		failedOnce = false;	    } else {		serverInput = new MeteredStream(serverInput,pe);	    }	} else {	    ProgressData.pdata.unregister(pe);	}	return ret;    }    public synchronized InputStream getInputStream() {	return serverInput;    }    public OutputStream getOutputStream() {	return serverOutput;    }    public String toString() {	return getClass().getName()+"("+url+")";    }    public final boolean isKeepingAlive() {	return getHttpKeepAliveSet() && keepingAlive;    }    protected void finalize() throws Throwable {	// This should do nothing.  The stream finalizer will	// close the fd.    }    /* Use only on connections in error. */    public void closeServer() {	try {	    keepingAlive = false;	    serverSocket.close();	} catch (Exception e) {}    }    /**     * @return the proxy host being used for this client, or null     *		if we're not going through a proxy     */    public String getProxyHostUsed() {	if (!usingProxy) {	    return null;	} else {	    return instProxy;	}    }    /**     * @return the proxy port being used for this client.  Meaningless     *		if getProxyHostUsed() gives null.     */    public int getProxyPortUsed() {	return instProxyPort;    }}

⌨️ 快捷键说明

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