summaryrefslogtreecommitdiffstats
path: root/luni/src/main/java/java/net/URL.java
diff options
context:
space:
mode:
Diffstat (limited to 'luni/src/main/java/java/net/URL.java')
-rw-r--r--luni/src/main/java/java/net/URL.java963
1 files changed, 963 insertions, 0 deletions
diff --git a/luni/src/main/java/java/net/URL.java b/luni/src/main/java/java/net/URL.java
new file mode 100644
index 0000000..2bc8c6c
--- /dev/null
+++ b/luni/src/main/java/java/net/URL.java
@@ -0,0 +1,963 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.net;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectOutputStream;
+import java.security.AccessController;
+import java.util.Hashtable;
+import java.util.StringTokenizer;
+
+import org.apache.harmony.luni.util.Msg;
+import org.apache.harmony.luni.util.PriviAction;
+import org.apache.harmony.luni.util.Util;
+
+/**
+ * A URL instance specifies the location of a resource on the internet as
+ * specified by RFC 1738. Such a resource can be a simple file or a service
+ * which generates the output dynamically. A URL is divided in its parts
+ * protocol, host name, port, path, file, user-info, query, reference and
+ * authority. However, not each of this parts has to be defined.
+ *
+ * @since Android 1.0
+ */
+public final class URL implements java.io.Serializable {
+ private static final long serialVersionUID = -7627629688361524110L;
+
+ private static final NetPermission specifyStreamHandlerPermission = new NetPermission(
+ "specifyStreamHandler"); //$NON-NLS-1$
+
+ private int hashCode;
+
+ /**
+ * The receiver's filename.
+ *
+ * @serial the file of this URL
+ *
+ */
+ private String file;
+
+ /**
+ * The receiver's protocol identifier.
+ *
+ * @serial the protocol of this URL (http, file)
+ *
+ */
+ private String protocol = null;
+
+ /**
+ * The receiver's host name.
+ *
+ * @serial the host of this URL
+ *
+ */
+ private String host;
+
+ /**
+ * The receiver's port number.
+ *
+ * @serial the port of this URL
+ *
+ */
+ private int port = -1;
+
+ /**
+ * The receiver's authority.
+ *
+ * @serial the authority of this URL
+ *
+ */
+ private String authority = null;
+
+ /**
+ * The receiver's userInfo.
+ */
+ private transient String userInfo = null;
+
+ /**
+ * The receiver's path.
+ */
+ private transient String path = null;
+
+ /**
+ * The receiver's query.
+ */
+ private transient String query = null;
+
+ /**
+ * The receiver's reference.
+ *
+ * @serial the reference of this URL
+ *
+ */
+ private String ref = null;
+
+ /**
+ * Cache for storing protocol handler
+ */
+ private static Hashtable<String, URLStreamHandler> streamHandlers = new Hashtable<String, URLStreamHandler>();
+
+ /**
+ * The URL Stream (protocol) Handler
+ */
+ transient URLStreamHandler strmHandler;
+
+ /**
+ * The factory responsible for producing URL Stream (protocol) Handler
+ */
+ private static URLStreamHandlerFactory streamHandlerFactory;
+
+ /**
+ * Sets the {@code URLStreamHandlerFactory} which creates protocol specific
+ * stream handlers. This method can be invoked only once during an
+ * application's lifetime. If the {@code URLStreamHandlerFactory} is already
+ * set an {@link Error} will be thrown.
+ * <p>
+ * A security check is performed to verify whether the current policy allows
+ * to set the stream handler factory.
+ * </p>
+ *
+ * @param streamFactory
+ * the factory to be used for creating stream protocol handlers.
+ * @since Android 1.0
+ */
+ public static synchronized void setURLStreamHandlerFactory(
+ URLStreamHandlerFactory streamFactory) {
+ if (streamHandlerFactory != null) {
+ throw new Error(Msg.getString("K004b")); //$NON-NLS-1$
+ }
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ sm.checkSetFactory();
+ }
+ streamHandlers.clear();
+ streamHandlerFactory = streamFactory;
+ }
+
+ /**
+ * Creates a new URL instance by parsing the string {@code spec}.
+ *
+ * @param spec
+ * the URL string representation which has to be parsed.
+ * @throws MalformedURLException
+ * if the given string {@code spec} could not be parsed as a
+ * URL.
+ * @since Android 1.0
+ */
+ public URL(String spec) throws MalformedURLException {
+ this((URL) null, spec, (URLStreamHandler) null);
+ }
+
+ /**
+ * Creates a new URL to the specified resource {@code spec}. This URL is
+ * relative to the given {@code context}. If the protocol of the parsed URL
+ * does not match with the protocol of the context URL, then the newly
+ * created URL is absolute and bases only on the given URL represented by
+ * {@code spec}. Otherwise the protocol is defined by the context URL.
+ *
+ * @param context
+ * the URL which is used as the context.
+ * @param spec
+ * the URL string representation which has to be parsed.
+ * @throws MalformedURLException
+ * if the given string {@code spec} could not be parsed as a URL
+ * or an invalid protocol has been found.
+ * @since Android 1.0
+ */
+ public URL(URL context, String spec) throws MalformedURLException {
+ this(context, spec, (URLStreamHandler) null);
+ }
+
+ /**
+ * Creates a new URL to the specified resource {@code spec}. This URL is
+ * relative to the given {@code context}. The {@code handler} will be used
+ * to parse the URL string representation. If this argument is {@code null}
+ * the default {@code URLStreamHandler} will be used. If the protocol of the
+ * parsed URL does not match with the protocol of the context URL, then the
+ * newly created URL is absolute and bases only on the given URL represented
+ * by {@code spec}. Otherwise the protocol is defined by the context URL.
+ *
+ * @param context
+ * the URL which is used as the context.
+ * @param spec
+ * the URL string representation which has to be parsed.
+ * @param handler
+ * the specific stream handler to be used by this URL.
+ * @throws MalformedURLException
+ * if the given string {@code spec} could not be parsed as a URL
+ * or an invalid protocol has been found.
+ * @since Android 1.0
+ */
+ public URL(URL context, String spec, URLStreamHandler handler)
+ throws MalformedURLException {
+ if (handler != null) {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ sm.checkPermission(specifyStreamHandlerPermission);
+ }
+ strmHandler = handler;
+ }
+
+ if (spec == null) {
+ throw new MalformedURLException();
+ }
+ spec = spec.trim();
+
+ // The spec includes a protocol if it includes a colon character
+ // before the first occurrence of a slash character. Note that,
+ // "protocol" is the field which holds this URLs protocol.
+ int index;
+ try {
+ index = spec.indexOf(':');
+ } catch (NullPointerException e) {
+ throw new MalformedURLException(e.toString());
+ }
+ int startIPv6Addr = spec.indexOf('[');
+ if (index >= 0) {
+ if ((startIPv6Addr == -1) || (index < startIPv6Addr)) {
+ protocol = spec.substring(0, index);
+ // According to RFC 2396 scheme part should match
+ // the following expression:
+ // alpha *( alpha | digit | "+" | "-" | "." )
+ // BEGIN android-changed
+ // copied from newer version of harmony
+ char c = protocol.charAt(0);
+ boolean valid = ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z');
+ for (int i = 1; valid && (i < protocol.length()); i++) {
+ c = protocol.charAt(i);
+ valid = ('a' <= c && c <= 'z') ||
+ ('A' <= c && c <= 'Z') ||
+ ('0' <= c && c <= '9') ||
+ (c == '+') ||
+ (c == '-') ||
+ (c == '.');
+ }
+ if (!valid) {
+ protocol = null;
+ index = -1;
+ } else {
+ // Ignore case in protocol names.
+ // Scheme is defined by ASCII characters.
+ protocol = Util.toASCIILowerCase(protocol);
+ }
+ // END android-changed
+ }
+ }
+
+ if (protocol != null) {
+ // If the context was specified, and it had the same protocol
+ // as the spec, then fill in the receiver's slots from the values
+ // in the context but still allow them to be over-ridden later
+ // by the values in the spec.
+ if (context != null && protocol.equals(context.getProtocol())) {
+ String cPath = context.getPath();
+ if (cPath != null && cPath.startsWith("/")) { //$NON-NLS-1$
+ set(protocol, context.getHost(), context.getPort(), context
+ .getAuthority(), context.getUserInfo(), cPath,
+ context.getQuery(), null);
+ }
+ if (strmHandler == null) {
+ strmHandler = context.strmHandler;
+ }
+ }
+ } else {
+ // If the spec did not include a protocol, then the context
+ // *must* be specified. Fill in the receiver's slots from the
+ // values in the context, but still allow them to be over-ridden
+ // by the values in the ("relative") spec.
+ if (context == null) {
+ throw new MalformedURLException(
+ org.apache.harmony.luni.util.Msg.getString(
+ "K00d8", spec)); //$NON-NLS-1$
+ }
+ set(context.getProtocol(), context.getHost(), context.getPort(),
+ context.getAuthority(), context.getUserInfo(), context
+ .getPath(), context.getQuery(), null);
+ if (strmHandler == null) {
+ strmHandler = context.strmHandler;
+ }
+ }
+
+ // If the stream handler has not been determined, set it
+ // to the default for the specified protocol.
+ if (strmHandler == null) {
+ setupStreamHandler();
+ if (strmHandler == null) {
+ throw new MalformedURLException(
+ org.apache.harmony.luni.util.Msg.getString(
+ "K00b3", protocol)); //$NON-NLS-1$
+ }
+ }
+
+ // Let the handler parse the URL. If the handler throws
+ // any exception, throw MalformedURLException instead.
+ //
+ // Note: We want "index" to be the index of the start of the scheme
+ // specific part of the URL. At this point, it will be either
+ // -1 or the index of the colon after the protocol, so we
+ // increment it to point at either character 0 or the character
+ // after the colon.
+ try {
+ strmHandler.parseURL(this, spec, ++index, spec.length());
+ } catch (Exception e) {
+ throw new MalformedURLException(e.toString());
+ }
+
+ if (port < -1) {
+ throw new MalformedURLException(org.apache.harmony.luni.util.Msg
+ .getString("K0325", port)); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Creates a new URL instance using the given arguments. The URL uses the
+ * default port for the specified protocol.
+ *
+ * @param protocol
+ * the protocol of the new URL.
+ * @param host
+ * the host name or IP address of the new URL.
+ * @param file
+ * the name of the resource.
+ * @throws MalformedURLException
+ * if the combination of all arguments do not represent a valid
+ * URL or the protocol is invalid.
+ * @since Android 1.0
+ */
+ public URL(String protocol, String host, String file)
+ throws MalformedURLException {
+ this(protocol, host, -1, file, (URLStreamHandler) null);
+ }
+
+ /**
+ * Creates a new URL instance using the given arguments. The URL uses the
+ * specified port instead of the default port for the given protocol.
+ *
+ * @param protocol
+ * the protocol of the new URL.
+ * @param host
+ * the host name or IP address of the new URL.
+ * @param port
+ * the specific port number of the URL. {@code -1} represents the
+ * default port of the protocol.
+ * @param file
+ * the name of the resource.
+ * @throws MalformedURLException
+ * if the combination of all arguments do not represent a valid
+ * URL or the protocol is invalid.
+ * @since Android 1.0
+ */
+ public URL(String protocol, String host, int port, String file)
+ throws MalformedURLException {
+ this(protocol, host, port, file, (URLStreamHandler) null);
+ }
+
+ /**
+ * Creates a new URL instance using the given arguments. The URL uses the
+ * specified port instead of the default port for the given protocol.
+ *
+ * @param protocol
+ * the protocol of the new URL.
+ * @param host
+ * the host name or IP address of the new URL.
+ * @param port
+ * the specific port number of the URL. {@code -1} represents the
+ * default port of the protocol.
+ * @param file
+ * the name of the resource.
+ * @param handler
+ * the stream handler to be used by this URL.
+ * @throws MalformedURLException
+ * if the combination of all arguments do not represent a valid
+ * URL or the protocol is invalid.
+ * @since Android 1.0
+ */
+ public URL(String protocol, String host, int port, String file,
+ URLStreamHandler handler) throws MalformedURLException {
+ if (port < -1) {
+ throw new MalformedURLException(org.apache.harmony.luni.util.Msg
+ .getString("K0325", port)); //$NON-NLS-1$
+ }
+
+ if (host != null && host.indexOf(":") != -1 && host.charAt(0) != '[') { //$NON-NLS-1$
+ host = "[" + host + "]"; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ if (protocol != null) {
+ this.protocol = protocol;
+ } else {
+ throw new NullPointerException(Msg.getString("K00b3", protocol)); //$NON-NLS-1$
+ }
+
+ this.host = host;
+ this.port = port;
+
+ // Set the fields from the arguments. Handle the case where the
+ // passed in "file" includes both a file and a reference part.
+ int index = -1;
+ index = file.indexOf("#", file.lastIndexOf("/")); //$NON-NLS-1$ //$NON-NLS-2$
+ if (index >= 0) {
+ this.file = file.substring(0, index);
+ ref = file.substring(index + 1);
+ } else {
+ this.file = file;
+ }
+ fixURL(false);
+
+ // Set the stream handler for the URL either to the handler
+ // argument if it was specified, or to the default for the
+ // receiver's protocol if the handler was null.
+ if (handler == null) {
+ setupStreamHandler();
+ if (strmHandler == null) {
+ throw new MalformedURLException(
+ org.apache.harmony.luni.util.Msg.getString(
+ "K00b3", protocol)); //$NON-NLS-1$
+ }
+ } else {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ sm.checkPermission(specifyStreamHandlerPermission);
+ }
+ strmHandler = handler;
+ }
+ }
+
+ void fixURL(boolean fixHost) {
+ int index;
+ if (host != null && host.length() > 0) {
+ authority = host;
+ if (port != -1) {
+ authority = authority + ":" + port; //$NON-NLS-1$
+ }
+ }
+ if (fixHost) {
+ if (host != null && (index = host.lastIndexOf('@')) > -1) {
+ userInfo = host.substring(0, index);
+ host = host.substring(index + 1);
+ } else {
+ userInfo = null;
+ }
+ }
+ if (file != null && (index = file.indexOf('?')) > -1) {
+ query = file.substring(index + 1);
+ path = file.substring(0, index);
+ } else {
+ query = null;
+ path = file;
+ }
+ }
+
+ /**
+ * Sets the properties of this URL using the provided arguments. Only a
+ * {@code URLStreamHandler} can use this method to set fields of the
+ * existing URL instance. A URL is generally constant.
+ *
+ * @param protocol
+ * the protocol to be set.
+ * @param host
+ * the host name to be set.
+ * @param port
+ * the port number to be set.
+ * @param file
+ * the file to be set.
+ * @param ref
+ * the reference to be set.
+ * @since Android 1.0
+ */
+ protected void set(String protocol, String host, int port, String file,
+ String ref) {
+ if (this.protocol == null) {
+ this.protocol = protocol;
+ }
+ this.host = host;
+ this.file = file;
+ this.port = port;
+ this.ref = ref;
+ hashCode = 0;
+ fixURL(true);
+ }
+
+ /**
+ * Compares this URL instance with the given argument {@code o} and
+ * determines if both are equal. Two URL instances are equal if all single
+ * parts are identical in their meaning. Compares the argument to the
+ * receiver, and returns true if they represent the same URL. Two URLs are
+ * equal if they have the same file, host, port, protocol, and reference
+ * components.
+ *
+ * @param o
+ * the URL this instance has to be compared with.
+ * @return {@code true} if both instances represents the same URL, {@code
+ * false} otherwise.
+ * @see #hashCode
+ * @since Android 1.0
+ */
+ @Override
+ public boolean equals(Object o) {
+ if (o == null) {
+ return false;
+ }
+ if (this == o) {
+ return true;
+ }
+ if (this.getClass() != o.getClass()) {
+ return false;
+ }
+ return strmHandler.equals(this, (URL) o);
+ }
+
+ /**
+ * Returns whether this URL refers to the same resource as the given
+ * argument {@code otherURL}. All URL components except the reference field
+ * are compared.
+ *
+ * @param otherURL
+ * the URL to compare against.
+ * @return {@code true} if both instances refer to the same resource,
+ * {@code false} otherwise.
+ * @since Android 1.0
+ */
+ public boolean sameFile(URL otherURL) {
+ return strmHandler.sameFile(this, otherURL);
+ }
+
+ /**
+ * Gets the hashcode value of this URL instance.
+ *
+ * @return the appropriate hashcode value.
+ * @since Android 1.0
+ */
+ @Override
+ public int hashCode() {
+ if (hashCode == 0) {
+ hashCode = strmHandler.hashCode(this);
+ }
+ return hashCode;
+ }
+
+ /**
+ * Sets the receiver's stream handler to one which is appropriate for its
+ * protocol. Throws a MalformedURLException if no reasonable handler is
+ * available.
+ * <p>
+ * Note that this will overwrite any existing stream handler with the new
+ * one. Senders must check if the strmHandler is null before calling the
+ * method if they do not want this behavior (a speed optimization).
+ * </p>
+ */
+ void setupStreamHandler() {
+ // Check for a cached (previously looked up) handler for
+ // the requested protocol.
+ strmHandler = streamHandlers.get(protocol);
+ if (strmHandler != null) {
+ return;
+ }
+
+ // If there is a stream handler factory, then attempt to
+ // use it to create the handler.
+ if (streamHandlerFactory != null) {
+ strmHandler = streamHandlerFactory.createURLStreamHandler(protocol);
+ if (strmHandler != null) {
+ streamHandlers.put(protocol, strmHandler);
+ return;
+ }
+ }
+
+ // Check if there is a list of packages which can provide handlers.
+ // If so, then walk this list looking for an applicable one.
+ String packageList = AccessController
+ .doPrivileged(new PriviAction<String>(
+ "java.protocol.handler.pkgs")); //$NON-NLS-1$
+ if (packageList != null) {
+ StringTokenizer st = new StringTokenizer(packageList, "|"); //$NON-NLS-1$
+ while (st.hasMoreTokens()) {
+ String className = st.nextToken() + "." + protocol + ".Handler"; //$NON-NLS-1$ //$NON-NLS-2$
+
+ try {
+ strmHandler = (URLStreamHandler) Class.forName(className,
+ true, ClassLoader.getSystemClassLoader())
+ .newInstance();
+ if (strmHandler != null) {
+ streamHandlers.put(protocol, strmHandler);
+ }
+ return;
+ } catch (IllegalAccessException e) {
+ } catch (InstantiationException e) {
+ } catch (ClassNotFoundException e) {
+ }
+ }
+ }
+
+ // No one else has provided a handler, so try our internal one.
+
+ String className = "org.apache.harmony.luni.internal.net.www.protocol." + protocol //$NON-NLS-1$
+ + ".Handler"; //$NON-NLS-1$
+ try {
+ strmHandler = (URLStreamHandler) Class.forName(className)
+ .newInstance();
+ } catch (IllegalAccessException e) {
+ } catch (InstantiationException e) {
+ } catch (ClassNotFoundException e) {
+ }
+ if (strmHandler != null) {
+ streamHandlers.put(protocol, strmHandler);
+ }
+
+ }
+
+ /**
+ * Gets the content of the resource which is referred by this URL. By
+ * default one of the following object types will be returned:
+ * <p>
+ * <li>Image for pictures</li>
+ * <li>AudioClip for audio sequences</li>
+ * <li>{@link InputStream} for all other data</li>
+ * </p>
+ *
+ * @return the content of the referred resource.
+ * @throws IOException
+ * if an error occurs obtaining the content.
+ * @since Android 1.0
+ */
+ public final Object getContent() throws IOException {
+ return openConnection().getContent();
+ }
+
+ /**
+ * Gets the content of the resource which is referred by this URL. The
+ * argument {@code types} is an array of allowed or expected object types.
+ * {@code null} will be returned if the obtained object type does not match
+ * with one from this list. Otherwise the first type that matches will be
+ * used.
+ *
+ * @param types
+ * the list of allowed or expected object types.
+ * @return the object representing the resource referred by this URL,
+ * {@code null} if the content does not match to a specified content
+ * type.
+ * @throws IOException
+ * if an error occurs obtaining the content.
+ * @since Android 1.0
+ */
+ // Param not generic in spec
+ @SuppressWarnings("unchecked")
+ public final Object getContent(Class[] types) throws IOException {
+ return openConnection().getContent(types);
+ }
+
+ /**
+ * Opens an InputStream to read the resource referred by this URL.
+ *
+ * @return the stream which allows to read the resource.
+ * @throws IOException
+ * if an error occurs while opening the InputStream.
+ * @since Android 1.0
+ */
+ public final InputStream openStream() throws java.io.IOException {
+ return openConnection().getInputStream();
+ }
+
+ /**
+ * Opens a connection to the remote resource specified by this URL. This
+ * connection allows bidirectional data transfer.
+ *
+ * @return the connection to this URL.
+ * @throws IOException
+ * if an error occurs while opening the connection.
+ * @since Android 1.0
+ */
+ public URLConnection openConnection() throws IOException {
+ return strmHandler.openConnection(this);
+ }
+
+ /**
+ * Converts this URL instance into an equivalent URI object.
+ *
+ * @return the URI instance that represents this URL.
+ * @throws URISyntaxException
+ * if this URL cannot be converted into a URI.
+ * @since Android 1.0
+ */
+ public URI toURI() throws URISyntaxException {
+ return new URI(toExternalForm());
+ }
+
+ /**
+ * Opens a connection to the remote resource specified by this URL. The
+ * connection will be established through the given proxy and allows
+ * bidirectional data transfer.
+ *
+ * @param proxy
+ * the proxy through which the connection will be established.
+ * @return the appropriate URLconnection instance representing the
+ * connection to this URL.
+ * @throws IOException
+ * if an I/O error occurs while opening the connection.
+ * @throws SecurityException
+ * if a security manager is installed and it denies to connect
+ * to the proxy.
+ * @throws IllegalArgumentException
+ * if the argument proxy is {@code null} or is an invalid type.
+ * @throws UnsupportedOperationException
+ * if the protocol handler does not support opening connections
+ * through proxies.
+ * @since Android 1.0
+ */
+ public URLConnection openConnection(Proxy proxy) throws IOException {
+ if (null == proxy) {
+ throw new IllegalArgumentException(Msg.getString("K034c")); //$NON-NLS-1$
+ }
+ return strmHandler.openConnection(this, proxy);
+ }
+
+ /**
+ * Returns a string containing a concise, human-readable representation of
+ * this URL. The returned string is the same as the result of the method
+ * {@code toExternalForm()}.
+ *
+ * @return the string representation of this URL.
+ * @since Android 1.0
+ */
+ @Override
+ public String toString() {
+ return toExternalForm();
+ }
+
+ /**
+ * Returns a string containing a concise, human-readable representation of
+ * this URL.
+ *
+ * @return the string representation of this URL.
+ * @since Android 1.0
+ */
+ public String toExternalForm() {
+ if (strmHandler == null) {
+ return "unknown protocol(" + protocol + ")://" + host + file; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ return strmHandler.toExternalForm(this);
+ }
+
+ /**
+ * This method is called to restore the state of a URL object that has been
+ * serialized. The stream handler is determined from the URL's protocol.
+ *
+ * @param stream
+ * the stream to read from.
+ *
+ * @throws IOException
+ * if an IO Exception occurs while reading the stream or the
+ * handler can not be found.
+ */
+ private void readObject(java.io.ObjectInputStream stream)
+ throws java.io.IOException {
+ try {
+ stream.defaultReadObject();
+ if (host != null && authority == null) {
+ fixURL(true);
+ } else if (authority != null) {
+ int index;
+ if ((index = authority.lastIndexOf('@')) > -1) {
+ userInfo = authority.substring(0, index);
+ }
+ if (file != null && (index = file.indexOf('?')) > -1) {
+ query = file.substring(index + 1);
+ path = file.substring(0, index);
+ } else {
+ path = file;
+ }
+ }
+ setupStreamHandler();
+ if (strmHandler == null) {
+ throw new IOException(Msg.getString("K00b3", protocol)); //$NON-NLS-1$
+ }
+ } catch (ClassNotFoundException e) {
+ throw new IOException(e.toString());
+ }
+ }
+
+ /**
+ * This method is called to write any non-transient, non-static variables
+ * into the output stream.
+ * <p>
+ * Note that, we really only need the readObject method but the spec that
+ * says readObject will be ignored if no writeObject is present.
+ * </p>
+ *
+ * @param s
+ * the stream to write on.
+ * @throws IOException
+ * if an IO Exception occurs during the write.
+ */
+ private void writeObject(ObjectOutputStream s) throws IOException {
+ s.defaultWriteObject();
+ }
+
+ /**
+ * Gets the value of the file part of this URL.
+ *
+ * @return the file name this URL refers to or an empty string if the file
+ * part is not set.
+ * @since Android 1.0
+ */
+ public String getFile() {
+ return file;
+ }
+
+ /**
+ * Gets the value of the host part of this URL.
+ *
+ * @return the host name or IP address of this URL.
+ * @since Android 1.0
+ */
+ public String getHost() {
+ return host;
+ }
+
+ /**
+ * Gets the port number of this URL or {@code -1} if the port is not set.
+ *
+ * @return the port number of this URL.
+ * @since Android 1.0
+ */
+ public int getPort() {
+ return port;
+ }
+
+ /**
+ * Gets the protocol of this URL.
+ *
+ * @return the protocol type of this URL.
+ * @since Android 1.0
+ */
+ public String getProtocol() {
+ return protocol;
+ }
+
+ /**
+ * Gets the value of the reference part of this URL.
+ *
+ * @return the reference part of this URL.
+ * @since Android 1.0
+ */
+ public String getRef() {
+ return ref;
+ }
+
+ /**
+ * Gets the value of the query part of this URL.
+ *
+ * @return the query part of this URL.
+ * @since Android 1.0
+ */
+ public String getQuery() {
+ return query;
+ }
+
+ /**
+ * Gets the value of the path part of this URL.
+ *
+ * @return the path part of this URL.
+ * @since Android 1.0
+ */
+ public String getPath() {
+ return path;
+ }
+
+ /**
+ * Gets the value of the user-info part of this URL.
+ *
+ * @return the user-info part of this URL.
+ * @since Android 1.0
+ */
+ public String getUserInfo() {
+ return userInfo;
+ }
+
+ /**
+ * Gets the value of the authority part of this URL.
+ *
+ * @return the authority part of this URL.
+ * @since Android 1.0
+ */
+ public String getAuthority() {
+ return authority;
+ }
+
+ /**
+ * Sets the properties of this URL using the provided arguments. Only a
+ * {@code URLStreamHandler} can use this method to set fields of the
+ * existing URL instance. A URL is generally constant.
+ *
+ * @param protocol
+ * the protocol to be set.
+ * @param host
+ * the host name to be set.
+ * @param port
+ * the port number to be set.
+ * @param authority
+ * the authority to be set.
+ * @param userInfo
+ * the user-info to be set.
+ * @param path
+ * the path to be set.
+ * @param query
+ * the query to be set.
+ * @param ref
+ * the reference to be set.
+ * @since Android 1.0
+ */
+ protected void set(String protocol, String host, int port,
+ String authority, String userInfo, String path, String query,
+ String ref) {
+ String file = path;
+ if (query != null && !query.equals("")) { //$NON-NLS-1$
+ if (file != null) {
+ file = file + "?" + query; //$NON-NLS-1$
+ } else {
+ file = "?" + query; //$NON-NLS-1$
+ }
+ }
+ set(protocol, host, port, file, ref);
+ this.authority = authority;
+ this.userInfo = userInfo;
+ this.path = path;
+ this.query = query;
+ }
+
+ // BEGIN android-removed
+ // copied from newer version of harmony
+ // URLStreamHandler getStreamHandler() {
+ // return strmHandler;
+ // }
+ // END android-removed
+
+ /**
+ * Gets the default port number of the protocol used by this URL. If no
+ * default port is defined by the protocol or the {@code URLStreamHandler},
+ * {@code -1} will be returned.
+ *
+ * @return the default port number according to the protocol of this URL.
+ * @see URLStreamHandler#getDefaultPort
+ * @since Android 1.0
+ */
+ public int getDefaultPort() {
+ return strmHandler.getDefaultPort();
+ }
+}