summaryrefslogtreecommitdiffstats
path: root/luni
diff options
context:
space:
mode:
authorJesse Wilson <jessewilson@google.com>2011-05-26 19:33:57 -0700
committerJesse Wilson <jessewilson@google.com>2011-05-27 09:35:55 -0700
commitc68609e723a5daa20888abdb640799d4353fd590 (patch)
tree9b08f4f4c8d43af80da216a05223a24ff8c9fed0 /luni
parent73d0c8232b23ad74af5cc198143603ff6ee5236b (diff)
downloadlibcore-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.java434
-rw-r--r--luni/src/main/java/java/net/URL.java16
-rw-r--r--luni/src/test/java/libcore/java/net/URITest.java81
-rw-r--r--luni/src/test/java/libcore/java/net/URLTest.java64
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
}