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