summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorElliott Hughes <enh@google.com>2010-02-17 15:51:36 -0800
committerAndroid (Google) Code Review <android-gerrit@google.com>2010-02-17 15:51:36 -0800
commit1d1f9244611a8ba3be65795d4ea6e84bcecdb89d (patch)
tree3ec0a17e2fcc0858b3acf4da493f1b1a8553112b
parent3129a6e024c3abc19ccfe5b784cb7d7c6509d638 (diff)
parente3f55fef357e71daa6d56e838fbba31dcebe443e (diff)
downloadlibcore-1d1f9244611a8ba3be65795d4ea6e84bcecdb89d.zip
libcore-1d1f9244611a8ba3be65795d4ea6e84bcecdb89d.tar.gz
libcore-1d1f9244611a8ba3be65795d4ea6e84bcecdb89d.tar.bz2
Merge "HTTP headers should be case-insensitive but case-preserving." into dalvik-dev
-rw-r--r--luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/Header.java34
-rw-r--r--luni/src/test/java/org/apache/harmony/luni/internal/net/www/protocol/http/HeaderTest.java41
2 files changed, 53 insertions, 22 deletions
diff --git a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/Header.java b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/Header.java
index bdd1d0a..0f8dfa9 100644
--- a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/Header.java
+++ b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/Header.java
@@ -19,24 +19,23 @@ package org.apache.harmony.luni.internal.net.www.protocol.http;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.TreeMap;
/**
* The general structure for request / response header. It is essentially
* constructed by hashtable with key indexed in a vector for position lookup.
*/
public class Header implements Cloneable {
- /*
- * we use the non-synchronized ArrayList and HashMap instead of the
- * synchronized Vector and Hashtable
- */
private ArrayList<String> props;
- private HashMap<String, LinkedList<String>> keyTable;
+ // BEGIN android-changed: header fields should be case-insensitive but case-preserving.
+ // http://code.google.com/p/android/issues/detail?id=6684
+ private TreeMap<String, LinkedList<String>> keyTable;
+ // END android-changed
private String statusLine;
@@ -48,7 +47,7 @@ public class Header implements Cloneable {
public Header() {
super();
this.props = new ArrayList<String>(20);
- this.keyTable = new HashMap<String, LinkedList<String>>(20);
+ this.keyTable = new TreeMap<String, LinkedList<String>>(String.CASE_INSENSITIVE_ORDER); // android-changed
}
/**
@@ -79,11 +78,9 @@ public class Header implements Cloneable {
try {
Header clone = (Header) super.clone();
clone.props = (ArrayList<String>) props.clone();
- clone.keyTable = new HashMap<String, LinkedList<String>>(20);
- for (Map.Entry<String, LinkedList<String>> next : this.keyTable
- .entrySet()) {
- LinkedList<String> v = (LinkedList<String>) next.getValue()
- .clone();
+ clone.keyTable = new TreeMap<String, LinkedList<String>>(String.CASE_INSENSITIVE_ORDER); // android-changed
+ for (Map.Entry<String, LinkedList<String>> next : this.keyTable.entrySet()) {
+ LinkedList<String> v = (LinkedList<String>) next.getValue().clone();
clone.keyTable.put(next.getKey(), v);
}
return clone;
@@ -102,14 +99,11 @@ public class Header implements Cloneable {
if (key == null) {
throw new NullPointerException();
}
- // BEGIN android-changed
- key = key.toLowerCase();
LinkedList<String> list = keyTable.get(key);
if (list == null) {
list = new LinkedList<String>();
- keyTable.put(key, list);
+ keyTable.put(key, list); // android-changed
}
- // END android-changed
list.add(value);
props.add(key);
props.add(value);
@@ -126,9 +120,6 @@ public class Header implements Cloneable {
if (key == null) {
throw new NullPointerException();
}
- // BEGIN android-added
- key = key.toLowerCase();
- // END android-added
LinkedList<String> list = keyTable.get(key);
if (list == null) {
add(key, value);
@@ -154,8 +145,7 @@ public class Header implements Cloneable {
* @since 1.4
*/
public Map<String, List<String>> getFieldMap() {
- Map<String, List<String>> result = new HashMap<String, List<String>>(
- keyTable.size());
+ Map<String, List<String>> result = new TreeMap<String, List<String>>(String.CASE_INSENSITIVE_ORDER); // android-changed
for (Map.Entry<String, LinkedList<String>> next : keyTable.entrySet()) {
List<String> v = next.getValue();
result.put(next.getKey(), Collections.unmodifiableList(v));
@@ -203,7 +193,7 @@ public class Header implements Cloneable {
* such key exists.
*/
public String get(String key) {
- LinkedList<String> result = keyTable.get(key.toLowerCase());
+ LinkedList<String> result = keyTable.get(key); // android-changed
if (result == null) {
return null;
}
diff --git a/luni/src/test/java/org/apache/harmony/luni/internal/net/www/protocol/http/HeaderTest.java b/luni/src/test/java/org/apache/harmony/luni/internal/net/www/protocol/http/HeaderTest.java
new file mode 100644
index 0000000..7ec5fd8
--- /dev/null
+++ b/luni/src/test/java/org/apache/harmony/luni/internal/net/www/protocol/http/HeaderTest.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.luni.internal.net.www.protocol.http;
+
+import java.util.Arrays;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class HeaderTest extends junit.framework.TestCase {
+ // http://code.google.com/p/android/issues/detail?id=6684
+ public void test_caseInsensitiveButCasePreserving() {
+ Header h = new Header();
+ h.add("Content-Type", "text/plain");
+ // Case-insensitive:
+ assertEquals("text/plain", h.get("Content-Type"));
+ assertEquals("text/plain", h.get("Content-type"));
+ assertEquals("text/plain", h.get("content-type"));
+ assertEquals("text/plain", h.get("CONTENT-TYPE"));
+ // ...but case-preserving:
+ assertEquals("Content-Type", h.getFieldMap().keySet().toArray()[0]);
+
+ // We differ from the RI in that the Map we return is also case-insensitive.
+ // Our behavior seems more consistent. (And code that works on the RI will work on Android.)
+ assertEquals(Arrays.asList("text/plain"), h.getFieldMap().get("Content-Type"));
+ assertEquals(Arrays.asList("text/plain"), h.getFieldMap().get("Content-type")); // RI fails this.
+ }
+}