juneau-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jamesbog...@apache.org
Subject [2/3] incubator-juneau git commit: Break up RestRequest into different functional classes.
Date Sun, 07 May 2017 20:16:14 GMT
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/321f6bde/juneau-rest/src/main/java/org/apache/juneau/rest/RequestHeaders.java
----------------------------------------------------------------------
diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/RequestHeaders.java b/juneau-rest/src/main/java/org/apache/juneau/rest/RequestHeaders.java
new file mode 100644
index 0000000..b0617bd
--- /dev/null
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/RequestHeaders.java
@@ -0,0 +1,675 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.http.*;
+import org.apache.juneau.http.Date;
+import org.apache.juneau.internal.*;
+import org.apache.juneau.parser.*;
+import org.apache.juneau.urlencoding.*;
+
+/**
+ * Represents the headers in an HTTP request.
+ * <p>
+ * Entries are stored in a case-insensitive map.
+ */
+public class RequestHeaders extends TreeMap<String,String[]> {
+	private static final long serialVersionUID = 1L;
+
+	private UrlEncodingParser parser;
+	private BeanSession beanSession;
+	private RequestQuery queryParams;
+
+	RequestHeaders() {
+		super(String.CASE_INSENSITIVE_ORDER);
+	}
+
+	RequestHeaders setParser(UrlEncodingParser parser) {
+		this.parser = parser;
+		return this;
+	}
+
+	RequestHeaders setBeanSession(BeanSession beanSession) {
+		this.beanSession = beanSession;
+		return this;
+	}
+
+	RequestHeaders setQueryParams(RequestQuery queryParams) {
+		this.queryParams = queryParams;
+		return this;
+	}
+
+	/**
+	 * Adds default entries to these headers.
+	 * <p>
+	 * This includes the default headers defined on the servlet and method levels.
+	 *
+	 * @param defaultEntries The default entries.  Can be <jk>null</jk>.
+	 * @return This object (for method chaining).
+	 */
+	public RequestHeaders addDefault(Map<String,String> defaultEntries) {
+		if (defaultEntries != null) {
+			for (Map.Entry<String,String> e : defaultEntries.entrySet()) {
+				String key = e.getKey(), value = e.getValue();
+				String[] v = get(key);
+				if (v == null)
+					put(key, new String[]{value});
+			}
+		}
+		return this;
+	}
+
+	/**
+	 * Adds a set of header values to this object.
+	 *
+	 * @param name The header name.
+	 * @param values The header values.
+	 * @return This object (for method chaining).
+	 */
+	public RequestHeaders put(String name, Enumeration<String> values) {
+		// Optimized for enumerations of one entry, the most-common case.
+		if (values.hasMoreElements()) {
+			String v = values.nextElement();
+			if (! v.isEmpty()) {
+				String[] s = new String[]{v};
+				while (values.hasMoreElements())
+					s = ArrayUtils.append(s, values.nextElement());
+				put(name, s);
+			}
+		}
+		return this;
+	}
+
+	/**
+	 * Returns the specified header value, or <jk>null</jk> if the header doesn't exist.
+	 * <p>
+	 * If {@code allowHeaderParams} init parameter is <jk>true</jk>, then first looks for {@code &HeaderName=x} in the URL query string.
+	 * <p>
+	 * @param name The header name.
+	 * @return The header value, or <jk>null</jk> if it doesn't exist.
+	 */
+	public String getFirst(String name) {
+		return getFirst(name, null);
+	}
+
+	/**
+	 * Returns the specified header value, or a default value if the header doesn't exist.
+	 * <p>
+	 * If {@code allowHeaderParams} init parameter is <jk>true</jk>, then first looks for {@code &HeaderName=x} in the URL query string.
+	 *
+	 * @param name The HTTP header name.
+	 * @param def The default value to return if the header value isn't found.
+	 * @return The header value, or the default value if the header isn't present.
+	 */
+	public String getFirst(String name, String def) {
+		String[] v = null;
+		if (queryParams != null)
+			v = queryParams.get(name);
+		if (v == null || v.length == 0)
+			v = get(name);
+		if (v == null || v.length == 0)
+			return def;
+		return v[0];
+	}
+
+	/**
+	 * Sets a request header value.
+	 *
+	 * @param name The header name.
+	 * @param value The header value.
+	 */
+	public void put(String name, Object value) {
+		super.put(name, new String[]{StringUtils.toString(value)});
+	}
+
+	/**
+	 * Returns the specified header value converted to a POJO.
+	 * <p>
+	 * The type can be any POJO type convertable from a <code>String</code>
+	 * (See <a class="doclink" href="package-summary.html#PojosConvertableFromString">POJOs Convertable From Strings</a>).
+	 * <p>
+	 * <h5 class='section'>Examples:</h5>
+	 * <p class='bcode'>
+	 * 	<jc>// Parse into an integer.</jc>
+	 * 	<jk>int</jk> myheader = req.getHeader(<js>"My-Header"</js>, <jk>int</jk>.<jk>class</jk>);
+	 *
+	 * 	<jc>// Parse a UUID.</jc>
+	 * 	UUID myheader = req.getHeader(<js>"My-Header"</js>, UUID.<jk>class</jk>);
+	 * </p>
+	 *
+	 * @param name The HTTP header name.
+	 * @param type The class type to convert the header value to.
+	 * @param <T> The class type to convert the header value to.
+	 * @return The parameter value converted to the specified class type.
+	 */
+	public <T> T get(String name, Class<T> type) {
+		String h = getFirst(name);
+		return beanSession.convertToType(h, type);
+	}
+
+	/**
+	 * Same as {@link #get(String, Class)} but returns a default value if not found.
+	 *
+	 * @param name The HTTP header name.
+	 * @param def The default value if the header was not specified or is <jk>null</jk>.
+	 * @param type The class type to convert the header value to.
+	 * @param <T> The class type to convert the header value to.
+	 * @return The parameter value converted to the specified class type.
+	 */
+	public <T> T get(String name, T def, Class<T> type) {
+		String h = getFirst(name);
+		if (h == null)
+			return def;
+		return beanSession.convertToType(h, type);
+	}
+
+	/**
+	 * Returns the specified header value converted to a POJO.
+	 * <p>
+	 * The type can be any POJO type convertable from a <code>String</code>
+	 * (See <a class="doclink" href="package-summary.html#PojosConvertableFromString">POJOs Convertable From Strings</a>).
+	 * <p>
+	 * <h5 class='section'>Examples:</h5>
+	 * <p class='bcode'>
+	 * 	<jc>// Parse into a linked-list of strings.</jc>
+	 * 	List&lt;String&gt; myheader = req.getHeader(<js>"My-Header"</js>, LinkedList.<jk>class</jk>, String.<jk>class</jk>);
+	 * </p>
+	 *
+	 * @param name The HTTP header name.
+	 * @param type The type of object to create.
+	 * 	<br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
+	 * @param args The type arguments of the class if it's a collection or map.
+	 * 	<br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
+	 * 	<br>Ignored if the main type is not a map or collection.
+	 * @param <T> The class type to convert the header value to.
+	 * @return The parameter value converted to the specified class type.
+	 * @throws ParseException If the header could not be converted to the specified type.
+	 */
+	public <T> T get(String name, Type type, Type...args) throws ParseException {
+		String h = getFirst(name);
+		return parser.parsePart(h, type, args);
+	}
+
+	/**
+	 * Returns the <code>Accept</code> header on the request.
+	 * <p>
+	 * Content-Types that are acceptable for the response.
+	 *
+	 * <h6 class='figure'>Example:</h6>
+	 * <p class='bcode'>
+	 * 	Accept: text/plain
+	 * </p>
+	 *
+	 * @return The parsed <code>Accept</code> header on the request, or <jk>null</jk> if not found.
+	 *
+	 */
+	public Accept getAccept() {
+		return Accept.forString(getFirst("Accept"));
+	}
+
+	/**
+	 * Returns the <code>Accept-Charset</code> header on the request.
+	 * <p>
+	 * Character sets that are acceptable.
+	 *
+	 * <h6 class='figure'>Example:</h6>
+	 * <p class='bcode'>
+	 * 	Accept-Charset: utf-8
+	 * </p>
+	 *
+	 * @return The parsed <code>Accept-Charset</code> header on the request, or <jk>null</jk> if not found.
+	 */
+	public AcceptCharset getAcceptCharset() {
+		return AcceptCharset.forString(getFirst("Accept-Charset"));
+	}
+
+	/**
+	 * Returns the <code>Accept-Encoding</code> header on the request.
+	 * <p>
+	 * List of acceptable encodings.
+	 *
+	 * <h6 class='figure'>Example:</h6>
+	 * <p class='bcode'>
+	 * 	Accept-Encoding: gzip, deflate
+	 * </p>
+	 *
+	 * @return The parsed <code>Accept-Encoding</code> header on the request, or <jk>null</jk> if not found.
+	 */
+	public AcceptEncoding getAcceptEncoding() {
+		return AcceptEncoding.forString(getFirst("Accept-Encoding"));
+	}
+
+	/**
+	 * Returns the <code>Accept-Language</code> header on the request.
+	 * <p>
+	 * List of acceptable human languages for response.
+	 *
+	 * <h6 class='figure'>Example:</h6>
+	 * <p class='bcode'>
+	 * 	Accept-Language: en-US
+	 * </p>
+	 *
+	 * @return The parsed <code>Accept-Language</code> header on the request, or <jk>null</jk> if not found.
+	 */
+	public AcceptLanguage getAcceptLanguage() {
+		return AcceptLanguage.forString(getFirst("Accept-Language"));
+	}
+
+	/**
+	 * Returns the <code>Authorization</code> header on the request.
+	 * <p>
+	 * Authentication credentials for HTTP authentication.
+	 *
+	 * <h6 class='figure'>Example:</h6>
+	 * <p class='bcode'>
+	 * 	Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
+	 * </p>
+	 *
+	 * @return The parsed <code>Authorization</code> header on the request, or <jk>null</jk> if not found.
+	 */
+	public Authorization getAuthorization() {
+		return Authorization.forString(getFirst("Authorization"));
+	}
+
+	/**
+	 * Returns the <code>Cache-Control</code> header on the request.
+	 * <p>
+	 * Used to specify directives that must be obeyed by all caching mechanisms along the request-response chain.
+	 *
+	 * <h6 class='figure'>Example:</h6>
+	 * <p class='bcode'>
+	 * 	Cache-Control: no-cache
+	 * </p>
+	 *
+	 * @return The parsed <code>Cache-Control</code> header on the request, or <jk>null</jk> if not found.
+	 */
+	public CacheControl getCacheControl() {
+		return CacheControl.forString(getFirst("Cache-Control"));
+	}
+
+	/**
+	 * Returns the <code>Connection</code> header on the request.
+	 * <p>
+	 * Control options for the current connection and list of hop-by-hop request fields.
+	 *
+	 * <h6 class='figure'>Example:</h6>
+	 * <p class='bcode'>
+	 * 	Connection: keep-alive
+	 * 	Connection: Upgrade
+	 * </p>
+	 *
+	 * @return The parsed <code></code> header on the request, or <jk>null</jk> if not found.
+	 */
+	public Connection getConnection() {
+		return Connection.forString(getFirst("Connection"));
+	}
+
+	/**
+	 * Returns the <code>Content-Length</code> header on the request.
+	 * <p>
+	 * The length of the request body in octets (8-bit bytes).
+	 *
+	 * <h6 class='figure'>Example:</h6>
+	 * <p class='bcode'>
+	 * 	Content-Length: 348
+	 * </p>
+	 *
+	 * @return The parsed <code>Content-Length</code> header on the request, or <jk>null</jk> if not found.
+	 */
+	public ContentLength getContentLength() {
+		return ContentLength.forString(getFirst("Content-Length"));
+	}
+
+	/**
+	 * Returns the <code>Content-Type</code> header on the request.
+	 * <p>
+	 * The MIME type of the body of the request (used with POST and PUT requests).
+	 *
+	 * <h6 class='figure'>Example:</h6>
+	 * <p class='bcode'>
+	 * 	Content-Type: application/x-www-form-urlencoded
+	 * </p>
+	 *
+	 * @return The parsed <code>Content-Type</code> header on the request, or <jk>null</jk> if not found.
+	 */
+	public ContentType getContentType() {
+		return ContentType.forString(getFirst("Content-Type"));
+	}
+
+	/**
+	 * Returns the <code>Date</code> header on the request.
+	 * <p>
+	 * The date and time that the message was originated (in "HTTP-date" format as defined by RFC 7231 Date/Time Formats).
+	 *
+	 * <h6 class='figure'>Example:</h6>
+	 * <p class='bcode'>
+	 * 	Date: Tue, 15 Nov 1994 08:12:31 GMT
+	 * </p>
+	 *
+	 * @return The parsed <code>Date</code> header on the request, or <jk>null</jk> if not found.
+	 */
+	public Date getDate() {
+		return Date.forString(getFirst("Date"));
+	}
+
+	/**
+	 * Returns the <code>Expect</code> header on the request.
+	 * <p>
+	 * Indicates that particular server behaviors are required by the client.
+	 *
+	 * <h6 class='figure'>Example:</h6>
+	 * <p class='bcode'>
+	 * 	Expect: 100-continue
+	 * </p>
+	 *
+	 * @return The parsed <code>Expect</code> header on the request, or <jk>null</jk> if not found.
+	 */
+	public Expect getExpect() {
+		return Expect.forString(getFirst("Expect"));
+	}
+
+	/**
+	 * Returns the <code>From</code> header on the request.
+	 * <p>
+	 * The email address of the user making the request.
+	 *
+	 * <h6 class='figure'>Example:</h6>
+	 * <p class='bcode'>
+	 * 	From: user@example.com
+	 * </p>
+	 *
+	 * @return The parsed <code>From</code> header on the request, or <jk>null</jk> if not found.
+	 */
+	public From getFrom() {
+		return From.forString(getFirst("From"));
+	}
+
+	/**
+	 * Returns the <code>Host</code> header on the request.
+	 * <p>
+	 * The domain name of the server (for virtual hosting), and the TCP port number on which the server is listening.
+	 * The port number may be omitted if the port is the standard port for the service requested.
+	 *
+	 * <h6 class='figure'>Example:</h6>
+	 * <p class='bcode'>
+	 * 	Host: en.wikipedia.org:8080
+	 * 	Host: en.wikipedia.org
+	 * </p>
+	 *
+	 * @return The parsed <code>Host</code> header on the request, or <jk>null</jk> if not found.
+	 */
+	public Host getHost() {
+		return Host.forString(getFirst("Host"));
+	}
+
+	/**
+	 * Returns the <code>If-Match</code> header on the request.
+	 * <p>
+	 * Only perform the action if the client supplied entity matches the same entity on the server.
+	 * This is mainly for methods like PUT to only update a resource if it has not been modified since the user last updated it.
+	 *
+	 * <h6 class='figure'>Example:</h6>
+	 * <p class='bcode'>
+	 * 	If-Match: "737060cd8c284d8af7ad3082f209582d"
+	 * </p>
+	 *
+	 * @return The parsed <code>If-Match</code> header on the request, or <jk>null</jk> if not found.
+	 */
+	public IfMatch getIfMatch() {
+		return IfMatch.forString(getFirst("If-Match"));
+	}
+
+	/**
+	 * Returns the <code>If-Modified-Since</code> header on the request.
+	 * <p>
+	 * Allows a 304 Not Modified to be returned if content is unchanged.
+	 *
+	 * <h6 class='figure'>Example:</h6>
+	 * <p class='bcode'>
+	 * 	If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT
+	 * </p>
+	 *
+	 * @return The parsed <code>If-Modified-Since</code> header on the request, or <jk>null</jk> if not found.
+	 */
+	public IfModifiedSince getIfModifiedSince() {
+		return IfModifiedSince.forString(getFirst("If-Modified-Since"));
+	}
+
+	/**
+	 * Returns the <code>If-None-Match</code> header on the request.
+	 * <p>
+	 * Allows a 304 Not Modified to be returned if content is unchanged, see HTTP ETag.
+	 *
+	 * <h6 class='figure'>Example:</h6>
+	 * <p class='bcode'>
+	 * 	If-None-Match: "737060cd8c284d8af7ad3082f209582d"
+	 * </p>
+	 *
+	 * @return The parsed <code>If-None-Match</code> header on the request, or <jk>null</jk> if not found.
+	 */
+	public IfNoneMatch getIfNoneMatch() {
+		return IfNoneMatch.forString(getFirst("If-None-Match"));
+	}
+
+	/**
+	 * Returns the <code>If-Range</code> header on the request.
+	 * <p>
+	 * If the entity is unchanged, send me the part(s) that I am missing; otherwise, send me the entire new entity.
+	 *
+	 * <h6 class='figure'>Example:</h6>
+	 * <p class='bcode'>
+	 * 	If-Range: "737060cd8c284d8af7ad3082f209582d"
+	 * </p>
+	 *
+	 * @return The parsed <code>If-Range</code> header on the request, or <jk>null</jk> if not found.
+	 */
+	public IfRange getIfRange() {
+		return IfRange.forString(getFirst("If-Range"));
+	}
+
+	/**
+	 * Returns the <code>If-Unmodified-Since</code> header on the request.
+	 * <p>
+	 * Only send the response if the entity has not been modified since a specific time.
+	 *
+	 * <h6 class='figure'>Example:</h6>
+	 * <p class='bcode'>
+	 * 	If-Unmodified-Since: Sat, 29 Oct 1994 19:43:31 GMT
+	 * </p>
+	 *
+	 * @return The parsed <code>If-Unmodified-Since</code> header on the request, or <jk>null</jk> if not found.
+	 */
+	public IfUnmodifiedSince getIfUnmodifiedSince() {
+		return IfUnmodifiedSince.forString(getFirst("If-Unmodified-Since"));
+	}
+
+	/**
+	 * Returns the <code>Max-Forwards</code> header on the request.
+	 * <p>
+	 * Limit the number of times the message can be forwarded through proxies or gateways.
+	 *
+	 * <h6 class='figure'>Example:</h6>
+	 * <p class='bcode'>
+	 * 	Max-Forwards: 10
+	 * </p>
+	 *
+	 * @return The parsed <code>Max-Forwards</code> header on the request, or <jk>null</jk> if not found.
+	 */
+	public MaxForwards getMaxForwards() {
+		return MaxForwards.forString(getFirst("Max-Forwards"));
+	}
+
+	/**
+	 * Returns the <code>Pragma</code> header on the request.
+	 * <p>
+	 * Implementation-specific fields that may have various effects anywhere along the request-response chain.
+	 *
+	 * <h6 class='figure'>Example:</h6>
+	 * <p class='bcode'>
+	 * 	Pragma: no-cache
+	 * </p>
+	 *
+	 * @return The parsed <code>Pragma</code> header on the request, or <jk>null</jk> if not found.
+	 */
+	public Pragma getPragma() {
+		return Pragma.forString(getFirst("Pragma"));
+	}
+
+	/**
+	 * Returns the <code>Proxy-Authorization</code> header on the request.
+	 * <p>
+	 * Authorization credentials for connecting to a proxy.
+	 *
+	 * <h6 class='figure'>Example:</h6>
+	 * <p class='bcode'>
+	 * 	Proxy-Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
+	 * </p>
+	 *
+	 * @return The parsed <code>Proxy-Authorization</code> header on the request, or <jk>null</jk> if not found.
+	 */
+	public ProxyAuthorization getProxyAuthorization() {
+		return ProxyAuthorization.forString(getFirst("Proxy-Authorization"));
+	}
+
+	/**
+	 * Returns the <code>Range</code> header on the request.
+	 * <p>
+	 * Request only part of an entity. Bytes are numbered from 0.
+	 *
+	 * <h6 class='figure'>Example:</h6>
+	 * <p class='bcode'>
+	 * 	Range: bytes=500-999
+	 * </p>
+	 *
+	 * @return The parsed <code>Range</code> header on the request, or <jk>null</jk> if not found.
+	 */
+	public Range getRange() {
+		return Range.forString(getFirst("Range"));
+	}
+
+	/**
+	 * Returns the <code>Referer</code> header on the request.
+	 * <p>
+	 * This is the address of the previous web page from which a link to the currently requested page was followed.
+	 *
+	 * <h6 class='figure'>Example:</h6>
+	 * <p class='bcode'>
+	 * 	Referer: http://en.wikipedia.org/wiki/Main_Page
+	 * </p>
+	 *
+	 * @return The parsed <code>Referer</code> header on the request, or <jk>null</jk> if not found.
+	 */
+	public Referer getReferer() {
+		return Referer.forString(getFirst("Referer"));
+	}
+
+	/**
+	 * Returns the <code>TE</code> header on the request.
+	 * <p>
+	 * The transfer encodings the user agent is willing to accept: the same values as for the response header field
+	 * Transfer-Encoding can be used, plus the "trailers" value (related to the "chunked" transfer method) to notify the
+	 * server it expects to receive additional fields in the trailer after the last, zero-sized, chunk.
+	 *
+	 * <h6 class='figure'>Example:</h6>
+	 * <p class='bcode'>
+	 * 	TE: trailers, deflate
+	 * </p>
+	 *
+	 * @return The parsed <code>TE</code> header on the request, or <jk>null</jk> if not found.
+	 */
+	public TE getTE() {
+		return TE.forString(getFirst("TE"));
+	}
+
+	/**
+	 * Returns the <code>Time-Zone</code> header value on the request if there is one.
+	 * <p>
+	 * Example: <js>"GMT"</js>.
+	 *
+	 * @return The <code>Time-Zone</code> header value on the request, or <jk>null</jk> if not present.
+	 */
+	public TimeZone getTimeZone() {
+		String tz = getFirst("Time-Zone");
+		if (tz != null)
+			return TimeZone.getTimeZone(tz);
+		return null;
+	}
+
+	/**
+	 * Returns the <code>User-Agent</code> header on the request.
+	 * <p>
+	 * The user agent string of the user agent.
+	 *
+	 * <h6 class='figure'>Example:</h6>
+	 * <p class='bcode'>
+	 * 	User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:12.0) Gecko/20100101 Firefox/21.0
+	 * </p>
+	 *
+	 * @return The parsed <code>User-Agent</code> header on the request, or <jk>null</jk> if not found.
+	 */
+	public UserAgent getUserAgent() {
+		return UserAgent.forString(getFirst("User-Agent"));
+	}
+
+	/**
+	 * Returns the <code>Upgrade</code> header on the request.
+	 * <p>
+	 * Ask the server to upgrade to another protocol.
+	 *
+	 * <h6 class='figure'>Example:</h6>
+	 * <p class='bcode'>
+	 * 	Upgrade: HTTP/2.0, HTTPS/1.3, IRC/6.9, RTA/x11, websocket
+	 * </p>
+	 *
+	 * @return The parsed <code>Upgrade</code> header on the request, or <jk>null</jk> if not found.
+	 */
+	public Upgrade getUpgrade() {
+		return Upgrade.forString(getFirst("Upgrade"));
+	}
+
+	/**
+	 * Returns the <code>Via</code> header on the request.
+	 * <p>
+	 * Informs the server of proxies through which the request was sent.
+	 *
+	 * <h6 class='figure'>Example:</h6>
+	 * <p class='bcode'>
+	 * 	Via: 1.0 fred, 1.1 example.com (Apache/1.1)
+	 * </p>
+	 *
+	 * @return The parsed <code>Via</code> header on the request, or <jk>null</jk> if not found.
+	 */
+	public Via getVia() {
+		return Via.forString(getFirst("Via"));
+	}
+
+	/**
+	 * Returns the <code>Warning</code> header on the request.
+	 * <p>
+	 * A general warning about possible problems with the entity body.
+	 *
+	 * <h6 class='figure'>Example:</h6>
+	 * <p class='bcode'>
+	 * 	Warning: 199 Miscellaneous warning
+	 * </p>
+	 *
+	 * @return The parsed <code>Warning</code> header on the request, or <jk>null</jk> if not found.
+	 */
+	public Warning getWarning() {
+		return Warning.forString(getFirst("Warning"));
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/321f6bde/juneau-rest/src/main/java/org/apache/juneau/rest/RequestPathParams.java
----------------------------------------------------------------------
diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/RequestPathParams.java b/juneau-rest/src/main/java/org/apache/juneau/rest/RequestPathParams.java
new file mode 100644
index 0000000..8a12a0e
--- /dev/null
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/RequestPathParams.java
@@ -0,0 +1,137 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.parser.*;
+import org.apache.juneau.urlencoding.*;
+
+/**
+ * Represents the path parameters on an HTTP request.
+ */
+@SuppressWarnings("unchecked")
+public class RequestPathParams extends TreeMap<String,String> {
+	private static final long serialVersionUID = 1L;
+
+	private UrlEncodingParser parser;
+	private BeanSession beanSession;
+
+	RequestPathParams() {
+		super(String.CASE_INSENSITIVE_ORDER);
+	}
+
+	RequestPathParams setParser(UrlEncodingParser parser) {
+		this.parser = parser;
+		return this;
+	}
+
+	RequestPathParams setBeanSession(BeanSession beanSession) {
+		this.beanSession = beanSession;
+		return this;
+	}
+
+	/**
+	 * Sets a request query parameter value.
+	 *
+	 * @param name The parameter name.
+	 * @param value The parameter value.
+	 */
+	public void put(String name, Object value) {
+		put(name, value);
+	}
+
+	/**
+	 * Returns the specified path parameter converted to a POJO.
+	 * <p>
+	 * The type can be any POJO type convertable from a <code>String</code> (See <a class="doclink" 
+	 * href="package-summary.html#PojosConvertableFromString">POJOs Convertable From Strings</a>).
+	 * <p>
+	 * <h5 class='section'>Examples:</h5>
+	 * <p class='bcode'>
+	 * 	<jc>// Parse into an integer.</jc>
+	 * 	<jk>int</jk> myparam = req.getPathParameter(<js>"myparam"</js>, <jk>int</jk>.<jk>class</jk>);
+	 *
+	 * 	<jc>// Parse into an int array.</jc>
+	 * 	<jk>int</jk>[] myparam = req.getPathParameter(<js>"myparam"</js>, <jk>int</jk>[].<jk>class</jk>);
+
+	 * 	<jc>// Parse into a bean.</jc>
+	 * 	MyBean myparam = req.getPathParameter(<js>"myparam"</js>, MyBean.<jk>class</jk>);
+	 *
+	 * 	<jc>// Parse into a linked-list of objects.</jc>
+	 * 	List myparam = req.getPathParameter(<js>"myparam"</js>, LinkedList.<jk>class</jk>);
+	 *
+	 * 	<jc>// Parse into a map of object keys/values.</jc>
+	 * 	Map myparam = req.getPathParameter(<js>"myparam"</js>, TreeMap.<jk>class</jk>);
+	 * </p>
+	 *
+	 * @param name The attribute name.
+	 * @param type The class type to convert the attribute value to.
+	 * @param <T> The class type to convert the attribute value to.
+	 * @return The attribute value converted to the specified class type.
+	 * @throws ParseException
+	 */
+	public <T> T get(String name, Class<T> type) throws ParseException {
+		return parse(name, beanSession.getClassMeta(type));
+	}
+
+	/**
+	 * Returns the specified path parameter converted to a POJO.
+	 * <p>
+	 * The type can be any POJO type convertable from a <code>String</code> (See <a class="doclink" href="package-summary.html#PojosConvertableFromString">POJOs Convertable From Strings</a>).
+	 * <p>
+	 * Use this method if you want to parse into a parameterized <code>Map</code>/<code>Collection</code> object.
+	 * <p>
+	 * <h5 class='section'>Examples:</h5>
+	 * <p class='bcode'>
+	 * 	<jc>// Parse into a linked-list of strings.</jc>
+	 * 	List&lt;String&gt; myparam = req.getPathParameter(<js>"myparam"</js>, LinkedList.<jk>class</jk>, String.<jk>class</jk>);
+	 *
+	 * 	<jc>// Parse into a linked-list of linked-lists of strings.</jc>
+	 * 	List&lt;List&lt;String&gt;&gt; myparam = req.getPathParameter(<js>"myparam"</js>, LinkedList.<jk>class</jk>, LinkedList.<jk>class</jk>, String.<jk>class</jk>);
+	 *
+	 * 	<jc>// Parse into a map of string keys/values.</jc>
+	 * 	Map&lt;String,String&gt; myparam = req.getPathParameter(<js>"myparam"</js>, TreeMap.<jk>class</jk>, String.<jk>class</jk>, String.<jk>class</jk>);
+	 *
+	 * 	<jc>// Parse into a map containing string keys and values of lists containing beans.</jc>
+	 * 	Map&lt;String,List&lt;MyBean&gt;&gt; myparam = req.getPathParameter(<js>"myparam"</js>, TreeMap.<jk>class</jk>, String.<jk>class</jk>, List.<jk>class</jk>, MyBean.<jk>class</jk>);
+	 * </p>
+	 *
+	 * @param name The attribute name.
+	 * @param type The type of object to create.
+	 * 	<br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
+	 * @param args The type arguments of the class if it's a collection or map.
+	 * 	<br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
+	 * 	<br>Ignored if the main type is not a map or collection.
+	 * @param <T> The class type to convert the attribute value to.
+	 * @return The attribute value converted to the specified class type.
+	 * @throws ParseException
+	 */
+	public <T> T get(String name, Type type, Type...args) throws ParseException {
+		return (T)parse(name, beanSession.getClassMeta(type, args));
+	}
+
+	/* Workhorse method */
+	<T> T parse(String name, ClassMeta<T> cm) throws ParseException {
+		Object attr = get(name);
+		T t = null;
+		if (attr != null)
+			t = parser.parsePart(attr.toString(), cm);
+		if (t == null && cm.isPrimitive())
+			return cm.getPrimitiveDefault();
+		return t;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/321f6bde/juneau-rest/src/main/java/org/apache/juneau/rest/RequestQuery.java
----------------------------------------------------------------------
diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/RequestQuery.java b/juneau-rest/src/main/java/org/apache/juneau/rest/RequestQuery.java
new file mode 100644
index 0000000..6a9a564
--- /dev/null
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/RequestQuery.java
@@ -0,0 +1,287 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import javax.servlet.http.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.internal.*;
+import org.apache.juneau.parser.*;
+import org.apache.juneau.urlencoding.*;
+
+/**
+ * Represents the query parameters in an HTTP request.
+ */
+@SuppressWarnings("unchecked")
+public final class RequestQuery extends LinkedHashMap<String,String[]> {
+	private static final long serialVersionUID = 1L;
+
+	private UrlEncodingParser parser;
+	private BeanSession beanSession;
+
+	RequestQuery setParser(UrlEncodingParser parser) {
+		this.parser = parser;
+		return this;
+	}
+
+	RequestQuery setBeanSession(BeanSession beanSession) {
+		this.beanSession = beanSession;
+		return this;
+	}
+
+	/**
+	 * Sets a request query parameter value.
+	 *
+	 * @param name The parameter name.
+	 * @param value The parameter value.
+	 */
+	public void put(String name, Object value) {
+		put(name, new String[]{StringUtils.toString(value)});
+	}
+
+	/**
+	 * Returns a query parameter value.
+	 * <p>
+	 * Same as {@link HttpServletRequest#getParameter(String)} except only looks in the URL string, not parameters from URL-Encoded FORM posts.
+	 * <p>
+	 * This method can be used to retrieve a parameter without triggering the underlying servlet API to load and parse the request body.
+	 *
+	 * @param name The URL parameter name.
+	 * @return The parameter value, or <jk>null</jk> if parameter not specified or has no value (e.g. <js>"&amp;foo"</js>.
+	 */
+	public String getFirst(String name) {
+		String[] v = get(name);
+		if (v == null || v.length == 0)
+			return null;
+		if (v.length == 1 && v[0] != null && v[0].isEmpty()) {
+			// Fix for behavior difference between Tomcat and WAS.
+			// getParameter("foo") on "&foo" in Tomcat returns "".
+			// getParameter("foo") on "&foo" in WAS returns null.
+			if (containsKey(name))
+				return null;
+		}
+		return v[0];
+	}
+
+	/**
+	 * Same as {@link #getFirst(String)} but returns the specified default value if the query parameter was not specified.
+	 *
+	 * @param name The URL parameter name.
+	 * @param def The default value.
+	 * @return The parameter value, or the default value if parameter not specified or has no value (e.g. <js>"&amp;foo"</js>.
+	 */
+	public String getFirst(String name, String def) {
+		String s = getFirst(name);
+		return s == null ? def : s;
+	}
+
+	/**
+	 * Returns the specified query parameter value converted to a POJO.
+	 * <p>
+	 * This method can be used to retrieve a parameter without triggering the underlying servlet API to load and parse the request body.
+	 * <p>
+	 * <h5 class='section'>Examples:</h5>
+	 * <p class='bcode'>
+	 * 	<jc>// Parse into an integer.</jc>
+	 * 	<jk>int</jk> myparam = req.getQueryParameter(<js>"myparam"</js>, <jk>int</jk>.<jk>class</jk>);
+	 *
+	 * 	<jc>// Parse into an int array.</jc>
+	 * 	<jk>int</jk>[] myparam = req.getQueryParameter(<js>"myparam"</js>, <jk>int</jk>[].<jk>class</jk>);
+
+	 * 	<jc>// Parse into a bean.</jc>
+	 * 	MyBean myparam = req.getQueryParameter(<js>"myparam"</js>, MyBean.<jk>class</jk>);
+	 *
+	 * 	<jc>// Parse into a linked-list of objects.</jc>
+	 * 	List myparam = req.getQueryParameter(<js>"myparam"</js>, LinkedList.<jk>class</jk>);
+	 *
+	 * 	<jc>// Parse into a map of object keys/values.</jc>
+	 * 	Map myparam = req.getQueryParameter(<js>"myparam"</js>, TreeMap.<jk>class</jk>);
+	 * </p>
+	 *
+	 * @param name The parameter name.
+	 * @param type The class type to convert the parameter value to.
+	 * @param <T> The class type to convert the parameter value to.
+	 * @return The parameter value converted to the specified class type.
+	 * @throws ParseException
+	 */
+	public <T> T get(String name, Class<T> type) throws ParseException {
+		return get(name, beanSession.getClassMeta(type));
+	}
+
+	/**
+	 * Same as {@link #get(String, Class)} except returns a default value if not found.
+	 *
+	 * @param name The parameter name.
+	 * @param def The default value if the parameter was not specified or is <jk>null</jk>.
+	 * @param type The class type to convert the parameter value to.
+	 * @param <T> The class type to convert the parameter value to.
+	 * @return The parameter value converted to the specified class type.
+	 * @throws ParseException
+	 */
+	public <T> T get(String name, T def, Class<T> type) throws ParseException {
+		return get(name, def, beanSession.getClassMeta(type));
+	}
+
+	/**
+	 * Returns the specified query parameter value converted to a POJO.
+	 * <p>
+	 * This method can be used to retrieve a parameter without triggering the underlying servlet API to load and parse the request body.
+	 * <p>
+	 * Use this method if you want to parse into a parameterized <code>Map</code>/<code>Collection</code> object.
+	 * <p>
+	 * <h5 class='section'>Examples:</h5>
+	 * <p class='bcode'>
+	 * 	<jc>// Parse into a linked-list of strings.</jc>
+	 * 	Listt&lt;String&gt; myparam = req.getQueryParameter(<js>"myparam"</js>, LinkedList.<jk>class</jk>, String.<jk>class</jk>);
+	 *
+	 * 	<jc>// Parse into a linked-list of linked-lists of strings.</jc>
+	 * 	Listt&lt;List&lt;String&gt;&gt; myparam = req.getQueryParameter(<js>"myparam"</js>, LinkedList.<jk>class</jk>, LinkedList.<jk>class</jk>, String.<jk>class</jk>);
+	 *
+	 * 	<jc>// Parse into a map of string keys/values.</jc>
+	 * 	Map&lt;String,String&gt; myparam = req.getQueryParameter(<js>"myparam"</js>, TreeMap.<jk>class</jk>, String.<jk>class</jk>, String.<jk>class</jk>);
+	 *
+	 * 	<jc>// Parse into a map containing string keys and values of lists containing beans.</jc>
+	 * 	Map&lt;String,List&lt;MyBean&gt;&gt; myparam = req.getQueryParameter(<js>"myparam"</js>, TreeMap.<jk>class</jk>, String.<jk>class</jk>, List.<jk>class</jk>, MyBean.<jk>class</jk>);
+	 * </p>
+	 *
+	 * @param name The parameter name.
+	 * @param type The type of object to create.
+	 * 	<br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
+	 * @param args The type arguments of the class if it's a collection or map.
+	 * 	<br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
+	 * 	<br>Ignored if the main type is not a map or collection.
+	 * @param <T> The class type to convert the parameter value to.
+	 * @return The parameter value converted to the specified class type.
+	 * @throws ParseException
+	 */
+	public <T> T get(String name, Type type, Type...args) throws ParseException {
+		return (T)parse(name, beanSession.getClassMeta(type, args));
+	}
+
+	/**
+	 * Same as {@link #get(String, Class)} except returns a default value if not found.
+	 *
+	 * @param name The parameter name.
+	 * @param type The type of object to create.
+	 * 	<br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
+	 * @param args The type arguments of the class if it's a collection or map.
+	 * 	<br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
+	 * 	<br>Ignored if the main type is not a map or collection.
+	 * @param def The default value if the parameter was not specified or is <jk>null</jk>.
+	 * @param <T> The class type to convert the parameter value to.
+	 * @return The parameter value converted to the specified class type.
+	 * @throws ParseException
+	 */
+	public <T> T get(String name, Object def, Type type, Type...args) throws ParseException {
+		return (T)parse(name, def, beanSession.getClassMeta(type, args));
+	}
+
+	/**
+	 * Same as {@link #get(String, Class)} except for use on multi-part parameters
+	 * (e.g. <js>"&amp;key=1&amp;key=2&amp;key=3"</js> instead of <js>"&amp;key=(1,2,3)"</js>).
+	 * <p>
+	 * This method must only be called when parsing into classes of type Collection or array.
+	 *
+	 * @param name The query parameter name.
+	 * @param c The class type to convert the parameter value to.
+	 * @param <T> The class type to convert the parameter value to.
+	 * @return The query parameter value converted to the specified class type.
+	 * @throws ParseException
+	 */
+	public <T> T getAll(String name, Class<T> c) throws ParseException {
+		return getAll(name, beanSession.getClassMeta(c));
+	}
+
+	/**
+	 * Same as {@link #get(String, Type, Type...)} except for use on multi-part parameters
+	 * (e.g. <js>"&amp;key=1&amp;key=2&amp;key=3"</js> instead of <js>"&amp;key=(1,2,3)"</js>).
+	 * <p>
+	 * This method must only be called when parsing into classes of type Collection or array.
+	 *
+	 * @param name The query parameter name.
+	 * @param type The type of object to create.
+	 * 	<br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
+	 * @param args The type arguments of the class if it's a collection or map.
+	 * 	<br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
+	 * 	<br>Ignored if the main type is not a map or collection.
+	 * @param <T> The class type to convert the parameter value to.
+	 * @return The query parameter value converted to the specified class type.
+	 * @throws ParseException
+	 */
+	public <T> T getAll(String name, Type type, Type...args) throws ParseException {
+		return (T)parseAll(name, beanSession.getClassMeta(type, args));
+	}
+
+	/**
+	 * Returns <jk>true</jk> if the request contains any of the specified query parameters.
+	 *
+	 * @param params The list of parameters to check for.
+	 * @return <jk>true</jk> if the request contains any of the specified query parameters.
+	 */
+	public boolean containsAnyKeys(String...params) {
+		for (String p : params)
+			if (containsKey(p))
+				return true;
+		return false;
+	}
+
+	/* Workhorse method */
+	private <T> T parse(String name, T def, ClassMeta<T> cm) throws ParseException {
+		String val = getFirst(name);
+		if (val == null)
+			return def;
+		return parseValue(val, cm);
+	}
+
+	/* Workhorse method */
+	private <T> T parse(String name, ClassMeta<T> cm) throws ParseException {
+		String val = getFirst(name);
+		if (cm.isPrimitive() && (val == null || val.isEmpty()))
+			return cm.getPrimitiveDefault();
+		return parseValue(val, cm);
+	}
+
+	/* Workhorse method */
+	@SuppressWarnings("rawtypes")
+	private <T> T parseAll(String name, ClassMeta<T> cm) throws ParseException {
+		String[] p = get(name);
+		if (p == null)
+			return null;
+		if (cm.isArray()) {
+			List c = new ArrayList();
+			for (int i = 0; i < p.length; i++)
+				c.add(parseValue(p[i], cm.getElementType()));
+			return (T)ArrayUtils.toArray(c, cm.getElementType().getInnerClass());
+		} else if (cm.isCollection()) {
+			try {
+				Collection c = (Collection)(cm.canCreateNewInstance() ? cm.newInstance() : new ObjectList());
+				for (int i = 0; i < p.length; i++)
+					c.add(parseValue(p[i], cm.getElementType()));
+				return (T)c;
+			} catch (ParseException e) {
+				throw e;
+			} catch (Exception e) {
+				// Typically an instantiation exception.
+				throw new ParseException(e);
+			}
+		}
+		throw new ParseException("Invalid call to getQueryParameters(String, ClassMeta).  Class type must be a Collection or array.");
+	}
+
+	private <T> T parseValue(String val, ClassMeta<T> c) throws ParseException {
+		return parser.parsePart(val, c);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/321f6bde/juneau-rest/src/main/java/org/apache/juneau/rest/RestContext.java
----------------------------------------------------------------------
diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/RestContext.java b/juneau-rest/src/main/java/org/apache/juneau/rest/RestContext.java
index 97ab2d4..54a3fa0 100644
--- a/juneau-rest/src/main/java/org/apache/juneau/rest/RestContext.java
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/RestContext.java
@@ -444,7 +444,7 @@ public final class RestContext extends Context {
 										if (m != null) {
 											try {
 												// Parse the args and invoke the method.
-												Parser p = req.getParser();
+												Parser p = req.getBody().getParser();
 												Object input = p.isReaderParser() ? req.getReader() : req.getInputStream();
 												Object output = m.invoke(o, p.parseArgs(input, m.getGenericParameterTypes()));
 												res.setOutput(output);

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/321f6bde/juneau-rest/src/main/java/org/apache/juneau/rest/RestParam.java
----------------------------------------------------------------------
diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/RestParam.java b/juneau-rest/src/main/java/org/apache/juneau/rest/RestParam.java
new file mode 100644
index 0000000..a900c14
--- /dev/null
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/RestParam.java
@@ -0,0 +1,978 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest;
+
+import static org.apache.juneau.rest.RestParamType.*;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.util.*;
+import java.util.logging.*;
+
+import javax.servlet.*;
+import javax.servlet.http.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.dto.swagger.*;
+import org.apache.juneau.http.*;
+import org.apache.juneau.http.Date;
+import org.apache.juneau.ini.*;
+import org.apache.juneau.internal.*;
+import org.apache.juneau.parser.*;
+import org.apache.juneau.utils.*;
+
+/**
+ * REST java method parameter resolver.
+ */
+public abstract class RestParam {
+
+	/**
+	 * Standard set of method parameter resolvers.
+	 */
+	public static final Map<Class<?>,RestParam> STANDARD_RESOLVERS;
+
+	static {
+		Map<Class<?>,RestParam> m = new HashMap<Class<?>,RestParam>();
+
+		@SuppressWarnings("rawtypes")
+		Class[] r = new Class[] {
+
+			// Standard top-level objects
+			HttpServletRequestObject.class,
+			RestRequestObject.class,
+			HttpServletResponseObject.class,
+			RestResponseObject.class,
+
+			// Headers
+			AcceptHeader.class,
+			AcceptCharsetHeader.class,
+			AcceptEncodingHeader.class,
+			AcceptLanguageHeader.class,
+			AuthorizationHeader.class,
+			CacheControlHeader.class,
+			ConnectionHeader.class,
+			ContentLengthHeader.class,
+			ContentTypeHeader.class,
+			DateHeader.class,
+			ExpectHeader.class,
+			FromHeader.class,
+			HostHeader.class,
+			IfMatchHeader.class,
+			IfModifiedSinceHeader.class,
+			IfNoneMatchHeader.class,
+			IfRangeHeader.class,
+			IfUnmodifiedSinceHeader.class,
+			MaxForwardsHeader.class,
+			PragmaHeader.class,
+			ProxyAuthorizationHeader.class,
+			RangeHeader.class,
+			RefererHeader.class,
+			TEHeader.class,
+			UserAgentHeader.class,
+			UpgradeHeader.class,
+			ViaHeader.class,
+			WarningHeader.class,
+			TimeZoneHeader.class,
+
+			// Other objects
+			ResourceBundleObject.class,
+			MessageBundleObject.class,
+			InputStreamObject.class,
+			ServletInputStreamObject.class,
+			ReaderObject.class,
+			OutputStreamObject.class,
+			ServletOutputStreamObject.class,
+			WriterObject.class,
+			RequestHeadersObject.class,
+			RequestQueryParamsObject.class,
+			RequestFormDataObject.class,
+			HttpMethodObject.class,
+			LoggerObject.class,
+			JuneauLoggerObject.class,
+			RestContextObject.class,
+			ParserObject.class,
+			LocaleObject.class,
+			SwaggerObject.class,
+			RequestPathParamsObject.class,
+			RequestBodyObject.class,
+			ConfigFileObject.class,
+		};
+
+		for (Class<?> c : r) {
+			try {
+				RestParam mpr = (RestParam)c.newInstance();
+				m.put(mpr.forClass(), mpr);
+			} catch (Exception e) {
+				e.printStackTrace();
+			}
+		}
+
+		STANDARD_RESOLVERS = Collections.unmodifiableMap(m);
+	}
+
+	final RestParamType paramType;
+	final String name;
+	final Type type;
+
+	/**
+	 * Constructor.
+	 *
+	 * @param paramType The Swagger parameter type.
+	 * @param name The parameter name.
+	 * 	Can be <jk>null</jk> if parameter doesn't have a name (e.g. the request body).
+	 * @param type The object type to convert the parameter to.
+	 */
+	protected RestParam(RestParamType paramType, String name, Type type) {
+		this.paramType = paramType;
+		this.name = name;
+		this.type = type;
+	}
+
+	/**
+	 * Resolves the parameter object.
+	 *
+	 * @param req The rest request.
+	 * @param res The rest response.
+	 * @return The resolved object.
+	 * @throws Exception
+	 */
+	public abstract Object resolve(RestRequest req, RestResponse res) throws Exception;
+
+	/**
+	 * Returns the parameter class type that this parameter resolver is meant for.
+	 * @return The parameter class type, or <jk>null</jk> if the type passed in isn't an instance of {@link Class}.
+	 */
+	protected Class<?> forClass() {
+		if (type instanceof Class)
+			return (Class<?>)type;
+		return null;
+	}
+
+	/**
+	 * Returns the swagger parameter type for this parameter as shown in the Swagger doc.
+	 * @return the swagger parameter type for this parameter.
+	 */
+	protected RestParamType getParamType() {
+		return paramType;
+	}
+
+	/**
+	 * Returns the parameter name for this parameter as shown in the Swagger doc.
+	 * @return the parameter name for this parameter.
+	 */
+	protected String getName() {
+		return name;
+	}
+
+	//-------------------------------------------------------------------------------------------------------------------
+	// Request / Response retrievers
+	//-------------------------------------------------------------------------------------------------------------------
+
+	static final class HttpServletRequestObject extends RestParam {
+
+		protected HttpServletRequestObject() {
+			super(OTHER, null, HttpServletRequest.class);
+		}
+
+		@Override /* RestParam */
+		public Object resolve(RestRequest req, RestResponse res) {
+			return req;
+		}
+	}
+
+	static final class HttpServletResponseObject extends RestParam {
+
+		protected HttpServletResponseObject() {
+			super(OTHER, null, HttpServletResponse.class);
+		}
+
+		@Override /* RestParam */
+		public Object resolve(RestRequest req, RestResponse res) {
+			return res;
+		}
+	}
+
+	static final class RestRequestObject extends RestParam {
+
+		protected RestRequestObject() {
+			super(OTHER, null, RestRequest.class);
+		}
+
+		@Override /* RestParam */
+		public Object resolve(RestRequest req, RestResponse res) {
+			return req;
+		}
+	}
+
+	static final class RestResponseObject extends RestParam {
+
+		protected RestResponseObject() {
+			super(OTHER, null, RestResponse.class);
+		}
+
+		@Override /* RestParam */
+		public Object resolve(RestRequest req, RestResponse res) {
+			return res;
+		}
+	}
+
+	//-------------------------------------------------------------------------------------------------------------------
+	// Header retrievers
+	//-------------------------------------------------------------------------------------------------------------------
+
+	static final class AcceptHeader extends RestParam {
+
+		protected AcceptHeader() {
+			super(HEADER, "Accept-Header", AcceptHeader.class);
+		}
+
+		@Override /* RestParam */
+		public Object resolve(RestRequest req, RestResponse res) {
+			return req.getHeaders().getAccept();
+		}
+	}
+
+	static final class AcceptCharsetHeader extends RestParam {
+
+		protected AcceptCharsetHeader() {
+			super(HEADER, "Accept-Charset", AcceptCharset.class);
+		}
+
+		@Override /* RestParam */
+		public AcceptCharset resolve(RestRequest req, RestResponse res) {
+			return req.getHeaders().getAcceptCharset();
+		}
+	}
+
+	static final class AcceptEncodingHeader extends RestParam {
+
+		protected AcceptEncodingHeader() {
+			super(HEADER, "Accept-Encoding", AcceptEncoding.class);
+		}
+
+		@Override
+		public AcceptEncoding resolve(RestRequest req, RestResponse res) {
+			return req.getHeaders().getAcceptEncoding();
+		}
+	}
+
+	static final class AcceptLanguageHeader extends RestParam {
+
+		protected AcceptLanguageHeader() {
+			super(HEADER, "Accept-Language", AcceptLanguage.class);
+		}
+
+		@Override
+		public AcceptLanguage resolve(RestRequest req, RestResponse res) {
+			return req.getHeaders().getAcceptLanguage();
+		}
+	}
+
+	static final class AuthorizationHeader extends RestParam {
+
+		protected AuthorizationHeader() {
+			super(HEADER, "Authorization", Authorization.class);
+		}
+
+		@Override
+		public Authorization resolve(RestRequest req, RestResponse res) {
+			return req.getHeaders().getAuthorization();
+		}
+	}
+
+	static final class CacheControlHeader extends RestParam {
+
+		protected CacheControlHeader() {
+			super(HEADER, "Cache-Control", CacheControl.class);
+		}
+
+		@Override
+		public CacheControl resolve(RestRequest req, RestResponse res) {
+			return req.getHeaders().getCacheControl();
+		}
+	}
+
+	static final class ConnectionHeader extends RestParam {
+
+		protected ConnectionHeader() {
+			super(HEADER, "Connection", Connection.class);
+		}
+
+		@Override
+		public Connection resolve(RestRequest req, RestResponse res) {
+			return req.getHeaders().getConnection();
+		}
+	}
+
+	static final class ContentLengthHeader extends RestParam {
+
+		protected ContentLengthHeader() {
+			super(HEADER, "Content-Length", ContentLength.class);
+		}
+
+		@Override
+		public ContentLength resolve(RestRequest req, RestResponse res) {
+			return req.getHeaders().getContentLength();
+		}
+	}
+
+	static final class ContentTypeHeader extends RestParam {
+
+		protected ContentTypeHeader() {
+			super(HEADER, "Content-Type", ContentType.class);
+		}
+
+		@Override
+		public ContentType resolve(RestRequest req, RestResponse res) {
+			return req.getHeaders().getContentType();
+		}
+	}
+
+	static final class DateHeader extends RestParam {
+
+		protected DateHeader() {
+			super(HEADER, "Date", Date.class);
+		}
+
+		@Override
+		public Date resolve(RestRequest req, RestResponse res) {
+			return req.getHeaders().getDate();
+		}
+	}
+
+	static final class ExpectHeader extends RestParam {
+
+		protected ExpectHeader() {
+			super(HEADER, "Expect", Expect.class);
+		}
+
+		@Override
+		public Expect resolve(RestRequest req, RestResponse res) {
+			return req.getHeaders().getExpect();
+		}
+	}
+
+	static final class FromHeader extends RestParam {
+
+		protected FromHeader() {
+			super(HEADER, "From", From.class);
+		}
+
+		@Override
+		public From resolve(RestRequest req, RestResponse res) {
+			return req.getHeaders().getFrom();
+		}
+	}
+
+	static final class HostHeader extends RestParam {
+
+		protected HostHeader() {
+			super(HEADER, "Host", Host.class);
+		}
+
+		@Override
+		public Host resolve(RestRequest req, RestResponse res) {
+			return req.getHeaders().getHost();
+		}
+	}
+
+	static final class IfMatchHeader extends RestParam {
+
+		protected IfMatchHeader() {
+			super(HEADER, "If-Match", IfMatch.class);
+		}
+
+		@Override
+		public IfMatch resolve(RestRequest req, RestResponse res) {
+			return req.getHeaders().getIfMatch();
+		}
+	}
+
+	static final class IfModifiedSinceHeader extends RestParam {
+
+		protected IfModifiedSinceHeader() {
+			super(HEADER, "If-Modified-Since", IfModifiedSince.class);
+		}
+
+		@Override
+		public IfModifiedSince resolve(RestRequest req, RestResponse res) {
+			return req.getHeaders().getIfModifiedSince();
+		}
+	}
+
+	static final class IfNoneMatchHeader extends RestParam {
+
+		protected IfNoneMatchHeader() {
+			super(HEADER, "If-None-Match", IfNoneMatch.class);
+		}
+
+		@Override
+		public IfNoneMatch resolve(RestRequest req, RestResponse res) {
+			return req.getHeaders().getIfNoneMatch();
+		}
+	}
+
+	static final class IfRangeHeader extends RestParam {
+
+		protected IfRangeHeader() {
+			super(HEADER, "If-Range", IfRange.class);
+		}
+
+		@Override
+		public IfRange resolve(RestRequest req, RestResponse res) {
+			return req.getHeaders().getIfRange();
+		}
+	}
+
+	static final class IfUnmodifiedSinceHeader extends RestParam {
+
+		protected IfUnmodifiedSinceHeader() {
+			super(HEADER, "If-Unmodified-Since", IfUnmodifiedSince.class);
+		}
+
+		@Override
+		public IfUnmodifiedSince resolve(RestRequest req, RestResponse res) {
+			return req.getHeaders().getIfUnmodifiedSince();
+		}
+	}
+
+	static final class MaxForwardsHeader extends RestParam {
+
+		protected MaxForwardsHeader() {
+			super(HEADER, "Max-Forwards", MaxForwards.class);
+		}
+
+		@Override
+		public MaxForwards resolve(RestRequest req, RestResponse res) {
+			return req.getHeaders().getMaxForwards();
+		}
+	}
+
+	static final class PragmaHeader extends RestParam {
+
+		protected PragmaHeader() {
+			super(HEADER, "Pragma", Pragma.class);
+		}
+
+		@Override
+		public Pragma resolve(RestRequest req, RestResponse res) {
+			return req.getHeaders().getPragma();
+		}
+	}
+
+	static final class ProxyAuthorizationHeader extends RestParam {
+
+		protected ProxyAuthorizationHeader() {
+			super(HEADER, "Proxy-Authorization", ProxyAuthorization.class);
+		}
+
+		@Override
+		public ProxyAuthorization resolve(RestRequest req, RestResponse res) {
+			return req.getHeaders().getProxyAuthorization();
+		}
+	}
+
+	static final class RangeHeader extends RestParam {
+
+		protected RangeHeader() {
+			super(HEADER, "Range", Range.class);
+		}
+
+		@Override
+		public Range resolve(RestRequest req, RestResponse res) {
+			return req.getHeaders().getRange();
+		}
+	}
+
+	static final class RefererHeader extends RestParam {
+
+		protected RefererHeader() {
+			super(HEADER, "Referer", Referer.class);
+		}
+
+		@Override
+		public Referer resolve(RestRequest req, RestResponse res) {
+			return req.getHeaders().getReferer();
+		}
+	}
+
+	static final class TEHeader extends RestParam {
+
+		protected TEHeader() {
+			super(HEADER, "TE", TE.class);
+		}
+
+		@Override
+		public TE resolve(RestRequest req, RestResponse res) {
+			return req.getHeaders().getTE();
+		}
+	}
+
+	static final class UserAgentHeader extends RestParam {
+
+		protected UserAgentHeader() {
+			super(HEADER, "User-Agent", UserAgent.class);
+		}
+
+		@Override
+		public UserAgent resolve(RestRequest req, RestResponse res) {
+			return req.getHeaders().getUserAgent();
+		}
+	}
+
+	static final class UpgradeHeader extends RestParam {
+
+		protected UpgradeHeader() {
+			super(HEADER, "Upgrade", Upgrade.class);
+		}
+
+		@Override
+		public Upgrade resolve(RestRequest req, RestResponse res) {
+			return req.getHeaders().getUpgrade();
+		}
+	}
+
+	static final class ViaHeader extends RestParam {
+
+		protected ViaHeader() {
+			super(HEADER, "Via", Via.class);
+		}
+
+		@Override
+		public Via resolve(RestRequest req, RestResponse res) {
+			return req.getHeaders().getVia();
+		}
+	}
+
+	static final class WarningHeader extends RestParam {
+
+		protected WarningHeader() {
+			super(HEADER, "Warning", Warning.class);
+		}
+
+		@Override
+		public Warning resolve(RestRequest req, RestResponse res) {
+			return req.getHeaders().getWarning();
+		}
+	}
+
+	static final class TimeZoneHeader extends RestParam {
+
+		protected TimeZoneHeader() {
+			super(HEADER, "Time-Zone", TimeZone.class);
+		}
+
+		@Override
+		public TimeZone resolve(RestRequest req, RestResponse res) {
+			return req.getHeaders().getTimeZone();
+		}
+	}
+
+	//-------------------------------------------------------------------------------------------------------------------
+	// Annotated retrievers
+	//-------------------------------------------------------------------------------------------------------------------
+
+	static final class PathParameterObject extends RestParam {
+
+		protected PathParameterObject(String name, Type type) {
+			super(PATH, name, type);
+		}
+
+		@Override /* RestParam */
+		public Object resolve(RestRequest req, RestResponse res) throws Exception {
+			return req.getPathParams().get(name, type);
+		}
+	}
+
+	static final class BodyObject extends RestParam {
+
+		protected BodyObject(Type type) {
+			super(BODY, null, type);
+		}
+
+		@Override /* RestParam */
+		public Object resolve(RestRequest req, RestResponse res) throws Exception {
+			return req.getBody().asType(type);
+		}
+	}
+
+	static final class HeaderObject extends RestParam {
+
+		protected HeaderObject(String name, Type type) {
+			super(HEADER, name, type);
+		}
+
+		@Override /* RestParam */
+		public Object resolve(RestRequest req, RestResponse res) throws Exception {
+			return req.getHeaders().get(name, type);
+		}
+	}
+
+	static final class MethodObject extends RestParam {
+
+		protected MethodObject() {
+			super(OTHER, null, null);
+		}
+
+		@Override /* RestParam */
+		public Object resolve(RestRequest req, RestResponse res) throws Exception {
+			return req.getMethod();
+		}
+	}
+
+	static final class FormDataObject extends RestParam {
+		private final boolean multiPart, plainParams;
+
+		protected FormDataObject(String name, Type type, boolean multiPart, boolean plainParams) {
+			super(FORMDATA, name, type);
+			this.multiPart = multiPart;
+			this.plainParams = plainParams;
+		}
+
+		@Override /* RestParam */
+		public Object resolve(RestRequest req, RestResponse res) throws Exception {
+			BeanSession bs = req.getBeanSession();
+			if (multiPart)
+				return req.getFormData().getAll(name, type);
+			if (plainParams)
+				return bs.convertToType(req.getFormData(name), bs.getClassMeta(type));
+			return req.getFormData().get(name, type);
+		}
+	}
+
+	static final class QueryObject extends RestParam {
+		private final boolean multiPart, plainParams;
+
+		protected QueryObject(String name, Type type, boolean multiPart, boolean plainParams) {
+			super(QUERY, name, type);
+			this.multiPart = multiPart;
+			this.plainParams = plainParams;
+		}
+
+		@Override /* RestParam */
+		public Object resolve(RestRequest req, RestResponse res) throws Exception {
+			BeanSession bs = req.getBeanSession();
+			if (multiPart)
+				return req.getQuery().getAll(name, type);
+			if (plainParams)
+				return bs.convertToType(req.getQuery(name), bs.getClassMeta(type));
+			return req.getQuery().get(name, type);
+		}
+	}
+
+	static final class HasFormDataObject extends RestParam {
+
+		protected HasFormDataObject(String name, Type type) {
+			super(FORMDATA, name, type);
+		}
+
+		@Override /* RestParam */
+		public Object resolve(RestRequest req, RestResponse res) throws Exception {
+			BeanSession bs = req.getBeanSession();
+			return bs.convertToType(req.getFormData().containsKey(name), bs.getClassMeta(type));
+		}
+	}
+
+	static final class HasQueryObject extends RestParam {
+
+		protected HasQueryObject(String name, Type type) {
+			super(QUERY, name, type);
+		}
+
+		@Override /* RestParam */
+		public Object resolve(RestRequest req, RestResponse res) throws Exception {
+			BeanSession bs = req.getBeanSession();
+			return bs.convertToType(req.getQuery().containsKey(name), bs.getClassMeta(type));
+		}
+	}
+
+	static final class PathRemainderObject extends RestParam {
+
+		protected PathRemainderObject() {
+			super(OTHER, null, null);
+		}
+
+		@Override /* RestParam */
+		public Object resolve(RestRequest req, RestResponse res) throws Exception {
+			return req.getPathRemainder();
+		}
+	}
+
+	static final class PropsObject extends RestParam {
+
+		protected PropsObject() {
+			super(OTHER, null, null);
+		}
+
+		@Override /* RestParam */
+		public Object resolve(RestRequest req, RestResponse res) throws Exception {
+			return req.getProperties();
+		}
+	}
+
+	//-------------------------------------------------------------------------------------------------------------------
+	// Other retrievers
+	//-------------------------------------------------------------------------------------------------------------------
+
+	static final class ResourceBundleObject extends RestParam {
+
+		protected ResourceBundleObject() {
+			super(OTHER, null, ResourceBundle.class);
+		}
+
+		@Override /* RestParam */
+		public Object resolve(RestRequest req, RestResponse res) throws Exception {
+			return req.getResourceBundle();
+		}
+	}
+
+	static final class MessageBundleObject extends RestParam {
+
+		protected MessageBundleObject() {
+			super(OTHER, null, MessageBundle.class);
+		}
+
+		@Override /* RestParam */
+		public Object resolve(RestRequest req, RestResponse res) throws Exception {
+			return req.getResourceBundle();
+		}
+	}
+
+	static final class InputStreamObject extends RestParam {
+
+		protected InputStreamObject() {
+			super(OTHER, null, InputStream.class);
+		}
+
+		@Override /* RestParam */
+		public Object resolve(RestRequest req, RestResponse res) throws Exception {
+			return req.getInputStream();
+		}
+	}
+
+	static final class ServletInputStreamObject extends RestParam {
+
+		protected ServletInputStreamObject() {
+			super(OTHER, null, ServletInputStream.class);
+		}
+
+		@Override /* RestParam */
+		public Object resolve(RestRequest req, RestResponse res) throws Exception {
+			return req.getInputStream();
+		}
+	}
+
+	static final class ReaderObject extends RestParam {
+
+		protected ReaderObject() {
+			super(OTHER, null, Reader.class);
+		}
+
+		@Override /* RestParam */
+		public Object resolve(RestRequest req, RestResponse res) throws Exception {
+			return req.getReader();
+		}
+	}
+
+	static final class OutputStreamObject extends RestParam {
+
+		protected OutputStreamObject() {
+			super(OTHER, null, OutputStream.class);
+		}
+
+		@Override /* RestParam */
+		public Object resolve(RestRequest req, RestResponse res) throws Exception {
+			return res.getOutputStream();
+		}
+	}
+
+	static final class ServletOutputStreamObject extends RestParam {
+
+		protected ServletOutputStreamObject() {
+			super(OTHER, null, ServletOutputStream.class);
+		}
+
+		@Override /* RestParam */
+		public Object resolve(RestRequest req, RestResponse res) throws Exception {
+			return res.getOutputStream();
+		}
+	}
+
+	static final class WriterObject extends RestParam {
+
+		protected WriterObject() {
+			super(OTHER, null, Writer.class);
+		}
+
+		@Override /* RestParam */
+		public Object resolve(RestRequest req, RestResponse res) throws Exception {
+			return res.getWriter();
+		}
+	}
+
+	static final class RequestHeadersObject extends RestParam {
+
+		protected RequestHeadersObject() {
+			super(OTHER, null, RequestHeaders.class);
+		}
+
+		@Override /* RestParam */
+		public Object resolve(RestRequest req, RestResponse res) throws Exception {
+			return req.getHeaders();
+		}
+	}
+
+	static final class RequestQueryParamsObject extends RestParam {
+
+		protected RequestQueryParamsObject() {
+			super(OTHER, null, RequestQuery.class);
+		}
+
+		@Override /* RestParam */
+		public Object resolve(RestRequest req, RestResponse res) throws Exception {
+			return req.getQuery();
+		}
+	}
+
+	static final class RequestFormDataObject extends RestParam {
+
+		protected RequestFormDataObject() {
+			super(OTHER, null, RequestFormData.class);
+		}
+
+		@Override /* RestParam */
+		public Object resolve(RestRequest req, RestResponse res) throws Exception {
+			return req.getFormData();
+		}
+	}
+
+	static final class HttpMethodObject extends RestParam {
+
+		protected HttpMethodObject() {
+			super(OTHER, null, HttpMethod.class);
+		}
+
+		@Override /* RestParam */
+		public Object resolve(RestRequest req, RestResponse res) throws Exception {
+			return req.getHttpMethod();
+		}
+	}
+
+	static final class LoggerObject extends RestParam {
+
+		protected LoggerObject() {
+			super(OTHER, null, Logger.class);
+		}
+
+		@Override /* RestParam */
+		public Object resolve(RestRequest req, RestResponse res) throws Exception {
+			return req.getContext().getLogger().getLogger();
+		}
+	}
+
+	static final class JuneauLoggerObject extends RestParam {
+
+		protected JuneauLoggerObject() {
+			super(OTHER, null, JuneauLogger.class);
+		}
+
+		@Override /* RestParam */
+		public Object resolve(RestRequest req, RestResponse res) throws Exception {
+			return req.getContext().getLogger().getLogger();
+		}
+	}
+
+	static final class RestContextObject extends RestParam {
+
+		protected RestContextObject() {
+			super(OTHER, null, RestContext.class);
+		}
+
+		@Override /* RestParam */
+		public Object resolve(RestRequest req, RestResponse res) throws Exception {
+			return req.getContext();
+		}
+	}
+
+	static final class ParserObject extends RestParam {
+
+		protected ParserObject() {
+			super(OTHER, null, Parser.class);
+		}
+
+		@Override /* RestParam */
+		public Object resolve(RestRequest req, RestResponse res) throws Exception {
+			return req.getBody().getParser();
+		}
+	}
+
+	static final class LocaleObject extends RestParam {
+
+		protected LocaleObject() {
+			super(OTHER, null, Locale.class);
+		}
+
+		@Override /* RestParam */
+		public Object resolve(RestRequest req, RestResponse res) throws Exception {
+			return req.getLocale();
+		}
+	}
+
+	static final class SwaggerObject extends RestParam {
+
+		protected SwaggerObject() {
+			super(OTHER, null, Swagger.class);
+		}
+
+		@Override /* RestParam */
+		public Object resolve(RestRequest req, RestResponse res) throws Exception {
+			return req.getSwagger();
+		}
+	}
+
+	static final class RequestPathParamsObject extends RestParam {
+
+		protected RequestPathParamsObject() {
+			super(OTHER, null, RequestPathParams.class);
+		}
+
+		@Override /* RestParam */
+		public Object resolve(RestRequest req, RestResponse res) throws Exception {
+			return req.getPathParams();
+		}
+	}
+
+	static final class RequestBodyObject extends RestParam {
+
+		protected RequestBodyObject() {
+			super(BODY, null, RequestBody.class);
+		}
+
+		@Override /* RestParam */
+		public Object resolve(RestRequest req, RestResponse res) throws Exception {
+			return req.getBody();
+		}
+	}
+
+	static final class ConfigFileObject extends RestParam {
+
+		protected ConfigFileObject() {
+			super(OTHER, null, ConfigFile.class);
+		}
+
+		@Override /* RestParam */
+		public Object resolve(RestRequest req, RestResponse res) throws Exception {
+			return req.getConfigFile();
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/321f6bde/juneau-rest/src/main/java/org/apache/juneau/rest/RestParamType.java
----------------------------------------------------------------------
diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/RestParamType.java b/juneau-rest/src/main/java/org/apache/juneau/rest/RestParamType.java
new file mode 100644
index 0000000..70fe2eb
--- /dev/null
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/RestParamType.java
@@ -0,0 +1,48 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest;
+
+/**
+ * Represents the possible parameter types as defined by the Swagger 2.0 specification.
+ */
+public enum RestParamType {
+
+	/** Path variable */
+	PATH("path"),
+
+	/** Header value */
+	HEADER("header"),
+
+	/** Form data entry */
+	FORMDATA("formData"),
+
+	/** Query parameter */
+	QUERY("query"),
+
+	/** Request body */
+	BODY("body"),
+
+	/** Not a standard Swagger-defined field */
+	OTHER("other");
+
+	private final String value;
+
+	private RestParamType(String value) {
+		this.value = value;
+	}
+
+	@Override /* Object */
+	public String toString() {
+		return value;
+	}
+}


Mime
View raw message