URLStreamHandler.java revision 7e00db4156e50ce5f20fefb820dca339299134d3
1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/* 2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Licensed to the Apache Software Foundation (ASF) under one or more 3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * contributor license agreements. See the NOTICE file distributed with 4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * this work for additional information regarding copyright ownership. 5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The ASF licenses this file to You under the Apache License, Version 2.0 6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * (the "License"); you may not use this file except in compliance with 7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the License. You may obtain a copy of the License at 8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software 12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * See the License for the specific language governing permissions and 15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * limitations under the License. 16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage java.net; 19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 20adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.IOException; 21d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilsonimport java.nio.charset.Charsets; 22e32b21f14d52bac429a9c54fe031f9e92c911d64Jesse Wilsonimport libcore.base.Objects; 23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.apache.harmony.luni.util.URLUtil; 24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** 26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The abstract class {@code URLStreamHandler} is the base for all classes which 27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * can handle the communication with a URL object over a particular protocol 28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * type. 29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpublic abstract class URLStreamHandler { 31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Establishes a new connection to the resource specified by the URL {@code 33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * u}. Since different protocols also have unique ways of connecting, it 34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * must be overwritten by the subclass. 35f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param u 37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the URL to the resource where a connection has to be opened. 38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return the opened URLConnection to the specified resource. 39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException 40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if an I/O error occurs during opening the connection. 41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected abstract URLConnection openConnection(URL u) throws IOException; 43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Establishes a new connection to the resource specified by the URL {@code 46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * u} using the given {@code proxy}. Since different protocols also have 47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * unique ways of connecting, it must be overwritten by the subclass. 48f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param u 50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the URL to the resource where a connection has to be opened. 51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param proxy 52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the proxy that is used to make the connection. 53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return the opened URLConnection to the specified resource. 54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException 55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if an I/O error occurs during opening the connection. 56adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IllegalArgumentException 57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if any argument is {@code null} or the type of proxy is 58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * wrong. 59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws UnsupportedOperationException 60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if the protocol handler doesn't support this method. 61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 62b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes protected URLConnection openConnection(URL u, Proxy proxy) throws IOException { 63b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new UnsupportedOperationException(); 64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Parses the clear text URL in {@code str} into a URL object. URL strings 68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * generally have the following format: 69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p> 70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * http://www.company.com/java/file1.java#reference 71f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * <p> 72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The string is parsed in HTTP format. If the protocol has a different URL 73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * format this method must be overridden. 74f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 75adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param u 76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the URL to fill in the parsed clear text URL parts. 77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param str 78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the URL string that is to be parsed. 79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param start 80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the string position from where to begin parsing. 81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param end 82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the string position to stop parsing. 83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see #toExternalForm 84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see URL 85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void parseURL(URL u, String str, int start, int end) { 87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // For compatibility, refer to Harmony-2941 88f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes if (str.startsWith("//", start) 89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project && str.indexOf('/', start + 2) == -1 90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project && end <= Integer.MIN_VALUE + 1) { 91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new StringIndexOutOfBoundsException(end - 2 - start); 92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (end < start) { 94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (this != u.strmHandler) { 95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new SecurityException(); 96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 99f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes String parseString = ""; 100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (start < end) { 101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project parseString = str.substring(start, end); 102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project end -= start; 104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int fileIdx = 0; 105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Default is to use info from context 107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String host = u.getHost(); 108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int port = u.getPort(); 109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String ref = u.getRef(); 110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String file = u.getPath(); 111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String query = u.getQuery(); 112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String authority = u.getAuthority(); 113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String userInfo = u.getUserInfo(); 114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int refIdx = parseString.indexOf('#', 0); 116f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes if (parseString.startsWith("//")) { 1178fd0225a5c3918fe0cd4680258388985c25533e5Jesse Wilson int hostIdx = 2; 118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project port = -1; 119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project fileIdx = parseString.indexOf('/', hostIdx); 120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int questionMarkIndex = parseString.indexOf('?', hostIdx); 1218fd0225a5c3918fe0cd4680258388985c25533e5Jesse Wilson if (questionMarkIndex != -1 && (fileIdx == -1 || fileIdx > questionMarkIndex)) { 122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project fileIdx = questionMarkIndex; 123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (fileIdx == -1) { 125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project fileIdx = end; 126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Use default 127f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes file = ""; 128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int hostEnd = fileIdx; 130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (refIdx != -1 && refIdx < fileIdx) { 131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project hostEnd = refIdx; 1328fd0225a5c3918fe0cd4680258388985c25533e5Jesse Wilson fileIdx = refIdx; 1338fd0225a5c3918fe0cd4680258388985c25533e5Jesse Wilson file = ""; 134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int userIdx = parseString.lastIndexOf('@', hostEnd); 136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project authority = parseString.substring(hostIdx, hostEnd); 1378fd0225a5c3918fe0cd4680258388985c25533e5Jesse Wilson if (userIdx != -1) { 138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project userInfo = parseString.substring(hostIdx, userIdx); 139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project hostIdx = userIdx + 1; 140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1428fd0225a5c3918fe0cd4680258388985c25533e5Jesse Wilson int endOfIPv6Addr = parseString.indexOf(']', hostIdx); 1438fd0225a5c3918fe0cd4680258388985c25533e5Jesse Wilson if (endOfIPv6Addr >= hostEnd) { 1448fd0225a5c3918fe0cd4680258388985c25533e5Jesse Wilson endOfIPv6Addr = -1; 1458fd0225a5c3918fe0cd4680258388985c25533e5Jesse Wilson } 1468fd0225a5c3918fe0cd4680258388985c25533e5Jesse Wilson 1478fd0225a5c3918fe0cd4680258388985c25533e5Jesse Wilson // the port separator must be immediately after an IPv6 address "http://[::1]:80/" 1488fd0225a5c3918fe0cd4680258388985c25533e5Jesse Wilson int portIdx = -1; 149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (endOfIPv6Addr != -1) { 1508fd0225a5c3918fe0cd4680258388985c25533e5Jesse Wilson int maybeColon = endOfIPv6Addr + 1; 1518fd0225a5c3918fe0cd4680258388985c25533e5Jesse Wilson if (maybeColon < hostEnd && parseString.charAt(maybeColon) == ':') { 1528fd0225a5c3918fe0cd4680258388985c25533e5Jesse Wilson portIdx = maybeColon; 153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1548fd0225a5c3918fe0cd4680258388985c25533e5Jesse Wilson } else { 1558fd0225a5c3918fe0cd4680258388985c25533e5Jesse Wilson portIdx = parseString.indexOf(':', hostIdx); 156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1588fd0225a5c3918fe0cd4680258388985c25533e5Jesse Wilson if (portIdx == -1 || portIdx > hostEnd) { 159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project host = parseString.substring(hostIdx, hostEnd); 160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project host = parseString.substring(hostIdx, portIdx); 162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String portString = parseString.substring(portIdx + 1, hostEnd); 163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (portString.length() == 0) { 164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project port = -1; 165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project port = Integer.parseInt(portString); 167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (refIdx > -1) { 172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ref = parseString.substring(refIdx + 1, end); 173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int fileEnd = (refIdx == -1 ? end : refIdx); 175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int queryIdx = parseString.lastIndexOf('?', fileEnd); 177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project boolean canonicalize = false; 178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (queryIdx > -1) { 179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project query = parseString.substring(queryIdx + 1, fileEnd); 180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (queryIdx == 0 && file != null) { 18180a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes if (file.isEmpty()) { 182f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes file = "/"; 183f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes } else if (file.startsWith("/")) { 184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project canonicalize = true; 185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int last = file.lastIndexOf('/') + 1; 187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project file = file.substring(0, last); 188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project fileEnd = queryIdx; 190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else 191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Don't inherit query unless only the ref is changed 192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (refIdx != 0) { 193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project query = null; 194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (fileIdx > -1) { 197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (fileIdx < end && parseString.charAt(fileIdx) == '/') { 198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project file = parseString.substring(fileIdx, fileEnd); 199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if (fileEnd > fileIdx) { 200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (file == null) { 201f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes file = ""; 20280a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes } else if (file.isEmpty()) { 203f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes file = "/"; 204f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes } else if (file.startsWith("/")) { 205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project canonicalize = true; 206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 207adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int last = file.lastIndexOf('/') + 1; 208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (last == 0) { 209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project file = parseString.substring(fileIdx, fileEnd); 210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project file = file.substring(0, last) 212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project + parseString.substring(fileIdx, fileEnd); 213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (file == null) { 217f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes file = ""; 218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (host == null) { 221f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes host = ""; 222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (canonicalize) { 225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // modify file if there's any relative referencing 226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project file = URLUtil.canonicalizePath(file); 227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project setURL(u, u.getProtocol(), host, port, authority, userInfo, file, 230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project query, ref); 231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Sets the fields of the URL {@code u} to the values of the supplied 235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * arguments. 236f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param u 238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the non-null URL object to be set. 239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param protocol 240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the protocol. 241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param host 242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the host name. 243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param port 244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the port number. 245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param file 246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the file component. 247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param ref 248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the reference. 249adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @deprecated use setURL(URL, String String, int, String, String, String, 250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * String, String) instead. 251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Deprecated 253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void setURL(URL u, String protocol, String host, int port, 254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String file, String ref) { 255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (this != u.strmHandler) { 256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new SecurityException(); 257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project u.set(protocol, host, port, file, ref); 259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Sets the fields of the URL {@code u} to the values of the supplied 263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * arguments. 264f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param u 266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the non-null URL object to be set. 267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param protocol 268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the protocol. 269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param host 270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the host name. 271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param port 272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the port number. 273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param authority 274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the authority. 275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param userInfo 276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the user info. 277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param file 278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the file component. 279adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param query 280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the query. 281adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param ref 282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the reference. 283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void setURL(URL u, String protocol, String host, int port, 285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String authority, String userInfo, String file, String query, 286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String ref) { 287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (this != u.strmHandler) { 288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new SecurityException(); 289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project u.set(protocol, host, port, authority, userInfo, file, query, ref); 291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 294adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns the clear text representation of a given URL using HTTP format. 295f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param url 297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the URL object to be converted. 298adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return the clear text representation of the specified URL. 299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see #parseURL 300adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see URL#toExternalForm() 301adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 302adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected String toExternalForm(URL url) { 303d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson return toExternalForm(url, false); 304d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson } 305d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson 306d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson String toExternalForm(URL url, boolean escapeIllegalCharacters) { 307d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson StringBuilder result = new StringBuilder(); 308d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson result.append(url.getProtocol()); 309d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson result.append(':'); 310d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson 311adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String authority = url.getAuthority(); 312d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson if (authority != null && !authority.isEmpty()) { 313d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson result.append("//"); 314d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson if (escapeIllegalCharacters) { 315d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson authority = fixEncoding(authority, "$,;@&=+:[]"); 316d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson } 317d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson result.append(authority); 318adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 319adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 320d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson String fileAndQuery = url.getFile(); 321d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson if (fileAndQuery != null) { 322d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson if (escapeIllegalCharacters) { 323d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson fileAndQuery = fixEncoding(fileAndQuery, "$,;@&=+:/?"); 324d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson } 325d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson result.append(fileAndQuery); 326a389b4a499f40379b0b204d7ba1c2057663d95c0Jesse Wilson } 327d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson 328d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson String ref = url.getRef(); 329adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (ref != null) { 330d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson result.append('#'); 331d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson if (escapeIllegalCharacters) { 332d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson ref = fixEncoding(ref, "$,;@&=+:/?[]"); 333d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson } 334d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson result.append(ref); 335adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 336d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson 337d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson return result.toString(); 338d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson } 339d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson 340d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson /** 341d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson * Escapes the unescaped characters of {@code s} that are not permitted. 342d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson * Permitted characters are: 343d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson * <ul> 344d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson * <li>Unreserved characters in RFC 2396. 345d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson * <li>{@code extraOkayChars}, 346d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson * <li>non-ASCII, non-control, non-whitespace characters 347d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson * </ul> 348d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson * 349d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson * <p>Unlike the methods in {@code URI}, this method ignores input that has 350d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson * already been escaped. For example, input of "hello%20world" is unchanged 351d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson * by this method but would be double-escaped to "hello%2520world" by URI. 352d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson * 353d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson * <p>UTF-8 is used to encode escaped characters. A single input character 354d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson * like "\u0080" may be encoded to multiple octets like %C2%80. 355d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson */ 356d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson private String fixEncoding(String s, String extraPermittedChars) { 357d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson StringBuilder result = null; 358d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson int copiedCount = 0; 359d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson 360d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson for (int i = 0; i < s.length(); i++) { 361d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson char c = s.charAt(i); 362d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson 363d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson if (c == '%') { 364d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson i += 2; // this is a 3-character sequence like "%20" 365d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson continue; 366d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson } 367d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson 368d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson // unreserved characters: alphanum | mark 369d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson if (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9' 370d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson || c == '-' || c == '_' || c == '.' || c == '!' || c == '~' 371d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson || c == '*' || c == '\'' || c == '(' || c == ')') { 372d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson continue; 373d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson } 374d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson 375d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson // characters permitted in this context 376d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson if (extraPermittedChars.indexOf(c) != -1) { 377d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson continue; 378d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson } 379d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson 380d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson // other characters 381d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson if (c > 0x7f && !Character.isISOControl(c) && !Character.isSpaceChar(c)) { 382d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson continue; 383d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson } 384d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson 385d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson /* 386d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson * We've encountered a character that must be escaped. 387d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson */ 388d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson if (result == null) { 389d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson result = new StringBuilder(); 390d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson } 391d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson result.append(s, copiedCount, i); 392d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson 393d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson if (c < 0x7f) { 3944b25199bc0b7a64a6feaa60e7d5d6b0474341234Elliott Hughes URIEncoderDecoder.appendHex(result, (byte) c); 395d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson } else { 396d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson for (byte b : s.substring(i, i + 1).getBytes(Charsets.UTF_8)) { 3974b25199bc0b7a64a6feaa60e7d5d6b0474341234Elliott Hughes URIEncoderDecoder.appendHex(result, b); 398d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson } 399d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson } 400d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson 401d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson copiedCount = i + 1; 402d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson } 403d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson 404d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson if (result == null) { 405d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson return s; 406d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson } else { 407d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson result.append(s, copiedCount, s.length()); 408d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson return result.toString(); 409d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson } 410d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson } 411d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson 412adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 4137e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson * Returns true if {@code a} and {@code b} have the same protocol, host, 4147e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson * port, file, and reference. 415adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 4167e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson protected boolean equals(URL a, URL b) { 4177e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson return sameFile(a, b) 4187e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson && Objects.equal(a.getRef(), b.getRef()) 4197e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson && Objects.equal(a.getQuery(), b.getQuery()); 420adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 421adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 422adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 423adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns the default port of the protocol used by the handled URL. The 4247e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson * default implementation always returns {@code -1}. 425adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 426adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected int getDefaultPort() { 427adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return -1; 428adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 429adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 430adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 4317e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson * Returns the host address of {@code url}. 432adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 433adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected InetAddress getHostAddress(URL url) { 434adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 435adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String host = url.getHost(); 436adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (host == null || host.length() == 0) { 437adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return null; 438adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 439adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return InetAddress.getByName(host); 440adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (UnknownHostException e) { 441adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return null; 442adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 443adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 444adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 445adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 4467e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson * Returns the hash code of {@code url}. 447adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 448adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected int hashCode(URL url) { 449adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return toExternalForm(url).hashCode(); 450adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 451adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 452adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 4537e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson * Returns true if the hosts of {@code a} and {@code b} are equal. 454adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 45567db542e53c47a28e3f96beb7c9e46330483dc40Jesse Wilson protected boolean hostsEqual(URL a, URL b) { 4567e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson // URLs with the same case-insensitive host name have equal hosts 45767db542e53c47a28e3f96beb7c9e46330483dc40Jesse Wilson String aHost = getHost(a); 45867db542e53c47a28e3f96beb7c9e46330483dc40Jesse Wilson String bHost = getHost(b); 4597e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson return aHost != null && aHost.equalsIgnoreCase(bHost); 460adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 461adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 462adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 4637e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson * Returns true if {@code a} and {@code b} have the same protocol, host, 4647e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson * port and file. 465adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 4667e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson protected boolean sameFile(URL a, URL b) { 4677e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson return Objects.equal(a.getProtocol(), b.getProtocol()) 4687e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson && hostsEqual(a, b) 4697e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson && a.getEffectivePort() == b.getEffectivePort() 4707e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson && Objects.equal(a.getFile(), b.getFile()); 471adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 472adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 473adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static String getHost(URL url) { 474adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String host = url.getHost(); 47580a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes if ("file".equals(url.getProtocol()) && host.isEmpty()) { 476f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes host = "localhost"; 477adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 478adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return host; 479adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 480adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 481