url.java
来自「《移动Agent技术》一书的所有章节源代码。」· Java 代码 · 共 719 行 · 第 1/2 页
JAVA
719 行
/*
* @(#)URL.java 1.43 97/09/29
*
* Copyright (c) 1995, 1996 Sun Microsystems, Inc. All Rights Reserved.
*
* This software is the confidential and proprietary information of Sun
* Microsystems, Inc. ("Confidential Information"). You shall not
* disclose such Confidential Information and shall use it only in
* accordance with the terms of the license agreement you entered into
* with Sun.
*
* SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
* SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
* SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
* THIS SOFTWARE OR ITS DERIVATIVES.
*
* CopyrightVersion 1.1_beta
*
*/
package java.net;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Hashtable;
import java.util.StringTokenizer;
/**
* Class <code>URL</code> represents a Uniform Resource
* Locator, a pointer to a "resource" on the World
* Wide Web. A resource can be something as simple as a file or a
* directory, or it can be a reference to a more complicated object,
* such as a query to a database or to a search engine. More
* information on the types of URLs and their formats can be found at:
* <ul><code>
* http://www.ncsa.uiuc.edu/demoweb/url-primer.html
* </code></ul>
* <p>
* In general, a URL can be broken into several parts. The previous
* example of a URL indicates that the protocol to use is
* <code>http</code> (HyperText Transport Protocol) and that the
* information resides on a host machine named
* <code>www.ncsa.uiuc.edu</code>. The information on that host
* machine is named <code>demoweb/url-primer.html</code>. The exact
* meaning of this name on the host machine is both protocol
* dependent and host dependent. The information normally resides in
* a file, but it could be generated on the fly. This component of
* the URL is called the <i>file</i> component, even though the
* information is not necessarily in a file.
* <p>
* A URL can optionally specify a "port", which is the
* port number to which the TCP connection is made on the remote host
* machine. If the port is not specified, the default port for
* the protocol is used instead. For example, the default port for
* <code>http</code> is <code>80</code>. An alternative port could be
* specified as:
* <ul><code>
* http://www.ncsa.uiuc.edu:8080/demoweb/url-primer.html
* </code></ul>
* <p>
* A URL may have appended to it an "anchor", also known
* as a "ref" or a "reference". The anchor is
* indicated by the sharp sign character "#" followed by
* more characters. For example,
* <ul><code>
* http://java.sun.com/index.html#chapter1
* </code></ul>
* <p>
* This anchor is not technically part of the URL. Rather, it
* indicates that after the specified resource is retrieved, the
* application is specifically interested in that part of the
* document that has the tag <code>chapter1</code> attached to it. The
* meaning of a tag is resource specific.
* <p>
* An application can also specify a "relative URL",
* which contains only enough information to reach the resource
* relative to another URL. Relative URLs are frequently used within
* HTML pages. For example, if the contents of the URL:
* <ul><code>
* http://java.sun.com/index.html
* </code></ul>
* contained within it the relative URL:
* <ul><code>
* FAQ.html
* </code></ul>
* it would be a shorthand for:
* <ul><code>
* http://java.sun.com/FAQ.html
* </code></ul>
* <p>
* The relative URL need not specify all the components of a URL. If
* the protocol, host name, or port number is missing, the value is
* inherited from the fully specified URL. The file component must be
* specified. The optional anchor is not inherited.
*
* @author James Gosling
* @version 1.43, 09/29/97
* @since JDK1.0
*/
public final class URL implements java.io.Serializable {
/**
* The property which specifies the package prefix list to be scanned
* for protocol handlers. The value of this property (if any) should
* be a vertical bar delimited list of package names to search through
* for a protocol handler to load. The policy of this class is that
* all protocol handlers will be in a class called <protocolname>.Handler,
* and each package in the list is examined in turn for a matching
* handler. If none are found (or the property is not specified), the
* default package prefix, sun.net.www.protocol, is used. The search
* proceeds from the first package in the last to the last and stops
* when a match is found.
*/
private static final String protocolPathProp = "java.protocol.handler.pkgs";
/**
* The protocol to use (ftp, http, nntp, ... etc.) .
*/
private String protocol;
/**
* The host name in which to connect to.
*/
private String host;
/**
* The protocol port to connect to.
*/
private int port = -1;
/**
* The specified file name on that host.
*/
private String file;
/**
* # reference.
*/
private String ref;
/**
* The URLStreamHandler for this URL.
*/
transient URLStreamHandler handler;
/* Our hash code */
private int hashCode = -1;
/**
* Creates a <code>URL</code> object from the specified
* <code>protocol</code>, <code>host</code>, <code>port</code>
* number, and <code>file</code>. Specifying a <code>port</code>
* number of <code>-1</code> indicates that the URL should use
* the default port for the protocol.
* <p>
* If this is the first URL object being created with the specified
* protocol, a <i>stream protocol handler</i> object, an instance of
* class <code>URLStreamHandler</code>, is created for that protocol:
* <ol>
* <li>If the application has previously set up an instance of
* <code>URLStreamHandlerFactory</code> as the stream handler factory,
* then the <code>createURLStreamHandler</code> method of that instance
* is called with the protocol string as an argument to create the
* stream protocol handler.
* <li>If no <code>URLStreamHandlerFactory</code> has yet been set up,
* or if the factory's <code>createURLStreamHandler</code> method
* returns <code>null</code>, then the constructor finds the
* value of the system property:
* <ul><code>
* java.handler.protol.pkgs
* </code></ul>
* If the value of that system property is not <code>null</code>,
* it is interpreted as a list of packages separated by a vertical
* slash character '<code>|</code>'. The constructor tries to load
* the class named:
* <ul><code>
* <<i>package</i>>.<<i>protocol</i>>.Handler
* </code></ul>
* where <<i>package</i>> is replaced by the name of the package
* and <<i>protocol</i>> is replaced by the name of the protocol.
* If this class does not exist, or if the class exists but it is not
* a subclass of <code>URLStreamHandler</code>, then the next package
* in the list is tried.
* <li>If the previous step fails to find a protocol handler, then the
* constructor tries to load the class named:
* <ul><code>
* sun.net.www.protocol.<<i>protocol</i>>.Handler
* </code></ul>
* If this class does not exist, or if the class exists but it is not a
* subclass of <code>URLStreamHandler</code>, then a
* <code>MalformedURLException</code> is thrown.
* </ol>
*
* @param protocol the name of the protocol.
* @param host the name of the host.
* @param port the port number.
* @param file the host file.
* @exception MalformedURLException if an unknown protocol is specified.
* @see java.lang.System#getProperty(java.lang.String)
* @see java.net.URL#setURLStreamHandlerFactory(java.net.URLStreamHandlerFactory)
* @see java.net.URLStreamHandler
* @see java.net.URLStreamHandlerFactory#createURLStreamHandler(java.lang.String)
* @since JDK1.0
*/
public URL(String protocol, String host, int port, String file)
throws MalformedURLException {
this.protocol = protocol;
this.host = host;
this.port = port;
int ind = file.indexOf('#');
this.file = ind < 0 ? file: file.substring(0, ind);
this.ref = ind < 0 ? null: file.substring(ind + 1);
if ((handler = getURLStreamHandler(protocol)) == null) {
throw new MalformedURLException("unknown protocol: " + protocol);
}
}
/**
* Creates an absolute URL from the specified <code>protocol</code>
* name, <code>host</code> name, and <code>file</code> name. The
* default port for the specified protocol is used.
* <p>
* This method is equivalent to calling the four-argument
* constructor with the arguments being <code>protocol</code>,
* <code>host</code>, <code>-1</code>, and <code>file</code>.
*
* @param protocol the protocol to use.
* @param host the host to connect to.
* @param file the file on that host.
* @exception MalformedURLException if an unknown protocol is specified.
* @see java.net.URL#URL(java.lang.String, java.lang.String, int, java.lang.String)
* @since JDK1.0
*/
public URL(String protocol, String host, String file) throws MalformedURLException {
this(protocol, host, -1, file);
}
/**
* Creates a <code>URL</code> object from the <code>String</code>
* representation.
* <p>
* This constructor is equivalent to a call to the two-argument
* constructor with a <code>null</code> first argument.
*
* @param spec the <code>String</code> to parse as a URL.
* @exception MalformedURLException If the string specifies an
* unknown protocol.
* @see java.net.URL#URL(java.net.URL, java.lang.String)
* @since JDK1.0
*/
public URL(String spec) throws MalformedURLException {
this(null, spec);
}
/**
* Creates a URL by parsing the specification <code>spec</code>
* within a specified context. If the <code>context</code> argument
* is not <code>null</code> and the <code>spec</code> argument is a
* partial URL specification, then any of the strings missing
* components are inherited from the <code>context</code> argument.
* <p>
* The specification given by the <code>String</code> argument is
* parsed to determine if it specifies a protocol. If the
* <code>String</code> contains an ASCII colon '<code>:</code>'
* character before the first occurrence of an ASCII slash character
* '<code>/</code>', then the characters before the colon comprise
* the protocol.
* <ul>
* <li>If the <code>spec</code> argument does not specify a protocol:
* <ul>
* <li>If the context argument is not <code>null</code>, then the
* protocol is copied from the context argument.
* <li>If the context argument is <code>null</code>, then a
* <code>MalformedURLException</code> is thrown.
* </ul>
* <li>If the <code>spec</code> argument does specify a protocol:
* <ul>
* <li>If the context argument is <code>null</code>, or specifies a
* different protocol than the specification argument, the context
* argument is ignored.
* <li>If the context argument is not <code>null</code> and specifies
* the same protocol as the specification, the <code>host</code>,
* <code>port</code> number, and <code>file</code> are copied from
* the context argument into the newly created <code>URL</code>.
* </ul>
* </ul>
* <p>
* The constructor then searches for an appropriate stream protocol
* handler of type <code>URLStreamHandler</code> as outlined for:
* <ul><code>
* java.net.URL#URL(java.lang.String, java.lang.String, int,
* java.lang.String)
* </code></ul>
* The stream protocol handler's
* <code>parseURL</code> method is called to parse the remaining
* fields of the specification that override any defaults set by the
* context argument.
* @param context the context in which to parse the specification.
* @param spec a <code>String</code> representation of a URL.
* @exception MalformedURLException if no protocol is specified, or an
* unknown protocol is found.
* @see java.net.URL#URL(java.lang.String, java.lang.String, int, java.lang.String)
* @see java.net.URLStreamHandler
* @see java.net.URLStreamHandler#parseURL(java.net.URL, java.lang.String, int, int)
* @since JDK1.0
*/
public URL(URL context, String spec) throws MalformedURLException {
String original = spec;
int i, limit, c;
int start = 0;
String newProtocol = null;
boolean aRef=false;
try {
limit = spec.length();
while ((limit > 0) && (spec.charAt(limit - 1) <= ' ')) {
limit--; //eliminate trailing whitespace
}
while ((start < limit) && (spec.charAt(start) <= ' ')) {
start++; // eliminate leading whitespace
}
if (spec.regionMatches(true, start, "url:", 0, 4)) {
start += 4;
}
if (start < spec.length() && spec.charAt(start) == '#') {
/* we're assuming this is a ref relative to the context URL.
* This means protocols cannot start w/ '#', but we must parse
* ref URL's like: "hello:there" w/ a ':' in them.
*/
aRef=true;
}
for (i = start ; !aRef && (i < limit) && ((c = spec.charAt(i)) != '/') ; i++) {
if (c == ':') {
newProtocol = spec.substring(start, i).toLowerCase();
start = i + 1;
break;
}
}
// Only use our context if the protocols match.
if ((context != null) && ((newProtocol == null) ||
newProtocol.equals(context.protocol))) {
protocol = context.protocol;
host = context.host;
port = context.port;
file = context.file;
} else {
protocol = newProtocol;
}
if (protocol == null) {
throw new MalformedURLException("no protocol: "+original);
}
if ((handler = getURLStreamHandler(protocol)) == null) {
throw new MalformedURLException("unknown protocol: "+protocol);
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?