diff options
author | Jesse Wilson <jessewilson@google.com> | 2011-05-26 19:33:57 -0700 |
---|---|---|
committer | Jesse Wilson <jessewilson@google.com> | 2011-05-27 09:35:55 -0700 |
commit | c68609e723a5daa20888abdb640799d4353fd590 (patch) | |
tree | 9b08f4f4c8d43af80da216a05223a24ff8c9fed0 /luni | |
parent | 73d0c8232b23ad74af5cc198143603ff6ee5236b (diff) | |
download | libcore-c68609e723a5daa20888abdb640799d4353fd590.zip libcore-c68609e723a5daa20888abdb640799d4353fd590.tar.gz libcore-c68609e723a5daa20888abdb640799d4353fd590.tar.bz2 |
Document java.net.URI.
Change-Id: I941ba9cb4a2d48b052c25b7799ac466549df8d53
http://b/2753295
Diffstat (limited to 'luni')
-rw-r--r-- | luni/src/main/java/java/net/URI.java | 434 | ||||
-rw-r--r-- | luni/src/main/java/java/net/URL.java | 16 | ||||
-rw-r--r-- | luni/src/test/java/libcore/java/net/URITest.java | 81 | ||||
-rw-r--r-- | luni/src/test/java/libcore/java/net/URLTest.java | 64 |
4 files changed, 321 insertions, 274 deletions
diff --git a/luni/src/main/java/java/net/URI.java b/luni/src/main/java/java/net/URI.java index 352e25f..4df73c1 100644 --- a/luni/src/main/java/java/net/URI.java +++ b/luni/src/main/java/java/net/URI.java @@ -26,9 +26,62 @@ import libcore.net.UriCodec; import libcore.net.url.UrlUtils; /** - * This class represents an instance of a URI as defined by - * <a href="http://www.ietf.org/rfc/rfc2396.txt">RFC 2396</a>. + * A Uniform Resource Identifier that identifies an abstract or physical + * resource, as specified by <a href="http://www.ietf.org/rfc/rfc2396.txt">RFC + * 2396</a>. + * + * <h3>Parts of a URI</h3> + * A URI is composed of many parts. This class can both parse URI strings into + * parts and compose URI strings from parts. For example, consider the parts of + * this URI: + * {@code http://username:password@host:8080/directory/file?query#fragment} + * <table> + * <tr><th>Component </th><th>Example value </th><th>Also known as</th></tr> + * <tr><td>{@link #getScheme() Scheme} </td><td>{@code http} </td><td>protocol</td></tr> + * <tr><td>{@link #getSchemeSpecificPart() Scheme-specific part}</td><td>{@code //username:password@host:8080/directory/file?query#fragment}</td><td></td></tr> + * <tr><td>{@link #getAuthority() Authority} </td><td>{@code username:password@host:8080} </td><td></td></tr> + * <tr><td>{@link #getUserInfo() User Info} </td><td>{@code username:password} </td><td></td></tr> + * <tr><td>{@link #getHost() Host} </td><td>{@code host} </td><td></td></tr> + * <tr><td>{@link #getPort() Port} </td><td>{@code 8080} </td><td></td></tr> + * <tr><td>{@link #getPath() Path} </td><td>{@code /directory/file} </td><td></td></tr> + * <tr><td>{@link #getQuery() Query} </td><td>{@code query} </td><td></td></tr> + * <tr><td>{@link #getFragment() Fragment} </td><td>{@code fragment} </td><td>ref</td></tr> + * </table> + * + * <h3>Encoding and Decoding URI Components</h3> + * Each component of a URI permits a limited set of legal characters. Other + * characters must first be <i>encoded</i> before they can be embedded in a URI. + * To recover the original characters from a URI, they may be <i>decoded</i>. + * This class refers to encoded strings as <string>raw</string> strings. For + * example, consider how this URI is decoded: + * {@code http://user:pa55w%3Frd@host:80/doc%7Csearch?q=green%20robots#over%206%22} + * <table> + * <tr><th>Component </th><th>Legal Characters </th><th>Other Constraints </th><th>Raw Value </th><th>Value</th></tr> + * <tr><td>Scheme </td><td>{@code 0-9}, {@code a-z}, {@code A-Z}, {@code +-.} </td><td>First character must be in {@code a-z}, {@code A-Z}</td><td> </td><td>{@code http}</td></tr> + * <tr><td>Scheme-specific part</td><td>{@code 0-9}, {@code a-z}, {@code A-Z}, {@code _-!.~'()*,;:$&+=?/[]@}</td><td>Non-ASCII characters okay </td><td>{@code //user:pa55w%3Frd@host:80/doc%7Csearch?q=green%20robots}</td><td>{@code //user:pa55w?rd@host:80/doc|search?q=green robots}</td></tr> + * <tr><td>Authority </td><td>{@code 0-9}, {@code a-z}, {@code A-Z}, {@code _-!.~'()*,;:$&+=@[]} </td><td>Non-ASCII characters okay </td><td>{@code user:pa55w%3Frd@host:80} </td><td>{@code user:pa55w?rd@host:80}</td></tr> + * <tr><td>User Info </td><td>{@code 0-9}, {@code a-z}, {@code A-Z}, {@code _-!.~'()*,;:$&+=} </td><td>Non-ASCII characters okay </td><td>{@code user:pa55w%3Frd} </td><td>{@code user:pa55w?rd}</td></tr> + * <tr><td>Host </td><td>{@code 0-9}, {@code a-z}, {@code A-Z}, {@code -.[]} </td><td>Domain name, IPv4 address or [IPv6 address] </td><td> </td><td>host</td></tr> + * <tr><td>Port </td><td>{@code 0-9} </td><td> </td><td> </td><td>{@code 80}</td></tr> + * <tr><td>Path </td><td>{@code 0-9}, {@code a-z}, {@code A-Z}, {@code _-!.~'()*,;:$&+=/@} </td><td>Non-ASCII characters okay </td><td>{@code /doc%7Csearch} </td><td>{@code /doc|search}</td></tr> + * <tr><td>Query </td><td>{@code 0-9}, {@code a-z}, {@code A-Z}, {@code _-!.~'()*,;:$&+=?/[]@}</td><td>Non-ASCII characters okay </td><td>{@code q=green%20robots} </td><td>{@code q=green robots}</td></tr> + * <tr><td>Fragment </td><td>{@code 0-9}, {@code a-z}, {@code A-Z}, {@code _-!.~'()*,;:$&+=?/[]@}</td><td>Non-ASCII characters okay </td><td>{@code over%206%22} </td><td>{@code over 6"}</td></tr> + * </table> + * A URI's host, port and scheme are not eligible for encoding and must not + * contain illegal characters. + * + * <p>To encode a URI, invoke any of the multiple-parameter constructors of this + * class. These constructors accept your original strings and encode them into + * their raw form. + * + * <p>To decode a URI, invoke the single-string constructor, and then the + * appropriate <code>get<i>Component()</i></code> methods to get the decoded + * components. + * + * <p>The {@link URL} class can be used to retrieve resources by their URI. */ +// TODO: document relative URIs +// TODO: document opaque URIs public final class URI implements Comparable<URI>, Serializable { private static final long serialVersionUID = -6052424284110960213l; @@ -96,94 +149,51 @@ public final class URI implements Comparable<URI>, Serializable { private URI() {} /** - * Creates a new URI instance according to the given string {@code uri}. + * Creates a new URI instance by parsing {@code spec}. * - * @param uri - * the textual URI representation to be parsed into a URI object. - * @throws URISyntaxException - * if the given {@code uri} isn't an - * <a href="http://www.ietf.org/rfc/rfc2396.txt">RFC 2396</a> URI - * or could not be parsed correctly. + * @param spec a URI whose illegal characters have all been encoded. */ - public URI(String uri) throws URISyntaxException { - parseURI(uri, false); + public URI(String spec) throws URISyntaxException { + parseURI(spec, false); } /** - * Creates a new URI instance using the given arguments. This constructor - * first creates a temporary URI string from the given components. This - * string will be parsed later on to create the URI instance. - * <p> - * {@code [scheme:]scheme-specific-part[#fragment]} + * Creates a new URI instance of the given unencoded component parts. * - * @param scheme - * the scheme part of the URI. - * @param ssp - * the scheme-specific-part of the URI. - * @param frag - * the fragment part of the URI. - * @throws URISyntaxException - * if the resulting URI isn't an - * <a href="http://www.ietf.org/rfc/rfc2396.txt">RFC 2396</a> URI - * or could not be parsed correctly. + * @param scheme the URI scheme, or null for a non-absolute URI. */ - public URI(String scheme, String ssp, String frag) throws URISyntaxException { + public URI(String scheme, String schemeSpecificPart, String fragment) + throws URISyntaxException { StringBuilder uri = new StringBuilder(); if (scheme != null) { uri.append(scheme); uri.append(':'); } - if (ssp != null) { - ALL_LEGAL_ENCODER.appendEncoded(uri, ssp); + if (schemeSpecificPart != null) { + ALL_LEGAL_ENCODER.appendEncoded(uri, schemeSpecificPart); } - if (frag != null) { + if (fragment != null) { uri.append('#'); - ALL_LEGAL_ENCODER.appendEncoded(uri, frag); + ALL_LEGAL_ENCODER.appendEncoded(uri, fragment); } parseURI(uri.toString(), false); } /** - * Creates a new URI instance using the given arguments. This constructor - * first creates a temporary URI string from the given components. This - * string will be parsed later on to create the URI instance. - * <p> - * {@code [scheme:][user-info@]host[:port][path][?query][#fragment]} + * Creates a new URI instance of the given unencoded component parts. * - * @param scheme - * the scheme part of the URI. - * @param userInfo - * the user information of the URI for authentication and - * authorization. - * @param host - * the host name of the URI. - * @param port - * the port number of the URI. - * @param path - * the path to the resource on the host. - * @param query - * the query part of the URI to specify parameters for the - * resource. - * @param fragment - * the fragment part of the URI. - * @throws URISyntaxException - * if the resulting URI isn't an - * <a href="http://www.ietf.org/rfc/rfc2396.txt">RFC 2396</a> URI - * or could not be parsed correctly. + * @param scheme the URI scheme, or null for a non-absolute URI. */ - public URI(String scheme, String userInfo, String host, int port, - String path, String query, String fragment) - throws URISyntaxException { - + public URI(String scheme, String userInfo, String host, int port, String path, String query, + String fragment) throws URISyntaxException { if (scheme == null && userInfo == null && host == null && path == null && query == null && fragment == null) { this.path = ""; return; } - if (scheme != null && path != null && path.length() > 0 - && path.charAt(0) != '/') { + if (scheme != null && path != null && !path.isEmpty() && path.charAt(0) != '/') { throw new URISyntaxException(path, "Relative path"); } @@ -203,10 +213,8 @@ public final class URI implements Comparable<URI>, Serializable { } if (host != null) { - // check for IPv6 addresses that hasn't been enclosed - // in square brackets - if (host.indexOf(':') != -1 && host.indexOf(']') == -1 - && host.indexOf('[') == -1) { + // check for IPv6 addresses that hasn't been enclosed in square brackets + if (host.indexOf(':') != -1 && host.indexOf(']') == -1 && host.indexOf('[') == -1) { host = "[" + host + "]"; } uri.append(host); @@ -235,56 +243,22 @@ public final class URI implements Comparable<URI>, Serializable { } /** - * Creates a new URI instance using the given arguments. This constructor - * first creates a temporary URI string from the given components. This - * string will be parsed later on to create the URI instance. - * <p> - * {@code [scheme:]host[path][#fragment]} + * Creates a new URI instance of the given unencoded component parts. * - * @param scheme - * the scheme part of the URI. - * @param host - * the host name of the URI. - * @param path - * the path to the resource on the host. - * @param fragment - * the fragment part of the URI. - * @throws URISyntaxException - * if the resulting URI isn't an - * <a href="http://www.ietf.org/rfc/rfc2396.txt">RFC 2396</a> URI - * or could not be parsed correctly. + * @param scheme the URI scheme, or null for a non-absolute URI. */ public URI(String scheme, String host, String path, String fragment) throws URISyntaxException { this(scheme, null, host, -1, path, null, fragment); } /** - * Creates a new URI instance using the given arguments. This constructor - * first creates a temporary URI string from the given components. This - * string will be parsed later on to create the URI instance. - * <p> - * {@code [scheme:][//authority][path][?query][#fragment]} + * Creates a new URI instance of the given unencoded component parts. * - * @param scheme - * the scheme part of the URI. - * @param authority - * the authority part of the URI. - * @param path - * the path to the resource on the host. - * @param query - * the query part of the URI to specify parameters for the - * resource. - * @param fragment - * the fragment part of the URI. - * @throws URISyntaxException - * if the resulting URI isn't an - * <a href="http://www.ietf.org/rfc/rfc2396.txt">RFC 2396</a> URI - * or could not be parsed correctly. + * @param scheme the URI scheme, or null for a non-absolute URI. */ public URI(String scheme, String authority, String path, String query, String fragment) throws URISyntaxException { - if (scheme != null && path != null && path.length() > 0 - && path.charAt(0) != '/') { + if (scheme != null && path != null && !path.isEmpty() && path.charAt(0) != '/') { throw new URISyntaxException(path, "Relative path"); } @@ -774,18 +748,7 @@ public final class URI implements Comparable<URI>, Serializable { return first.substring(prevIndex).equals(second.substring(prevIndex)); } - /** - * Compares this URI instance with the given argument {@code o} and - * determines if both are equal. Two URI instances are equal if all single - * parts are identical in their meaning. - * - * @param o - * the URI this instance has to be compared with. - * @return {@code true} if both URI instances point to the same resource, - * {@code false} otherwise. - */ - @Override - public boolean equals(Object o) { + @Override public boolean equals(Object o) { if (!(o instanceof URI)) { return false; } @@ -866,45 +829,71 @@ public final class URI implements Comparable<URI>, Serializable { } /** - * Gets the decoded authority part of this URI. - * - * @return the decoded authority part or {@code null} if undefined. + * Returns the scheme of this URI, or null if this URI has no scheme. This + * is also known as the protocol. + */ + public String getScheme() { + return scheme; + } + + /** + * Returns the decoded scheme-specific part of this URI, or null if this URI + * has no scheme-specific part. + */ + public String getSchemeSpecificPart() { + return decode(schemeSpecificPart); + } + + /** + * Returns the encoded scheme-specific part of this URI, or null if this URI + * has no scheme-specific part. + */ + public String getRawSchemeSpecificPart() { + return schemeSpecificPart; + } + + /** + * Returns the decoded authority part of this URI, or null if this URI has + * no authority. */ public String getAuthority() { return decode(authority); } /** - * Gets the decoded fragment part of this URI. - * - * @return the decoded fragment part or {@code null} if undefined. + * Returns the encoded authority of this URI, or null if this URI has no + * authority. */ - public String getFragment() { - return decode(fragment); + public String getRawAuthority() { + return authority; } /** - * Gets the host part of this URI. - * - * @return the host part or {@code null} if undefined. + * Returns the decoded user info of this URI, or null if this URI has no + * user info. */ - public String getHost() { - return host; + public String getUserInfo() { + return decode(userInfo); } /** - * Gets the decoded path part of this URI. - * - * @return the decoded path part or {@code null} if undefined. + * Returns the encoded user info of this URI, or null if this URI has no + * user info. */ - public String getPath() { - return decode(path); + public String getRawUserInfo() { + return userInfo; } /** - * Gets the port number of this URI. - * - * @return the port number or {@code -1} if undefined. + * Returns the host of this URI, or null if this URI has no host. + */ + public String getHost() { + return host; + } + + /** + * Returns the port number of this URI, or {@code -1} if this URI has no + * explicit port. */ public int getPort() { return port; @@ -936,102 +925,50 @@ public final class URI implements Comparable<URI>, Serializable { } /** - * Gets the decoded query part of this URI. - * - * @return the decoded query part or {@code null} if undefined. - */ - public String getQuery() { - return decode(query); - } - - /** - * Gets the authority part of this URI in raw form. - * - * @return the encoded authority part or {@code null} if undefined. - */ - public String getRawAuthority() { - return authority; - } - - /** - * Gets the fragment part of this URI in raw form. - * - * @return the encoded fragment part or {@code null} if undefined. + * Returns the decoded path of this URI, or null if this URI has no path. */ - public String getRawFragment() { - return fragment; + public String getPath() { + return decode(path); } /** - * Gets the path part of this URI in raw form. - * - * @return the encoded path part or {@code null} if undefined. + * Gets the encoded path of this URI, or null if this URI has no path. */ public String getRawPath() { return path; } /** - * Gets the query part of this URI in raw form. - * - * @return the encoded query part or {@code null} if undefined. + * Returns the decoded query of this URI, or null if this URI has no query. */ - public String getRawQuery() { - return query; - } - - /** - * Gets the scheme-specific part of this URI in raw form. - * - * @return the encoded scheme-specific part or {@code null} if undefined. - */ - public String getRawSchemeSpecificPart() { - return schemeSpecificPart; - } - - /** - * Gets the user-info part of this URI in raw form. - * - * @return the encoded user-info part or {@code null} if undefined. - */ - public String getRawUserInfo() { - return userInfo; + public String getQuery() { + return decode(query); } /** - * Gets the scheme part of this URI. - * - * @return the scheme part or {@code null} if undefined. + * Returns the encoded query of this URI, or null if this URI has no query. */ - public String getScheme() { - return scheme; + public String getRawQuery() { + return query; } /** - * Gets the decoded scheme-specific part of this URI. - * - * @return the decoded scheme-specific part or {@code null} if undefined. + * Returns the decoded fragment of this URI, or null if this URI has no + * fragment. */ - public String getSchemeSpecificPart() { - return decode(schemeSpecificPart); + public String getFragment() { + return decode(fragment); } /** - * Gets the decoded user-info part of this URI. - * - * @return the decoded user-info part or {@code null} if undefined. + * Gets the encoded fragment of this URI, or null if this URI has no + * fragment. */ - public String getUserInfo() { - return decode(userInfo); + public String getRawFragment() { + return fragment; } - /** - * Gets the hashcode value of this URI instance. - * - * @return the appropriate hashcode value. - */ - @Override - public int hashCode() { + @Override public int hashCode() { if (hash == -1) { hash = getHashString().hashCode(); } @@ -1039,22 +976,18 @@ public final class URI implements Comparable<URI>, Serializable { } /** - * Indicates whether this URI is absolute, which means that a scheme part is - * defined in this URI. - * - * @return {@code true} if this URI is absolute, {@code false} otherwise. + * Returns true if this URI is absolute, which means that a scheme is + * defined. */ public boolean isAbsolute() { + // TODO: simplify to 'scheme != null' ? return absolute; } /** - * Indicates whether this URI is opaque or not. An opaque URI is absolute - * and has a scheme-specific part which does not start with a slash - * character. All parts except scheme, scheme-specific and fragment are - * undefined. - * - * @return {@code true} if the URI is opaque, {@code false} otherwise. + * Returns true if this URI is opaque. Opaque URIs are absolute and have a + * scheme-specific part that does not start with a slash character. All + * parts except scheme, scheme-specific and fragment are undefined. */ public boolean isOpaque() { return opaque; @@ -1276,43 +1209,42 @@ public final class URI implements Comparable<URI>, Serializable { } /** - * Returns the textual string representation of this URI instance. - * - * @return the textual string representation of this URI. + * Returns the encoded URI. */ - @Override - public String toString() { - if (string == null) { - StringBuilder result = new StringBuilder(); - if (scheme != null) { - result.append(scheme); - result.append(':'); - } - if (opaque) { - result.append(schemeSpecificPart); - } else { - if (authority != null) { - result.append("//"); - result.append(authority); - } + @Override public String toString() { + if (string != null) { + return string; + } - if (path != null) { - result.append(path); - } + StringBuilder result = new StringBuilder(); + if (scheme != null) { + result.append(scheme); + result.append(':'); + } + if (opaque) { + result.append(schemeSpecificPart); + } else { + if (authority != null) { + result.append("//"); + result.append(authority); + } - if (query != null) { - result.append('?'); - result.append(query); - } + if (path != null) { + result.append(path); } - if (fragment != null) { - result.append('#'); - result.append(fragment); + if (query != null) { + result.append('?'); + result.append(query); } + } - string = result.toString(); + if (fragment != null) { + result.append('#'); + result.append(fragment); } + + string = result.toString(); return string; } @@ -1378,8 +1310,7 @@ public final class URI implements Comparable<URI>, Serializable { return new URL(toString()); } - private void readObject(ObjectInputStream in) throws IOException, - ClassNotFoundException { + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); try { parseURI(string, false); @@ -1388,8 +1319,7 @@ public final class URI implements Comparable<URI>, Serializable { } } - private void writeObject(ObjectOutputStream out) throws IOException, - ClassNotFoundException { + private void writeObject(ObjectOutputStream out) throws IOException, ClassNotFoundException { // call toString() to ensure the value of string field is calculated toString(); out.defaultWriteObject(); diff --git a/luni/src/main/java/java/net/URL.java b/luni/src/main/java/java/net/URL.java index 91a398e..798fee7 100644 --- a/luni/src/main/java/java/net/URL.java +++ b/luni/src/main/java/java/net/URL.java @@ -248,20 +248,14 @@ public final class URL implements Serializable { this.host = host; this.port = port; - /* - * Force the path to start with a '/' if this URL has an authority. - * Otherwise they blend together like http://android.comindex.html. - */ - if (host != null && !host.isEmpty() && !file.startsWith("/")) { - file = "/" + file; - } + file = UrlUtils.authoritySafePath(host, file); // Set the fields from the arguments. Handle the case where the // passed in "file" includes both a file and a reference part. - int index = file.indexOf("#", file.lastIndexOf("/")); - if (index != -1) { - this.file = file.substring(0, index); - ref = file.substring(index + 1); + int hash = file.indexOf("#"); + if (hash != -1) { + this.file = file.substring(0, hash); + this.ref = file.substring(hash + 1); } else { this.file = file; } diff --git a/luni/src/test/java/libcore/java/net/URITest.java b/luni/src/test/java/libcore/java/net/URITest.java index 3a419c0..9ff8543 100644 --- a/luni/src/test/java/libcore/java/net/URITest.java +++ b/luni/src/test/java/libcore/java/net/URITest.java @@ -366,7 +366,7 @@ public final class URITest extends TestCase { assertEquals("http://a/b/c/g/", base.resolve("g/").toString()); assertEquals("http://a/g", base.resolve("/g").toString()); assertEquals("http://g", base.resolve("//g").toString()); - assertEquals("http://a/b/c/d;p?y", base.resolve("?y").toString()); // fails on RI + assertEquals("http://a/b/c/d;p?y", base.resolve("?y").toString()); // RI fails; loses file assertEquals("http://a/b/c/g?y", base.resolve("g?y").toString()); assertEquals("http://a/b/c/d;p?q#s", base.resolve("#s").toString()); assertEquals("http://a/b/c/g#s", base.resolve("g#s").toString()); @@ -387,13 +387,13 @@ public final class URITest extends TestCase { public void testRfc1808AbnormalExampleTooManyDotDotSequences() throws Exception { URI base = new URI("http://a/b/c/d;p?q"); - assertEquals("http://a/g", base.resolve("../../../g").toString()); // fails on RI + assertEquals("http://a/g", base.resolve("../../../g").toString()); // RI doesn't normalize assertEquals("http://a/g", base.resolve("../../../../g").toString()); // fails on RI } public void testRfc1808AbnormalExampleRemoveDotSegments() throws Exception { URI base = new URI("http://a/b/c/d;p?q"); - assertEquals("http://a/g", base.resolve("/./g").toString()); // fails on RI + assertEquals("http://a/g", base.resolve("/./g").toString()); // RI doesn't normalize assertEquals("http://a/g", base.resolve("/../g").toString()); // fails on RI assertEquals("http://a/b/c/g.", base.resolve("g.").toString()); assertEquals("http://a/b/c/.g", base.resolve(".g").toString()); @@ -508,7 +508,7 @@ public final class URITest extends TestCase { public void testRelativize() throws Exception { URI a = new URI("http://host/a/b"); URI b = new URI("http://host/a/b/c"); - assertEquals("b/c", a.relativize(b).toString()); // fails on both the RI and libcore + assertEquals("b/c", a.relativize(b).toString()); // RI assumes a directory } public void testParseServerAuthorityInvalidAuthority() throws Exception { @@ -531,9 +531,76 @@ public final class URITest extends TestCase { assertEquals(-1, uri.getPort()); } - // TODO: test http://#fragment - // TODO: test http://?query - // TODO: test http:///path + public void testEncodingParts() throws Exception { + URI uri = new URI("http", "user:pa55w?rd", "host", 80, "/doc|search", + "q=green robots", "over 6\""); + assertEquals("http", uri.getScheme()); + assertEquals("user:pa55w?rd@host:80", uri.getAuthority()); + assertEquals("user:pa55w%3Frd@host:80", uri.getRawAuthority()); + assertEquals("user:pa55w?rd", uri.getUserInfo()); + assertEquals("user:pa55w%3Frd", uri.getRawUserInfo()); + assertEquals("/doc|search", uri.getPath()); + assertEquals("/doc%7Csearch", uri.getRawPath()); + assertEquals("q=green robots", uri.getQuery()); + assertEquals("q=green%20robots", uri.getRawQuery()); + assertEquals("over 6\"", uri.getFragment()); + assertEquals("over%206%22", uri.getRawFragment()); + assertEquals("//user:pa55w?rd@host:80/doc|search?q=green robots", + uri.getSchemeSpecificPart()); + assertEquals("//user:pa55w%3Frd@host:80/doc%7Csearch?q=green%20robots", + uri.getRawSchemeSpecificPart()); + assertEquals("http://user:pa55w%3Frd@host:80/doc%7Csearch?q=green%20robots#over%206%22", + uri.toString()); + } + + public void testSchemeCaseIsNotCanonicalized() throws Exception { + URI uri = new URI("HTTP://host/path"); + assertEquals("HTTP", uri.getScheme()); + } + + public void testEmptyAuthorityWithPath() throws Exception { + URI uri = new URI("http:///path"); + assertEquals(null, uri.getAuthority()); + assertEquals("/path", uri.getPath()); + } + + public void testEmptyAuthorityWithQuery() throws Exception { + URI uri = new URI("http://?query"); + assertEquals(null, uri.getAuthority()); + assertEquals("", uri.getPath()); + assertEquals("query", uri.getQuery()); + } + + public void testEmptyAuthorityWithFragment() throws Exception { + URI uri = new URI("http://#fragment"); + assertEquals(null, uri.getAuthority()); + assertEquals("", uri.getPath()); + assertEquals("fragment", uri.getFragment()); + } + + public void testEncodingConstructorsRefuseRelativePath() throws Exception { + try { + new URI("http", "host", "relative", null); + fail(); + } catch (URISyntaxException expected) { + } + try { + new URI("http", "host", "relative", null, null); + fail(); + } catch (URISyntaxException expected) { + } + try { + new URI("http", null, "host", -1, "relative", null, null); + fail(); + } catch (URISyntaxException expected) { + } + } + + public void testEncodingConstructorsAcceptEmptyPath() throws Exception { + assertEquals("", new URI("http", "host", "", null).getPath()); + assertEquals("", new URI("http", "host", "", null, null).getPath()); + assertEquals("", new URI("http", null, "host", -1, "", null, null).getPath()); + } // Adding a new test? Consider adding an equivalent test to URLTest.java } diff --git a/luni/src/test/java/libcore/java/net/URLTest.java b/luni/src/test/java/libcore/java/net/URLTest.java index d57db07..946ac5c 100644 --- a/luni/src/test/java/libcore/java/net/URLTest.java +++ b/luni/src/test/java/libcore/java/net/URLTest.java @@ -19,6 +19,8 @@ package libcore.java.net; import java.net.Inet6Address; import java.net.InetAddress; import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; import java.net.URL; import junit.framework.TestCase; import libcore.java.util.SerializableTester; @@ -59,7 +61,7 @@ public final class URLTest extends TestCase { URL urlByHostName = new URL("http://localhost/foo?bar=baz#quux"); URL urlByAddress = new URL("http://" + address + "/foo?bar=baz#quux"); assertFalse("Expected " + urlByHostName + " to not equal " + urlByAddress, - urlByHostName.equals(urlByAddress)); // fails on RI + urlByHostName.equals(urlByAddress)); // fails on RI, which does DNS } } @@ -321,6 +323,13 @@ public final class URLTest extends TestCase { assertEquals("fragment/path", url.getRef()); } + public void testSlashInFragmentCombiningConstructor() throws Exception { + URL url = new URL("http", "host", "/file#fragment/path"); + assertEquals("/file", url.getFile()); + assertEquals("/file", url.getPath()); + assertEquals("fragment/path", url.getRef()); + } + public void testHashInFragment() throws Exception { URL url = new URL("http://host/file#fragment#another"); assertEquals("/file", url.getFile()); @@ -426,7 +435,7 @@ public final class URLTest extends TestCase { public void testMalformedUrlsRefusedByFirefoxAndChrome() throws Exception { URL base = new URL("http://host/a/b/c"); - assertEquals("http://", new URL(base, "http://").toString()); // fails on RI + assertEquals("http://", new URL(base, "http://").toString()); // fails on RI; path retained assertEquals("http://", new URL(base, "//").toString()); // fails on RI assertEquals("https:", new URL(base, "https:").toString()); assertEquals("https:/", new URL(base, "https:/").toString()); @@ -441,7 +450,7 @@ public final class URLTest extends TestCase { assertEquals("http://a/b/c/g/", new URL(base, "g/").toString()); assertEquals("http://a/g", new URL(base, "/g").toString()); assertEquals("http://g", new URL(base, "//g").toString()); - assertEquals("http://a/b/c/d;p?y", new URL(base, "?y").toString()); // fails on RI + assertEquals("http://a/b/c/d;p?y", new URL(base, "?y").toString()); // RI fails; file lost assertEquals("http://a/b/c/g?y", new URL(base, "g?y").toString()); assertEquals("http://a/b/c/d;p?q#s", new URL(base, "#s").toString()); assertEquals("http://a/b/c/g#s", new URL(base, "g#s").toString()); @@ -511,7 +520,7 @@ public final class URLTest extends TestCase { assertEquals("http", url.getProtocol()); assertEquals("host", url.getAuthority()); assertEquals("host", url.getHost()); - assertEquals("/a", url.getFile()); // fails on RI + assertEquals("/a", url.getFile()); // RI fails; doesn't insert '/' separator assertEquals("http://host/a", url.toString()); // fails on RI } @@ -602,5 +611,52 @@ public final class URLTest extends TestCase { assertFalse(new URL("http://android.com").equals(new URL("http://android.com/"))); } + public void testUrlDoesNotEncodeParts() throws Exception { + URL url = new URL("http", "host", 80, "/doc|search?q=green robots#over 6\""); + assertEquals("http", url.getProtocol()); + assertEquals("host:80", url.getAuthority()); + assertEquals("/doc|search", url.getPath()); + assertEquals("q=green robots", url.getQuery()); + assertEquals("over 6\"", url.getRef()); + assertEquals("http://host:80/doc|search?q=green robots#over 6\"", url.toString()); + } + + public void testSchemeCaseIsCanonicalized() throws Exception { + URL url = new URL("HTTP://host/path"); + assertEquals("http", url.getProtocol()); + } + + public void testEmptyAuthorityWithPath() throws Exception { + URL url = new URL("http:///path"); + assertEquals("", url.getAuthority()); + assertEquals("/path", url.getPath()); + } + + public void testEmptyAuthorityWithQuery() throws Exception { + URL url = new URL("http://?query"); + assertEquals("", url.getAuthority()); + assertEquals("", url.getPath()); + assertEquals("query", url.getQuery()); + } + + public void testEmptyAuthorityWithFragment() throws Exception { + URL url = new URL("http://#fragment"); + assertEquals("", url.getAuthority()); + assertEquals("", url.getPath()); + assertEquals("fragment", url.getRef()); + } + + public void testCombiningConstructorsMakeRelativePathsAbsolute() throws Exception { + assertEquals("/relative", new URL("http", "host", "relative").getPath()); + assertEquals("/relative", new URL("http", "host", -1, "relative").getPath()); + assertEquals("/relative", new URL("http", "host", -1, "relative", null).getPath()); + } + + public void testCombiningConstructorsDoNotMakeEmptyPathsAbsolute() throws Exception { + assertEquals("", new URL("http", "host", "").getPath()); + assertEquals("", new URL("http", "host", -1, "").getPath()); + assertEquals("", new URL("http", "host", -1, "", null).getPath()); + } + // Adding a new test? Consider adding an equivalent test to URITest.java } |