summaryrefslogtreecommitdiffstats
path: root/luni/src
diff options
context:
space:
mode:
authorNarayan Kamath <narayan@google.com>2014-05-08 15:56:31 +0100
committerNarayan Kamath <narayan@google.com>2014-05-09 10:53:56 +0100
commitd94e746976d2906b89197448db15e4a0e355d98a (patch)
treef4daebb530f894c48c4e70ea3aaa8732a900d5de /luni/src
parentf560c538e8cb2750502c7337cae86c536e44ca8d (diff)
downloadlibcore-d94e746976d2906b89197448db15e4a0e355d98a.zip
libcore-d94e746976d2906b89197448db15e4a0e355d98a.tar.gz
libcore-d94e746976d2906b89197448db15e4a0e355d98a.tar.bz2
Fix various errors in FileURLConnectionTest.
- First, the test was broken pretty badly. It would pass a Jar style URL to a FileURLConnection and expect it to work, this is out of spec and seems wrong in general (file:///foo.apk!resources/foo.txt). - The RI supports various "headers" on file URL connections (sigh). As if the getHeaderField(int) and getHeaderFieldKey(int) APIs weren't bad enough. This has now been implemented with a naive implementation. - Fixes FileURLConnection to populate a header map for information it provides (content length, content type etc.) bug: 11664881 Change-Id: I7a3e9aaa79bf125abbcfe8367574115ce54718e3
Diffstat (limited to 'luni/src')
-rw-r--r--luni/src/main/java/libcore/net/url/FileURLConnection.java146
1 files changed, 134 insertions, 12 deletions
diff --git a/luni/src/main/java/libcore/net/url/FileURLConnection.java b/luni/src/main/java/libcore/net/url/FileURLConnection.java
index f8d7926..94fe1d6 100644
--- a/luni/src/main/java/libcore/net/url/FileURLConnection.java
+++ b/luni/src/main/java/libcore/net/url/FileURLConnection.java
@@ -28,6 +28,11 @@ import java.io.InputStream;
import java.io.PrintStream;
import java.net.URL;
import java.net.URLConnection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
import libcore.net.UriCodec;
/**
@@ -38,17 +43,45 @@ import libcore.net.UriCodec;
*/
public class FileURLConnection extends URLConnection {
+ private static final Comparator<String> HEADER_COMPARATOR = new Comparator<String>() {
+ @Override
+ public int compare(String a, String b) {
+ if (a == b) {
+ return 0;
+ } else if (a == null) {
+ return -1;
+ } else if (b == null) {
+ return 1;
+ } else {
+ return String.CASE_INSENSITIVE_ORDER.compare(a, b);
+ }
+ }
+ };
+
private String filename;
private InputStream is;
private long length = -1;
+ private long lastModified = -1;
+
private boolean isDir;
private FilePermission permission;
/**
+ * A set of three key value pairs representing the headers we support.
+ */
+ private final String[] headerKeysAndValues;
+
+ private static final int CONTENT_TYPE_VALUE_IDX = 1;
+ private static final int CONTENT_LENGTH_VALUE_IDX = 3;
+ private static final int LAST_MODIFIED_VALUE_IDX = 5;
+
+ private Map<String, List<String>> headerFields;
+
+ /**
* Creates an instance of <code>FileURLConnection</code> for establishing
* a connection to the file pointed by this <code>URL<code>
*
@@ -61,6 +94,10 @@ public class FileURLConnection extends URLConnection {
filename = "";
}
filename = UriCodec.decode(filename);
+ headerKeysAndValues = new String[] {
+ "content-type", null,
+ "content-length", null,
+ "last-modified", null };
}
/**
@@ -74,15 +111,105 @@ public class FileURLConnection extends URLConnection {
@Override
public void connect() throws IOException {
File f = new File(filename);
+ IOException error = null;
if (f.isDirectory()) {
isDir = true;
is = getDirectoryListing(f);
// use -1 for the contentLength
+ lastModified = f.lastModified();
+ headerKeysAndValues[CONTENT_TYPE_VALUE_IDX] = "text/html";
} else {
- is = new BufferedInputStream(new FileInputStream(f));
- length = f.length();
+ try {
+ is = new BufferedInputStream(new FileInputStream(f));
+ } catch (IOException ioe) {
+ error = ioe;
+ }
+
+ if (error == null) {
+ length = f.length();
+ lastModified = f.lastModified();
+ headerKeysAndValues[CONTENT_TYPE_VALUE_IDX] = getContentTypeForPlainFiles();
+ } else {
+ headerKeysAndValues[CONTENT_TYPE_VALUE_IDX] = "content/unknown";
+ }
}
+
+ headerKeysAndValues[CONTENT_LENGTH_VALUE_IDX] = String.valueOf(length);
+ headerKeysAndValues[LAST_MODIFIED_VALUE_IDX] = String.valueOf(lastModified);
+
connected = true;
+ if (error != null) {
+ throw error;
+ }
+ }
+
+ @Override
+ public String getHeaderField(String key) {
+ if (!connected) {
+ try {
+ connect();
+ } catch (IOException ioe) {
+ return null;
+ }
+ }
+
+ for (int i = 0; i < headerKeysAndValues.length; i += 2) {
+ if (headerKeysAndValues[i].equalsIgnoreCase(key)) {
+ return headerKeysAndValues[i + 1];
+ }
+ }
+
+ return null;
+ }
+
+ @Override
+ public String getHeaderFieldKey(int position) {
+ if (!connected) {
+ try {
+ connect();
+ } catch (IOException ioe) {
+ return null;
+ }
+ }
+
+ if (position < 0 || position > headerKeysAndValues.length / 2) {
+ return null;
+ }
+
+ return headerKeysAndValues[position * 2];
+ }
+
+ @Override
+ public String getHeaderField(int position) {
+ if (!connected) {
+ try {
+ connect();
+ } catch (IOException ioe) {
+ return null;
+ }
+ }
+
+ if (position < 0 || position > headerKeysAndValues.length / 2) {
+ return null;
+ }
+
+ return headerKeysAndValues[(position * 2) + 1];
+ }
+
+ @Override
+ public Map<String, List<String>> getHeaderFields() {
+ if (headerFields == null) {
+ final TreeMap<String, List<String>> headerFieldsMap = new TreeMap<>(HEADER_COMPARATOR);
+
+ for (int i = 0; i < headerKeysAndValues.length; i+=2) {
+ headerFieldsMap.put(headerKeysAndValues[i],
+ Collections.singletonList(headerKeysAndValues[i + 1]));
+ }
+
+ headerFields = Collections.unmodifiableMap(headerFieldsMap);
+ }
+
+ return headerFields;
}
/**
@@ -123,16 +250,11 @@ public class FileURLConnection extends URLConnection {
*/
@Override
public String getContentType() {
- try {
- if (!connected) {
- connect();
- }
- } catch (IOException e) {
- return "content/unknown";
- }
- if (isDir) {
- return "text/plain";
- }
+ // The content-type header field is always at position 0.
+ return getHeaderField(0);
+ }
+
+ private String getContentTypeForPlainFiles() {
String result = guessContentTypeFromName(url.getFile());
if (result != null) {
return result;