Don't NullPointerException when a URL contains a space.

We end up creating a URI of http://and%20roid which has no host
name part because and%20roid is not a valid host name. It's unclear
where the best place to fail is. This is consistent with the RI
which doesn't fail until it attempts to connect.

Bug: http://code.google.com/p/android/issues/detail?id=16895
Change-Id: Ifa4dc3c651f4627e27622ed5cedfa820f9a35358
diff --git a/luni/src/main/java/libcore/net/http/HttpConnection.java b/luni/src/main/java/libcore/net/http/HttpConnection.java
index 756edb8..461a309 100644
--- a/luni/src/main/java/libcore/net/http/HttpConnection.java
+++ b/luni/src/main/java/libcore/net/http/HttpConnection.java
@@ -30,6 +30,7 @@
 import java.net.SocketException;
 import java.net.SocketTimeoutException;
 import java.net.URI;
+import java.net.UnknownHostException;
 import java.util.List;
 import javax.net.ssl.HostnameVerifier;
 import javax.net.ssl.SSLSocket;
@@ -292,13 +293,16 @@
         private final String socketHost;
         private final int socketPort;
 
-        public Address(URI uri) {
+        public Address(URI uri) throws UnknownHostException {
             this.proxy = null;
             this.requiresTunnel = false;
             this.uriHost = uri.getHost();
             this.uriPort = uri.getEffectivePort();
             this.socketHost = uriHost;
             this.socketPort = uriPort;
+            if (uriHost == null) {
+                throw new UnknownHostException(uri.toString());
+            }
         }
 
         /**
@@ -307,7 +311,7 @@
          *     proxy. When doing so, we must avoid buffering bytes intended for
          *     the higher-level protocol.
          */
-        public Address(URI uri, Proxy proxy, boolean requiresTunnel) {
+        public Address(URI uri, Proxy proxy, boolean requiresTunnel) throws UnknownHostException {
             this.proxy = proxy;
             this.requiresTunnel = requiresTunnel;
             this.uriHost = uri.getHost();
@@ -321,6 +325,9 @@
             InetSocketAddress proxySocketAddress = (InetSocketAddress) proxyAddress;
             this.socketHost = proxySocketAddress.getHostName();
             this.socketPort = proxySocketAddress.getPort();
+            if (uriHost == null) {
+                throw new UnknownHostException(uri.toString());
+            }
         }
 
         public Proxy getProxy() {
diff --git a/luni/src/test/java/libcore/java/net/URITest.java b/luni/src/test/java/libcore/java/net/URITest.java
index d45facc..ea33568 100644
--- a/luni/src/test/java/libcore/java/net/URITest.java
+++ b/luni/src/test/java/libcore/java/net/URITest.java
@@ -621,5 +621,43 @@
         assertEquals(new URI(""), relative.relativize(relative));
     }
 
+    public void testPartContainsSpace() throws Exception {
+        try {
+            new URI("ht tp://host/");
+            fail();
+        } catch (URISyntaxException expected) {
+        }
+        try {
+            new URI("http://user name@host/");
+            fail();
+        } catch (URISyntaxException expected) {
+        }
+        try {
+            new URI("http://ho st/");
+            fail();
+        } catch (URISyntaxException expected) {
+        }
+        try {
+            new URI("http://host:80 80/");
+            fail();
+        } catch (URISyntaxException expected) {
+        }
+        try {
+            new URI("http://host/fi le");
+            fail();
+        } catch (URISyntaxException expected) {
+        }
+        try {
+            new URI("http://host/file?que ry");
+            fail();
+        } catch (URISyntaxException expected) {
+        }
+        try {
+            new URI("http://host/file?query#re f");
+            fail();
+        } catch (URISyntaxException expected) {
+        }
+    }
+
     // Adding a new test? Consider adding an equivalent test to URLTest.java
 }
diff --git a/luni/src/test/java/libcore/java/net/URLConnectionTest.java b/luni/src/test/java/libcore/java/net/URLConnectionTest.java
index acd3c13..4e65d4c 100644
--- a/luni/src/test/java/libcore/java/net/URLConnectionTest.java
+++ b/luni/src/test/java/libcore/java/net/URLConnectionTest.java
@@ -42,6 +42,7 @@
 import java.net.URI;
 import java.net.URL;
 import java.net.URLConnection;
+import java.net.UnknownHostException;
 import java.security.cert.CertificateException;
 import java.security.cert.X509Certificate;
 import java.util.ArrayList;
@@ -1895,6 +1896,28 @@
         assertEquals(-1, in.read());
     }
 
+    // http://code.google.com/p/android/issues/detail?id=16895
+    public void testUrlWithSpaceInHost() throws Exception {
+        URLConnection urlConnection = new URL("http://and roid.com/").openConnection();
+        try {
+            urlConnection.getInputStream();
+            fail();
+        } catch (UnknownHostException expected) {
+        }
+    }
+
+    public void testUrlWithSpaceInHostViaHttpProxy() throws Exception {
+        server.enqueue(new MockResponse());
+        server.play();
+        URLConnection urlConnection = new URL("http://and roid.com/")
+                .openConnection(server.toProxyAddress());
+        try {
+            urlConnection.getInputStream();
+            fail(); // the RI makes a bogus proxy request for "GET http://and roid.com/ HTTP/1.1"
+        } catch (UnknownHostException expected) {
+        }
+    }
+
     /**
      * Returns a gzipped copy of {@code bytes}.
      */
diff --git a/luni/src/test/java/libcore/java/net/URLTest.java b/luni/src/test/java/libcore/java/net/URLTest.java
index af5915a..3574b8f 100644
--- a/luni/src/test/java/libcore/java/net/URLTest.java
+++ b/luni/src/test/java/libcore/java/net/URLTest.java
@@ -668,5 +668,23 @@
         assertEquals("", new URL("http", "host", -1, "", null).getPath());
     }
 
+    public void testPartContainsSpace() throws Exception {
+        try {
+            new URL("ht tp://host/");
+            fail();
+        } catch (MalformedURLException expected) {
+        }
+        assertEquals("user name", new URL("http://user name@host/").getUserInfo());
+        assertEquals("ho st", new URL("http://ho st/").getHost());
+        try {
+            new URL("http://host:80 80/");
+            fail();
+        } catch (MalformedURLException expected) {
+        }
+        assertEquals("/fi le", new URL("http://host/fi le").getFile());
+        assertEquals("que ry", new URL("http://host/file?que ry").getQuery());
+        assertEquals("re f", new URL("http://host/file?query#re f").getRef());
+    }
+
     // Adding a new test? Consider adding an equivalent test to URITest.java
 }