1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  Licensed to the Apache Software Foundation (ASF) under one or more
3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  contributor license agreements.  See the NOTICE file distributed with
4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  this work for additional information regarding copyright ownership.
5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  The ASF licenses this file to You under the Apache License, Version 2.0
6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  (the "License"); you may not use this file except in compliance with
7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  the License.  You may obtain a copy of the License at
8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *     http://www.apache.org/licenses/LICENSE-2.0
10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  Unless required by applicable law or agreed to in writing, software
12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  distributed under the License is distributed on an "AS IS" BASIS,
13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  See the License for the specific language governing permissions and
15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  limitations under the License.
16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpackage java.net;
19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.IOException;
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.apache.harmony.luni.util.Msg;
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.apache.harmony.luni.util.URLUtil;
24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/**
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The abstract class {@code URLStreamHandler} is the base for all classes which
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * can handle the communication with a URL object over a particular protocol
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * type.
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic abstract class URLStreamHandler {
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Establishes a new connection to the resource specified by the URL {@code
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * u}. Since different protocols also have unique ways of connecting, it
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * must be overwritten by the subclass.
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param u
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the URL to the resource where a connection has to be opened.
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return the opened URLConnection to the specified resource.
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws IOException
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if an I/O error occurs during opening the connection.
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected abstract URLConnection openConnection(URL u) throws IOException;
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Establishes a new connection to the resource specified by the URL {@code
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * u} using the given {@code proxy}. Since different protocols also have
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * unique ways of connecting, it must be overwritten by the subclass.
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param u
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the URL to the resource where a connection has to be opened.
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param proxy
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the proxy that is used to make the connection.
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return the opened URLConnection to the specified resource.
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws IOException
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if an I/O error occurs during opening the connection.
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws IllegalArgumentException
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if any argument is {@code null} or the type of proxy is
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             wrong.
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws UnsupportedOperationException
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if the protocol handler doesn't support this method.
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected URLConnection openConnection(URL u, Proxy proxy)
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throws IOException {
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        throw new UnsupportedOperationException(Msg.getString("K034d")); //$NON-NLS-1$
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Parses the clear text URL in {@code str} into a URL object. URL strings
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * generally have the following format:
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <p>
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * http://www.company.com/java/file1.java#reference
723819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     * <p>
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The string is parsed in HTTP format. If the protocol has a different URL
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * format this method must be overridden.
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param u
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the URL to fill in the parsed clear text URL parts.
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param str
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the URL string that is to be parsed.
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param start
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the string position from where to begin parsing.
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param end
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the string position to stop parsing.
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @see #toExternalForm
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @see URL
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected void parseURL(URL u, String str, int start, int end) {
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // For compatibility, refer to Harmony-2941
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (str.startsWith("//", start) //$NON-NLS-1$
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                && str.indexOf('/', start + 2) == -1
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                && end <= Integer.MIN_VALUE + 1) {
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new StringIndexOutOfBoundsException(end - 2 - start);
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (end < start) {
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (this != u.strmHandler) {
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                throw new SecurityException();
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return;
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        String parseString = ""; //$NON-NLS-1$
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (start < end) {
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            parseString = str.substring(start, end);
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        end -= start;
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int fileIdx = 0;
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // Default is to use info from context
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        String host = u.getHost();
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int port = u.getPort();
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        String ref = u.getRef();
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        String file = u.getPath();
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        String query = u.getQuery();
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        String authority = u.getAuthority();
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        String userInfo = u.getUserInfo();
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int refIdx = parseString.indexOf('#', 0);
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (parseString.startsWith("//")) { //$NON-NLS-1$
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int hostIdx = 2, portIdx = -1;
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            port = -1;
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            fileIdx = parseString.indexOf('/', hostIdx);
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int questionMarkIndex = parseString.indexOf('?', hostIdx);
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if ((questionMarkIndex != -1)
123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    && ((fileIdx == -1) || (fileIdx > questionMarkIndex))) {
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                fileIdx = questionMarkIndex;
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (fileIdx == -1) {
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                fileIdx = end;
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // Use default
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                file = ""; //$NON-NLS-1$
130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int hostEnd = fileIdx;
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (refIdx != -1 && refIdx < fileIdx) {
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                hostEnd = refIdx;
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int userIdx = parseString.lastIndexOf('@', hostEnd);
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            authority = parseString.substring(hostIdx, hostEnd);
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (userIdx > -1) {
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                userInfo = parseString.substring(hostIdx, userIdx);
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                hostIdx = userIdx + 1;
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            portIdx = parseString.indexOf(':', userIdx == -1 ? hostIdx
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    : userIdx);
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int endOfIPv6Addr = parseString.indexOf(']');
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // if there are square braces, ie. IPv6 address, use last ':'
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (endOfIPv6Addr != -1) {
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                try {
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if (parseString.length() > endOfIPv6Addr + 1) {
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        char c = parseString.charAt(endOfIPv6Addr + 1);
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        if (c == ':') {
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            portIdx = endOfIPv6Addr + 1;
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        } else {
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            portIdx = -1;
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        }
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    } else {
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        portIdx = -1;
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                } catch (Exception e) {
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    // Ignored
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (portIdx == -1 || portIdx > fileIdx) {
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                host = parseString.substring(hostIdx, hostEnd);
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                host = parseString.substring(hostIdx, portIdx);
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                String portString = parseString.substring(portIdx + 1, hostEnd);
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (portString.length() == 0) {
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    port = -1;
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                } else {
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    port = Integer.parseInt(portString);
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (refIdx > -1) {
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ref = parseString.substring(refIdx + 1, end);
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int fileEnd = (refIdx == -1 ? end : refIdx);
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int queryIdx = parseString.lastIndexOf('?', fileEnd);
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        boolean canonicalize = false;
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (queryIdx > -1) {
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            query = parseString.substring(queryIdx + 1, fileEnd);
185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (queryIdx == 0 && file != null) {
186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (file.equals("")) { //$NON-NLS-1$
187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    file = "/"; //$NON-NLS-1$
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                } else if (file.startsWith("/")) { //$NON-NLS-1$
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    canonicalize = true;
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                int last = file.lastIndexOf('/') + 1;
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                file = file.substring(0, last);
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            fileEnd = queryIdx;
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // Don't inherit query unless only the ref is changed
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (refIdx != 0) {
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            query = null;
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (fileIdx > -1) {
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (fileIdx < end && parseString.charAt(fileIdx) == '/') {
203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                file = parseString.substring(fileIdx, fileEnd);
204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else if (fileEnd > fileIdx) {
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (file == null) {
206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    file = ""; //$NON-NLS-1$
207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                } else if (file.equals("")) { //$NON-NLS-1$
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    file = "/"; //$NON-NLS-1$
209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                } else if (file.startsWith("/")) { //$NON-NLS-1$
210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    canonicalize = true;
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                int last = file.lastIndexOf('/') + 1;
213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (last == 0) {
214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    file = parseString.substring(fileIdx, fileEnd);
215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                } else {
216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    file = file.substring(0, last)
217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            + parseString.substring(fileIdx, fileEnd);
218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (file == null) {
222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            file = ""; //$NON-NLS-1$
223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (host == null) {
226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            host = ""; //$NON-NLS-1$
227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (canonicalize) {
230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // modify file if there's any relative referencing
231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            file = URLUtil.canonicalizePath(file);
232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        setURL(u, u.getProtocol(), host, port, authority, userInfo, file,
235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                query, ref);
236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Sets the fields of the URL {@code u} to the values of the supplied
240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * arguments.
241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param u
243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the non-null URL object to be set.
244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param protocol
245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the protocol.
246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param host
247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the host name.
248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param port
249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the port number.
250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param file
251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the file component.
252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param ref
253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the reference.
254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @deprecated use setURL(URL, String String, int, String, String, String,
255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             String, String) instead.
256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Deprecated
258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected void setURL(URL u, String protocol, String host, int port,
259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            String file, String ref) {
260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (this != u.strmHandler) {
261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new SecurityException();
262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        u.set(protocol, host, port, file, ref);
264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Sets the fields of the URL {@code u} to the values of the supplied
268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * arguments.
269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param u
271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the non-null URL object to be set.
272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param protocol
273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the protocol.
274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param host
275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the host name.
276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param port
277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the port number.
278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param authority
279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the authority.
280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param userInfo
281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the user info.
282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param file
283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the file component.
284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param query
285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the query.
286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param ref
287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the reference.
288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected void setURL(URL u, String protocol, String host, int port,
290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            String authority, String userInfo, String file, String query,
291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            String ref) {
292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (this != u.strmHandler) {
293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new SecurityException();
294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        u.set(protocol, host, port, authority, userInfo, file, query, ref);
296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns the clear text representation of a given URL using HTTP format.
300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param url
302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the URL object to be converted.
303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return the clear text representation of the specified URL.
304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @see #parseURL
305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @see URL#toExternalForm()
306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected String toExternalForm(URL url) {
30801021fcb0c9026e81ac2c262caf5e2ec830a7025Jesse Wilson        StringBuilder answer = new StringBuilder();
309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        answer.append(url.getProtocol());
310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        answer.append(':');
311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        String authority = url.getAuthority();
312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (authority != null && authority.length() > 0) {
313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            answer.append("//"); //$NON-NLS-1$
314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            answer.append(url.getAuthority());
315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        String file = url.getFile();
318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        String ref = url.getRef();
31901021fcb0c9026e81ac2c262caf5e2ec830a7025Jesse Wilson        if (file != null) {
32001021fcb0c9026e81ac2c262caf5e2ec830a7025Jesse Wilson            answer.append(file);
32101021fcb0c9026e81ac2c262caf5e2ec830a7025Jesse Wilson        }
322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (ref != null) {
323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            answer.append('#');
324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            answer.append(ref);
325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return answer.toString();
327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Compares two URL objects whether they represent the same URL. Two URLs
331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * are equal if they have the same file, host, port, protocol, query, and
332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * reference components.
333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param url1
335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the first URL to compare.
336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param url2
337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the second URL to compare.
338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return {@code true} if the URLs are the same, {@code false} otherwise.
339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @see #hashCode
340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected boolean equals(URL url1, URL url2) {
342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!sameFile(url1, url2)) {
343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return false;
344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        String s1 = url1.getRef(), s2 = url2.getRef();
346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (s1 != s2 && (s1 == null || !s1.equals(s2))) {
347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return false;
348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        s1 = url1.getQuery();
350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        s2 = url2.getQuery();
351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return s1 == s2 || (s1 != null && s1.equals(s2));
352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns the default port of the protocol used by the handled URL. The
356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * current implementation returns always {@code -1}.
3573819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *
358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return the appropriate default port number of the protocol.
359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected int getDefaultPort() {
361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns the host address of the given URL.
3663819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *
367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param url
368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the URL object where to read the host address from.
369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return the host address of the specified URL.
370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected InetAddress getHostAddress(URL url) {
372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        try {
373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            String host = url.getHost();
374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (host == null || host.length() == 0) {
375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return null;
376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return InetAddress.getByName(host);
378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } catch (UnknownHostException e) {
379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return null;
380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns the hashcode value for the given URL object.
385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param url
387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the URL to determine the hashcode.
388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return the hashcode of the given URL.
389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected int hashCode(URL url) {
391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return toExternalForm(url).hashCode();
392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Compares two URL objects whether they refer to the same host.
3963819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *
397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param url1
398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the first URL to be compared.
399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param url2
400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the second URL to be compared.
401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return {@code true} if both URLs refer to the same host, {@code false}
402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *         otherwise.
403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected boolean hostsEqual(URL url1, URL url2) {
405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        String host1 = getHost(url1), host2 = getHost(url2);
40672e7c5a8d32494c81206971d4c1077e3f2b88f00Jesse Wilson        if (host1 != null && host1.equalsIgnoreCase(host2)) {
407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return true;
408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // Compare host address if the host name is not equal.
410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        InetAddress address1 = getHostAddress(url1);
411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        InetAddress address2 = getHostAddress(url2);
412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (address1 != null && address1.equals(address2)) {
413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return true;
414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Compares two URL objects whether they refer to the same file. In the
420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * comparison included are the URL components protocol, host, port and file.
421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param url1
423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the first URL to be compared.
424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param url2
425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the second URL to be compared.
426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return {@code true} if both URLs refer to the same file, {@code false}
427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *         otherwise.
428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected boolean sameFile(URL url1, URL url2) {
430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        String s1 = url1.getProtocol();
431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        String s2 = url2.getProtocol();
432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (s1 != s2 && (s1 == null || !s1.equals(s2))) {
433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return false;
434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        s1 = url1.getFile();
437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        s2 = url2.getFile();
438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (s1 != s2 && (s1 == null || !s1.equals(s2))) {
439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return false;
440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!hostsEqual(url1, url2)) {
442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return false;
443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int p1 = url1.getPort();
445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (p1 == -1) {
446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            p1 = getDefaultPort();
447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int p2 = url2.getPort();
449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (p2 == -1) {
450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            p2 = getDefaultPort();
451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return p1 == p2;
453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * If the URL host is empty while protocal is file, the host is regarded as
457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * localhost.
458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static String getHost(URL url) {
460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        String host = url.getHost();
461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if ("file".equals(url.getProtocol()) //$NON-NLS-1$
462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                && "".equals(host)) { //$NON-NLS-1$
463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            host = "localhost"; //$NON-NLS-1$
464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return host;
466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
468