151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/*
22c87ad3a45cecf9e344487cad1abfdebe79f2c7cNarayan Kamath * Copyright (C) 2014 The Android Open Source Project
351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved.
451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is free software; you can redistribute it and/or modify it
751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * under the terms of the GNU General Public License version 2 only, as
851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * published by the Free Software Foundation.  Oracle designates this
951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * particular file as subject to the "Classpath" exception as provided
1051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * by Oracle in the LICENSE file that accompanied this code.
1151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
1251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is distributed in the hope that it will be useful, but WITHOUT
1351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * version 2 for more details (a copy is included in the LICENSE file that
1651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * accompanied this code).
1751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
1851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * You should have received a copy of the GNU General Public License version
1951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2 along with this work; if not, write to the Free Software Foundation,
2051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
2251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or visit www.oracle.com if you need additional information or have any
2451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * questions.
2551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
2651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
2751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipackage java.net;
2851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
2951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.IOException;
3051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.InputStream;
3151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.OutputStream;
3251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.security.AccessController;
3351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.security.PrivilegedAction;
3451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.Hashtable;
3551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.StringTokenizer;
3651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport sun.security.util.SecurityConstants;
3751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
3851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/**
3951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Class <code>URL</code> represents a Uniform Resource
4051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Locator, a pointer to a "resource" on the World
4151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Wide Web. A resource can be something as simple as a file or a
4251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * directory, or it can be a reference to a more complicated object,
4351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * such as a query to a database or to a search engine. More
4451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * information on the types of URLs and their formats can be found at:
4551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <blockquote>
4651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <a href="http://www.socs.uts.edu.au/MosaicDocs-old/url-primer.html">
4751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *    <i>http://www.socs.uts.edu.au/MosaicDocs-old/url-primer.html</i></a>
4851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * </blockquote>
4951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>
5051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * In general, a URL can be broken into several parts. The previous
5151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * example of a URL indicates that the protocol to use is
5251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>http</code> (HyperText Transfer Protocol) and that the
5351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * information resides on a host machine named
5451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>www.socs.uts.edu.au</code>. The information on that host
5551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * machine is named <code>/MosaicDocs-old/url-primer.html</code>. The exact
5651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * meaning of this name on the host machine is both protocol
5751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * dependent and host dependent. The information normally resides in
5851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * a file, but it could be generated on the fly. This component of
5951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the URL is called the <i>path</i> component.
6051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>
6151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * A URL can optionally specify a "port", which is the
6251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * port number to which the TCP connection is made on the remote host
6351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * machine. If the port is not specified, the default port for
6451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the protocol is used instead. For example, the default port for
6551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>http</code> is <code>80</code>. An alternative port could be
6651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * specified as:
6751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <blockquote><pre>
6851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     http://www.socs.uts.edu.au:80/MosaicDocs-old/url-primer.html
6951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * </pre></blockquote>
7051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>
7151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The syntax of <code>URL</code> is defined by  <a
7251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * href="http://www.ietf.org/rfc/rfc2396.txt"><i>RFC&nbsp;2396: Uniform
7351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Resource Identifiers (URI): Generic Syntax</i></a>, amended by <a
7451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * href="http://www.ietf.org/rfc/rfc2732.txt"><i>RFC&nbsp;2732: Format for
7551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Literal IPv6 Addresses in URLs</i></a>. The Literal IPv6 address format
7651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * also supports scope_ids. The syntax and usage of scope_ids is described
7751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <a href="Inet6Address.html#scoped">here</a>.
7851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>
7951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * A URL may have appended to it a "fragment", also known
8051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * as a "ref" or a "reference". The fragment is indicated by the sharp
8151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * sign character "#" followed by more characters. For example,
8251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <blockquote><pre>
8351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     http://java.sun.com/index.html#chapter1
8451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * </pre></blockquote>
8551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>
8651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This fragment is not technically part of the URL. Rather, it
8751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * indicates that after the specified resource is retrieved, the
8851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * application is specifically interested in that part of the
8951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * document that has the tag <code>chapter1</code> attached to it. The
9051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * meaning of a tag is resource specific.
9151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>
9251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * An application can also specify a "relative URL",
9351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * which contains only enough information to reach the resource
9451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * relative to another URL. Relative URLs are frequently used within
9551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * HTML pages. For example, if the contents of the URL:
9651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <blockquote><pre>
9751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     http://java.sun.com/index.html
9851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * </pre></blockquote>
9951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * contained within it the relative URL:
10051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <blockquote><pre>
10151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     FAQ.html
10251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * </pre></blockquote>
10351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * it would be a shorthand for:
10451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <blockquote><pre>
10551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     http://java.sun.com/FAQ.html
10651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * </pre></blockquote>
10751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>
10851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The relative URL need not specify all the components of a URL. If
10951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the protocol, host name, or port number is missing, the value is
11051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * inherited from the fully specified URL. The file component must be
11151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * specified. The optional fragment is not inherited.
11251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>
11351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The URL class does not itself encode or decode any URL components
11451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * according to the escaping mechanism defined in RFC2396. It is the
11551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * responsibility of the caller to encode any fields, which need to be
11651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * escaped prior to calling URL, and also to decode any escaped fields,
11751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * that are returned from URL. Furthermore, because URL has no knowledge
11851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * of URL escaping, it does not recognise equivalence between the encoded
11951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or decoded form of the same URL. For example, the two URLs:<br>
12051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <pre>    http://foo.com/hello world/ and http://foo.com/hello%20world</pre>
12151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * would be considered not equal to each other.
12251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>
12351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Note, the {@link java.net.URI} class does perform escaping of its
12451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * component fields in certain circumstances. The recommended way
12551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * to manage the encoding and decoding of URLs is to use {@link java.net.URI},
12651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * and to convert between these two classes using {@link #toURI()} and
12751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * {@link URI#toURL()}.
12851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>
12951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The {@link URLEncoder} and {@link URLDecoder} classes can also be
13051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * used, but only for HTML form encoding, which is not the same
13151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * as the encoding scheme defined in RFC2396.
13251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
13351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @author  James Gosling
13451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @since JDK1.0
13551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
13651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipublic final class URL implements java.io.Serializable {
13751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
13851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    static final long serialVersionUID = -7627629688361524110L;
13951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
14051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
14151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * The property which specifies the package prefix list to be scanned
14251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * for protocol handlers.  The value of this property (if any) should
14351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * be a vertical bar delimited list of package names to search through
14451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * for a protocol handler to load.  The policy of this class is that
14551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * all protocol handlers will be in a class called <protocolname>.Handler,
14651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * and each package in the list is examined in turn for a matching
14751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * handler.  If none are found (or the property is not specified), the
14851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * default package prefix, sun.net.www.protocol, is used.  The search
14951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * proceeds from the first package in the list to the last and stops
15051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * when a match is found.
15151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
15251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static final String protocolPathProp = "java.protocol.handler.pkgs";
15351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
15451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
15551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * The protocol to use (ftp, http, nntp, ... etc.) .
15651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @serial
15751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
15851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private String protocol;
15951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
16051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
16151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * The host name to connect to.
16251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @serial
16351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
16451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private String host;
16551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
16651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
16751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * The protocol port to connect to.
16851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @serial
16951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
17051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private int port = -1;
17151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
17251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
17351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * The specified file name on that host. <code>file</code> is
17451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * defined as <code>path[?query]</code>
17551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @serial
17651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
17751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private String file;
17851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
17951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
18051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * The query part of this URL.
18151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
18251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private transient String query;
18351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
18451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
18551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * The authority part of this URL.
18651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @serial
18751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
18851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private String authority;
18951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
19051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
19151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * The path part of this URL.
19251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
19351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private transient String path;
19451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
19551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
19651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * The userinfo part of this URL.
19751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
19851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private transient String userInfo;
19951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
20051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
20151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * # reference.
20251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @serial
20351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
20451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private String ref;
20551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
20651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
20751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * The host's IP address, used in equals and hashCode.
20851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Computed on demand. An uninitialized or unknown hostAddress is null.
20951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
21051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    transient InetAddress hostAddress;
21151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
21251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
21351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * The URLStreamHandler for this URL.
21451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
21551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    transient URLStreamHandler handler;
21651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
21751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /* Our hash code.
21851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @serial
21951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
22006fc5c380e77f61adcf02305c5bbea9eac129583Przemyslaw Szczepaniak    // ----- BEGIN android -----
22106fc5c380e77f61adcf02305c5bbea9eac129583Przemyslaw Szczepaniak    //private int hashCode = -1;
22206fc5c380e77f61adcf02305c5bbea9eac129583Przemyslaw Szczepaniak    private transient int hashCode = -1;
22306fc5c380e77f61adcf02305c5bbea9eac129583Przemyslaw Szczepaniak    // ----- END android -----
22451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
22551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
22651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Creates a <code>URL</code> object from the specified
22751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <code>protocol</code>, <code>host</code>, <code>port</code>
22851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * number, and <code>file</code>.<p>
22951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
23051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <code>host</code> can be expressed as a host name or a literal
23151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * IP address. If IPv6 literal address is used, it should be
23251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * enclosed in square brackets (<tt>'['</tt> and <tt>']'</tt>), as
23351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * specified by <a
23451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * href="http://www.ietf.org/rfc/rfc2732.txt">RFC&nbsp;2732</a>;
23551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * However, the literal IPv6 address format defined in <a
23651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * href="http://www.ietf.org/rfc/rfc2373.txt"><i>RFC&nbsp;2373: IP
23751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Version 6 Addressing Architecture</i></a> is also accepted.<p>
23851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
23951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Specifying a <code>port</code> number of <code>-1</code>
24051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * indicates that the URL should use the default port for the
24151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * protocol.<p>
24251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
24351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * If this is the first URL object being created with the specified
24451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * protocol, a <i>stream protocol handler</i> object, an instance of
24551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * class <code>URLStreamHandler</code>, is created for that protocol:
24651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <ol>
24751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <li>If the application has previously set up an instance of
24851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     <code>URLStreamHandlerFactory</code> as the stream handler factory,
24951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     then the <code>createURLStreamHandler</code> method of that instance
25051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     is called with the protocol string as an argument to create the
25151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     stream protocol handler.
25251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <li>If no <code>URLStreamHandlerFactory</code> has yet been set up,
25351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     or if the factory's <code>createURLStreamHandler</code> method
25451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     returns <code>null</code>, then the constructor finds the
25551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     value of the system property:
25651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     <blockquote><pre>
25751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *         java.protocol.handler.pkgs
25851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     </pre></blockquote>
25951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     If the value of that system property is not <code>null</code>,
26051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     it is interpreted as a list of packages separated by a vertical
26151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     slash character '<code>|</code>'. The constructor tries to load
26251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     the class named:
26351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     <blockquote><pre>
26451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *         &lt;<i>package</i>&gt;.&lt;<i>protocol</i>&gt;.Handler
26551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     </pre></blockquote>
26651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     where &lt;<i>package</i>&gt; is replaced by the name of the package
26751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     and &lt;<i>protocol</i>&gt; is replaced by the name of the protocol.
26851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     If this class does not exist, or if the class exists but it is not
26951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     a subclass of <code>URLStreamHandler</code>, then the next package
27051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     in the list is tried.
27151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <li>If the previous step fails to find a protocol handler, then the
27251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     constructor tries to load from a system default package.
27351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     <blockquote><pre>
27451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *         &lt;<i>system default package</i>&gt;.&lt;<i>protocol</i>&gt;.Handler
27551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     </pre></blockquote>
27651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     If this class does not exist, or if the class exists but it is not a
27751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     subclass of <code>URLStreamHandler</code>, then a
27851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     <code>MalformedURLException</code> is thrown.
27951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * </ol>
28051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
28151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>Protocol handlers for the following protocols are guaranteed
28251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * to exist on the search path :-
28351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <blockquote><pre>
28451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     http, https, ftp, file, and jar
28551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * </pre></blockquote>
28651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Protocol handlers for additional protocols may also be
28751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * available.
28851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
28951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>No validation of the inputs is performed by this constructor.
29051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
29151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param      protocol   the name of the protocol to use.
29251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param      host       the name of the host.
29351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param      port       the port number on the host.
29451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param      file       the file on the host
29551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception  MalformedURLException  if an unknown protocol is specified.
29651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see        java.lang.System#getProperty(java.lang.String)
29751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see        java.net.URL#setURLStreamHandlerFactory(
29851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *                  java.net.URLStreamHandlerFactory)
29951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see        java.net.URLStreamHandler
30051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see        java.net.URLStreamHandlerFactory#createURLStreamHandler(
30151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *                  java.lang.String)
30251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
30351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public URL(String protocol, String host, int port, String file)
30451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws MalformedURLException
30551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
30651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        this(protocol, host, port, file, null);
30751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
30851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
30951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
31051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Creates a URL from the specified <code>protocol</code>
31151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * name, <code>host</code> name, and <code>file</code> name. The
31251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * default port for the specified protocol is used.
31351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>
31451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * This method is equivalent to calling the four-argument
31551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * constructor with the arguments being <code>protocol</code>,
31651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <code>host</code>, <code>-1</code>, and <code>file</code>.
31751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
31851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * No validation of the inputs is performed by this constructor.
31951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
32051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param      protocol   the name of the protocol to use.
32151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param      host       the name of the host.
32251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param      file       the file on the host.
32351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception  MalformedURLException  if an unknown protocol is specified.
32451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see        java.net.URL#URL(java.lang.String, java.lang.String,
32551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *                  int, java.lang.String)
32651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
32751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public URL(String protocol, String host, String file)
32851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throws MalformedURLException {
32951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        this(protocol, host, -1, file);
33051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
33151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
33251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
33351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Creates a <code>URL</code> object from the specified
33451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <code>protocol</code>, <code>host</code>, <code>port</code>
33551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * number, <code>file</code>, and <code>handler</code>. Specifying
33651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * a <code>port</code> number of <code>-1</code> indicates that
33751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * the URL should use the default port for the protocol. Specifying
33851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * a <code>handler</code> of <code>null</code> indicates that the URL
33951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * should use a default stream handler for the protocol, as outlined
34051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * for:
34151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     java.net.URL#URL(java.lang.String, java.lang.String, int,
34251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *                      java.lang.String)
34351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
34451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>If the handler is not null and there is a security manager,
34551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * the security manager's <code>checkPermission</code>
34651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * method is called with a
34751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <code>NetPermission("specifyStreamHandler")</code> permission.
34851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * This may result in a SecurityException.
34951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
35051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * No validation of the inputs is performed by this constructor.
35151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
35251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param      protocol   the name of the protocol to use.
35351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param      host       the name of the host.
35451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param      port       the port number on the host.
35551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param      file       the file on the host
35651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param      handler    the stream handler for the URL.
35751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception  MalformedURLException  if an unknown protocol is specified.
35851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception  SecurityException
35951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *        if a security manager exists and its
36051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *        <code>checkPermission</code> method doesn't allow
36151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *        specifying a stream handler explicitly.
36251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see        java.lang.System#getProperty(java.lang.String)
36351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see        java.net.URL#setURLStreamHandlerFactory(
36451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *                  java.net.URLStreamHandlerFactory)
36551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see        java.net.URLStreamHandler
36651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see        java.net.URLStreamHandlerFactory#createURLStreamHandler(
36751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *                  java.lang.String)
36851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see        SecurityManager#checkPermission
36951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see        java.net.NetPermission
37051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
37151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public URL(String protocol, String host, int port, String file,
37251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski               URLStreamHandler handler) throws MalformedURLException {
37351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (handler != null) {
37451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            SecurityManager sm = System.getSecurityManager();
37551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (sm != null) {
37651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // check for permission to specify a handler
37751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                checkSpecifyHandler(sm);
37851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
37951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
38051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
38151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        protocol = protocol.toLowerCase();
38251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        this.protocol = protocol;
38351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (host != null) {
38451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
38551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            /**
38651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski             * if host is a literal IPv6 address,
38751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski             * we will make it conform to RFC 2732
38851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski             */
38951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (host.indexOf(':') >= 0 && !host.startsWith("[")) {
39051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                host = "["+host+"]";
39151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
39251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            this.host = host;
39351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
39451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (port < -1) {
39551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                throw new MalformedURLException("Invalid port number :" +
39651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                                    port);
39751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
39851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            this.port = port;
39951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            authority = (port == -1) ? host : host + ":" + port;
40051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
40151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
40206fc5c380e77f61adcf02305c5bbea9eac129583Przemyslaw Szczepaniak        Parts parts = new Parts(file, host);
40351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        path = parts.getPath();
40451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        query = parts.getQuery();
40551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
40651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (query != null) {
40751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            this.file = path + "?" + query;
40851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else {
40951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            this.file = path;
41051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
41151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        ref = parts.getRef();
41251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
41351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Note: we don't do validation of the URL here. Too risky to change
41451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // right now, but worth considering for future reference. -br
41551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (handler == null &&
41651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            (handler = getURLStreamHandler(protocol)) == null) {
41751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new MalformedURLException("unknown protocol: " + protocol);
41851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
41951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        this.handler = handler;
42051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
42151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
42251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
42351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Creates a <code>URL</code> object from the <code>String</code>
42451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * representation.
42551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>
42651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * This constructor is equivalent to a call to the two-argument
42751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * constructor with a <code>null</code> first argument.
42851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
42951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param      spec   the <code>String</code> to parse as a URL.
43051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception  MalformedURLException  if no protocol is specified, or an
43151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *               unknown protocol is found, or <tt>spec</tt> is <tt>null</tt>.
43251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see        java.net.URL#URL(java.net.URL, java.lang.String)
43351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
43451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public URL(String spec) throws MalformedURLException {
43551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        this(null, spec);
43651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
43751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
43851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
43951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Creates a URL by parsing the given spec within a specified context.
44051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
44151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * The new URL is created from the given context URL and the spec
44251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * argument as described in
44351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * RFC2396 &quot;Uniform Resource Identifiers : Generic * Syntax&quot; :
44451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <blockquote><pre>
44551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *          &lt;scheme&gt;://&lt;authority&gt;&lt;path&gt;?&lt;query&gt;#&lt;fragment&gt;
44651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * </pre></blockquote>
44751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * The reference is parsed into the scheme, authority, path, query and
44851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * fragment parts. If the path component is empty and the scheme,
44951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * authority, and query components are undefined, then the new URL is a
45051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * reference to the current document. Otherwise, the fragment and query
45151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * parts present in the spec are used in the new URL.
45251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>
45351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * If the scheme component is defined in the given spec and does not match
45451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * the scheme of the context, then the new URL is created as an absolute
45551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * URL based on the spec alone. Otherwise the scheme component is inherited
45651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * from the context URL.
45751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>
45851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * If the authority component is present in the spec then the spec is
45951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * treated as absolute and the spec authority and path will replace the
46051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * context authority and path. If the authority component is absent in the
46151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * spec then the authority of the new URL will be inherited from the
46251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * context.
46351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>
46451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * If the spec's path component begins with a slash character
46551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * &quot;/&quot; then the
46651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * path is treated as absolute and the spec path replaces the context path.
46751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>
46851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Otherwise, the path is treated as a relative path and is appended to the
46951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * context path, as described in RFC2396. Also, in this case,
47051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * the path is canonicalized through the removal of directory
47151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * changes made by occurences of &quot;..&quot; and &quot;.&quot;.
47251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>
47351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * For a more detailed description of URL parsing, refer to RFC2396.
47451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
47551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param      context   the context in which to parse the specification.
47651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param      spec      the <code>String</code> to parse as a URL.
47751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception  MalformedURLException  if no protocol is specified, or an
47851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *               unknown protocol is found, or <tt>spec</tt> is <tt>null</tt>.
47951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see        java.net.URL#URL(java.lang.String, java.lang.String,
48051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *                  int, java.lang.String)
48151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see        java.net.URLStreamHandler
48251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see        java.net.URLStreamHandler#parseURL(java.net.URL,
48351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *                  java.lang.String, int, int)
48451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
48551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public URL(URL context, String spec) throws MalformedURLException {
48651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        this(context, spec, null);
48751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
48851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
48951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
49051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Creates a URL by parsing the given spec with the specified handler
49151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * within a specified context. If the handler is null, the parsing
49251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * occurs as with the two argument constructor.
49351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
49451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param      context   the context in which to parse the specification.
49551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param      spec      the <code>String</code> to parse as a URL.
49651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param      handler   the stream handler for the URL.
49751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception  MalformedURLException  if no protocol is specified, or an
49851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *               unknown protocol is found, or <tt>spec</tt> is <tt>null</tt>.
49951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception  SecurityException
50051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *        if a security manager exists and its
50151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *        <code>checkPermission</code> method doesn't allow
50251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *        specifying a stream handler.
50351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see        java.net.URL#URL(java.lang.String, java.lang.String,
50451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *                  int, java.lang.String)
50551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see        java.net.URLStreamHandler
50651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see        java.net.URLStreamHandler#parseURL(java.net.URL,
50751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *                  java.lang.String, int, int)
50851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
50951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public URL(URL context, String spec, URLStreamHandler handler)
51051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws MalformedURLException
51151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
51251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        String original = spec;
51351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int i, limit, c;
51451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int start = 0;
51551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        String newProtocol = null;
51651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        boolean aRef=false;
51751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        boolean isRelative = false;
51851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
51951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Check for permission to specify a handler
52051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (handler != null) {
52151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            SecurityManager sm = System.getSecurityManager();
52251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (sm != null) {
52351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                checkSpecifyHandler(sm);
52451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
52551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
52651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
52751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
52851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            limit = spec.length();
52951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            while ((limit > 0) && (spec.charAt(limit - 1) <= ' ')) {
53051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                limit--;        //eliminate trailing whitespace
53151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
53251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            while ((start < limit) && (spec.charAt(start) <= ' ')) {
53351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                start++;        // eliminate leading whitespace
53451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
53551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
53651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (spec.regionMatches(true, start, "url:", 0, 4)) {
53751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                start += 4;
53851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
53951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (start < spec.length() && spec.charAt(start) == '#') {
54051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                /* we're assuming this is a ref relative to the context URL.
54151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                 * This means protocols cannot start w/ '#', but we must parse
54251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                 * ref URL's like: "hello:there" w/ a ':' in them.
54351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                 */
54451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                aRef=true;
54551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
54651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            for (i = start ; !aRef && (i < limit) &&
54751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                     ((c = spec.charAt(i)) != '/') ; i++) {
54851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (c == ':') {
54951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
55051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    String s = spec.substring(start, i).toLowerCase();
55151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (isValidProtocol(s)) {
55251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        newProtocol = s;
55351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        start = i + 1;
55451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
55551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    break;
55651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
55751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
55851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
55951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // Only use our context if the protocols match.
56051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            protocol = newProtocol;
56151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if ((context != null) && ((newProtocol == null) ||
56251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            newProtocol.equalsIgnoreCase(context.protocol))) {
56351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // inherit the protocol handler from the context
56451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // if not specified to the constructor
56551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (handler == null) {
56651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    handler = context.handler;
56751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
56851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
56951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // If the context is a hierarchical URL scheme and the spec
57051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // contains a matching scheme then maintain backwards
57151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // compatibility and treat it as if the spec didn't contain
57251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // the scheme; see 5.2.3 of RFC2396
57351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (context.path != null && context.path.startsWith("/"))
57451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    newProtocol = null;
57551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
57651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (newProtocol == null) {
57751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    protocol = context.protocol;
57851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    authority = context.authority;
57951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    userInfo = context.userInfo;
58051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    host = context.host;
58151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    port = context.port;
58251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    file = context.file;
58351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    path = context.path;
58451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    isRelative = true;
58551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
58651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
58751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
58851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (protocol == null) {
58951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                throw new MalformedURLException("no protocol: "+original);
59051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
59151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
59251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // Get the protocol handler if not specified or the protocol
59351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // of the context could not be used
59451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (handler == null &&
59551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                (handler = getURLStreamHandler(protocol)) == null) {
59651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                throw new MalformedURLException("unknown protocol: "+protocol);
59751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
59851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
59951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            this.handler = handler;
60051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
60151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            i = spec.indexOf('#', start);
60251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (i >= 0) {
60351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                ref = spec.substring(i + 1, limit);
60451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                limit = i;
60551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
60651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
60751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            /*
60851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski             * Handle special case inheritance of query and fragment
60951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski             * implied by RFC2396 section 5.2.2.
61051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski             */
61151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (isRelative && start == limit) {
61251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                query = context.query;
61351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (ref == null) {
61451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    ref = context.ref;
61551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
61651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
61751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
61851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            handler.parseURL(this, spec, start, limit);
61951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
62051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch(MalformedURLException e) {
62151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw e;
62251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch(Exception e) {
62351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            MalformedURLException exception = new MalformedURLException(e.getMessage());
62451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            exception.initCause(e);
62551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw exception;
62651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
62751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
62851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
62951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /*
63051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Returns true if specified string is a valid protocol name.
63151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
63251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private boolean isValidProtocol(String protocol) {
63351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int len = protocol.length();
63451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (len < 1)
63551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return false;
63651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        char c = protocol.charAt(0);
63751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (!Character.isLetter(c))
63851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return false;
63951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        for (int i = 1; i < len; i++) {
64051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            c = protocol.charAt(i);
64151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (!Character.isLetterOrDigit(c) && c != '.' && c != '+' &&
64251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                c != '-') {
64351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return false;
64451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
64551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
64651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return true;
64751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
64851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
64951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /*
65051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Checks for permission to specify a stream handler.
65151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
65251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private void checkSpecifyHandler(SecurityManager sm) {
65351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        sm.checkPermission(SecurityConstants.SPECIFY_HANDLER_PERMISSION);
65451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
65551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
65651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
65751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Sets the fields of the URL. This is not a public method so that
65851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * only URLStreamHandlers can modify URL fields. URLs are
65951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * otherwise constant.
66051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
66151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param protocol the name of the protocol to use
66251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param host the name of the host
66351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski       @param port the port number on the host
66451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param file the file on the host
66551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param ref the internal reference in the URL
66651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
66751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected void set(String protocol, String host,
66851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                       int port, String file, String ref) {
66951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        synchronized (this) {
67051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            this.protocol = protocol;
67151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            this.host = host;
67251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            authority = port == -1 ? host : host + ":" + port;
67351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            this.port = port;
67451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            this.file = file;
67551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            this.ref = ref;
67651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            /* This is very important. We must recompute this after the
67751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski             * URL has been changed. */
67851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            hashCode = -1;
67951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            hostAddress = null;
68051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int q = file.lastIndexOf('?');
68151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (q != -1) {
68251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                query = file.substring(q+1);
68351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                path = file.substring(0, q);
68451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else
68551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                path = file;
68651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
68751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
68851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
68951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
69051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Sets the specified 8 fields of the URL. This is not a public method so
69151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * that only URLStreamHandlers can modify URL fields. URLs are otherwise
69251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * constant.
69351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
69451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param protocol the name of the protocol to use
69551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param host the name of the host
69651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param port the port number on the host
69751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param authority the authority part for the url
69851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param userInfo the username and password
69951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param path the file on the host
70051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param ref the internal reference in the URL
70151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param query the query part of this URL
70251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @since 1.3
70351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
70451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected void set(String protocol, String host, int port,
70551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                       String authority, String userInfo, String path,
70651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                       String query, String ref) {
70751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        synchronized (this) {
70851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            this.protocol = protocol;
70951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            this.host = host;
71051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            this.port = port;
71157acf7ac56d7fed06c96a1451fe7d8570dbb2977Przemyslaw Szczepaniak            this.file = (query == null || query.isEmpty()) ? path : path + "?" + query;
71251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            this.userInfo = userInfo;
71351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            this.path = path;
71451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            this.ref = ref;
71551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            /* This is very important. We must recompute this after the
71651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski             * URL has been changed. */
71751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            hashCode = -1;
71851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            hostAddress = null;
71951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            this.query = query;
72051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            this.authority = authority;
72151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
72251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
72351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
72451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
72551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Gets the query part of this <code>URL</code>.
72651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
72751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return  the query part of this <code>URL</code>,
72851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * or <CODE>null</CODE> if one does not exist
72951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @since 1.3
73051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
73151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public String getQuery() {
73251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return query;
73351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
73451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
73551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
73651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Gets the path part of this <code>URL</code>.
73751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
73851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return  the path part of this <code>URL</code>, or an
73951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * empty string if one does not exist
74051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @since 1.3
74151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
74251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public String getPath() {
74351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return path;
74451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
74551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
74651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
74751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Gets the userInfo part of this <code>URL</code>.
74851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
74951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return  the userInfo part of this <code>URL</code>, or
75051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <CODE>null</CODE> if one does not exist
75151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @since 1.3
75251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
75351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public String getUserInfo() {
75451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return userInfo;
75551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
75651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
75751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
75851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Gets the authority part of this <code>URL</code>.
75951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
76051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return  the authority part of this <code>URL</code>
76151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @since 1.3
76251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
76351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public String getAuthority() {
76451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return authority;
76551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
76651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
76751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
76851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Gets the port number of this <code>URL</code>.
76951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
77051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return  the port number, or -1 if the port is not set
77151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
77251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public int getPort() {
77351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return port;
77451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
77551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
77651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
77751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Gets the default port number of the protocol associated
77851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * with this <code>URL</code>. If the URL scheme or the URLStreamHandler
77951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * for the URL do not define a default port number,
78051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * then -1 is returned.
78151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
78251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return  the port number
78351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @since 1.4
78451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
78551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public int getDefaultPort() {
78651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return handler.getDefaultPort();
78751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
78851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
78951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
79051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Gets the protocol name of this <code>URL</code>.
79151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
79251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return  the protocol of this <code>URL</code>.
79351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
79451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public String getProtocol() {
79551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return protocol;
79651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
79751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
79851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
79951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Gets the host name of this <code>URL</code>, if applicable.
80051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * The format of the host conforms to RFC 2732, i.e. for a
80151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * literal IPv6 address, this method will return the IPv6 address
80251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * enclosed in square brackets (<tt>'['</tt> and <tt>']'</tt>).
80351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
80451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return  the host name of this <code>URL</code>.
80551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
80651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public String getHost() {
80751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return host;
80851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
80951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
81051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
81151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Gets the file name of this <code>URL</code>.
81251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * The returned file portion will be
81351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * the same as <CODE>getPath()</CODE>, plus the concatenation of
81451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * the value of <CODE>getQuery()</CODE>, if any. If there is
81551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * no query portion, this method and <CODE>getPath()</CODE> will
81651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * return identical results.
81751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
81851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return  the file name of this <code>URL</code>,
81951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * or an empty string if one does not exist
82051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
82151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public String getFile() {
82251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return file;
82351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
82451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
82551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
82651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Gets the anchor (also known as the "reference") of this
82751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <code>URL</code>.
82851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
82951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return  the anchor (also known as the "reference") of this
83051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *          <code>URL</code>, or <CODE>null</CODE> if one does not exist
83151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
83251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public String getRef() {
83351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return ref;
83451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
83551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
83651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
83751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Compares this URL for equality with another object.<p>
83851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
83951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * If the given object is not a URL then this method immediately returns
84051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <code>false</code>.<p>
84151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
84251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Two URL objects are equal if they have the same protocol, reference
84351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * equivalent hosts, have the same port number on the host, and the same
84451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * file and fragment of the file.<p>
84551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
846b93dbaedd71dae5c1e4fb2faba863acbde1080c2Narayan Kamath     * Returns true if this URL equals {@code o}. URLs are equal if they have
847b93dbaedd71dae5c1e4fb2faba863acbde1080c2Narayan Kamath     * the same protocol, host, port, file, and reference.
848b93dbaedd71dae5c1e4fb2faba863acbde1080c2Narayan Kamath     *
849b93dbaedd71dae5c1e4fb2faba863acbde1080c2Narayan Kamath     * <h3>Network I/O Warning</h3>
850b93dbaedd71dae5c1e4fb2faba863acbde1080c2Narayan Kamath     * <p>Some implementations of URL.equals() resolve host names over the
851b93dbaedd71dae5c1e4fb2faba863acbde1080c2Narayan Kamath     * network. This is problematic:
852b93dbaedd71dae5c1e4fb2faba863acbde1080c2Narayan Kamath     * <ul>
853b93dbaedd71dae5c1e4fb2faba863acbde1080c2Narayan Kamath     * <li><strong>The network may be slow.</strong> Many classes, including
854b93dbaedd71dae5c1e4fb2faba863acbde1080c2Narayan Kamath     * core collections like {@link java.util.Map Map} and {@link java.util.Set
855b93dbaedd71dae5c1e4fb2faba863acbde1080c2Narayan Kamath     * Set} expect that {@code equals} and {@code hashCode} will return quickly.
856b93dbaedd71dae5c1e4fb2faba863acbde1080c2Narayan Kamath     * By violating this assumption, this method posed potential performance
857b93dbaedd71dae5c1e4fb2faba863acbde1080c2Narayan Kamath     * problems.
858b93dbaedd71dae5c1e4fb2faba863acbde1080c2Narayan Kamath     * <li><strong>Equal IP addresses do not imply equal content.</strong>
859b93dbaedd71dae5c1e4fb2faba863acbde1080c2Narayan Kamath     * Virtual hosting permits unrelated sites to share an IP address. This
860b93dbaedd71dae5c1e4fb2faba863acbde1080c2Narayan Kamath     * method could report two otherwise unrelated URLs to be equal because
861b93dbaedd71dae5c1e4fb2faba863acbde1080c2Narayan Kamath     * they're hosted on the same server.</li>
862b93dbaedd71dae5c1e4fb2faba863acbde1080c2Narayan Kamath     * <li><strong>The network may not be available.</strong> Two URLs could be
863b93dbaedd71dae5c1e4fb2faba863acbde1080c2Narayan Kamath     * equal when a network is available and unequal otherwise.</li>
864b93dbaedd71dae5c1e4fb2faba863acbde1080c2Narayan Kamath     * <li><strong>The network may change.</strong> The IP address for a given
865b93dbaedd71dae5c1e4fb2faba863acbde1080c2Narayan Kamath     * host name varies by network and over time. This is problematic for mobile
866b93dbaedd71dae5c1e4fb2faba863acbde1080c2Narayan Kamath     * devices. Two URLs could be equal on some networks and unequal on
867b93dbaedd71dae5c1e4fb2faba863acbde1080c2Narayan Kamath     * others.</li>
868b93dbaedd71dae5c1e4fb2faba863acbde1080c2Narayan Kamath     * </ul>
869b93dbaedd71dae5c1e4fb2faba863acbde1080c2Narayan Kamath     * <p>This problem is fixed in Android 4.0 (Ice Cream Sandwich). In that
870b93dbaedd71dae5c1e4fb2faba863acbde1080c2Narayan Kamath     * release, URLs are only equal if their host names are equal (ignoring
871b93dbaedd71dae5c1e4fb2faba863acbde1080c2Narayan Kamath     * case).
87251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
87351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param   obj   the URL to compare against.
87451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return  <code>true</code> if the objects are the same;
87551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *          <code>false</code> otherwise.
87651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
87751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public boolean equals(Object obj) {
87851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (!(obj instanceof URL))
87951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return false;
88051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        URL u2 = (URL)obj;
88151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
88251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return handler.equals(this, u2);
88351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
88451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
88551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
88651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Creates an integer suitable for hash table indexing.<p>
88751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
88851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * The hash code is based upon all the URL components relevant for URL
88951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * comparison. As such, this operation is a blocking operation.<p>
89051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
89151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return  a hash code for this <code>URL</code>.
89251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
89351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public synchronized int hashCode() {
89451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (hashCode != -1)
89551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return hashCode;
89651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
89751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        hashCode = handler.hashCode(this);
89851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return hashCode;
89951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
90051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
90151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
90251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Compares two URLs, excluding the fragment component.<p>
90351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
90451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Returns <code>true</code> if this <code>URL</code> and the
90551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <code>other</code> argument are equal without taking the
90651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * fragment component into consideration.
90751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
90851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param   other   the <code>URL</code> to compare against.
90951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return  <code>true</code> if they reference the same remote object;
91051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *          <code>false</code> otherwise.
91151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
91251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public boolean sameFile(URL other) {
91351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return handler.sameFile(this, other);
91451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
91551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
91651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
91751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Constructs a string representation of this <code>URL</code>. The
91851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * string is created by calling the <code>toExternalForm</code>
91951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * method of the stream protocol handler for this object.
92051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
92151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return  a string representation of this object.
92251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see     java.net.URL#URL(java.lang.String, java.lang.String, int,
92351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *                  java.lang.String)
92451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see     java.net.URLStreamHandler#toExternalForm(java.net.URL)
92551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
92651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public String toString() {
92751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return toExternalForm();
92851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
92951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
93051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
93151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Constructs a string representation of this <code>URL</code>. The
93251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * string is created by calling the <code>toExternalForm</code>
93351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * method of the stream protocol handler for this object.
93451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
93551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return  a string representation of this object.
93651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see     java.net.URL#URL(java.lang.String, java.lang.String,
93751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *                  int, java.lang.String)
93851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see     java.net.URLStreamHandler#toExternalForm(java.net.URL)
93951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
94051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public String toExternalForm() {
94151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return handler.toExternalForm(this);
94251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
94351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
94451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
94551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Returns a {@link java.net.URI} equivalent to this URL.
94651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * This method functions in the same way as <code>new URI (this.toString())</code>.
94751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>Note, any URL instance that complies with RFC 2396 can be converted
94851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * to a URI. However, some URLs that are not strictly in compliance
94951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * can not be converted to a URI.
95051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
95151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception URISyntaxException if this URL is not formatted strictly according to
95251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *            to RFC2396 and cannot be converted to a URI.
95351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
95451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return    a URI instance equivalent to this URL.
95551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @since 1.5
95651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
95751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public URI toURI() throws URISyntaxException {
95851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return new URI (toString());
95951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
96051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
96151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
96251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Returns a {@link java.net.URLConnection URLConnection} instance that
96351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * represents a connection to the remote object referred to by the
96451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * {@code URL}.
96551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
96651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <P>A new instance of {@linkplain java.net.URLConnection URLConnection} is
96751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * created every time when invoking the
96851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * {@linkplain java.net.URLStreamHandler#openConnection(URL)
96951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * URLStreamHandler.openConnection(URL)} method of the protocol handler for
97051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * this URL.</P>
97151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
97251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <P>It should be noted that a URLConnection instance does not establish
97351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * the actual network connection on creation. This will happen only when
97451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * calling {@linkplain java.net.URLConnection#connect() URLConnection.connect()}.</P>
97551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
97651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <P>If for the URL's protocol (such as HTTP or JAR), there
97751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * exists a public, specialized URLConnection subclass belonging
97851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * to one of the following packages or one of their subpackages:
97951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * java.lang, java.io, java.util, java.net, the connection
98051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * returned will be of that subclass. For example, for HTTP an
98151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * HttpURLConnection will be returned, and for JAR a
98251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * JarURLConnection will be returned.</P>
98351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
98451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return     a {@link java.net.URLConnection URLConnection} linking
98551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *             to the URL.
98651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception  IOException  if an I/O exception occurs.
98751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see        java.net.URL#URL(java.lang.String, java.lang.String,
98851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *             int, java.lang.String)
98951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
99051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public URLConnection openConnection() throws java.io.IOException {
99151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return handler.openConnection(this);
99251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
99351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
99451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
99551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Same as {@link #openConnection()}, except that the connection will be
99651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * made through the specified proxy; Protocol handlers that do not
99751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * support proxing will ignore the proxy parameter and make a
99851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * normal connection.
99951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
100051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Invoking this method preempts the system's default ProxySelector
100151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * settings.
100251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
100351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param      proxy the Proxy through which this connection
100451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *             will be made. If direct connection is desired,
100551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *             Proxy.NO_PROXY should be specified.
100651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return     a <code>URLConnection</code> to the URL.
100751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception  IOException  if an I/O exception occurs.
100851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception  SecurityException if a security manager is present
100951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *             and the caller doesn't have permission to connect
101051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *             to the proxy.
101151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception  IllegalArgumentException will be thrown if proxy is null,
101251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *             or proxy has the wrong type
101351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception  UnsupportedOperationException if the subclass that
101451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *             implements the protocol handler doesn't support
101551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *             this method.
101651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see        java.net.URL#URL(java.lang.String, java.lang.String,
101751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *             int, java.lang.String)
101851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see        java.net.URLConnection
101951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see        java.net.URLStreamHandler#openConnection(java.net.URL,
102051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *             java.net.Proxy)
102151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @since      1.5
102251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
102351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public URLConnection openConnection(Proxy proxy)
102451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws java.io.IOException {
102551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (proxy == null) {
102651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new IllegalArgumentException("proxy can not be null");
102751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
102851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
102951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Create a copy of Proxy as a security measure
103051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Proxy p = proxy == Proxy.NO_PROXY ? Proxy.NO_PROXY : sun.net.ApplicationProxy.create(proxy);
103151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        SecurityManager sm = System.getSecurityManager();
103251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (p.type() != Proxy.Type.DIRECT && sm != null) {
103351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            InetSocketAddress epoint = (InetSocketAddress) p.address();
103451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (epoint.isUnresolved())
103551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                sm.checkConnect(epoint.getHostName(), epoint.getPort());
103651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            else
103751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                sm.checkConnect(epoint.getAddress().getHostAddress(),
103851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                epoint.getPort());
103951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
104051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return handler.openConnection(this, p);
104151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
104251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
104351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
104451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Opens a connection to this <code>URL</code> and returns an
104551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <code>InputStream</code> for reading from that connection. This
104651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * method is a shorthand for:
104751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <blockquote><pre>
104851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     openConnection().getInputStream()
104951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * </pre></blockquote>
105051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
105151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return     an input stream for reading from the URL connection.
105251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception  IOException  if an I/O exception occurs.
105351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see        java.net.URL#openConnection()
105451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see        java.net.URLConnection#getInputStream()
105551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
105651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public final InputStream openStream() throws java.io.IOException {
105751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return openConnection().getInputStream();
105851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
105951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
106051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
106151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Gets the contents of this URL. This method is a shorthand for:
106251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <blockquote><pre>
106351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     openConnection().getContent()
106451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * </pre></blockquote>
106551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
106651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return     the contents of this URL.
106751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception  IOException  if an I/O exception occurs.
106851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see        java.net.URLConnection#getContent()
106951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
107051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public final Object getContent() throws java.io.IOException {
107151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return openConnection().getContent();
107251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
107351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
107451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
107551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Gets the contents of this URL. This method is a shorthand for:
107651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <blockquote><pre>
107751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     openConnection().getContent(Class[])
107851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * </pre></blockquote>
107951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
108051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param classes an array of Java types
108151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return     the content object of this URL that is the first match of
108251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *               the types specified in the classes array.
108351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *               null if none of the requested types are supported.
108451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception  IOException  if an I/O exception occurs.
108551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see        java.net.URLConnection#getContent(Class[])
108651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @since 1.3
108751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
108851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public final Object getContent(Class[] classes)
108951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    throws java.io.IOException {
109051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return openConnection().getContent(classes);
109151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
109251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
109351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
109451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * The URLStreamHandler factory.
109551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
109651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    static URLStreamHandlerFactory factory;
109751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
109851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
109951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Sets an application's <code>URLStreamHandlerFactory</code>.
110051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * This method can be called at most once in a given Java Virtual
110151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Machine.
110251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
110351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *<p> The <code>URLStreamHandlerFactory</code> instance is used to
110451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *construct a stream protocol handler from a protocol name.
110551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
110651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p> If there is a security manager, this method first calls
110751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * the security manager's <code>checkSetFactory</code> method
110851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * to ensure the operation is allowed.
110951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * This could result in a SecurityException.
111051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
111151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param      fac   the desired factory.
111251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception  Error  if the application has already set a factory.
111351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception  SecurityException  if a security manager exists and its
111451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *             <code>checkSetFactory</code> method doesn't allow
111551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *             the operation.
111651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see        java.net.URL#URL(java.lang.String, java.lang.String,
111751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *             int, java.lang.String)
111851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see        java.net.URLStreamHandlerFactory
111951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see        SecurityManager#checkSetFactory
112051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
112151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static void setURLStreamHandlerFactory(URLStreamHandlerFactory fac) {
112251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        synchronized (streamHandlerLock) {
112351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (factory != null) {
112451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                throw new Error("factory already defined");
112551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
112651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            SecurityManager security = System.getSecurityManager();
112751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (security != null) {
112851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                security.checkSetFactory();
112951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
113051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            handlers.clear();
113151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            factory = fac;
113251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
113351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
113451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
113551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
113651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * A table of protocol handlers.
113751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
113851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    static Hashtable handlers = new Hashtable();
113951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static Object streamHandlerLock = new Object();
114051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
114151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
114251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Returns the Stream Handler.
114351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param protocol the protocol to use
114451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
114551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    static URLStreamHandler getURLStreamHandler(String protocol) {
114651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
114751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        URLStreamHandler handler = (URLStreamHandler)handlers.get(protocol);
114851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (handler == null) {
114951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
115051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            boolean checkedWithFactory = false;
115151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
115251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // Use the factory (if any)
115351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (factory != null) {
115451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                handler = factory.createURLStreamHandler(protocol);
115551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                checkedWithFactory = true;
115651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
115751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
115851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // Try java protocol handler
115951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (handler == null) {
1160f861f1e3bb6be1cd486079fc240337f84836d21cNarayan Kamath                final String packagePrefixList = System.getProperty(protocolPathProp,"");
1161f861f1e3bb6be1cd486079fc240337f84836d21cNarayan Kamath                StringTokenizer packagePrefixIter = new StringTokenizer(packagePrefixList, "|");
116251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
116351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                while (handler == null &&
116451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                       packagePrefixIter.hasMoreTokens()) {
116551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
1166f861f1e3bb6be1cd486079fc240337f84836d21cNarayan Kamath                    String packagePrefix = packagePrefixIter.nextToken().trim();
116751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    try {
1168f861f1e3bb6be1cd486079fc240337f84836d21cNarayan Kamath                        String clsName = packagePrefix + "." + protocol +  ".Handler";
116951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        Class cls = null;
117051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        try {
117151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            ClassLoader cl = ClassLoader.getSystemClassLoader();
1172f861f1e3bb6be1cd486079fc240337f84836d21cNarayan Kamath                            cls = Class.forName(clsName, true, cl);
1173f861f1e3bb6be1cd486079fc240337f84836d21cNarayan Kamath                        } catch (ClassNotFoundException e) {
1174f861f1e3bb6be1cd486079fc240337f84836d21cNarayan Kamath                            ClassLoader contextLoader = Thread.currentThread().getContextClassLoader();
1175f861f1e3bb6be1cd486079fc240337f84836d21cNarayan Kamath                            if (contextLoader != null) {
1176f861f1e3bb6be1cd486079fc240337f84836d21cNarayan Kamath                                cls = Class.forName(clsName, true, contextLoader);
117751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            }
117851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        }
117951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        if (cls != null) {
118051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            handler  =
118151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                              (URLStreamHandler)cls.newInstance();
118251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        }
1183f861f1e3bb6be1cd486079fc240337f84836d21cNarayan Kamath                    } catch (ReflectiveOperationException ignored) {
118451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
118551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
118651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
118751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
1188320a3d38fa5a32ceb5e342e439862604b2626807Przemyslaw Szczepaniak            // Fallback to built-in stream handler.
1189f861f1e3bb6be1cd486079fc240337f84836d21cNarayan Kamath            // Makes okhttp the default http/https handler
1190320a3d38fa5a32ceb5e342e439862604b2626807Przemyslaw Szczepaniak            if (handler == null) {
1191320a3d38fa5a32ceb5e342e439862604b2626807Przemyslaw Szczepaniak                try {
1192320a3d38fa5a32ceb5e342e439862604b2626807Przemyslaw Szczepaniak                    if (protocol.equals("file")) {
1193320a3d38fa5a32ceb5e342e439862604b2626807Przemyslaw Szczepaniak                        handler = (URLStreamHandler)Class.
1194320a3d38fa5a32ceb5e342e439862604b2626807Przemyslaw Szczepaniak                            forName("sun.net.www.protocol.file.Handler").newInstance();
1195320a3d38fa5a32ceb5e342e439862604b2626807Przemyslaw Szczepaniak                    } else if (protocol.equals("ftp")) {
1196320a3d38fa5a32ceb5e342e439862604b2626807Przemyslaw Szczepaniak                        handler = (URLStreamHandler)Class.
1197320a3d38fa5a32ceb5e342e439862604b2626807Przemyslaw Szczepaniak                            forName("sun.net.www.protocol.ftp.Handler").newInstance();
1198320a3d38fa5a32ceb5e342e439862604b2626807Przemyslaw Szczepaniak                    } else if (protocol.equals("jar")) {
1199320a3d38fa5a32ceb5e342e439862604b2626807Przemyslaw Szczepaniak                        handler = (URLStreamHandler)Class.
1200320a3d38fa5a32ceb5e342e439862604b2626807Przemyslaw Szczepaniak                            forName("sun.net.www.protocol.jar.Handler").newInstance();
1201320a3d38fa5a32ceb5e342e439862604b2626807Przemyslaw Szczepaniak                    } else if (protocol.equals("http")) {
1202320a3d38fa5a32ceb5e342e439862604b2626807Przemyslaw Szczepaniak                        handler = (URLStreamHandler)Class.
1203320a3d38fa5a32ceb5e342e439862604b2626807Przemyslaw Szczepaniak                            forName("com.android.okhttp.HttpHandler").newInstance();
1204320a3d38fa5a32ceb5e342e439862604b2626807Przemyslaw Szczepaniak                    } else if (protocol.equals("https")) {
1205320a3d38fa5a32ceb5e342e439862604b2626807Przemyslaw Szczepaniak                        handler = (URLStreamHandler)Class.
1206320a3d38fa5a32ceb5e342e439862604b2626807Przemyslaw Szczepaniak                            forName("com.android.okhttp.HttpsHandler").newInstance();
1207320a3d38fa5a32ceb5e342e439862604b2626807Przemyslaw Szczepaniak                    }
1208320a3d38fa5a32ceb5e342e439862604b2626807Przemyslaw Szczepaniak                } catch (Exception e) {
1209320a3d38fa5a32ceb5e342e439862604b2626807Przemyslaw Szczepaniak                    throw new AssertionError(e);
1210320a3d38fa5a32ceb5e342e439862604b2626807Przemyslaw Szczepaniak                }
1211320a3d38fa5a32ceb5e342e439862604b2626807Przemyslaw Szczepaniak            }
1212320a3d38fa5a32ceb5e342e439862604b2626807Przemyslaw Szczepaniak
121351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            synchronized (streamHandlerLock) {
121451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
121551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                URLStreamHandler handler2 = null;
121651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
121751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // Check again with hashtable just in case another
121851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // thread created a handler since we last checked
121951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                handler2 = (URLStreamHandler)handlers.get(protocol);
122051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
122151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (handler2 != null) {
122251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return handler2;
122351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
122451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
122551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // Check with factory if another thread set a
122651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // factory since our last check
122751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (!checkedWithFactory && factory != null) {
122851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    handler2 = factory.createURLStreamHandler(protocol);
122951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
123051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
123151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (handler2 != null) {
123251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    // The handler from the factory must be given more
123351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    // importance. Discard the default handler that
123451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    // this thread created.
123551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    handler = handler2;
123651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
123751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
123851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // Insert this handler into the hashtable
123951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (handler != null) {
124051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    handlers.put(protocol, handler);
124151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
124251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
124351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
124451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
124551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
124651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return handler;
124751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
124851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
124951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
125051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
125151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * WriteObject is called to save the state of the URL to an
125251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * ObjectOutputStream. The handler is not saved since it is
125351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * specific to this system.
125451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
125551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @serialData the default write object value. When read back in,
125651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * the reader must ensure that calling getURLStreamHandler with
125751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * the protocol variable returns a valid URLStreamHandler and
125851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * throw an IOException if it does not.
125951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
126051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private synchronized void writeObject(java.io.ObjectOutputStream s)
126151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws IOException
126251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
126351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        s.defaultWriteObject(); // write the fields
126451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
126551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
126651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
126751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * readObject is called to restore the state of the URL from the
126851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * stream.  It reads the components of the URL and finds the local
126951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * stream handler.
127051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
127151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private synchronized void readObject(java.io.ObjectInputStream s)
127251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         throws IOException, ClassNotFoundException
127351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
127451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        s.defaultReadObject();  // read the fields
127551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if ((handler = getURLStreamHandler(protocol)) == null) {
127651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new IOException("unknown protocol: " + protocol);
127751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
127851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
127951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Construct authority part
128051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (authority == null &&
128151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            ((host != null && host.length() > 0) || port != -1)) {
128251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (host == null)
128351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                host = "";
128451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            authority = (port == -1) ? host : host + ":" + port;
128551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
128651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // Handle hosts with userInfo in them
128751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int at = host.lastIndexOf('@');
128851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (at != -1) {
128951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                userInfo = host.substring(0, at);
129051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                host = host.substring(at+1);
129151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
129251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else if (authority != null) {
129351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // Construct user info part
129451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int ind = authority.indexOf('@');
129551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (ind != -1)
129651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                userInfo = authority.substring(0, ind);
129751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
129851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
129951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Construct path and query part
130051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        path = null;
130151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        query = null;
130251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (file != null) {
130351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // Fix: only do this if hierarchical?
130451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int q = file.lastIndexOf('?');
130551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (q != -1) {
130651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                query = file.substring(q+1);
130751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                path = file.substring(0, q);
130851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else
130951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                path = file;
131051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
131106fc5c380e77f61adcf02305c5bbea9eac129583Przemyslaw Szczepaniak        hashCode = -1;
131251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
131351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
131451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
131551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiclass Parts {
131651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    String path, query, ref;
131751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
131806fc5c380e77f61adcf02305c5bbea9eac129583Przemyslaw Szczepaniak    Parts(String file, String host) {
131951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int ind = file.indexOf('#');
132051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        ref = ind < 0 ? null: file.substring(ind + 1);
132151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        file = ind < 0 ? file: file.substring(0, ind);
132251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int q = file.lastIndexOf('?');
132351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (q != -1) {
132451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            query = file.substring(q+1);
132551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            path = file.substring(0, q);
132651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else {
132751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            path = file;
132851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
132906fc5c380e77f61adcf02305c5bbea9eac129583Przemyslaw Szczepaniak        if (path != null && path.length() > 0 && path.charAt(0) != '/' &&
133006fc5c380e77f61adcf02305c5bbea9eac129583Przemyslaw Szczepaniak            host != null && !host.isEmpty()) {
1331a53c889dff2031f9eb20594c1a172c6a228c0298Przemyslaw Szczepaniak            path = '/' + path;
1332a53c889dff2031f9eb20594c1a172c6a228c0298Przemyslaw Szczepaniak        }
133351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
133451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
133551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    String getPath() {
133651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return path;
133751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
133851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
133951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    String getQuery() {
134051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return query;
134151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
134251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
134351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    String getRef() {
134451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return ref;
134551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
134651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
1347