View Javadoc
1   /*
2    * Copyright 2002-2015 the original author or authors.
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  
17  package com.foxinmy.weixin4j.http;
18  
19  import java.io.Serializable;
20  import java.net.URI;
21  import java.nio.charset.Charset;
22  import java.text.ParseException;
23  import java.text.SimpleDateFormat;
24  import java.util.ArrayList;
25  import java.util.Collection;
26  import java.util.Collections;
27  import java.util.Date;
28  import java.util.EnumSet;
29  import java.util.Iterator;
30  import java.util.LinkedHashMap;
31  import java.util.LinkedList;
32  import java.util.List;
33  import java.util.Locale;
34  import java.util.Map;
35  import java.util.Set;
36  import java.util.TimeZone;
37  
38  import com.foxinmy.weixin4j.util.LinkedCaseInsensitiveMap;
39  import com.foxinmy.weixin4j.util.MultiValueMap;
40  import com.foxinmy.weixin4j.util.StringUtil;
41  
42  /**
43   * Represents HTTP request and response headers, mapping string header names to
44   * list of string values.
45   *
46   * <p>
47   * In addition to the normal methods defined by {@link Map}, this class offers
48   * the following convenience methods:
49   * <ul>
50   * <li>{@link #getFirst(String)} returns the first value associated with a given
51   * header name</li>
52   * <li>{@link #add(String, String)} adds a header value to the list of values
53   * for a header name</li>
54   * <li>{@link #set(String, String)} sets the header value to a single string
55   * value</li>
56   * </ul>
57   *
58   * <p>
59   *
60   * @author Arjen Poutsma
61   * @author Sebastien Deleuze
62   * @since 3.0
63   */
64  public class HttpHeaders implements MultiValueMap<String, String>, Serializable {
65  
66  	private static final long serialVersionUID = -8578554704772377436L;
67  
68  	/**
69  	 * The HTTP {@code Accept} header field name.
70  	 * 
71  	 * @see <a href="http://tools.ietf.org/html/rfc7231#section-5.3.2">Section
72  	 *      5.3.2 of RFC 7231</a>
73  	 */
74  	public static final String ACCEPT = "Accept";
75  	/**
76  	 * The HTTP {@code Accept-Charset} header field name.
77  	 * 
78  	 * @see <a href="http://tools.ietf.org/html/rfc7231#section-5.3.3">Section
79  	 *      5.3.3 of RFC 7231</a>
80  	 */
81  	public static final String ACCEPT_CHARSET = "Accept-Charset";
82  	/**
83  	 * The HTTP {@code Accept-Encoding} header field name.
84  	 * 
85  	 * @see <a href="http://tools.ietf.org/html/rfc7231#section-5.3.4">Section
86  	 *      5.3.4 of RFC 7231</a>
87  	 */
88  	public static final String ACCEPT_ENCODING = "Accept-Encoding";
89  	/**
90  	 * The HTTP {@code Accept-Language} header field name.
91  	 * 
92  	 * @see <a href="http://tools.ietf.org/html/rfc7231#section-5.3.5">Section
93  	 *      5.3.5 of RFC 7231</a>
94  	 */
95  	public static final String ACCEPT_LANGUAGE = "Accept-Language";
96  	/**
97  	 * The HTTP {@code Accept-Ranges} header field name.
98  	 * 
99  	 * @see <a href="http://tools.ietf.org/html/rfc7233#section-2.3">Section
100 	 *      5.3.5 of RFC 7233</a>
101 	 */
102 	public static final String ACCEPT_RANGES = "Accept-Ranges";
103 	/**
104 	 * The CORS {@code Access-Control-Allow-Credentials} response header field
105 	 * name.
106 	 * 
107 	 * @see <a href="http://www.w3.org/TR/cors/">CORS W3C recommandation</a>
108 	 */
109 	public static final String ACCESS_CONTROL_ALLOW_CREDENTIALS = "Access-Control-Allow-Credentials";
110 	/**
111 	 * The CORS {@code Access-Control-Allow-Headers} response header field name.
112 	 * 
113 	 * @see <a href="http://www.w3.org/TR/cors/">CORS W3C recommandation</a>
114 	 */
115 	public static final String ACCESS_CONTROL_ALLOW_HEADERS = "Access-Control-Allow-Headers";
116 	/**
117 	 * The CORS {@code Access-Control-Allow-Methods} response header field name.
118 	 * 
119 	 * @see <a href="http://www.w3.org/TR/cors/">CORS W3C recommandation</a>
120 	 */
121 	public static final String ACCESS_CONTROL_ALLOW_METHODS = "Access-Control-Allow-Methods";
122 	/**
123 	 * The CORS {@code Access-Control-Allow-Origin} response header field name.
124 	 * 
125 	 * @see <a href="http://www.w3.org/TR/cors/">CORS W3C recommandation</a>
126 	 */
127 	public static final String ACCESS_CONTROL_ALLOW_ORIGIN = "Access-Control-Allow-Origin";
128 	/**
129 	 * The CORS {@code Access-Control-Expose-Headers} response header field
130 	 * name.
131 	 * 
132 	 * @see <a href="http://www.w3.org/TR/cors/">CORS W3C recommandation</a>
133 	 */
134 	public static final String ACCESS_CONTROL_EXPOSE_HEADERS = "Access-Control-Expose-Headers";
135 	/**
136 	 * The CORS {@code Access-Control-Max-Age} response header field name.
137 	 * 
138 	 * @see <a href="http://www.w3.org/TR/cors/">CORS W3C recommandation</a>
139 	 */
140 	public static final String ACCESS_CONTROL_MAX_AGE = "Access-Control-Max-Age";
141 	/**
142 	 * The CORS {@code Access-Control-Request-Headers} request header field
143 	 * name.
144 	 * 
145 	 * @see <a href="http://www.w3.org/TR/cors/">CORS W3C recommandation</a>
146 	 */
147 	public static final String ACCESS_CONTROL_REQUEST_HEADERS = "Access-Control-Request-Headers";
148 	/**
149 	 * The CORS {@code Access-Control-Request-Method} request header field name.
150 	 * 
151 	 * @see <a href="http://www.w3.org/TR/cors/">CORS W3C recommandation</a>
152 	 */
153 	public static final String ACCESS_CONTROL_REQUEST_METHOD = "Access-Control-Request-Method";
154 	/**
155 	 * The HTTP {@code Age} header field name.
156 	 * 
157 	 * @see <a href="http://tools.ietf.org/html/rfc7234#section-5.1">Section 5.1
158 	 *      of RFC 7234</a>
159 	 */
160 	public static final String AGE = "Age";
161 	/**
162 	 * The HTTP {@code Allow} header field name.
163 	 * 
164 	 * @see <a href="http://tools.ietf.org/html/rfc7231#section-7.4.1">Section
165 	 *      7.4.1 of RFC 7231</a>
166 	 */
167 	public static final String ALLOW = "Allow";
168 	/**
169 	 * The HTTP {@code Authorization} header field name.
170 	 * 
171 	 * @see <a href="http://tools.ietf.org/html/rfc7235#section-4.2">Section 4.2
172 	 *      of RFC 7235</a>
173 	 */
174 	public static final String AUTHORIZATION = "Authorization";
175 	/**
176 	 * The HTTP {@code Cache-Control} header field name.
177 	 * 
178 	 * @see <a href="http://tools.ietf.org/html/rfc7234#section-5.2">Section 5.2
179 	 *      of RFC 7234</a>
180 	 */
181 	public static final String CACHE_CONTROL = "Cache-Control";
182 	/**
183 	 * The HTTP {@code Connection} header field name.
184 	 * 
185 	 * @see <a href="http://tools.ietf.org/html/rfc7230#section-6.1">Section 6.1
186 	 *      of RFC 7230</a>
187 	 */
188 	public static final String CONNECTION = "Connection";
189 	/**
190 	 * The HTTP {@code Content-Encoding} header field name.
191 	 * 
192 	 * @see <a href="http://tools.ietf.org/html/rfc7231#section-3.1.2.2">Section
193 	 *      3.1.2.2 of RFC 7231</a>
194 	 */
195 	public static final String CONTENT_ENCODING = "Content-Encoding";
196 	/**
197 	 * The HTTP {@code Content-Disposition} header field name
198 	 * 
199 	 * @see <a href="http://tools.ietf.org/html/rfc6266">RFC 6266</a>
200 	 */
201 	public static final String CONTENT_DISPOSITION = "Content-Disposition";
202 	/**
203 	 * The HTTP {@code Content-Language} header field name.
204 	 * 
205 	 * @see <a href="http://tools.ietf.org/html/rfc7231#section-3.1.3.2">Section
206 	 *      3.1.3.2 of RFC 7231</a>
207 	 */
208 	public static final String CONTENT_LANGUAGE = "Content-Language";
209 	/**
210 	 * The HTTP {@code Content-Length} header field name.
211 	 * 
212 	 * @see <a href="http://tools.ietf.org/html/rfc7230#section-3.3.2">Section
213 	 *      3.3.2 of RFC 7230</a>
214 	 */
215 	public static final String CONTENT_LENGTH = "Content-Length";
216 	/**
217 	 * The HTTP {@code Content-Location} header field name.
218 	 * 
219 	 * @see <a href="http://tools.ietf.org/html/rfc7231#section-3.1.4.2">Section
220 	 *      3.1.4.2 of RFC 7231</a>
221 	 */
222 	public static final String CONTENT_LOCATION = "Content-Location";
223 	/**
224 	 * The HTTP {@code Content-Range} header field name.
225 	 * 
226 	 * @see <a href="http://tools.ietf.org/html/rfc7233#section-4.2">Section 4.2
227 	 *      of RFC 7233</a>
228 	 */
229 	public static final String CONTENT_RANGE = "Content-Range";
230 	/**
231 	 * The HTTP {@code Content-Type} header field name.
232 	 * 
233 	 * @see <a href="http://tools.ietf.org/html/rfc7231#section-3.1.1.5">Section
234 	 *      3.1.1.5 of RFC 7231</a>
235 	 */
236 	public static final String CONTENT_TYPE = "Content-Type";
237 	/**
238 	 * The HTTP {@code Cookie} header field name.
239 	 * 
240 	 * @see <a href="http://tools.ietf.org/html/rfc2109#section-4.3.4">Section
241 	 *      4.3.4 of RFC 2109</a>
242 	 */
243 	public static final String COOKIE = "Cookie";
244 	/**
245 	 * The HTTP {@code Date} header field name.
246 	 * 
247 	 * @see <a href="http://tools.ietf.org/html/rfc7231#section-7.1.1.2">Section
248 	 *      7.1.1.2 of RFC 7231</a>
249 	 */
250 	public static final String DATE = "Date";
251 	/**
252 	 * The HTTP {@code ETag} header field name.
253 	 * 
254 	 * @see <a href="http://tools.ietf.org/html/rfc7232#section-2.3">Section 2.3
255 	 *      of RFC 7232</a>
256 	 */
257 	public static final String ETAG = "ETag";
258 	/**
259 	 * The HTTP {@code Expect} header field name.
260 	 * 
261 	 * @see <a href="http://tools.ietf.org/html/rfc7231#section-5.1.1">Section
262 	 *      5.1.1 of RFC 7231</a>
263 	 */
264 	public static final String EXPECT = "Expect";
265 	/**
266 	 * The HTTP {@code Expires} header field name.
267 	 * 
268 	 * @see <a href="http://tools.ietf.org/html/rfc7234#section-5.3">Section 5.3
269 	 *      of RFC 7234</a>
270 	 */
271 	public static final String EXPIRES = "Expires";
272 	/**
273 	 * The HTTP {@code From} header field name.
274 	 * 
275 	 * @see <a href="http://tools.ietf.org/html/rfc7231#section-5.5.1">Section
276 	 *      5.5.1 of RFC 7231</a>
277 	 */
278 	public static final String FROM = "From";
279 	/**
280 	 * The HTTP {@code Host} header field name.
281 	 * 
282 	 * @see <a href="http://tools.ietf.org/html/rfc7230#section-5.4">Section 5.4
283 	 *      of RFC 7230</a>
284 	 */
285 	public static final String HOST = "Host";
286 	/**
287 	 * The HTTP {@code If-Match} header field name.
288 	 * 
289 	 * @see <a href="http://tools.ietf.org/html/rfc7232#section-3.1">Section 3.1
290 	 *      of RFC 7232</a>
291 	 */
292 	public static final String IF_MATCH = "If-Match";
293 	/**
294 	 * The HTTP {@code If-Modified-Since} header field name.
295 	 * 
296 	 * @see <a href="http://tools.ietf.org/html/rfc7232#section-3.3">Section 3.3
297 	 *      of RFC 7232</a>
298 	 */
299 	public static final String IF_MODIFIED_SINCE = "If-Modified-Since";
300 	/**
301 	 * The HTTP {@code If-None-Match} header field name.
302 	 * 
303 	 * @see <a href="http://tools.ietf.org/html/rfc7232#section-3.2">Section 3.2
304 	 *      of RFC 7232</a>
305 	 */
306 	public static final String IF_NONE_MATCH = "If-None-Match";
307 	/**
308 	 * The HTTP {@code If-Range} header field name.
309 	 * 
310 	 * @see <a href="http://tools.ietf.org/html/rfc7233#section-3.2">Section 3.2
311 	 *      of RFC 7233</a>
312 	 */
313 	public static final String IF_RANGE = "If-Range";
314 	/**
315 	 * The HTTP {@code If-Unmodified-Since} header field name.
316 	 * 
317 	 * @see <a href="http://tools.ietf.org/html/rfc7232#section-3.4">Section 3.4
318 	 *      of RFC 7232</a>
319 	 */
320 	public static final String IF_UNMODIFIED_SINCE = "If-Unmodified-Since";
321 	/**
322 	 * The HTTP {@code Last-Modified} header field name.
323 	 * 
324 	 * @see <a href="http://tools.ietf.org/html/rfc7232#section-2.2">Section 2.2
325 	 *      of RFC 7232</a>
326 	 */
327 	public static final String LAST_MODIFIED = "Last-Modified";
328 	/**
329 	 * The HTTP {@code Link} header field name.
330 	 * 
331 	 * @see <a href="http://tools.ietf.org/html/rfc5988">RFC 5988</a>
332 	 */
333 	public static final String LINK = "Link";
334 	/**
335 	 * The HTTP {@code Location} header field name.
336 	 * 
337 	 * @see <a href="http://tools.ietf.org/html/rfc7231#section-7.1.2">Section
338 	 *      7.1.2 of RFC 7231</a>
339 	 */
340 	public static final String LOCATION = "Location";
341 	/**
342 	 * The HTTP {@code Max-Forwards} header field name.
343 	 * 
344 	 * @see <a href="http://tools.ietf.org/html/rfc7231#section-5.1.2">Section
345 	 *      5.1.2 of RFC 7231</a>
346 	 */
347 	public static final String MAX_FORWARDS = "Max-Forwards";
348 	/**
349 	 * The HTTP {@code Origin} header field name.
350 	 * 
351 	 * @see <a href="http://tools.ietf.org/html/rfc6454">RFC 6454</a>
352 	 */
353 	public static final String ORIGIN = "Origin";
354 	/**
355 	 * The HTTP {@code Pragma} header field name.
356 	 * 
357 	 * @see <a href="http://tools.ietf.org/html/rfc7234#section-5.4">Section 5.4
358 	 *      of RFC 7234</a>
359 	 */
360 	public static final String PRAGMA = "Pragma";
361 	/**
362 	 * The HTTP {@code Proxy-Authenticate} header field name.
363 	 * 
364 	 * @see <a href="http://tools.ietf.org/html/rfc7235#section-4.3">Section 4.3
365 	 *      of RFC 7235</a>
366 	 */
367 	public static final String PROXY_AUTHENTICATE = "Proxy-Authenticate";
368 	/**
369 	 * The HTTP {@code Proxy-Authorization} header field name.
370 	 * 
371 	 * @see <a href="http://tools.ietf.org/html/rfc7235#section-4.4">Section 4.4
372 	 *      of RFC 7235</a>
373 	 */
374 	public static final String PROXY_AUTHORIZATION = "Proxy-Authorization";
375 	/**
376 	 * The HTTP {@code Range} header field name.
377 	 * 
378 	 * @see <a href="http://tools.ietf.org/html/rfc7233#section-3.1">Section 3.1
379 	 *      of RFC 7233</a>
380 	 */
381 	public static final String RANGE = "Range";
382 	/**
383 	 * The HTTP {@code Referer} header field name.
384 	 * 
385 	 * @see <a href="http://tools.ietf.org/html/rfc7231#section-5.5.2">Section
386 	 *      5.5.2 of RFC 7231</a>
387 	 */
388 	public static final String REFERER = "Referer";
389 	/**
390 	 * The HTTP {@code Retry-After} header field name.
391 	 * 
392 	 * @see <a href="http://tools.ietf.org/html/rfc7231#section-7.1.3">Section
393 	 *      7.1.3 of RFC 7231</a>
394 	 */
395 	public static final String RETRY_AFTER = "Retry-After";
396 	/**
397 	 * The HTTP {@code Server} header field name.
398 	 * 
399 	 * @see <a href="http://tools.ietf.org/html/rfc7231#section-7.4.2">Section
400 	 *      7.4.2 of RFC 7231</a>
401 	 */
402 	public static final String SERVER = "Server";
403 	/**
404 	 * The HTTP {@code Set-Cookie} header field name.
405 	 * 
406 	 * @see <a href="http://tools.ietf.org/html/rfc2109#section-4.2.2">Section
407 	 *      4.2.2 of RFC 2109</a>
408 	 */
409 	public static final String SET_COOKIE = "Set-Cookie";
410 	/**
411 	 * The HTTP {@code Set-Cookie2} header field name.
412 	 * 
413 	 * @see <a href="http://tools.ietf.org/html/rfc2965">RFC 2965</a>
414 	 */
415 	public static final String SET_COOKIE2 = "Set-Cookie2";
416 	/**
417 	 * The HTTP {@code TE} header field name.
418 	 * 
419 	 * @see <a href="http://tools.ietf.org/html/rfc7230#section-4.3">Section 4.3
420 	 *      of RFC 7230</a>
421 	 */
422 	public static final String TE = "TE";
423 	/**
424 	 * The HTTP {@code Trailer} header field name.
425 	 * 
426 	 * @see <a href="http://tools.ietf.org/html/rfc7230#section-4.4">Section 4.4
427 	 *      of RFC 7230</a>
428 	 */
429 	public static final String TRAILER = "Trailer";
430 	/**
431 	 * The HTTP {@code Transfer-Encoding} header field name.
432 	 * 
433 	 * @see <a href="http://tools.ietf.org/html/rfc7230#section-3.3.1">Section
434 	 *      3.3.1 of RFC 7230</a>
435 	 */
436 	public static final String TRANSFER_ENCODING = "Transfer-Encoding";
437 	/**
438 	 * The HTTP {@code Upgrade} header field name.
439 	 * 
440 	 * @see <a href="http://tools.ietf.org/html/rfc7230#section-6.7">Section 6.7
441 	 *      of RFC 7230</a>
442 	 */
443 	public static final String UPGRADE = "Upgrade";
444 	/**
445 	 * The HTTP {@code User-Agent} header field name.
446 	 * 
447 	 * @see <a href="http://tools.ietf.org/html/rfc7231#section-5.5.3">Section
448 	 *      5.5.3 of RFC 7231</a>
449 	 */
450 	public static final String USER_AGENT = "User-Agent";
451 	/**
452 	 * The HTTP {@code Vary} header field name.
453 	 * 
454 	 * @see <a href="http://tools.ietf.org/html/rfc7231#section-7.1.4">Section
455 	 *      7.1.4 of RFC 7231</a>
456 	 */
457 	public static final String VARY = "Vary";
458 	/**
459 	 * The HTTP {@code Via} header field name.
460 	 * 
461 	 * @see <a href="http://tools.ietf.org/html/rfc7230#section-5.7.1">Section
462 	 *      5.7.1 of RFC 7230</a>
463 	 */
464 	public static final String VIA = "Via";
465 	/**
466 	 * The HTTP {@code Warning} header field name.
467 	 * 
468 	 * @see <a href="http://tools.ietf.org/html/rfc7234#section-5.5">Section 5.5
469 	 *      of RFC 7234</a>
470 	 */
471 	public static final String WARNING = "Warning";
472 	/**
473 	 * The HTTP {@code WWW-Authenticate} header field name.
474 	 * 
475 	 * @see <a href="http://tools.ietf.org/html/rfc7235#section-4.1">Section 4.1
476 	 *      of RFC 7235</a>
477 	 */
478 	public static final String WWW_AUTHENTICATE = "WWW-Authenticate";
479 
480 	/**
481 	 * Date formats as specified in the HTTP RFC
482 	 * 
483 	 * @see <a
484 	 *      href="https://tools.ietf.org/html/rfc7231#section-7.1.1.1">Section
485 	 *      7.1.1.1 of RFC 7231</a>
486 	 */
487 	private static final String[] DATE_FORMATS = new String[] {
488 			"EEE, dd MMM yyyy HH:mm:ss zzz", "EEE, dd-MMM-yy HH:mm:ss zzz",
489 			"EEE MMM dd HH:mm:ss yyyy" };
490 
491 	private static TimeZone GMT = TimeZone.getTimeZone("GMT");
492 
493 	private final Map<String, List<String>> headers;
494 
495 	/**
496 	 * Constructs a new, empty instance of the {@code HttpHeaders} object.
497 	 */
498 	public HttpHeaders() {
499 		this(new LinkedCaseInsensitiveMap<List<String>>(8, Locale.ENGLISH),
500 				false);
501 	}
502 
503 	/**
504 	 * Private constructor that can create read-only {@code HttpHeader}
505 	 * instances.
506 	 */
507 	private HttpHeaders(Map<String, List<String>> headers, boolean readOnly) {
508 		if (readOnly) {
509 			Map<String, List<String>> map = new LinkedCaseInsensitiveMap<List<String>>(
510 					headers.size(), Locale.ENGLISH);
511 			for (Entry<String, List<String>> entry : headers.entrySet()) {
512 				List<String> values = Collections.unmodifiableList(entry
513 						.getValue());
514 				map.put(entry.getKey(), values);
515 			}
516 			this.headers = Collections.unmodifiableMap(map);
517 		} else {
518 			this.headers = headers;
519 		}
520 	}
521 
522 	/**
523 	 * Set the list of acceptable {@linkplain MediaType media types}, as
524 	 * specified by the {@code Accept} header.
525 	 */
526 	public void setAccept(List<ContentType> acceptableMediaTypes) {
527 		set(ACCEPT, ContentType.toString(acceptableMediaTypes));
528 	}
529 
530 	/**
531 	 * Return the list of acceptable {@linkplain MediaType media types}, as
532 	 * specified by the {@code Accept} header.
533 	 * <p>
534 	 * Returns an empty list when the acceptable media types are unspecified.
535 	 */
536 	public String getAccept() {
537 		return getFirst(ACCEPT);
538 	}
539 
540 	/**
541 	 * Set the (new) value of the {@code Access-Control-Allow-Credentials}
542 	 * response header.
543 	 */
544 	public void setAccessControlAllowCredentials(boolean allowCredentials) {
545 		set(ACCESS_CONTROL_ALLOW_CREDENTIALS,
546 				Boolean.toString(allowCredentials));
547 	}
548 
549 	/**
550 	 * Returns the value of the {@code Access-Control-Allow-Credentials}
551 	 * response header.
552 	 */
553 	public boolean getAccessControlAllowCredentials() {
554 		return Boolean.valueOf(getFirst(ACCESS_CONTROL_ALLOW_CREDENTIALS));
555 	}
556 
557 	/**
558 	 * Set the (new) value of the {@code Access-Control-Allow-Headers} response
559 	 * header.
560 	 */
561 	public void setAccessControlAllowHeaders(List<String> allowedHeaders) {
562 		set(ACCESS_CONTROL_ALLOW_HEADERS,
563 				toCommaDelimitedString(allowedHeaders));
564 	}
565 
566 	/**
567 	 * Returns the value of the {@code Access-Control-Allow-Headers} response
568 	 * header.
569 	 */
570 	public List<String> getAccessControlAllowHeaders() {
571 		return getFirstValueAsList(ACCESS_CONTROL_ALLOW_HEADERS);
572 	}
573 
574 	/**
575 	 * Set the (new) value of the {@code Access-Control-Allow-Methods} response
576 	 * header.
577 	 */
578 	public void setAccessControlAllowMethods(List<HttpMethod> allowedMethods) {
579 		set(ACCESS_CONTROL_ALLOW_METHODS, StringUtil.join(allowedMethods, ','));
580 	}
581 
582 	/**
583 	 * Returns the value of the {@code Access-Control-Allow-Methods} response
584 	 * header.
585 	 */
586 	public List<HttpMethod> getAccessControlAllowMethods() {
587 		List<HttpMethod> result = new ArrayList<HttpMethod>();
588 		String value = getFirst(ACCESS_CONTROL_ALLOW_METHODS);
589 		if (value != null) {
590 			String[] tokens = value.split(",\\s*");
591 			for (String token : tokens) {
592 				result.add(HttpMethod.valueOf(token));
593 			}
594 		}
595 		return result;
596 	}
597 
598 	/**
599 	 * Set the (new) value of the {@code Access-Control-Allow-Origin} response
600 	 * header.
601 	 */
602 	public void setAccessControlAllowOrigin(String allowedOrigin) {
603 		set(ACCESS_CONTROL_ALLOW_ORIGIN, allowedOrigin);
604 	}
605 
606 	/**
607 	 * Returns the value of the {@code Access-Control-Allow-Origin} response
608 	 * header.
609 	 */
610 	public String getAccessControlAllowOrigin() {
611 		return getFirst(ACCESS_CONTROL_ALLOW_ORIGIN);
612 	}
613 
614 	/**
615 	 * Set the (new) value of the {@code Access-Control-Expose-Headers} response
616 	 * header.
617 	 */
618 	public void setAccessControlExposeHeaders(List<String> exposedHeaders) {
619 		set(ACCESS_CONTROL_EXPOSE_HEADERS,
620 				toCommaDelimitedString(exposedHeaders));
621 	}
622 
623 	/**
624 	 * Returns the value of the {@code Access-Control-Expose-Headers} response
625 	 * header.
626 	 */
627 	public List<String> getAccessControlExposeHeaders() {
628 		return getFirstValueAsList(ACCESS_CONTROL_EXPOSE_HEADERS);
629 	}
630 
631 	/**
632 	 * Set the (new) value of the {@code Access-Control-Max-Age} response
633 	 * header.
634 	 */
635 	public void setAccessControlMaxAge(long maxAge) {
636 		set(ACCESS_CONTROL_MAX_AGE, Long.toString(maxAge));
637 	}
638 
639 	/**
640 	 * Returns the value of the {@code Access-Control-Max-Age} response header.
641 	 * <p>
642 	 * Returns -1 when the max age is unknown.
643 	 */
644 	public long getAccessControlMaxAge() {
645 		String value = getFirst(ACCESS_CONTROL_MAX_AGE);
646 		return (value != null ? Long.parseLong(value) : -1);
647 	}
648 
649 	/**
650 	 * Set the (new) value of the {@code Access-Control-Request-Headers} request
651 	 * header.
652 	 */
653 	public void setAccessControlRequestHeaders(List<String> requestHeaders) {
654 		set(ACCESS_CONTROL_REQUEST_HEADERS,
655 				toCommaDelimitedString(requestHeaders));
656 	}
657 
658 	/**
659 	 * Returns the value of the {@code Access-Control-Request-Headers} request
660 	 * header.
661 	 */
662 	public List<String> getAccessControlRequestHeaders() {
663 		return getFirstValueAsList(ACCESS_CONTROL_REQUEST_HEADERS);
664 	}
665 
666 	/**
667 	 * Set the (new) value of the {@code Access-Control-Request-Method} request
668 	 * header.
669 	 */
670 	public void setAccessControlRequestMethod(HttpMethod requestedMethod) {
671 		set(ACCESS_CONTROL_REQUEST_METHOD, requestedMethod.name());
672 	}
673 
674 	/**
675 	 * Returns the value of the {@code Access-Control-Request-Method} request
676 	 * header.
677 	 */
678 	public HttpMethod getAccessControlRequestMethod() {
679 		String value = getFirst(ACCESS_CONTROL_REQUEST_METHOD);
680 		return (value != null ? HttpMethod.valueOf(value) : null);
681 	}
682 
683 	/**
684 	 * Set the list of acceptable {@linkplain Charset charsets}, as specified by
685 	 * the {@code Accept-Charset} header.
686 	 */
687 	public void setAcceptCharset(List<Charset> acceptableCharsets) {
688 		StringBuilder builder = new StringBuilder();
689 		for (Iterator<Charset> iterator = acceptableCharsets.iterator(); iterator
690 				.hasNext();) {
691 			Charset charset = iterator.next();
692 			builder.append(charset.name().toLowerCase(Locale.ENGLISH));
693 			if (iterator.hasNext()) {
694 				builder.append(", ");
695 			}
696 		}
697 		set(ACCEPT_CHARSET, builder.toString());
698 	}
699 
700 	/**
701 	 * Return the list of acceptable {@linkplain Charset charsets}, as specified
702 	 * by the {@code Accept-Charset} header.
703 	 */
704 	public List<Charset> getAcceptCharset() {
705 		List<Charset> result = new ArrayList<Charset>();
706 		String value = getFirst(ACCEPT_CHARSET);
707 		if (value != null) {
708 			String[] tokens = value.split(",\\s*");
709 			for (String token : tokens) {
710 				int paramIdx = token.indexOf(';');
711 				String charsetName;
712 				if (paramIdx == -1) {
713 					charsetName = token;
714 				} else {
715 					charsetName = token.substring(0, paramIdx);
716 				}
717 				if (!charsetName.equals("*")) {
718 					result.add(Charset.forName(charsetName));
719 				}
720 			}
721 		}
722 		return result;
723 	}
724 
725 	/**
726 	 * Set the set of allowed {@link HttpMethod HTTP methods}, as specified by
727 	 * the {@code Allow} header.
728 	 */
729 	public void setAllow(Set<HttpMethod> allowedMethods) {
730 		set(ALLOW, StringUtil.join(allowedMethods, ','));
731 	}
732 
733 	/**
734 	 * Return the set of allowed {@link HttpMethod HTTP methods}, as specified
735 	 * by the {@code Allow} header.
736 	 * <p>
737 	 * Returns an empty set when the allowed methods are unspecified.
738 	 */
739 	public Set<HttpMethod> getAllow() {
740 		String value = getFirst(ALLOW);
741 		if (StringUtil.isNotBlank(value)) {
742 			List<HttpMethod> allowedMethod = new ArrayList<HttpMethod>(5);
743 			String[] tokens = value.split(",\\s*");
744 			for (String token : tokens) {
745 				allowedMethod.add(HttpMethod.valueOf(token));
746 			}
747 			return EnumSet.copyOf(allowedMethod);
748 		} else {
749 			return EnumSet.noneOf(HttpMethod.class);
750 		}
751 	}
752 
753 	/**
754 	 * Set the (new) value of the {@code Cache-Control} header.
755 	 */
756 	public void setCacheControl(String cacheControl) {
757 		set(CACHE_CONTROL, cacheControl);
758 	}
759 
760 	/**
761 	 * Returns the value of the {@code Cache-Control} header.
762 	 */
763 	public String getCacheControl() {
764 		return getFirst(CACHE_CONTROL);
765 	}
766 
767 	/**
768 	 * Set the (new) value of the {@code Connection} header.
769 	 */
770 	public void setConnection(String connection) {
771 		set(CONNECTION, connection);
772 	}
773 
774 	/**
775 	 * Set the (new) value of the {@code Connection} header.
776 	 */
777 	public void setConnection(List<String> connection) {
778 		set(CONNECTION, toCommaDelimitedString(connection));
779 	}
780 
781 	/**
782 	 * Returns the value of the {@code Connection} header.
783 	 */
784 	public List<String> getConnection() {
785 		return getFirstValueAsList(CONNECTION);
786 	}
787 
788 	/**
789 	 * Set the (new) value of the {@code Content-Disposition} header for
790 	 * {@code form-data}.
791 	 * 
792 	 * @param name
793 	 *            the control name
794 	 * @param filename
795 	 *            the filename (may be {@code null})
796 	 */
797 	public void setContentDispositionFormData(String name, String filename) {
798 		StringBuilder builder = new StringBuilder("form-data; name=\"");
799 		builder.append(name).append('\"');
800 		if (filename != null) {
801 			builder.append("; filename=\"");
802 			builder.append(filename).append('\"');
803 		}
804 		set(CONTENT_DISPOSITION, builder.toString());
805 	}
806 
807 	/**
808 	 * Set the length of the body in bytes, as specified by the
809 	 * {@code Content-Length} header.
810 	 */
811 	public void setContentLength(long contentLength) {
812 		set(CONTENT_LENGTH, Long.toString(contentLength));
813 	}
814 
815 	/**
816 	 * Return the length of the body in bytes, as specified by the
817 	 * {@code Content-Length} header.
818 	 * <p>
819 	 * Returns -1 when the content-length is unknown.
820 	 */
821 	public long getContentLength() {
822 		String value = getFirst(CONTENT_LENGTH);
823 		return (value != null ? Long.parseLong(value) : -1);
824 	}
825 
826 	/**
827 	 * Set the {@linkplain ContentType media type} of the body, as specified by
828 	 * the {@code Content-Type} header.
829 	 */
830 	public void setContentType(ContentType contentType) {
831 		set(CONTENT_TYPE, contentType.toString());
832 	}
833 
834 	/**
835 	 * Return the {@linkplain MediaType media type} of the body, as specified by
836 	 * the {@code Content-Type} header.
837 	 * <p>
838 	 * Returns {@code null} when the content-type is unknown.
839 	 */
840 	public String getContentType() {
841 		return getFirst(CONTENT_TYPE);
842 	}
843 
844 	/**
845 	 * Set the date and time at which the message was created, as specified by
846 	 * the {@code Date} header.
847 	 * <p>
848 	 * The date should be specified as the number of milliseconds since January
849 	 * 1, 1970 GMT.
850 	 */
851 	public void setDate(long date) {
852 		setDate(DATE, date);
853 	}
854 
855 	/**
856 	 * Return the date and time at which the message was created, as specified
857 	 * by the {@code Date} header.
858 	 * <p>
859 	 * The date is returned as the number of milliseconds since January 1, 1970
860 	 * GMT. Returns -1 when the date is unknown.
861 	 * 
862 	 * @throws IllegalArgumentException
863 	 *             if the value can't be converted to a date
864 	 */
865 	public long getDate() {
866 		return getFirstDate(DATE);
867 	}
868 
869 	/**
870 	 * Set the (new) entity tag of the body, as specified by the {@code ETag}
871 	 * header.
872 	 */
873 	public void setETag(String eTag) {
874 		set(ETAG, eTag);
875 	}
876 
877 	/**
878 	 * Return the entity tag of the body, as specified by the {@code ETag}
879 	 * header.
880 	 */
881 	public String getETag() {
882 		return getFirst(ETAG);
883 	}
884 
885 	/**
886 	 * Set the date and time at which the message is no longer valid, as
887 	 * specified by the {@code Expires} header.
888 	 * <p>
889 	 * The date should be specified as the number of milliseconds since January
890 	 * 1, 1970 GMT.
891 	 */
892 	public void setExpires(long expires) {
893 		setDate(EXPIRES, expires);
894 	}
895 
896 	/**
897 	 * Return the date and time at which the message is no longer valid, as
898 	 * specified by the {@code Expires} header.
899 	 * <p>
900 	 * The date is returned as the number of milliseconds since January 1, 1970
901 	 * GMT. Returns -1 when the date is unknown.
902 	 */
903 	public long getExpires() {
904 		try {
905 			return getFirstDate(EXPIRES);
906 		} catch (IllegalArgumentException ex) {
907 			return -1;
908 		}
909 	}
910 
911 	/**
912 	 * Set the (new) value of the {@code If-Modified-Since} header.
913 	 * <p>
914 	 * The date should be specified as the number of milliseconds since January
915 	 * 1, 1970 GMT.
916 	 */
917 	public void setIfModifiedSince(long ifModifiedSince) {
918 		setDate(IF_MODIFIED_SINCE, ifModifiedSince);
919 	}
920 
921 	/**
922 	 * Return the value of the {@code If-Modified-Since} header.
923 	 * <p>
924 	 * The date is returned as the number of milliseconds since January 1, 1970
925 	 * GMT. Returns -1 when the date is unknown.
926 	 */
927 	public long getIfModifiedSince() {
928 		return getFirstDate(IF_MODIFIED_SINCE);
929 	}
930 
931 	/**
932 	 * Set the (new) value of the {@code If-None-Match} header.
933 	 */
934 	public void setIfNoneMatch(String ifNoneMatch) {
935 		set(IF_NONE_MATCH, ifNoneMatch);
936 	}
937 
938 	/**
939 	 * Set the (new) values of the {@code If-None-Match} header.
940 	 */
941 	public void setIfNoneMatch(List<String> ifNoneMatchList) {
942 		set(IF_NONE_MATCH, toCommaDelimitedString(ifNoneMatchList));
943 	}
944 
945 	protected String toCommaDelimitedString(List<String> list) {
946 		StringBuilder builder = new StringBuilder();
947 		for (Iterator<String> iterator = list.iterator(); iterator.hasNext();) {
948 			String ifNoneMatch = iterator.next();
949 			builder.append(ifNoneMatch);
950 			if (iterator.hasNext()) {
951 				builder.append(", ");
952 			}
953 		}
954 		return builder.toString();
955 	}
956 
957 	/**
958 	 * Return the value of the {@code If-None-Match} header.
959 	 */
960 	public List<String> getIfNoneMatch() {
961 		return getFirstValueAsList(IF_NONE_MATCH);
962 	}
963 
964 	protected List<String> getFirstValueAsList(String header) {
965 		List<String> result = new ArrayList<String>();
966 		String value = getFirst(header);
967 		if (value != null) {
968 			String[] tokens = value.split(",\\s*");
969 			for (String token : tokens) {
970 				result.add(token);
971 			}
972 		}
973 		return result;
974 	}
975 
976 	/**
977 	 * Set the time the resource was last changed, as specified by the
978 	 * {@code Last-Modified} header.
979 	 * <p>
980 	 * The date should be specified as the number of milliseconds since January
981 	 * 1, 1970 GMT.
982 	 */
983 	public void setLastModified(long lastModified) {
984 		setDate(LAST_MODIFIED, lastModified);
985 	}
986 
987 	/**
988 	 * Return the time the resource was last changed, as specified by the
989 	 * {@code Last-Modified} header.
990 	 * <p>
991 	 * The date is returned as the number of milliseconds since January 1, 1970
992 	 * GMT. Returns -1 when the date is unknown.
993 	 */
994 	public long getLastModified() {
995 		return getFirstDate(LAST_MODIFIED);
996 	}
997 
998 	/**
999 	 * Set the (new) location of a resource, as specified by the
1000 	 * {@code Location} header.
1001 	 */
1002 	public void setLocation(URI location) {
1003 		set(LOCATION, location.toASCIIString());
1004 	}
1005 
1006 	/**
1007 	 * Return the (new) location of a resource as specified by the
1008 	 * {@code Location} header.
1009 	 * <p>
1010 	 * Returns {@code null} when the location is unknown.
1011 	 */
1012 	public URI getLocation() {
1013 		String value = getFirst(LOCATION);
1014 		return (value != null ? URI.create(value) : null);
1015 	}
1016 
1017 	/**
1018 	 * Set the (new) value of the {@code Origin} header.
1019 	 */
1020 	public void setOrigin(String origin) {
1021 		set(ORIGIN, origin);
1022 	}
1023 
1024 	/**
1025 	 * Return the value of the {@code Origin} header.
1026 	 */
1027 	public String getOrigin() {
1028 		return getFirst(ORIGIN);
1029 	}
1030 
1031 	/**
1032 	 * Set the (new) value of the {@code Pragma} header.
1033 	 */
1034 	public void setPragma(String pragma) {
1035 		set(PRAGMA, pragma);
1036 	}
1037 
1038 	/**
1039 	 * Return the value of the {@code Pragma} header.
1040 	 */
1041 	public String getPragma() {
1042 		return getFirst(PRAGMA);
1043 	}
1044 
1045 	/**
1046 	 * Sets the (new) value of the {@code Range} header.
1047 	 */
1048 	public void setRange(String range) {
1049 		set(RANGE, range);
1050 	}
1051 
1052 	/**
1053 	 * Returns the value of the {@code Range} header.
1054 	 * <p>
1055 	 * Returns an empty list when the range is unknown.
1056 	 */
1057 	public String getRange() {
1058 		return getFirst(RANGE);
1059 	}
1060 
1061 	/**
1062 	 * Set the (new) value of the {@code Upgrade} header.
1063 	 */
1064 	public void setUpgrade(String upgrade) {
1065 		set(UPGRADE, upgrade);
1066 	}
1067 
1068 	/**
1069 	 * Returns the value of the {@code Upgrade} header.
1070 	 */
1071 	public String getUpgrade() {
1072 		return getFirst(UPGRADE);
1073 	}
1074 
1075 	/**
1076 	 * Parse the first header value for the given header name as a date, return
1077 	 * -1 if there is no value, or raise {@link IllegalArgumentException} if the
1078 	 * value cannot be parsed as a date.
1079 	 */
1080 	public long getFirstDate(String headerName) {
1081 		String headerValue = getFirst(headerName);
1082 		if (headerValue == null) {
1083 			return -1;
1084 		}
1085 		for (String dateFormat : DATE_FORMATS) {
1086 			SimpleDateFormat simpleDateFormat = new SimpleDateFormat(
1087 					dateFormat, Locale.US);
1088 			simpleDateFormat.setTimeZone(GMT);
1089 			try {
1090 				return simpleDateFormat.parse(headerValue).getTime();
1091 			} catch (ParseException ex) {
1092 				// ignore
1093 			}
1094 		}
1095 		throw new IllegalArgumentException("Cannot parse date value \""
1096 				+ headerValue + "\" for \"" + headerName + "\" header");
1097 	}
1098 
1099 	/**
1100 	 * Set the given date under the given header name after formatting it as a
1101 	 * string using the pattern {@code "EEE, dd MMM yyyy HH:mm:ss zzz"}. The
1102 	 * equivalent of {@link #set(String, String)} but for date headers.
1103 	 */
1104 	public void setDate(String headerName, long date) {
1105 		SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMATS[0],
1106 				Locale.US);
1107 		dateFormat.setTimeZone(GMT);
1108 		set(headerName, dateFormat.format(new Date(date)));
1109 	}
1110 
1111 	/**
1112 	 * Return the first header value for the given header name, if any.
1113 	 * 
1114 	 * @param headerName
1115 	 *            the header name
1116 	 * @return the first header value, or {@code null} if none
1117 	 */
1118 	@Override
1119 	public String getFirst(String headerName) {
1120 		List<String> headerValues = this.headers.get(headerName);
1121 		return (headerValues != null ? headerValues.get(0) : null);
1122 	}
1123 
1124 	/**
1125 	 * Add the given, single header value under the given name.
1126 	 * 
1127 	 * @param headerName
1128 	 *            the header name
1129 	 * @param headerValue
1130 	 *            the header value
1131 	 * @throws UnsupportedOperationException
1132 	 *             if adding headers is not supported
1133 	 * @see #put(String, List)
1134 	 * @see #set(String, String)
1135 	 */
1136 	@Override
1137 	public void add(String headerName, String headerValue) {
1138 		List<String> headerValues = this.headers.get(headerName);
1139 		if (headerValues == null) {
1140 			headerValues = new LinkedList<String>();
1141 			this.headers.put(headerName, headerValues);
1142 		}
1143 		headerValues.add(headerValue);
1144 	}
1145 
1146 	/**
1147 	 * Set the given, single header value under the given name.
1148 	 * 
1149 	 * @param headerName
1150 	 *            the header name
1151 	 * @param headerValue
1152 	 *            the header value
1153 	 * @throws UnsupportedOperationException
1154 	 *             if adding headers is not supported
1155 	 * @see #put(String, List)
1156 	 * @see #add(String, String)
1157 	 */
1158 	@Override
1159 	public void set(String headerName, String headerValue) {
1160 		List<String> headerValues = new LinkedList<String>();
1161 		headerValues.add(headerValue);
1162 		this.headers.put(headerName, headerValues);
1163 	}
1164 
1165 	@Override
1166 	public void setAll(Map<String, String> values) {
1167 		for (Entry<String, String> entry : values.entrySet()) {
1168 			set(entry.getKey(), entry.getValue());
1169 		}
1170 	}
1171 
1172 	@Override
1173 	public Map<String, String> toSingleValueMap() {
1174 		LinkedHashMap<String, String> singleValueMap = new LinkedHashMap<String, String>(
1175 				this.headers.size());
1176 		for (Entry<String, List<String>> entry : this.headers.entrySet()) {
1177 			singleValueMap.put(entry.getKey(), entry.getValue().get(0));
1178 		}
1179 		return singleValueMap;
1180 	}
1181 
1182 	// Map implementation
1183 
1184 	@Override
1185 	public int size() {
1186 		return this.headers.size();
1187 	}
1188 
1189 	@Override
1190 	public boolean isEmpty() {
1191 		return this.headers.isEmpty();
1192 	}
1193 
1194 	@Override
1195 	public boolean containsKey(Object key) {
1196 		return this.headers.containsKey(key);
1197 	}
1198 
1199 	@Override
1200 	public boolean containsValue(Object value) {
1201 		return this.headers.containsValue(value);
1202 	}
1203 
1204 	@Override
1205 	public List<String> get(Object key) {
1206 		return this.headers.get(key);
1207 	}
1208 
1209 	@Override
1210 	public List<String> put(String key, List<String> value) {
1211 		return this.headers.put(key, value);
1212 	}
1213 
1214 	@Override
1215 	public List<String> remove(Object key) {
1216 		return this.headers.remove(key);
1217 	}
1218 
1219 	@Override
1220 	public void putAll(Map<? extends String, ? extends List<String>> map) {
1221 		this.headers.putAll(map);
1222 	}
1223 
1224 	@Override
1225 	public void clear() {
1226 		this.headers.clear();
1227 	}
1228 
1229 	@Override
1230 	public Set<String> keySet() {
1231 		return this.headers.keySet();
1232 	}
1233 
1234 	@Override
1235 	public Collection<List<String>> values() {
1236 		return this.headers.values();
1237 	}
1238 
1239 	@Override
1240 	public Set<Entry<String, List<String>>> entrySet() {
1241 		return this.headers.entrySet();
1242 	}
1243 
1244 	@Override
1245 	public boolean equals(Object other) {
1246 		if (this == other) {
1247 			return true;
1248 		}
1249 		if (!(other instanceof HttpHeaders)) {
1250 			return false;
1251 		}
1252 		HttpHeaders otherHeaders = (HttpHeaders) other;
1253 		return this.headers.equals(otherHeaders.headers);
1254 	}
1255 
1256 	@Override
1257 	public int hashCode() {
1258 		return this.headers.hashCode();
1259 	}
1260 
1261 	@Override
1262 	public String toString() {
1263 		return this.headers.toString();
1264 	}
1265 
1266 	/**
1267 	 * Return a {@code HttpHeaders} object that can only be read, not written
1268 	 * to.
1269 	 */
1270 	public static HttpHeaders readOnlyHttpHeaders(HttpHeaders headers) {
1271 		return new HttpHeaders(headers, true);
1272 	}
1273 }