http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/91a388d0/juneau-server/src/main/java/org/apache/juneau/server/RestRequest.java
----------------------------------------------------------------------
diff --git 
a/juneau-server/src/main/java/org/apache/juneau/server/RestRequest.java 
b/juneau-server/src/main/java/org/apache/juneau/server/RestRequest.java
deleted file mode 100755
index 2272604..0000000
--- a/juneau-server/src/main/java/org/apache/juneau/server/RestRequest.java
+++ /dev/null
@@ -1,1870 +0,0 @@
-// 
***************************************************************************************************************************
-// * 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.server;
-
-import static java.util.Collections.*;
-import static java.util.logging.Level.*;
-import static javax.servlet.http.HttpServletResponse.*;
-
-import java.io.*;
-import java.lang.reflect.*;
-import java.net.*;
-import java.text.*;
-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.encoders.*;
-import org.apache.juneau.encoders.Encoder;
-import org.apache.juneau.ini.*;
-import org.apache.juneau.internal.*;
-import org.apache.juneau.parser.*;
-import org.apache.juneau.parser.ParseException;
-import org.apache.juneau.serializer.*;
-import org.apache.juneau.svl.*;
-import org.apache.juneau.urlencoding.*;
-import org.apache.juneau.utils.*;
-
-/**
- * Represents an HTTP request for a REST resource.
- * <p>
- *     Equivalent to {@link HttpServletRequest} except with some additional 
convenience methods.
- * </p>
- * <p>
- *     For reference, given the URL 
<js>"http://localhost:9080/contextRoot/servletPath/foo?bar=baz#qux";</js>, the
- *     following methods return the following values....
- * </p>
- * <table class='styled'>
- *     <tr><th>Method</th><th>Value</th></tr>
- *     <tr><td>{@code getContextPath()}</td><td>{@code /contextRoot}</td></tr>
- *     <tr><td>{@code getPathInfo()}</td><td>{@code /foo}</td></tr>
- *     <tr><td>{@code getPathTranslated()}</td><td>{@code 
path-to-deployed-war-on-filesystem/foo}</td></tr>
- *     <tr><td>{@code getQueryString()}</td><td>{@code bar=baz}</td></tr>
- *     <tr><td>{@code getRequestURI()}</td><td>{@code 
/contextRoot/servletPath/foo}</td></tr>
- *     <tr><td>{@code getRequestURL()}</td><td>{@code 
http://localhost:9080/contextRoot/servletPath/foo}</td></tr>
- *     <tr><td>{@code getServletPath()}</td><td>{@code /servletPath}</td></tr>
- * </table>
- * <p>
- *     Refer to <a class='doclink' href='package-summary.html#TOC'>REST 
Servlet API</a> for information about using this class.
- * </p>
- */
-@SuppressWarnings("unchecked")
-public final class RestRequest extends HttpServletRequestWrapper {
-
-       private final RestServlet servlet;
-       private String method, pathRemainder, body;
-       Method javaMethod;
-       private ObjectMap properties;
-       private SerializerGroup serializerGroup;
-       private ParserGroup parserGroup;
-       private Encoder encoder;
-       private int contentLength;
-       private final boolean debug;
-       private UrlEncodingParser urlEncodingParser;   // The parser used to 
parse URL attributes and parameters (beanContext also used to parse headers)
-       private BeanSession beanSession;
-       private VarResolverSession varSession;
-       private Map<String,String[]> queryParams;
-       private Map<String,String> defaultServletHeaders, defaultMethodHeaders, 
overriddenHeaders, overriddenQueryParams, overriddenFormDataParams, 
pathParameters;
-       private boolean isPost;
-       private String servletURI, relativeServletURI;
-       private String charset, defaultCharset;
-       private ObjectMap headers;
-       private ConfigFile cf;
-       private Swagger swagger, fileSwagger;
-
-       /**
-        * Constructor.
-        */
-       RestRequest(RestServlet servlet, HttpServletRequest req) throws 
ServletException {
-               super(req);
-
-               try {
-                       this.servlet = servlet;
-                       isPost = req.getMethod().equalsIgnoreCase("POST");
-
-                       // If this is a POST, we want to parse the query 
parameters ourselves to prevent
-                       // the servlet code from processing the HTTP body as 
URL-Encoded parameters.
-                       if (isPost)
-                               queryParams = 
servlet.getUrlEncodingParser().parseIntoSimpleMap(getQueryString());
-                       else {
-                               queryParams = req.getParameterMap();
-                       }
-
-                       // Get the HTTP method.
-                       // Can be overridden through a "method" GET attribute.
-                       method = super.getMethod();
-
-                       String m = getQueryParameter("method");
-                       if (! StringUtils.isEmpty(m) && 
(servlet.context.allowMethodParams.contains(m) || 
servlet.context.allowMethodParams.contains("*")))
-                               method = m;
-
-                       if (servlet.context.allowBodyParam)
-                               body = getQueryParameter("body");
-
-                       defaultServletHeaders = 
servlet.getDefaultRequestHeaders();
-
-                       debug = "true".equals(getQueryParameter("debug", 
"false"));
-
-                       if (debug) {
-                               servlet.log(Level.INFO, toString());
-                       }
-
-               } catch (RestException e) {
-                       throw e;
-               } catch (Exception e) {
-                       throw new ServletException(e);
-               }
-       }
-
-       /*
-        * Called from RestServlet after a match has been made but before the 
guard or method invocation.
-        */
-       @SuppressWarnings("hiding")
-       final void init(Method javaMethod, String pathRemainder, ObjectMap 
properties, Map<String,String> mDefaultRequestHeaders, String defaultCharset, 
SerializerGroup mSerializers, ParserGroup mParsers, UrlEncodingParser 
mUrlEncodingParser) {
-               this.javaMethod = javaMethod;
-               this.pathRemainder = pathRemainder;
-               this.properties = properties;
-               this.defaultMethodHeaders = mDefaultRequestHeaders;
-               this.serializerGroup = mSerializers;
-               this.parserGroup = mParsers;
-               this.urlEncodingParser = mUrlEncodingParser;
-               this.beanSession = 
urlEncodingParser.getBeanContext().createSession();
-               this.defaultCharset = defaultCharset;
-       }
-
-       /**
-        * Returns a string of the form <js>"HTTP method-name full-url"</js>
-        *
-        * @return A description of the request.
-        */
-       public String getDescription() {
-               String qs = getQueryString();
-               return "HTTP " + getMethod() + " " + getRequestURI() + (qs == 
null ? "" : "?" + qs);
-       }
-
-       
//--------------------------------------------------------------------------------
-       // Properties
-       
//--------------------------------------------------------------------------------
-
-       /**
-        * Servlet calls this method to initialize the properties.
-        */
-       RestRequest setProperties(ObjectMap properties) {
-               this.properties = properties;
-               return this;
-       }
-
-       /**
-        * Retrieve the properties active for this request.
-        * <p>
-        *      These properties can be modified by the request.
-        *
-        * @return The properties active for this request.
-        */
-       public ObjectMap getProperties() {
-               return this.properties;
-       }
-
-       
//--------------------------------------------------------------------------------
-       // Headers
-       
//--------------------------------------------------------------------------------
-
-       /**
-        * Sets a request header value.
-        *
-        * @param name The header name.
-        * @param value The header value.
-        */
-       public void setHeader(String name, String value) {
-               if (overriddenHeaders == null)
-                       overriddenHeaders = new 
TreeMap<String,String>(String.CASE_INSENSITIVE_ORDER);
-               overriddenHeaders.put(name, value);
-       }
-
-
-       /**
-        * 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.
-        */
-       @Override /* ServletRequest */
-       public String getHeader(String name) {
-               return getHeader(name, (String)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 getHeader(String name, String def) {
-               String h = getOverriddenHeader(name);
-               if (h != null)
-                       return h;
-               h = super.getHeader(name);
-               if (h != null && ! h.isEmpty())
-                       return h;
-               if (defaultMethodHeaders != null) {
-                       h = defaultMethodHeaders.get(name);
-                       if (h != null)
-                               return h;
-               }
-               h = defaultServletHeaders.get(name);
-               if (h != null)
-                       return h;
-               return def;
-       }
-
-       /**
-        * 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>).
-        *
-        * @param name The HTTP header name.
-        * @param c The class type to convert the header value to.
-        * @param def The default value if the header was not specified or is 
<jk>null</jk>.
-        * @param <T> The class type to convert the header value to.
-        * @return The parameter value converted to the specified class type.
-        */
-       public <T> T getHeader(String name, Class<T> c, T def) {
-               String h = getHeader(name);
-               if (h == null)
-                       return def;
-               return beanSession.convertToType(h, c);
-       }
-
-       /**
-        * 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>).
-        *
-        * @param name The HTTP header name.
-        * @param c 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 getHeader(String name, Class<T> c) {
-               String h = getHeader(name);
-               return beanSession.convertToType(h, c);
-       }
-
-       /**
-        * Same as {@link #getHeader(String, Class)} except works on 
parameterized
-        * types such as those returned by {@link 
Method#getGenericParameterTypes()}
-        *
-        * @param name The HTTP header name.
-        * @param c 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 getHeader(String name, Type c) {
-               String h = getHeader(name);
-               return (T)beanSession.convertToType(null, h, 
beanSession.getClassMeta(c));
-       }
-
-       /**
-        * Returns all the request headers as an {@link ObjectMap}.
-        * <p>
-        *      Altering entries in this map does not alter headers in the 
underlying request.
-        *
-        * @return The request headers.  Never <jk>null</jk>.
-        */
-       public ObjectMap getHeaders() {
-               if (headers == null) {
-                       headers = new ObjectMap();
-                       for (Enumeration<String> e = getHeaderNames(); 
e.hasMoreElements();) {
-                               String key = e.nextElement();
-                               headers.put(key, getHeader(key));
-                       }
-               }
-               return headers;
-       }
-
-       @Override /* ServletRequest */
-       public Enumeration<String> getHeaders(String name) {
-               String h = getOverriddenHeader(name);
-               if (h != null)
-                       return enumeration(singleton(h));
-               return super.getHeaders(name);
-       }
-
-       /**
-        * Returns the <code>Content-Type</code> header value on the request, 
stripped
-        *      of any parameters such as <js>";charset=X"</js>.
-        * <p>
-        *      Example: <js>"text/json"</js>.
-        * <p>
-        *      If the content type is not specified, and the content is 
specified via a
-        *      <code>&body</code> query parameter, the content type is assumed 
to be
-        *      <js>"text/uon"</js>.  Otherwise, the content type is assumed to 
be <js>"text/json"</js>.
-        *
-        * @return The <code>Content-Type</code> media-type header value on the 
request.
-        */
-       public String getMediaType() {
-               String cm = getHeader("Content-Type");
-               if (cm == null) {
-                       if (body != null)
-                               return "text/uon";
-                       return "text/json";
-               }
-               int j = cm.indexOf(';');
-               if (j != -1)
-                       cm = cm.substring(0, j);
-               return cm;
-       }
-
-       /**
-        * 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 = getHeader("Time-Zone");
-               if (tz != null)
-                       return TimeZone.getTimeZone(tz);
-               return null;
-       }
-
-       /**
-        * Returns the media types that are valid for <code>Content-Type</code> 
headers on the request.
-        *
-        * @return The set of media types registered in the parser group of 
this request.
-        */
-       public List<String> getSupportedMediaTypes() {
-               return parserGroup.getSupportedMediaTypes();
-       }
-
-       /**
-        * Sets the charset to expect on the request body.
-        */
-       @Override /* ServletRequest */
-       public void setCharacterEncoding(String charset) {
-               this.charset = charset;
-       }
-
-       /**
-        * Returns the charset specified on the <code>Content-Type</code> 
header, or
-        * <js>"UTF-8"</js> if not specified.
-        */
-       @Override /* ServletRequest */
-       public String getCharacterEncoding() {
-               if (charset == null) {
-                       // Determine charset
-                       // NOTE:  Don't use super.getCharacterEncoding() 
because the spec is implemented inconsistently.
-                       // Jetty returns the default charset instead of null if 
the character is not specified on the request.
-                       String h = getHeader("Content-Type");
-                       if (h != null) {
-                               int i = h.indexOf(";charset=");
-                               if (i > 0)
-                                       charset = h.substring(i+9).trim();
-                       }
-                       if (charset == null)
-                               charset = defaultCharset;
-                       if (! 
RestServlet.availableCharsets.containsKey(charset))
-                               throw new 
RestException(SC_UNSUPPORTED_MEDIA_TYPE, "Unsupported charset in header 
''Content-Type'': ''{0}''", h);
-               }
-               return charset;
-       }
-
-       @Override /* ServletRequest */
-       public Locale getLocale() {
-               String h = getOverriddenHeader("Accept-Language");
-               if (h != null) {
-                       MediaRange[] mr = MediaRange.parse(h);
-                       if (mr.length > 0)
-                               return toLocale(mr[0].getType());
-               }
-               return super.getLocale();
-       }
-
-       @Override /* ServletRequest */
-       public Enumeration<Locale> getLocales() {
-               String h = getOverriddenHeader("Accept-Language");
-               if (h != null) {
-                       MediaRange[] mr = MediaRange.parse(h);
-                       if (mr.length > 0) {
-                               List<Locale> l = new 
ArrayList<Locale>(mr.length);
-                               for (MediaRange r : mr)
-                                       l.add(toLocale(r.getType()));
-                               return enumeration(l);
-                       }
-               }
-               return super.getLocales();
-       }
-
-       
//--------------------------------------------------------------------------------
-       // Query parameters
-       
//--------------------------------------------------------------------------------
-
-       /**
-        * Sets a request query parameter value.
-        *
-        * @param name The parameter name.
-        * @param value The parameter value.
-        */
-       public void setQueryParameter(String name, Object value) {
-               if (overriddenQueryParams == null)
-                       overriddenQueryParams = new 
TreeMap<String,String>(String.CASE_INSENSITIVE_ORDER);
-               overriddenQueryParams.put(name, value == null ? null : 
value.toString());
-       }
-
-       /**
-        * Returns a query parameter value.
-        * <p>
-        *      Same as {@link #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>"&foo"</js>.
-        */
-       public String getQueryParameter(String name) {
-               String s = null;
-               if (overriddenQueryParams != null)
-                       s = overriddenQueryParams.get(name);
-               if (s != null)
-                       return s;
-               String[] v = queryParams.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 (queryParams.containsKey(name))
-                               return null;
-               }
-               return v[0];
-       }
-
-       /**
-        * Same as {@link #getQueryParameter(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>"&foo"</js>.
-        */
-       public String getQueryParameter(String name, String def) {
-               String s = getQueryParameter(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.
-        *
-        * @param name The parameter name.
-        * @param c The class type to convert the parameter value to.
-        * @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 getQueryParameter(String name, Class<T> c, T def) throws 
ParseException {
-               return getQueryParameter(name, beanSession.getClassMeta(c), 
def);
-       }
-
-       /**
-        * 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.
-        *
-        * @param name The parameter name.
-        * @param cm The class type to convert the parameter value to.
-        * @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 getQueryParameter(String name, ClassMeta<T> cm, T def) 
throws ParseException {
-               String val = getQueryParameter(name);
-               if (val == null)
-                       return def;
-               return parseParameter(val, cm);
-       }
-
-       /**
-        * 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.
-        *
-        * @param name The 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 parameter value converted to the specified class type.
-        * @throws ParseException
-        */
-       public <T> T getQueryParameter(String name, Class<T> c) throws 
ParseException {
-               return getQueryParameter(name, beanSession.getClassMeta(c));
-       }
-
-       /**
-        * Same as {@link #getQueryParameter(String, Class)} except for use on 
multi-part parameters
-        *      (e.g. <js>"&key=1&key=2&key=3"</js> instead of 
<js>"&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 getQueryParameters(String name, Class<T> c) throws 
ParseException {
-               return getQueryParameters(name, beanSession.getClassMeta(c));
-       }
-
-       /**
-        * Same as {@link #getQueryParameter(String, Class)} except works on 
parameterized
-        * types such as those returned by {@link 
Method#getGenericParameterTypes()}
-        *
-        * @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 getQueryParameter(String name, Type c) throws 
ParseException {
-               return (T)getQueryParameter(name, beanSession.getClassMeta(c));
-       }
-
-       /**
-        * Same as {@link #getQueryParameter(String, Type)} except for use on 
multi-part parameters
-        *      (e.g. <js>"&key=1&key=2&key=3"</js> instead of 
<js>"&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 getQueryParameters(String name, Type c) throws 
ParseException {
-               return (T)getQueryParameters(name, beanSession.getClassMeta(c));
-       }
-
-       /**
-        * 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.
-        *
-        * @param name The parameter name.
-        * @param cm 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 getQueryParameter(String name, ClassMeta<T> cm) throws 
ParseException {
-
-               String val = getQueryParameter(name);
-
-               if (cm.isPrimitive() && (val == null || val.isEmpty()))
-                       return cm.getPrimitiveDefault();
-               return parseParameter(val, cm);
-       }
-
-       /**
-        * Same as {@link #getQueryParameter(String, ClassMeta)} except for use 
on multi-part parameters
-        *      (e.g. <js>"&key=1&key=2&key=3"</js> instead of 
<js>"&key=(1,2,3)"</js>).
-        * <p>
-        *      This method must only be called when parsing into classes of 
type Collection or array.
-        *
-        * @param name The parameter name.
-        * @param cm 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
-        */
-       @SuppressWarnings("rawtypes")
-       public <T> T getQueryParameters(String name, ClassMeta<T> cm) throws 
ParseException {
-               String[] p = getQueryParameters(name);
-               if (p == null)
-                       return null;
-               if (cm.isArray()) {
-                       List c = new ArrayList();
-                       for (int i = 0; i < p.length; i++)
-                               c.add(parseParameter(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(parseParameter(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.");
-       }
-
-       /**
-        * Returns the list of all query parameters with the specified name.
-        * <p>
-        *      Same as {@link #getParameterValues(String)} except only looks 
in the URL string,
-        *      not parameters from URL-Encoded FORM posts.
-        * <p>
-        *      This method can be used to retrieve parameters without 
triggering the underlying
-        *      servlet API to load and parse the request body.
-        *
-        * @param name
-        * @return the list of query parameters, or <jk>null</jk> if the 
parameter does not exist.
-        */
-       public String[] getQueryParameters(String name) {
-               return queryParams.get(name);
-       }
-
-       /**
-        * Returns <jk>true</jk> if the query parameters on this request 
contains the specified entry.
-        * <p>
-        *      Note that this returns <jk>true</jk> even if the value is set 
to null (e.g. <js>"?key"</js>).
-        * <p>
-        *      This method can be used to check the existence of a parameter 
without triggering the underlying
-        *      servlet API to load and parse the request body.
-        *
-        * @param name The URL parameter name.
-        * @return <jk>true</jk> if the URL parameters on this request contains 
the specified entry.
-        */
-       public boolean hasQueryParameter(String name) {
-               return queryParams.containsKey(name);
-       }
-
-       /**
-        * 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 hasAnyQueryParameters(String...params) {
-               for (String p : params)
-                       if (hasQueryParameter(p))
-                               return true;
-               return false;
-       }
-
-       /**
-        * Equivalent to {@link #getParameterMap()}, but only looks for query 
parameters in the URL, not form posts.
-        * <p>
-        *      This method can be used to retrieve query parameters without 
triggering the underlying
-        *      servlet API to load and parse the request body.
-        * <p>
-        *      This object is modifiable.
-        *
-        * @return The query parameters as a modifiable map.
-        */
-       public Map<String,String[]> getQueryParameterMap() {
-               return queryParams;
-       }
-
-       /**
-        * Equivalent to {@link #getParameterNames()}, but only looks for query 
parameters in the URL, not form posts.
-        * <p>
-        *      This method can be used to retrieve query parameters without 
triggering the underlying
-        *      servlet API to load and parse the request body.
-        * <p>
-        *      This object is modifiable.
-        *
-        * @return An iterator of query parameter names.
-        */
-       public Iterator<String> getQueryParameterNames() {
-               return queryParams.keySet().iterator();
-       }
-
-       
//--------------------------------------------------------------------------------
-       // Form data parameters
-       
//--------------------------------------------------------------------------------
-
-       /**
-        * Sets a request form data parameter value.
-        *
-        * @param name The parameter name.
-        * @param value The parameter value.
-        */
-       public void setFormDataParameter(String name, Object value) {
-               if (overriddenFormDataParams == null)
-                       overriddenFormDataParams = new 
TreeMap<String,String>(String.CASE_INSENSITIVE_ORDER);
-               overriddenFormDataParams.put(name, value == null ? null : 
value.toString());
-       }
-
-       /**
-        * Returns a form data parameter value.
-        * <p>
-        *      Parameter lookup is case-insensitive (consistent with WAS, but 
differs from Tomcat).
-        * <p>
-        *      <i>Note:</i> Calling this method on URL-Encoded FORM posts 
causes the body content to be loaded and parsed by
-        *      the underlying servlet API.
-        * <p>
-        *      <i>Note:</i> This method returns the raw unparsed value, and 
differs from calling <code>getFormDataParameter(name, 
String.<jk>class</js>)</code>
-        *      which will convert the value from UON notation:
-        * <ul>
-        *      <li><js>"\u0000"</js> =&gt; <jk>null</jk>
-        *      <li><js>"$s(foo)"</js> =&gt; <js>"foo"</js>
-        *      <li><js>"(foo)"</js> =&gt; <js>"foo"</js>
-        * </ul>
-        *
-        * @param name The form data parameter name.
-        * @return The parameter value, or <jk>null</jk> if parameter does not 
exist.
-        */
-       public String getFormDataParameter(String name) {
-               String s = null;
-               if (overriddenFormDataParams != null)
-                       s = overriddenFormDataParams.get(name);
-               if (s != null)
-                       return s;
-
-               return super.getParameter(name);
-       }
-
-       /**
-        * Same as {@link #getFormDataParameter(String)} except returns a 
default value if <jk>null</jk> or empty.
-        *
-        * @param name The form data parameter name.
-        * @param def The default value.
-        * @return The parameter value, or the default value if <jk>null</jk> 
or empty.
-        */
-       public String getFormDataParameter(String name, String def) {
-               String val = getParameter(name);
-               if (val == null || val.isEmpty())
-                       return def;
-               return val;
-       }
-
-       /**
-        * Returns the specified form data parameter value converted to a POJO 
using the
-        *      {@link UrlEncodingParser} registered with this servlet.
-        * <p>
-        *      <i>Note:</i> Calling this method on URL-Encoded FORM posts 
causes the body content to be loaded and parsed by
-        *      the underlying servlet API.
-        *
-        * @param name The parameter name.
-        * @param c The class type to convert the parameter value to.
-        * @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 getFormDataParameter(String name, Class<T> c, T def) 
throws ParseException {
-               return getFormDataParameter(name, beanSession.getClassMeta(c), 
def);
-       }
-
-       /**
-        * Returns the specified form data parameter value converted to a POJO 
using the
-        *      {@link UrlEncodingParser} registered with this servlet.
-        * <p>
-        *      <i>Note:</i> Calling this method on URL-Encoded FORM posts 
causes the body content to be loaded and parsed by
-        *      the underlying servlet API.
-        * <p>
-        *      Unlike {@link #getFormDataParameter(String, Class, Object)}, 
this method can be used to parse parameters
-        *      of complex types involving JCF classes.
-        * <p class='bcode'>
-        *      ClassMeta&ltMap&lt;String,Integer&gt;&gt; cm = 
request.getBeanContext().getMapClassMeta(TreeMap.<jk>class</jk>, 
String.<jk>class</jk>, Integer.<jk>class</jk>);
-        *      Map&lt;String,Integer&gt; m = 
request.getFormDataParameter(<js>"myParameter"</js>, cm, <jk>new</jk> 
TreeMap&lt;String,Integer&gt;());
-        * </p>
-        *
-        * @param name The parameter name.
-        * @param cm The class type to convert the parameter value to.
-        * @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 getFormDataParameter(String name, ClassMeta<T> cm, T def) 
throws ParseException {
-               String val = getParameter(name);
-               if (val == null)
-                       return def;
-               return parseParameter(val, cm);
-       }
-
-       /**
-        * Returns the specified form data parameter value converted to a POJO 
using the
-        *      {@link UrlEncodingParser} registered with this servlet.
-        * <p>
-        * <i>Note:</i> Calling this method on URL-Encoded FORM posts causes 
the body content to be loaded and parsed by
-        *      the underlying servlet API.
-        *
-        * @param name The 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 parameter value converted to the specified class type.
-        * @throws ParseException
-        */
-       public <T> T getFormDataParameter(String name, Class<T> c) throws 
ParseException {
-               return getFormDataParameter(name, beanSession.getClassMeta(c));
-       }
-
-       /**
-        * Same as {@link #getFormDataParameter(String, Class)} except for use 
on multi-part parameters
-        *      (e.g. <js>"key=1&key=2&key=3"</js> instead of 
<js>"key=(1,2,3)"</js>)
-        * <p>
-        *      This method must only be called when parsing into classes of 
type Collection or array.
-        *
-        * @param name The parameter name.
-        * @param c The class type to convert the parameter value to.
-        * @return The parameter value converted to the specified class type.
-        * @throws ParseException
-        */
-       public <T> T getFormDataParameters(String name, Class<T> c) throws 
ParseException {
-               return getFormDataParameters(name, beanSession.getClassMeta(c));
-       }
-
-       /**
-        * Same as {@link #getFormDataParameter(String, Class)} except works on 
parameterized
-        * types such as those returned by {@link 
Method#getGenericParameterTypes()}
-        *
-        * @param name The parameter name.
-        * @param c The class type to convert the parameter value to.
-        * @return The parameter value converted to the specified class type.
-        * @throws ParseException
-        */
-       public <T> T getFormDataParameter(String name, Type c) throws 
ParseException {
-               return (T)getFormDataParameter(name, 
beanSession.getClassMeta(c));
-       }
-
-       /**
-        * Same as {@link #getFormDataParameter(String, Class)} except for use 
on multi-part parameters
-        *      (e.g. <js>"key=1&key=2&key=3"</js> instead of 
<js>"key=(1,2,3)"</js>)
-        * <p>
-        *      This method must only be called when parsing into classes of 
type Collection or array.
-        *
-        * @param name The parameter name.
-        * @param c The class type to convert the parameter value to.
-        * @return The parameter value converted to the specified class type.
-        * @throws ParseException
-        */
-       public <T> T getFormDataParameters(String name, Type c) throws 
ParseException {
-               return (T)getFormDataParameters(name, 
beanSession.getClassMeta(c));
-       }
-
-       /**
-        * Returns the specified form data parameter value converted to a POJO 
using the
-        *      {@link UrlEncodingParser} registered with this servlet.
-        * <p>
-        *      <i>Note:</i> Calling this method on URL-Encoded FORM posts 
causes the body content to be loaded and parsed by
-        *      the underlying servlet API.
-        * <p>
-        *      Unlike {@link #getFormDataParameter(String, Class)}, this 
method can be used to parse parameters
-        *      of complex types involving JCF classes.
-        * <p class='bcode'>
-        *      ClassMeta&lt;Map&lt;String,Integer&gt;&gt; cm = 
request.getBeanContext().getMapClassMeta(TreeMap.<jk>class</jk>, 
String.<jk>class</jk>, Integer.<jk>class</jk>);
-        *      Map&lt;String,Integer&gt; m = 
request.getFormDataParameter(<js>"myParameter"</js>, cm);
-        * </p>
-        *
-        * @param name The parameter name.
-        * @param cm 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 getFormDataParameter(String name, ClassMeta<T> cm) throws 
ParseException {
-
-               String val = getParameter(name);
-
-               if (cm.isPrimitive() && (val == null || val.isEmpty()))
-                       return cm.getPrimitiveDefault();
-
-               return parseParameter(val, cm);
-       }
-
-       /**
-        * Same as {@link #getFormDataParameter(String, ClassMeta)} except for 
use on multi-part parameters
-        *      (e.g. <js>"key=1&key=2&key=3"</js> instead of 
<js>"key=(1,2,3)"</js>)
-        * <p>
-        *      This method must only be called when parsing into classes of 
type Collection or array.
-        *
-        * @param name The parameter name.
-        * @param cm 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
-        */
-       @SuppressWarnings("rawtypes")
-       public <T> T getFormDataParameters(String name, ClassMeta<T> cm) throws 
ParseException {
-               String[] p = getParameterValues(name);
-               if (p == null)
-                       return null;
-               if (cm.isArray()) {
-                       List c = new ArrayList();
-                       for (int i = 0; i < p.length; i++)
-                               c.add(parseParameter(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(parseParameter(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 getParameters(String, 
ClassMeta).  Class type must be a Collection or array.");
-       }
-
-       /**
-        * Returns <jk>true</jk> if the form data parameters on this request 
contains the specified entry.
-        * <p>
-        *      Note that this returns <jk>true</jk> even if the value is set 
to null (e.g. <js>"?key"</js>).
-        *
-        * @param name The URL parameter name.
-        * @return <jk>true</jk> if the URL parameters on this request contains 
the specified entry.
-        */
-       public boolean hasFormDataParameter(String name) {
-               return getParameterMap().containsKey(name);
-       }
-
-       
//--------------------------------------------------------------------------------
-       // Path parameters
-       
//--------------------------------------------------------------------------------
-
-       /**
-        * Sets a path parameter value.
-        * <p>
-        *      A path parameter is a variable in the path pattern such as 
<js>"/{foo}"</js>
-        *
-        * @param name The parameter name.
-        * @param value The parameter value.
-        */
-       public void setPathParameter(String name, String value) {
-               if (pathParameters == null)
-                       pathParameters = new 
TreeMap<String,String>(String.CASE_INSENSITIVE_ORDER);
-               pathParameters.put(name, value == null ? null : 
value.toString());
-       }
-
-       /**
-        * Returns a path parameter value.
-        * <p>
-        *      A path parameter is a variable in the path pattern such as 
<js>"/{foo}"</js>
-        *
-        * @param name The parameter name.
-        * @return The paramter value, or <jk>null</jk> if path parameter not 
specified.
-        */
-       public String getPathParameter(String name) {
-               return (pathParameters == null ? null : 
pathParameters.get(name));
-       }
-
-       /**
-        * 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>).
-        *
-        * @param name The attribute name.
-        * @param c 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 getPathParameter(String name, Class<T> c) throws 
ParseException {
-               return getPathParameter(name, beanSession.getClassMeta(c));
-       }
-
-       /**
-        * Same as {@link #getPathParameter(String, Class)} except works on 
parameterized
-        * types such as those returned by {@link 
Method#getGenericParameterTypes()}
-        *
-        * @param name The attribute name.
-        * @param c 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 getPathParameter(String name, Type c) throws 
ParseException {
-               return (T)getPathParameter(name, beanSession.getClassMeta(c));
-       }
-
-       /**
-        * 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>).
-        *
-        * @param name The attribute name.
-        * @param cm 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 getPathParameter(String name, ClassMeta<T> cm) throws 
ParseException {
-               Object attr = getPathParameter(name);
-               T t = null;
-               if (attr != null)
-                       t = urlEncodingParser.parseParameter(attr.toString(), 
cm);
-               if (t == null && cm.isPrimitive())
-                       return cm.getPrimitiveDefault();
-               return t;
-       }
-
-       
//--------------------------------------------------------------------------------
-       // Body methods
-       
//--------------------------------------------------------------------------------
-
-       /**
-        * Same as {@link #getBody(ClassMeta)}, except a shortcut for passing 
in regular {@link Class} objects
-        *      instead of having to look up {@link ClassMeta} objects.
-        *
-        * @param type The class type to instantiate.
-        * @param <T> The class type to instantiate.
-        * @return The input parsed to a POJO.
-        * @throws IOException If a problem occurred trying to read from the 
reader.
-        * @throws ParseException If the input contains a syntax error or is 
malformed for the requested {@code Accept} header or is not valid for the 
specified type.
-        */
-       public <T> T getBody(Class<T> type) throws IOException, ParseException {
-               return getBody(beanSession.getClassMeta(type));
-       }
-
-       /**
-        * Same as {@link #getBody(Class)} except works on parameterized
-        * types such as those returned by {@link 
Method#getGenericParameterTypes()}
-        *
-        * @param type The class type to instantiate.
-        * @param <T> The class type to instantiate.
-        * @return The input parsed to a POJO.
-        */
-       public <T> T getBody(Type type) {
-               return (T)getBody(beanSession.getClassMeta(type));
-       }
-
-       /**
-        * Reads the input from the HTTP request as JSON, XML, or HTML and 
converts the input to a POJO.
-        * <p>
-        *      If {@code allowHeaderParams} init parameter is <jk>true</jk>, 
then first looks
-        *      for {@code &body=xxx} in the URL query string.
-        * <p>
-        *      If type is <jk>null</jk> or <code>Object.<jk>class</jk></code>, 
then the actual type will be determined automatically based on the
-        *      following input:
-        *      <table class='styled'>
-        *              <tr><th>Type</th><th>JSON input</th><th>XML 
input</th><th>Return type</th></tr>
-        *              <tr>
-        *                      <td>object</td>
-        *                      <td><js>"{...}"</js></td>
-        *                      
<td><code><xt>&lt;object&gt;</xt>...<xt>&lt;/object&gt;</xt></code><br><code><xt>&lt;x</xt>
 <xa>type</xa>=<xs>'object'</xs><xt>&gt;</xt>...<xt>&lt;/x&gt;</xt></code></td>
-        *                      <td>{@link ObjectMap}</td>
-        *              </tr>
-        *              <tr>
-        *                      <td>array</td>
-        *                      <td><js>"[...]"</js></td>
-        *                      
<td><code><xt>&lt;array&gt;</xt>...<xt>&lt;/array&gt;</xt></code><br><code><xt>&lt;x</xt>
 <xa>type</xa>=<xs>'array'</xs><xt>&gt;</xt>...<xt>&lt;/x&gt;</xt></code></td>
-        *                      <td>{@link ObjectList}</td>
-        *              </tr>
-        *              <tr>
-        *                      <td>string</td>
-        *                      <td><js>"'...'"</js></td>
-        *                      
<td><code><xt>&lt;string&gt;</xt>...<xt>&lt;/string&gt;</xt></code><br><code><xt>&lt;x</xt>
 <xa>type</xa>=<xs>'string'</xs><xt>&gt;</xt>...<xt>&lt;/x&gt;</xt></code></td>
-        *                      <td>{@link String}</td>
-        *              </tr>
-        *              <tr>
-        *                      <td>number</td>
-        *                      <td><code>123</code></td>
-        *                      
<td><code><xt>&lt;number&gt;</xt>123<xt>&lt;/number&gt;</xt></code><br><code><xt>&lt;x</xt>
 <xa>type</xa>=<xs>'number'</xs><xt>&gt;</xt>...<xt>&lt;/x&gt;</xt></code></td>
-        *                      <td>{@link Number}</td>
-        *              </tr>
-        *              <tr>
-        *                      <td>boolean</td>
-        *                      <td><jk>true</jk></td>
-        *                      
<td><code><xt>&lt;boolean&gt;</xt>true<xt>&lt;/boolean&gt;</xt></code><br><code><xt>&lt;x</xt>
 <xa>type</xa>=<xs>'boolean'</xs><xt>&gt;</xt>...<xt>&lt;/x&gt;</xt></code></td>
-        *                      <td>{@link Boolean}</td>
-        *              </tr>
-        *              <tr>
-        *                      <td>null</td>
-        *                      <td><jk>null</jk> or blank</td>
-        *                      <td><code><xt>&lt;null/&gt;</xt></code> or 
blank<br><code><xt>&lt;x</xt> 
<xa>type</xa>=<xs>'null'</xs><xt>/&gt;</xt></code></td>
-        *                      <td><jk>null</jk></td>
-        *              </tr>
-        *      </table>
-        * <p>
-        *      Refer to <a 
href='../../../../overview-summary.html#Core.PojoCategories' 
class='doclink'>POJO Categories</a> for a complete definition of supported 
POJOs.
-        *
-        * @param type The class type to instantiate.
-        * @param <T> The class type to instantiate.
-        * @return The input parsed to a POJO.
-        * @throws RestException If a problem occurred trying to read the input.
-        */
-       public <T> T getBody(ClassMeta<T> type) throws RestException {
-
-               try {
-                       if (type.isReader())
-                               return (T)getReader();
-
-                       if (type.isInputStream())
-                               return (T)getInputStream();
-
-                       String mediaType = getMediaType();
-                       TimeZone timeZone = getTimeZone();
-                       Locale locale = getLocale();
-                       Parser p = getParser();
-
-                       if (p != null) {
-                               try {
-                                       properties.append("mediaType", 
mediaType).append("characterEncoding", getCharacterEncoding());
-                                       if (! p.isReaderParser()) {
-                                               InputStreamParser p2 = 
(InputStreamParser)p;
-                                               ParserSession session = 
p2.createSession(getInputStream(), properties, getJavaMethod(), getServlet(), 
locale, timeZone);
-                                               return p2.parse(session, type);
-                                       }
-                                       ReaderParser p2 = (ReaderParser)p;
-                                       ParserSession session = 
p2.createSession(getUnbufferedReader(), properties, getJavaMethod(), 
getServlet(), locale, timeZone);
-                                       return p2.parse(session, type);
-                               } catch (ParseException e) {
-                                       throw new RestException(SC_BAD_REQUEST,
-                                               "Could not convert request body 
content to class type ''{0}'' using parser ''{1}''.",
-                                               type, p.getClass().getName()
-                                       ).initCause(e);
-                               }
-                       }
-
-                       throw new RestException(SC_UNSUPPORTED_MEDIA_TYPE,
-                               "Unsupported media-type in request header 
''Content-Type'': ''{0}''\n\tSupported media-types: {1}",
-                               getHeader("Content-Type"), 
parserGroup.getSupportedMediaTypes()
-                       );
-
-               } catch (IOException e) {
-                       throw new RestException(SC_INTERNAL_SERVER_ERROR,
-                               "I/O exception occurred while attempting to 
handle request ''{0}''.",
-                               getDescription()
-                       ).initCause(e);
-               }
-       }
-
-       /**
-        * Returns the HTTP body content as a plain string.
-        * <p>
-        *      If {@code allowHeaderParams} init parameter is true, then first 
looks
-        *      for {@code &body=xxx} in the URL query string.
-        *
-        * @return The incoming input from the connection as a plain string.
-        * @throws IOException If a problem occurred trying to read from the 
reader.
-        */
-       public String getBodyAsString() throws IOException {
-               if (body != null)
-                       return body;
-               body = IOUtils.read(getReader()).toString();
-               return body;
-       }
-
-       /**
-        * Returns the HTTP body content as a {@link Reader}.
-        * <p>
-        *      If {@code allowHeaderParams} init parameter is true, then first 
looks
-        *      for {@code &body=xxx} in the URL query string.
-        * <p>
-        *      Automatically handles GZipped input streams.
-        */
-       @Override /* ServletRequest */
-       public BufferedReader getReader() throws IOException {
-               Reader r = getUnbufferedReader();
-               if (r instanceof BufferedReader)
-                       return (BufferedReader)r;
-               int len = getContentLength();
-               int buffSize = len <= 0 ? 8192 : Math.max(len, 8192);
-               return new BufferedReader(r, buffSize);
-       }
-
-       /**
-        * Same as {@link #getReader()}, but doesn't encapsulate the result in 
a {@link BufferedReader};
-        *
-        * @return An unbuffered reader.
-        * @throws IOException
-        */
-       protected Reader getUnbufferedReader() throws IOException {
-               if (body != null)
-                       return new CharSequenceReader(body);
-               return new InputStreamReader(getInputStream(), 
getCharacterEncoding());
-       }
-
-       /**
-        * Returns the HTTP body content as an {@link InputStream}.
-        * <p>
-        *      Automatically handles GZipped input streams.
-        *
-        * @return The negotiated input stream.
-        * @throws IOException If any error occurred while trying to get the 
input stream or wrap it
-        *      in the GZIP wrapper.
-        */
-       @Override /* ServletRequest */
-       public ServletInputStream getInputStream() throws IOException {
-
-               Encoder enc = getEncoder();
-
-               ServletInputStream is = super.getInputStream();
-               if (enc != null) {
-                       final InputStream is2 = enc.getInputStream(is);
-                       return new ServletInputStream() {
-                               @Override /* InputStream */
-                               public final int read() throws IOException {
-                                       return is2.read();
-                               }
-                               @Override /* InputStream */
-                               public final void close() throws IOException {
-                                       is2.close();
-                               }
-                       };
-               }
-               return is;
-       }
-
-       
//--------------------------------------------------------------------------------
-       // URI-related methods
-       
//--------------------------------------------------------------------------------
-
-       /**
-        * Same as {@link HttpServletRequest#getPathInfo()} except returns the 
path undecoded.
-        *
-        * @return The undecoded portion of the URL after the resource URL path 
pattern match.
-        */
-       public String getPathInfoUndecoded() {
-               return RestUtils.getPathInfoUndecoded(this);
-       }
-
-       /**
-        * Returns the value {@link #getPathInfo()} split on the <js>'/'</js> 
character.
-        * <p>
-        *      If path info is <jk>null</jk>, returns an empty list.
-        * <p>
-        *      URL-encoded characters in segments are automatically decoded by 
this method.
-        *
-        * @return The decoded segments, or an empty list if path info is 
<jk>null</jk>.
-        */
-       public String[] getPathInfoParts() {
-               String s = getPathInfoUndecoded();
-               if (s == null || s.isEmpty() || s.equals("/"))
-                       return new String[0];
-               s = s.substring(1);
-               if (s.endsWith("/"))
-                       s = s.substring(0, s.length()-1);
-               boolean needsDecode = (s.indexOf('%') != -1 || s.indexOf('+') 
!= -1);
-               String[] l = s.split("/", Integer.MAX_VALUE);
-               try {
-                       if (needsDecode)
-                               for (int i = 0; i < l.length; i++)
-                                       l[i] = URLDecoder.decode(l[i], "UTF-8");
-               } catch (UnsupportedEncodingException e) {
-                       e.printStackTrace();  // Won't happen.
-               }
-               return l;
-       }
-
-       /**
-        * Returns a resolved URL.
-        * <p>
-        * <ul class='spaced-list'>
-        *      <li>Fully-qualified absolute URLs (e.g. <js>"http://...";</js>, 
<js>"https://";</js>) are simply converted to a URL.
-        *      <li>Absolute URLs (e.g. <js>"/foo/..."</js>) are interpreted as 
relative to the server hostname.
-        *      <li>Relative URLs (e.g. <js>"foo/..."</js>) are interpreted as 
relative to this servlet path.
-        * </ul>
-        *
-        * @param path The URL path to resolve.
-        * @return The resolved URL.
-        * @throws MalformedURLException If path is not a valid URL component.
-        */
-       public URL getURL(String path) throws MalformedURLException {
-               if (path.startsWith("http://";) || path.startsWith("https://";))
-                       return new URL(path);
-               if (StringUtils.startsWith(path, '/'))
-                       return new URL(getScheme(), getLocalName(), 
getLocalPort(), path);
-               return new URL(getScheme(), getLocalName(), getLocalPort(), 
getContextPath() + getServletPath() + (StringUtils.isEmpty(path) ? "" : ('/' + 
path)));
-       }
-
-       /**
-        * Returns the URI of the parent of this servlet.
-        *
-        * @return The URI of the parent of this servlet.
-        */
-       public String getServletParentURI() {
-               String s = getServletURI();
-               return s.substring(0, s.lastIndexOf('/'));
-       }
-
-       /**
-        * Returns the decoded remainder of the URL following any path pattern 
matches.
-        * <p>
-        *      The behavior of path remainder is shown below given the path 
pattern "/foo/*":
-        * <p>
-        *      <table class='styled'>
-        *              <tr>
-        *                      <th>URL</th>
-        *                      <th>Path Remainder</th>
-        *              </tr>
-        *              <tr>
-        *                      <th><code>/foo</code></th>
-        *                      <th><jk>null</jk></th>
-        *              </tr>
-        *              <tr>
-        *                      <th><code>/foo/</code></th>
-        *                      <th><js>""</js></th>
-        *              </tr>
-        *              <tr>
-        *                      <th><code>/foo//</code></th>
-        *                      <th><js>"/"</js></th>
-        *              </tr>
-        *              <tr>
-        *                      <th><code>/foo///</code></th>
-        *                      <th><js>"//"</js></th>
-        *              </tr>
-        *              <tr>
-        *                      <th><code>/foo/a/b</code></th>
-        *                      <th><js>"a/b"</js></th>
-        *              </tr>
-        *              <tr>
-        *                      <th><code>/foo//a/b/</code></th>
-        *                      <th><js>"/a/b/"</js></th>
-        *              </tr>
-        *              <tr>
-        *                      <th><code>/foo/a%2Fb</code></th>
-        *                      <th><js>"a/b"</js></th>
-        *              </tr>
-        *      </table>
-        *
-        * <h6 class='topic'>Example:</h6>
-        * <p class='bcode'>
-        *      <jc>// REST method</jc>
-        *      
<ja>@RestMethod</ja>(name=<js>"GET"</js>,path=<js>"/foo/{bar}/*"</js>)
-        *      <jk>public</jk> doGetById(RestServlet res, RestResponse res, 
<jk>int</jk> bar) {
-        *              System.<jsm>err</jsm>.println(res.getRemainder());
-        *      }
-        *
-        *      <jc>// Prints "path/remainder"</jc>
-        *      <jk>new</jk> RestCall(servletPath + 
<js>"/foo/123/path/remainder"</js>).connect();
-        * </p>
-        *
-        * @return The path remainder string.
-        */
-       public String getPathRemainder() {
-               return RestUtils.decode(pathRemainder);
-       }
-
-       /**
-        * Same as {@link #getPathRemainder()} but doesn't decode characters.
-        *
-        * @return The undecoded path remainder.
-        */
-       public String getPathRemainderUndecoded() {
-               return pathRemainder;
-       }
-
-       /**
-        * Returns the URI of the parent resource.
-        * <p>
-        *      Trailing slashes in the path are ignored by this method.
-        * <p>
-        *      The behavior is shown below:
-        *      <table class='styled'>
-        *              <tr>
-        *                      <th>getRequestURI</th>
-        *                      <th>getRequestParentURI</th>
-        *              </tr>
-        *              <tr>
-        *                      <th><code>/foo/bar</code></th>
-        *                      <th><code>/foo</code></th>
-        *              </tr>
-        *              <tr>
-        *                      <th><code>/foo/bar?baz=bing</code></th>
-        *                      <th><code>/foo</code></th>
-        *              </tr>
-        *              <tr>
-        *                      <th><code>/foo/bar/</code></th>
-        *                      <th><code>/foo</code></th>
-        *              </tr>
-        *              <tr>
-        *                      <th><code>/foo/bar//</code></th>
-        *                      <th><code>/foo</code></th>
-        *              </tr>
-        *              <tr>
-        *                      <th><code>/foo//bar//</code></th>
-        *                      <th><code>/foo/</code></th>
-        *              </tr>
-        *              <tr>
-        *                      <th><code>/foo</code></th>
-        *                      <th>/</th>
-        *              </tr>
-        *      </table>
-        *
-        * @return The request parent URI.
-        */
-       public String getRequestParentURI() {
-               String uri = getRequestURI();
-               while (StringUtils.endsWith(uri, '/'))
-                       uri = uri.substring(0, uri.length()-1);
-               int i = uri.lastIndexOf('/');
-               if (i <= 0)
-                       return "/";
-               return uri.substring(0, i);
-       }
-
-       /**
-        * Same as {@link #getRequestURI()} but trims trailing slashes from the 
result.
-        *
-        * @return The trimmed request URI.
-        */
-       public String getTrimmedRequestURI() {
-               return RestUtils.trimTrailingSlashes(getRequestURI());
-       }
-
-       /**
-        * Same as {@link #getRequestURL()} but trims trailing slashes from the 
result.
-        *
-        * @return The trimmed request URL.
-        */
-       public StringBuffer getTrimmedRequestURL() {
-               return RestUtils.trimTrailingSlashes(getRequestURL());
-       }
-
-       /**
-        * Gets the URI of the servlet (e.g. 
<js>"https://localhost:9080/contextPath/servletPath";</js>).
-        *
-        * @return The servlet URI.
-        */
-       public String getServletURI() {
-               if (servletURI == null) {
-                       // Note that we can't use getPathInfo() to calculate 
this since it replaces
-                       // URL-encoded chars (e.g. %2F) which throws off the 
length calculation
-                       // because getRequestURL() does not replace those chars.
-                       servletURI = getServletURIBuilder().toString();
-               }
-               return servletURI;
-       }
-
-       /**
-        * Gets the path-absolute relative URI of the servlet (e.g. 
<js>"/contextPath/servletPath"</js>).
-        *
-        * @return The relative servlet URI.
-        */
-       public String getRelativeServletURI() {
-               if (relativeServletURI == null)
-                       relativeServletURI = getContextPath() + 
getServletPath();
-               return relativeServletURI;
-       }
-
-       /**
-        * Returns a <code>StringBuffer</code> prefilled with the string 
<code><js>"/[contextPath]/[servletPath]"</js></code>.
-        *
-        * @return The servlet URI string builder.
-        */
-       public StringBuffer getServletURIBuilder() {
-               return RestUtils.trimPathInfo(getRequestURL(), 
getContextPath(), getServletPath());
-       }
-
-       
//--------------------------------------------------------------------------------
-       // Labels
-       
//--------------------------------------------------------------------------------
-
-       /**
-        * Returns the localized servlet title.
-        * <p>
-        *      Equivalent to calling {@link RestServlet#getTitle(RestRequest)} 
with this object.
-        *
-        * @return The localized servlet label.
-        */
-       public String getServletTitle() {
-               return servlet.getTitle(this);
-       }
-
-       /**
-        * Returns the localized servlet description.
-        * <p>
-        *      Equivalent to calling {@link 
RestServlet#getDescription(RestRequest)} with this object.
-        *
-        * @return The localized servlet description.
-        */
-       public String getServletDescription() {
-               return servlet.getDescription(this);
-       }
-
-       /**
-        * Returns the localized method summary.
-        * <p>
-        *      Equivalent to calling {@link 
RestServlet#getMethodSummary(String, RestRequest)} with this object.
-        *
-        * @return The localized method description.
-        */
-       public String getMethodSummary() {
-               return servlet.getMethodSummary(javaMethod.getName(), this);
-       }
-
-       /**
-        * Returns the localized method description.
-        * <p>
-        *      Equivalent to calling {@link 
RestServlet#getMethodDescription(String, RestRequest)} with this object.
-        *
-        * @return The localized method description.
-        */
-       public String getMethodDescription() {
-               return servlet.getMethodDescription(javaMethod.getName(), this);
-       }
-
-       
//--------------------------------------------------------------------------------
-       // Other methods
-       
//--------------------------------------------------------------------------------
-
-       /**
-        * Returns the serializers associated with this request.
-        *
-        * @return The serializers associated with this request.
-        */
-       public SerializerGroup getSerializerGroup() {
-               return serializerGroup;
-       }
-
-       /**
-        * Returns the parsers associated with this request.
-        *
-        * @return The parsers associated with this request.
-        */
-       public ParserGroup getParserGroup() {
-               return parserGroup;
-       }
-
-       /**
-        * Returns the parser matching the request <code>Accept</code> header.
-        *
-        * @return The parser matching the request <code>Accept</code> header, 
or <jk>null</jk>
-        *      if no matching parser was found.
-        */
-       public Parser getParser() {
-               String mediaType = getMediaType();
-               Parser p = parserGroup.getParser(mediaType);
-
-               // If no patching parser for URL-encoding, use the one defined 
on the servlet.
-               if (p == null && 
mediaType.equals("application/x-www-form-urlencoded"))
-                       p = urlEncodingParser;
-
-               return p;
-       }
-
-       /**
-        * Returns the reader parser matching the request <code>Accept</code> 
header.
-        *
-        * @return The reader parser matching the request <code>Accept</code> 
header, or <jk>null</jk>
-        *      if no matching reader parser was found, or the matching parser 
was an input stream parser.
-        */
-       public ReaderParser getReaderParser() {
-               Parser p = getParser();
-               if (p.isReaderParser())
-                       return (ReaderParser)p;
-               return null;
-       }
-
-       /**
-        * Returns the method of this request.
-        * <p>
-        *      If <code>allowHeaderParams</code> init parameter is 
<jk>true</jk>, then first looks
-        *      for <code>&method=xxx</code> in the URL query string.
-        */
-       @Override /* ServletRequest */
-       public String getMethod() {
-               return method;
-       }
-
-
-       @Override /* ServletRequest */
-       public int getContentLength() {
-               return contentLength == 0 ? super.getContentLength() : 
contentLength;
-       }
-
-       /**
-        * Returns <jk>true</jk> if <code>&plainText=true</code> was specified 
as a URL parameter.
-        * <p>
-        *      This indicates that the <code>Content-Type</code> of the output 
should always be set to <js>"text/plain"</js>
-        *      to make it easy to render in a browser.
-        * <p>
-        *      This feature is useful for debugging.
-        *
-        * @return <jk>true</jk> if {@code &plainText=true} was specified as a 
URL parameter
-        */
-       public boolean isPlainText() {
-               return "true".equals(getQueryParameter("plainText", "false"));
-       }
-
-       /**
-        * Shortcut method for calling {@link RestServlet#getMessage(Locale, 
String, Object...)} based
-        *      on the request locale.
-        *
-        * @param key The message key.
-        * @param args Optional {@link MessageFormat} variable values in the 
value.
-        * @return The localized message.
-        */
-       public String getMessage(String key, Object...args) {
-               return servlet.getMessage(getLocale(), key, args);
-       }
-
-       /**
-        * Returns the resource bundle for the request locale.
-        *
-        * @return The resource bundle.  Never <jk>null</jk>.
-        */
-       public MessageBundle getResourceBundle() {
-               return servlet.getMessages(getLocale());
-       }
-
-       /**
-        * Returns the servlet handling the request.
-        * <p>
-        *      Can be used to access servlet-init parameters or annotations 
during requests,
-        *      such as in calls to {@link RestGuard#guard(RestRequest, 
RestResponse)}..
-        *
-        * @return The servlet handling the request.
-        */
-       public RestServlet getServlet() {
-               return servlet;
-       }
-
-       /**
-        * Returns the java method handling the request.
-        * <p>
-        *      Can be used to access the method name or method annotations 
during requests, such
-        *      as in calls to {@link RestGuard#guard(RestRequest, 
RestResponse)}.
-        * <p>
-        *      Note:  This returns null when evaluating servlet-level guards 
since the method
-        *      has not been resolved at that point of execution.
-        *
-        * @return The Java method handling the request, or <code>null</code> 
if the method
-        *      has not yet been resolved.
-        */
-       public Method getJavaMethod() {
-               return javaMethod;
-       }
-
-       /**
-        * Returns the {@link BeanSession} associated with this request.
-        *
-        * @return The request bean session.
-        */
-       public BeanSession getBeanSession() {
-               return beanSession;
-       }
-
-       /**
-        * Returns the variable resolver session for this request using session 
objects created by {@link RestServlet#getSessionObjects(RestRequest)}.
-        *
-        * @return The variable resolver for this request.
-        */
-       public VarResolverSession getVarResolverSession() {
-               if (varSession == null)
-                       varSession = 
servlet.getVarResolver().createSession(servlet.getSessionObjects(this));
-               return varSession;
-       }
-
-       /**
-        * Shortcut for calling 
<code>getVarResolverSession().resolve(input)</code>.
-        *
-        * @param input The input string to resolve variables in.
-        * @return The string with variables resolved, or <jk>null</jk> if 
input is null.
-        */
-       public String resolveVars(String input) {
-               return getVarResolverSession().resolve(input);
-       }
-
-       /**
-        * Returns an instance of a {@link ReaderResource} that represents the 
contents of a resource text file from the classpath.
-        *
-        * @param name The name of the resource (i.e. the value normally passed 
to {@link Class#getResourceAsStream(String)}.
-        * @param resolveVars If <jk>true</jk>, any {@link 
org.apache.juneau.server.annotation.Parameter} variables will be resolved by 
the variable resolver returned
-        *      by {@link #getVarResolverSession()}.
-        * @param contentType The value to set as the <js>"Content-Type"</js> 
header for this object.
-        * @return A new reader resource, or <jk>null</jk> if resource could 
not be found.
-        * @throws IOException
-        */
-       public ReaderResource getReaderResource(String name, boolean 
resolveVars, String contentType) throws IOException {
-               String s = servlet.getResourceAsString(name, getLocale());
-               if (s == null)
-                       return null;
-               ReaderResource rr = new ReaderResource(s, contentType);
-               if (resolveVars)
-                       rr.setVarSession(getVarResolverSession());
-               return rr;
-       }
-
-       /**
-        * Same as {@link #getReaderResource(String, boolean, String)} except 
uses {@link RestServlet#getMimetypesFileTypeMap()}
-        * to determine the media type.
-        *
-        * @param name The name of the resource (i.e. the value normally passed 
to {@link Class#getResourceAsStream(String)}.
-        * @param resolveVars If <jk>true</jk>, any {@link 
org.apache.juneau.server.annotation.Parameter} variables will be resolved by 
the variable resolver returned
-        *      by {@link #getVarResolverSession()}.
-        * @return A new reader resource, or <jk>null</jk> if resource could 
not be found.
-        * @throws IOException
-        */
-       public ReaderResource getReaderResource(String name, boolean 
resolveVars) throws IOException {
-               return getReaderResource(name, resolveVars, 
servlet.getMimetypesFileTypeMap().getContentType(name));
-       }
-
-       /**
-        * Same as {@link #getReaderResource(String, boolean)} with 
<code>resolveVars == <jk>false</jk></code>
-        *
-        * @param name The name of the resource (i.e. the value normally passed 
to {@link Class#getResourceAsStream(String)}.
-        * @return A new reader resource, or <jk>null</jk> if resource could 
not be found.
-        * @throws IOException
-        */
-       public ReaderResource getReaderResource(String name) throws IOException 
{
-               return getReaderResource(name, false, 
servlet.getMimetypesFileTypeMap().getContentType(name));
-       }
-
-       /**
-        * Returns the config file associated with the servlet.
-        *
-        * @return The config file associated with the servlet, or 
<jk>null</jk> if servlet does not have a config file associated with it.
-        */
-       public ConfigFile getConfig() {
-               if (cf == null)
-                       cf = 
servlet.getConfig().getResolving(getVarResolverSession());
-               return cf;
-       }
-
-       /**
-        * Returns the localized swagger associated with the servlet.
-        *
-        * @return The swagger associated with the servlet.  Never 
<jk>null</jk>.
-        */
-       public Swagger getSwagger() {
-               if (swagger == null)
-                       swagger = servlet.getSwagger(this);
-               return swagger;
-       }
-
-       /**
-        * Returns the localized Swagger from the file system.
-        * <p>
-        *      Looks for a file called <js>"{ServletClass}_{locale}.json"</js> 
in the same package
-        *      as this servlet and returns it as a parsed {@link Swagger} 
object.
-        * <p>
-        *      Returned objects are cached for later quick-lookup.
-        *
-        * @return The parsed swagger object, or <jk>null</jk> if the swagger 
file could not be found.
-        */
-       protected Swagger getSwaggerFromFile() {
-               if (fileSwagger == null)
-                       fileSwagger = 
servlet.getSwaggerFromFile(this.getLocale());
-               if (fileSwagger == null)
-                       fileSwagger = Swagger.NULL;
-               return fileSwagger == Swagger.NULL ? null : fileSwagger;
-       }
-
-       @Override /* Object */
-       public String toString() {
-               StringBuilder sb = new 
StringBuilder("\n").append(getDescription()).append("\n");
-               sb.append("---Headers---\n");
-               for (Enumeration<String> e = getHeaderNames(); 
e.hasMoreElements();) {
-                       String h = e.nextElement();
-                       sb.append("\t").append(h).append(": 
").append(getHeader(h)).append("\n");
-               }
-               sb.append("---Default Servlet Headers---\n");
-               for (Map.Entry<String,String> e : 
defaultServletHeaders.entrySet()) {
-                       sb.append("\t").append(e.getKey()).append(": 
").append(e.getValue()).append("\n");
-               }
-               if (method.equals("PUT") || method.equals("POST")) {
-                       sb.append("---Body---\n");
-                       try {
-                               sb.append(getBodyAsString()).append("\n");
-                       } catch (Exception e1) {
-                               sb.append(e1.getLocalizedMessage());
-                               servlet.log(WARNING, e1, "Error occurred while 
trying to read debug input.");
-                       }
-               }
-               return sb.toString();
-       }
-
-       
//--------------------------------------------------------------------------------
-       // Utility methods
-       
//--------------------------------------------------------------------------------
-
-       private <T> T parseParameter(String val, ClassMeta<T> c) throws 
ParseException {
-               if (val == null)
-                       return null;
-               // Shortcut - If we're returning a string and the value doesn't 
start with '$' or '(', then
-               // just return the string since it's a plain value.
-               if (c.getInnerClass() == String.class && val.length() > 0) {
-                       char x = val.charAt(0);
-                       if (x != '(' && x != '$' && x != '\u0000' && 
val.indexOf('~') == -1)
-                               return (T)val;
-               }
-               return urlEncodingParser.parseParameter(val, c);
-       }
-
-       /*
-        * Converts an Accept-Language value entry to a Locale.
-        */
-       private Locale toLocale(String lang) {
-      String country = "";
-      int i = lang.indexOf('-');
-      if (i > -1) {
-          country = lang.substring(i+1).trim();
-          lang = lang.substring(0,i).trim();
-      }
-      return new Locale(lang, country);
-       }
-
-       private Encoder getEncoder() {
-               if (encoder == null) {
-                       String ce = getHeader("content-encoding");
-                       if (! (ce == null || ce.isEmpty())) {
-                               ce = ce.trim();
-                               encoder = servlet.getEncoders().getEncoder(ce);
-                               if (encoder == null)
-                                       throw new 
RestException(SC_UNSUPPORTED_MEDIA_TYPE,
-                                               "Unsupported encoding in 
request header ''Content-Encoding'': ''{0}''\n\tSupported codings: {1}",
-                                               getHeader("content-encoding"), 
servlet.getEncoders().getSupportedEncodings()
-                                       );
-                       }
-
-                       if (encoder != null)
-                               contentLength = -1;
-               }
-               // Note that if this is the identity encoder, we want to return 
null
-               // so that we don't needlessly wrap the input stream.
-               if (encoder == IdentityEncoder.INSTANCE)
-                       return null;
-               return encoder;
-       }
-
-       /*
-        * Returns header value from URL-parameters or set via setHeader() meant
-        * to override actual header values on the request.
-        */
-       private String getOverriddenHeader(String name) {
-               String h = null;
-               if (servlet.context.allowHeaderParams)
-                       h = getQueryParameter(name);
-               if (h != null)
-                       return h;
-               if (overriddenHeaders != null) {
-                       h = overriddenHeaders.get(name);
-                       if (h != null)
-                               return h;
-               }
-               return h;
-       }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/91a388d0/juneau-server/src/main/java/org/apache/juneau/server/RestResponse.java
----------------------------------------------------------------------
diff --git 
a/juneau-server/src/main/java/org/apache/juneau/server/RestResponse.java 
b/juneau-server/src/main/java/org/apache/juneau/server/RestResponse.java
deleted file mode 100755
index 6b79bfc..0000000
--- a/juneau-server/src/main/java/org/apache/juneau/server/RestResponse.java
+++ /dev/null
@@ -1,425 +0,0 @@
-// 
***************************************************************************************************************************
-// * 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.server;
-
-import java.io.*;
-import java.util.*;
-
-import javax.servlet.*;
-import javax.servlet.http.*;
-
-import org.apache.juneau.*;
-import org.apache.juneau.encoders.*;
-import org.apache.juneau.jena.*;
-import org.apache.juneau.json.*;
-import org.apache.juneau.serializer.*;
-import org.apache.juneau.urlencoding.*;
-import org.apache.juneau.xml.*;
-
-/**
- * Represents an HTTP response for a REST resource.
- * <p>
- * Essentially an extended {@link HttpServletResponse} with some special 
convenience methods
- *     that allow you to easily output POJOs as responses.
- * </p>
- * <p>
- * Since this class extends {@link HttpServletResponse}, developers are free 
to use these
- *     convenience methods, or revert to using lower level methods like any 
other servlet response.
- * </p>
- *
- * <h6 class='topic'>Example:</h6>
- * <p class='bcode'>
- *     <ja>@RestMethod</ja>(name=<js>"GET"</js>)
- *     <jk>public void</jk> doGet(RestRequest req, RestResponse res) {
- *             res.setProperty(HtmlSerializerContext.<jsf>HTMLDOC_title</jsf>, 
<js>"My title"</js>)
- *                     .setOutput(<js>"Simple string response"</js>);
- *     }
- * </p>
- * <p>
- *     Refer to <a class='doclink' href='package-summary.html#TOC'>REST 
Servlet API</a> for information about using this class.
- * </p>
- */
-public final class RestResponse extends HttpServletResponseWrapper {
-
-       private final RestRequest request;
-       private Object output;                               // The POJO being 
sent to the output.
-       private boolean isNullOutput;                        // The output is 
null (as opposed to not being set at all)
-       private ObjectMap properties;                        // Response 
properties
-       SerializerGroup serializerGroup;
-       UrlEncodingSerializer urlEncodingSerializer;         // The serializer 
used to convert arguments passed into Redirect objects.
-       private EncoderGroup encoders;
-       private RestServlet servlet;
-       private ServletOutputStream os;
-
-       /**
-        * Constructor.
-        */
-       RestResponse(RestServlet servlet, RestRequest req, HttpServletResponse 
res) {
-               super(res);
-               this.request = req;
-               this.servlet = servlet;
-
-               for (Map.Entry<String,Object> e : 
servlet.getDefaultResponseHeaders().entrySet())
-                       setHeader(e.getKey(), e.getValue().toString());
-
-               try {
-                       String passThroughHeaders = 
req.getHeader("x-response-headers");
-                       if (passThroughHeaders != null) {
-                               ObjectMap m = 
servlet.getUrlEncodingParser().parseParameter(passThroughHeaders, 
ObjectMap.class);
-                               for (Map.Entry<String,Object> e : m.entrySet())
-                                       setHeader(e.getKey(), 
e.getValue().toString());
-                       }
-               } catch (Exception e1) {
-                       throw new RestException(SC_BAD_REQUEST, "Invalid format 
for header 'x-response-headers'.  Must be in URL-encoded 
format.").initCause(e1);
-               }
-       }
-
-       /*
-        * Called from RestServlet after a match has been made but before the 
guard or method invocation.
-        */
-       @SuppressWarnings("hiding")
-       final void init(ObjectMap properties, String defaultCharset, 
SerializerGroup mSerializers, UrlEncodingSerializer mUrlEncodingSerializer, 
EncoderGroup encoders) {
-               this.properties = properties;
-               this.serializerGroup = mSerializers;
-               this.urlEncodingSerializer = mUrlEncodingSerializer;
-               this.encoders = encoders;
-
-               // Find acceptable charset
-               String h = request.getHeader("accept-charset");
-               String charset = null;
-               if (h == null)
-                       charset = defaultCharset;
-               else for (MediaRange r : MediaRange.parse(h)) {
-                       if (r.getQValue() > 0) {
-                               if (r.getType().equals("*"))
-                                       charset = defaultCharset;
-                               else if 
(RestServlet.availableCharsets.containsKey(r.getType()))
-                                       charset = r.getType();
-                               if (charset != null)
-                                       break;
-                       }
-               }
-
-               if (charset == null)
-                       throw new RestException(SC_NOT_ACCEPTABLE, "No 
supported charsets in header ''Accept-Charset'': ''{0}''", 
request.getHeader("Accept-Charset"));
-               super.setCharacterEncoding(charset);
-       }
-
-       /**
-        * Gets the serializer group for the response.
-        *
-        * @return The serializer group for the response.
-        */
-       public SerializerGroup getSerializerGroup() {
-               return serializerGroup;
-       }
-
-       /**
-        * Returns the media types that are valid for <code>Accept</code> 
headers on the request.
-        *
-        * @return The set of media types registered in the parser group of 
this request.
-        */
-       public List<String> getSupportedMediaTypes() {
-               return serializerGroup.getSupportedMediaTypes();
-       }
-
-       /**
-        * Returns the codings that are valid for <code>Accept-Encoding</code> 
and <code>Content-Encoding</code> headers on the request.
-        *
-        * @return The set of media types registered in the parser group of 
this request.
-        * @throws RestServletException
-        */
-       public List<String> getSupportedEncodings() throws RestServletException 
{
-               return servlet.getEncoders().getSupportedEncodings();
-       }
-
-       /**
-        * Sets the HTTP output on the response.
-        * <p>
-        *      Calling this method is functionally equivalent to returning the 
object in the REST Java method.
-        * <p>
-        *      Can be of any of the following types:
-        *      <ul>
-        *        <li> {@link InputStream}
-        *        <li> {@link Reader}
-        *        <li> Any serializable type defined in <a 
href='../../../../overview-summary.html#Core.PojoCategories'>POJO Categories</a>
-        *      </ul>
-        * <p>
-        *      If it's an {@link InputStream} or {@link Reader}, you must also 
specify the <code>Content-Type</code> using the {@link #setContentType(String)} 
method.
-        *
-        * @param output The output to serialize to the connection.
-        * @return This object (for method chaining).
-        */
-       public RestResponse setOutput(Object output) {
-               this.output = output;
-               this.isNullOutput = output == null;
-               return this;
-       }
-
-       /**
-        * Add a serializer property to send to the serializers to override a 
default value.
-        * <p>
-        * Can be any value specified in the following classes:
-        * <ul>
-        *      <li>{@link SerializerContext}
-        *      <li>{@link JsonSerializerContext}
-        *      <li>{@link XmlSerializerContext}
-        *      <li>{@link RdfSerializerContext}
-        * </ul>
-        *
-        * @param key The setting name.
-        * @param value The setting value.
-        * @return This object (for method chaining).
-        */
-       public RestResponse setProperty(String key, Object value) {
-               properties.put(key, value);
-               return this;
-       }
-
-       /**
-        * Returns the properties set via {@link #setProperty(String, Object)}.
-        *
-        * @return A map of all the property values set.
-        */
-       public ObjectMap getProperties() {
-               return properties;
-       }
-
-       /**
-        * Shortcut method that allows you to use varargs to simplify setting 
array output.
-        *
-        * <h6 class='topic'>Example:</h6>
-        * <p class='bcode'>
-        *      <jc>// Instead of...</jc>
-        *      response.setOutput(<jk>new</jk> Object[]{x,y,z});
-        *
-        *      <jc>// ...call this...</jc>
-        *      response.setOutput(x,y,z);
-        * </p>
-        *
-        * @param output The output to serialize to the connection.
-        * @return This object (for method chaining).
-        */
-       public RestResponse setOutputs(Object...output) {
-               this.output = output;
-               return this;
-       }
-
-       /**
-        * Returns the output that was set by calling {@link 
#setOutput(Object)}.
-        *
-        * @return The output object.
-        */
-       public Object getOutput() {
-               return output;
-       }
-
-       /**
-        * Returns <jk>true</jk> if this response has any output associated 
with it.
-        *
-        * @return <jk>true</jk> if {@code setInput()} has been called.
-        */
-       public boolean hasOutput() {
-               return output != null || isNullOutput;
-       }
-
-       /**
-        * Sets the output to a plain-text message regardless of the content 
type.
-        *
-        * @param text The output text to send.
-        * @return This object (for method chaining).
-        * @throws IOException If a problem occurred trying to write to the 
writer.
-        */
-       public RestResponse sendPlainText(String text) throws IOException {
-               setContentType("text/plain");
-               getNegotiatedWriter().write(text);
-               return this;
-       }
-
-       /**
-        * Equivalent to {@link HttpServletResponse#getOutputStream()}, except
-        *      wraps the output stream if an {@link Encoder} was found that 
matched
-        *      the <code>Accept-Encoding</code> header.
-        *
-        * @return A negotiated output stream.
-        * @throws IOException
-        */
-       public ServletOutputStream getNegotiatedOutputStream() throws 
IOException {
-               if (os == null) {
-                       Encoder encoder = null;
-
-                       String ae = request.getHeader("Accept-Encoding");
-                       if (! (ae == null || ae.isEmpty())) {
-                               String match = encoders != null ? 
encoders.findMatch(ae) : null;
-                               if (match == null) {
-                                       // Identity should always match unless 
"identity;q=0" or "*;q=0" is specified.
-                                       if 
(ae.matches(".*(identity|\\*)\\s*;\\s*q\\s*=\\s*(0(?!\\.)|0\\.0).*")) {
-                                               throw new 
RestException(SC_NOT_ACCEPTABLE,
-                                                       "Unsupported encoding 
in request header ''Accept-Encoding'': ''{0}''\n\tSupported codings: {1}",
-                                                       ae, 
encoders.getSupportedEncodings()
-                                               );
-                                       }
-                               } else {
-                                       encoder = encoders.getEncoder(match);
-
-                                       // Some clients don't recognize 
identity as an encoding, so don't set it.
-                                       if (! match.equals("identity"))
-                                       setHeader("content-encoding", match);
-                               }
-                       }
-                       os = getOutputStream();
-                       if (encoder != null) {
-                               final OutputStream os2 = 
encoder.getOutputStream(os);
-                               os = new ServletOutputStream(){
-                                       @Override /* OutputStream */
-                                       public final void write(byte[] b, int 
off, int len) throws IOException {
-                                               os2.write(b, off, len);
-                                       }
-                                       @Override /* OutputStream */
-                                       public final void write(int b) throws 
IOException {
-                                               os2.write(b);
-                                       }
-                                       @Override /* OutputStream */
-                                       public final void flush() throws 
IOException {
-                                               os2.flush();
-                                       }
-                                       @Override /* OutputStream */
-                                       public final void close() throws 
IOException {
-                                               os2.close();
-                                       }
-                               };
-                       }
-               }
-               return os;
-       }
-
-       @Override /* ServletResponse */
-       public ServletOutputStream getOutputStream() throws IOException {
-               if (os == null)
-                       os = super.getOutputStream();
-               return os;
-       }
-
-       /**
-        * Returns <jk>true</jk> if {@link #getOutputStream()} has been called.
-        *
-        * @return <jk>true</jk> if {@link #getOutputStream()} has been called.
-        */
-       public boolean getOutputStreamCalled() {
-               return os != null;
-       }
-
-       /**
-        * Returns the writer to the response body.
-        * This methods bypasses any specified encoders and returns a regular 
unbuffered writer.
-        * Use the {@link #getNegotiatedWriter()} method if you want to use the 
matched encoder (if any).
-        */
-       @Override /* ServletResponse */
-       public PrintWriter getWriter() throws IOException {
-               return getWriter(true);
-       }
-
-       /**
-        * Convenience method meant to be used when rendering directly to a 
browser with no buffering.
-        * Sets the header <js>"x-content-type-options=nosniff"</js> so that 
output is rendered
-        * immediately on IE and Chrome without any buffering for content-type 
sniffing.
-        *
-        * @param contentType The value to set as the <code>Content-Type</code> 
on the response.
-        * @return The raw writer.
-        * @throws IOException
-        */
-       public PrintWriter getDirectWriter(String contentType) throws 
IOException {
-               setContentType(contentType);
-               setHeader("x-content-type-options", "nosniff");
-               return getWriter();
-       }
-
-       /**
-        * Equivalent to {@link HttpServletResponse#getWriter()}, except
-        *      wraps the output stream if an {@link Encoder} was found that 
matched
-        *      the <code>Accept-Encoding</code> header and sets the 
<code>Content-Encoding</code>
-        *      header to the appropriate value.
-        *
-        * @return The negotiated writer.
-        * @throws IOException
-        */
-       public PrintWriter getNegotiatedWriter() throws IOException {
-               return getWriter(false);
-       }
-
-       private PrintWriter getWriter(boolean raw) throws IOException {
-               // If plain text requested, override it now.
-               if (request.isPlainText()) {
-                       setHeader("Content-Type", "text/plain");
-               }
-
-               try {
-                       OutputStream out = (raw ? getOutputStream() : 
getNegotiatedOutputStream());
-                       return new PrintWriter(new OutputStreamWriter(out, 
getCharacterEncoding()));
-               } catch (UnsupportedEncodingException e) {
-                       String ce = getCharacterEncoding();
-                       setCharacterEncoding("UTF-8");
-                       throw new RestException(SC_NOT_ACCEPTABLE, "Unsupported 
charset in request header ''Accept-Charset'': ''{0}''", ce);
-               }
-       }
-
-       /**
-        * Returns the <code>Content-Type</code> header stripped of the charset 
attribute if present.
-        *
-        * @return The <code>media-type</code> portion of the 
<code>Content-Type</code> header.
-        */
-       public String getMediaType() {
-               String contentType = getContentType();
-               if (contentType == null)
-                       return null;
-               int i = contentType.indexOf(';');
-               if (i == -1)
-                       return contentType;
-               return contentType.substring(0, i).trim();
-
-       }
-
-       /**
-        * Redirects to the specified URI.
-        * <p>
-        * Relative URIs are always interpreted as relative to the context root.
-        * This is similar to how WAS handles redirect requests, and is 
different from how Tomcat
-        *      handles redirect requests.
-        */
-       @Override /* ServletResponse */
-       public void sendRedirect(String uri) throws IOException {
-               char c = (uri.length() > 0 ? uri.charAt(0) : 0);
-               if (c != '/' && uri.indexOf("://") == -1)
-                       uri = request.getContextPath() + '/' + uri;
-               super.sendRedirect(uri);
-       }
-
-       /**
-        * Returns the URL-encoding serializer associated with this response.
-        *
-        * @return The URL-encoding serializer associated with this response.
-        */
-       public UrlEncodingSerializer getUrlEncodingSerializer() {
-               return urlEncodingSerializer;
-       }
-
-       @Override /* ServletResponse */
-       public void setHeader(String name, String value) {
-               // Jetty doesn't set the content type correctly if set through 
this method.
-               // Tomcat/WAS does.
-               if (name.equalsIgnoreCase("Content-Type"))
-                       super.setContentType(value);
-               else
-                       super.setHeader(name, value);
-       }
-}

Reply via email to