URLStreamHandler.java revision 32559028b14b9b321b10eede050afd554a376569
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; 216186821cb13f4ac7ff50950c813394367e021eaeJesse Wilsonimport libcore.util.Objects; 22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.apache.harmony.luni.util.URLUtil; 23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** 25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The abstract class {@code URLStreamHandler} is the base for all classes which 26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * can handle the communication with a URL object over a particular protocol 27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * type. 28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpublic abstract class URLStreamHandler { 30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Establishes a new connection to the resource specified by the URL {@code 32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * u}. Since different protocols also have unique ways of connecting, it 33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * must be overwritten by the subclass. 34f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param u 36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the URL to the resource where a connection has to be opened. 37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return the opened URLConnection to the specified resource. 38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException 39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if an I/O error occurs during opening the connection. 40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected abstract URLConnection openConnection(URL u) throws IOException; 42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Establishes a new connection to the resource specified by the URL {@code 45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * u} using the given {@code proxy}. Since different protocols also have 46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * unique ways of connecting, it must be overwritten by the subclass. 47f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param u 49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the URL to the resource where a connection has to be opened. 50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param proxy 51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the proxy that is used to make the connection. 52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return the opened URLConnection to the specified resource. 53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException 54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if an I/O error occurs during opening the connection. 55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IllegalArgumentException 56adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if any argument is {@code null} or the type of proxy is 57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * wrong. 58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws UnsupportedOperationException 59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if the protocol handler doesn't support this method. 60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 61b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes protected URLConnection openConnection(URL u, Proxy proxy) throws IOException { 62b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new UnsupportedOperationException(); 63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Parses the clear text URL in {@code str} into a URL object. URL strings 67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * generally have the following format: 68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p> 69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * http://www.company.com/java/file1.java#reference 70f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * <p> 71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The string is parsed in HTTP format. If the protocol has a different URL 72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * format this method must be overridden. 73f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param u 75adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the URL to fill in the parsed clear text URL parts. 76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param str 77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the URL string that is to be parsed. 78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param start 79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the string position from where to begin parsing. 80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param end 81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the string position to stop parsing. 82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see #toExternalForm 83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see URL 84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void parseURL(URL u, String str, int start, int end) { 86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // For compatibility, refer to Harmony-2941 87f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes if (str.startsWith("//", start) 88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project && str.indexOf('/', start + 2) == -1 89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project && end <= Integer.MIN_VALUE + 1) { 90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new StringIndexOutOfBoundsException(end - 2 - start); 91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (end < start) { 93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (this != u.strmHandler) { 94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new SecurityException(); 95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 98f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes String parseString = ""; 99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (start < end) { 100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project parseString = str.substring(start, end); 101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project end -= start; 103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int fileIdx = 0; 104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Default is to use info from context 106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String host = u.getHost(); 107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int port = u.getPort(); 108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String ref = u.getRef(); 109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String file = u.getPath(); 110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String query = u.getQuery(); 111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String authority = u.getAuthority(); 112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String userInfo = u.getUserInfo(); 113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int refIdx = parseString.indexOf('#', 0); 115f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes if (parseString.startsWith("//")) { 1168fd0225a5c3918fe0cd4680258388985c25533e5Jesse Wilson int hostIdx = 2; 117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project port = -1; 118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project fileIdx = parseString.indexOf('/', hostIdx); 119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int questionMarkIndex = parseString.indexOf('?', hostIdx); 1208fd0225a5c3918fe0cd4680258388985c25533e5Jesse Wilson if (questionMarkIndex != -1 && (fileIdx == -1 || fileIdx > questionMarkIndex)) { 121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project fileIdx = questionMarkIndex; 122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (fileIdx == -1) { 124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project fileIdx = end; 125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Use default 126f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes file = ""; 127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int hostEnd = fileIdx; 129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (refIdx != -1 && refIdx < fileIdx) { 130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project hostEnd = refIdx; 1318fd0225a5c3918fe0cd4680258388985c25533e5Jesse Wilson fileIdx = refIdx; 1328fd0225a5c3918fe0cd4680258388985c25533e5Jesse Wilson file = ""; 133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int userIdx = parseString.lastIndexOf('@', hostEnd); 135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project authority = parseString.substring(hostIdx, hostEnd); 1368fd0225a5c3918fe0cd4680258388985c25533e5Jesse Wilson if (userIdx != -1) { 137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project userInfo = parseString.substring(hostIdx, userIdx); 138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project hostIdx = userIdx + 1; 139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1418fd0225a5c3918fe0cd4680258388985c25533e5Jesse Wilson int endOfIPv6Addr = parseString.indexOf(']', hostIdx); 1428fd0225a5c3918fe0cd4680258388985c25533e5Jesse Wilson if (endOfIPv6Addr >= hostEnd) { 1438fd0225a5c3918fe0cd4680258388985c25533e5Jesse Wilson endOfIPv6Addr = -1; 1448fd0225a5c3918fe0cd4680258388985c25533e5Jesse Wilson } 1458fd0225a5c3918fe0cd4680258388985c25533e5Jesse Wilson 1468fd0225a5c3918fe0cd4680258388985c25533e5Jesse Wilson // the port separator must be immediately after an IPv6 address "http://[::1]:80/" 1478fd0225a5c3918fe0cd4680258388985c25533e5Jesse Wilson int portIdx = -1; 148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (endOfIPv6Addr != -1) { 1498fd0225a5c3918fe0cd4680258388985c25533e5Jesse Wilson int maybeColon = endOfIPv6Addr + 1; 1508fd0225a5c3918fe0cd4680258388985c25533e5Jesse Wilson if (maybeColon < hostEnd && parseString.charAt(maybeColon) == ':') { 1518fd0225a5c3918fe0cd4680258388985c25533e5Jesse Wilson portIdx = maybeColon; 152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1538fd0225a5c3918fe0cd4680258388985c25533e5Jesse Wilson } else { 1548fd0225a5c3918fe0cd4680258388985c25533e5Jesse Wilson portIdx = parseString.indexOf(':', hostIdx); 155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1578fd0225a5c3918fe0cd4680258388985c25533e5Jesse Wilson if (portIdx == -1 || portIdx > hostEnd) { 158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project host = parseString.substring(hostIdx, hostEnd); 159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project host = parseString.substring(hostIdx, portIdx); 161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String portString = parseString.substring(portIdx + 1, hostEnd); 162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (portString.length() == 0) { 163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project port = -1; 164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project port = Integer.parseInt(portString); 166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (refIdx > -1) { 171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ref = parseString.substring(refIdx + 1, end); 172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int fileEnd = (refIdx == -1 ? end : refIdx); 174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int queryIdx = parseString.lastIndexOf('?', fileEnd); 176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project boolean canonicalize = false; 177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (queryIdx > -1) { 178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project query = parseString.substring(queryIdx + 1, fileEnd); 179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (queryIdx == 0 && file != null) { 18080a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes if (file.isEmpty()) { 181f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes file = "/"; 182f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes } else if (file.startsWith("/")) { 183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project canonicalize = true; 184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int last = file.lastIndexOf('/') + 1; 186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project file = file.substring(0, last); 187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project fileEnd = queryIdx; 189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else 190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Don't inherit query unless only the ref is changed 191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (refIdx != 0) { 192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project query = null; 193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (fileIdx > -1) { 196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (fileIdx < end && parseString.charAt(fileIdx) == '/') { 197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project file = parseString.substring(fileIdx, fileEnd); 198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if (fileEnd > fileIdx) { 199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (file == null) { 200f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes file = ""; 20180a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes } else if (file.isEmpty()) { 202f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes file = "/"; 203f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes } else if (file.startsWith("/")) { 204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project canonicalize = true; 205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int last = file.lastIndexOf('/') + 1; 207adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (last == 0) { 208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project file = parseString.substring(fileIdx, fileEnd); 209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project file = file.substring(0, last) 211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project + parseString.substring(fileIdx, fileEnd); 212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (file == null) { 216f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes file = ""; 217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (host == null) { 220f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes host = ""; 221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (canonicalize) { 224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // modify file if there's any relative referencing 225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project file = URLUtil.canonicalizePath(file); 226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project setURL(u, u.getProtocol(), host, port, authority, userInfo, file, 229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project query, ref); 230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Sets the fields of the URL {@code u} to the values of the supplied 234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * arguments. 235f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param u 237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the non-null URL object to be set. 238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param protocol 239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the protocol. 240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param host 241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the host name. 242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param port 243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the port number. 244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param file 245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the file component. 246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param ref 247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the reference. 248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @deprecated use setURL(URL, String String, int, String, String, String, 249adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * String, String) instead. 250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Deprecated 252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void setURL(URL u, String protocol, String host, int port, 253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String file, String ref) { 254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (this != u.strmHandler) { 255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new SecurityException(); 256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project u.set(protocol, host, port, file, ref); 258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Sets the fields of the URL {@code u} to the values of the supplied 262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * arguments. 263f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param u 265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the non-null URL object to be set. 266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param protocol 267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the protocol. 268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param host 269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the host name. 270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param port 271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the port number. 272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param authority 273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the authority. 274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param userInfo 275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the user info. 276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param file 277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the file component. 278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param query 279adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the query. 280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param ref 281adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the reference. 282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void setURL(URL u, String protocol, String host, int port, 284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String authority, String userInfo, String file, String query, 285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String ref) { 286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (this != u.strmHandler) { 287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new SecurityException(); 288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project u.set(protocol, host, port, authority, userInfo, file, query, ref); 290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns the clear text representation of a given URL using HTTP format. 294f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 295adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param url 296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the URL object to be converted. 297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return the clear text representation of the specified URL. 298adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see #parseURL 299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see URL#toExternalForm() 300adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 301adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected String toExternalForm(URL url) { 302d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson return toExternalForm(url, false); 303d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson } 304d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson 305d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson String toExternalForm(URL url, boolean escapeIllegalCharacters) { 306d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson StringBuilder result = new StringBuilder(); 307d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson result.append(url.getProtocol()); 308d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson result.append(':'); 309d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson 310adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String authority = url.getAuthority(); 311d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson if (authority != null && !authority.isEmpty()) { 312d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson result.append("//"); 313d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson if (escapeIllegalCharacters) { 31432559028b14b9b321b10eede050afd554a376569Jesse Wilson URI.AUTHORITY_ENCODER.appendPartiallyEncoded(result, authority); 31532559028b14b9b321b10eede050afd554a376569Jesse Wilson } else { 31632559028b14b9b321b10eede050afd554a376569Jesse Wilson result.append(authority); 317d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson } 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) { 32332559028b14b9b321b10eede050afd554a376569Jesse Wilson URI.FILE_AND_QUERY_ENCODER.appendPartiallyEncoded(result, fileAndQuery); 32432559028b14b9b321b10eede050afd554a376569Jesse Wilson } else { 32532559028b14b9b321b10eede050afd554a376569Jesse Wilson result.append(fileAndQuery); 326d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson } 327a389b4a499f40379b0b204d7ba1c2057663d95c0Jesse Wilson } 328d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson 329d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson String ref = url.getRef(); 330adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (ref != null) { 331d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson result.append('#'); 332d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson if (escapeIllegalCharacters) { 33332559028b14b9b321b10eede050afd554a376569Jesse Wilson URI.ALL_LEGAL_ENCODER.appendPartiallyEncoded(result, ref); 33432559028b14b9b321b10eede050afd554a376569Jesse Wilson } else { 33532559028b14b9b321b10eede050afd554a376569Jesse Wilson result.append(ref); 336d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson } 337adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 338d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson 339d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson return result.toString(); 340d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson } 341d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson 342d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson /** 3437e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson * Returns true if {@code a} and {@code b} have the same protocol, host, 3447e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson * port, file, and reference. 345adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 3467e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson protected boolean equals(URL a, URL b) { 3477e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson return sameFile(a, b) 3487e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson && Objects.equal(a.getRef(), b.getRef()) 3497e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson && Objects.equal(a.getQuery(), b.getQuery()); 350adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 351adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 352adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 353adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns the default port of the protocol used by the handled URL. The 3547e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson * default implementation always returns {@code -1}. 355adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 356adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected int getDefaultPort() { 357adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return -1; 358adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 359adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 360adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 3617e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson * Returns the host address of {@code url}. 362adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 363adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected InetAddress getHostAddress(URL url) { 364adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 365adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String host = url.getHost(); 366adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (host == null || host.length() == 0) { 367adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return null; 368adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 369adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return InetAddress.getByName(host); 370adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (UnknownHostException e) { 371adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return null; 372adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 373adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 374adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 375adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 3767e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson * Returns the hash code of {@code url}. 377adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 378adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected int hashCode(URL url) { 379adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return toExternalForm(url).hashCode(); 380adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 381adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 382adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 3837e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson * Returns true if the hosts of {@code a} and {@code b} are equal. 384adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 38567db542e53c47a28e3f96beb7c9e46330483dc40Jesse Wilson protected boolean hostsEqual(URL a, URL b) { 3867e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson // URLs with the same case-insensitive host name have equal hosts 38767db542e53c47a28e3f96beb7c9e46330483dc40Jesse Wilson String aHost = getHost(a); 38867db542e53c47a28e3f96beb7c9e46330483dc40Jesse Wilson String bHost = getHost(b); 3897e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson return aHost != null && aHost.equalsIgnoreCase(bHost); 390adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 391adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 392adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 3937e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson * Returns true if {@code a} and {@code b} have the same protocol, host, 3947e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson * port and file. 395adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 3967e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson protected boolean sameFile(URL a, URL b) { 3977e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson return Objects.equal(a.getProtocol(), b.getProtocol()) 3987e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson && hostsEqual(a, b) 3997e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson && a.getEffectivePort() == b.getEffectivePort() 4007e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson && Objects.equal(a.getFile(), b.getFile()); 401adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 402adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 403adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static String getHost(URL url) { 404adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String host = url.getHost(); 40580a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes if ("file".equals(url.getProtocol()) && host.isEmpty()) { 406f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes host = "localhost"; 407adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 408adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return host; 409adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 410adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 411