Headers.java revision 54b6cfa9a9e5b861a9930af873580d6dc20f773c
1/* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.net.http; 18 19import android.util.Config; 20import android.util.Log; 21 22import java.util.ArrayList; 23 24import org.apache.http.HeaderElement; 25import org.apache.http.entity.ContentLengthStrategy; 26import org.apache.http.message.BasicHeaderValueParser; 27import org.apache.http.message.ParserCursor; 28import org.apache.http.protocol.HTTP; 29import org.apache.http.util.CharArrayBuffer; 30 31/** 32 * Manages received headers 33 * 34 * {@hide} 35 */ 36public final class Headers { 37 private static final String LOGTAG = "Http"; 38 39 // header parsing constant 40 /** 41 * indicate HTTP 1.0 connection close after the response 42 */ 43 public final static int CONN_CLOSE = 1; 44 /** 45 * indicate HTTP 1.1 connection keep alive 46 */ 47 public final static int CONN_KEEP_ALIVE = 2; 48 49 // initial values. 50 public final static int NO_CONN_TYPE = 0; 51 public final static long NO_TRANSFER_ENCODING = 0; 52 public final static long NO_CONTENT_LENGTH = -1; 53 54 // header string 55 public final static String TRANSFER_ENCODING = "transfer-encoding"; 56 public final static String CONTENT_LEN = "content-length"; 57 public final static String CONTENT_TYPE = "content-type"; 58 public final static String CONTENT_ENCODING = "content-encoding"; 59 public final static String CONN_DIRECTIVE = "connection"; 60 61 public final static String LOCATION = "location"; 62 public final static String PROXY_CONNECTION = "proxy-connection"; 63 64 public final static String WWW_AUTHENTICATE = "www-authenticate"; 65 public final static String PROXY_AUTHENTICATE = "proxy-authenticate"; 66 public final static String CONTENT_DISPOSITION = "content-disposition"; 67 public final static String ACCEPT_RANGES = "accept-ranges"; 68 public final static String EXPIRES = "expires"; 69 public final static String CACHE_CONTROL = "cache-control"; 70 public final static String LAST_MODIFIED = "last-modified"; 71 public final static String ETAG = "etag"; 72 public final static String SET_COOKIE = "set-cookie"; 73 public final static String PRAGMA = "pragma"; 74 public final static String REFRESH = "refresh"; 75 76 // following hash are generated by String.hashCode() 77 private final static int HASH_TRANSFER_ENCODING = 1274458357; 78 private final static int HASH_CONTENT_LEN = -1132779846; 79 private final static int HASH_CONTENT_TYPE = 785670158; 80 private final static int HASH_CONTENT_ENCODING = 2095084583; 81 private final static int HASH_CONN_DIRECTIVE = -775651618; 82 private final static int HASH_LOCATION = 1901043637; 83 private final static int HASH_PROXY_CONNECTION = 285929373; 84 private final static int HASH_WWW_AUTHENTICATE = -243037365; 85 private final static int HASH_PROXY_AUTHENTICATE = -301767724; 86 private final static int HASH_CONTENT_DISPOSITION = -1267267485; 87 private final static int HASH_ACCEPT_RANGES = 1397189435; 88 private final static int HASH_EXPIRES = -1309235404; 89 private final static int HASH_CACHE_CONTROL = -208775662; 90 private final static int HASH_LAST_MODIFIED = 150043680; 91 private final static int HASH_ETAG = 3123477; 92 private final static int HASH_SET_COOKIE = 1237214767; 93 private final static int HASH_PRAGMA = -980228804; 94 private final static int HASH_REFRESH = 1085444827; 95 96 private long transferEncoding; 97 private long contentLength; // Content length of the incoming data 98 private int connectionType; 99 100 private String contentType; 101 private String contentEncoding; 102 private String location; 103 private String wwwAuthenticate; 104 private String proxyAuthenticate; 105 private String contentDisposition; 106 private String acceptRanges; 107 private String expires; 108 private String cacheControl; 109 private String lastModified; 110 private String etag; 111 private String pragma; 112 private String refresh; 113 private ArrayList<String> cookies = new ArrayList<String>(2); 114 115 public Headers() { 116 transferEncoding = NO_TRANSFER_ENCODING; 117 contentLength = NO_CONTENT_LENGTH; 118 connectionType = NO_CONN_TYPE; 119 } 120 121 public void parseHeader(CharArrayBuffer buffer) { 122 int pos = CharArrayBuffers.setLowercaseIndexOf(buffer, ':'); 123 if (pos == -1) { 124 return; 125 } 126 String name = buffer.substringTrimmed(0, pos); 127 if (name.length() == 0) { 128 return; 129 } 130 pos++; 131 132 if (HttpLog.LOGV) { 133 String val = buffer.substringTrimmed(pos, buffer.length()); 134 HttpLog.v("hdr " + buffer.length() + " " + buffer); 135 } 136 137 switch (name.hashCode()) { 138 case HASH_TRANSFER_ENCODING: 139 if (name.equals(TRANSFER_ENCODING)) { 140 // headers.transferEncoding = 141 HeaderElement[] encodings = BasicHeaderValueParser.DEFAULT 142 .parseElements(buffer, new ParserCursor(pos, 143 buffer.length())); 144 // The chunked encoding must be the last one applied RFC2616, 145 // 14.41 146 int len = encodings.length; 147 if (HTTP.IDENTITY_CODING.equalsIgnoreCase(buffer 148 .substringTrimmed(pos, buffer.length()))) { 149 transferEncoding = ContentLengthStrategy.IDENTITY; 150 } else if ((len > 0) 151 && (HTTP.CHUNK_CODING 152 .equalsIgnoreCase(encodings[len - 1].getName()))) { 153 transferEncoding = ContentLengthStrategy.CHUNKED; 154 } else { 155 transferEncoding = ContentLengthStrategy.IDENTITY; 156 } 157 } 158 break; 159 case HASH_CONTENT_LEN: 160 if (name.equals(CONTENT_LEN)) { 161 try { 162 contentLength = Long.parseLong(buffer.substringTrimmed(pos, 163 buffer.length())); 164 } catch (NumberFormatException e) { 165 if (Config.LOGV) { 166 Log.v(LOGTAG, "Headers.headers(): error parsing" 167 + " content length: " + buffer.toString()); 168 } 169 } 170 } 171 break; 172 case HASH_CONTENT_TYPE: 173 if (name.equals(CONTENT_TYPE)) { 174 contentType = buffer.substringTrimmed(pos, buffer.length()); 175 } 176 break; 177 case HASH_CONTENT_ENCODING: 178 if (name.equals(CONTENT_ENCODING)) { 179 contentEncoding = buffer.substringTrimmed(pos, buffer.length()); 180 } 181 break; 182 case HASH_CONN_DIRECTIVE: 183 if (name.equals(CONN_DIRECTIVE)) { 184 setConnectionType(buffer, pos); 185 } 186 break; 187 case HASH_LOCATION: 188 if (name.equals(LOCATION)) { 189 location = buffer.substringTrimmed(pos, buffer.length()); 190 } 191 break; 192 case HASH_PROXY_CONNECTION: 193 if (name.equals(PROXY_CONNECTION)) { 194 setConnectionType(buffer, pos); 195 } 196 break; 197 case HASH_WWW_AUTHENTICATE: 198 if (name.equals(WWW_AUTHENTICATE)) { 199 wwwAuthenticate = buffer.substringTrimmed(pos, buffer.length()); 200 } 201 break; 202 case HASH_PROXY_AUTHENTICATE: 203 if (name.equals(PROXY_AUTHENTICATE)) { 204 proxyAuthenticate = buffer.substringTrimmed(pos, buffer 205 .length()); 206 } 207 break; 208 case HASH_CONTENT_DISPOSITION: 209 if (name.equals(CONTENT_DISPOSITION)) { 210 contentDisposition = buffer.substringTrimmed(pos, buffer 211 .length()); 212 } 213 break; 214 case HASH_ACCEPT_RANGES: 215 if (name.equals(ACCEPT_RANGES)) { 216 acceptRanges = buffer.substringTrimmed(pos, buffer.length()); 217 } 218 break; 219 case HASH_EXPIRES: 220 if (name.equals(EXPIRES)) { 221 expires = buffer.substringTrimmed(pos, buffer.length()); 222 } 223 break; 224 case HASH_CACHE_CONTROL: 225 if (name.equals(CACHE_CONTROL)) { 226 cacheControl = buffer.substringTrimmed(pos, buffer.length()); 227 } 228 break; 229 case HASH_LAST_MODIFIED: 230 if (name.equals(LAST_MODIFIED)) { 231 lastModified = buffer.substringTrimmed(pos, buffer.length()); 232 } 233 break; 234 case HASH_ETAG: 235 if (name.equals(ETAG)) { 236 etag = buffer.substringTrimmed(pos, buffer.length()); 237 } 238 break; 239 case HASH_SET_COOKIE: 240 if (name.equals(SET_COOKIE)) { 241 cookies.add(buffer.substringTrimmed(pos, buffer.length())); 242 } 243 break; 244 case HASH_PRAGMA: 245 if (name.equals(PRAGMA)) { 246 pragma = buffer.substringTrimmed(pos, buffer.length()); 247 } 248 break; 249 case HASH_REFRESH: 250 if (name.equals(REFRESH)) { 251 refresh = buffer.substringTrimmed(pos, buffer.length()); 252 } 253 break; 254 default: 255 // ignore 256 } 257 } 258 259 public long getTransferEncoding() { 260 return transferEncoding; 261 } 262 263 public long getContentLength() { 264 return contentLength; 265 } 266 267 public int getConnectionType() { 268 return connectionType; 269 } 270 271 private void setConnectionType(CharArrayBuffer buffer, int pos) { 272 if (CharArrayBuffers.containsIgnoreCaseTrimmed( 273 buffer, pos, HTTP.CONN_CLOSE)) { 274 connectionType = CONN_CLOSE; 275 } else if (CharArrayBuffers.containsIgnoreCaseTrimmed( 276 buffer, pos, HTTP.CONN_KEEP_ALIVE)) { 277 connectionType = CONN_KEEP_ALIVE; 278 } 279 } 280 281 public String getContentType() { 282 return this.contentType; 283 } 284 285 public String getContentEncoding() { 286 return this.contentEncoding; 287 } 288 289 public String getLocation() { 290 return this.location; 291 } 292 293 public String getWwwAuthenticate() { 294 return this.wwwAuthenticate; 295 } 296 297 public String getProxyAuthenticate() { 298 return this.proxyAuthenticate; 299 } 300 301 public String getContentDisposition() { 302 return this.contentDisposition; 303 } 304 305 public String getAcceptRanges() { 306 return this.acceptRanges; 307 } 308 309 public String getExpires() { 310 return this.expires; 311 } 312 313 public String getCacheControl() { 314 return this.cacheControl; 315 } 316 317 public String getLastModified() { 318 return this.lastModified; 319 } 320 321 public String getEtag() { 322 return this.etag; 323 } 324 325 public ArrayList<String> getSetCookie() { 326 return this.cookies; 327 } 328 329 public String getPragma() { 330 return this.pragma; 331 } 332 333 public String getRefresh() { 334 return this.refresh; 335 } 336 337 public void setContentLength(long value) { 338 this.contentLength = value; 339 } 340 341 public void setContentType(String value) { 342 this.contentType = value; 343 } 344 345 public void setContentEncoding(String value) { 346 this.contentEncoding = value; 347 } 348 349 public void setLocation(String value) { 350 this.location = value; 351 } 352 353 public void setWwwAuthenticate(String value) { 354 this.wwwAuthenticate = value; 355 } 356 357 public void setProxyAuthenticate(String value) { 358 this.proxyAuthenticate = value; 359 } 360 361 public void setContentDisposition(String value) { 362 this.contentDisposition = value; 363 } 364 365 public void setAcceptRanges(String value) { 366 this.acceptRanges = value; 367 } 368 369 public void setExpires(String value) { 370 this.expires = value; 371 } 372 373 public void setCacheControl(String value) { 374 this.cacheControl = value; 375 } 376 377 public void setLastModified(String value) { 378 this.lastModified = value; 379 } 380 381 public void setEtag(String value) { 382 this.etag = value; 383 } 384} 385