package org.simpleframework.common; import java.util.HashMap; import java.util.Map; import junit.framework.TestCase; /** * Test for fast case insensitive mapping for headers that have been taken * from the request HTTP header or added to the response HTTP header. * * @author Niall Gallagher */ public class KeyTest extends TestCase { public class Index implements Name { private final String value; public Index(String value) { this.value = value.toLowerCase(); } public int hashCode() { return value.hashCode(); } public boolean equals(Object key) { if(key instanceof Name) { return key.equals(value); } if(key instanceof String) { return key.equals(value); } return false; } } public interface Name { public int hashCode(); public boolean equals(Object value); } public class ArrayName implements Name { private String cache; private byte[] array; private int off; private int size; private int hash; public ArrayName(byte[] array) { this(array, 0, array.length); } public ArrayName(byte[] array, int off, int size) { this.array = array; this.size = size; this.off = off; } public boolean equals(Object value) { if(value instanceof String) { String text = value.toString(); return equals(text); } return false; } public boolean equals(String value) { int length = value.length(); if(length != size) { return false; } for(int i = 0; i < size; i++) { int left = value.charAt(i); int right = array[off + i]; if(right >= 'A' && right <= 'Z') { right = (right - 'A') + 'a'; } if(left != right) { return false; } } return true; } public int hashCode() { int code = hash; if(code == 0) { int pos = off; for(int i = 0; i < size; i++) { int next = array[pos++]; if(next >= 'A' && next <= 'Z') { next = (next - 'A') + 'a'; } code = 31*code + next; } hash = code; } return code; } } public class StringName implements Name { private final String value; private final String key; public StringName(String value) { this.key = value.toLowerCase(); this.value = value; } public int hashCode() { return key.hashCode(); } public boolean equals(Object value) { return value.equals(key); } } public class NameTable { private final Map map; public NameTable() { this.map = new HashMap(); } public void put(Name key, T value) { map.put(key, value); } public void put(String text, T value) { Name key = new StringName(text); map.put(key, value); } public T get(String key) { Index index = new Index(key); return map.get(index); } public T remove(String key) { Index index = new Index(key); return map.remove(index); } } public void testName() { Name contentLength = new ArrayName("Content-Length".getBytes()); Name contentType = new ArrayName("Content-Type".getBytes()); Name transferEncoding = new ArrayName("Transfer-Encoding".getBytes()); Name userAgent = new ArrayName("User-Agent".getBytes()); NameTable map = new NameTable(); assertEquals(contentLength.hashCode(), "Content-Length".toLowerCase().hashCode()); assertEquals(contentType.hashCode(), "Content-Type".toLowerCase().hashCode()); assertEquals(transferEncoding.hashCode(), "Transfer-Encoding".toLowerCase().hashCode()); assertEquals(userAgent.hashCode(), "User-Agent".toLowerCase().hashCode()); map.put(contentLength, "1024"); map.put(contentType, "text/html"); map.put(transferEncoding, "chunked"); map.put(userAgent, "Mozilla/4.0"); map.put("Date", "18/11/1977"); map.put("Accept", "text/plain, text/html, image/gif"); assertEquals(map.get("Content-Length"), "1024"); assertEquals(map.get("CONTENT-LENGTH"), "1024"); assertEquals(map.get("content-length"), "1024"); assertEquals(map.get("Content-length"), "1024"); assertEquals(map.get("Content-Type"), "text/html"); assertEquals(map.get("Transfer-Encoding"), "chunked"); assertEquals(map.get("USER-AGENT"), "Mozilla/4.0"); assertEquals(map.get("Accept"), "text/plain, text/html, image/gif"); assertEquals(map.get("ACCEPT"), "text/plain, text/html, image/gif"); assertEquals(map.get("accept"), "text/plain, text/html, image/gif"); assertEquals(map.get("DATE"), "18/11/1977"); assertEquals(map.get("Date"), "18/11/1977"); assertEquals(map.get("date"), "18/11/1977"); } }