001// ***************************************************************************************************************************
002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
003// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
005// * with the License.  You may obtain a copy of the License at                                                              *
006// *                                                                                                                         *
007// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
008// *                                                                                                                         *
009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
011// * specific language governing permissions and limitations under the License.                                              *
012// ***************************************************************************************************************************
013package org.apache.juneau.rest;
014
015import static org.apache.juneau.internal.ArrayUtils.*;
016import static org.apache.juneau.internal.StringUtils.*;
017
018import java.lang.reflect.*;
019import java.util.*;
020
021import org.apache.juneau.*;
022import org.apache.juneau.http.*;
023import org.apache.juneau.http.Date;
024import org.apache.juneau.httppart.*;
025import org.apache.juneau.internal.*;
026import org.apache.juneau.json.*;
027import org.apache.juneau.oapi.*;
028import org.apache.juneau.parser.*;
029import org.apache.juneau.rest.exception.*;
030
031/**
032 * Represents the headers in an HTTP request.
033 *
034 * <p>
035 * Entries are stored in a case-insensitive map.
036 *
037 * <h5 class='section'>See Also:</h5>
038 * <ul>
039 *    <li class='link'>{@doc juneau-rest-server.RestMethod.RequestHeaders}
040 * </ul>
041 */
042public class RequestHeaders extends TreeMap<String,String[]> {
043   private static final long serialVersionUID = 1L;
044
045   private final RestRequest req;
046   private HttpPartParser parser;
047   private RequestQuery queryParams;
048
049   RequestHeaders(RestRequest req) {
050      super(String.CASE_INSENSITIVE_ORDER);
051      this.req = req;
052   }
053
054   RequestHeaders parser(HttpPartParser parser) {
055      this.parser = parser;
056      return this;
057   }
058
059   RequestHeaders queryParams(RequestQuery queryParams) {
060      this.queryParams = queryParams;
061      return this;
062   }
063
064   /**
065    * Adds default entries to these headers.
066    *
067    * <p>
068    * Similar to {@link #put(String, Object)} but doesn't override existing values.
069    *
070    * @param defaultEntries
071    *    The default entries.
072    *    <br>Can be <jk>null</jk>.
073    * @return This object (for method chaining).
074    */
075   public RequestHeaders addDefault(Map<String,Object> defaultEntries) {
076      if (defaultEntries != null) {
077         for (Map.Entry<String,Object> e : defaultEntries.entrySet()) {
078            String key = e.getKey();
079            Object value = e.getValue();
080            String[] v = get(key);
081            if (v == null || v.length == 0 || StringUtils.isEmpty(v[0]))
082               put(key, asStrings(value));
083         }
084      }
085      return this;
086   }
087
088   /**
089    * Adds a default header value on this request.
090    *
091    * <p>
092    * Similar to {@link #put(String, Object)} but doesn't override existing values.
093    *
094    * @param name
095    *    The header name.
096    * @param value
097    *    The header value.
098    *    <br>Converted to a String using <code>toString()</code>.
099    *    <br>Ignored if value is <jk>null</jk> or blank.
100    * @return This object (for method chaining).
101    */
102   public RequestHeaders addDefault(String name, Object value) {
103      return addDefault(Collections.singletonMap(name, value));
104   }
105
106   /**
107    * Adds a set of header values to this object.
108    *
109    * @param name The header name.
110    * @param values The header values.
111    * @return This object (for method chaining).
112    */
113   public RequestHeaders put(String name, Enumeration<String> values) {
114      // Optimized for enumerations of one entry, the most-common case.
115      if (values.hasMoreElements()) {
116         String v = values.nextElement();
117         String[] s = new String[]{v};
118         while (values.hasMoreElements())
119            s = append(s, values.nextElement());
120         put(name, s);
121      }
122      return this;
123   }
124
125   /**
126    * Returns the specified header value as a string.
127    *
128    * <h5 class='section'>Notes:</h5>
129    * <ul class='spaced-list'>
130    *    <li>
131    *       If {@code allowHeaderParams} init parameter is <jk>true</jk>, then first looks for {@code &HeaderName=x} in the URL query string.
132    * </ul>
133    *
134    * @param name The header name.
135    * @return The header value, or <jk>null</jk> if it doesn't exist.
136    */
137   public String getString(String name) {
138      String[] v = null;
139      if (queryParams != null)
140         v = queryParams.get(name);
141      if (v == null || v.length == 0)
142         v = get(name);
143      if (v == null || v.length == 0)
144         return null;
145      return v[0];
146   }
147
148   /**
149    * Returns the specified header value as a string.
150    *
151    * <h5 class='section'>Notes:</h5>
152    * <ul class='spaced-list'>
153    *    <li>
154    *       If {@code allowHeaderParams} init parameter is <jk>true</jk>, then first looks for {@code &HeaderName=x} in the URL query string.
155    * </ul>
156    *
157    * @param name The HTTP header name.
158    * @param def The default value to return if the header value isn't found.
159    * @return The header value, or the default value if the header isn't present.
160    */
161   public String getString(String name, String def) {
162      String s = getString(name);
163      return StringUtils.isEmpty(s) ? def : s;
164   }
165
166   /**
167    * Same as {@link #getString(String)} but converts the value to an integer.
168    *
169    * @param name The HTTP header name.
170    * @return The header value, or the default value if the header isn't present.
171    */
172   public int getInt(String name) {
173      return getInt(name, 0);
174   }
175
176   /**
177    * Same as {@link #getString(String,String)} but converts the value to an integer.
178    *
179    * @param name The HTTP header name.
180    * @param def The default value to return if the header value isn't found.
181    * @return The header value, or the default value if the header isn't present.
182    */
183   public int getInt(String name, int def) {
184      String s = getString(name);
185      return StringUtils.isEmpty(s) ? def : Integer.parseInt(s);
186   }
187
188   /**
189    * Same as {@link #getString(String)} but converts the value to a boolean.
190    *
191    * @param name The HTTP header name.
192    * @return The header value, or the default value if the header isn't present.
193    */
194   public boolean getBoolean(String name) {
195      return getBoolean(name, false);
196   }
197
198   /**
199    * Same as {@link #getString(String,String)} but converts the value to a boolean.
200    *
201    * @param name The HTTP header name.
202    * @param def The default value to return if the header value isn't found.
203    * @return The header value, or the default value if the header isn't present.
204    */
205   public boolean getBoolean(String name, boolean def) {
206      String s = getString(name);
207      return StringUtils.isEmpty(s) ? def : Boolean.parseBoolean(s);
208   }
209
210   /**
211    * Sets a request header value.
212    *
213    * <p>
214    * This overwrites any previous value.
215    *
216    * @param name The header name.
217    * @param value The header value.
218    */
219   public void put(String name, Object value) {
220      super.put(name, asStrings(value));
221   }
222
223   /**
224    * Returns the specified header value converted to a POJO using the {@link HttpPartParser} registered with the resource.
225    *
226    * <h5 class='section'>Examples:</h5>
227    * <p class='bcode w800'>
228    *    <jc>// Parse into an integer.</jc>
229    *    <jk>int</jk> myheader = req.getHeader(<js>"My-Header"</js>, <jk>int</jk>.<jk>class</jk>);
230    *
231    *    <jc>// Parse a UUID.</jc>
232    *    UUID myheader = req.getHeader(<js>"My-Header"</js>, UUID.<jk>class</jk>);
233    * </p>
234    *
235    * <h5 class='section'>Notes:</h5>
236    * <ul class='spaced-list'>
237    *    <li>
238    *       If {@code allowHeaderParams} init parameter is <jk>true</jk>, then first looks for {@code &HeaderName=x} in the URL query string.
239    * </ul>
240    *
241    * <h5 class='section'>See Also:</h5>
242    * <ul>
243    *    <li class='jf'>{@link RestContext#REST_partParser}
244    * </ul>
245    *
246    * @param name The HTTP header name.
247    * @param type The class type to convert the header value to.
248    * @param <T> The class type to convert the header value to.
249    * @return The parameter value converted to the specified class type.
250    * @throws BadRequest Thrown if input could not be parsed.
251    * @throws InternalServerError Thrown if any other exception occurs.
252    */
253   public <T> T get(String name, Class<T> type) throws BadRequest, InternalServerError {
254      return getInner(null, null, name, null, getClassMeta(type));
255   }
256
257   /**
258    * Same as {@link #get(String, Class)} but allows you to override the part parser used.
259    *
260    * @param parser
261    *    The parser to use for parsing the string header.
262    *    <br>If <jk>null</jk>, uses the part parser defined on the resource/method.
263    * @param schema
264    *    The schema object that defines the format of the input.
265    *    <br>If <jk>null</jk>, defaults to the schema defined on the parser.
266    *    <br>If that's also <jk>null</jk>, defaults to {@link HttpPartSchema#DEFAULT}.
267    *    <br>Only used if parser is schema-aware (e.g. {@link OpenApiParser}).
268    * @param name The HTTP header name.
269    * @param type The class type to convert the header value to.
270    * @param <T> The class type to convert the header value to.
271    * @return The parameter value converted to the specified class type.
272    * @throws BadRequest Thrown if input could not be parsed or fails schema validation.
273    * @throws InternalServerError Thrown if any other exception occurs.
274    */
275   public <T> T get(HttpPartParser parser, HttpPartSchema schema, String name, Class<T> type) throws BadRequest, InternalServerError {
276      return getInner(parser, schema, name, null, getClassMeta(type));
277   }
278
279   /**
280    * Same as {@link #get(String, Class)} but returns a default value if not found.
281    *
282    * @param name The HTTP header name.
283    * @param def The default value if the header was not specified or is <jk>null</jk>.
284    * @param type The class type to convert the header value to.
285    * @param <T> The class type to convert the header value to.
286    * @return The parameter value converted to the specified class type.
287    * @throws BadRequest Thrown if input could not be parsed.
288    * @throws InternalServerError Thrown if any other exception occurs.
289    */
290   public <T> T get(String name, T def, Class<T> type) throws BadRequest, InternalServerError {
291      return getInner(null, null, name, def, getClassMeta(type));
292   }
293
294   /**
295    * Same as {@link #get(String, Object, Class)} but allows you to override the part parser used.
296    *
297    * @param parser
298    *    The parser to use for parsing the string header.
299    *    <br>If <jk>null</jk>, uses the part parser defined on the resource/method.
300    * @param schema
301    *    The schema object that defines the format of the input.
302    *    <br>If <jk>null</jk>, defaults to the schema defined on the parser.
303    *    <br>If that's also <jk>null</jk>, defaults to {@link HttpPartSchema#DEFAULT}.
304    *    <br>Only used if parser is schema-aware (e.g. {@link OpenApiParser}).
305    * @param name The HTTP header name.
306    * @param def The default value if the header was not specified or is <jk>null</jk>.
307    * @param type The class type to convert the header value to.
308    * @param <T> The class type to convert the header value to.
309    * @return The parameter value converted to the specified class type.
310    * @throws BadRequest Thrown if input could not be parsed or fails schema validation.
311    * @throws InternalServerError Thrown if any other exception occurs.
312    */
313   public <T> T get(HttpPartParser parser, HttpPartSchema schema, String name, T def, Class<T> type) throws BadRequest, InternalServerError {
314      return getInner(parser, schema, name, def, getClassMeta(type));
315   }
316
317   /**
318    * Returns the specified header value converted to a POJO using the {@link HttpPartParser} registered with the resource.
319    *
320    * <p>
321    * Similar to {@link #get(String,Class)} but allows for complex collections of POJOs to be created.
322    *
323    * <h5 class='section'>Examples:</h5>
324    * <p class='bcode w800'>
325    *    <jc>// Parse into a linked-list of strings.</jc>
326    *    List&lt;String&gt; myheader = req.getHeader(<js>"My-Header"</js>, LinkedList.<jk>class</jk>, String.<jk>class</jk>);
327    * </p>
328    *
329    * <h5 class='section'>Notes:</h5>
330    * <ul class='spaced-list'>
331    *    <li>
332    *       <code>Collections</code> must be followed by zero or one parameter representing the value type.
333    *    <li>
334    *       <code>Maps</code> must be followed by zero or two parameters representing the key and value types.
335    *    <li>
336    *       If {@code allowHeaderParams} init parameter is <jk>true</jk>, then first looks for {@code &HeaderName=x} in the URL query string.
337    * </ul>
338    *
339    * <h5 class='section'>See Also:</h5>
340    * <ul>
341    *    <li class='jf'>{@link RestContext#REST_partParser}
342    * </ul>
343    *
344    * @param name The HTTP header name.
345    * @param type
346    *    The type of object to create.
347    *    <br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
348    * @param args
349    *    The type arguments of the class if it's a collection or map.
350    *    <br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
351    *    <br>Ignored if the main type is not a map or collection.
352    * @param <T> The class type to convert the header value to.
353    * @return The parameter value converted to the specified class type.
354    * @throws BadRequest Thrown if input could not be parsed.
355    * @throws InternalServerError Thrown if any other exception occurs.
356    */
357   public <T> T get(String name, Type type, Type...args) throws BadRequest, InternalServerError {
358      return getInner(null, null, name, null, this.<T>getClassMeta(type, args));
359   }
360
361   /**
362    * Same as {@link #get(String, Type, Type...)} but allows you to override the part parser used.
363    *
364    * @param parser
365    *    The parser to use for parsing the string header.
366    *    <br>If <jk>null</jk>, uses the part parser defined on the resource/method.
367    * @param schema
368    *    The schema object that defines the format of the input.
369    *    <br>If <jk>null</jk>, defaults to the schema defined on the parser.
370    *    <br>If that's also <jk>null</jk>, defaults to {@link HttpPartSchema#DEFAULT}.
371    *    <br>Only used if parser is schema-aware (e.g. {@link OpenApiParser}).
372    * @param name
373    *    The HTTP header name.
374    * @param type
375    *    The type of object to create.
376    *    <br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
377    * @param args
378    *    The type arguments of the class if it's a collection or map.
379    *    <br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
380    *    <br>Ignored if the main type is not a map or collection.
381    * @param <T> The class type to convert the header value to.
382    * @return The parameter value converted to the specified class type.
383    * @throws BadRequest Thrown if input could not be parsed or fails schema validation.
384    * @throws InternalServerError Thrown if any other exception occurs.
385    */
386   public <T> T get(HttpPartParser parser, HttpPartSchema schema, String name, Type type, Type...args) throws BadRequest, InternalServerError {
387      return getInner(parser, schema, name, null, this.<T>getClassMeta(type, args));
388   }
389
390   /* Workhorse method */
391   private <T> T getInner(HttpPartParser parser, HttpPartSchema schema, String name, T def, ClassMeta<T> cm) throws BadRequest, InternalServerError {
392      try {
393         if (cm.isMapOrBean() && isOneOf(name, "*", "")) {
394            ObjectMap m = new ObjectMap();
395            for (Map.Entry<String,String[]> e : this.entrySet()) {
396               String k = e.getKey();
397               HttpPartSchema pschema = schema == null ? null : schema.getProperty(k);
398               ClassMeta<?> cm2 = cm.getValueType();
399               m.put(k, getInner(parser, pschema, k, null, cm2));
400            }
401            return req.getBeanSession().convertToType(m, cm);
402         }
403         T t = parse(parser, schema, getString(name), cm);
404         return (t == null ? def : t);
405      } catch (SchemaValidationException e) {
406         throw new BadRequest(e, "Validation failed on header ''{0}''. ", name);
407      } catch (ParseException e) {
408         throw new BadRequest(e, "Could not parse header ''{0}''.", name) ;
409      } catch (Exception e) {
410         throw new InternalServerError(e, "Could not parse header ''{0}''.", name);
411      }
412   }
413
414   /* Workhorse method */
415   private <T> T parse(HttpPartParser parser, HttpPartSchema schema, String val, ClassMeta<T> cm) throws SchemaValidationException, ParseException {
416      if (parser == null)
417         parser = this.parser;
418      return parser.createPartSession(req.getParserSessionArgs()).parse(HttpPartType.HEADER, schema, val, cm);
419   }
420
421   /**
422    * Returns a copy of this object but only with the specified header names copied.
423    *
424    * @param headers The headers to include in the copy.
425    * @return A new headers object.
426    */
427   public RequestHeaders subset(String...headers) {
428      RequestHeaders rh2 = new RequestHeaders(req).parser(parser).queryParams(queryParams);
429      for (String h : headers)
430         if (containsKey(h))
431            rh2.put(h, get(h));
432      return rh2;
433   }
434
435   /**
436    * Same as {@link #subset(String...)} but allows you to specify header names as a comma-delimited list.
437    *
438    * @param headers The headers to include in the copy.
439    * @return A new headers object.
440    */
441   public RequestHeaders subset(String headers) {
442      return subset(split(headers));
443   }
444
445   /**
446    * Returns the <code>Accept</code> header on the request.
447    *
448    * <p>
449    * Content-Types that are acceptable for the response.
450    *
451    * <h5 class='figure'>Example:</h5>
452    * <p class='bcode w800'>
453    *    Accept: text/plain
454    * </p>
455    *
456    * @return The parsed <code>Accept</code> header on the request, or <jk>null</jk> if not found.
457    */
458   public Accept getAccept() {
459      return Accept.forString(getString("Accept"));
460   }
461
462   /**
463    * Returns the <code>Accept-Charset</code> header on the request.
464    *
465    * <p>
466    * Character sets that are acceptable.
467    *
468    * <h5 class='figure'>Example:</h5>
469    * <p class='bcode w800'>
470    *    Accept-Charset: utf-8
471    * </p>
472    *
473    * @return The parsed <code>Accept-Charset</code> header on the request, or <jk>null</jk> if not found.
474    */
475   public AcceptCharset getAcceptCharset() {
476      return AcceptCharset.forString(getString("Accept-Charset"));
477   }
478
479   /**
480    * Returns the <code>Accept-Encoding</code> header on the request.
481    *
482    * <p>
483    * List of acceptable encodings.
484    *
485    * <h5 class='figure'>Example:</h5>
486    * <p class='bcode w800'>
487    *    Accept-Encoding: gzip, deflate
488    * </p>
489    *
490    * @return The parsed <code>Accept-Encoding</code> header on the request, or <jk>null</jk> if not found.
491    */
492   public AcceptEncoding getAcceptEncoding() {
493      return AcceptEncoding.forString(getString("Accept-Encoding"));
494   }
495
496   /**
497    * Returns the <code>Accept-Language</code> header on the request.
498    *
499    * <p>
500    * List of acceptable human languages for response.
501    *
502    * <h5 class='figure'>Example:</h5>
503    * <p class='bcode w800'>
504    *    Accept-Language: en-US
505    * </p>
506    *
507    * @return The parsed <code>Accept-Language</code> header on the request, or <jk>null</jk> if not found.
508    */
509   public AcceptLanguage getAcceptLanguage() {
510      return AcceptLanguage.forString(getString("Accept-Language"));
511   }
512
513   /**
514    * Returns the <code>Authorization</code> header on the request.
515    *
516    * <p>
517    * Authentication credentials for HTTP authentication.
518    *
519    * <h5 class='figure'>Example:</h5>
520    * <p class='bcode w800'>
521    *    Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
522    * </p>
523    *
524    * @return The parsed <code>Authorization</code> header on the request, or <jk>null</jk> if not found.
525    */
526   public Authorization getAuthorization() {
527      return Authorization.forString(getString("Authorization"));
528   }
529
530   /**
531    * Returns the <code>Cache-Control</code> header on the request.
532    *
533    * <p>
534    * Used to specify directives that must be obeyed by all caching mechanisms along the request-response chain.
535    *
536    * <h5 class='figure'>Example:</h5>
537    * <p class='bcode w800'>
538    *    Cache-Control: no-cache
539    * </p>
540    *
541    * @return The parsed <code>Cache-Control</code> header on the request, or <jk>null</jk> if not found.
542    */
543   public CacheControl getCacheControl() {
544      return CacheControl.forString(getString("Cache-Control"));
545   }
546
547   /**
548    * Returns the <code>Connection</code> header on the request.
549    *
550    * <p>
551    * Control options for the current connection and list of hop-by-hop request fields.
552    *
553    * <h5 class='figure'>Example:</h5>
554    * <p class='bcode w800'>
555    *    Connection: keep-alive
556    *    Connection: Upgrade
557    * </p>
558    *
559    * @return The parsed <code></code> header on the request, or <jk>null</jk> if not found.
560    */
561   public Connection getConnection() {
562      return Connection.forString(getString("Connection"));
563   }
564
565   /**
566    * Returns the <code>Content-Length</code> header on the request.
567    *
568    * <p>
569    * The length of the request body in octets (8-bit bytes).
570    *
571    * <h5 class='figure'>Example:</h5>
572    * <p class='bcode w800'>
573    *    Content-Length: 348
574    * </p>
575    *
576    * @return The parsed <code>Content-Length</code> header on the request, or <jk>null</jk> if not found.
577    */
578   public ContentLength getContentLength() {
579      return ContentLength.forString(getString("Content-Length"));
580   }
581
582   /**
583    * Returns the <code>Content-Type</code> header on the request.
584    *
585    * <p>
586    * The MIME type of the body of the request (used with POST and PUT requests).
587    *
588    * <h5 class='figure'>Example:</h5>
589    * <p class='bcode w800'>
590    *    Content-Type: application/x-www-form-urlencoded
591    * </p>
592    *
593    * @return The parsed <code>Content-Type</code> header on the request, or <jk>null</jk> if not found.
594    */
595   public ContentType getContentType() {
596      return ContentType.forString(getString("Content-Type"));
597   }
598
599   /**
600    * Returns the <code>Date</code> header on the request.
601    *
602    * <p>
603    * The date and time that the message was originated (in "HTTP-date" format as defined by RFC 7231 Date/Time Formats).
604    *
605    * <h5 class='figure'>Example:</h5>
606    * <p class='bcode w800'>
607    *    Date: Tue, 15 Nov 1994 08:12:31 GMT
608    * </p>
609    *
610    * @return The parsed <code>Date</code> header on the request, or <jk>null</jk> if not found.
611    */
612   public Date getDate() {
613      return Date.forString(getString("Date"));
614   }
615
616   /**
617    * Returns the <code>Expect</code> header on the request.
618    *
619    * <p>
620    * Indicates that particular server behaviors are required by the client.
621    *
622    * <h5 class='figure'>Example:</h5>
623    * <p class='bcode w800'>
624    *    Expect: 100-continue
625    * </p>
626    *
627    * @return The parsed <code>Expect</code> header on the request, or <jk>null</jk> if not found.
628    */
629   public Expect getExpect() {
630      return Expect.forString(getString("Expect"));
631   }
632
633   /**
634    * Returns the <code>From</code> header on the request.
635    *
636    * <p>
637    * The email address of the user making the request.
638    *
639    * <h5 class='figure'>Example:</h5>
640    * <p class='bcode w800'>
641    *    From: user@example.com
642    * </p>
643    *
644    * @return The parsed <code>From</code> header on the request, or <jk>null</jk> if not found.
645    */
646   public From getFrom() {
647      return From.forString(getString("From"));
648   }
649
650   /**
651    * Returns the <code>Host</code> header on the request.
652    *
653    * <p>
654    * The domain name of the server (for virtual hosting), and the TCP port number on which the server is listening.
655    * The port number may be omitted if the port is the standard port for the service requested.
656    *
657    * <h5 class='figure'>Example:</h5>
658    * <p class='bcode w800'>
659    *    Host: en.wikipedia.org:8080
660    *    Host: en.wikipedia.org
661    * </p>
662    *
663    * @return The parsed <code>Host</code> header on the request, or <jk>null</jk> if not found.
664    */
665   public Host getHost() {
666      return Host.forString(getString("Host"));
667   }
668
669   /**
670    * Returns the <code>If-Match</code> header on the request.
671    *
672    * <p>
673    * Only perform the action if the client supplied entity matches the same entity on the server.
674    * This is mainly for methods like PUT to only update a resource if it has not been modified since the user last
675    * updated it.
676    *
677    * <h5 class='figure'>Example:</h5>
678    * <p class='bcode w800'>
679    *    If-Match: "737060cd8c284d8af7ad3082f209582d"
680    * </p>
681    *
682    * @return The parsed <code>If-Match</code> header on the request, or <jk>null</jk> if not found.
683    */
684   public IfMatch getIfMatch() {
685      return IfMatch.forString(getString("If-Match"));
686   }
687
688   /**
689    * Returns the <code>If-Modified-Since</code> header on the request.
690    *
691    * <p>
692    * Allows a 304 Not Modified to be returned if content is unchanged.
693    *
694    * <h5 class='figure'>Example:</h5>
695    * <p class='bcode w800'>
696    *    If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT
697    * </p>
698    *
699    * @return The parsed <code>If-Modified-Since</code> header on the request, or <jk>null</jk> if not found.
700    */
701   public IfModifiedSince getIfModifiedSince() {
702      return IfModifiedSince.forString(getString("If-Modified-Since"));
703   }
704
705   /**
706    * Returns the <code>If-None-Match</code> header on the request.
707    *
708    * <p>
709    * Allows a 304 Not Modified to be returned if content is unchanged, see HTTP ETag.
710    *
711    * <h5 class='figure'>Example:</h5>
712    * <p class='bcode w800'>
713    *    If-None-Match: "737060cd8c284d8af7ad3082f209582d"
714    * </p>
715    *
716    * @return The parsed <code>If-None-Match</code> header on the request, or <jk>null</jk> if not found.
717    */
718   public IfNoneMatch getIfNoneMatch() {
719      return IfNoneMatch.forString(getString("If-None-Match"));
720   }
721
722   /**
723    * Returns the <code>If-Range</code> header on the request.
724    *
725    * <p>
726    * If the entity is unchanged, send me the part(s) that I am missing; otherwise, send me the entire new entity.
727    *
728    * <h5 class='figure'>Example:</h5>
729    * <p class='bcode w800'>
730    *    If-Range: "737060cd8c284d8af7ad3082f209582d"
731    * </p>
732    *
733    * @return The parsed <code>If-Range</code> header on the request, or <jk>null</jk> if not found.
734    */
735   public IfRange getIfRange() {
736      return IfRange.forString(getString("If-Range"));
737   }
738
739   /**
740    * Returns the <code>If-Unmodified-Since</code> header on the request.
741    *
742    * <p>
743    * Only send the response if the entity has not been modified since a specific time.
744    *
745    * <h5 class='figure'>Example:</h5>
746    * <p class='bcode w800'>
747    *    If-Unmodified-Since: Sat, 29 Oct 1994 19:43:31 GMT
748    * </p>
749    *
750    * @return The parsed <code>If-Unmodified-Since</code> header on the request, or <jk>null</jk> if not found.
751    */
752   public IfUnmodifiedSince getIfUnmodifiedSince() {
753      return IfUnmodifiedSince.forString(getString("If-Unmodified-Since"));
754   }
755
756   /**
757    * Returns the <code>Max-Forwards</code> header on the request.
758    *
759    * <p>
760    * Limit the number of times the message can be forwarded through proxies or gateways.
761    *
762    * <h5 class='figure'>Example:</h5>
763    * <p class='bcode w800'>
764    *    Max-Forwards: 10
765    * </p>
766    *
767    * @return The parsed <code>Max-Forwards</code> header on the request, or <jk>null</jk> if not found.
768    */
769   public MaxForwards getMaxForwards() {
770      return MaxForwards.forString(getString("Max-Forwards"));
771   }
772
773   /**
774    * Returns the <code>Pragma</code> header on the request.
775    *
776    * <p>
777    * Implementation-specific fields that may have various effects anywhere along the request-response chain.
778    *
779    * <h5 class='figure'>Example:</h5>
780    * <p class='bcode w800'>
781    *    Pragma: no-cache
782    * </p>
783    *
784    * @return The parsed <code>Pragma</code> header on the request, or <jk>null</jk> if not found.
785    */
786   public Pragma getPragma() {
787      return Pragma.forString(getString("Pragma"));
788   }
789
790   /**
791    * Returns the <code>Proxy-Authorization</code> header on the request.
792    *
793    * <p>
794    * Authorization credentials for connecting to a proxy.
795    *
796    * <h5 class='figure'>Example:</h5>
797    * <p class='bcode w800'>
798    *    Proxy-Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
799    * </p>
800    *
801    * @return The parsed <code>Proxy-Authorization</code> header on the request, or <jk>null</jk> if not found.
802    */
803   public ProxyAuthorization getProxyAuthorization() {
804      return ProxyAuthorization.forString(getString("Proxy-Authorization"));
805   }
806
807   /**
808    * Returns the <code>Range</code> header on the request.
809    *
810    * <p>
811    * Request only part of an entity. Bytes are numbered from 0.
812    *
813    * <h5 class='figure'>Example:</h5>
814    * <p class='bcode w800'>
815    *    Range: bytes=500-999
816    * </p>
817    *
818    * @return The parsed <code>Range</code> header on the request, or <jk>null</jk> if not found.
819    */
820   public Range getRange() {
821      return Range.forString(getString("Range"));
822   }
823
824   /**
825    * Returns the <code>Referer</code> header on the request.
826    *
827    * <p>
828    * This is the address of the previous web page from which a link to the currently requested page was followed.
829    *
830    * <h5 class='figure'>Example:</h5>
831    * <p class='bcode w800'>
832    *    Referer: http://en.wikipedia.org/wiki/Main_Page
833    * </p>
834    *
835    * @return The parsed <code>Referer</code> header on the request, or <jk>null</jk> if not found.
836    */
837   public Referer getReferer() {
838      return Referer.forString(getString("Referer"));
839   }
840
841   /**
842    * Returns the <code>TE</code> header on the request.
843    *
844    * <p>
845    * The transfer encodings the user agent is willing to accept: the same values as for the response header field
846    * Transfer-Encoding can be used, plus the "trailers" value (related to the "chunked" transfer method) to notify the
847    * server it expects to receive additional fields in the trailer after the last, zero-sized, chunk.
848    *
849    * <h5 class='figure'>Example:</h5>
850    * <p class='bcode w800'>
851    *    TE: trailers, deflate
852    * </p>
853    *
854    * @return The parsed <code>TE</code> header on the request, or <jk>null</jk> if not found.
855    */
856   public TE getTE() {
857      return TE.forString(getString("TE"));
858   }
859
860   /**
861    * Returns the <code>Time-Zone</code> header value on the request if there is one.
862    *
863    * <p>
864    * Example: <js>"GMT"</js>.
865    *
866    * @return The <code>Time-Zone</code> header value on the request, or <jk>null</jk> if not present.
867    */
868   public TimeZone getTimeZone() {
869      String tz = getString("Time-Zone");
870      if (tz != null)
871         return TimeZone.getTimeZone(tz);
872      return null;
873   }
874
875   /**
876    * Returns the <code>User-Agent</code> header on the request.
877    *
878    * <p>
879    * The user agent string of the user agent.
880    *
881    * <h5 class='figure'>Example:</h5>
882    * <p class='bcode w800'>
883    *    User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:12.0) Gecko/20100101 Firefox/21.0
884    * </p>
885    *
886    * @return The parsed <code>User-Agent</code> header on the request, or <jk>null</jk> if not found.
887    */
888   public UserAgent getUserAgent() {
889      return UserAgent.forString(getString("User-Agent"));
890   }
891
892   /**
893    * Returns the <code>Upgrade</code> header on the request.
894    *
895    * <p>
896    * Ask the server to upgrade to another protocol.
897    *
898    * <h5 class='figure'>Example:</h5>
899    * <p class='bcode w800'>
900    *    Upgrade: HTTP/2.0, HTTPS/1.3, IRC/6.9, RTA/x11, websocket
901    * </p>
902    *
903    * @return The parsed <code>Upgrade</code> header on the request, or <jk>null</jk> if not found.
904    */
905   public Upgrade getUpgrade() {
906      return Upgrade.forString(getString("Upgrade"));
907   }
908
909   /**
910    * Returns the <code>Via</code> header on the request.
911    *
912    * <p>
913    * Informs the server of proxies through which the request was sent.
914    *
915    * <h5 class='figure'>Example:</h5>
916    * <p class='bcode w800'>
917    *    Via: 1.0 fred, 1.1 example.com (Apache/1.1)
918    * </p>
919    *
920    * @return The parsed <code>Via</code> header on the request, or <jk>null</jk> if not found.
921    */
922   public Via getVia() {
923      return Via.forString(getString("Via"));
924   }
925
926   /**
927    * Returns the <code>Warning</code> header on the request.
928    *
929    * <p>
930    * A general warning about possible problems with the entity body.
931    *
932    * <h5 class='figure'>Example:</h5>
933    * <p class='bcode w800'>
934    *    Warning: 199 Miscellaneous warning
935    * </p>
936    *
937    * @return The parsed <code>Warning</code> header on the request, or <jk>null</jk> if not found.
938    */
939   public Warning getWarning() {
940      return Warning.forString(getString("Warning"));
941   }
942
943   /**
944    * Converts the headers to a readable string.
945    *
946    * @param sorted Sort the headers by name.
947    * @return A JSON string containing the contents of the headers.
948    */
949   public String toString(boolean sorted) {
950      Map<String,Object> m = (sorted ? new TreeMap<String,Object>() : new LinkedHashMap<String,Object>());
951      for (Map.Entry<String,String[]> e : this.entrySet()) {
952         String[] v = e.getValue();
953         m.put(e.getKey(), v.length == 1 ? v[0] : v);
954      }
955      return SimpleJsonSerializer.DEFAULT.toString(m);
956   }
957
958   @Override /* Object */
959   public String toString() {
960      return toString(false);
961   }
962
963   //-----------------------------------------------------------------------------------------------------------------
964   // Helper methods
965   //-----------------------------------------------------------------------------------------------------------------
966
967   private <T> ClassMeta<T> getClassMeta(Type type, Type...args) {
968      return req.getBeanSession().getClassMeta(type, args);
969   }
970
971   private <T> ClassMeta<T> getClassMeta(Class<T> type) {
972      return req.getBeanSession().getClassMeta(type);
973   }
974
975   /**
976    * @deprecated Use {@link #get(HttpPartParser, HttpPartSchema, String, Class)}
977    */
978   @SuppressWarnings({ "javadoc", "unused" })
979   @Deprecated
980   public <T> T get(HttpPartParser parser, String name, Class<T> type) throws ParseException {
981      return get(parser, null, name, type);
982   }
983
984   /**
985    * @deprecated Use {@link #get(HttpPartParser, HttpPartSchema, String, Object, Class)}
986    */
987   @SuppressWarnings({ "javadoc", "unused" })
988   @Deprecated
989   public <T> T get(HttpPartParser parser, String name, T def, Class<T> type) throws ParseException {
990      return get(parser, null, name, def, type);
991   }
992
993   /**
994    * @deprecated Use {@link #get(HttpPartParser, HttpPartSchema, String, Type, Type...)}
995    */
996   @SuppressWarnings({ "javadoc", "unused" })
997   @Deprecated
998   public <T> T get(HttpPartParser parser, String name, Type type, Type...args) throws ParseException {
999      return get(parser, null, name, type, args);
1000   }
1001}