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; 21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.InputStream; 228f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilsonimport java.io.ObjectInputStream; 23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.ObjectOutputStream; 248f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilsonimport java.io.Serializable; 25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.Hashtable; 268f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilsonimport java.util.jar.JarFile; 275aafac4db69e6d087c512cdfa5c7c0e2f1611681Jesse Wilsonimport libcore.net.url.FileHandler; 285aafac4db69e6d087c512cdfa5c7c0e2f1611681Jesse Wilsonimport libcore.net.url.FtpHandler; 295aafac4db69e6d087c512cdfa5c7c0e2f1611681Jesse Wilsonimport libcore.net.url.JarHandler; 305292410e4ebf7fb5149eefd2f52fcb94c46690a6Jesse Wilsonimport libcore.net.url.UrlUtils; 31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** 338f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * A Uniform Resource Locator that identifies the location of an Internet 348f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * resource as specified by <a href="http://www.ietf.org/rfc/rfc1738.txt">RFC 358f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * 1738</a>. 368f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * 378f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * <h3>Parts of a URL</h3> 388f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * A URL is composed of many parts. This class can both parse URL strings into 398f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * parts and compose URL strings from parts. For example, consider the parts of 408f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * this URL: 418f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * {@code http://username:password@host:8080/directory/file?query#ref}: 428f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * <table> 438f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * <tr><th>Component</th><th>Example value</th><th>Also known as</th></tr> 448f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * <tr><td>{@link #getProtocol() Protocol}</td><td>{@code http}</td><td>scheme</td></tr> 458f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * <tr><td>{@link #getAuthority() Authority}</td><td>{@code username:password@host:8080}</td><td></td></tr> 468f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * <tr><td>{@link #getUserInfo() User Info}</td><td>{@code username:password}</td><td></td></tr> 478f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * <tr><td>{@link #getHost() Host}</td><td>{@code host}</td><td></td></tr> 488f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * <tr><td>{@link #getPort() Port}</td><td>{@code 8080}</td><td></td></tr> 498f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * <tr><td>{@link #getFile() File}</td><td>{@code /directory/file?query}</td><td></td></tr> 508f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * <tr><td>{@link #getPath() Path}</td><td>{@code /directory/file}</td><td></td></tr> 518f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * <tr><td>{@link #getQuery() Query}</td><td>{@code query}</td><td></td></tr> 528f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * <tr><td>{@link #getRef() Ref}</td><td>{@code ref}</td><td>fragment</td></tr> 538f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * </table> 548f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * 558f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * <h3>Supported Protocols</h3> 568f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * This class may be used to construct URLs with the following protocols: 578f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * <ul> 588f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * <li><strong>file</strong>: read files from the local filesystem. 598f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * <li><strong>ftp</strong>: <a href="http://www.ietf.org/rfc/rfc959.txt">File 608f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * Transfer Protocol</a> 618f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * <li><strong>http</strong>: <a href="http://www.ietf.org/rfc/rfc2616.txt">Hypertext 628f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * Transfer Protocol</a> 638f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * <li><strong>https</strong>: <a href="http://www.ietf.org/rfc/rfc2818.txt">HTTP 648f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * over TLS</a> 658f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * <li><strong>jar</strong>: read {@link JarFile Jar files} from the 668f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * filesystem</li> 678f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * </ul> 688f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * In general, attempts to create URLs with any other protocol will fail with a 698f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * {@link MalformedURLException}. Applications may install handlers for other 708f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * schemes using {@link #setURLStreamHandlerFactory} or with the {@code 718f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * java.protocol.handler.pkgs} system property. 728f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * 738f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * <p>The {@link URI} class can be used to manipulate URLs of any protocol. 74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 758f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilsonpublic final class URL implements Serializable { 76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static final long serialVersionUID = -7627629688361524110L; 77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 788f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson private static URLStreamHandlerFactory streamHandlerFactory; 79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 808f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson /** Cache of protocols to their handlers */ 818f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson private static final Hashtable<String, URLStreamHandler> streamHandlers 828f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson = new Hashtable<String, URLStreamHandler>(); 83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 848f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson private String protocol; 858f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson private String authority; 86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private String host; 87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private int port = -1; 888f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson private String file; 898f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson private String ref; 90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 918f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson private transient String userInfo; 928f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson private transient String path; 938f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson private transient String query; 94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 958f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson transient URLStreamHandler streamHandler; 96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 988f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * The cached hash code, or 0 if it hasn't been computed yet. Unlike the RI, 998f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * this implementation's hashCode is transient because the hash code is 1008f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * unspecified and may vary between VMs or versions. 101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 1028f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson private transient int hashCode; 103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 1058f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * Sets the stream handler factory for this VM. 106f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 1078f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * @throws Error if a URLStreamHandlerFactory has already been installed 1088f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * for the current VM. 109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 1108f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson public static synchronized void setURLStreamHandlerFactory(URLStreamHandlerFactory factory) { 111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (streamHandlerFactory != null) { 112b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new Error("Factory already set"); 113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 114c2ebff3511f9df4d8cca2b82630c2d760af9d204Jesse Wilson streamHandlers.clear(); 1158f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson streamHandlerFactory = factory; 116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 1198f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * Creates a new URL instance by parsing {@code spec}. 120f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 1218f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * @throws MalformedURLException if {@code spec} could not be parsed as a 1228f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * URL. 123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public URL(String spec) throws MalformedURLException { 1258f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson this((URL) null, spec, null); 126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 1298f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * Creates a new URL by resolving {@code spec} relative to {@code context}. 130f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 1318f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * @param context the URL to which {@code spec} is relative, or null for 1328f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * no context in which case {@code spec} must be an absolute URL. 1338f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * @throws MalformedURLException if {@code spec} could not be parsed as a 1348f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * URL or has an unsupported protocol. 135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public URL(URL context, String spec) throws MalformedURLException { 1378f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson this(context, spec, null); 138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 1418f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * Creates a new URL by resolving {@code spec} relative to {@code context}. 142f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 1438f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * @param context the URL to which {@code spec} is relative, or null for 1448f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * no context in which case {@code spec} must be an absolute URL. 1458f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * @param handler the stream handler for this URL, or null for the 1468f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * protocol's default stream handler. 1478f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * @throws MalformedURLException if the given string {@code spec} could not 1488f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * be parsed as a URL or an invalid protocol has been found. 149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 150ad41624e761bcf1af9c8008eb45187fc13983717Elliott Hughes public URL(URL context, String spec, URLStreamHandler handler) throws MalformedURLException { 151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (spec == null) { 152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new MalformedURLException(); 153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1545292410e4ebf7fb5149eefd2f52fcb94c46690a6Jesse Wilson if (handler != null) { 1555292410e4ebf7fb5149eefd2f52fcb94c46690a6Jesse Wilson streamHandler = handler; 1565292410e4ebf7fb5149eefd2f52fcb94c46690a6Jesse Wilson } 157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project spec = spec.trim(); 158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1595292410e4ebf7fb5149eefd2f52fcb94c46690a6Jesse Wilson protocol = UrlUtils.getSchemePrefix(spec); 1605292410e4ebf7fb5149eefd2f52fcb94c46690a6Jesse Wilson int schemeSpecificPartStart = protocol != null ? (protocol.length() + 1) : 0; 1615292410e4ebf7fb5149eefd2f52fcb94c46690a6Jesse Wilson 1625292410e4ebf7fb5149eefd2f52fcb94c46690a6Jesse Wilson // If the context URL has a different protocol, discard it because we can't use it. 1635292410e4ebf7fb5149eefd2f52fcb94c46690a6Jesse Wilson if (protocol != null && context != null && !protocol.equals(context.protocol)) { 1645292410e4ebf7fb5149eefd2f52fcb94c46690a6Jesse Wilson context = null; 165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1675292410e4ebf7fb5149eefd2f52fcb94c46690a6Jesse Wilson // Inherit from the context URL if it exists. 1685292410e4ebf7fb5149eefd2f52fcb94c46690a6Jesse Wilson if (context != null) { 1695292410e4ebf7fb5149eefd2f52fcb94c46690a6Jesse Wilson set(context.protocol, context.getHost(), context.getPort(), context.getAuthority(), 1705292410e4ebf7fb5149eefd2f52fcb94c46690a6Jesse Wilson context.getUserInfo(), context.getPath(), context.getQuery(), 1715292410e4ebf7fb5149eefd2f52fcb94c46690a6Jesse Wilson context.getRef()); 1728f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson if (streamHandler == null) { 1738f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson streamHandler = context.streamHandler; 174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1755292410e4ebf7fb5149eefd2f52fcb94c46690a6Jesse Wilson } else if (protocol == null) { 1765292410e4ebf7fb5149eefd2f52fcb94c46690a6Jesse Wilson throw new MalformedURLException("Protocol not found: " + spec); 177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1798f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson if (streamHandler == null) { 180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project setupStreamHandler(); 1818f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson if (streamHandler == null) { 182b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new MalformedURLException("Unknown protocol: " + protocol); 183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1865292410e4ebf7fb5149eefd2f52fcb94c46690a6Jesse Wilson // Parse the URL. If the handler throws any exception, throw MalformedURLException instead. 187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 1885292410e4ebf7fb5149eefd2f52fcb94c46690a6Jesse Wilson streamHandler.parseURL(this, spec, schemeSpecificPartStart, spec.length()); 189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (Exception e) { 190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new MalformedURLException(e.toString()); 191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 1958f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * Creates a new URL of the given component parts. The URL uses the 1968f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * protocol's default port. 197f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 1988f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * @throws MalformedURLException if the combination of all arguments do not 1998f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * represent a valid URL or if the protocol is invalid. 200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 2018f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson public URL(String protocol, String host, String file) throws MalformedURLException { 2028f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson this(protocol, host, -1, file, null); 203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 2068f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * Creates a new URL of the given component parts. The URL uses the 2078f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * protocol's default port. 208f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 2098f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * @param host the host name or IP address of the new URL. 2108f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * @param port the port, or {@code -1} for the protocol's default port. 2118f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * @param file the name of the resource. 2128f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * @throws MalformedURLException if the combination of all arguments do not 2138f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * represent a valid URL or if the protocol is invalid. 2148f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson */ 2158f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson public URL(String protocol, String host, int port, String file) throws MalformedURLException { 2168f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson this(protocol, host, port, file, null); 2178f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson } 2188f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson 2198f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson /** 2208f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * Creates a new URL of the given component parts. The URL uses the 2218f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * protocol's default port. 222f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 2238f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * @param host the host name or IP address of the new URL. 2248f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * @param port the port, or {@code -1} for the protocol's default port. 2258f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * @param file the name of the resource. 2268f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * @param handler the stream handler for this URL, or null for the 2278f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * protocol's default stream handler. 2288f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * @throws MalformedURLException if the combination of all arguments do not 2298f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * represent a valid URL or if the protocol is invalid. 230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public URL(String protocol, String host, int port, String file, 232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project URLStreamHandler handler) throws MalformedURLException { 233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (port < -1) { 2345292410e4ebf7fb5149eefd2f52fcb94c46690a6Jesse Wilson throw new MalformedURLException("port < -1: " + port); 2355292410e4ebf7fb5149eefd2f52fcb94c46690a6Jesse Wilson } 2365292410e4ebf7fb5149eefd2f52fcb94c46690a6Jesse Wilson if (protocol == null) { 2375292410e4ebf7fb5149eefd2f52fcb94c46690a6Jesse Wilson throw new NullPointerException("protocol == null"); 238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 2405292410e4ebf7fb5149eefd2f52fcb94c46690a6Jesse Wilson // Wrap IPv6 addresses in square brackets if they aren't already. 2418f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson if (host != null && host.contains(":") && host.charAt(0) != '[') { 242f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes host = "[" + host + "]"; 243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 245f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson this.protocol = protocol; 246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.host = host; 247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.port = port; 248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 249c68609e723a5daa20888abdb640799d4353fd590Jesse Wilson file = UrlUtils.authoritySafePath(host, file); 2505292410e4ebf7fb5149eefd2f52fcb94c46690a6Jesse Wilson 251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Set the fields from the arguments. Handle the case where the 252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // passed in "file" includes both a file and a reference part. 253c68609e723a5daa20888abdb640799d4353fd590Jesse Wilson int hash = file.indexOf("#"); 254c68609e723a5daa20888abdb640799d4353fd590Jesse Wilson if (hash != -1) { 255c68609e723a5daa20888abdb640799d4353fd590Jesse Wilson this.file = file.substring(0, hash); 256c68609e723a5daa20888abdb640799d4353fd590Jesse Wilson this.ref = file.substring(hash + 1); 257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.file = file; 259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project fixURL(false); 261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Set the stream handler for the URL either to the handler 263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // argument if it was specified, or to the default for the 264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // receiver's protocol if the handler was null. 265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (handler == null) { 266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project setupStreamHandler(); 2678f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson if (streamHandler == null) { 268b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new MalformedURLException("Unknown protocol: " + protocol); 269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 2718f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson streamHandler = handler; 272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project void fixURL(boolean fixHost) { 276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int index; 277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (host != null && host.length() > 0) { 278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project authority = host; 279adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (port != -1) { 280f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes authority = authority + ":" + port; 281adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (fixHost) { 284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (host != null && (index = host.lastIndexOf('@')) > -1) { 285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project userInfo = host.substring(0, index); 286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project host = host.substring(index + 1); 287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project userInfo = null; 289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (file != null && (index = file.indexOf('?')) > -1) { 292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project query = file.substring(index + 1); 293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project path = file.substring(0, index); 294adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 295adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project query = null; 296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project path = file; 297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 298adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 300adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 301adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Sets the properties of this URL using the provided arguments. Only a 302adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@code URLStreamHandler} can use this method to set fields of the 303adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * existing URL instance. A URL is generally constant. 3048f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson */ 3058f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson protected void set(String protocol, String host, int port, String file, String ref) { 306adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (this.protocol == null) { 307adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.protocol = protocol; 308adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 309adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.host = host; 310adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.file = file; 311adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.port = port; 312adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.ref = ref; 313adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project hashCode = 0; 314adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project fixURL(true); 315adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 316adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 317adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 3187e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson * Returns true if this URL equals {@code o}. URLs are equal if they have 3197e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson * the same protocol, host, port, file, and reference. 320f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 3217e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson * <h3>Network I/O Warning</h3> 3227e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson * <p>Some implementations of URL.equals() resolve host names over the 3237e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson * network. This is problematic: 3247e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson * <ul> 3257e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson * <li><strong>The network may be slow.</strong> Many classes, including 3267e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson * core collections like {@link java.util.Map Map} and {@link java.util.Set 3277e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson * Set} expect that {@code equals} and {@code hashCode} will return quickly. 3287e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson * By violating this assumption, this method posed potential performance 3297e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson * problems. 3307e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson * <li><strong>Equal IP addresses do not imply equal content.</strong> 3317e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson * Virtual hosting permits unrelated sites to share an IP address. This 3327e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson * method could report two otherwise unrelated URLs to be equal because 3337e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson * they're hosted on the same server.</li> 3347e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson * <li><strong>The network many not be available.</strong> Two URLs could be 3357e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson * equal when a network is available and unequal otherwise.</li> 3367e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson * <li><strong>The network may change.</strong> The IP address for a given 3377e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson * host name varies by network and over time. This is problematic for mobile 3387e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson * devices. Two URLs could be equal on some networks and unequal on 3397e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson * others.</li> 3407e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson * </ul> 34164785533018893463bbab2e34959879bac446c8dJesse Wilson * <p>This problem is fixed in Android 4.0 (Ice Cream Sandwich). In that 34264785533018893463bbab2e34959879bac446c8dJesse Wilson * release, URLs are only equal if their host names are equal (ignoring 3437e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson * case). 344adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 3457e00db4156e50ce5f20fefb820dca339299134d3Jesse Wilson @Override public boolean equals(Object o) { 346adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (o == null) { 347adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return false; 348adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 349adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (this == o) { 350adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return true; 351adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 352adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (this.getClass() != o.getClass()) { 353adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return false; 354adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 3558f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson return streamHandler.equals(this, (URL) o); 356adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 357adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 358adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 3598f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * Returns true if this URL refers to the same resource as {@code otherURL}. 3608f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * All URL components except the reference field are compared. 361adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 362adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean sameFile(URL otherURL) { 3638f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson return streamHandler.sameFile(this, otherURL); 364adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 365adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 3668f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson @Override public int hashCode() { 367adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (hashCode == 0) { 3688f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson hashCode = streamHandler.hashCode(this); 369adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 370adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return hashCode; 371adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 372adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 373adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 374adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Sets the receiver's stream handler to one which is appropriate for its 3758f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * protocol. 3768f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * 3778f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * <p>Note that this will overwrite any existing stream handler with the new 3788f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * one. Senders must check if the streamHandler is null before calling the 379adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * method if they do not want this behavior (a speed optimization). 3808f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * 3818f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * @throws MalformedURLException if no reasonable handler is available. 382adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 383adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project void setupStreamHandler() { 384adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Check for a cached (previously looked up) handler for 385adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // the requested protocol. 3868f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson streamHandler = streamHandlers.get(protocol); 3878f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson if (streamHandler != null) { 388adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 389adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 390adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 391adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // If there is a stream handler factory, then attempt to 392adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // use it to create the handler. 393adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (streamHandlerFactory != null) { 3948f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson streamHandler = streamHandlerFactory.createURLStreamHandler(protocol); 3958f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson if (streamHandler != null) { 3968f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson streamHandlers.put(protocol, streamHandler); 397adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 398adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 399adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 400adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 401adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Check if there is a list of packages which can provide handlers. 402adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // If so, then walk this list looking for an applicable one. 403ad41624e761bcf1af9c8008eb45187fc13983717Elliott Hughes String packageList = System.getProperty("java.protocol.handler.pkgs"); 404cf216b0bb538b3e555af205f4fad8064331b9265Jesse Wilson ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); 405cf216b0bb538b3e555af205f4fad8064331b9265Jesse Wilson if (packageList != null && contextClassLoader != null) { 406118abc3050371812703e4fabf03f4399d01fb28cElliott Hughes for (String packageName : packageList.split("\\|")) { 407118abc3050371812703e4fabf03f4399d01fb28cElliott Hughes String className = packageName + "." + protocol + ".Handler"; 408adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 409cf216b0bb538b3e555af205f4fad8064331b9265Jesse Wilson Class<?> c = contextClassLoader.loadClass(className); 4108f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson streamHandler = (URLStreamHandler) c.newInstance(); 4118f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson if (streamHandler != null) { 4128f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson streamHandlers.put(protocol, streamHandler); 413adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 414adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 4155aafac4db69e6d087c512cdfa5c7c0e2f1611681Jesse Wilson } catch (IllegalAccessException ignored) { 4165aafac4db69e6d087c512cdfa5c7c0e2f1611681Jesse Wilson } catch (InstantiationException ignored) { 4175aafac4db69e6d087c512cdfa5c7c0e2f1611681Jesse Wilson } catch (ClassNotFoundException ignored) { 418adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 419adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 420adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 421c2ebff3511f9df4d8cca2b82630c2d760af9d204Jesse Wilson 422c2ebff3511f9df4d8cca2b82630c2d760af9d204Jesse Wilson // Fall back to a built-in stream handler if the user didn't supply one 423c2ebff3511f9df4d8cca2b82630c2d760af9d204Jesse Wilson if (protocol.equals("file")) { 4248f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson streamHandler = new FileHandler(); 425c2ebff3511f9df4d8cca2b82630c2d760af9d204Jesse Wilson } else if (protocol.equals("ftp")) { 4268f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson streamHandler = new FtpHandler(); 427c2ebff3511f9df4d8cca2b82630c2d760af9d204Jesse Wilson } else if (protocol.equals("http")) { 4282503556d17b28c7b4e6e514540a77df1627857d0jwilson try { 4292503556d17b28c7b4e6e514540a77df1627857d0jwilson String name = "com.android.okhttp.HttpHandler"; 4302503556d17b28c7b4e6e514540a77df1627857d0jwilson streamHandler = (URLStreamHandler) Class.forName(name).newInstance(); 4312503556d17b28c7b4e6e514540a77df1627857d0jwilson } catch (Exception e) { 4322503556d17b28c7b4e6e514540a77df1627857d0jwilson throw new AssertionError(e); 4332503556d17b28c7b4e6e514540a77df1627857d0jwilson } 434c2ebff3511f9df4d8cca2b82630c2d760af9d204Jesse Wilson } else if (protocol.equals("https")) { 4352503556d17b28c7b4e6e514540a77df1627857d0jwilson try { 4362503556d17b28c7b4e6e514540a77df1627857d0jwilson String name = "com.android.okhttp.HttpsHandler"; 4372503556d17b28c7b4e6e514540a77df1627857d0jwilson streamHandler = (URLStreamHandler) Class.forName(name).newInstance(); 4382503556d17b28c7b4e6e514540a77df1627857d0jwilson } catch (Exception e) { 4392503556d17b28c7b4e6e514540a77df1627857d0jwilson throw new AssertionError(e); 4402503556d17b28c7b4e6e514540a77df1627857d0jwilson } 441c2ebff3511f9df4d8cca2b82630c2d760af9d204Jesse Wilson } else if (protocol.equals("jar")) { 4428f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson streamHandler = new JarHandler(); 443c2ebff3511f9df4d8cca2b82630c2d760af9d204Jesse Wilson } 4448f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson if (streamHandler != null) { 4458f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson streamHandlers.put(protocol, streamHandler); 446c2ebff3511f9df4d8cca2b82630c2d760af9d204Jesse Wilson } 447adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 448adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 449adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 4508f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * Returns the content of the resource which is referred by this URL. By 4515292410e4ebf7fb5149eefd2f52fcb94c46690a6Jesse Wilson * default this returns an {@code InputStream}, or null if the content type 4528f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * of the response is unknown. 453adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 454adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final Object getContent() throws IOException { 455adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return openConnection().getContent(); 456adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 457adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 458adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 4598f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * Equivalent to {@code openConnection().getContent(types)}. 4608f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson */ 4618f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson @SuppressWarnings("unchecked") // Param not generic in spec 462adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final Object getContent(Class[] types) throws IOException { 463adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return openConnection().getContent(types); 464adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 465adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 466adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 4678f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * Equivalent to {@code openConnection().getInputStream(types)}. 468adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 4698f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson public final InputStream openStream() throws IOException { 470adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return openConnection().getInputStream(); 471adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 472adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 473adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 4748f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * Returns a new connection to the resource referred to by this URL. 475f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 4768f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * @throws IOException if an error occurs while opening the connection. 477adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 478adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public URLConnection openConnection() throws IOException { 4798f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson return streamHandler.openConnection(this); 4808f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson } 4818f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson 4828f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson /** 4838f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * Returns a new connection to the resource referred to by this URL. 4848f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * 4858f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * @param proxy the proxy through which the connection will be established. 4868f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * @throws IOException if an I/O error occurs while opening the connection. 4878f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * @throws IllegalArgumentException if the argument proxy is null or of is 4888f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * an invalid type. 4898f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * @throws UnsupportedOperationException if the protocol handler does not 4908f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * support opening connections through proxies. 4918f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson */ 4928f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson public URLConnection openConnection(Proxy proxy) throws IOException { 4938f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson if (proxy == null) { 4948f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson throw new IllegalArgumentException("proxy == null"); 4958f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson } 4968f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson return streamHandler.openConnection(this, proxy); 497adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 498adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 499adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 5008f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * Returns the URI equivalent to this URL. 501f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 5028f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * @throws URISyntaxException if this URL cannot be converted into a URI. 503adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 504adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public URI toURI() throws URISyntaxException { 505adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return new URI(toExternalForm()); 506adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 507adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 508adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 509d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson * Encodes this URL to the equivalent URI after escaping characters that are 510d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson * not permitted by URI. 511d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson * 512d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson * @hide 513d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson */ 514d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson public URI toURILenient() throws URISyntaxException { 5158f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson if (streamHandler == null) { 516d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson throw new IllegalStateException(protocol); 517d1b5e5da828434388e486a388710d21e4306dae0Jesse Wilson } 5188f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson return new URI(streamHandler.toExternalForm(this, true)); 519adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 520adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 521adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 522adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns a string containing a concise, human-readable representation of 523adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * this URL. The returned string is the same as the result of the method 524adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@code toExternalForm()}. 525adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 5268f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson @Override public String toString() { 527adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return toExternalForm(); 528adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 529adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 530adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 531adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns a string containing a concise, human-readable representation of 532adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * this URL. 533adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 534adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public String toExternalForm() { 5358f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson if (streamHandler == null) { 536f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes return "unknown protocol(" + protocol + ")://" + host + file; 537adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 5388f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson return streamHandler.toExternalForm(this); 539adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 540adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 5418f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson private void readObject(ObjectInputStream stream) throws IOException { 542adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 543adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project stream.defaultReadObject(); 544adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (host != null && authority == null) { 545adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project fixURL(true); 546adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if (authority != null) { 547adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int index; 548adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if ((index = authority.lastIndexOf('@')) > -1) { 549adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project userInfo = authority.substring(0, index); 550adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 551adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (file != null && (index = file.indexOf('?')) > -1) { 552adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project query = file.substring(index + 1); 553adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project path = file.substring(0, index); 554adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 555adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project path = file; 556adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 557adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 558adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project setupStreamHandler(); 5598f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson if (streamHandler == null) { 560b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new IOException("Unknown protocol: " + protocol); 561adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 5628f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson hashCode = 0; // necessary until http://b/4471249 is fixed 563adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (ClassNotFoundException e) { 5648f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson throw new IOException(e); 565adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 566adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 567adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 568adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private void writeObject(ObjectOutputStream s) throws IOException { 569adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project s.defaultWriteObject(); 570adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 571adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 5728f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson /** @hide */ 5738f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson public int getEffectivePort() { 5748f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson return URI.getEffectivePort(protocol, port); 5758f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson } 5768f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson 577adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 5788f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * Returns the protocol of this URL like "http" or "file". This is also 5798f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * known as the scheme. The returned string is lower case. 580adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 5818f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson public String getProtocol() { 5828f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson return protocol; 583adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 584adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 585adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 5865292410e4ebf7fb5149eefd2f52fcb94c46690a6Jesse Wilson * Returns the authority part of this URL, or null if this URL has no 5875292410e4ebf7fb5149eefd2f52fcb94c46690a6Jesse Wilson * authority. 588adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 5898f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson public String getAuthority() { 5908f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson return authority; 591adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 592adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 593adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 5945292410e4ebf7fb5149eefd2f52fcb94c46690a6Jesse Wilson * Returns the user info of this URL, or null if this URL has no user info. 595adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 5968f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson public String getUserInfo() { 5978f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson return userInfo; 598adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 599adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 6008f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson /** 6018f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * Returns the host name or IP address of this URL. 6028f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson */ 6038f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson public String getHost() { 6048f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson return host; 605c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson } 606c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson 607adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 6085292410e4ebf7fb5149eefd2f52fcb94c46690a6Jesse Wilson * Returns the port number of this URL or {@code -1} if this URL has no 6098f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * explicit port. 610f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 6118f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * <p>If this URL has no explicit port, connections opened using this URL 6128f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * will use its {@link #getDefaultPort() default port}. 613adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 6148f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson public int getPort() { 6158f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson return port; 616adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 617adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 618adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 6198f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * Returns the default port number of the protocol used by this URL. If no 6208f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * default port is defined by the protocol or the {@code URLStreamHandler}, 6218f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * {@code -1} will be returned. 622f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 6238f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * @see URLStreamHandler#getDefaultPort 624adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 6258f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson public int getDefaultPort() { 6268f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson return streamHandler.getDefaultPort(); 627adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 628adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 629adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 6305292410e4ebf7fb5149eefd2f52fcb94c46690a6Jesse Wilson * Returns the file of this URL. 631adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 6328f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson public String getFile() { 6338f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson return file; 634adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 635adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 636adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 6378f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson * Returns the path part of this URL. 638adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 639adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public String getPath() { 640adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return path; 641adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 642adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 643adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 6445292410e4ebf7fb5149eefd2f52fcb94c46690a6Jesse Wilson * Returns the query part of this URL, or null if this URL has no query. 645adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 6468f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson public String getQuery() { 6478f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson return query; 648adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 649adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 650adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 6515292410e4ebf7fb5149eefd2f52fcb94c46690a6Jesse Wilson * Returns the value of the reference part of this URL, or null if this URL 6525292410e4ebf7fb5149eefd2f52fcb94c46690a6Jesse Wilson * has no reference part. This is also known as the fragment. 653adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 6548f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson public String getRef() { 6558f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson return ref; 656adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 657adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 658adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 659adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Sets the properties of this URL using the provided arguments. Only a 660adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@code URLStreamHandler} can use this method to set fields of the 661adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * existing URL instance. A URL is generally constant. 6628f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson */ 6638f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson protected void set(String protocol, String host, int port, String authority, String userInfo, 6648f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson String path, String query, String ref) { 6655292410e4ebf7fb5149eefd2f52fcb94c46690a6Jesse Wilson String file = path; 66680a7fbab52b96c9fd47c72f8987d1babe2cd001dElliott Hughes if (query != null && !query.isEmpty()) { 6675292410e4ebf7fb5149eefd2f52fcb94c46690a6Jesse Wilson file += "?" + query; 668adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 6695292410e4ebf7fb5149eefd2f52fcb94c46690a6Jesse Wilson set(protocol, host, port, file, ref); 670adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.authority = authority; 671adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.userInfo = userInfo; 672adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.path = path; 673adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.query = query; 674adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 675adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 676