151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/*
22c87ad3a45cecf9e344487cad1abfdebe79f2c7cNarayan Kamath * Copyright (C) 2014 The Android Open Source Project
37f4b1b8935a58d3f44351083cf5ef19045761de3Yi Kong * Copyright (c) 1995, 2013, 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;
30b93dbaedd71dae5c1e4fb2faba863acbde1080c2Narayan Kamathimport java.util.Objects;
31b93dbaedd71dae5c1e4fb2faba863acbde1080c2Narayan Kamath
3251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport sun.net.util.IPAddressUtil;
3351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
3451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/**
353a6411ec91b24e73f36301d0075bc7b052894ae9Yi Kong * The abstract class {@code URLStreamHandler} is the common
3651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * superclass for all stream protocol handlers. A stream protocol
3751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * handler knows how to make a connection for a particular protocol
383a6411ec91b24e73f36301d0075bc7b052894ae9Yi Kong * type, such as {@code http} or {@code https}.
3951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>
403a6411ec91b24e73f36301d0075bc7b052894ae9Yi Kong * In most cases, an instance of a {@code URLStreamHandler}
4151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * subclass is not created directly by an application. Rather, the
4251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * first time a protocol name is encountered when constructing a
433a6411ec91b24e73f36301d0075bc7b052894ae9Yi Kong * {@code URL}, the appropriate stream protocol handler is
4451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * automatically loaded.
4551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
4651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @author  James Gosling
4751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see     java.net.URL#URL(java.lang.String, java.lang.String, int, java.lang.String)
4851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @since   JDK1.0
4951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
5051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipublic abstract class URLStreamHandler {
5151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
5251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Opens a connection to the object referenced by the
533a6411ec91b24e73f36301d0075bc7b052894ae9Yi Kong     * {@code URL} argument.
5451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * This method should be overridden by a subclass.
5551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
5651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>If for the handler's protocol (such as HTTP or JAR), there
5751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * exists a public, specialized URLConnection subclass belonging
5851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * to one of the following packages or one of their subpackages:
5951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * java.lang, java.io, java.util, java.net, the connection
6051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * returned will be of that subclass. For example, for HTTP an
6151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * HttpURLConnection will be returned, and for JAR a
6251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * JarURLConnection will be returned.
6351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
6451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param      u   the URL that this connects to.
653a6411ec91b24e73f36301d0075bc7b052894ae9Yi Kong     * @return     a {@code URLConnection} object for the {@code URL}.
6651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception  IOException  if an I/O error occurs while opening the
6751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *               connection.
6851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
6951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    abstract protected URLConnection openConnection(URL u) throws IOException;
7051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
7151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
7251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Same as openConnection(URL), except that the connection will be
7351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * made through the specified proxy; Protocol handlers that do not
7451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * support proxying will ignore the proxy parameter and make a
7551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * normal connection.
7651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
7751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Calling this method preempts the system's default ProxySelector
7851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * settings.
7951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
8051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param      u   the URL that this connects to.
8151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param      p   the proxy through which the connection will be made.
8251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *                 If direct connection is desired, Proxy.NO_PROXY
8351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *                 should be specified.
843a6411ec91b24e73f36301d0075bc7b052894ae9Yi Kong     * @return     a {@code URLConnection} object for the {@code URL}.
8551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception  IOException  if an I/O error occurs while opening the
8651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *               connection.
8751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception  IllegalArgumentException if either u or p is null,
8851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *               or p has the wrong type.
8951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception  UnsupportedOperationException if the subclass that
9051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *               implements the protocol doesn't support this method.
9151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @since      1.5
9251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
9351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected URLConnection openConnection(URL u, Proxy p) throws IOException {
9451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throw new UnsupportedOperationException("Method not implemented.");
9551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
9651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
9751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
983a6411ec91b24e73f36301d0075bc7b052894ae9Yi Kong     * Parses the string representation of a {@code URL} into a
993a6411ec91b24e73f36301d0075bc7b052894ae9Yi Kong     * {@code URL} object.
10051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>
10151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * If there is any inherited context, then it has already been
1023a6411ec91b24e73f36301d0075bc7b052894ae9Yi Kong     * copied into the {@code URL} argument.
10351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>
1043a6411ec91b24e73f36301d0075bc7b052894ae9Yi Kong     * The {@code parseURL} method of {@code URLStreamHandler}
10551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * parses the string representation as if it were an
1063a6411ec91b24e73f36301d0075bc7b052894ae9Yi Kong     * {@code http} specification. Most URL protocol families have a
10751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * similar parsing. A stream protocol handler for a protocol that has
10851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * a different syntax must override this routine.
10951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
1103a6411ec91b24e73f36301d0075bc7b052894ae9Yi Kong     * @param   u       the {@code URL} to receive the result of parsing
11151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *                  the spec.
1123a6411ec91b24e73f36301d0075bc7b052894ae9Yi Kong     * @param   spec    the {@code String} representing the URL that
11351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *                  must be parsed.
11451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param   start   the character index at which to begin parsing. This is
1153a6411ec91b24e73f36301d0075bc7b052894ae9Yi Kong     *                  just past the '{@code :}' (if there is one) that
11651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *                  specifies the determination of the protocol name.
11751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param   limit   the character position to stop parsing at. This is the
11851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *                  end of the string or the position of the
1193a6411ec91b24e73f36301d0075bc7b052894ae9Yi Kong     *                  "{@code #}" character, if present. All information
12051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *                  after the sharp sign indicates an anchor.
12151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
12251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected void parseURL(URL u, String spec, int start, int limit) {
12351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // These fields may receive context content if this was relative URL
12451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        String protocol = u.getProtocol();
12551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        String authority = u.getAuthority();
12651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        String userInfo = u.getUserInfo();
12751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        String host = u.getHost();
12851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int port = u.getPort();
12951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        String path = u.getPath();
13051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        String query = u.getQuery();
13151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
13251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // This field has already been parsed
13351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        String ref = u.getRef();
13451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
13551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        boolean isRelPath = false;
13651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        boolean queryOnly = false;
1378ef423ca0e43afa10f169bbd5df9004ada5daa74Victor Chang        // BEGIN Android-changed: App compat
13806fc5c380e77f61adcf02305c5bbea9eac129583Przemyslaw Szczepaniak        boolean querySet = false;
1398ef423ca0e43afa10f169bbd5df9004ada5daa74Victor Chang        // END Android-changed: App compat
14051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
1417f4b1b8935a58d3f44351083cf5ef19045761de3Yi Kong// FIX: should not assume query if opaque
14251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Strip off the query part
14351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (start < limit) {
14451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int queryStart = spec.indexOf('?');
14551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            queryOnly = queryStart == start;
14651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if ((queryStart != -1) && (queryStart < limit)) {
14751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                query = spec.substring(queryStart+1, limit);
14851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (limit > queryStart)
14951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    limit = queryStart;
15051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                spec = spec.substring(0, queryStart);
1518ef423ca0e43afa10f169bbd5df9004ada5daa74Victor Chang                // BEGIN Android-changed: App compat
15206fc5c380e77f61adcf02305c5bbea9eac129583Przemyslaw Szczepaniak                querySet = true;
1538ef423ca0e43afa10f169bbd5df9004ada5daa74Victor Chang                // END Android-changed: App compat
15451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
15551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
15651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
15751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int i = 0;
15851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Parse the authority part if any
1598ef423ca0e43afa10f169bbd5df9004ada5daa74Victor Chang        // BEGIN Android-changed: App compat
16006fc5c380e77f61adcf02305c5bbea9eac129583Przemyslaw Szczepaniak        // boolean isUNCName = (start <= limit - 4) &&
16106fc5c380e77f61adcf02305c5bbea9eac129583Przemyslaw Szczepaniak        //                 (spec.charAt(start) == '/') &&
16206fc5c380e77f61adcf02305c5bbea9eac129583Przemyslaw Szczepaniak        //                 (spec.charAt(start + 1) == '/') &&
16306fc5c380e77f61adcf02305c5bbea9eac129583Przemyslaw Szczepaniak        //                 (spec.charAt(start + 2) == '/') &&
16406fc5c380e77f61adcf02305c5bbea9eac129583Przemyslaw Szczepaniak        //                 (spec.charAt(start + 3) == '/');
16506fc5c380e77f61adcf02305c5bbea9eac129583Przemyslaw Szczepaniak        boolean isUNCName = false;
1668ef423ca0e43afa10f169bbd5df9004ada5daa74Victor Chang        // END Android-changed: App compat
16751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (!isUNCName && (start <= limit - 2) && (spec.charAt(start) == '/') &&
16851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            (spec.charAt(start + 1) == '/')) {
16951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            start += 2;
17051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            i = spec.indexOf('/', start);
1717247f6a70e89efb4696aaaffaf7a0325604a6e06Yi Kong            if (i < 0 || i > limit) {
17251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                i = spec.indexOf('?', start);
1737247f6a70e89efb4696aaaffaf7a0325604a6e06Yi Kong                if (i < 0 || i > limit)
17451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    i = limit;
17551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
17651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
17751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            host = authority = spec.substring(start, i);
17851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
17951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int ind = authority.indexOf('@');
18051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (ind != -1) {
1817247f6a70e89efb4696aaaffaf7a0325604a6e06Yi Kong                if (ind != authority.lastIndexOf('@')) {
1827247f6a70e89efb4696aaaffaf7a0325604a6e06Yi Kong                    // more than one '@' in authority. This is not server based
1837247f6a70e89efb4696aaaffaf7a0325604a6e06Yi Kong                    userInfo = null;
1847247f6a70e89efb4696aaaffaf7a0325604a6e06Yi Kong                    host = null;
1857247f6a70e89efb4696aaaffaf7a0325604a6e06Yi Kong                } else {
1867247f6a70e89efb4696aaaffaf7a0325604a6e06Yi Kong                    userInfo = authority.substring(0, ind);
1877247f6a70e89efb4696aaaffaf7a0325604a6e06Yi Kong                    host = authority.substring(ind+1);
1887247f6a70e89efb4696aaaffaf7a0325604a6e06Yi Kong                }
18951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else {
19051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                userInfo = null;
19151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
19251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (host != null) {
19351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // If the host is surrounded by [ and ] then its an IPv6
19451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // literal address as specified in RFC2732
19551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (host.length()>0 && (host.charAt(0) == '[')) {
19651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if ((ind = host.indexOf(']')) > 2) {
19751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
19851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        String nhost = host ;
19951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        host = nhost.substring(0,ind+1);
20051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        if (!IPAddressUtil.
20151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            isIPv6LiteralAddress(host.substring(1, ind))) {
20251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            throw new IllegalArgumentException(
20351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                "Invalid host: "+ host);
20451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        }
20551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
20651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        port = -1 ;
20751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        if (nhost.length() > ind+1) {
20851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            if (nhost.charAt(ind+1) == ':') {
20951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                ++ind ;
21051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                // port can be null according to RFC2396
21151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                if (nhost.length() > (ind + 1)) {
21251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                    port = Integer.parseInt(nhost.substring(ind+1));
21351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                }
21451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            } else {
21551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                throw new IllegalArgumentException(
21651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                    "Invalid authority field: " + authority);
21751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            }
21851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        }
21951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    } else {
22051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        throw new IllegalArgumentException(
22151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            "Invalid authority field: " + authority);
22251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
22351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } else {
22451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    ind = host.indexOf(':');
22551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    port = -1;
22651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (ind >= 0) {
22751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        // port can be null according to RFC2396
22851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        if (host.length() > (ind + 1)) {
2298ef423ca0e43afa10f169bbd5df9004ada5daa74Victor Chang                            // BEGIN Android-changed: App compat
23006fc5c380e77f61adcf02305c5bbea9eac129583Przemyslaw Szczepaniak                            // port = Integer.parseInt(host.substring(ind + 1));
23106fc5c380e77f61adcf02305c5bbea9eac129583Przemyslaw Szczepaniak                            char firstPortChar = host.charAt(ind+1);
23206fc5c380e77f61adcf02305c5bbea9eac129583Przemyslaw Szczepaniak                            if (firstPortChar >= '0' && firstPortChar <= '9') {
23306fc5c380e77f61adcf02305c5bbea9eac129583Przemyslaw Szczepaniak                                port = Integer.parseInt(host.substring(ind + 1));
23406fc5c380e77f61adcf02305c5bbea9eac129583Przemyslaw Szczepaniak                            } else {
23506fc5c380e77f61adcf02305c5bbea9eac129583Przemyslaw Szczepaniak                                throw new IllegalArgumentException("invalid port: " +
23606fc5c380e77f61adcf02305c5bbea9eac129583Przemyslaw Szczepaniak                                                                   host.substring(ind + 1));
23706fc5c380e77f61adcf02305c5bbea9eac129583Przemyslaw Szczepaniak                            }
2388ef423ca0e43afa10f169bbd5df9004ada5daa74Victor Chang                            // END Android-changed: App compat
23951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        }
24051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        host = host.substring(0, ind);
24151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
24251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
24351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else {
24451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                host = "";
24551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
24651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (port < -1)
24751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                throw new IllegalArgumentException("Invalid port number :" +
24851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                                   port);
24951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            start = i;
25006fc5c380e77f61adcf02305c5bbea9eac129583Przemyslaw Szczepaniak
25151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // If the authority is defined then the path is defined by the
25251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // spec only; See RFC 2396 Section 5.2.4.
2538ef423ca0e43afa10f169bbd5df9004ada5daa74Victor Chang            // BEGIN Android-changed: App compat
25406fc5c380e77f61adcf02305c5bbea9eac129583Przemyslaw Szczepaniak            // if (authority != null && authority.length() > 0)
25506fc5c380e77f61adcf02305c5bbea9eac129583Przemyslaw Szczepaniak            //   path = "";
25606fc5c380e77f61adcf02305c5bbea9eac129583Przemyslaw Szczepaniak            path = null;
25706fc5c380e77f61adcf02305c5bbea9eac129583Przemyslaw Szczepaniak            if (!querySet) {
25806fc5c380e77f61adcf02305c5bbea9eac129583Przemyslaw Szczepaniak                query = null;
25906fc5c380e77f61adcf02305c5bbea9eac129583Przemyslaw Szczepaniak            }
2608ef423ca0e43afa10f169bbd5df9004ada5daa74Victor Chang            // END Android-changed: App compat
26151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
26251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
26351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (host == null) {
26451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            host = "";
26551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
26651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
26751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Parse the file path if any
26851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (start < limit) {
26951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (spec.charAt(start) == '/') {
27051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                path = spec.substring(start, limit);
27151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else if (path != null && path.length() > 0) {
27251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                isRelPath = true;
27351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                int ind = path.lastIndexOf('/');
27451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                String seperator = "";
27551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (ind == -1 && authority != null)
27651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    seperator = "/";
27751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                path = path.substring(0, ind + 1) + seperator +
27851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                         spec.substring(start, limit);
27951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
28051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else {
28151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                String seperator = (authority != null) ? "/" : "";
28251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                path = seperator + spec.substring(start, limit);
28351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
28451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
2858ef423ca0e43afa10f169bbd5df9004ada5daa74Victor Chang        // BEGIN Android-changed: App compat
286e4dc89b637bb77dc97fb33a84339fbfe83abe567Przemyslaw Szczepaniak        //else if (queryOnly && path != null) {
287e4dc89b637bb77dc97fb33a84339fbfe83abe567Przemyslaw Szczepaniak        //    int ind = path.lastIndexOf('/');
288e4dc89b637bb77dc97fb33a84339fbfe83abe567Przemyslaw Szczepaniak        //    if (ind < 0)
289e4dc89b637bb77dc97fb33a84339fbfe83abe567Przemyslaw Szczepaniak        //        ind = 0;
290e4dc89b637bb77dc97fb33a84339fbfe83abe567Przemyslaw Szczepaniak        //    path = path.substring(0, ind) + "/";
291e4dc89b637bb77dc97fb33a84339fbfe83abe567Przemyslaw Szczepaniak        //}
2928ef423ca0e43afa10f169bbd5df9004ada5daa74Victor Chang        // END Android-changed: App compat
29351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (path == null)
29451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            path = "";
29551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
2966975f84c2ed72e1e26d20190b6f318718c849008Tobias Thierer        // BEGIN Android-changed
297a53c889dff2031f9eb20594c1a172c6a228c0298Przemyslaw Szczepaniak        //if (isRelPath) {
298a53c889dff2031f9eb20594c1a172c6a228c0298Przemyslaw Szczepaniak        if (true) {
2996975f84c2ed72e1e26d20190b6f318718c849008Tobias Thierer        // END Android-changed
30051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // Remove embedded /./
30151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            while ((i = path.indexOf("/./")) >= 0) {
30251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                path = path.substring(0, i) + path.substring(i + 2);
30351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
30451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // Remove embedded /../ if possible
30551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            i = 0;
30651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            while ((i = path.indexOf("/../", i)) >= 0) {
3078ef423ca0e43afa10f169bbd5df9004ada5daa74Victor Chang                // BEGIN Android-changed: App compat
308e4dc89b637bb77dc97fb33a84339fbfe83abe567Przemyslaw Szczepaniak                /*
309e4dc89b637bb77dc97fb33a84339fbfe83abe567Przemyslaw Szczepaniak                 * Trailing /../
310e4dc89b637bb77dc97fb33a84339fbfe83abe567Przemyslaw Szczepaniak                 */
311e4dc89b637bb77dc97fb33a84339fbfe83abe567Przemyslaw Szczepaniak                if (i == 0) {
312e4dc89b637bb77dc97fb33a84339fbfe83abe567Przemyslaw Szczepaniak                    path = path.substring(i + 3);
313e4dc89b637bb77dc97fb33a84339fbfe83abe567Przemyslaw Szczepaniak                    i = 0;
3148ef423ca0e43afa10f169bbd5df9004ada5daa74Victor Chang                // END Android-changed: App compat
31551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                /*
31651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                 * A "/../" will cancel the previous segment and itself,
31751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                 * unless that segment is a "/../" itself
31851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                 * i.e. "/a/b/../c" becomes "/a/c"
31951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                 * but "/../../a" should stay unchanged
32051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                 */
3218ef423ca0e43afa10f169bbd5df9004ada5daa74Victor Chang                // Android-changed: App compat
3228ef423ca0e43afa10f169bbd5df9004ada5daa74Victor Chang                // if (i > 0 && (limit = path.lastIndexOf('/', i - 1)) >= 0 &&
323e4dc89b637bb77dc97fb33a84339fbfe83abe567Przemyslaw Szczepaniak                } else if (i > 0 && (limit = path.lastIndexOf('/', i - 1)) >= 0 &&
32451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    (path.indexOf("/../", limit) != 0)) {
32551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    path = path.substring(0, limit) + path.substring(i + 3);
32651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    i = 0;
32751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } else {
32851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    i = i + 3;
32951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
33051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
33151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // Remove trailing .. if possible
33251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            while (path.endsWith("/..")) {
33351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                i = path.indexOf("/..");
33451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if ((limit = path.lastIndexOf('/', i - 1)) >= 0) {
33551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    path = path.substring(0, limit+1);
33651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } else {
33751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    break;
33851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
33951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
34051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // Remove starting .
34151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (path.startsWith("./") && path.length() > 2)
34251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                path = path.substring(2);
34351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
34451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // Remove trailing .
34551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (path.endsWith("/."))
34651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                path = path.substring(0, path.length() -1);
347e56459a04d499071dd682bbb906946798b71eaa5Przemyslaw Szczepaniak
3488ef423ca0e43afa10f169bbd5df9004ada5daa74Victor Chang            // Android-changed: App compat: Remove trailing ?
349e56459a04d499071dd682bbb906946798b71eaa5Przemyslaw Szczepaniak            if (path.endsWith("?"))
350e56459a04d499071dd682bbb906946798b71eaa5Przemyslaw Szczepaniak                path = path.substring(0, path.length() -1);
35151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
35251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
35351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        setURL(u, protocol, host, port, authority, userInfo, path, query, ref);
35451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
35551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
35651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
35751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Returns the default port for a URL parsed by this handler. This method
35851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * is meant to be overidden by handlers with default port numbers.
3593a6411ec91b24e73f36301d0075bc7b052894ae9Yi Kong     * @return the default port for a {@code URL} parsed by this handler.
36051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @since 1.3
36151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
36251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected int getDefaultPort() {
36351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return -1;
36451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
36551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
36651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
36751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Provides the default equals calculation. May be overidden by handlers
36851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * for other protocols that have different requirements for equals().
36951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * This method requires that none of its arguments is null. This is
37051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * guaranteed by the fact that it is only called by java.net.URL class.
37151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param u1 a URL object
37251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param u2 a URL object
3733a6411ec91b24e73f36301d0075bc7b052894ae9Yi Kong     * @return {@code true} if the two urls are
37451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * considered equal, ie. they refer to the same
37551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * fragment in the same file.
37651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @since 1.3
37751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
37851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected boolean equals(URL u1, URL u2) {
3798ef423ca0e43afa10f169bbd5df9004ada5daa74Victor Chang        // Android-changed: Avoid network I/O
380b93dbaedd71dae5c1e4fb2faba863acbde1080c2Narayan Kamath        return Objects.equals(u1.getRef(), u2.getRef()) &&
381b93dbaedd71dae5c1e4fb2faba863acbde1080c2Narayan Kamath               Objects.equals(u1.getQuery(), u2.getQuery()) &&
382b93dbaedd71dae5c1e4fb2faba863acbde1080c2Narayan Kamath               // sameFile compares the protocol, file, port & host components of
383b93dbaedd71dae5c1e4fb2faba863acbde1080c2Narayan Kamath               // the URLs.
38451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski               sameFile(u1, u2);
38551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
38651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
38751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
38851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Provides the default hash calculation. May be overidden by handlers for
38951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * other protocols that have different requirements for hashCode
39051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * calculation.
39151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param u a URL object
3923a6411ec91b24e73f36301d0075bc7b052894ae9Yi Kong     * @return an {@code int} suitable for hash table indexing
39351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @since 1.3
39451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
39551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected int hashCode(URL u) {
3968ef423ca0e43afa10f169bbd5df9004ada5daa74Victor Chang        // Android-changed: Avoid network I/O
397b93dbaedd71dae5c1e4fb2faba863acbde1080c2Narayan Kamath        // Hash on the same set of fields that we compare in equals().
398b93dbaedd71dae5c1e4fb2faba863acbde1080c2Narayan Kamath        return Objects.hash(
399b93dbaedd71dae5c1e4fb2faba863acbde1080c2Narayan Kamath                u.getRef(),
400b93dbaedd71dae5c1e4fb2faba863acbde1080c2Narayan Kamath                u.getQuery(),
401b93dbaedd71dae5c1e4fb2faba863acbde1080c2Narayan Kamath                u.getProtocol(),
402b93dbaedd71dae5c1e4fb2faba863acbde1080c2Narayan Kamath                u.getFile(),
403b93dbaedd71dae5c1e4fb2faba863acbde1080c2Narayan Kamath                u.getHost(),
404b93dbaedd71dae5c1e4fb2faba863acbde1080c2Narayan Kamath                u.getPort());
40551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
40651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
40751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
40851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Compare two urls to see whether they refer to the same file,
40951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * i.e., having the same protocol, host, port, and path.
41051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * This method requires that none of its arguments is null. This is
41151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * guaranteed by the fact that it is only called indirectly
41251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * by java.net.URL class.
41351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param u1 a URL object
41451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param u2 a URL object
41551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return true if u1 and u2 refer to the same file
41651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @since 1.3
41751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
41851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected boolean sameFile(URL u1, URL u2) {
41951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Compare the protocols.
42051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (!((u1.getProtocol() == u2.getProtocol()) ||
42151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski              (u1.getProtocol() != null &&
42251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski               u1.getProtocol().equalsIgnoreCase(u2.getProtocol()))))
42351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return false;
42451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
42551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Compare the files.
42651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (!(u1.getFile() == u2.getFile() ||
42751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski              (u1.getFile() != null && u1.getFile().equals(u2.getFile()))))
42851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return false;
42951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
43051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Compare the ports.
43151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int port1, port2;
43251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        port1 = (u1.getPort() != -1) ? u1.getPort() : u1.handler.getDefaultPort();
43351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        port2 = (u2.getPort() != -1) ? u2.getPort() : u2.handler.getDefaultPort();
43451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (port1 != port2)
43551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return false;
43651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
43751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Compare the hosts.
43851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (!hostsEqual(u1, u2))
43951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return false;
44051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
44151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return true;
44251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
44351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
44451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
44551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Get the IP address of our host. An empty host field or a DNS failure
44651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * will result in a null return.
44751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
44851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param u a URL object
4493a6411ec91b24e73f36301d0075bc7b052894ae9Yi Kong     * @return an {@code InetAddress} representing the host
45051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * IP address.
45151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @since 1.3
45251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
45351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected synchronized InetAddress getHostAddress(URL u) {
45451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (u.hostAddress != null)
45551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return u.hostAddress;
45651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
45751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        String host = u.getHost();
45851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (host == null || host.equals("")) {
45951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return null;
46051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else {
46151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            try {
46251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                u.hostAddress = InetAddress.getByName(host);
46351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } catch (UnknownHostException ex) {
46451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return null;
46551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } catch (SecurityException se) {
46651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return null;
46751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
46851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
46951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return u.hostAddress;
47051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
47151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
47251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
47351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Compares the host components of two URLs.
47451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param u1 the URL of the first host to compare
47551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param u2 the URL of the second host to compare
4763a6411ec91b24e73f36301d0075bc7b052894ae9Yi Kong     * @return  {@code true} if and only if they
4773a6411ec91b24e73f36301d0075bc7b052894ae9Yi Kong     * are equal, {@code false} otherwise.
47851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @since 1.3
47951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
48051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected boolean hostsEqual(URL u1, URL u2) {
4816975f84c2ed72e1e26d20190b6f318718c849008Tobias Thierer        // Android-changed: Don't compare the InetAddresses of the hosts.
48206fc5c380e77f61adcf02305c5bbea9eac129583Przemyslaw Szczepaniak        if (u1.getHost() != null && u2.getHost() != null)
48351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return u1.getHost().equalsIgnoreCase(u2.getHost());
48451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         else
48551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return u1.getHost() == null && u2.getHost() == null;
48651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
48751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
48851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
4893a6411ec91b24e73f36301d0075bc7b052894ae9Yi Kong     * Converts a {@code URL} of a specific protocol to a
4903a6411ec91b24e73f36301d0075bc7b052894ae9Yi Kong     * {@code String}.
49151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
49251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param   u   the URL.
4933a6411ec91b24e73f36301d0075bc7b052894ae9Yi Kong     * @return  a string representation of the {@code URL} argument.
49451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
49551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected String toExternalForm(URL u) {
4963a6411ec91b24e73f36301d0075bc7b052894ae9Yi Kong
49751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // pre-compute length of StringBuffer
49851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int len = u.getProtocol().length() + 1;
49951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (u.getAuthority() != null && u.getAuthority().length() > 0)
50051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            len += 2 + u.getAuthority().length();
50151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (u.getPath() != null) {
50251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            len += u.getPath().length();
50351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
50451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (u.getQuery() != null) {
50551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            len += 1 + u.getQuery().length();
50651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
50751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (u.getRef() != null)
50851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            len += 1 + u.getRef().length();
50951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
5108ef423ca0e43afa10f169bbd5df9004ada5daa74Victor Chang        // BEGIN Android-changed: Add a toExternalForm variant that optionally escapes illegal chars
5118ef423ca0e43afa10f169bbd5df9004ada5daa74Victor Chang        // TODO: The variant has been removed. We can potentially revert the change
512f7ab2bc37debba91864bfec6572a3e7bbe994c58Piotr Jastrzebski        StringBuilder result = new StringBuilder(len);
51351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        result.append(u.getProtocol());
51451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        result.append(":");
51506fc5c380e77f61adcf02305c5bbea9eac129583Przemyslaw Szczepaniak        if (u.getAuthority() != null) {// ANDROID: && u.getAuthority().length() > 0) {
51651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            result.append("//");
517fe6fe17d1ca75ee039df7ab93314f3f1e068794fNarayan Kamath            result.append(u.getAuthority());
51851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
519f7ab2bc37debba91864bfec6572a3e7bbe994c58Piotr Jastrzebski        String fileAndQuery = u.getFile();
520f7ab2bc37debba91864bfec6572a3e7bbe994c58Piotr Jastrzebski        if (fileAndQuery != null) {
521fe6fe17d1ca75ee039df7ab93314f3f1e068794fNarayan Kamath            result.append(fileAndQuery);
52251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
5238ef423ca0e43afa10f169bbd5df9004ada5daa74Victor Chang        // END Android-changed: Add a toExternalForm variant that optionally escapes illegal chars
52451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (u.getRef() != null) {
52551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            result.append("#");
526fe6fe17d1ca75ee039df7ab93314f3f1e068794fNarayan Kamath            result.append(u.getRef());
52751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
52851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return result.toString();
52951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
53051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
53151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
5323a6411ec91b24e73f36301d0075bc7b052894ae9Yi Kong     * Sets the fields of the {@code URL} argument to the indicated values.
5333a6411ec91b24e73f36301d0075bc7b052894ae9Yi Kong     * Only classes derived from URLStreamHandler are able
5343a6411ec91b24e73f36301d0075bc7b052894ae9Yi Kong     * to use this method to set the values of the URL fields.
53551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
53651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param   u         the URL to modify.
53751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param   protocol  the protocol name.
53851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param   host      the remote host value for the URL.
53951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param   port      the port on the remote machine.
54051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param   authority the authority part for the URL.
54151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param   userInfo the userInfo part of the URL.
54251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param   path      the path component of the URL.
54351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param   query     the query part for the URL.
54451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param   ref       the reference.
54551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception       SecurityException       if the protocol handler of the URL is
54651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *                                  different from this one
54751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see     java.net.URL#set(java.lang.String, java.lang.String, int, java.lang.String, java.lang.String)
54851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @since 1.3
54951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
55051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski       protected void setURL(URL u, String protocol, String host, int port,
55151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                             String authority, String userInfo, String path,
55251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                             String query, String ref) {
55351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (this != u.handler) {
55451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new SecurityException("handler for url different from " +
55551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                        "this handler");
55651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
55751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // ensure that no one can reset the protocol on a given URL.
55851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        u.set(u.getProtocol(), host, port, authority, userInfo, path, query, ref);
55951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
56051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
56151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
5623a6411ec91b24e73f36301d0075bc7b052894ae9Yi Kong     * Sets the fields of the {@code URL} argument to the indicated values.
5633a6411ec91b24e73f36301d0075bc7b052894ae9Yi Kong     * Only classes derived from URLStreamHandler are able
5643a6411ec91b24e73f36301d0075bc7b052894ae9Yi Kong     * to use this method to set the values of the URL fields.
56551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
56651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param   u         the URL to modify.
56751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param   protocol  the protocol name. This value is ignored since 1.2.
56851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param   host      the remote host value for the URL.
56951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param   port      the port on the remote machine.
57051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param   file      the file.
57151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param   ref       the reference.
57251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception       SecurityException       if the protocol handler of the URL is
57351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *                                  different from this one
57451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @deprecated Use setURL(URL, String, String, int, String, String, String,
57551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *             String);
57651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
57751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    @Deprecated
57851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected void setURL(URL u, String protocol, String host, int port,
57951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                          String file, String ref) {
58051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /*
58151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Only old URL handlers call this, so assume that the host
58251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * field might contain "user:passwd@host". Fix as necessary.
58351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
58451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        String authority = null;
58551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        String userInfo = null;
58651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (host != null && host.length() != 0) {
58751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            authority = (port == -1) ? host : host + ":" + port;
58851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int at = host.lastIndexOf('@');
58951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (at != -1) {
59051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                userInfo = host.substring(0, at);
59151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                host = host.substring(at+1);
59251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
59351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
59451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
59551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /*
59651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Assume file might contain query part. Fix as necessary.
59751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
59851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        String path = null;
59951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        String query = null;
60051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (file != null) {
60151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int q = file.lastIndexOf('?');
60251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (q != -1) {
60351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                query = file.substring(q+1);
60451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                path = file.substring(0, q);
60551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else
60651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                path = file;
60751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
60851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        setURL(u, protocol, host, port, authority, userInfo, path, query, ref);
60951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
61051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
611