juneau-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jamesbog...@apache.org
Subject [2/4] juneau git commit: Improvements to static files support in REST.
Date Thu, 04 Jan 2018 17:06:30 GMT
http://git-wip-us.apache.org/repos/asf/juneau/blob/b820b273/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContextBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContextBuilder.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContextBuilder.java
index 8a682fe..cb052e3 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContextBuilder.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContextBuilder.java
@@ -144,6 +144,7 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
 		this.parentContext = parentContext;
 		
 		logger(RestLogger.Normal.class);
+		staticFileResponseHeader("Cache-Control", "max-age=86400, public");
 
 		try {
 
@@ -198,8 +199,12 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
 				serializers(r.serializers());
 				parsers(r.parsers());
 				encoders(r.encoders());
-				defaultRequestHeaders(r.defaultRequestHeaders());
-				defaultResponseHeaders(r.defaultResponseHeaders());
+				if (r.supportedAcceptTypes().length > 0)
+					supportedAcceptTypes(false, resolveVars(vr, r.supportedAcceptTypes()));
+				if (r.supportedContentTypes().length > 0)
+					supportedContentTypes(false, resolveVars(vr, r.supportedContentTypes()));
+				defaultRequestHeaders(resolveVars(vr, r.defaultRequestHeaders()));
+				defaultResponseHeaders(resolveVars(vr, r.defaultResponseHeaders()));
 				responseHandlers(r.responseHandlers());
 				converters(r.converters());
 				guards(reverse(r.guards()));
@@ -207,16 +212,22 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
 				beanFilters(r.beanFilters());
 				pojoSwaps(r.pojoSwaps());
 				paramResolvers(r.paramResolvers());
-				serializerListener(r.serializerListener());
-				parserListener(r.parserListener());
+				if (r.serializerListener() != SerializerListener.Null.class)
+					serializerListener(r.serializerListener());
+				if (r.parserListener() != ParserListener.Null.class)
+					parserListener(r.parserListener());
 				contextPath(r.contextPath());
-				if (! r.staticFiles().isEmpty())
-					staticFiles(c, r.staticFiles());
+				for (String mapping : r.staticFiles())
+					staticFiles(c, vr.resolve(mapping));
+				staticFileResponseHeaders(resolveVars(vr, r.staticFileResponseHeaders()));
+				if (! r.useClasspathResourceCaching().isEmpty())
+					useClasspathResourceCaching(Boolean.valueOf(vr.resolve(r.useClasspathResourceCaching())));
+				if (r.classpathResourceFinder() != ClasspathResourceFinder.Null.class)
+					classpathResourceFinder(r.classpathResourceFinder());
 				if (! r.path().isEmpty())
 					path(r.path());
 				if (! r.clientVersionHeader().isEmpty())
 					clientVersionHeader(r.clientVersionHeader());
-
 				if (r.resourceResolver() != RestResourceResolver.class)
 					resourceResolver(r.resourceResolver());
 				if (r.logger() != RestLogger.Normal.class)
@@ -260,6 +271,13 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
 			throw new ServletException(e);
 		}
 	}
+	
+	private static String[] resolveVars(VarResolver vr, String[] in) {
+		String[] out = new String[in.length];
+		for (int i = 0; i < in.length; i++) 
+			out[i] = vr.resolve(in[i]);
+		return out;
+	}
 
 	/*
 	 * Calls all @RestHook(INIT) methods on the specified resource object.
@@ -589,7 +607,7 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
 	 * <p>
 	 * These definitions are used in the following locations for setting the media type on responses:
 	 * <ul>
-	 * 	<li>{@link RestRequest#getReaderResource(String)}
+	 * 	<li>{@link RestRequest#getClasspathReaderResource(String)}
 	 * 	<li>Static files resolved through {@link RestResource#staticFiles()}
 	 * </ul>
 	 *
@@ -662,31 +680,6 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
 	}
 
 	/**
-	 * Appends to the static files resource map.
-	 *
-	 * <p>
-	 * Use this method to specify resources located in the classpath to be served up as static files.
-	 *
-	 * <p>
-	 * This is the programmatic equivalent to the {@link RestResource#staticFiles() @RestResource.staticFiles()}
-	 * annotation.
-	 *
-	 * @param resourceClass The resource class used to resolve the resource streams.
-	 * @param staticFilesString
-	 * 	A JSON string denoting a map of child URLs to classpath subdirectories.
-	 * 	For example, if this string is <js>"{htdocs:'docs'}"</js> with class <code>com.foo.MyResource</code>,
-	 * 	then URLs of the form <js>"/resource-path/htdocs/..."</js> will resolve to files located in the
-	 * 	<code>com.foo.docs</code> package.
-	 * @return This object (for method chaining).
-	 */
-	public RestContextBuilder staticFiles(Class<?> resourceClass, String staticFilesString) {
-		if (staticFiles == null)
-			staticFiles = new ArrayList<>();
-		staticFiles.add(new Pair<Class<?>,Object>(resourceClass, staticFilesString));
-		return this;
-	}
-
-	/**
 	 * Defines widgets that can be used in conjunction with string variables of the form <js>"$W{name}"</js>to quickly
 	 * generate arbitrary replacement text.
 	 *
@@ -805,9 +798,15 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
 	 * <p>
 	 * <h5 class='section'>Notes:</h5>
 	 * <ul class='spaced-list'>
-	 * 	<li>Property: {@link RestContext#REST_path}
-	 * 	<li>Annotation:  {@link RestResource#path()} 
-	 * 	<li>Method: {@link RestContextBuilder#path(String)} 
+	 * 	<li>Property:  {@link RestContext#REST_path}
+	 * 	<li>Annotations:
+	 * 		<ul>
+	 * 			<li>{@link RestResource#path()}
+	 * 		</ul> 
+	 * 	<li>Methods:
+	 * 		<ul>
+	 * 			<li>{@link RestContextBuilder#path(String)} 
+	 * 		</ul>
 	 * 	<li>This annotation is ignored on top-level servlets (i.e. servlets defined in <code>web.xml</code> files).
 	 * 		<br>Therefore, implementers can optionally specify a path value for documentation purposes.
 	 * 	<li>Typically, this setting is only applicable to resources defined as children through the 
@@ -840,9 +839,15 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
 	 * <p>
 	 * <h5 class='section'>Notes:</h5>
 	 * <ul class='spaced-list'>
-	 * 	<li>Property: {@link RestContext#REST_contextPath}
-	 * 	<li>Annotation:  {@link RestResource#contextPath()} 
-	 * 	<li>Method: {@link RestContextBuilder#contextPath(String)} 
+	 * 	<li>Property:  {@link RestContext#REST_contextPath}
+	 * 	<li>Annotations:
+	 * 		<ul>
+	 * 			<li>{@link RestResource#contextPath()} 
+	 * 		</ul>
+	 * 	<li>Methods:
+	 * 		<ul>
+	 * 			<li>@link RestContextBuilder#contextPath(String)} 
+	 * 		</ul>
 	 *	</ul>
 	 *
 	 * @param contextPath The context path for this resource and any child resources.
@@ -864,13 +869,18 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
 	 * 
 	 * <h5 class='section'>Notes:</h5>
 	 * <ul class='spaced-list'>
-	 * 	<li>Property: {@link RestContext#REST_allowHeaderParams}
-	 * 	<li>Annotation:  {@link RestResource#allowHeaderParams()}
-	 * 	<li>Method: {@link RestContextBuilder#allowHeaderParams(boolean)}
+	 * 	<li>Property:  {@link RestContext#REST_allowHeaderParams}
+	 * 	<li>Annotations:
+	 * 		<ul>
+	 * 			<li>{@link RestResource#allowHeaderParams()}
+	 * 		</ul>
+	 * 	<li>Methods:
+	 * 		<ul>
+	 * 			<li>{@link RestContextBuilder#allowHeaderParams(boolean)}
+	 * 		</ul>
 	 * 	<li>Format is a comma-delimited list of HTTP method names that can be passed in as a method parameter.
 	 * 	<li>Parameter name is case-insensitive.
 	 * 	<li>Useful for debugging REST interface using only a browser.
-	 * 	<li>This is equivalent to calling <code>set(<jsf>REST_allowHeaderParams</jsf>, value)</code>.
 	 *	</ul>
 	 *
 	 * @param value The new value for this setting.
@@ -898,12 +908,17 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
 	 * 
 	 * <h5 class='section'>Notes:</h5>
 	 * <ul class='spaced-list'>
-	 * 	<li>Property: {@link RestContext#REST_allowBodyParam}
-	 * 	<li>Annotation:  {@link RestResource#allowBodyParam()}
-	 * 	<li>Method: {@link RestContextBuilder#allowBodyParam(boolean)}
+	 * 	<li>Property:  {@link RestContext#REST_allowBodyParam}
+	 * 	<li>Annotations:
+	 * 		<ul>
+	 * 			<li>{@link RestResource#allowBodyParam()}
+	 * 		</ul>
+	 * 	<li>Methods:
+	 * 		<ul>
+	 * 			<li>{@link RestContextBuilder#allowBodyParam(boolean)}
+	 * 		</ul>
 	 * 	<li>Parameter name is case-insensitive.
 	 * 	<li>Useful for debugging PUT and POST methods using only a browser.
-	 * 	<li>This is equivalent to calling <code>set(<jsf>REST_allowBodyParam</jsf>, value)</code>.
 	 *	</ul>
 	 *
 	 * @param value The new value for this setting.
@@ -924,9 +939,15 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
 	 *
 	 * <h5 class='section'>Notes:</h5>
 	 * <ul class='spaced-list'>
-	 * 	<li>Property: {@link RestContext#REST_allowedMethodParams}
-	 * 	<li>Annotation:  {@link RestResource#allowedMethodParams()}
-	 * 	<li>Method: {@link RestContextBuilder#allowedMethodParams(String...)}
+	 * 	<li>Property:  {@link RestContext#REST_allowedMethodParams}
+	 * 	<li>Annotations:
+	 * 		<ul>
+	 * 			<li>{@link RestResource#allowedMethodParams()}
+	 * 		</ul>
+	 * 	<li>Methods:
+	 * 		<ul>
+	 * 			<li>{@link RestContextBuilder#allowedMethodParams(String...)}
+	 * 		</ul>
 	 * 	<li>Parameter name is case-insensitive.
 	 * 	<li>Use "*" to represent all methods.
 	 *	</ul>
@@ -951,12 +972,17 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
 	 *
 	 * <h5 class='section'>Notes:</h5>
 	 * <ul class='spaced-list'>
-	 * 	<li>Property: {@link RestContext#REST_renderResponseStackTraces}
-	 * 	<li>Annotation:  {@link RestResource#renderResponseStackTraces()}
-	 * 	<li>Method: {@link RestContextBuilder#renderResponseStackTraces(boolean)}
+	 * 	<li>Property:  {@link RestContext#REST_renderResponseStackTraces}
+	 * 	<li>Annotations:
+	 * 		<ul>
+	 * 			<li>{@link RestResource#renderResponseStackTraces()}
+	 * 		</ul>
+	 * 	<li>Methods:
+	 * 		<ul>
+	 * 			<li>{@link RestContextBuilder#renderResponseStackTraces(boolean)}
+	 * 		</ul>
 	 * 	<li>Useful for debugging, although allowing stack traces to be rendered may cause security concerns so use
 	 * 		caution when enabling.
-	 * 	<li>This is equivalent to calling <code>set(<jsf>REST_renderResponseStackTraces</jsf>, value)</code>.
 	 *	</ul>
 	 *
 	 * @param value The new value for this setting.
@@ -975,10 +1001,15 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
 	 *
 	 * <h5 class='section'>Notes:</h5>
 	 * <ul class='spaced-list'>
-	 * 	<li>Property: {@link RestContext#REST_useStackTraceHashes}
-	 * 	<li>Annotation:  {@link RestResource#useStackTraceHashes()} 
-	 * 	<li>Method: {@link RestContextBuilder#useStackTraceHashes(boolean)}
-	 * 	<li>This is equivalent to calling <code>set(<jsf>REST_useStackTraceHashes</jsf>, value)</code>.
+	 * 	<li>Property:  {@link RestContext#REST_useStackTraceHashes}
+	 * 	<li>Annotations:
+	 * 		<ul>
+	 * 			<li>{@link RestResource#useStackTraceHashes()} 
+	 * 		</ul>
+	 * 	<li>Methods:
+	 * 		<ul>
+	 * 			<li>{@link RestContextBuilder#useStackTraceHashes(boolean)}
+	 * 		</ul>
 	 *	</ul>
 	 *
 	 * @param value The new value for this setting.
@@ -996,10 +1027,16 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
 	 *
 	 * <h5 class='section'>Notes:</h5>
 	 * <ul class='spaced-list'>
-	 * 	<li>Property: {@link RestContext#REST_defaultCharset}
-	 * 	<li>Annotation:  {@link RestResource#defaultCharset()} / {@link RestMethod#defaultCharset()}
-	 * 	<li>Method: {@link RestContextBuilder#defaultCharset(String)}
-	 * 	<li>This is equivalent to calling <code>set(<jsf>REST_defaultCharset</jsf>, value)</code>.
+	 * 	<li>Property:  {@link RestContext#REST_defaultCharset}
+	 * 	<li>Annotations:
+	 * 		<ul>
+	 * 			<li>{@link RestResource#defaultCharset()}
+					<li>{@link RestMethod#defaultCharset()}
+				</ul>
+	 * 	<li>Methods:
+	 * 		<ul>
+	 * 			<li>{@link RestContextBuilder#defaultCharset(String)}
+	 * 		</ul>
 	 *	</ul>
 	 *
 	 * @param value The new value for this setting.
@@ -1018,9 +1055,16 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
 	 * 
 	 * <h5 class='section'>Notes:</h5>
 	 * <ul class='spaced-list'>
-	 * 	<li>Property: {@link RestContext#REST_maxInput}
-	 * 	<li>Annotation:  {@link RestResource#maxInput()} / {@link RestMethod#maxInput()}
-	 * 	<li>Method: {@link RestContextBuilder#maxInput(String)}
+	 * 	<li>Property:  {@link RestContext#REST_maxInput}
+	 * 	<li>Annotations:
+	 * 		<ul>
+	 * 			<li>{@link RestResource#maxInput()}
+	 * 			<li>{@link RestMethod#maxInput()}
+	 * 		</ul>
+	 * 	<li>Methods:
+	 * 		<ul>
+	 * 			<li>{@link RestContextBuilder#maxInput(String)}
+	 * 		</ul>
 	 * 	<li>String value that gets resolved to a <jk>long</jk>.
 	 * 	<li>Can be suffixed with any of the following representing kilobytes, megabytes, and gigabytes:  
 	 * 		<js>'K'</js>, <js>'M'</js>, <js>'G'</js>.
@@ -1064,9 +1108,15 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
 	 *
 	 * <h5 class='section'>Notes:</h5>
 	 * <ul class='spaced-list'>
-	 * 	<li>Property: {@link RestContext#REST_paramResolvers}
-	 * 	<li>Annotation:  {@link RestResource#paramResolvers()}
-	 * 	<li>Method: {@link RestContextBuilder#paramResolvers(Class...)}
+	 * 	<li>Property:  {@link RestContext#REST_paramResolvers}
+	 * 	<li>Annotations:
+	 * 		<ul>
+	 * 			<li>{@link RestResource#paramResolvers()}
+	 * 		</ul>
+	 * 	<li>Methods:
+	 * 		<ul>
+	 * 			<li>{@link RestContextBuilder#paramResolvers(Class...)}
+	 * 		</ul>
 	 * 	<li>{@link RestParam} classes must have either a no-arg or {@link PropertyStore} argument constructors.
 	 *	</ul>
 	 *
@@ -1108,9 +1158,15 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
 	 *
 	 * <h5 class='section'>Notes:</h5>
 	 * <ul class='spaced-list'>
-	 * 	<li>Property: {@link RestContext#REST_paramResolvers}
-	 * 	<li>Annotation:  {@link RestResource#paramResolvers()}
-	 * 	<li>Method: {@link RestContextBuilder#paramResolvers(Class...)}
+	 * 	<li>Property:  {@link RestContext#REST_paramResolvers}
+	 * 	<li>Annotations:
+	 * 		<ul>
+	 * 			<li>{@link RestResource#paramResolvers()}
+	 * 		</ul>
+	 * 	<li>Methods:
+	 * 		<ul>
+	 * 			<li>{@link RestContextBuilder#paramResolvers(Class...)}
+	 * 		</ul>
 	 * 	<li>{@link RestParam} classes must have either a no-arg or {@link PropertyStore} argument constructors.
 	 *	</ul>
 	 *
@@ -1138,9 +1194,17 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
 	 * 
 	 * <h5 class='section'>Notes:</h5>
 	 * <ul class='spaced-list'>
-	 * 	<li>Property: {@link RestContext#REST_converters}
-	 * 	<li>Annotation:  {@link RestResource#converters()} / {@link RestMethod#converters()}
-	 * 	<li>Method: {@link RestContextBuilder#converters(Class...)} / {@link RestContextBuilder#converters(RestConverter...)}
+	 * 	<li>Property:  {@link RestContext#REST_converters}
+	 * 	<li>Annotation:
+	 * 		<ul>
+	 * 			<li>{@link RestResource#converters()}
+	 * 			<li>{@link RestMethod#converters()}
+	 * 		</ul>
+	 * 	<li>Method:
+	 * 		<ul>
+	 * 			<li>{@link RestContextBuilder#converters(Class...)}
+	 * 			<li>{@link RestContextBuilder#converters(RestConverter...)}
+	 * 		</ul>
 	 * 	<li>{@link RestConverter} classes must have either a no-arg or {@link PropertyStore} argument constructors.
 	 *	</ul>
 	 *
@@ -1168,9 +1232,17 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
 	 * 
 	 * <h5 class='section'>Notes:</h5>
 	 * <ul class='spaced-list'>
-	 * 	<li>Property: {@link RestContext#REST_converters}
-	 * 	<li>Annotation:  {@link RestResource#converters()} / {@link RestMethod#converters()}
-	 * 	<li>Method: {@link RestContextBuilder#converters(Class...)} / {@link RestContextBuilder#converters(RestConverter...)}
+	 * 	<li>Property:  {@link RestContext#REST_converters}
+	 * 	<li>Annotation:
+	 * 		<ul>
+	 * 			<li>{@link RestResource#converters()}
+	 * 			<li>{@link RestMethod#converters()}
+	 * 		</ul>
+	 * 	<li>Method:
+	 * 		<ul>
+	 * 			<li>{@link RestContextBuilder#converters(Class...)}
+	 * 			<li>{@link RestContextBuilder#converters(RestConverter...)}
+	 * 		</ul>
 	 * 	<li>{@link RestConverter} classes must have either a no-arg or {@link PropertyStore} argument constructors.
 	 *	</ul>
 	 *
@@ -1194,9 +1266,17 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
 	 *
 	 * <h5 class='section'>Notes:</h5>
 	 * <ul class='spaced-list'>
-	 * 	<li>Property: {@link RestContext#REST_guards}
-	 * 	<li>Annotation:  {@link RestResource#guards()} / {@link RestMethod#guards()}
-	 * 	<li>Method: {@link RestContextBuilder#guards(Class...)} / {@link RestContextBuilder#guards(RestGuard...)}
+	 * 	<li>Property:  {@link RestContext#REST_guards}
+	 * 	<li>Annotations:
+	 * 		<ul>
+	 * 			<li>{@link RestResource#guards()}
+	 * 			<li>{@link RestMethod#guards()}
+	 * 		</ul>
+	 * 	<li>Method:
+	 * 		<ul>
+	 * 			<li>{@link RestContextBuilder#guards(Class...)}
+	 * 			<li>{@link RestContextBuilder#guards(RestGuard...)}
+	 * 		</ul>
 	 * 	<li>{@link RestGuard} classes must have either a no-arg or {@link PropertyStore} argument constructors.
 	 * 	<li>Values are added AFTER those found in the annotation and therefore take precedence over those defined via the
 	 * 		annotation.
@@ -1222,9 +1302,17 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
 	 *
 	 * <h5 class='section'>Notes:</h5>
 	 * <ul class='spaced-list'>
-	 * 	<li>Property: {@link RestContext#REST_guards}
-	 * 	<li>Annotation:  {@link RestResource#guards()} / {@link RestMethod#guards()}
-	 * 	<li>Method: {@link RestContextBuilder#guards(Class...)} / {@link RestContextBuilder#guards(RestGuard...)}
+	 * 	<li>Property:  {@link RestContext#REST_guards}
+	 * 	<li>Annotations:
+	 * 		<ul>
+	 * 			<li>{@link RestResource#guards()}
+	 * 			<li>{@link RestMethod#guards()}
+	 * 		</ul>
+	 * 	<li>Methods:
+	 * 		<ul>
+	 * 			<li>{@link RestContextBuilder#guards(Class...)}
+	 * 			<li>{@link RestContextBuilder#guards(RestGuard...)}
+	 * 		</ul>
 	 * 	<li>{@link RestGuard} classes must have either a no-arg or {@link PropertyStore} argument constructors.
 	 * 	<li>Values are added AFTER those found in the annotation and therefore take precedence over those defined via the
 	 * 		annotation.
@@ -1258,9 +1346,16 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
 	 * <p>
 	 * <h5 class='section'>Notes:</h5>
 	 * <ul class='spaced-list'>
-	 * 	<li>Property: {@link RestContext#REST_responseHandlers}
-	 * 	<li>Annotation:  {@link RestResource#responseHandlers()} 
-	 * 	<li>Method: {@link RestContextBuilder#responseHandlers(Class...)} / {@link RestContextBuilder#responseHandlers(ResponseHandler...)}
+	 * 	<li>Property:  {@link RestContext#REST_responseHandlers}
+	 * 	<li>Annotations:
+	 * 		<ul>
+	 * 			<li>{@link RestResource#responseHandlers()} 
+	 * 		</ul>
+	 * 	<li>Methods:
+	 * 		<ul>
+	 * 			<li>{@link RestContextBuilder#responseHandlers(Class...)}
+	 * 			<li>{@link RestContextBuilder#responseHandlers(ResponseHandler...)}
+	 * 		</ul>
 	 * 	<li>{@link ResponseHandler} classes must have either a no-arg or {@link PropertyStore} argument constructors.
 	 *	</ul>
 	 *
@@ -1292,9 +1387,16 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
 	 * <p>
 	 * <h5 class='section'>Notes:</h5>
 	 * <ul class='spaced-list'>
-	 * 	<li>Property: {@link RestContext#REST_responseHandlers}
-	 * 	<li>Annotation:  {@link RestResource#responseHandlers()} 
-	 * 	<li>Method: {@link RestContextBuilder#responseHandlers(Class...)} / {@link RestContextBuilder#responseHandlers(ResponseHandler...)}
+	 * 	<li>Property:  {@link RestContext#REST_responseHandlers}
+	 * 	<li>Annotations:
+	 * 		<ul>
+	 * 			<li>{@link RestResource#responseHandlers()} 
+	 * 		</ul>
+	 * 	<li>Methods:
+	 * 		<ul>
+	 * 			<li>{@link RestContextBuilder#responseHandlers(Class...)}
+	 * 			<li>{@link RestContextBuilder#responseHandlers(ResponseHandler...)}
+	 * 		</ul>
 	 * 	<li>{@link ResponseHandler} classes must have either a no-arg or {@link PropertyStore} argument constructors.
 	 *	</ul>
 	 *
@@ -1314,9 +1416,17 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
 	 * <p>
 	 * <h5 class='section'>Notes:</h5>
 	 * <ul class='spaced-list'>
-	 * 	<li>Property: {@link RestContext#REST_defaultRequestHeaders}
-	 * 	<li>Annotation:  {@link RestResource#defaultRequestHeaders()} / {@link RestMethod#defaultRequestHeaders()} 
-	 * 	<li>Method: {@link RestContextBuilder#defaultRequestHeader(String,Object)} / {@link RestContextBuilder#defaultRequestHeaders(String...)}
+	 * 	<li>Property:  {@link RestContext#REST_defaultRequestHeaders}
+	 * 	<li>Annotations:
+	 * 		<ul>
+	 * 			<li>{@link RestResource#defaultRequestHeaders()}
+	 * 			<li>{@link RestMethod#defaultRequestHeaders()} 
+	 * 		</ul>
+	 * 	<li>Methods:
+	 * 		<ul>
+	 * 			<li>{@link RestContextBuilder#defaultRequestHeader(String,Object)}
+	 * 			<li>{@link RestContextBuilder#defaultRequestHeaders(String...)}
+	 * 		</ul>
 	 * 	<li>Affects values returned by {@link RestRequest#getHeader(String)} when the header is not present on the request.
 	 * 	<li>The most useful reason for this annotation is to provide a default <code>Accept</code> header when one is not
 	 * 		specified so that a particular default {@link Serializer} is picked.
@@ -1339,9 +1449,17 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
 	 * <p>
 	 * <h5 class='section'>Notes:</h5>
 	 * <ul class='spaced-list'>
-	 * 	<li>Property: {@link RestContext#REST_defaultRequestHeaders}
-	 * 	<li>Annotation:  {@link RestResource#defaultRequestHeaders()} / {@link RestMethod#defaultRequestHeaders()} 
-	 * 	<li>Method: {@link RestContextBuilder#defaultRequestHeader(String,Object)} / {@link RestContextBuilder#defaultRequestHeaders(String...)}
+	 * 	<li>Property:  {@link RestContext#REST_defaultRequestHeaders}
+	 * 	<li>Annotations:
+	 * 		<ul>
+	 * 			<li>{@link RestResource#defaultRequestHeaders()}
+	 * 			<li>{@link RestMethod#defaultRequestHeaders()} 
+	 * 		</ul>
+	 * 	<li>Methods:
+	 * 		<ul>
+	 * 			<li>{@link RestContextBuilder#defaultRequestHeader(String,Object)}
+	 * 			<li>{@link RestContextBuilder#defaultRequestHeaders(String...)}
+	 * 		</ul>
 	 * 	<li>Strings are of the format <js>"Header-Name: header-value"</js>.
 	 * 	<li>You can use either <js>':'</js> or <js>'='</js> as the key/value delimiter.
 	 * 	<li>Key and value is trimmed of whitespace.
@@ -1374,9 +1492,16 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
 	 * <p>
 	 * <h5 class='section'>Notes:</h5>
 	 * <ul class='spaced-list'>
-	 * 	<li>Property: {@link RestContext#REST_defaultResponseHeaders}
-	 * 	<li>Annotation:  {@link RestResource#defaultResponseHeaders()} 
-	 * 	<li>Method: {@link RestContextBuilder#defaultResponseHeader(String,Object)} / {@link RestContextBuilder#defaultResponseHeaders(String...)}
+	 * 	<li>Property:  {@link RestContext#REST_defaultResponseHeaders}
+	 * 	<li>Annotations:
+	 * 		<ul>
+	 * 			<li>{@link RestResource#defaultResponseHeaders()} 
+	 * 		</ul>
+	 * 	<li>Methods:
+	 * 		<ul>
+	 * 			<li>{@link RestContextBuilder#defaultResponseHeader(String,Object)}
+	 * 			<li>{@link RestContextBuilder#defaultResponseHeaders(String...)}
+	 * 		</ul>
 	 * 	<li>This is equivalent to calling {@link RestResponse#setHeader(String, String)} programmatically in each of 
 	 * 		the Java methods.
 	 * 	<li>The header value will not be set if the header value has already been specified (hence the 'default' in the name).
@@ -1401,9 +1526,16 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
 	 * <p>
 	 * <h5 class='section'>Notes:</h5>
 	 * <ul class='spaced-list'>
-	 * 	<li>Property: {@link RestContext#REST_defaultResponseHeaders}
-	 * 	<li>Annotation:  {@link RestResource#defaultResponseHeaders()} 
-	 * 	<li>Method: {@link RestContextBuilder#defaultResponseHeader(String,Object)} / {@link RestContextBuilder#defaultResponseHeaders(String...)}
+	 * 	<li>Property:  {@link RestContext#REST_defaultResponseHeaders}
+	 * 	<li>Annotations:
+	 * 		<ul>
+	 * 			<li>{@link RestResource#defaultResponseHeaders()} 
+	 * 		</ul>
+	 * 	<li>Methods:
+	 * 		<ul>
+	 * 			<li>{@link RestContextBuilder#defaultResponseHeader(String,Object)}
+	 * 			<li>{@link RestContextBuilder#defaultResponseHeaders(String...)}
+	 * 		</ul>
 	 * 	<li>Strings are of the format <js>"Header-Name: header-value"</js>.
 	 * 	<li>You can use either <js>':'</js> or <js>'='</js> as the key/value delimiter.
 	 * 	<li>Key and value is trimmed of whitespace.
@@ -1434,13 +1566,25 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
 	 *
 	 * <p>
 	 * Overrides the media types inferred from the serializers that identify what media types can be produced by the resource.
+	 * 
+	 * <p>
+	 * This affects the values returned by {@link RestRequest#getSupportedAcceptTypes()} and the supported accept
+	 * types shown in {@link RestInfoProvider#getSwagger(RestRequest)}.
 	 *
 	 * <p>
 	 * <h5 class='section'>Notes:</h5>
 	 * <ul class='spaced-list'>
-	 * 	<li>Property: {@link RestContext#REST_supportedAcceptTypes}
-	 * 	<li>Annotation:  N/A 
-	 * 	<li>Method: {@link RestContextBuilder#supportedAcceptTypes(boolean,String...)} / {@link RestContextBuilder#supportedAcceptTypes(boolean,MediaType...)}
+	 * 	<li>Property:  {@link RestContext#REST_supportedAcceptTypes}
+	 * 	<li>Annotations:
+	 * 		<ul>
+	 * 			<li>{@link RestResource#supportedAcceptTypes()}
+	 * 			<li>{@link RestMethod#supportedAcceptTypes()}
+	 * 		</ul> 
+	 * 	<li>Methods:  
+	 * 		<ul>
+	 * 			<li>{@link RestContextBuilder#supportedAcceptTypes(boolean,String...)}
+	 * 			<li>{@link RestContextBuilder#supportedAcceptTypes(boolean,MediaType...)}
+	 * 		</ul>
 	 *	</ul>
 	 *
 	 * @param append
@@ -1457,13 +1601,25 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
 	 *
 	 * <p>
 	 * Overrides the media types inferred from the serializers that identify what media types can be produced by the resource.
+	 * 
+	 * <p>
+	 * This affects the values returned by {@link RestRequest#getSupportedAcceptTypes()} and the supported accept
+	 * types shown in {@link RestInfoProvider#getSwagger(RestRequest)}.
 	 *
 	 * <p>
 	 * <h5 class='section'>Notes:</h5>
 	 * <ul class='spaced-list'>
-	 * 	<li>Property: {@link RestContext#REST_supportedAcceptTypes}
-	 * 	<li>Annotation:  N/A 
-	 * 	<li>Method: {@link RestContextBuilder#supportedAcceptTypes(boolean,String...)} / {@link RestContextBuilder#supportedAcceptTypes(boolean,MediaType...)}
+	 * 	<li>Property:  {@link RestContext#REST_supportedAcceptTypes}
+	 * 	<li>Annotations:
+	 * 		<ul>
+	 * 			<li>{@link RestResource#supportedAcceptTypes()}
+	 * 			<li>{@link RestMethod#supportedAcceptTypes()}
+	 * 		</ul> 
+	 * 	<li>Methods:  
+	 * 		<ul>
+	 * 			<li>{@link RestContextBuilder#supportedAcceptTypes(boolean,String...)}
+	 * 			<li>{@link RestContextBuilder#supportedAcceptTypes(boolean,MediaType...)}
+	 * 		</ul>
 	 *	</ul>
 	 *
 	 * @param append
@@ -1482,11 +1638,23 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
 	 * Overrides the media types inferred from the parsers that identify what media types can be consumed by the resource.
 	 *
 	 * <p>
+	 * This affects the values returned by {@link RestRequest#getSupportedContentTypes()} and the supported content
+	 * types shown in {@link RestInfoProvider#getSwagger(RestRequest)}.
+	 * 
+	 * <p>
 	 * <h5 class='section'>Notes:</h5>
 	 * <ul class='spaced-list'>
-	 * 	<li>Property: {@link RestContext#REST_supportedContentTypes}
-	 * 	<li>Annotation:  N/A 
-	 * 	<li>Method: {@link RestContextBuilder#supportedContentTypes(boolean,String...)} / {@link RestContextBuilder#supportedContentTypes(boolean,MediaType...)}
+	 * 	<li>Property:  {@link RestContext#REST_supportedContentTypes}
+	 * 	<li>Annotations:
+	 * 		<ul>
+	 * 			<li>{@link RestResource#supportedContentTypes()}
+	 * 			<li>{@link RestMethod#supportedContentTypes()}
+	 * 		</ul> 
+	 * 	<li>Methods:  
+	 * 		<ul>
+	 * 			<li>{@link RestContextBuilder#supportedContentTypes(boolean,String...)}
+	 * 			<li>{@link RestContextBuilder#supportedContentTypes(boolean,MediaType...)}
+	 * 		</ul>
 	 *	</ul>
 	 *
 	 * @param append
@@ -1505,11 +1673,23 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
 	 * Overrides the media types inferred from the parsers that identify what media types can be consumed by the resource.
 	 *
 	 * <p>
+	 * This affects the values returned by {@link RestRequest#getSupportedContentTypes()} and the supported content
+	 * types shown in {@link RestInfoProvider#getSwagger(RestRequest)}.
+	 * 
+	 * <p>
 	 * <h5 class='section'>Notes:</h5>
 	 * <ul class='spaced-list'>
-	 * 	<li>Property: {@link RestContext#REST_supportedContentTypes}
-	 * 	<li>Annotation:  N/A 
-	 * 	<li>Method: {@link RestContextBuilder#supportedContentTypes(boolean,String...)} / {@link RestContextBuilder#supportedContentTypes(boolean,MediaType...)}
+	 * 	<li>Property:  {@link RestContext#REST_supportedContentTypes}
+	 * 	<li>Annotations:
+	 * 		<ul>
+	 * 			<li>{@link RestResource#supportedContentTypes()}
+	 * 			<li>{@link RestMethod#supportedContentTypes()}
+	 * 		</ul> 
+	 * 	<li>Methods:  
+	 * 		<ul>
+	 * 			<li>{@link RestContextBuilder#supportedContentTypes(boolean,String...)}
+	 * 			<li>{@link RestContextBuilder#supportedContentTypes(boolean,MediaType...)}
+	 * 		</ul>
 	 *	</ul>
 	 *
 	 * @param append
@@ -1534,9 +1714,15 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
 	 * <p>
 	 * <h5 class='section'>Notes:</h5>
 	 * <ul class='spaced-list'>
-	 * 	<li>Property: {@link RestContext#REST_clientVersionHeader}
-	 * 	<li>Annotation:  {@link RestResource#clientVersionHeader()} 
-	 * 	<li>Method: {@link RestContextBuilder#clientVersionHeader(String)}
+	 * 	<li>Property:  {@link RestContext#REST_clientVersionHeader}
+	 * 	<li>Annotations:
+	 * 		<ul>
+	 * 			<li>{@link RestResource#clientVersionHeader()} 
+	 * 		</ul>
+	 * 	<li>Methods:
+	 * 		<ul>
+	 * 			<li>{@link RestContextBuilder#clientVersionHeader(String)}
+	 * 		</ul>
 	 *	</ul>
 	 *
 	 * @param clientVersionHeader The name of the HTTP header that denotes the client version.
@@ -1558,9 +1744,16 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
 	 * <p>
 	 * <h5 class='section'>Notes:</h5>
 	 * <ul class='spaced-list'>
-	 * 	<li>Property: {@link RestContext#REST_resourceResolver}
-	 * 	<li>Annotation:  {@link RestResource#resourceResolver()} 
-	 * 	<li>Method: {@link RestContextBuilder#resourceResolver(Class)} / {@link RestContextBuilder#resourceResolver(RestResourceResolver)}
+	 * 	<li>Property:  {@link RestContext#REST_resourceResolver}
+	 * 	<li>Annotations:
+	 * 		<ul>
+	 * 			<li>{@link RestResource#resourceResolver()} 
+	 * 		</ul>
+	 * 	<li>Methods:
+	 * 		<ul>
+	 * 			<li>{@link RestContextBuilder#resourceResolver(Class)}
+	 * 			<li>{@link RestContextBuilder#resourceResolver(RestResourceResolver)}
+	 * 		</ul>
 	 * 	<li>Unless overridden, resource resolvers are inherited from parent resources.
 	 *	</ul>
 	 *
@@ -1583,9 +1776,16 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
 	 * <p>
 	 * <h5 class='section'>Notes:</h5>
 	 * <ul class='spaced-list'>
-	 * 	<li>Property: {@link RestContext#REST_resourceResolver}
-	 * 	<li>Annotation:  {@link RestResource#resourceResolver()} 
-	 * 	<li>Method: {@link RestContextBuilder#resourceResolver(Class)} / {@link RestContextBuilder#resourceResolver(RestResourceResolver)}
+	 * 	<li>Property:  {@link RestContext#REST_resourceResolver}
+	 * 	<li>Annotations:
+	 * 		<ul>
+	 * 			<li>{@link RestResource#resourceResolver()} 
+	 * 		</ul>
+	 * 	<li>Methods:
+	 * 		<ul>
+	 * 			<li>{@link RestContextBuilder#resourceResolver(Class)}
+					<li>{@link RestContextBuilder#resourceResolver(RestResourceResolver)}
+				</ul>
 	 * 	<li>Unless overridden, resource resolvers are inherited from parent resources.
 	 *	</ul>
 	 *
@@ -1609,9 +1809,16 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
 	 * <p>
 	 * <h5 class='section'>Notes:</h5>
 	 * <ul class='spaced-list'>
-	 * 	<li>Property: {@link RestContext#REST_logger}
-	 * 	<li>Annotation:  {@link RestResource#logger()} 
-	 * 	<li>Method: {@link RestContextBuilder#logger(Class)} / {@link RestContextBuilder#logger(RestLogger)} 
+	 * 	<li>Property:  {@link RestContext#REST_logger}
+	 * 	<li>Annotations:
+	 * 		<ul>
+	 * 			<li>{@link RestResource#logger()} 
+	 * 		</ul>
+	 * 	<li>Methods:
+	 * 		<ul>
+	 * 			<li>{@link RestContextBuilder#logger(Class)}
+	 * 			<li>{@link RestContextBuilder#logger(RestLogger)} 
+	 * 		</ul>
 	 *	</ul>
 	 *
 	 * @param logger The new logger for this resource.  Can be <jk>null</jk> to disable logging.
@@ -1634,9 +1841,16 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
 	 * <p>
 	 * <h5 class='section'>Notes:</h5>
 	 * <ul class='spaced-list'>
-	 * 	<li>Property: {@link RestContext#REST_logger}
-	 * 	<li>Annotation:  {@link RestResource#logger()} 
-	 * 	<li>Method: {@link RestContextBuilder#logger(Class)} / {@link RestContextBuilder#logger(RestLogger)} 
+	 * 	<li>Property:  {@link RestContext#REST_logger}
+	 * 	<li>Annotations:
+	 * 		<ul>
+	 * 			<li>{@link RestResource#logger()} 
+	 * 		</ul>
+	 * 	<li>Methods:
+	 * 		<ul>
+	 * 			<li>{@link RestContextBuilder#logger(Class)}
+	 * 			<li>{@link RestContextBuilder#logger(RestLogger)} 
+	 * 		</ul>
 	 *	</ul>
 	 *
 	 * @param logger The new logger for this resource.  Can be <jk>null</jk> to disable logging.
@@ -1656,9 +1870,16 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
 	 * <p>
 	 * <h5 class='section'>Notes:</h5>
 	 * <ul class='spaced-list'>
-	 * 	<li>Property: {@link RestContext#REST_callHandler}
-	 * 	<li>Annotation:  {@link RestResource#callHandler()} 
-	 * 	<li>Method: {@link RestContextBuilder#callHandler(Class)} / {@link RestContextBuilder#callHandler(RestCallHandler)} 
+	 * 	<li>Property:  {@link RestContext#REST_callHandler}
+	 * 	<li>Annotations:
+	 * 		<ul>
+	 * 			<li>{@link RestResource#callHandler()} 
+	 * 		</ul>
+	 * 	<li>Methods:
+	 * 		<ul>
+	 * 			<li>{@link RestContextBuilder#callHandler(Class)}
+	 * 			<li>{@link RestContextBuilder#callHandler(RestCallHandler)} 
+	 * 		</ul>
 	 *	</ul>
 	 *
 	 * @param restHandler The new call handler for this resource.
@@ -1678,9 +1899,16 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
 	 * <p>
 	 * <h5 class='section'>Notes:</h5>
 	 * <ul class='spaced-list'>
-	 * 	<li>Property: {@link RestContext#REST_callHandler}
-	 * 	<li>Annotation:  {@link RestResource#callHandler()} 
-	 * 	<li>Method: {@link RestContextBuilder#callHandler(Class)} / {@link RestContextBuilder#callHandler(RestCallHandler)} 
+	 * 	<li>Property:  {@link RestContext#REST_callHandler}
+	 * 	<li>Annotations:
+	 * 		<ul>
+	 * 			<li>{@link RestResource#callHandler()} 
+	 * 		</ul>
+	 * 	<li>Methods:
+	 * 		<ul>
+	 * 			<li>{@link RestContextBuilder#callHandler(Class)}
+	 * 			<li>{@link RestContextBuilder#callHandler(RestCallHandler)} 
+	 * 		</ul>
 	 *	</ul>
 	 *
 	 * @param restHandler The new call handler for this resource.
@@ -1702,9 +1930,16 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
 	 * <p>
 	 * <h5 class='section'>Notes:</h5>
 	 * <ul class='spaced-list'>
-	 * 	<li>Property: {@link RestContext#REST_infoProvider}
-	 * 	<li>Annotation:  {@link RestResource#infoProvider()} 
-	 * 	<li>Method: {@link RestContextBuilder#infoProvider(Class)} / {@link RestContextBuilder#infoProvider(RestInfoProvider)} 
+	 * 	<li>Property:  {@link RestContext#REST_infoProvider}
+	 * 	<li>Annotations:
+	 * 		<ul>
+	 * 			<li>{@link RestResource#infoProvider()} 
+	 * 		</ul>
+	 * 	<li>Methods:
+	 * 		<ul>
+	 * 			<li>{@link RestContextBuilder#infoProvider(Class)}
+	 * 			<li>{@link RestContextBuilder#infoProvider(RestInfoProvider)} 
+	 * 		</ul>
 	 *	</ul>
 	 *
 	 * @param infoProvider The new info provider for this resource.
@@ -1726,9 +1961,16 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
 	 * <p>
 	 * <h5 class='section'>Notes:</h5>
 	 * <ul class='spaced-list'>
-	 * 	<li>Property: {@link RestContext#REST_infoProvider}
-	 * 	<li>Annotation:  {@link RestResource#infoProvider()} 
-	 * 	<li>Method: {@link RestContextBuilder#infoProvider(Class)} / {@link RestContextBuilder#infoProvider(RestInfoProvider)} 
+	 * 	<li>Property:  {@link RestContext#REST_infoProvider}
+	 * 	<li>Annotations:
+	 * 		<ul>
+	 * 			<li>{@link RestResource#infoProvider()} 
+	 * 		</ul>
+	 * 	<li>Methods:
+	 * 		<ul>
+	 * 			<li>{@link RestContextBuilder#infoProvider(Class)}
+	 * 			<li>{@link RestContextBuilder#infoProvider(RestInfoProvider)} 
+	 * 		</ul>
 	 *	</ul>
 	 *
 	 * @param infoProvider The new info provider for this resource.
@@ -1739,6 +1981,325 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
 	}
 
 	/**
+	 * <b>Configuration property:</b>  Static file mappings. 
+	 *
+	 * <p>
+	 * Used to define paths and locations of statically-served files such as images or HTML documents.
+	 * 
+	 * <p>
+	 * Static files are found by calling {@link RestContext#getClasspathResource(String,Locale)} which uses the registered 
+	 * {@link ClasspathResourceFinder} for locating files on the classpath (or other location).
+	 * 
+	 * <p>
+	 * An example where this class is used is in the {@link RestResource#staticFiles} annotation:
+	 * <p class='bcode'>
+	 * 	<jk>package</jk> com.foo.mypackage;
+	 * 
+	 * 	<ja>@RestResource</ja>(
+	 * 		path=<js>"/myresource"</js>,
+	 * 		staticFiles=<js>"htdocs:docs"</js>
+	 * 	)
+	 * 	<jk>public class</jk> MyResource <jk>extends</jk> RestServletDefault {...}
+	 * </p>
+	 * 
+	 * <p>
+	 * In the example above, given a GET request to <l>/myresource/htdocs/foobar.html</l>, the servlet will attempt to find 
+	 * the <l>foobar.html</l> file in the following ordered locations:
+	 * <ol>
+	 * 	<li><l>com.foo.mypackage.docs</l> package.
+	 * 	<li><l>org.apache.juneau.rest.docs</l> package (since <l>RestServletDefault</l> is in <l>org.apache.juneau.rest</l>).
+	 * 	<li><l>[working-dir]/docs</l> directory.
+	 * </ol>
+	 * 
+	 * <h6 class='topic'>Notes:</h6>
+	 * <ul class='spaced-list'>
+	 * 	<li>Property:  {@link RestContext#REST_staticFiles}
+	 * 	<li>Annotations: 
+	 * 		<ul>
+	 * 			<li>{@link RestResource#staticFiles()} 
+	 * 		</ul>
+	 * 	<li>Methods: 
+	 * 		<ul>
+	 * 			<li>{@link RestContextBuilder#staticFiles(String)},
+	 * 			<li>{@link RestContextBuilder#staticFiles(Class,String)}
+	 * 			<li>{@link RestContextBuilder#staticFiles(String,String)}
+	 * 			<li>{@link RestContextBuilder#staticFiles(Class,String,String)} 
+	 * 			<li>{@link RestContextBuilder#staticFiles(StaticFileMapping...)} 
+	 * 		</ul>
+	 * 	<li>Mappings are cumulative from parent to child.  
+	 * 	<li>Child resources can override mappings made on parent resources.
+	 * 	<li>The media type on the response is determined by the {@link RestContext#getMediaTypeForName(String)} method.
+	 * 	<li>The resource finder is configured via the {@link RestContext#REST_classpathResourceFinder} setting, and can be
+	 * 		overridden to provide customized handling of resource retrieval.
+	 * 	<li>The {@link RestContext#REST_useClasspathResourceCaching} setting can be used to cache static files in memory
+	 * 		to improve performance.
+	 * </ul>
+	 *
+	 * @param sfm The static file mappings to add to this resource.
+	 * @return This object (for method chaining).
+	 */
+	public RestContextBuilder staticFiles(StaticFileMapping...sfm) {
+		return addTo(REST_staticFiles, sfm);
+	}
+
+	/**
+	 * Same as {@link #staticFiles(StaticFileMapping...)}, except input is in the form of a mapping string.
+	 * 
+	 * <p>
+	 * Mapping string must be one of these formats:
+	 * <ul>
+	 * 	<li><js>"path:location"</js> (e.g. <js>"foodocs:docs/foo"</js>)
+	 * 	<li><js>"path:location:headers-json"</js> (e.g. <js>"foodocs:docs/foo:{'Cache-Control':'max-age=86400, public'}"</js>)
+	 * </ul>
+	 * 
+	 * @param mappingString The static file mapping string.
+	 * @return This object (for method chaining).
+	 */
+	public RestContextBuilder staticFiles(String mappingString) {
+		return staticFiles(new StaticFileMapping(resourceClass, mappingString));
+	}
+
+	/**
+	 * Same as {@link #staticFiles(String)}, except overrides the base class for retrieving the resource.
+	 * 
+	 * <p>
+	 * Mapping string must be one of these formats:
+	 * <ul>
+	 * 	<li><js>"path:location"</js> (e.g. <js>"foodocs:docs/foo"</js>)
+	 * 	<li><js>"path:location:headers-json"</js> (e.g. <js>"foodocs:docs/foo:{'Cache-Control':'max-age=86400, public'}"</js>)
+	 * </ul>
+	 * 
+	 * @param baseClass 
+	 * 	Overrides the default class to use for retrieving the classpath resource. 
+	 * 	<br>If <jk>null<jk>, uses the REST resource class.
+	 * @param mappingString The static file mapping string.
+	 * @return This object (for method chaining).
+	 */
+	public RestContextBuilder staticFiles(Class<?> baseClass, String mappingString) {
+		return staticFiles(new StaticFileMapping(baseClass, mappingString));
+	}
+	
+	/**
+	 * Same as {@link #staticFiles(String)}, except path and location are already split values.
+	 * 
+	 * @param path 
+	 * 	The mapped URI path.
+	 * 	<br>Leading and trailing slashes are trimmed.
+	 * @param location 
+	 * 	The location relative to the resource class.
+	 * 	<br>Leading and trailing slashes are trimmed.
+	 * @return This object (for method chaining).
+	 */
+	public RestContextBuilder staticFiles(String path, String location) {
+		return staticFiles(new StaticFileMapping(null, path, location, null));
+	}
+
+	/**
+	 * Same as {@link #staticFiles(String,String)},  except overrides the base class for retrieving the resource.
+	 * 
+	 * @param baseClass 
+	 * 	Overrides the default class to use for retrieving the classpath resource. 
+	 * 	<br>If <jk>null<jk>, uses the REST resource class.
+	 * @param path 
+	 * 	The mapped URI path.
+	 * 	<br>Leading and trailing slashes are trimmed.
+	 * @param location 
+	 * 	The location relative to the resource class.
+	 * 	<br>Leading and trailing slashes are trimmed.
+	 * @return This object (for method chaining).
+	 */
+	public RestContextBuilder staticFiles(Class<?> baseClass, String path, String location) {
+		return staticFiles(new StaticFileMapping(baseClass, path, location, null));
+	}
+
+	/**
+	 * <b>Configuration property:</b>  Static file response headers. 
+	 *
+	 * <p>
+	 * Used to customize the headers on responses returned for statically-served files.
+	 * 
+	 * <h6 class='topic'>Notes:</h6>
+	 * <ul class='spaced-list'>
+	 * 	<li>Property:  {@link RestContext#REST_staticFileResponseHeaders}
+	 * 	<li>Annotations: 
+	 * 		<ul>
+	 * 			<li>{@link RestResource#staticFileResponseHeaders()} 
+	 * 		</ul>
+	 * 	<li>Methods: 
+	 * 		<ul>
+	 * 			<li>{@link RestContextBuilder#staticFileResponseHeaders(boolean,Map)}
+	 * 			<li>{@link RestContextBuilder#staticFileResponseHeaders(String...)}
+	 * 			<li>{@link RestContextBuilder#staticFileResponseHeader(String,String)}
+	 * 		</ul>
+	 * </ul>
+	 * 
+	 * @param append
+	 * 	If <jk>true</jk>, append to the existing list, otherwise overwrite the previous value. 
+	 * @param headers The headers to add to this list.
+	 * @return This object (for method chaining).
+	 */
+	public RestContextBuilder staticFileResponseHeaders(boolean append, Map<String,String> headers) {
+		return set(append, REST_staticFileResponseHeaders, headers);
+	}
+
+	/**
+	 * <b>Configuration property:</b>  Static file response headers. 
+	 *
+	 * <p>
+	 * Used to customize the headers on responses returned for statically-served files.
+	 * 
+	 * <h6 class='topic'>Notes:</h6>
+	 * <ul class='spaced-list'>
+	 * 	<li>Property:  {@link RestContext#REST_staticFileResponseHeaders}
+	 * 	<li>Annotations: 
+	 * 		<ul>
+	 * 			<li>{@link RestResource#staticFileResponseHeaders()} 
+	 * 		</ul>
+	 * 	<li>Methods: 
+	 * 		<ul>
+	 * 			<li>{@link RestContextBuilder#staticFileResponseHeaders(boolean,Map)}
+	 * 			<li>{@link RestContextBuilder#staticFileResponseHeaders(String...)}
+	 * 			<li>{@link RestContextBuilder#staticFileResponseHeader(String,String)}
+	 * 		</ul>
+	 * </ul>
+	 * 
+	 * @param headers The headers in the format <js>"Header-Name: header-value"</js>.
+	 * @return This object (for method chaining).
+	 * @throws RestServletException If malformed header is found.
+	 */
+	public RestContextBuilder staticFileResponseHeaders(String...headers) throws RestServletException {
+		for (String header : headers) {
+			String[] h = RestUtils.parseHeader(header);
+			if (h == null)
+				throw new RestServletException("Invalid static file response header specified: ''{0}''.  Must be in the format: ''Header-Name: header-value''", header);
+			staticFileResponseHeader(h[0], h[1]);
+		}
+		return this;
+	}
+
+	/**
+	 * <b>Configuration property:</b>  Static file response headers. 
+	 *
+	 * <p>
+	 * Used to customize the headers on responses returned for statically-served files.
+	 * 
+	 * <h6 class='topic'>Notes:</h6>
+	 * <ul class='spaced-list'>
+	 * 	<li>Property:  {@link RestContext#REST_staticFileResponseHeaders}
+	 * 	<li>Annotations: 
+	 * 		<ul>
+	 * 			<li>{@link RestResource#staticFileResponseHeaders()} 
+	 * 		</ul>
+	 * 	<li>Methods: 
+	 * 		<ul>
+	 * 			<li>{@link RestContextBuilder#staticFileResponseHeaders(boolean,Map)}
+	 * 			<li>{@link RestContextBuilder#staticFileResponseHeaders(String...)}
+	 * 			<li>{@link RestContextBuilder#staticFileResponseHeader(String,String)}
+	 * 		</ul>
+	 * </ul>
+	 * 
+	 * @param name The HTTP header name.
+	 * @param value The HTTP header value.
+	 * @return This object (for method chaining).
+	 */
+	public RestContextBuilder staticFileResponseHeader(String name, String value) {
+		return addTo(REST_staticFileResponseHeaders, name, value);
+	}
+
+	/**
+	 * <b>Configuration property:</b>  Classpath resource finder. 
+	 * 
+	 * <p>
+	 * Used to retrieve localized files from the classpath.
+	 * 
+	 * <h6 class='topic'>Notes:</h6>
+	 * <ul class='spaced-list'>
+	 * 	<li>Property:  {@link RestContext#REST_classpathResourceFinder}
+	 * 	<li>Annotations: 
+	 * 		<ul>
+	 * 			<li>{@link RestResource#classpathResourceFinder()} 
+	 * 		</ul>
+	 * 	<li>Methods: 
+	 * 		<ul>
+	 * 			<li>{@link RestContextBuilder#classpathResourceFinder(Class)}
+	 * 			<li>{@link RestContextBuilder#classpathResourceFinder(ClasspathResourceFinder)}
+	 * 		</ul>
+	 * 	<li>
+	 * 		The default value is {@link ClasspathResourceFinderBasic} which provides basic support for finding localized
+	 * 		resources on the classpath and JVM working directory.
+	 * 		<br>The {@link ClasspathResourceFinderRecursive} is another option that also recursively searches for resources
+	 * 		up the parent class hierarchy.
+	 * 		<br>Each of these classes can be extended to provide customized handling of resource retrieval.
+	 * </ul>
+	 * 
+	 * @param classpathResourceFinder The resource finder class.
+	 * @return This object (for method chaining).
+	 */
+	public RestContextBuilder classpathResourceFinder(Class<? extends ClasspathResourceFinder> classpathResourceFinder) {
+		return set(REST_classpathResourceFinder, classpathResourceFinder);
+	}
+	
+	/**
+	 * <b>Configuration property:</b>  Classpath resource finder. 
+	 * 
+	 * <p>
+	 * Used to retrieve localized files from the classpath.
+	 * 
+	 * <h6 class='topic'>Notes:</h6>
+	 * <ul class='spaced-list'>
+	 * 	<li>Property:  {@link RestContext#REST_classpathResourceFinder}
+	 * 	<li>Annotations: 
+	 * 		<ul>
+	 * 			<li>{@link RestResource#classpathResourceFinder()} 
+	 * 		</ul>
+	 * 	<li>Methods: 
+	 * 		<ul>
+	 * 			<li>{@link RestContextBuilder#classpathResourceFinder(Class)}
+	 * 			<li>{@link RestContextBuilder#classpathResourceFinder(ClasspathResourceFinder)}
+	 * 		</ul>
+	 * 	<li>
+	 * 		The default value is {@link ClasspathResourceFinderBasic} which provides basic support for finding localized
+	 * 		resources on the classpath and JVM working directory.
+	 * 		<br>The {@link ClasspathResourceFinderRecursive} is another option that also recursively searches for resources
+	 * 		up the parent class hierarchy.
+	 * 		<br>Each of these classes can be extended to provide customized handling of resource retrieval.
+	 * </ul>
+	 * 
+	 * @param classpathResourceFinder The resource finder instance.
+	 * @return This object (for method chaining).
+	 */
+	public RestContextBuilder classpathResourceFinder(ClasspathResourceFinder classpathResourceFinder) {
+		return set(REST_classpathResourceFinder, classpathResourceFinder);
+	}
+
+	/**
+	 * <b>Configuration property:</b>  Use classpath resource caching. 
+	 *
+	 * <p>
+	 * When enabled, resources retrieved via {@link RestContext#getClasspathResource(String, Locale)} (and related 
+	 * methods) will be cached in memory to speed subsequent lookups.
+	 * 
+	 * <h6 class='topic'>Notes:</h6>
+	 * <ul class='spaced-list'>
+	 * 	<li>Property:  {@link RestContext#REST_useClasspathResourceCaching}
+	 * 	<li>Annotations: 
+	 * 		<ul>
+	 * 			<li>{@link RestResource#useClasspathResourceCaching()} 
+	 * 		</ul>
+	 * 	<li>Methods: 
+	 * 		<ul>
+	 * 			<li>{@link RestContextBuilder#useClasspathResourceCaching(boolean)}
+	 * 		</ul>
+	 * </ul>
+	 * 
+	 * @param value The new value.
+	 * @return This object (for method chaining).
+	 */
+	public RestContextBuilder useClasspathResourceCaching(boolean value) {
+		return set(REST_useClasspathResourceCaching, value);
+	}
+
+	/**
 	 * <b>Configuration property:</b>  Serializer listener.
 	 * 
 	 * <p>
@@ -1747,17 +2308,21 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
 	 * <p>
 	 * <h5 class='section'>Notes:</h5>
 	 * <ul class='spaced-list'>
-	 * 	<li>Property: {@link Serializer#SERIALIZER_listener}
-	 * 	<li>Annotation:  {@link RestResource#serializerListener()} 
-	 * 	<li>Method: {@link RestContextBuilder#serializerListener(Class)} 
+	 * 	<li>Property:  {@link Serializer#SERIALIZER_listener}
+	 * 	<li>Annotations:
+	 * 		<ul>
+	 * 			<li>{@link RestResource#serializerListener()} 
+	 * 		</ul>
+	 * 	<li>Methods:
+	 * 		<ul>
+	 * 			<li>{@link RestContextBuilder#serializerListener(Class)} 
+	 * 		</ul>
 	 *	</ul>
 	 *
 	 * @param listener The listener to add to this config.
 	 * @return This object (for method chaining).
 	 */
 	public RestContextBuilder serializerListener(Class<? extends SerializerListener> listener) {
-		if (listener == SerializerListener.Null.class)
-			return this;
 		return set(SERIALIZER_listener, listener);
 	}
 
@@ -1770,17 +2335,21 @@ public class RestContextBuilder extends BeanContextBuilder implements ServletCon
 	 * <p>
 	 * <h5 class='section'>Notes:</h5>
 	 * <ul class='spaced-list'>
-	 * 	<li>Property: {@link Parser#PARSER_listener}
-	 * 	<li>Annotation:  {@link RestResource#parserListener()} 
-	 * 	<li>Method: {@link RestContextBuilder#parserListener(Class)} 
+	 * 	<li>Property:  {@link Parser#PARSER_listener}
+	 * 	<li>Annotations:
+	 * 		<ul>
+	 * 			<li>{@link RestResource#parserListener()} 
+	 * 		</ul>
+	 * 	<li>Methods:
+	 * 		<ul>
+	 * 			<li>{@link RestContextBuilder#parserListener(Class)}
+	 * 		</ul> 
 	 *	</ul>
 	 *
 	 * @param listener The listener to add to this config.
 	 * @return This object (for method chaining).
 	 */
 	public RestContextBuilder parserListener(Class<? extends ParserListener> listener) {
-		if (listener == ParserListener.Null.class)
-			return this;
 		return set(PARSER_listener, listener);
 	}
 

http://git-wip-us.apache.org/repos/asf/juneau/blob/b820b273/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestInfoProvider.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestInfoProvider.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestInfoProvider.java
index 2a3344d..e40e26a 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestInfoProvider.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestInfoProvider.java
@@ -122,7 +122,7 @@ public class RestInfoProvider {
 	 * @return A new Swagger instance.
 	 * @throws RestException
 	 */
-	protected Swagger getSwagger(RestRequest req) throws RestException {
+	public Swagger getSwagger(RestRequest req) throws RestException {
 		try {
 			// If a file is defined, use that.
 			Swagger s = req.getSwaggerFromFile();
@@ -136,8 +136,8 @@ public class RestInfoProvider {
 					.description(getDescription(req))
 					.termsOfService(getTermsOfService(req))
 				)
-				.consumes(context.getSupportedAcceptTypes())
-				.produces(context.getSupportedContentTypes())
+				.consumes(req.getSupportedAcceptTypes())
+				.produces(req.getSupportedContentTypes())
 				.tags(getTags(req))
 				.externalDocs(getExternalDocs(req));
 
@@ -177,7 +177,7 @@ public class RestInfoProvider {
 		Swagger s = swaggers.get(locale);
 		if (s == null) {
 			try {
-				s = context.getResource(Swagger.class, MediaType.JSON, getClass().getSimpleName() + ".json", locale);
+				s = context.getClasspathResource(Swagger.class, MediaType.JSON, getClass().getSimpleName() + ".json", locale);
 				swaggers.putIfAbsent(locale, s == null ? Swagger.NULL : s);
 			} catch (Exception e) {
 				throw new RestException(SC_INTERNAL_SERVER_ERROR, e);

http://git-wip-us.apache.org/repos/asf/juneau/blob/b820b273/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestRequest.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestRequest.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestRequest.java
index fd38e24..226b100 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestRequest.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestRequest.java
@@ -87,7 +87,7 @@ public final class RestRequest extends HttpServletRequestWrapper {
 	private VarResolverSession varSession;
 	private final RequestQuery queryParams;
 	private RequestFormData formData;
-	private Map<String,String> defFormData;
+	private Map<String,Object> defFormData;
 	private RequestPathMatch pathParams;
 	private boolean isPost;
 	private UriContext uriContext;
@@ -96,6 +96,7 @@ public final class RestRequest extends HttpServletRequestWrapper {
 	private ConfigFile cf;
 	private Swagger swagger, fileSwagger;
 	private Map<String,Widget> widgets;
+	private List<MediaType> supportedContentTypes, supportedAcceptTypes;
 
 	/**
 	 * Constructor.
@@ -159,10 +160,11 @@ public final class RestRequest extends HttpServletRequestWrapper {
 	/*
 	 * Called from RestServlet after a match has been made but before the guard or method invocation.
 	 */
-	final void init(Method javaMethod, ObjectMap properties, Map<String,String> defHeader,
-			Map<String,String> defQuery, Map<String,String> defFormData, String defaultCharset, long maxInput,
+	final void init(Method javaMethod, ObjectMap properties, Map<String,Object> defHeader,
+			Map<String,Object> defQuery, Map<String,Object> defFormData, String defaultCharset, long maxInput,
 			SerializerGroup mSerializers, ParserGroup mParsers, HttpPartParser mUrlEncodingParser,
-			BeanContext beanContext, EncoderGroup encoders, Map<String,Widget> widgets) {
+			BeanContext beanContext, EncoderGroup encoders, Map<String,Widget> widgets, List<MediaType> supportedAcceptTypes, 
+			List<MediaType> supportedContentTypes) {
 		this.javaMethod = javaMethod;
 		this.properties = properties;
 		this.partParser = mUrlEncodingParser;
@@ -190,6 +192,8 @@ public final class RestRequest extends HttpServletRequestWrapper {
 		this.defaultCharset = defaultCharset;
 		this.defFormData = defFormData;
 		this.widgets = widgets;
+		this.supportedAcceptTypes = supportedAcceptTypes;
+		this.supportedContentTypes = supportedContentTypes;
 
 		String stylesheet = getQuery().getString("stylesheet");
 		if (stylesheet != null)
@@ -301,12 +305,21 @@ public final class RestRequest extends HttpServletRequestWrapper {
 	}
 
 	/**
+	 * Returns the media types that are valid for <code>Accept</code> headers on the request.
+	 *
+	 * @return The set of media types registered in the serializer group of this request.
+	 */
+	public List<MediaType> getSupportedAcceptTypes() {
+		return supportedAcceptTypes;
+	}
+
+	/**
 	 * 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<MediaType> getSupportedMediaTypes() {
-		return parserGroup.getSupportedMediaTypes();
+	public List<MediaType> getSupportedContentTypes() {
+		return supportedContentTypes;
 	}
 
 	/**
@@ -870,8 +883,8 @@ public final class RestRequest extends HttpServletRequestWrapper {
 	 * @return A new reader resource, or <jk>null</jk> if resource could not be found.
 	 * @throws IOException
 	 */
-	public ReaderResource getReaderResource(String name, boolean resolveVars, MediaType mediaType) throws IOException {
-		String s = context.getResourceAsString(name, getLocale());
+	public ReaderResource getClasspathReaderResource(String name, boolean resolveVars, MediaType mediaType) throws IOException {
+		String s = context.getClasspathResourceAsString(name, getLocale());
 		if (s == null)
 			return null;
 		ReaderResource.Builder b = new ReaderResource.Builder().mediaType(mediaType).contents(s);
@@ -881,7 +894,7 @@ public final class RestRequest extends HttpServletRequestWrapper {
 	}
 
 	/**
-	 * Same as {@link #getReaderResource(String, boolean, MediaType)} except uses the resource mime-type map
+	 * Same as {@link #getClasspathReaderResource(String, boolean, MediaType)} except uses the resource mime-type map
 	 * constructed using {@link RestContextBuilder#mimeTypes(String...)} to determine the media type.
 	 *
 	 * @param name The name of the resource (i.e. the value normally passed to {@link Class#getResourceAsStream(String)}.
@@ -892,19 +905,19 @@ public final class RestRequest extends HttpServletRequestWrapper {
 	 * @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, MediaType.forString(context.getMediaTypeForName(name)));
+	public ReaderResource getClasspathReaderResource(String name, boolean resolveVars) throws IOException {
+		return getClasspathReaderResource(name, resolveVars, MediaType.forString(context.getMediaTypeForName(name)));
 	}
 
 	/**
-	 * Same as {@link #getReaderResource(String, boolean)} with <code>resolveVars == <jk>false</jk></code>
+	 * Same as {@link #getClasspathReaderResource(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, MediaType.forString(context.getMediaTypeForName(name)));
+	public ReaderResource getClasspathReaderResource(String name) throws IOException {
+		return getClasspathReaderResource(name, false, MediaType.forString(context.getMediaTypeForName(name)));
 	}
 
 	/**
@@ -973,7 +986,7 @@ public final class RestRequest extends HttpServletRequestWrapper {
 			sb.append("\t").append(h).append(": ").append(getHeader(h)).append("\n");
 		}
 		sb.append("---Default Servlet Headers---\n");
-		for (Map.Entry<String,String> e : context.getDefaultRequestHeaders().entrySet()) {
+		for (Map.Entry<String,Object> e : context.getDefaultRequestHeaders().entrySet()) {
 			sb.append("\t").append(e.getKey()).append(": ").append(e.getValue()).append("\n");
 		}
 		if (javaMethod == null) {

http://git-wip-us.apache.org/repos/asf/juneau/blob/b820b273/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestResponse.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestResponse.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestResponse.java
index 63206a6..310d910 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestResponse.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestResponse.java
@@ -23,6 +23,7 @@ import org.apache.juneau.*;
 import org.apache.juneau.encoders.*;
 import org.apache.juneau.http.*;
 import org.apache.juneau.httppart.*;
+import org.apache.juneau.internal.*;
 import org.apache.juneau.serializer.*;
 
 /**
@@ -69,8 +70,8 @@ public final class RestResponse extends HttpServletResponseWrapper {
 		super(res);
 		this.request = req;
 
-		for (Map.Entry<String,String> e : context.getDefaultResponseHeaders().entrySet())
-			setHeader(e.getKey(), e.getValue());
+		for (Map.Entry<String,Object> e : context.getDefaultResponseHeaders().entrySet())
+			setHeader(e.getKey(), StringUtils.toString(e.getValue()));
 
 		try {
 			String passThroughHeaders = req.getHeader("x-response-headers");

http://git-wip-us.apache.org/repos/asf/juneau/blob/b820b273/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestServletDefault.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestServletDefault.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestServletDefault.java
index 2c6d8f1..900ac77 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestServletDefault.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestServletDefault.java
@@ -153,7 +153,7 @@ import org.apache.juneau.xml.*;
  * 		to <js>"styles/juneau.css"</js>.
  * 	<li>
  * 		Provides a default classpath entry "htdocs" by setting
- * 		{@link RestResource#staticFiles() @RestResource.staticFiles()} to <js>"{htdocs:'htdocs'}"</js>.
+ * 		{@link RestResource#staticFiles() @RestResource.staticFiles()} to <code>{<js>"htdocs:htdocs"</js>,<js>"styles:styles"</js>}</code>.
  * 		This allows files inside the <code>[servletPackage].htdocs</code> package to be served up under the URL
  * 		<code>/servletPath/htdocs</code>.
  * </ul>
@@ -201,7 +201,8 @@ import org.apache.juneau.xml.*;
 	),
 
 	// These are static files that are served up by the servlet under the specified sub-paths.
-	staticFiles="{htdocs:'htdocs',styles:'styles'}"
+	// For example, "/servletPath/htdocs/javadoc.css" resolves to the file "[servlet-package]/htdocs/javadoc.css"
+	staticFiles={"htdocs:htdocs","styles:styles"}
 )
 public abstract class RestServletDefault extends RestServlet {
 	private static final long serialVersionUID = 1L;

http://git-wip-us.apache.org/repos/asf/juneau/blob/b820b273/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/StaticFileMapping.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/StaticFileMapping.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/StaticFileMapping.java
new file mode 100644
index 0000000..057da6f
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/StaticFileMapping.java
@@ -0,0 +1,122 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              * 
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest;
+
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.internal.*;
+import org.apache.juneau.parser.*;
+import org.apache.juneau.rest.annotation.*;
+import org.apache.juneau.utils.*;
+
+/**
+ * Static file mapping.
+ * 
+ * <p>
+ * Used to define paths and locations of statically-served files such as images or HTML documents.
+ * 
+ * <p>
+ * An example where this class is used is in the {@link RestResource#staticFiles} annotation:
+ * <p class='bcode'>
+ * <jk>package</jk> com.foo.mypackage;
+ * 
+ * <ja>@RestResource</ja>(
+ * 	path=<js>"/myresource"</js>,
+ * 	staticFiles={<js>"htdocs:docs"</js>}
+ * )
+ * <jk>public class</jk> MyResource <jk>extends</jk> RestServletDefault {...}
+ * </p>
+ * 
+ * <p>
+ * Static files are found by using the {@link ClasspathResourceFinder} defined on the resource.
+ * 
+ * <p>
+ * In the example above, given a GET request to <l>/myresource/htdocs/foobar.html</l>, the servlet will attempt to find 
+ * the <l>foobar.html</l> file in the following ordered locations:
+ * <ol>
+ * 	<li><l>com.foo.mypackage.docs</l> package.
+ * 	<li><l>org.apache.juneau.rest.docs</l> package (since <l>RestServletDefault</l> is in <l>org.apache.juneau.rest</l>).
+ * 	<li><l>[working-dir]/docs</l> directory.
+ * </ol>
+ * 
+ * <h6 class='topic'>Notes:</h6>
+ * <ul class='spaced-list'>
+ * 	<li>
+ * 		Mappings are cumulative from parent to child.  Child resources can override mappings made on parent resources.
+ * 	<li>
+ * 		The media type on the response is determined by the {@link org.apache.juneau.rest.RestContext#getMediaTypeForName(String)} method.
+ * </ul>
+ */
+public class StaticFileMapping {
+	
+	final Class<?> resourceClass;
+	final String path, location;
+	final Map<String,Object> responseHeaders;
+	
+	/**
+	 * Constructor.
+	 * 
+	 * @param resourceClass 
+	 * 	The resource/servlet class which serves as the base location of the location below.
+	 * @param path 
+	 * 	The mapped URI path.
+	 * 	<br>Leading and trailing slashes are trimmed.
+	 * @param location 
+	 * 	The location relative to the resource class.
+	 * 	<br>Leading and trailing slashes are trimmed.
+	 * @param responseHeaders 
+	 * 	The response headers.
+	 * 	Can be <jk>null</jk>. 
+	 */
+	public StaticFileMapping(Class<?> resourceClass, String path, String location, Map<String,Object> responseHeaders) {
+		this.resourceClass = resourceClass;
+		this.path = StringUtils.trimSlashes(path);
+		this.location = StringUtils.trimSlashes(location);
+		this.responseHeaders = responseHeaders == null ? null : Collections.unmodifiableMap(new LinkedHashMap<>(responseHeaders));
+	}
+	
+	/**
+	 * Constructor using a mapping string to represent a path/location pairing.
+	 * 
+	 * <p>
+	 * Mapping string must be one of these formats:
+	 * <ul>
+	 * 	<li><js>"path:location"</js> (e.g. <js>"foodocs:docs/foo"</js>)
+	 * 	<li><js>"path:location:headers-json"</js> (e.g. <js>"foodocs:docs/foo:{'Cache-Control':'max-age=86400, public'}"</js>)
+	 * </ul>
+	 * 
+	 * @param resourceClass 
+	 * 	The resource/servlet class which serves as the base location of the location below.
+	 * @param mappingString 
+	 * 	The mapping string that represents the path/location mapping.
+	 * 	<br>Leading and trailing slashes and whitespace are trimmed from path and location.
+	 */
+	public StaticFileMapping(Class<?> resourceClass, String mappingString) {
+		this.resourceClass = resourceClass;
+		String[] parts = StringUtils.split(mappingString, ':', 3);
+		if (parts == null || parts.length <= 1)
+			throw new FormattedRuntimeException("Invalid mapping string format: ''{0}''", mappingString);
+		this.path = StringUtils.trimSlashes(parts[0]); 
+		this.location = StringUtils.trimSlashes(parts[1]); 
+		if (parts.length == 3) {
+			try {
+				responseHeaders = Collections.unmodifiableMap(new ObjectMap(parts[2]));
+			} catch (ParseException e) {
+				throw new FormattedRuntimeException(e, "Invalid mapping string format: ''{0}''", mappingString);
+			}
+		} else {
+			responseHeaders = null;
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/juneau/blob/b820b273/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestMethod.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestMethod.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestMethod.java
index b59fa2c..a2eae24 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestMethod.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestMethod.java
@@ -16,9 +16,11 @@ import static java.lang.annotation.ElementType.*;
 import static java.lang.annotation.RetentionPolicy.*;
 
 import java.lang.annotation.*;
+import java.util.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.encoders.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.parser.*;
 import org.apache.juneau.remoteable.*;
 import org.apache.juneau.rest.*;
@@ -128,9 +130,17 @@ public @interface RestMethod {
 	 *
 	 * <h5 class='section'>Notes:</h5>
 	 * <ul class='spaced-list'>
-	 * 	<li>Property: {@link RestContext#REST_guards}
-	 * 	<li>Annotation:  {@link RestResource#guards()} / {@link RestMethod#guards()}
-	 * 	<li>Method: {@link RestContextBuilder#guards(Class...)} / {@link RestContextBuilder#guards(RestGuard...)}
+	 * 	<li>Property:  {@link RestContext#REST_guards}
+	 * 	<li>Annotations:
+	 * 		<ul>
+	 * 			<li>{@link RestResource#guards()}
+	 * 			<li>{@link RestMethod#guards()}
+	 * 		</ul>
+	 * 	<li>Methods:
+	 * 		<ul>
+	 * 			<li>{@link RestContextBuilder#guards(Class...)}
+	 * 			<li>{@link RestContextBuilder#guards(RestGuard...)}
+	 * 		</ul>
 	 * 	<li>{@link RestGuard} classes must have either a no-arg or {@link PropertyStore} argument constructors.
 	 * 	<li>Values are added AFTER those found in the annotation and therefore take precedence over those defined via the
 	 * 		annotation.
@@ -155,9 +165,17 @@ public @interface RestMethod {
 	 * 
 	 * <h5 class='section'>Notes:</h5>
 	 * <ul class='spaced-list'>
-	 * 	<li>Property: {@link RestContext#REST_converters}
-	 * 	<li>Annotation:  {@link RestResource#converters()} / {@link RestMethod#converters()}
-	 * 	<li>Method: {@link RestContextBuilder#converters(Class...)} / {@link RestContextBuilder#converters(RestConverter...)}
+	 * 	<li>Property:  {@link RestContext#REST_converters}
+	 * 	<li>Annotations:
+	 * 		<ul>
+	 * 			<li>{@link RestResource#converters()}
+	 * 			<li>{@link RestMethod#converters()}
+	 * 		</ul>
+	 * 	<li>Methods:
+	 * 		<ul>
+	 * 			<li>{@link RestContextBuilder#converters(Class...)}
+	 * 			<li>{@link RestContextBuilder#converters(RestConverter...)}
+	 * 		</ul>
 	 * 	<li>{@link RestConverter} classes must have either a no-arg or {@link PropertyStore} argument constructors.
 	 *	</ul>
 	 */
@@ -260,6 +278,62 @@ public @interface RestMethod {
 	String inherit() default "";
 	
 	/**
+	 * Supported accept media types.
+	 *
+	 * <p>
+	 * Overrides the media types inferred from the serializers that identify what media types can be produced by the resource.
+	 * 
+	 * <p>
+	 * This affects the values returned by {@link RestRequest#getSupportedAcceptTypes()} and the supported accept
+	 * types shown in {@link RestInfoProvider#getSwagger(RestRequest)}.
+	 *
+	 * <p>
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>Property:  {@link RestContext#REST_supportedAcceptTypes}
+	 * 	<li>Annotations:
+	 * 		<ul>
+	 * 			<li>{@link RestResource#supportedAcceptTypes()}
+	 * 			<li>{@link RestMethod#supportedAcceptTypes()}
+	 * 		</ul> 
+	 * 	<li>Methods:  
+	 * 		<ul>
+	 * 			<li>{@link RestContextBuilder#supportedAcceptTypes(boolean,String...)}
+	 * 			<li>{@link RestContextBuilder#supportedAcceptTypes(boolean,MediaType...)}
+	 * 		</ul>
+	 *	</ul>
+	 */
+	String[] supportedAcceptTypes() default {};
+	
+	/**
+	 * Supported content media types.
+	 *
+	 * <p>
+	 * Overrides the media types inferred from the parsers that identify what media types can be consumed by the resource.
+	 *
+	 * <p>
+	 * This affects the values returned by {@link RestRequest#getSupportedContentTypes()} and the supported content
+	 * types shown in {@link RestInfoProvider#getSwagger(RestRequest)}.
+	 * 
+	 * <p>
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>Property:  {@link RestContext#REST_supportedContentTypes}
+	 * 	<li>Annotations:
+	 * 		<ul>
+	 * 			<li>{@link RestResource#supportedContentTypes()}
+	 * 			<li>{@link RestMethod#supportedContentTypes()}
+	 * 		</ul> 
+	 * 	<li>Methods:  
+	 * 		<ul>
+	 * 			<li>{@link RestContextBuilder#supportedContentTypes(boolean,String...)}
+	 * 			<li>{@link RestContextBuilder#supportedContentTypes(boolean,MediaType...)}
+	 * 		</ul>
+	 *	</ul>
+	 */
+	String[] supportedContentTypes() default {};
+
+	/**
 	 * Appends to the list of {@link Encoder encoders} specified on the servlet.
 	 *
 	 * <p>
@@ -313,11 +387,49 @@ public @interface RestMethod {
 
 	/**
 	 * Appends the specified bean filters to all serializers and parsers used by this method.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>Property:  {@link BeanContext#BEAN_beanFilters}
+	 * 	<li>Annotations:
+	 * 		<ul>
+	 * 			<li>{@link RestResource#beanFilters()}
+	 * 			<li>{@link RestMethod#beanFilters()}
+	 * 		</ul>
+	 * 	<li>Methods:
+	 * 		<ul>
+	 * 			<li>{@link RestContextBuilder#beanFilters(Class...)}
+	 * 			<li>{@link RestContextBuilder#beanFilters(Collection)}
+	 * 			<li>{@link RestContextBuilder#beanFilters(boolean, Class...)}
+	 * 			<li>{@link RestContextBuilder#beanFilters(boolean, Collection)}
+	 * 			<li>{@link RestContextBuilder#beanFiltersRemove(Class...)}
+	 * 			<li>{@link RestContextBuilder#beanFiltersRemove(Collection)}
+	 * 		</ul>
+	 *	</ul>
 	 */
 	Class<?>[] beanFilters() default {};
 
 	/**
 	 * Appends the specified POJO swaps to all serializers and parsers used by this method.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>Property:  {@link BeanContext#BEAN_pojoSwaps}
+	 * 	<li>Annotations:
+	 * 		<ul>
+	 * 			<li>{@link RestResource#pojoSwaps()}
+	 * 			<li>{@link RestMethod#pojoSwaps()}
+	 * 		</ul>
+	 * 	<li>Methods:
+	 * 		<ul>
+	 * 			<li>{@link RestContextBuilder#pojoSwaps(Class...)}
+	 * 			<li>{@link RestContextBuilder#pojoSwaps(Collection)}
+	 * 			<li>{@link RestContextBuilder#pojoSwaps(boolean, Class...)}
+	 * 			<li>{@link RestContextBuilder#pojoSwaps(boolean, Collection)}
+	 * 			<li>{@link RestContextBuilder#pojoSwapsRemove(Class...)}
+	 * 			<li>{@link RestContextBuilder#pojoSwapsRemove(Collection)}
+	 * 		</ul>
+	 *	</ul>
 	 */
 	Class<?>[] pojoSwaps() default {};
 
@@ -432,9 +544,17 @@ public @interface RestMethod {
 	 * <p>
 	 * <h5 class='section'>Notes:</h5>
 	 * <ul class='spaced-list'>
-	 * 	<li>Property: {@link RestContext#REST_defaultRequestHeaders}
-	 * 	<li>Annotation:  {@link RestResource#defaultRequestHeaders()} / {@link RestMethod#defaultRequestHeaders()} 
-	 * 	<li>Method: {@link RestContextBuilder#defaultRequestHeader(String,Object)} / {@link RestContextBuilder#defaultRequestHeaders(String...)}
+	 * 	<li>Property:  {@link RestContext#REST_defaultRequestHeaders}
+	 * 	<li>Annotations:
+	 * 		<ul>
+	 * 			<li>{@link RestResource#defaultRequestHeaders()}
+	 * 			<li>{@link RestMethod#defaultRequestHeaders()} 
+	 * 		</ul>
+	 * 	<li>Methods:
+	 * 		<ul>
+	 * 			<li>{@link RestContextBuilder#defaultRequestHeader(String,Object)}
+	 * 			<li>{@link RestContextBuilder#defaultRequestHeaders(String...)}
+	 * 		</ul>
 	 * 	<li>Strings are of the format <js>"Header-Name: header-value"</js>.
 	 * 	<li>You can use either <js>':'</js> or <js>'='</js> as the key/value delimiter.
 	 * 	<li>Key and value is trimmed of whitespace.
@@ -635,9 +755,16 @@ public @interface RestMethod {
 	 *
 	 * <h5 class='section'>Notes:</h5>
 	 * <ul class='spaced-list'>
-	 * 	<li>Property: {@link RestContext#REST_defaultCharset}
-	 * 	<li>Annotation:  {@link RestResource#defaultCharset()} / {@link RestMethod#defaultCharset()}
-	 * 	<li>Method: {@link RestContextBuilder#defaultCharset(String)}
+	 * 	<li>Property:  {@link RestContext#REST_defaultCharset}
+	 * 	<li>Annotations:
+	 * 		<ul>
+	 * 			<li>{@link RestResource#defaultCharset()}
+	 * 			<li>{@link RestMethod#defaultCharset()}
+	 * 		</ul>
+	 * 	<li>Methods:
+	 * 		<ul>
+	 * 			<li>{@link RestContextBuilder#defaultCharset(String)}
+	 * 		</ul>
 	 * 	<li>String value.
 	 * 	<li>Can contain variables.
 	 *	</ul>
@@ -659,9 +786,16 @@ public @interface RestMethod {
 	 * 
 	 * <h5 class='section'>Notes:</h5>
 	 * <ul class='spaced-list'>
-	 * 	<li>Property: {@link RestContext#REST_maxInput}
-	 * 	<li>Annotation:  {@link RestResource#maxInput()} / {@link RestMethod#maxInput()}
-	 * 	<li>Method: {@link RestContextBuilder#maxInput(String)}
+	 * 	<li>Property:  {@link RestContext#REST_maxInput}
+	 * 	<li>Annotations:
+	 * 		<ul>
+	 * 			<li>{@link RestResource#maxInput()}
+	 * 			<li>{@link RestMethod#maxInput()}
+	 * 		</ul>
+	 * 	<li>Methods:
+	 * 		<ul>
+	 * 			<li>{@link RestContextBuilder#maxInput(String)}
+	 * 		</ul>
 	 * 	<li>String value that gets resolved to a <jk>long</jk>.
 	 * 	<li>Can contain variables.
 	 * 	<li>Can be suffixed with any of the following representing kilobytes, megabytes, and gigabytes:  


Mime
View raw message