Merge "Return HTTP headers even if there is no HTTP response body."
diff --git a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnectionImpl.java b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnectionImpl.java
index 06eb28f..b31f11d 100644
--- a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnectionImpl.java
+++ b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnectionImpl.java
@@ -210,7 +210,7 @@
this.proxy = proxy;
}
- @Override public void connect() throws IOException {
+ @Override public final void connect() throws IOException {
if (connected) {
return;
}
@@ -225,7 +225,7 @@
* <p>Request parameters may not be changed after this method has been
* called.
*/
- public void makeConnection() throws IOException {
+ protected void makeConnection() throws IOException {
connected = true;
if (connection != null || responseBodyIn != null) {
@@ -358,14 +358,14 @@
/**
* Close the socket connection to the remote origin server or proxy.
*/
- @Override public void disconnect() {
+ @Override public final void disconnect() {
releaseSocket(false);
}
/**
* Releases this connection so that it may be either reused or closed.
*/
- protected synchronized void releaseSocket(boolean reuseSocket) {
+ protected final void releaseSocket(boolean reuseSocket) {
// we cannot recycle sockets that have incomplete output.
if (requestBodyOut != null && !requestBodyOut.closed) {
reuseSocket = false;
@@ -406,7 +406,7 @@
* Discard all state initialized from the HTTP response including response
* code, message, headers and body.
*/
- protected void discardIntermediateResponse() throws IOException {
+ protected final void discardIntermediateResponse() throws IOException {
boolean oldIntermediateResponse = intermediateResponse;
intermediateResponse = true;
try {
@@ -441,7 +441,7 @@
* @return InputStream the error input stream returned by the server.
*/
@Override
- public InputStream getErrorStream() {
+ public final InputStream getErrorStream() {
if (connected && method != HEAD && responseCode >= HTTP_BAD_REQUEST) {
return responseBodyIn;
}
@@ -453,9 +453,9 @@
* are fewer than {@code position} headers.
*/
@Override
- public String getHeaderField(int position) {
+ public final String getHeaderField(int position) {
try {
- getInputStream();
+ retrieveResponse();
} catch (IOException ignored) {
}
return responseHeader != null ? responseHeader.getValue(position) : null;
@@ -476,9 +476,9 @@
* @see #getHeaderFieldKey
*/
@Override
- public String getHeaderField(String key) {
+ public final String getHeaderField(String key) {
try {
- getInputStream();
+ retrieveResponse();
} catch (IOException ignored) {
}
if (responseHeader == null) {
@@ -488,16 +488,16 @@
}
@Override
- public String getHeaderFieldKey(int position) {
+ public final String getHeaderFieldKey(int position) {
try {
- getInputStream();
+ retrieveResponse();
} catch (IOException ignored) {
}
return responseHeader != null ? responseHeader.getKey(position) : null;
}
@Override
- public Map<String, List<String>> getHeaderFields() {
+ public final Map<String, List<String>> getHeaderFields() {
try {
retrieveResponse();
} catch (IOException ignored) {
@@ -506,7 +506,7 @@
}
@Override
- public Map<String, List<String>> getRequestProperties() {
+ public final Map<String, List<String>> getRequestProperties() {
if (connected) {
throw new IllegalStateException(
"Cannot access request header fields after connection is set");
@@ -515,7 +515,7 @@
}
@Override
- public InputStream getInputStream() throws IOException {
+ public final InputStream getInputStream() throws IOException {
if (!doInput) {
throw new ProtocolException("This protocol does not support input");
}
@@ -580,7 +580,7 @@
}
@Override
- public OutputStream getOutputStream() throws IOException {
+ public final OutputStream getOutputStream() throws IOException {
if (!doOutput) {
throw new ProtocolException("Does not support output");
}
@@ -648,13 +648,13 @@
}
@Override
- public Permission getPermission() throws IOException {
+ public final Permission getPermission() throws IOException {
String connectToAddress = getConnectToHost() + ":" + getConnectToPort();
return new SocketPermission(connectToAddress, "connect, resolve");
}
@Override
- public String getRequestProperty(String field) {
+ public final String getRequestProperty(String field) {
if (field == null) {
return null;
}
@@ -732,7 +732,7 @@
}
@Override
- public int getResponseCode() throws IOException {
+ public final int getResponseCode() throws IOException {
retrieveResponse();
return responseCode;
}
@@ -940,7 +940,7 @@
* if already connected.
*/
@Override
- public void setIfModifiedSince(long newValue) {
+ public final void setIfModifiedSince(long newValue) {
super.setIfModifiedSince(newValue);
// convert from millisecond since epoch to date string
SimpleDateFormat sdf = new SimpleDateFormat("E, dd MMM yyyy HH:mm:ss 'GMT'", Locale.US);
@@ -950,7 +950,7 @@
}
@Override
- public void setRequestProperty(String field, String newValue) {
+ public final void setRequestProperty(String field, String newValue) {
if (connected) {
throw new IllegalStateException("Cannot set request property after connection is made");
}
@@ -961,7 +961,7 @@
}
@Override
- public void addRequestProperty(String field, String value) {
+ public final void addRequestProperty(String field, String value) {
if (connected) {
throw new IllegalStateException("Cannot set request property after connection is made");
}
diff --git a/luni/src/test/java/libcore/java/net/URLConnectionTest.java b/luni/src/test/java/libcore/java/net/URLConnectionTest.java
index 016f9ba..6fabc74 100644
--- a/luni/src/test/java/libcore/java/net/URLConnectionTest.java
+++ b/luni/src/test/java/libcore/java/net/URLConnectionTest.java
@@ -29,6 +29,7 @@
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.PasswordAuthentication;
+import java.net.ProtocolException;
import java.net.Proxy;
import java.net.ResponseCache;
import java.net.SecureCacheResponse;
@@ -49,6 +50,7 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
@@ -424,6 +426,67 @@
server.shutdown(); // tearDown() isn't sufficient; this test starts multiple servers
}
+ /**
+ * Test that we can interrogate the response when the cache is being
+ * populated. http://code.google.com/p/android/issues/detail?id=7787
+ */
+ public void testResponseCacheCallbackApis() throws Exception {
+ final String body = "ABCDE";
+ final AtomicInteger cacheCount = new AtomicInteger();
+
+ server.enqueue(new MockResponse()
+ .setStatus("HTTP/1.1 200 Fantastic")
+ .addHeader("fgh: ijk")
+ .setBody(body));
+ server.play();
+
+ ResponseCache.setDefault(new ResponseCache() {
+ @Override public CacheResponse get(URI uri, String requestMethod,
+ Map<String, List<String>> requestHeaders) throws IOException {
+ return null;
+ }
+ @Override public CacheRequest put(URI uri, URLConnection conn) throws IOException {
+ HttpURLConnection httpConnection = (HttpURLConnection) conn;
+ assertEquals("HTTP/1.1 200 Fantastic", httpConnection.getHeaderField(null));
+ assertEquals(Arrays.asList("HTP/1.1 200 Fantastic"),
+ httpConnection.getHeaderFields().get(null));
+ assertEquals(200, httpConnection.getResponseCode());
+ assertEquals("Fantastic", httpConnection.getResponseMessage());
+ assertEquals(body.length(), httpConnection.getContentLength());
+ assertEquals("ijk", httpConnection.getHeaderField("fgh"));
+ try {
+ httpConnection.getInputStream(); // the RI doesn't forbid this, but it should
+ fail();
+ } catch (IOException expected) {
+ }
+ cacheCount.incrementAndGet();
+ return null;
+ }
+ });
+
+ URL url = server.getUrl("/");
+ HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+ assertEquals(body, readAscii(connection.getInputStream(), Integer.MAX_VALUE));
+ assertEquals(1, cacheCount.get());
+ }
+
+ public void testGetResponseCodeNoResponseBody() throws Exception {
+ server.enqueue(new MockResponse()
+ .addHeader("abc: def"));
+ server.play();
+
+ URL url = server.getUrl("/");
+ HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+ conn.setDoInput(false);
+ assertEquals("def", conn.getHeaderField("abc"));
+ assertEquals(200, conn.getResponseCode());
+ try {
+ conn.getInputStream();
+ fail();
+ } catch (ProtocolException expected) {
+ }
+ }
+
public void testConnectViaHttps() throws IOException, InterruptedException {
TestSSLContext testSSLContext = TestSSLContext.create();